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.awt.event.ActionEvent;
034:
035: import javax.swing.*;
036: import javax.swing.event.ChangeEvent;
037: import javax.swing.event.ChangeListener;
038: import javax.swing.text.JTextComponent;
039:
040: import com.jgoodies.binding.tutorial.Album;
041: import com.jgoodies.binding.tutorial.TutorialUtils;
042: import com.jgoodies.forms.builder.PanelBuilder;
043: import com.jgoodies.forms.factories.ButtonBarFactory;
044: import com.jgoodies.forms.layout.CellConstraints;
045: import com.jgoodies.forms.layout.FormLayout;
046:
047: /**
048: * Builds an editor that copies data from the domain back and forth.
049: * This approach is known as the "copying" approach or "push/pull".<p>
050: *
051: * The event handling used to enable and disable the composer text field
052: * is invoked by a ChangeListener that hooks into the classical check box.
053: * Note that this lacks the domain logic, where the composer is set to
054: * <code>null</code> if the classical property is set to false.
055: * This logic is deferred until the component values are written to the
056: * edited Album via <code>#updateModel</code> when OK is pressed.
057: *
058: * @author Karsten Lentzsch
059: * @version $Revision: 1.14 $
060: */
061:
062: public final class EditorCopyingExample {
063:
064: /**
065: * Refers to the Album that is to be edited by this example editor.
066: */
067: private final Album editedAlbum;
068:
069: private JTextComponent titleField;
070: private JTextComponent artistField;
071: private JCheckBox classicalBox;
072: private JTextComponent composerField;
073: private JButton okButton;
074: private JButton cancelButton;
075: private JButton resetButton;
076:
077: // Launching **************************************************************
078:
079: public static void main(String[] args) {
080: try {
081: UIManager
082: .setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
083: } catch (Exception e) {
084: // Likely PlasticXP is not in the class path; ignore.
085: }
086: JFrame frame = new JFrame();
087: frame.setTitle("Binding Tutorial :: Editor (Copying)");
088: frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
089: EditorCopyingExample example = new EditorCopyingExample();
090: JComponent panel = example.buildPanel();
091: example.updateView();
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 an editor for an example Album.
102: */
103: public EditorCopyingExample() {
104: this (Album.ALBUM1);
105: }
106:
107: /**
108: * Constructs an editor for an Album to be edited.
109: *
110: * @param album the Album to be edited
111: */
112: public EditorCopyingExample(Album album) {
113: this .editedAlbum = album;
114: }
115:
116: // Initialization *********************************************************
117:
118: /**
119: * Creates and initializes the UI components.
120: */
121: private void initComponents() {
122: titleField = new JTextField();
123: artistField = new JTextField();
124: classicalBox = new JCheckBox("Classical");
125: composerField = new JTextField();
126: okButton = new JButton(new OKAction());
127: cancelButton = new JButton(new CancelAction());
128: resetButton = new JButton(new ResetAction());
129:
130: updateComposerField();
131: }
132:
133: /**
134: * Observes the classical check box to update the composer field's
135: * enablement and contents. For demonstration purposes a listener
136: * is registered that writes all changes to the console.
137: */
138: private void initEventHandling() {
139: classicalBox.addChangeListener(new ClassicalChangeHandler());
140:
141: // Report changes in all bound Album properties.
142: editedAlbum.addPropertyChangeListener(TutorialUtils
143: .createDebugPropertyChangeListener());
144: }
145:
146: // Copying Data Back and Forth ********************************************
147:
148: /**
149: * Reads the property values from the edited Album
150: * and sets them in this editor's components.
151: */
152: private void updateView() {
153: titleField.setText(editedAlbum.getTitle());
154: artistField.setText(editedAlbum.getArtist());
155: classicalBox.setSelected(editedAlbum.isClassical());
156: composerField.setText(editedAlbum.getComposer());
157: }
158:
159: /**
160: * Reads the values from this editor's components
161: * and set the associated Album properties.
162: */
163: private void updateModel() {
164: editedAlbum.setTitle(titleField.getText());
165: editedAlbum.setArtist(artistField.getText());
166: editedAlbum.setClassical(classicalBox.isSelected());
167: editedAlbum.setComposer(composerField.getText());
168: }
169:
170: // Building ***************************************************************
171:
172: /**
173: * Builds and returns the editor panel.
174: *
175: * @return the built panel
176: */
177: public JComponent buildPanel() {
178: initComponents();
179: initEventHandling();
180:
181: FormLayout layout = new FormLayout(
182: "right:pref, 3dlu, 150dlu:grow",
183: "p, 3dlu, p, 3dlu, p, 3dlu, p, 9dlu, p");
184:
185: PanelBuilder builder = new PanelBuilder(layout);
186: builder.setDefaultDialogBorder();
187: CellConstraints cc = new CellConstraints();
188:
189: builder.addLabel("Artist", cc.xy(1, 1));
190: builder.add(artistField, cc.xy(3, 1));
191: builder.addLabel("Title", cc.xy(1, 3));
192: builder.add(titleField, cc.xy(3, 3));
193: builder.add(classicalBox, cc.xy(3, 5));
194: builder.addLabel("Composer", cc.xy(1, 7));
195: builder.add(composerField, cc.xy(3, 7));
196: builder.add(buildButtonBar(), cc.xyw(1, 9, 3));
197:
198: return builder.getPanel();
199: }
200:
201: private JComponent buildButtonBar() {
202: return ButtonBarFactory.buildRightAlignedBar(okButton,
203: cancelButton, resetButton);
204: }
205:
206: // Event Handling *********************************************************
207:
208: /**
209: * Updates the composer field's enablement and contents.
210: * Sets the enablement according to the selection state
211: * of the classical check box. If the composer is not enabled,
212: * we copy the domain logic and clear the composer field's text.
213: */
214: private void updateComposerField() {
215: boolean composerEnabled = classicalBox.isSelected();
216: composerField.setEnabled(composerEnabled);
217: if (!composerEnabled) {
218: composerField.setText("");
219: }
220: }
221:
222: /**
223: * Updates the composer field's enablement and text.
224: */
225: private final class ClassicalChangeHandler implements
226: ChangeListener {
227:
228: /**
229: * The selection state of the classical check box has changed.
230: * Updates the enablement and contents of the composer field.
231: */
232: public void stateChanged(ChangeEvent evt) {
233: updateComposerField();
234: }
235: }
236:
237: // Actions ****************************************************************
238:
239: private final class OKAction extends AbstractAction {
240:
241: private OKAction() {
242: super ("OK");
243: }
244:
245: public void actionPerformed(ActionEvent e) {
246: updateModel();
247: System.out.println(editedAlbum);
248: System.exit(0);
249: }
250: }
251:
252: private final class CancelAction extends AbstractAction {
253:
254: private CancelAction() {
255: super ("Cancel");
256: }
257:
258: public void actionPerformed(ActionEvent e) {
259: // Just ignore the current content.
260: System.out.println(editedAlbum);
261: System.exit(0);
262: }
263: }
264:
265: private final class ResetAction extends AbstractAction {
266:
267: private ResetAction() {
268: super ("Reset");
269: }
270:
271: public void actionPerformed(ActionEvent e) {
272: updateView();
273: System.out.println(editedAlbum);
274: }
275: }
276:
277: }
|