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.Color;
034: import java.awt.Component;
035: import java.awt.Window;
036: import java.awt.event.*;
037: import java.beans.PropertyChangeEvent;
038: import java.beans.PropertyChangeListener;
039: import java.io.Serializable;
040: import java.text.NumberFormat;
041: import java.util.Date;
042: import java.util.GregorianCalendar;
043:
044: import javax.swing.*;
045: import javax.swing.border.LineBorder;
046:
047: import com.jgoodies.binding.PresentationModel;
048: import com.jgoodies.binding.adapter.BasicComponentFactory;
049: import com.jgoodies.binding.adapter.BoundedRangeAdapter;
050: import com.jgoodies.binding.adapter.SingleListSelectionAdapter;
051: import com.jgoodies.binding.adapter.SpinnerAdapterFactory;
052: import com.jgoodies.binding.beans.Model;
053: import com.jgoodies.binding.list.ArrayListModel;
054: import com.jgoodies.binding.list.ObservableList;
055: import com.jgoodies.binding.list.SelectionInList;
056: import com.jgoodies.binding.tutorial.Album;
057: import com.jgoodies.binding.tutorial.TutorialUtils;
058: import com.jgoodies.binding.value.BufferedValueModel;
059: import com.jgoodies.binding.value.ConverterFactory;
060: import com.jgoodies.binding.value.Trigger;
061: import com.jgoodies.binding.value.ValueModel;
062: import com.jgoodies.forms.builder.PanelBuilder;
063: import com.jgoodies.forms.layout.CellConstraints;
064: import com.jgoodies.forms.layout.ColumnSpec;
065: import com.jgoodies.forms.layout.FormLayout;
066:
067: /**
068: * Demonstrates how to bind different value types to Swing components.
069: *
070: * @author Karsten Lentzsch
071: * @version $Revision: 1.24 $
072: *
073: * @see com.jgoodies.binding.adapter.BasicComponentFactory
074: * @see com.jgoodies.binding.adapter.Bindings
075: */
076: public final class ComponentsExample {
077:
078: // Holds an ExampleBean and vends ValueModels that adapt its properties.
079: private final ExamplePresentationModel<ExampleBean> presentationModel;
080:
081: // Text Components
082: private JTextField textField;
083: private JTextArea textArea;
084: private JPasswordField passwordField;
085: private JLabel textLabel;
086:
087: // Formatted Input
088: private JFormattedTextField dateField;
089: private JFormattedTextField integerField;
090: private JFormattedTextField longField;
091:
092: // Lists
093: private JComboBox comboBox;
094: private JList list;
095: private JTable table;
096:
097: // Choice
098: private JRadioButton leftIntRadio;
099: private JRadioButton centerIntRadio;
100: private JRadioButton rightIntRadio;
101: private JComboBox alignmentIntCombo;
102: private JRadioButton leftObjectRadio;
103: private JRadioButton centerObjectRadio;
104: private JRadioButton rightObjectRadio;
105: private JComboBox alignmentObjectCombo;
106:
107: // Misc
108: private JCheckBox checkBox;
109: private JPanel colorPreview;
110: private JSlider slider;
111: private JLabel floatLabel;
112: private JSpinner spinner;
113:
114: // Launching **************************************************************
115:
116: public static void main(String[] args) {
117: try {
118: UIManager
119: .setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
120: } catch (Exception e) {
121: // Likely PlasticXP is not in the class path; ignore.
122: }
123: JFrame frame = new JFrame();
124: frame.setTitle("Binding Tutorial :: Components");
125: frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
126: ComponentsExample example = new ComponentsExample();
127: JComponent panel = example.buildPanel();
128: frame.getContentPane().add(panel);
129: frame.pack();
130: TutorialUtils.locateOnOpticalScreenCenter(frame);
131: frame.setVisible(true);
132: }
133:
134: // Instance Creation ******************************************************
135:
136: /**
137: * Constructs the 'Components' example on an instance of ExampleBean.
138: */
139: public ComponentsExample() {
140: presentationModel = new ExamplePresentationModel<ExampleBean>(
141: new ExampleBean());
142: }
143:
144: // Component Creation and Initialization **********************************
145:
146: /**
147: * Creates, binds and configures the UI components.<p>
148: *
149: * If possible, the components are created using the BasicComponentFactory,
150: * or the Bindings class.
151: */
152: private void initComponents() {
153: // Text Components
154: textField = BasicComponentFactory
155: .createTextField(presentationModel
156: .getModel(ExampleBean.PROPERTYNAME_TEXT));
157: textArea = BasicComponentFactory
158: .createTextArea(presentationModel
159: .getModel(ExampleBean.PROPERTYNAME_TEXT));
160: passwordField = BasicComponentFactory
161: .createPasswordField(presentationModel
162: .getModel(ExampleBean.PROPERTYNAME_TEXT));
163: textLabel = BasicComponentFactory.createLabel(presentationModel
164: .getModel(ExampleBean.PROPERTYNAME_TEXT));
165:
166: // Formatted Input
167: dateField = BasicComponentFactory
168: .createDateField(presentationModel
169: .getModel(ExampleBean.PROPERTYNAME_DATE));
170: integerField = BasicComponentFactory
171: .createIntegerField(presentationModel
172: .getModel(ExampleBean.PROPERTYNAME_INT_VALUE));
173: longField = BasicComponentFactory
174: .createLongField(presentationModel
175: .getModel(ExampleBean.PROPERTYNAME_LONG_VALUE));
176:
177: // Choice
178: ValueModel intChoiceModel = presentationModel
179: .getModel(ExampleBean.PROPERTYNAME_INT_CHOICE);
180: leftIntRadio = BasicComponentFactory.createRadioButton(
181: intChoiceModel, ExampleBean.LEFT_INTEGER, "Left");
182: centerIntRadio = BasicComponentFactory.createRadioButton(
183: intChoiceModel, ExampleBean.CENTER_INTEGER, "Center");
184: rightIntRadio = BasicComponentFactory.createRadioButton(
185: intChoiceModel, ExampleBean.RIGHT_INTEGER, "Right");
186: alignmentIntCombo = BasicComponentFactory
187: .createComboBox(new SelectionInList<Integer>(
188: ExampleBean.INTEGER_CHOICES, intChoiceModel));
189:
190: ValueModel objectChoiceModel = presentationModel
191: .getModel(ExampleBean.PROPERTYNAME_OBJECT_CHOICE);
192: leftObjectRadio = BasicComponentFactory.createRadioButton(
193: objectChoiceModel, ExampleBean.LEFT, "Left");
194: centerObjectRadio = BasicComponentFactory.createRadioButton(
195: objectChoiceModel, ExampleBean.CENTER, "Center");
196: rightObjectRadio = BasicComponentFactory.createRadioButton(
197: objectChoiceModel, ExampleBean.RIGHT, "Right");
198: alignmentObjectCombo = BasicComponentFactory
199: .createComboBox(new SelectionInList<Object>(
200: ExampleBean.OBJECT_CHOICES, objectChoiceModel));
201:
202: // Lists
203: comboBox = BasicComponentFactory.createComboBox(
204: presentationModel.getSelectionInList(), TutorialUtils
205: .createAlbumListCellRenderer());
206:
207: list = BasicComponentFactory.createList(presentationModel
208: .getSelectionInList(), TutorialUtils
209: .createAlbumListCellRenderer());
210:
211: table = new JTable();
212: table.setModel(TutorialUtils
213: .createAlbumTableModel(presentationModel
214: .getSelectionInList()));
215: table.setSelectionModel(new SingleListSelectionAdapter(
216: presentationModel.getSelectionInList()
217: .getSelectionIndexHolder()));
218:
219: // Misc
220: checkBox = BasicComponentFactory
221: .createCheckBox(
222: presentationModel
223: .getModel(ExampleBean.PROPERTYNAME_BOOLEAN_VALUE),
224: "available");
225: colorPreview = new JPanel();
226: colorPreview.setBorder(new LineBorder(Color.GRAY));
227: updatePreviewPanel();
228:
229: ValueModel floatModel = presentationModel
230: .getModel(ExampleBean.PROPERTYNAME_FLOAT_VALUE);
231: slider = new JSlider();
232: slider.setModel(new BoundedRangeAdapter(ConverterFactory
233: .createFloatToIntegerConverter(floatModel, 100), 0, 0,
234: 100));
235: floatLabel = BasicComponentFactory.createLabel(ConverterFactory
236: .createStringConverter(floatModel, NumberFormat
237: .getPercentInstance()));
238: spinner = new JSpinner();
239: spinner
240: .setModel(SpinnerAdapterFactory
241: .createNumberAdapter(
242: presentationModel
243: .getModel(ExampleBean.PROPERTYNAME_INT_LIMITED),
244: 0, // defaultValue
245: 0, // minValue
246: 100, // maxValue
247: 5)); // step
248: }
249:
250: private void initEventHandling() {
251: presentationModel.getModel(ExampleBean.PROPERTYNAME_COLOR)
252: .addValueChangeListener(new ColorUpdateHandler());
253: }
254:
255: private void updatePreviewPanel() {
256: colorPreview.setBackground(presentationModel.getBean()
257: .getColor());
258: }
259:
260: // Building ***************************************************************
261:
262: /**
263: * Builds and returns the panel.
264: *
265: * @return the built panel
266: */
267: public JComponent buildPanel() {
268: initComponents();
269: initEventHandling();
270:
271: JTabbedPane tabbedPane = new JTabbedPane();
272: tabbedPane.putClientProperty("jgoodies.noContentBorder",
273: Boolean.TRUE);
274:
275: tabbedPane.addTab("Text", buildTextPanel());
276: tabbedPane.addTab("Formatted", buildFormattedPanel());
277: tabbedPane.addTab("Choices", buildChoicesPanel());
278: tabbedPane.addTab("List", buildListPanel());
279: tabbedPane.addTab("Misc", buildMiscPanel());
280: return tabbedPane;
281: }
282:
283: private JPanel buildTextPanel() {
284: FormLayout layout = new FormLayout(
285: "right:max(50dlu;pref), 3dlu, 50dlu",
286: "p, 3dlu, p, 3dlu, p, 14dlu, 3dlu, p");
287: layout.setRowGroups(new int[][] { { 1, 3, 5 } });
288:
289: PanelBuilder builder = new PanelBuilder(layout);
290: builder.setDefaultDialogBorder();
291: CellConstraints cc = new CellConstraints();
292: builder.addLabel("JTextField", cc.xy(1, 1));
293: builder.add(textField, cc.xy(3, 1));
294: builder.addLabel("JPasswordField", cc.xy(1, 3));
295: builder.add(passwordField, cc.xy(3, 3));
296: builder.addLabel("JTextArea", cc.xy(1, 5));
297: builder.add(new JScrollPane(textArea), cc.xywh(3, 5, 1, 2));
298: builder.addLabel("JLabel", cc.xy(1, 8));
299: builder.add(textLabel, cc.xy(3, 8));
300: return builder.getPanel();
301: }
302:
303: private JPanel buildFormattedPanel() {
304: FormLayout layout = new FormLayout(
305: "right:max(50dlu;pref), 3dlu, 50dlu",
306: "p, 3dlu, p, 3dlu, p");
307:
308: PanelBuilder builder = new PanelBuilder(layout);
309: builder.setDefaultDialogBorder();
310: CellConstraints cc = new CellConstraints();
311: builder.addLabel("Date", cc.xy(1, 1));
312: builder.add(dateField, cc.xy(3, 1));
313: builder.addLabel("Integer", cc.xy(1, 3));
314: builder.add(integerField, cc.xy(3, 3));
315: builder.addLabel("Long", cc.xy(1, 5));
316: builder.add(longField, cc.xy(3, 5));
317: return builder.getPanel();
318: }
319:
320: private JPanel buildChoicesPanel() {
321: FormLayout layout = new FormLayout(
322: "right:max(50dlu;pref), 3dlu, p, 6dlu, p, 6dlu, p, 0:grow",
323: "p, 3dlu, p, 3dlu, p, 9dlu, p, 3dlu, p, 3dlu, p");
324:
325: PanelBuilder builder = new PanelBuilder(layout);
326: builder.setDefaultDialogBorder();
327: CellConstraints cc = new CellConstraints();
328: builder.addSeparator("Integer Choice", cc.xyw(1, 1, 8));
329: builder.addLabel("JRadioButton", cc.xy(1, 3));
330: builder.add(leftIntRadio, cc.xy(3, 3));
331: builder.add(centerIntRadio, cc.xy(5, 3));
332: builder.add(rightIntRadio, cc.xy(7, 3));
333: builder.addLabel("JComboBox", cc.xy(1, 5));
334: builder.add(alignmentIntCombo, cc.xyw(3, 5, 3));
335:
336: builder.addSeparator("Object Choice", cc.xyw(1, 7, 8));
337: builder.addLabel("JRadioButton", cc.xy(1, 9));
338: builder.add(leftObjectRadio, cc.xy(3, 9));
339: builder.add(centerObjectRadio, cc.xy(5, 9));
340: builder.add(rightObjectRadio, cc.xy(7, 9));
341: builder.addLabel("JComboBox", cc.xy(1, 11));
342: builder.add(alignmentObjectCombo, cc.xyw(3, 11, 3));
343: return builder.getPanel();
344: }
345:
346: private JPanel buildListPanel() {
347: FormLayout layout = new FormLayout(
348: "right:max(50dlu;pref), 3dlu, 150dlu",
349: "fill:60dlu, 6dlu, fill:60dlu, 6dlu, p");
350:
351: PanelBuilder builder = new PanelBuilder(layout);
352: builder.setDefaultDialogBorder();
353: CellConstraints cc = new CellConstraints();
354: builder.addLabel("JList", cc.xy(1, 1, "right, top"));
355: builder.add(new JScrollPane(list), cc.xy(3, 1));
356: builder.addLabel("JTable", cc.xy(1, 3, "right, top"));
357: builder.add(new JScrollPane(table), cc.xy(3, 3));
358: builder.addLabel("JComboBox", cc.xy(1, 5));
359: builder.add(comboBox, cc.xy(3, 5));
360: return builder.getPanel();
361: }
362:
363: private JPanel buildMiscPanel() {
364: FormLayout layout = new FormLayout(
365: "right:max(50dlu;pref), 3dlu, 50dlu, 3dlu, 50dlu",
366: "p, 3dlu, p, 3dlu, p, 3dlu, p");
367: layout.setRowGroups(new int[][] { { 1, 3, 5 } });
368:
369: PanelBuilder builder = new PanelBuilder(layout);
370: builder.setDefaultDialogBorder();
371:
372: Action chooseAction = new ChooseColorAction(builder.getPanel(),
373: presentationModel
374: .getModel(ExampleBean.PROPERTYNAME_COLOR));
375:
376: CellConstraints cc = new CellConstraints();
377: builder.addLabel("JCheckBox", cc.xy(1, 1));
378: builder.add(checkBox, cc.xy(3, 1));
379: builder.addLabel("JSlider", cc.xy(1, 3));
380: builder.add(slider, cc.xy(3, 3));
381: builder.add(floatLabel, cc.xy(5, 3));
382: builder.addLabel("JSpinner", cc.xy(1, 5));
383: builder.add(spinner, cc.xy(3, 5));
384: builder.addLabel("JColorChooser", cc.xy(1, 7));
385: builder.add(colorPreview, cc.xy(3, 7, "fill, fill"));
386: builder.add(new JButton(chooseAction), cc.xy(5, 7,
387: "left, center"));
388: return builder.getPanel();
389: }
390:
391: // Helper Code ************************************************************
392:
393: @SuppressWarnings("boxing")
394: public static final class ExampleBean extends Model {
395:
396: // Names of the Bound Bean Properties *************************************
397:
398: public static final String PROPERTYNAME_BOOLEAN_VALUE = "booleanValue";
399: public static final String PROPERTYNAME_COLOR = "color";
400: public static final String PROPERTYNAME_DATE = "date";
401: public static final String PROPERTYNAME_FLOAT_VALUE = "floatValue";
402: public static final String PROPERTYNAME_INT_CHOICE = "intChoice";
403: public static final String PROPERTYNAME_INT_LIMITED = "intLimited";
404: public static final String PROPERTYNAME_INT_VALUE = "intValue";
405: public static final String PROPERTYNAME_LIST_SELECTION = "listSelection";
406: public static final String PROPERTYNAME_LONG_VALUE = "longValue";
407: public static final String PROPERTYNAME_OBJECT_CHOICE = "objectChoice";
408: public static final String PROPERTYNAME_TEXT = "text";
409:
410: // Constants **************************************************************
411:
412: // An int based enumeration.
413: public static final Integer LEFT_INTEGER = 0;
414: public static final Integer CENTER_INTEGER = 1;
415: public static final Integer RIGHT_INTEGER = 2;
416: static final Integer[] INTEGER_CHOICES = { LEFT_INTEGER,
417: CENTER_INTEGER, RIGHT_INTEGER };
418:
419: // An object based enumeration (using an enum from the JGoodies Forms)
420: public static final Object LEFT = ColumnSpec.LEFT;
421: public static final Object CENTER = ColumnSpec.CENTER;
422: public static final Object RIGHT = ColumnSpec.RIGHT;
423: static final Object[] OBJECT_CHOICES = { LEFT, CENTER, RIGHT };
424:
425: private static final int NO_DATE = -1;
426:
427: // Fields *****************************************************************
428:
429: private boolean booleanValue;
430: private Color color;
431: private long date;
432: private float floatValue;
433: private int intChoice;
434: private int intLimited; // for a spinner
435: private int intValue;
436: private long longValue;
437: private Object objectChoice;
438: private String text;
439: private final ObservableList<Album> listModel;
440: private Album listSelection;
441:
442: // Instance Creation ******************************************************
443:
444: public ExampleBean() {
445: booleanValue = true;
446: color = Color.WHITE;
447: date = new GregorianCalendar(1967, 11, 5).getTime()
448: .getTime();
449: floatValue = 0.5f;
450: intChoice = LEFT_INTEGER.intValue();
451: intLimited = 15;
452: intValue = 42;
453: longValue = 42L;
454: objectChoice = LEFT;
455: text = "Text";
456: listModel = new ArrayListModel<Album>();
457: listModel.addAll(Album.ALBUMS);
458: listSelection = listModel.get(0);
459: }
460:
461: // Accessors **************************************************************
462:
463: public boolean getBooleanValue() {
464: return booleanValue;
465: }
466:
467: public void setBooleanValue(boolean newBooleanValue) {
468: boolean oldBooleanValue = getBooleanValue();
469: booleanValue = newBooleanValue;
470: firePropertyChange(PROPERTYNAME_BOOLEAN_VALUE,
471: oldBooleanValue, newBooleanValue);
472: }
473:
474: public Color getColor() {
475: return color;
476: }
477:
478: public void setColor(Color newColor) {
479: Color oldColor = getColor();
480: color = newColor;
481: firePropertyChange(PROPERTYNAME_COLOR, oldColor, newColor);
482: }
483:
484: public Date getDate() {
485: return date == NO_DATE ? null : new Date(date);
486: }
487:
488: public void setDate(Date newDate) {
489: Date oldDate = getDate();
490: date = newDate == null ? NO_DATE : newDate.getTime();
491: firePropertyChange(PROPERTYNAME_DATE, oldDate, newDate);
492: }
493:
494: public float getFloatValue() {
495: return floatValue;
496: }
497:
498: public void setFloatValue(float newFloatValue) {
499: float oldFloatValue = getFloatValue();
500: floatValue = newFloatValue;
501: firePropertyChange(PROPERTYNAME_FLOAT_VALUE, oldFloatValue,
502: newFloatValue);
503: }
504:
505: public int getIntChoice() {
506: return intChoice;
507: }
508:
509: public void setIntChoice(int newIntChoice) {
510: int oldIntChoice = getIntChoice();
511: intChoice = newIntChoice;
512: firePropertyChange(PROPERTYNAME_INT_CHOICE, oldIntChoice,
513: newIntChoice);
514: }
515:
516: public int getIntLimited() {
517: return intLimited;
518: }
519:
520: public void setIntLimited(int newIntLimited) {
521: int oldIntLimited = getIntLimited();
522: intLimited = newIntLimited;
523: firePropertyChange(PROPERTYNAME_INT_LIMITED, oldIntLimited,
524: newIntLimited);
525: }
526:
527: public int getIntValue() {
528: return intValue;
529: }
530:
531: public void setIntValue(int newIntValue) {
532: int oldIntValue = getIntValue();
533: intValue = newIntValue;
534: firePropertyChange(PROPERTYNAME_INT_VALUE, oldIntValue,
535: newIntValue);
536: }
537:
538: public long getLongValue() {
539: return longValue;
540: }
541:
542: public void setLongValue(long newLongValue) {
543: long oldLongValue = getLongValue();
544: longValue = newLongValue;
545: firePropertyChange(PROPERTYNAME_LONG_VALUE, oldLongValue,
546: newLongValue);
547: }
548:
549: public Object getObjectChoice() {
550: return objectChoice;
551: }
552:
553: public void setObjectChoice(Object newObjectChoice) {
554: Object oldObjectChoice = getObjectChoice();
555: objectChoice = newObjectChoice;
556: firePropertyChange(PROPERTYNAME_OBJECT_CHOICE,
557: oldObjectChoice, newObjectChoice);
558: }
559:
560: public String getText() {
561: return text;
562: }
563:
564: public void setText(String newText) {
565: String oldText = getText();
566: text = newText;
567: firePropertyChange(PROPERTYNAME_TEXT, oldText, newText);
568: }
569:
570: public ListModel getListModel() {
571: return listModel;
572: }
573:
574: public Album getListSelection() {
575: return listSelection;
576: }
577:
578: public void setListSelection(Album newListSelection) {
579: Object oldListSelection = getListSelection();
580: listSelection = newListSelection;
581: firePropertyChange(PROPERTYNAME_LIST_SELECTION,
582: oldListSelection, newListSelection);
583: }
584:
585: }
586:
587: /**
588: * A custom PresentationModel that provides a SelectionInList
589: * for the bean's ListModel and the bean's list selection.
590: */
591: private static final class ExamplePresentationModel<B> extends
592: PresentationModel<B> {
593:
594: /**
595: * Holds the bean's list model plus a selection.
596: */
597: private final SelectionInList<Album> selectionInList;
598:
599: // Instance Creation -----------------------------------------
600:
601: private ExamplePresentationModel(ExampleBean exampleBean) {
602: super (exampleBean);
603: selectionInList = new SelectionInList<Album>(exampleBean
604: .getListModel(),
605: getModel(ExampleBean.PROPERTYNAME_LIST_SELECTION));
606: }
607:
608: // Custom Models ---------------------------------------------
609:
610: public SelectionInList<Album> getSelectionInList() {
611: return selectionInList;
612: }
613:
614: }
615:
616: private final class ColorUpdateHandler implements
617: PropertyChangeListener {
618: public void propertyChange(PropertyChangeEvent evt) {
619: updatePreviewPanel();
620: }
621: }
622:
623: private static final class ChooseColorAction extends AbstractAction {
624:
625: private final Component parent;
626: private final ValueModel bufferedColorModel;
627: private final Trigger trigger;
628:
629: private ChooseColorAction(Component parent,
630: ValueModel colorModel) {
631: super ("\u2026");
632: this .parent = parent;
633: this .trigger = new Trigger();
634: this .bufferedColorModel = new BufferedValueModel(
635: colorModel, trigger);
636: }
637:
638: public void actionPerformed(ActionEvent e) {
639: JColorChooser colorChooser = BasicComponentFactory
640: .createColorChooser(bufferedColorModel);
641: ActionListener okHandler = new OKHandler(trigger);
642: JDialog dialog = JColorChooser
643: .createDialog(parent, "Choose Color", true,
644: colorChooser, okHandler, null);
645: dialog.addWindowListener(new Closer());
646: dialog.addComponentListener(new DisposeOnClose());
647:
648: dialog.setVisible(true); // blocks until user brings dialog down...
649: }
650:
651: private static final class Closer extends WindowAdapter
652: implements Serializable {
653: @Override
654: public void windowClosing(WindowEvent e) {
655: Window w = e.getWindow();
656: w.setVisible(false);
657: }
658: }
659:
660: private static final class DisposeOnClose extends
661: ComponentAdapter implements Serializable {
662: @Override
663: public void componentHidden(ComponentEvent e) {
664: Window w = (Window) e.getComponent();
665: w.dispose();
666: }
667: }
668:
669: private static final class OKHandler implements ActionListener {
670: private final Trigger trigger;
671:
672: private OKHandler(Trigger trigger) {
673: this .trigger = trigger;
674: }
675:
676: public void actionPerformed(ActionEvent e) {
677: trigger.triggerCommit();
678: }
679: }
680:
681: }
682:
683: }
|