branch develop updated (82212b4 -> f534abd)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository jaxx. See http://git.nuiton.org/jaxx.git from 82212b4 fixes #3579 [Table Filter] the "CONTAINS" filter does not work with the upper case words new f534abd refs-90 #3580: Introduce a new FilterableDoubleList widget The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit f534abd477b11f970dcfe190f2e51268ee7b62e0 Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Nov 28 11:53:16 2014 +0100 refs-90 #3580: Introduce a new FilterableDoubleList widget Summary of changes: ...leListDemo.css => FilterableDoubleListDemo.css} | 10 +- ...ListDemo.jaxx => FilterableDoubleListDemo.jaxx} | 14 +- .../editor/FilterableDoubleListDemoHandler.java | 60 +++ .../main/java/jaxx/demo/tree/DemoDataProvider.java | 2 + .../runtime/swing/model/JaxxDefaultListModel.java | 42 +- .../swing/model/JaxxFilterableListModel.java | 6 + .../jaxx/runtime/swing/editor/bean/BeanUIUtil.java | 2 +- .../widgets/editor/bean/FilterableDoubleList.css} | 24 +- .../widgets/editor/bean/FilterableDoubleList.jaxx} | 95 ++-- .../editor/bean/FilterableDoubleListConfig.java | 68 +++ .../editor/bean/FilterableDoubleListHandler.java | 550 +++++++++++++++++++++ .../editor/bean/FilterableDoubleListModel.java | 378 ++++++++++++++ 12 files changed, 1163 insertions(+), 88 deletions(-) copy jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/{BeanDoubleListDemo.css => FilterableDoubleListDemo.css} (98%) copy jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/{BeanDoubleListDemo.jaxx => FilterableDoubleListDemo.jaxx} (90%) create mode 100644 jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemoHandler.java copy jaxx-widgets/src/main/java/{jaxx/runtime/swing/editor/bean/BeanDoubleList.css => org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.css} (89%) copy jaxx-widgets/src/main/java/{jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx => org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.jaxx} (69%) create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListConfig.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListHandler.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListModel.java -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jaxx. See http://git.nuiton.org/jaxx.git commit f534abd477b11f970dcfe190f2e51268ee7b62e0 Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Nov 28 11:53:16 2014 +0100 refs-90 #3580: Introduce a new FilterableDoubleList widget --- .../jaxx/editor/FilterableDoubleListDemo.css | 57 +++ .../jaxx/editor/FilterableDoubleListDemo.jaxx | 48 ++ .../editor/FilterableDoubleListDemoHandler.java | 60 +++ .../main/java/jaxx/demo/tree/DemoDataProvider.java | 2 + .../runtime/swing/model/JaxxDefaultListModel.java | 42 +- .../swing/model/JaxxFilterableListModel.java | 6 + .../jaxx/runtime/swing/editor/bean/BeanUIUtil.java | 2 +- .../widgets/editor/bean/FilterableDoubleList.css | 124 +++++ .../widgets/editor/bean/FilterableDoubleList.jaxx | 153 ++++++ .../editor/bean/FilterableDoubleListConfig.java | 68 +++ .../editor/bean/FilterableDoubleListHandler.java | 550 +++++++++++++++++++++ .../editor/bean/FilterableDoubleListModel.java | 378 ++++++++++++++ 12 files changed, 1479 insertions(+), 11 deletions(-) diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemo.css b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemo.css new file mode 100644 index 0000000..226397e --- /dev/null +++ b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemo.css @@ -0,0 +1,57 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +#configurationPanel { + border: {new TitledBorder(t("jaxxdemo.beandoublelistdemo.configuration"))}; +} + +#filterableButton { + text: "jaxxdemo.beandoublelistdemo.filterable"; + selected: true; +} + +#highlightFilterTextButton { + text: "jaxxdemo.beandoublelistdemo.highlightFilterText"; + selected: false; +} + +#showResetButton { + text: "jaxxdemo.beandoublelistdemo.showReset"; + selected: true; +} + +#showDecoratorButton { + text: "jaxxdemo.beandoublelistdemo.showDecorator"; + selected: true; +} + +#filterOnNachoButton { + text: "jaxxdemo.beandoublelistdemo.filterOnNacho"; + selected: false; +} + +#doubleList { + i18nPrefix: "jaxxdemo.common."; + filterable: {filterableButton.isSelected()}; + showReset: {showResetButton.isSelected()}; + showDecorator: {showDecoratorButton.isSelected()}; + highlightFilterText: {highlightFilterTextButton.isSelected()}; +} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemo.jaxx new file mode 100644 index 0000000..f0238d2 --- /dev/null +++ b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemo.jaxx @@ -0,0 +1,48 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + jaxx.demo.entities.People + org.nuiton.jaxx.widgets.editor.bean.FilterableDoubleList + </import> + + <Table fill='both'> + <row> + <cell> + <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> + <JCheckBox id='filterableButton'/> + <JCheckBox id='highlightFilterTextButton'/> + <JCheckBox id='showResetButton'/> + <JCheckBox id='showDecoratorButton'/> + <JCheckBox id='filterOnNachoButton'/> + </JPanel> + </cell> + </row> + <row> + <cell weighty='1' weightx='1'> + <FilterableDoubleList id='doubleList' genericType='People'/> + </cell> + </row> + </Table> + +</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemoHandler.java new file mode 100644 index 0000000..104862f --- /dev/null +++ b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FilterableDoubleListDemoHandler.java @@ -0,0 +1,60 @@ +package jaxx.demo.component.jaxx.editor; + +import com.google.common.base.Predicate; +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.DemoDecoratorProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.runtime.spi.UIHandler; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.jaxx.widgets.editor.bean.FilterableDoubleList; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.util.List; + +/** + * Created on 11/28/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class FilterableDoubleListDemoHandler implements UIHandler<FilterableDoubleListDemo> { + + @Override + public void beforeInit(FilterableDoubleListDemo ui) { + // nothing to do + } + + @Override + public void afterInit(final FilterableDoubleListDemo ui) { + DemoDataProvider demoDataProvider = new DemoDataProvider(); + List<People> data = demoDataProvider.getPeoples(); + JXPathDecorator<People> decorator = (JXPathDecorator<People>) new DemoDecoratorProvider().getDecoratorByType(People.class); + + + FilterableDoubleList<People> doubleList = ui.getDoubleList(); + doubleList.setFilterable(true); + + doubleList.init(decorator, data, data.subList(0, 1)); + + final Movie nacho = demoDataProvider.getMovie("0"); + final Predicate<People> filter = new Predicate<People>() { + + public boolean apply(People input) { + return nacho.getActors().contains(input); + } + }; + ui.getFilterOnNachoButton().addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent e) { + if (ui.getFilterOnNachoButton().isSelected()) { + ui.getDoubleList().getHandler().addFilter(filter); + + } else { + ui.getDoubleList().getHandler().clearFilters(); + } + } + }); + } +} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java index 1237f83..639e76e 100644 --- a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java +++ b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java @@ -30,6 +30,7 @@ import jaxx.demo.component.jaxx.editor.BeanFilterableComboBoxDemo; import jaxx.demo.component.jaxx.editor.ComboEditorDemo; import jaxx.demo.component.jaxx.editor.DatePickerDemo; import jaxx.demo.component.jaxx.editor.FileEditorDemo; +import jaxx.demo.component.jaxx.editor.FilterableDoubleListDemo; import jaxx.demo.component.jaxx.editor.I18nEditorDemo; import jaxx.demo.component.jaxx.editor.ListSelectorDemo; import jaxx.demo.component.jaxx.editor.NumberEditor2Demo; @@ -170,6 +171,7 @@ public class DemoDataProvider implements NavDataProvider { BeanComboBoxDemo.class, BeanFilterableComboBoxDemo.class, BeanDoubleListDemo.class, + FilterableDoubleListDemo.class, n("jaxxdemo.component.jaxx.editor.gis"), n("jaxxdemo.component.jaxx.editor.datetime") ); diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java index 8db1670..8837bd2 100644 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java +++ b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java @@ -167,8 +167,8 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * Tests whether this list has any components. * * @return <code>true</code> if and only if this list has - * no components, that is, its size is zero; - * <code>false</code> otherwise + * no components, that is, its size is zero; + * <code>false</code> otherwise * @see Vector#isEmpty() */ public boolean isEmpty() { @@ -190,7 +190,7 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * * @param elem an object * @return <code>true</code> if the specified object - * is the same as a component in this list + * is the same as a component in this list * @see Vector#contains(Object) */ public boolean contains(E elem) { @@ -202,7 +202,7 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * * @param elem an object * @return the index of the first occurrence of the argument in this - * list; returns <code>-1</code> if the object is not found + * list; returns <code>-1</code> if the object is not found * @see Vector#indexOf(Object) */ public int indexOf(E elem) { @@ -216,8 +216,8 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * @param elem an desired component * @param index the index from which to begin searching * @return the index where the first occurrence of <code>elem</code> - * is found after <code>index</code>; returns <code>-1</code> - * if the <code>elem</code> is not found in the list + * is found after <code>index</code>; returns <code>-1</code> + * if the <code>elem</code> is not found in the list * @see Vector#indexOf(Object, int) */ public int indexOf(E elem, int index) { @@ -229,7 +229,7 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * * @param elem the desired component * @return the index of the last occurrence of <code>elem</code> - * in the list; returns <code>-1</code> if the object is not found + * in the list; returns <code>-1</code> if the object is not found * @see Vector#lastIndexOf(Object) */ public int lastIndexOf(E elem) { @@ -243,8 +243,8 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * @param elem the desired component * @param index the index to start searching from * @return the index of the last occurrence of the <code>elem</code> - * in this list at position less than <code>index</code>; - * returns <code>-1</code> if the object is not found + * in this list at position less than <code>index</code>; + * returns <code>-1</code> if the object is not found * @see Vector#lastIndexOf(Object, int) */ public int lastIndexOf(E elem, int index) { @@ -392,7 +392,7 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { * * @param obj the component to be removed * @return <code>true</code> if the argument was a component of this - * list; <code>false</code> otherwise + * list; <code>false</code> otherwise * @see Vector#removeElement(Object) */ public boolean removeElement(E obj) { @@ -519,6 +519,20 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { } } + public void removeAllElements(Collection<E> elements) { + if (CollectionUtils.isNotEmpty(elements)) { + + int firstIndex = 0; + int lastIndex = delegate.size(); + this.delegate.removeAll(elements); + if (lastIndex > -1) { + if (!isValueIsAdjusting()) { + fireContentsChanged(this, firstIndex, lastIndex); + } + } + } + } + /** * Removes the element at the specified position in this list. * Returns the element that was removed from the list. @@ -588,6 +602,14 @@ public class JaxxDefaultListModel<E> extends AbstractListModel { } } + public void refresh(int size) { + + if (!isValueIsAdjusting()) { + fireContentsChanged(this, 0, size); + } + + } + /* public void addAll(Collection c) { } diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java index 4ef5b54..a81989d 100644 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java +++ b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java @@ -160,6 +160,12 @@ public class JaxxFilterableListModel<E> extends JaxxDefaultListModel<E> { } @Override + public void removeAllElements(Collection<E> elements) { + super.removeAllElements(elements); + refilter(); + } + + @Override public E remove(int index) { E rv = super.remove(index); refilter(); diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java index d81298e..6f73cc0 100644 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java +++ b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java @@ -347,7 +347,7 @@ public class BeanUIUtil { * @param sortDown * @param decorator le decorateur a utiliser */ - protected void preparePopup(String selectedTip, + public void preparePopup(String selectedTip, String notSelectedTip, String i18nPrefix, String title, diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.css b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.css new file mode 100644 index 0000000..117dff2 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.css @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +#filterPanel { + visible: {isFilterable()}; +} + +#filterFieldLabel { + actionIcon: "filter"; +} + +#universeList { + model:{model.getUniverseModel()}; +} + +#addButton { + toolTipText:"beandoublelist.button.add"; + actionIcon:"bean-doublelist-select"; + enabled:{model.isAddEnabled()}; +} + +#selectedList { + model:{model.getSelectedModel()}; + componentPopupMenu:{handler.getSelectedListPopup(isShowSelectPopupEnabled())}; +} + +#removeButton { + toolTipText:"beandoublelist.button.remove"; + actionIcon:"bean-doublelist-unselect"; + enabled:{model.isRemoveEnabled()}; +} + +#popup { + border:{new TitledBorder(t("beandoublelist.popup.title"))}; +} + +#popupSortLabel { + actionIcon:"bean-sort"; + text:"bean.sort.label"; +} + +#sortUp { + buttonGroup:"sortGroup"; + value:{false}; + actionIcon:"bean-sort-up"; + text:"bean.sort.up"; + selected:{!isReverseSort()}; +} + +#sortDown { + buttonGroup:"sortGroup"; + value:{true}; + actionIcon:"bean-sort-down"; + text:"bean.sort.down"; + selected:{isReverseSort()}; +} + +#selectedListMoveUpAction { + actionIcon: "bean-doublelist-up"; + text: "bean.action.selected.move.up"; + toolTipText: "bean.action.selected.move.up.tip"; + enabled:{model.isSelectedUpEnabled()}; +} + +#selectedListMoveDownAction { + actionIcon: "bean-doublelist-down"; + text: "bean.action.selected.move.down"; + toolTipText: "bean.action.selected.move.down.tip"; + enabled:{model.isSelectedDownEnabled()}; +} + +#selectedListRemoveAction { + actionIcon: "bean-doublelist-unselect"; + text: "bean.action.selected.remove"; + toolTipText: "bean.action.selected.remove.tip"; + enabled:{model.isRemoveEnabled()}; +} + +#toolbarLeft { + floatable:false; + borderPainted:false; + visible:{isShowReset()}; +} + +#resetButton { + actionIcon:"doublelist-reset"; + toolTipText:"beandoublelist.action.reset.tip"; + focusable:false; + focusPainted:false; + enabled:{isShowReset() && isEnabled()}; +} + +#toolbarRight { + floatable:false; + borderPainted:false; + visible:{isShowDecorator()}; +} + +#changeDecorator { + actionIcon:"doublelist-sort"; + toolTipText:"beandoublelist.action.sort.tip"; + focusable:false; + focusPainted:false; + enabled:{isShowDecorator() && isEnabled()}; +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.jaxx new file mode 100644 index 0000000..27ed770 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleList.jaxx @@ -0,0 +1,153 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Table genericType='O extends Serializable' implements='jaxx.runtime.bean.BeanTypeAware<O>'> + + <import> + org.nuiton.decorator.JXPathDecorator + + java.io.Serializable + </import> + + <!-- filterable list property --> + <Boolean id='filterable' javaBean='true'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='true'/> + + <!-- show showSelectPopupEnabled property --> + <Boolean id='showSelectPopupEnabled' javaBean='true'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- show highlightFilterText property --> + <Boolean id='highlightFilterText' javaBean='false'/> + + <!-- model --> + <FilterableDoubleListModel id='model' genericType='O' initializer='getContextValue(FilterableDoubleListModel.class)'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + onPopupMenuWillBecomeInvisible='changeDecorator.setSelected(false)' + onPopupMenuCanceled='changeDecorator.setSelected(false)'> + <JLabel id='popupSortLabel'/> + <JRadioButtonMenuItem id='sortUp'/> + <JRadioButtonMenuItem id='sortDown'/> + <JSeparator id='popupSeparator'/> + <JLabel id='popupLabel'/> + <JSeparator/> + </JPopupMenu> + + <!-- popup on the selected list --> + <JPopupMenu id='selectedListPopup'> + <JMenuItem id='selectedListMoveUpAction' onActionPerformed='handler.moveUpSelected( (O) selectedList.getSelectedValue())'/> + <JMenuItem id='selectedListMoveDownAction' onActionPerformed='handler.moveDownSelected( (O) selectedList.getSelectedValue())'/> + <JMenuItem id='selectedListRemoveAction' onActionPerformed='handler.unselect()'/> + </JPopupMenu> + + <row> + <cell columns='3' fill='both'> + <JPanel layout='{new BorderLayout()}' id='beforeFilterPanel'/> + </cell> + </row> + <row> + <cell columns='3' fill='both'> + <JPanel layout='{new BorderLayout()}' id='filterPanel'> + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.WEST'> + <JLabel id='filterFieldLabel' constraints='BorderLayout.WEST'/> + <JToolBar id='toolbarLeft' constraints='BorderLayout.EAST'> + <JButton id='resetButton' onActionPerformed='filterField.setText("")'/> + </JToolBar> + </JPanel> + <JTextField id='filterField' constraints='BorderLayout.CENTER'/> + <JToolBar id='toolbarRight' constraints='BorderLayout.EAST'> + <JToggleButton id='changeDecorator' onActionPerformed='handler.togglePopup()'/> + </JToolBar> + </JPanel> + </cell> + </row> + <row> + <cell weightx='0.5' weighty='1' fill='both'> + <JScrollPane onFocusGained='universeList.requestFocus()'> + <!-- List of all the remaining available elements --> + <JList id='universeList' + onFocusGained='handler.selectFirstRowIfNoSelection(event)' + onMouseClicked='handler.onUniverseListClicked(event)' + onKeyPressed='handler.onKeyPressedOnUniverseList(event)'/> + </JScrollPane> + </cell> + + <cell anchor='north'> + <JPanel layout='{new GridLayout(0,1)}'> + <JButton id='addButton' onActionPerformed='handler.select()'/> + <JButton id='removeButton' onActionPerformed='handler.unselect()'/> + </JPanel> + </cell> + + <cell weightx='0.5' weighty='1' fill='both'> + <JScrollPane onFocusGained='selectedList.requestFocus()'> + <!-- List of the selected elements --> + <JList id='selectedList' + onFocusGained='handler.selectFirstRowIfNoSelection(event)' + onMouseClicked='handler.onSelectedListClicked(event)' + onKeyPressed='handler.onKeyPressedOnSelectedList(event)'/> + </JScrollPane> + </cell> + </row> + + <script><![CDATA[ + +public void init(JXPathDecorator<O> decorator, JXPathDecorator<O> decorator2, List<O> universe, List<O> selected) { + handler.init(decorator, decorator2, universe, selected); + } + +public void init(JXPathDecorator<O> decorator, List<O> universe, List<O> selected) { + handler.init(decorator, universe, selected); +} + +public Class<O> getBeanType() { return model.getConfig().getBeanType(); } + +// Config delegate methods +public void setBeanType(Class<O> beanType) { model.getConfig().setBeanType(beanType); } +public void setProperty(String property) { model.getConfig().setProperty(property); } +public void setUseMultiSelect(boolean useMultiSelect) { model.getConfig().setUseMultiSelect(useMultiSelect); } +public void setI18nPrefix(String i18nPrefix) { model.getConfig().setI18nPrefix(i18nPrefix); } + +// Model delegate methods +public void setBean(Serializable bean) { model.setBean(bean); } +public void setUniverse(List<O> universe) { model.setUniverse(universe);} +public void setSelected(List<O> selected) { model.setSelected(selected);} + +]]></script> + +</Table> diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListConfig.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListConfig.java new file mode 100644 index 0000000..aceb5cc --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListConfig.java @@ -0,0 +1,68 @@ +package org.nuiton.jaxx.widgets.editor.bean; + +import java.io.Serializable; + +/** + * Put here all immutable options used to init the filtreable double list. + * + * Created on 11/28/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class FilterableDoubleListConfig<O extends Serializable> implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Optional property where to bind the selected value changes in optional bean. + */ + protected String property; + + /** + * Bean type. + */ + protected Class<O> beanType; + + /** + * to be able to select a same entry more than one time property. + */ + protected boolean useMultiSelect; + + /** + * I18n prefix use to display build i18n messages. + */ + protected String i18nPrefix; + + public Class<O> getBeanType() { + return beanType; + } + + public void setBeanType(Class<O> beanType) { + this.beanType = beanType; + } + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + + public boolean isUseMultiSelect() { + return useMultiSelect; + } + + public void setUseMultiSelect(boolean useMultiSelect) { + this.useMultiSelect = useMultiSelect; + } + + public String getI18nPrefix() { + return i18nPrefix; + } + + public void setI18nPrefix(String i18nPrefix) { + this.i18nPrefix = i18nPrefix; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListHandler.java new file mode 100644 index 0000000..56b4d78 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListHandler.java @@ -0,0 +1,550 @@ +package org.nuiton.jaxx.widgets.editor.bean; + +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Lists; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.spi.UIHandler; +import jaxx.runtime.swing.JAXXButtonGroup; +import jaxx.runtime.swing.editor.bean.BeanUIUtil; +import jaxx.runtime.swing.model.JaxxFilterableListModel; +import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import jaxx.runtime.swing.renderer.FilteredDecoratorListCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.DecoratorUtil; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.decorator.MultiJXPathDecorator; +import org.nuiton.jaxx.widgets.MutateOnConditionalPropertyChangeListener; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.ListSelectionModel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +/** + * Created on 11/28/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class FilterableDoubleListHandler<O extends Serializable> implements UIHandler<FilterableDoubleList<O>> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(FilterableDoubleListHandler.class); + + private FilterableDoubleList<O> ui; + + /** the decorator of data */ + private MultiJXPathDecorator<O> decorator; + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + @Override + public void beforeInit(FilterableDoubleList<O> ui) { + + this.ui = ui; + + FilterableDoubleListConfig<O> config = new FilterableDoubleListConfig<O>(); + FilterableDoubleListModel<O> model = new FilterableDoubleListModel<O>(config); + ui.setContextValue(model); + + } + + @Override + public void afterInit(FilterableDoubleList<O> ui) { + // nothing to do here, everything is done in init method + } + + //------------------------------------------------------------------------// + //-- Filter methods ------------------------------------------------------// + //------------------------------------------------------------------------// + + public void addFilter(Predicate<O> filter) { + ui.getModel().getUniverseModel().addFilter(filter); + } + + public void removeFilter(Predicate<O> filter) { + ui.getModel().getUniverseModel().removeFilter(filter); + } + + public void clearFilters() { + ui.getModel().getUniverseModel().clearFilters(); + } + + public void refreshFilteredElements() { + ui.getModel().getUniverseModel().refreshFilteredElements(); + } + + //------------------------------------------------------------------------// + //-- Public methods ------------------------------------------------------// + //------------------------------------------------------------------------// + + /** + * When universe list was double clicked, move selected items to selected list. + * + * @param event mouse event + */ + public void onUniverseListClicked(MouseEvent event) { + + JList universeList = ui.getUniverseList(); + + if (event.getClickCount() == 2) { + int index = universeList.locationToIndex(event.getPoint()); + if (index < 0) { + return; + } + + O item = ui.getModel().getUniverseModel().getElementAt(index); + List<O> items = Lists.newArrayList(item); + ui.getModel().addToSelected(items); + +// sortData(); + } + + } + + /** + * When selected list was double clicked, move selected items to universe list. + * + * @param event mouse event + */ + public void onSelectedListClicked(MouseEvent event) { + + JList selectedList = ui.getSelectedList(); + + if (event.getClickCount() == 2) { + int index = selectedList.locationToIndex(event.getPoint()); + if (index < 0) { + return; + } + + O item = ui.getModel().getSelectedModel().getElementAt(index); + List<O> items = Lists.newArrayList(item); + ui.getModel().removeFromSelected(items); + + sortData(); + } + + } + + /** When add button was hit, move selected items (from universe list) to selected list. */ + public void select() { + + Object[] selectedValues = ui.getUniverseList().getSelectedValues(); + List<O> selection = (List) Arrays.asList(selectedValues); + ui.getModel().addToSelected(selection); + ui.getUniverseList().clearSelection(); + +// sortData(); + + } + + /** When remove button was hit, move selected items (from selected list) to universe list. */ + public void unselect() { + + Object[] selectedValues = ui.getSelectedList().getSelectedValues(); + List<O> selection = (List) Arrays.asList(selectedValues); + ui.getModel().removeFromSelected(selection); + ui.getSelectedList().clearSelection(); + + sortData(); + + } + + public void onKeyPressedOnUniverseList(KeyEvent e) { + + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + int lastIndice = ui.getUniverseList().getSelectionModel().getLeadSelectionIndex(); + select(); + JList source = (JList) e.getSource(); + if (source.getModel().getSize() > 0) { + source.setSelectedIndex(Math.min(lastIndice, source.getModel().getSize() - 1)); + } else { + ui.getSelectedList().requestFocus(); + } + } + + } + + public void onKeyPressedOnSelectedList(KeyEvent e) { + + if (e.getKeyCode() == KeyEvent.VK_DELETE) { + int lastIndice = ui.getSelectedList().getSelectionModel().getLeadSelectionIndex(); + unselect(); + JList source = (JList) e.getSource(); + if (source.getModel().getSize() > 0) { + source.setSelectedIndex(Math.min(lastIndice, source.getModel().getSize() - 1)); + ui.getSelectedList().requestFocus(); + } + } + + } + + public void selectFirstRowIfNoSelection(FocusEvent event) { + + JList list = (JList) event.getSource(); + if (list.isSelectionEmpty()) { + list.setSelectedIndex(0); + } + + } + + /** + * Move up a selected item. + * + * @param item the selected item + * @since 2.5.26 + */ + public void moveUpSelected(O item) { + + ui.getModel().moveUpSelected(item); + ui.getSelectedList().setSelectedValue(item, true); + + } + + /** + * Move down a selected item. + * + * @param item the selected item + * @since 2.5.26 + */ + public void moveDownSelected(O item) { + + ui.getModel().moveDownSelected(item); + ui.getSelectedList().setSelectedValue(item, true); + + } + + public JPopupMenu getSelectedListPopup(boolean showIt) { + JPopupMenu result; + if (showIt) { + result = ui.getSelectedListPopup(); + } else { + result = null; + } + return result; + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + //------------------------------------------------------------------------// + //-- Init methods --------------------------------------------------------// + //------------------------------------------------------------------------// + + /** + * Initializes the handler of the UI + * + * @param decorator the decorator to use to display the data nicely + * @param universe the list of all the available items + * @param selected the list of selected items + */ + public void init(JXPathDecorator<O> decorator, List<O> universe, List<O> selected) { + init(decorator, decorator, universe, selected); + } + + /** + * Initializes the handler of the UI + * + * @param decorator the decorator to use to display the data nicely + * @param decorator2 the selected decorator to use to display the selected data nicely (if none, then reuse the first one) + * @param universe the list of all the available items + * @param selected the list of selected items + */ + public void init(JXPathDecorator<O> decorator, JXPathDecorator<O> decorator2, List<O> universe, List<O> selected) { + + if (decorator == null) { + throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); + } + + this.decorator = BeanUIUtil.createDecorator(decorator); + + FilterableDoubleListModel<O> model = ui.getModel(); + + FilterableDoubleListConfig<O> config = model.getConfig(); + + Object bean = model.getBean(); + + if (bean != null) { + + String property = config.getProperty(); + + if (property != null) { + + Method mutator = BeanUtil.getMutator(bean, property); + + // check mutator exists + Preconditions.checkNotNull(mutator, "could not find mutator for " + property); + + // When selected list changed, let's push it back in bean + model.addPropertyChangeListener( + FilterableDoubleListModel.PROPERTY_SELECTED, + new MutateOnConditionalPropertyChangeListener<FilterableDoubleListModel>(model, mutator, Predicates.<FilterableDoubleListModel>alwaysTrue())); + + } + } + + ui.getModel().setUniverse(universe); + ui.getModel().setSelected(selected); + + { + // Init universe list + JList universeList = ui.getUniverseList(); + final FilteredDecoratorListCellRenderer universeListCellRenderer + = new FilteredDecoratorListCellRenderer(this.decorator); + universeList.setCellRenderer(universeListCellRenderer); + // When universe list selection model changed, update the add button enabled property + universeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + ListSelectionModel source = (ListSelectionModel) e.getSource(); + ui.getModel().setAddEnabled(!source.isSelectionEmpty()); + } + }); + + final JaxxFilterableListModel<O> filterModel = (JaxxFilterableListModel) ui.getModel().getUniverseModel(); + + filterModel.setDecorator(this.decorator); + + ui.getFilterField().getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void insertUpdate(DocumentEvent e) { + String text = ui.getFilterField().getText(); + universeListCellRenderer.setFilterText(text); + filterModel.setFilterText(text); + } + + @Override + public void removeUpdate(DocumentEvent e) { + String text = ui.getFilterField().getText(); + universeListCellRenderer.setFilterText(text); + filterModel.setFilterText(text); + } + + @Override + public void changedUpdate(DocumentEvent e) { + String text = ui.getFilterField().getText(); + universeListCellRenderer.setFilterText(text); + filterModel.setFilterText(text); + } + }); + } + + { + // Init selected list + JList selectedList = ui.getSelectedList(); + if (decorator2 != null) { + decorator2 = BeanUIUtil.createDecorator(decorator2); + } else { + decorator2 = this.decorator; + } + selectedList.setCellRenderer(new DecoratorListCellRenderer(decorator2)); + + + // When selected list selection model changed, update the add button enabled property + selectedList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + ListSelectionModel source = (ListSelectionModel) e.getSource(); + FilterableDoubleListModel<O> model = ui.getModel(); + if (!e.getValueIsAdjusting()) { + boolean removeEnabled = !source.isSelectionEmpty(); + model.setRemoveEnabled(removeEnabled); + + int minSelectionIndex = source.getMinSelectionIndex(); + int maxSelectionIndex = source.getMaxSelectionIndex(); + + boolean oneSelection = minSelectionIndex == maxSelectionIndex; + + boolean upEnabled = removeEnabled && + oneSelection && + minSelectionIndex > 0; + model.setSelectedUpEnabled(upEnabled); + + boolean downEnabled = removeEnabled && + oneSelection && + minSelectionIndex + 1 < model.getSelectedListSize(); + model.setSelectedDownEnabled(downEnabled); + } + } + }); + } + + { + // Init decorator ui + JAXXButtonGroup indexes = ui.getIndexes(); + + // build popup + popupHandler.preparePopup(null, + null, + config.getI18nPrefix(), + null, + indexes, + ui.getPopupSeparator(), + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + + sortData(); + + } + + { + + // Listen ui changes + + ui.addPropertyChangeListener(FilterableDoubleList.PROPERTY_INDEX, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + + } + }); + + ui.addPropertyChangeListener(FilterableDoubleList.PROPERTY_REVERSE_SORT, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + } + }); + + ui.addPropertyChangeListener(FilterableDoubleList.PROPERTY_HIGHLIGHT_FILTER_TEXT, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + setHighlightFilterText((Boolean) evt.getNewValue()); + } + }); + } + + // force to reload the showSelectPopup binding + ui.processDataBinding(FilterableDoubleList.BINDING_SELECTED_LIST_COMPONENT_POPUP_MENU); + + } + + //------------------------------------------------------------------------// + //-- Internal methods ----------------------------------------------------// + //------------------------------------------------------------------------// + + private void sortData() { + + // just update UI should do the math of this + updateUI(ui.getIndex(), ui.isReverseSort()); + + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + AbstractButton button = ui.getIndexes().getButton(newValue); + if (button != null) { + button.setSelected(true); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + protected void setHighlightFilterText(Boolean newValue) { + FilteredDecoratorListCellRenderer universeListCellRenderer = + (FilteredDecoratorListCellRenderer) ui.getUniverseList().getCellRenderer(); + universeListCellRenderer.setHighlightFilterText(newValue); + ui.getUniverseList().repaint(); + } + + protected void updateUI(int index, boolean reversesort) { + + if (decorator == null) { + + // can't come here right now... + return; + } + + // change decorator context + decorator.setContextIndex(index); + + List<O> data = ui.getModel().getUniverseModel().toList(); + try { + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + data, + index, + reversesort + ); + + } catch (Exception eee) { + log.warn(eee.getMessage(), eee); + } + + // reload the model + SwingUtil.fillList(ui.getUniverseList(), data, null); + + ui.getUniverseList().requestFocus(); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListModel.java new file mode 100644 index 0000000..0711b1c --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/widgets/editor/bean/FilterableDoubleListModel.java @@ -0,0 +1,378 @@ +package org.nuiton.jaxx.widgets.editor.bean; + +import jaxx.runtime.swing.model.JaxxDefaultListModel; +import jaxx.runtime.swing.model.JaxxFilterableListModel; +import org.jdesktop.beans.AbstractSerializableBean; +import org.nuiton.jaxx.widgets.ModelToBean; + +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Created on 11/28/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class FilterableDoubleListModel<O extends Serializable> extends AbstractSerializableBean implements ModelToBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_ADD_ENABLED = "addEnabled"; + + public static final String PROPERTY_REMOVE_ENABLED = "removeEnabled"; + + public static final String PROPERTY_SELECTED_UP_ENABLED = "selectedUpEnabled"; + + public static final String PROPERTY_SELECTED_DOWN_ENABLED = "selectedDownEnabled"; + + public static final String PROPERTY_BEAN = "bean"; + + public static final String PROPERTY_SELECTED = "selected"; + + /** + * Can use select action ? + */ + protected boolean addEnabled; + + /** + * Can use unselect action ? + */ + protected boolean removeEnabled; + + /** + * Can use select up action ? + */ + protected boolean selectedUpEnabled; + + /** + * Can use select down action ? + */ + protected boolean selectedDownEnabled; + + /** + * Optional bean where to push data. + */ + protected Serializable bean; + + /** + * Internal flag to avoid reentrant code while firing some events. + */ + protected boolean objectIsAdjusting; + + /** + * Universe of items useables in not-selected and selected lists. + */ + protected final List<O> universe = new ArrayList<O>(); + + /** + * Model containing the remaining available items. + */ + protected final JaxxFilterableListModel<O> universeModel = new JaxxFilterableListModel<O>(); + + /** + * Model containing the selected items. + */ + protected final JaxxDefaultListModel<O> selectedModel = new JaxxDefaultListModel<O>(); + + private final FilterableDoubleListConfig<O> config; + + public FilterableDoubleListModel(FilterableDoubleListConfig<O> config) { + this.config = config; + this.selectedModel.addListDataListener(new ListDataListener() { + @Override + public void intervalAdded(ListDataEvent e) { + fireSelectedChange(); + } + + @Override + public void intervalRemoved(ListDataEvent e) { + fireSelectedChange(); + } + + @Override + public void contentsChanged(ListDataEvent e) { + fireSelectedChange(); + } + }); + } + + private void fireSelectedChange() { + + if (!selectedModel.isValueIsAdjusting()) { + + // only fire when not adjusting model + List<O> selected = getSelected(); + firePropertyChange(PROPERTY_SELECTED, null /* To force event propagation */, selected); + } + + } + + public JaxxDefaultListModel<O> getSelectedModel() { + return selectedModel; + } + + public JaxxFilterableListModel<O> getUniverseModel() { + return universeModel; + } + + //------------------------------------------------------------------------// + //-- Config delegate methods ---------------------------------------------// + //------------------------------------------------------------------------// + + public FilterableDoubleListConfig<O> getConfig() { + return config; + } + + public Class<O> getBeanType() { + return config.getBeanType(); + } + + public boolean isUseMultiSelect() { + return config.isUseMultiSelect(); + } + + public String getProperty() { + return config.getProperty(); + } + + public String getI18nPrefix() { + return config.getI18nPrefix(); + } + + //------------------------------------------------------------------------// + //-- Universe - Selected methods -----------------------------------------// + //------------------------------------------------------------------------// + + public List<O> getSelected() { + + List<O> selected = selectedModel.toList(); + return selected; + + } + + public int getSelectedListSize() { + return selectedModel.size(); + } + + public void setUniverse(List<O> universe) { + + resetUniverse(); + + this.universe.clear(); + if (universe != null) { + this.universe.addAll(universe); + } + + } + + public void setSelected(List<O> selected) { + + setValueIsAdjustingToTrue(); + + try { + + resetUniverse(); + + selectedModel.clear(); + + if (selected != null) { + + addToSelected(selected); + + } + + } finally { + + setValueIsAdjustingToFalse(true); + + } + + } + + public void addToSelected(Iterable<O> items) { + + setValueIsAdjustingToTrue(); + + try { + for (O item : items) { + + addToSelected(item); + + } + } finally { + + setValueIsAdjustingToFalse(isUseMultiSelect()); + + } + + } + + public void removeFromSelected(Iterable<O> items) { + + setValueIsAdjustingToTrue(); + + try { + for (O item : items) { + + removeFromSelected(item); + + } + } finally { + + setValueIsAdjustingToFalse(isUseMultiSelect()); + + } + + } + + /** + * Move up a selected item. + * + * @param item the selected item + */ + public void moveUpSelected(O item) { + int i = selectedModel.indexOf(item); + selectedModel.removeElement(item); + selectedModel.insertElementAt(item, i - 1); + } + + /** + * Move down a selected item. + * + * @param item the selected item + */ + public void moveDownSelected(O item) { + + int i = selectedModel.indexOf(item); + selectedModel.removeElement(item); + selectedModel.insertElementAt(item, i + 1); + + } + + //------------------------------------------------------------------------// + //-- Bean property methods -----------------------------------------------// + //------------------------------------------------------------------------// + + public boolean isAddEnabled() { + return addEnabled; + } + + public void setAddEnabled(boolean addEnabled) { + boolean oldValue = isAddEnabled(); + this.addEnabled = addEnabled; + firePropertyChange(PROPERTY_ADD_ENABLED, oldValue, addEnabled); + } + + public boolean isRemoveEnabled() { + return removeEnabled; + } + + public void setRemoveEnabled(boolean removeEnabled) { + boolean oldValue = isRemoveEnabled(); + this.removeEnabled = removeEnabled; + firePropertyChange(PROPERTY_REMOVE_ENABLED, oldValue, removeEnabled); + } + + public boolean isSelectedUpEnabled() { + return selectedUpEnabled; + } + + public void setSelectedUpEnabled(boolean selectedUpEnabled) { + boolean oldValue = isSelectedUpEnabled(); + this.selectedUpEnabled = selectedUpEnabled; + firePropertyChange(PROPERTY_SELECTED_UP_ENABLED, oldValue, selectedUpEnabled); + } + + public boolean isSelectedDownEnabled() { + return selectedDownEnabled; + } + + public void setSelectedDownEnabled(boolean selectedDownEnabled) { + boolean oldValue = isSelectedDownEnabled(); + this.selectedDownEnabled = selectedDownEnabled; + firePropertyChange(PROPERTY_SELECTED_DOWN_ENABLED, oldValue, selectedDownEnabled); + } + + @Override + public Serializable getBean() { + return bean; + } + + public void setBean(Serializable bean) { + Object oldValue = getBean(); + this.bean = bean; + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + //------------------------------------------------------------------------// + //-- Internal methods ----------------------------------------------------// + //------------------------------------------------------------------------// + + private void resetUniverse() { + + universeModel.setAllElements(universe); + + } + + private void addToSelected(O item) { + + selectedModel.addElement(item); + if (!isUseMultiSelect()) { + // remove from universe list + universeModel.removeElement(item); + } + + } + + private void removeFromSelected(O item) { + + selectedModel.removeElement(item); + if (!isUseMultiSelect()) { + // add to universe list + universeModel.addElement(item); + } + + } + + int universeSize; + + int selectedSize; + + private void setValueIsAdjustingToTrue() { + + universeSize = universeModel.size(); + selectedSize = selectedModel.size(); + + universeModel.setValueIsAdjusting(true); + selectedModel.setValueIsAdjusting(true); + } + + private void setValueIsAdjustingToFalse(boolean updateUniverse) { + + universeModel.setValueIsAdjusting(false); + selectedModel.setValueIsAdjusting(false); + + if (updateUniverse) { + + universeModel.refresh(); + + } + + int currentSelectedSize = selectedModel.size(); + + if (currentSelectedSize <= selectedSize) { + + selectedModel.refresh(selectedSize); + + } else { + + selectedModel.refresh(); + + } + + } +} -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
participants (1)
-
nuiton.org scm