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.dialog;
017
018 import java.awt.Window;
019 import java.awt.event.FocusAdapter;
020 import java.awt.event.FocusEvent;
021 import java.beans.PropertyChangeListener;
022
023 import javax.swing.JComponent;
024 import javax.swing.JFormattedTextField;
025 import javax.swing.SwingUtilities;
026 import javax.swing.text.JTextComponent;
027
028 import org.springframework.binding.form.ValidatingFormModel;
029 import org.springframework.rules.closure.Closure;
030 import org.springframework.rules.constraint.Constraint;
031 import org.springframework.richclient.core.Message;
032 import org.springframework.richclient.form.FormGuard;
033 import org.springframework.richclient.form.FormModelHelper;
034 import org.springframework.richclient.form.SimpleValidationResultsReporter;
035 import org.springframework.richclient.form.binding.swing.SwingBindingFactory;
036 import org.springframework.richclient.layout.TableLayoutBuilder;
037 import org.springframework.util.Assert;
038
039 /**
040 * Simple input application dialog consisting of a label and a text field for
041 * accepting input.
042 *
043 * @author Keith Donald
044 */
045 public class InputApplicationDialog extends ApplicationDialog implements Messagable {
046
047 private String inputLabelMessage = "dialog.input";
048
049 private JComponent inputField;
050
051 private Constraint inputConstraint;
052
053 private Closure finishAction;
054
055 private MessagePane reporter;
056
057 private ValidatingFormModel formModel;
058
059 public InputApplicationDialog(Object bean, String propertyName) {
060 this(bean, propertyName, true);
061 }
062
063 public InputApplicationDialog(Object bean, String propertyName, boolean bufferChanges) {
064 this(FormModelHelper.createFormModel(bean, bufferChanges), propertyName);
065 }
066
067 public InputApplicationDialog(ValidatingFormModel formModel, String propertyName) {
068 this();
069 this.formModel = formModel;
070 setInputField(new SwingBindingFactory(formModel).createBinding(propertyName).getControl());
071 }
072
073 public InputApplicationDialog() {
074 this(null, null, CloseAction.DISPOSE);
075 }
076
077 public InputApplicationDialog(String title, Window parent) {
078 this(title, parent, CloseAction.DISPOSE);
079 }
080
081 public InputApplicationDialog(String title, Window parent, CloseAction closeAction) {
082 super(title, parent, closeAction);
083 setResizable(true);
084 }
085
086 public void setInputField(JComponent field) {
087 Assert.notNull(field);
088 this.inputField = field;
089 }
090
091 public void setInputLabelMessage(String inputLabel) {
092 Assert.hasText(inputLabel, "The input label is required");
093 this.inputLabelMessage = inputLabel;
094 }
095
096 public void setInputConstraint(Constraint constraint) {
097 this.inputConstraint = constraint;
098 }
099
100 public void setFinishAction(Closure procedure) {
101 this.finishAction = procedure;
102 }
103
104 protected MessagePane createMessagePane() {
105 return new DefaultMessageAreaPane();
106 }
107
108 private MessagePane getMessagePane() {
109 if (reporter == null) {
110 reporter = createMessagePane();
111
112 if (this.formModel != null) {
113 new SimpleValidationResultsReporter(formModel.getValidationResults(), reporter);
114 FormGuard formGuard = new FormGuard(formModel);
115 formGuard.addGuarded(this, FormGuard.FORMERROR_GUARDED);
116 }
117 }
118 return reporter;
119 }
120
121 protected JComponent createDialogContentPane() {
122 TableLayoutBuilder layoutBuilder = new TableLayoutBuilder();
123
124 if (this.inputField == null) {
125 this.inputField = getComponentFactory().createTextField();
126 }
127 // work around for bug in JFormattedTextField text field for selectAll
128 if (inputField instanceof JFormattedTextField) {
129 SelectAllBugFixer selectAllBugFixer = new SelectAllBugFixer();
130 inputField.addFocusListener(selectAllBugFixer);
131 }
132
133 layoutBuilder.cell(createInputLabel(), TableLayoutBuilder.DEFAULT_LABEL_ATTRIBUTES);
134 layoutBuilder.labelGapCol();
135 layoutBuilder.cell(inputField);
136
137 layoutBuilder.unrelatedGapRow();
138 layoutBuilder.cell(getMessagePane().getControl());
139
140 layoutBuilder.relatedGapRow();
141 layoutBuilder.separator("");
142 return layoutBuilder.getPanel();
143 }
144
145 protected JComponent createInputLabel() {
146 return getComponentFactory().createLabelFor(inputLabelMessage, getInputField());
147 }
148
149 protected boolean onFinish() {
150 if (checkInputConstraint()) {
151 onFinish(getInputValue());
152 return true;
153 }
154 return false;
155 }
156
157 private boolean checkInputConstraint() {
158 if (inputConstraint != null)
159 return inputConstraint.test(getInputValue());
160
161 return true;
162 }
163
164 private Object getInputValue() {
165 if (inputField instanceof JFormattedTextField) {
166 return ((JFormattedTextField)inputField).getValue();
167 }
168 else if (inputField instanceof JTextComponent) {
169 return ((JTextComponent)inputField).getText();
170 }
171 else {
172 throw new IllegalStateException("Input field type not supported");
173 }
174 }
175
176 protected void onFinish(Object inputValue) {
177 if (formModel != null) {
178 formModel.commit();
179 }
180 if (finishAction != null) {
181 finishAction.call(inputValue);
182 }
183 }
184
185 public ValidatingFormModel getFormModel() {
186 return formModel;
187 }
188
189 /**
190 * @return Returns the inputField.
191 */
192 public JComponent getInputField() {
193 return inputField;
194 }
195
196 private static class SelectAllBugFixer extends FocusAdapter {
197 public void focusGained(final FocusEvent evt) {
198 SwingUtilities.invokeLater(new Runnable() {
199 public void run() {
200 ((JFormattedTextField)evt.getComponent()).selectAll();
201 }
202 });
203 }
204 }
205
206 public void setMessage(Message message) {
207 getMessagePane().setMessage(message);
208 }
209
210 public void addPropertyChangeListener(PropertyChangeListener listener) {
211 getMessagePane().addPropertyChangeListener(listener);
212 }
213
214 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
215 getMessagePane().addPropertyChangeListener(propertyName, listener);
216 }
217
218 public void removePropertyChangeListener(PropertyChangeListener listener) {
219 getMessagePane().removePropertyChangeListener(listener);
220 }
221
222 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
223 getMessagePane().removePropertyChangeListener(propertyName, listener);
224 }
225 }