001    package org.springframework.richclient.samples.showcase.binding;
002    
003    import org.springframework.binding.value.support.RefreshableValueHolder;
004    import org.springframework.binding.value.support.ValueHolder;
005    import org.springframework.richclient.dialog.TitledApplicationDialog;
006    import org.springframework.richclient.form.AbstractForm;
007    import org.springframework.richclient.form.Form;
008    import org.springframework.richclient.form.FormModelHelper;
009    import org.springframework.richclient.form.binding.swing.SwingBindingFactory;
010    import org.springframework.richclient.form.builder.TableFormBuilder;
011    import org.springframework.richclient.selection.binding.ListSelectionDialogBinder;
012    import org.springframework.richclient.selection.binding.support.LabelProvider;
013    import org.springframework.rules.closure.Closure;
014    
015    import javax.swing.*;
016    import java.beans.PropertyChangeEvent;
017    import java.beans.PropertyChangeListener;
018    import java.util.*;
019    
020    public class ListSelectionBindingDialog extends TitledApplicationDialog {
021    
022            private RefreshableValueHolder refreshableTownValueHolder;
023    
024            private List<Country> countries;
025    
026            private Map<Country, List<Town>> towns;
027    
028            private class Country {
029                    private String name;
030    
031                    public Country(String name) {
032                            this.name = name;
033                    }
034    
035                    public String getName() {
036                            return name;
037                    }
038            }
039    
040            private class Town {
041                    private String name;
042    
043                    public Town(String name) {
044                            this.name = name;
045                    }
046    
047                    public String getName() {
048                            return name;
049                    }
050            }
051    
052            protected void init() {
053                    Country belgium = new Country("Belgium");
054                    Country netherlands = new Country("Netherlands");
055                    Country germany = new Country("Germany");
056                    countries = new ArrayList<Country>();
057                    countries.add(belgium);
058                    countries.add(netherlands);
059                    countries.add(germany);
060                    towns = new HashMap<Country, List<Town>>();
061                    List<Town> belgiumTowns = new ArrayList<Town>();
062                    belgiumTowns.add(new Town("Ghent"));
063                    belgiumTowns.add(new Town("Antwerp"));
064                    towns.put(belgium, belgiumTowns);
065                    List<Town> netherlandsTowns = new ArrayList<Town>();
066                    netherlandsTowns.add(new Town("Eindhoven"));
067                    netherlandsTowns.add(new Town("Amsterdam"));
068                    towns.put(netherlands, netherlandsTowns);
069                    List<Town> germanyTowns = new ArrayList<Town>();
070                    germanyTowns.add(new Town("Dortmund"));
071                    germanyTowns.add(new Town("Keulen"));
072                    towns.put(germany, germanyTowns);
073            }
074    
075            public List<Country> getCountries() {
076                    return countries;
077            }
078    
079            public List<Town> getTowns(Country country) {
080                    return towns.get(country);
081            }
082    
083            private class Selection {
084                    private Country country;
085                    private Town town;
086                    private List<Town> towns = new ArrayList<Town>();
087    
088                    public void setCountry(Country country) {
089                            this.country = country;
090                    }
091    
092                    public Country getCountry() {
093                            return country;
094                    }
095    
096                    public void setTown(Town town) {
097                            this.town = town;
098                    }
099    
100                    public Town getTown() {
101                            return town;
102                    }
103    
104                    public List<Town> getTowns() {
105                            return towns;
106                    }
107    
108                    public void setTowns(List<Town> towns) {
109                            this.towns = towns;
110                    }
111            }
112    
113            private class ListSelectionBindingForm extends AbstractForm {
114    
115                    public ListSelectionBindingForm() {
116                            super(FormModelHelper.createFormModel(new Selection()));
117                    }
118    
119                    protected JComponent createFormControl() {
120                            SwingBindingFactory bf = new SwingBindingFactory(getFormModel());
121                            TableFormBuilder formBuilder = new TableFormBuilder(bf);
122                            formBuilder.row();
123    
124                            Map<String, Object> countryContext = new HashMap<String, Object>();
125                            countryContext.put(ListSelectionDialogBinder.SELECTABLE_ITEMS_HOLDER_KEY, new ValueHolder(countries));
126                            countryContext.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY, new LabelProvider() {
127                                    public String getLabel(Object item) {
128                                            Country country = (Country) item;
129                                            return country == null ? "" : country.getName();
130                                    }
131                            });
132                            countryContext.put(ListSelectionDialogBinder.FILTERED_KEY, Boolean.TRUE);
133                            countryContext.put(ListSelectionDialogBinder.FILTER_PROPERTIES_KEY, new String[] { "name" });
134                        
135                            // this works ... but unfortunately ListSelectionDialogBinder has no public constructor
136    //          ListSelectionDialogBinder binder = new ListSelectionDialogBinder();
137    //          Binding binding = binder.bind(getFormModel(), "country", countryContext);
138    //          formBuilder.add(binding, "colSpan=2");
139    
140                // this works if the binderSelectionStrategy is configured in richclient-application-context.xml
141                formBuilder.add(bf.createBinding("country", countryContext), "colSpan=2");
142    
143                formBuilder.row();
144    
145                            this.addFormValueChangeListener("country", new ChangeCountryListener());
146    
147                            refreshableTownValueHolder = new RefreshableValueHolder(new Closure() {
148                                    public Object call(Object object) {
149                                            Country country = (Country) getValue("country");
150                                            List<Town> towns = getTowns(country);
151                                            if (towns == null) {
152                            towns = Collections.EMPTY_LIST;
153                        }
154                                            return towns;
155                                    }
156                            }, true, false);
157                            refreshableTownValueHolder.setValue(Collections.EMPTY_LIST);
158                            formBuilder
159                                            .add(bf.createBoundComboBox("town", refreshableTownValueHolder, "name"), "colSpan=2 align=left");
160                            formBuilder.row();
161    
162                            return formBuilder.getForm();
163                    }
164            }
165    
166            private class ChangeCountryListener implements PropertyChangeListener {
167                    public ChangeCountryListener() {
168                    }
169    
170                    public void propertyChange(final PropertyChangeEvent evt) {
171                            refreshableTownValueHolder.refresh();
172                    }
173            }
174    
175            protected JComponent createTitledDialogContentPane() {
176                    Form form = new ListSelectionBindingForm();
177                    return form.getControl();
178            }
179    
180            protected boolean onFinish() {
181                    return true;
182            }
183    
184    }