001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.binding.tutorial.basics;
032:
033: import java.beans.PropertyChangeEvent;
034: import java.beans.PropertyChangeListener;
035:
036: import javax.swing.*;
037:
038: import com.jgoodies.binding.PresentationModel;
039: import com.jgoodies.binding.adapter.BasicComponentFactory;
040: import com.jgoodies.binding.beans.Model;
041: import com.jgoodies.binding.beans.PropertyConnector;
042: import com.jgoodies.binding.tutorial.TutorialUtils;
043: import com.jgoodies.binding.value.ComponentValueModel;
044: import com.jgoodies.forms.builder.PanelBuilder;
045: import com.jgoodies.forms.layout.CellConstraints;
046: import com.jgoodies.forms.layout.FormLayout;
047:
048: /**
049: * Demonstrates how to modify the enabled/editable/visible state
050: * of a Swing component in a Presentation Model using the new
051: * ComponentValueModel that has been introduced in the Binding 1.1.
052: * The advantage of this approach is, that a PresentationModel
053: * can now easily operate on frequently used GUI state.<p>
054: *
055: * See the JavaDoc method comment for #initEventHandling
056: * in the ExamplePresentationModel.
057: *
058: * @author Karsten Lentzsch
059: * @version $Revision: 1.7 $
060: *
061: * @see com.jgoodies.binding.adapter.BasicComponentFactory
062: * @see com.jgoodies.binding.adapter.Bindings
063: *
064: * @since 1.1
065: */
066: public final class ComponentValueModelExample {
067:
068: // Holds an ExampleBean and vends ValueModels that adapt its properties.
069: private final ExamplePresentationModel<ExampleBean> presentationModel;
070:
071: private JTextField text1Field;
072: private JCheckBox enabledBox;
073: private JTextField text2Field;
074: private JCheckBox editableBox;
075: private JTextField text3Field;
076: private JCheckBox visibleBox;
077:
078: // Launching **************************************************************
079:
080: public static void main(String[] args) {
081: try {
082: UIManager
083: .setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
084: } catch (Exception e) {
085: // Likely PlasticXP is not in the class path; ignore.
086: }
087: JFrame frame = new JFrame();
088: frame.setTitle("Binding Tutorial :: ComponentValueModel");
089: frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
090: ComponentValueModelExample example = new ComponentValueModelExample();
091: JComponent panel = example.buildPanel();
092: frame.getContentPane().add(panel);
093: frame.pack();
094: TutorialUtils.locateOnOpticalScreenCenter(frame);
095: frame.setVisible(true);
096: }
097:
098: // Instance Creation ******************************************************
099:
100: /**
101: * Constructs the 'Components' example on an instance of ExampleBean.
102: */
103: public ComponentValueModelExample() {
104: presentationModel = new ExamplePresentationModel<ExampleBean>(
105: new ExampleBean());
106: }
107:
108: // Component Creation and Initialization **********************************
109:
110: /**
111: * Creates, binds and configures the UI components.<p>
112: *
113: * If possible, the components are created using the BasicComponentFactory,
114: * or the Bindings class.
115: */
116: private void initComponents() {
117: text1Field = BasicComponentFactory
118: .createTextField(presentationModel
119: .getComponentModel(ExampleBean.PROPERTYNAME_TEXT1));
120: text2Field = BasicComponentFactory
121: .createTextField(presentationModel
122: .getComponentModel(ExampleBean.PROPERTYNAME_TEXT2));
123: text3Field = BasicComponentFactory
124: .createTextField(presentationModel
125: .getComponentModel(ExampleBean.PROPERTYNAME_TEXT3));
126:
127: enabledBox = BasicComponentFactory.createCheckBox(
128: presentationModel
129: .getModel(ExampleBean.PROPERTYNAME_ENABLED),
130: "enabled");
131: editableBox = BasicComponentFactory.createCheckBox(
132: presentationModel
133: .getModel(ExampleBean.PROPERTYNAME_EDITABLE),
134: "editable");
135: visibleBox = BasicComponentFactory.createCheckBox(
136: presentationModel
137: .getModel(ExampleBean.PROPERTYNAME_VISIBLE),
138: "visible");
139: }
140:
141: // Building ***************************************************************
142:
143: /**
144: * Builds and returns the panel.
145: *
146: * @return the built panel
147: */
148: public JComponent buildPanel() {
149: initComponents();
150:
151: FormLayout layout = new FormLayout(
152: "right:pref, 3dlu, 50dlu, 3dlu, pref",
153: "p, 3dlu, p, 3dlu, p");
154:
155: PanelBuilder builder = new PanelBuilder(layout);
156: builder.setDefaultDialogBorder();
157: CellConstraints cc = new CellConstraints();
158: builder.addLabel("Text1", cc.xy(1, 1));
159: builder.add(text1Field, cc.xy(3, 1));
160: builder.add(enabledBox, cc.xy(5, 1));
161: builder.addLabel("Text2", cc.xy(1, 3));
162: builder.add(text2Field, cc.xy(3, 3));
163: builder.add(editableBox, cc.xy(5, 3));
164: builder.addLabel("Text3", cc.xy(1, 5));
165: builder.add(text3Field, cc.xy(3, 5));
166: builder.add(visibleBox, cc.xy(5, 5));
167: return builder.getPanel();
168: }
169:
170: // Helper Code ************************************************************
171:
172: public static final class ExampleBean extends Model {
173:
174: // Names of the Bound Bean Properties *************************************
175:
176: public static final String PROPERTYNAME_ENABLED = "enabled";
177: public static final String PROPERTYNAME_EDITABLE = "editable";
178: public static final String PROPERTYNAME_VISIBLE = "visible";
179: public static final String PROPERTYNAME_TEXT1 = "text1";
180: public static final String PROPERTYNAME_TEXT2 = "text2";
181: public static final String PROPERTYNAME_TEXT3 = "text3";
182:
183: // Fields *****************************************************************
184:
185: private boolean enabled;
186: private boolean editable;
187: private boolean visible;
188: private String text1;
189: private String text2;
190: private String text3;
191:
192: // Instance Creation ******************************************************
193:
194: public ExampleBean() {
195: enabled = true;
196: editable = false;
197: visible = true;
198: text1 = "Sample text1";
199: text2 = "Sample text2";
200: text3 = "Sample text3";
201: }
202:
203: // Accessors **************************************************************
204:
205: public boolean isEnabled() {
206: return enabled;
207: }
208:
209: public void setEnabled(boolean newEnabled) {
210: boolean oldEnabled = isEnabled();
211: enabled = newEnabled;
212: firePropertyChange(PROPERTYNAME_ENABLED, oldEnabled,
213: newEnabled);
214: }
215:
216: public boolean isEditable() {
217: return editable;
218: }
219:
220: public void setEditable(boolean newEditable) {
221: boolean oldEditable = isEditable();
222: editable = newEditable;
223: firePropertyChange(PROPERTYNAME_EDITABLE, oldEditable,
224: newEditable);
225: }
226:
227: public boolean isVisible() {
228: return visible;
229: }
230:
231: public void setVisible(boolean newVisible) {
232: boolean oldVisible = isVisible();
233: visible = newVisible;
234: firePropertyChange(PROPERTYNAME_VISIBLE, oldVisible,
235: newVisible);
236: }
237:
238: public String getText1() {
239: return text1;
240: }
241:
242: public void setText1(String newText) {
243: String oldText = getText1();
244: text1 = newText;
245: firePropertyChange(PROPERTYNAME_TEXT1, oldText, newText);
246: }
247:
248: public String getText2() {
249: return text2;
250: }
251:
252: public void setText2(String newText) {
253: String oldText = getText2();
254: text2 = newText;
255: firePropertyChange(PROPERTYNAME_TEXT2, oldText, newText);
256: }
257:
258: public String getText3() {
259: return text3;
260: }
261:
262: public void setText3(String newText) {
263: String oldText = getText3();
264: text3 = newText;
265: firePropertyChange(PROPERTYNAME_TEXT3, oldText, newText);
266: }
267:
268: }
269:
270: /**
271: * A custom PresentationModel that provides a SelectionInList
272: * for the bean's ListModel and the bean's list selection.
273: */
274: private static final class ExamplePresentationModel<B> extends
275: PresentationModel<B> {
276:
277: // Instance Creation -----------------------------------------
278:
279: private ExamplePresentationModel(ExampleBean exampleBean) {
280: super (exampleBean);
281: initEventHandling();
282: }
283:
284: // Event Handling ---------------------------------------------
285:
286: /**
287: * Initializes the event handling. The three domain properties
288: * enabled, editable, and visible are bound to the related
289: * properties of the ComponentValueModels for text1, text2, text3.<p>
290: *
291: * The first approach demonstrates how to register a hand-made
292: * value change handler with the domain's enabled model.
293: * This handler updates the enabled state of the ComponentValueModel
294: * whenever the domain changes. The ComponentValueModel change will
295: * in turn update all components bound to it.<p>
296: *
297: * A shorter way to write the above is to use a PropertyConnector.
298: * Whenever the editable or visible domain model changes,
299: * the PropertyConnector will update the connected property
300: * in the ComponentValueModel, which in turn will update all
301: * components bound to it.<p>
302: *
303: * Both approaches require to synchronize the ComponentValueModel state
304: * with the domain state at initialization time. In this example
305: * the initial domain state for enabled and visible is true,
306: * but the initial editable domain state is false, so the
307: * view bound to text 2 shall be non-editable first.
308: */
309: private void initEventHandling() {
310: // Observe changes in the domain's enabled property
311: // to update the enablement of the text1 views.
312: getModel(ExampleBean.PROPERTYNAME_ENABLED)
313: .addValueChangeListener(
314: new PropertyChangeListener() {
315: public void propertyChange(
316: PropertyChangeEvent evt) {
317: updateText1ViewsEnablement();
318: }
319: });
320: // Update the enablement of all views bound to text1 now.
321: updateText1ViewsEnablement();
322:
323: // Observe changes in the domain's editable property
324: // to update the editable state of text2 views.
325: // Update the editable state of all views bound to text2 now.
326: PropertyConnector.connectAndUpdate(
327: getModel(ExampleBean.PROPERTYNAME_EDITABLE),
328: getComponentModel(ExampleBean.PROPERTYNAME_TEXT2),
329: ComponentValueModel.PROPERTYNAME_EDITABLE);
330:
331: PropertyConnector.connectAndUpdate(
332: getModel(ExampleBean.PROPERTYNAME_VISIBLE),
333: getComponentModel(ExampleBean.PROPERTYNAME_TEXT3),
334: ComponentValueModel.PROPERTYNAME_VISIBLE);
335: }
336:
337: private void updateText1ViewsEnablement() {
338: boolean enabled = getModel(ExampleBean.PROPERTYNAME_ENABLED)
339: .booleanValue();
340: getComponentModel(ExampleBean.PROPERTYNAME_TEXT1)
341: .setEnabled(enabled);
342: }
343:
344: }
345:
346: }
|