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.support;
017
018 import java.awt.BorderLayout;
019 import java.awt.FlowLayout;
020 import java.beans.PropertyChangeListener;
021
022 import javax.swing.JComponent;
023 import javax.swing.JPanel;
024
025 import org.springframework.binding.value.PropertyChangePublisher;
026 import org.springframework.binding.value.support.PropertyChangeSupport;
027 import org.springframework.richclient.application.ApplicationServicesLocator;
028 import org.springframework.richclient.command.ActionCommand;
029 import org.springframework.richclient.command.config.CommandConfigurer;
030 import org.springframework.richclient.dialog.ApplicationDialog;
031 import org.springframework.richclient.factory.AbstractControlFactory;
032
033 /**
034 * <tt>SelectField</tt> base class. Allows for customization of the renderer component.
035 * <p>
036 * A <tt>SelectField</tt> provides a renderer component (provided by subclasses), a select button and a clear button.
037 * The renderer component shows the current value, the select button opens the selection dialog, and the clear button
038 * sets the value to <code>null</code>.
039 * </p>
040 *
041 * @author Peter De Bruycker
042 */
043 public abstract class SelectField extends AbstractControlFactory implements PropertyChangePublisher {
044
045 private JComponent renderer;
046 private SelectCommand selectCommand = new SelectCommand();
047 private ClearCommand clearCommand = new ClearCommand();
048 private boolean editable;
049 private Object value;
050 private ApplicationDialog dialog;
051 private LabelProvider labelProvider;
052 private JPanel control;
053 private boolean nullable = true;
054
055 private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
056
057 protected JComponent createControl() {
058 control = new JPanel(new BorderLayout());
059
060 renderer = createRenderer();
061 control.add(renderer);
062
063 // configure commands
064 CommandConfigurer configurer = (CommandConfigurer) ApplicationServicesLocator.services().getService(
065 CommandConfigurer.class);
066 configurer.configure(selectCommand);
067 configurer.configure(clearCommand);
068
069 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
070
071 buttonPanel.add(selectCommand.createButton());
072 if (nullable) {
073 buttonPanel.add(clearCommand.createButton());
074 }
075
076 control.add(buttonPanel, BorderLayout.LINE_END);
077
078 return control;
079 }
080
081 /**
082 * Create the component that will do the rendering. Cannot return <code>null</code>.
083 *
084 * @return the renderer component
085 */
086 protected abstract JComponent createRenderer();
087
088 public void setEnabled(boolean enabled) {
089 control.setEnabled(enabled);
090
091 renderer.setEnabled(enabled);
092 selectCommand.setEnabled(enabled);
093 clearCommand.setEnabled(enabled);
094 }
095
096 public void setEditable(boolean editable) {
097 this.editable = editable;
098
099 selectCommand.setEnabled(control.isEnabled() && editable);
100 clearCommand.setEnabled(control.isEnabled() && editable);
101 }
102
103 public boolean isEditable() {
104 return editable;
105 }
106
107 public void setValue(Object value) {
108 Object oldValue = this.value;
109 this.value = value;
110
111 render(value);
112
113 propertyChangeSupport.firePropertyChange("value", oldValue, value);
114 }
115
116 /**
117 * Convenience method, calls <code>setValue(null)</code>.
118 */
119 public void clear() {
120 setValue(null);
121 }
122
123 /**
124 * Render the given value. Warning: the value can be <code>null</code>.
125 *
126 * @param value
127 * the value
128 */
129 protected abstract void render(Object value);
130
131 public Object getValue() {
132 return value;
133 }
134
135 public void setSelectionDialog(ApplicationDialog dialog) {
136 this.dialog = dialog;
137 }
138
139 public void setLabelProvider(LabelProvider labelProvider) {
140 this.labelProvider = labelProvider;
141 }
142
143 public LabelProvider getLabelProvider() {
144 return labelProvider;
145 }
146
147 /**
148 * Returns whether the property is nullable. If set to true, the "clear" button is shown.
149 *
150 * @return whether the property is nullable
151 */
152 public boolean isNullable() {
153 return nullable;
154 }
155
156 /**
157 * Sets whether the clear button is shown
158 *
159 * @param nullable
160 * whether the clear button is shown
161 */
162 public void setNullable(boolean nullable) {
163 this.nullable = nullable;
164 }
165
166 private class ClearCommand extends ActionCommand {
167
168 public ClearCommand() {
169 super("selectField.clearCommand");
170 }
171
172 protected void doExecuteCommand() {
173 clear();
174 }
175
176 }
177
178 private class SelectCommand extends ActionCommand {
179
180 public SelectCommand() {
181 super("selectField.selectCommand");
182 }
183
184 protected void doExecuteCommand() {
185 dialog.showDialog();
186 }
187 }
188
189 public void addPropertyChangeListener(PropertyChangeListener listener) {
190 propertyChangeSupport.addPropertyChangeListener(listener);
191 }
192
193 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
194 propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
195 }
196
197 public void removePropertyChangeListener(PropertyChangeListener listener) {
198 propertyChangeSupport.removePropertyChangeListener(listener);
199 }
200
201 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
202 propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
203 }
204 }