001    /*
002     * Copyright 2002-2008 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.selection.binding;
017    
018    import java.beans.PropertyChangeEvent;
019    import java.beans.PropertyChangeListener;
020    import java.util.Collections;
021    import java.util.Comparator;
022    
023    import javax.swing.JComponent;
024    import javax.swing.ListCellRenderer;
025    
026    import org.springframework.binding.form.FormModel;
027    import org.springframework.binding.value.ValueModel;
028    import org.springframework.richclient.dialog.ApplicationDialog;
029    import org.springframework.richclient.form.binding.support.CustomBinding;
030    import org.springframework.richclient.selection.binding.support.LabelProvider;
031    import org.springframework.richclient.selection.binding.support.LabelProviderListCellRenderer;
032    import org.springframework.richclient.selection.binding.support.SelectField;
033    import org.springframework.richclient.selection.binding.support.ValueModel2EventListBridge;
034    import org.springframework.richclient.selection.dialog.FilterListSelectionDialog;
035    import org.springframework.richclient.selection.dialog.ListSelectionDialog;
036    import org.springframework.rules.closure.Closure;
037    import org.springframework.rules.closure.support.Block;
038    import org.springframework.util.StringUtils;
039    
040    import ca.odell.glazedlists.EventList;
041    import ca.odell.glazedlists.FilterList;
042    import ca.odell.glazedlists.GlazedLists;
043    import ca.odell.glazedlists.SortedList;
044    import ca.odell.glazedlists.impl.beans.BeanTextFilterator;
045    import ca.odell.glazedlists.impl.filter.StringTextFilterator;
046    
047    /**
048     * Binding for selection objects in a form.
049     * 
050     * @author Peter De Bruycker
051     */
052    public class ListSelectionDialogBinding extends CustomBinding {
053    
054        protected SelectField selectField;
055        private boolean filtered;
056        private String[] filterProperties;
057        private ListCellRenderer renderer;
058        private ValueModel selectableItemsHolder;
059        private LabelProvider labelProvider;
060        private Comparator comparator;
061        private String descriptionKey;
062        private String titleKey;
063        private boolean nullable = true;
064    
065        protected ListSelectionDialogBinding(SelectField selectField, FormModel formModel, String formPropertyPath) {
066            super(formModel, formPropertyPath, null);
067            this.selectField = selectField;
068        }
069    
070        protected JComponent doBindControl() {
071            selectField.setLabelProvider(labelProvider);
072            selectField.setSelectionDialog(createSelectionDialog());
073    
074            selectField.setNullable(nullable);
075            
076            // trigger control creation so we can set the value
077            selectField.getControl();
078    
079            selectField.setValue(getValue());
080    
081            selectField.addPropertyChangeListener("value", new PropertyChangeListener() {
082                public void propertyChange(PropertyChangeEvent evt) {
083                    controlValueChanged(selectField.getValue());
084                }
085            });
086    
087            return selectField.getControl();
088        }
089    
090        protected ApplicationDialog createSelectionDialog() {
091            EventList eventList = createEventList(selectableItemsHolder);
092            final ValueModel2EventListBridge itemRefresher = new ValueModel2EventListBridge(selectableItemsHolder,
093                    eventList, true);
094    
095            ListSelectionDialog selectionDialog = null;
096            if (filtered) {
097                FilterListSelectionDialog filterDialog = new FilterListSelectionDialog("", null, new FilterList(eventList));
098                if (filterProperties == null) {
099                    filterDialog.setFilterator(new StringTextFilterator());
100                } else {
101                    filterDialog.setFilterator(new BeanTextFilterator(filterProperties));
102                }
103    
104                selectionDialog = filterDialog;
105            } else {
106                selectionDialog = new ListSelectionDialog("", null, eventList);
107            }
108    
109            selectionDialog.setOnAboutToShow(new Block() {
110                protected void handle(Object ignore) {
111                    itemRefresher.synchronize();
112                }
113            });
114    
115            selectionDialog.setOnSelectAction(new Closure() {
116                public Object call(Object argument) {
117                    controlValueChanged(argument);
118                    selectField.setValue(argument);
119    
120                    return argument;
121                }
122            });
123            selectionDialog.setRenderer(getRendererForSelectionDialog());
124    
125            if (StringUtils.hasText(descriptionKey)) {
126                String description = getMessage(descriptionKey);
127                selectionDialog.setDescription(description);
128            }
129            if (StringUtils.hasText(titleKey)) {
130                String title = getMessage(titleKey);
131                selectionDialog.setTitle(title);
132            }
133    
134            return selectionDialog;
135        }
136    
137        private EventList createEventList(ValueModel selectableItemsHolder) {
138            EventList eventList = GlazedLists.eventList(Collections.emptyList());
139    
140            if (comparator != null) {
141                eventList = new SortedList(eventList, comparator);
142            }
143    
144            return eventList;
145        }
146    
147        protected ListCellRenderer getRendererForSelectionDialog() {
148            if (renderer != null) {
149                return renderer;
150            }
151    
152            if (labelProvider != null) {
153                return new LabelProviderListCellRenderer(labelProvider);
154            }
155    
156            return null;
157        }
158    
159        protected void enabledChanged() {
160            selectField.setEnabled(isEnabled());
161        }
162    
163        protected void readOnlyChanged() {
164            selectField.setEditable(!isReadOnly());
165        }
166    
167        public void setLabelProvider(LabelProvider provider) {
168            this.labelProvider = provider;
169        }
170    
171        protected void valueModelChanged(Object newValue) {
172            selectField.setValue(newValue);
173        }
174    
175        public void setFilterProperties(String[] filterProperties) {
176            this.filterProperties = filterProperties;
177        }
178    
179        public void setFiltered(boolean filtered) {
180            this.filtered = filtered;
181        }
182    
183        public void setRenderer(ListCellRenderer renderer) {
184            this.renderer = renderer;
185        }
186    
187        public void setSelectableItemsHolder(ValueModel selectableItemsHolder) {
188            this.selectableItemsHolder = selectableItemsHolder;
189        }
190    
191        public void setComparator(Comparator comparator) {
192            this.comparator = comparator;
193        }
194    
195        public void setDescriptionKey(String descriptionKey) {
196            this.descriptionKey = descriptionKey;
197        }
198    
199        public void setTitleKey(String titleKey) {
200            this.titleKey = titleKey;
201        }
202    
203        public void setNullable(boolean nullable) {
204            this.nullable = nullable;
205        }
206    }