001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.list;
017    
018    import java.beans.PropertyChangeEvent;
019    import java.beans.PropertyChangeListener;
020    import java.util.Collection;
021    import java.util.List;
022    
023    import org.apache.commons.logging.Log;
024    import org.apache.commons.logging.LogFactory;
025    import org.springframework.binding.value.ValueModel;
026    import org.springframework.binding.value.support.ValueHolder;
027    
028    /**
029     * A combobox whose contents are dynamically refreshable.
030     * 
031     * @author Keith Donald
032     */
033    public class DynamicComboBoxListModel extends ComboBoxListModel implements PropertyChangeListener {
034        
035        private static final Log logger = LogFactory.getLog(DynamicComboBoxListModel.class);
036        
037        private final SelectedItemChangeHandler selectedItemChangeHandler = new SelectedItemChangeHandler();
038    
039        private final ValueModel selectedItemHolder;
040    
041        private ValueModel selectableItemsHolder;
042    
043        public DynamicComboBoxListModel(ValueModel selectedItemHolder) {
044            this(selectedItemHolder, (ValueModel)null);
045        }
046    
047        public DynamicComboBoxListModel(ValueModel selectedItemHolder, List items) {
048            this(selectedItemHolder, new ValueHolder(items));
049        }
050    
051        public DynamicComboBoxListModel(ValueModel selectedItemHolder, ValueModel selectableItemsHolder) {
052            this.selectedItemHolder = selectedItemHolder;
053            if (selectedItemHolder != null) {
054                selectedItemHolder.addValueChangeListener(selectedItemChangeHandler);
055            }
056            setSelectableItemsHolder(selectableItemsHolder);
057        }
058    
059        public void setSelectableItemsHolder(ValueModel holder) {
060            if (this.selectableItemsHolder == holder) {
061                return;
062            }
063            if (this.selectableItemsHolder != null) {
064                holder.removeValueChangeListener(this);
065            }
066            this.selectableItemsHolder = holder;
067            if (this.selectableItemsHolder != null) {
068                doAdd(holder.getValue());
069                this.selectableItemsHolder.addValueChangeListener(this);
070            }
071        }
072    
073        public Object getSelectedItem() {
074            if (selectedItemHolder != null) {
075                if (logger.isDebugEnabled()) {
076                    logger.debug("Returning selected item " + selectedItemHolder.getValue());
077                }
078                return selectedItemHolder.getValue();
079            }
080    
081            return super.getSelectedItem();
082        }
083    
084        public void setSelectedItem(Object selectedItem) {
085            if (selectedItemHolder != null) {
086                if (logger.isDebugEnabled()) {
087                    logger.debug("Setting newly selected item on value holder to " + selectedItem);
088                }
089                selectedItemHolder.setValue(selectedItem);
090            }
091            else {
092                super.setSelectedItem(selectedItem);
093            }
094        }
095    
096        public void propertyChange(PropertyChangeEvent evt) {
097            if (logger.isDebugEnabled()) {
098                logger.debug("Backing collection of selectable items changed; "
099                        + "refreshing combo box with contents of new collection.");
100            }
101            doAdd(selectableItemsHolder.getValue());
102        }
103    
104        private void doAdd(Object items) {
105            clear();
106            if (items != null) {
107                if (items instanceof Collection) {
108                    addAll((Collection)items);
109                }
110                else if (items instanceof Object[]) {
111                    Object[] itemsArray = (Object[])items;
112                    for (int i = 0; i < itemsArray.length; i++) {
113                        add(itemsArray[i]);
114                    }
115                }
116                else {
117                    throw new IllegalArgumentException("selectableItemsHolder must hold a Collection or array");
118                }
119            }
120            sort();
121        }
122        
123        private class SelectedItemChangeHandler implements PropertyChangeListener {
124    
125            public void propertyChange(PropertyChangeEvent evt) {
126                if (logger.isDebugEnabled()) {
127                    logger.debug("Notifying combo box view selected value changed; new value is '"
128                            + selectedItemHolder.getValue() + "'");
129                }
130                /*
131                if (selectedItemHolder.getValue() == null) {
132                    if (size() > 0 && get(0) != null) {
133                        if (logger.isDebugEnabled()) {
134                            logger
135                                    .debug("Backing value model is null; Pre-setting initial value to first combo-box element "
136                                            + get(0));
137                        }
138                        setSelectedItem(get(0));
139                    }
140                }
141                else {
142                */
143                    if (logger.isDebugEnabled()) {
144                        logger.debug("Firing contents change event; selected item may have changed");
145                    }
146                    fireContentsChanged(this, -1, -1);
147                    if (logger.isDebugEnabled()) {
148                        logger.debug("Fired contents change event!");
149                    }
150                //}
151            }
152        }
153    
154    }