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>.