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;
032:
033: import java.beans.PropertyChangeEvent;
034: import java.beans.PropertyChangeListener;
035:
036: import com.jgoodies.binding.PresentationModel;
037: import com.jgoodies.binding.value.ValueHolder;
038:
039: /**
040: * In addition to its superclass this class provides a bound
041: * read-only property <em>composerEnabled</em> that is true
042: * if and only if the underlying Album is non-<code>null</code> and classical.
043: * This property is intended to be used by a variety of presentation properties,
044: * not just a component's <em>enabled</em> state. You can enable or disable
045: * a composer presentation, or switch a composer field's <em>editable</em>
046: * property, or to hide and show a larger composer editor section.<p>
047: *
048: * I've added the <em>composerEnabled</em> property primarily for learning
049: * and demonstration purposes. And I wanted to closely follow the example
050: * used in Martin Fowler's description of the
051: * <a href="http://martinfowler.com/eaaDev/PresentationModel.html">Presentation
052: * Model</a> pattern. This example shows how "raw" domain object properties
053: * can be aggregated or filtered by the presentation model layer for use in
054: * the presentation layer. In cases where there's a direct mapping between
055: * a raw property and the aggregated property used in the UI, it may be easier
056: * to observe the raw property. But if this mapping becomes more complex
057: * an aggregated property is recommended.<p>
058: *
059: * Note that a UI that buffers the classical property cannot use
060: * <em>composerEnabled</em> but requires a separate aggregated property,
061: * for example <em>bufferedComposerEnabled</em>. To keep this code close
062: * to Fowler's original, I've implemented this feature in a subclass, see
063: * {@link com.jgoodies.binding.tutorial.manager.BufferedAlbumPresentationModel}.
064: * The buffered composer enabled property is an example where the eager
065: * property aggregation adds overhead and complexity, and it may turn out
066: * that using the buffered classical property would be easier to understand.
067: *
068: * @author Karsten Lentzsch
069: * @version $Revision: 1.11 $
070: *
071: * @see com.jgoodies.binding.tutorial.manager.BufferedAlbumPresentationModel
072: */
073: public class AlbumPresentationModel extends PresentationModel<Album> {
074:
075: /**
076: * The name of the bound read-only property that indicates that
077: * a presentation for the composer property should be enabled/disabled,
078: * editable/not editable, or visible/hidden.
079: *
080: * @see #isComposerEnabled()
081: */
082: public static final String PROPERTYNAME_COMPOSER_ENABLED = "composerEnabled";
083:
084: // Instance Creation ******************************************************
085:
086: /**
087: * Constructs an AlbumPresentationModel for the given Album.
088: *
089: * @param album the initial Album to adapt and work with
090: */
091: public AlbumPresentationModel(Album album) {
092: super (new ValueHolder(album, true));
093: initEventHandling();
094: }
095:
096: // Initialization *********************************************************
097:
098: /**
099: * Registers a listener that is notified about changes in the
100: * classical property of the current Album or a new Album.
101: */
102: private void initEventHandling() {
103: getModel(Album.PROPERTYNAME_CLASSICAL).addValueChangeListener(
104: new ClassicalChangeHandler());
105: }
106:
107: // Accessing Aggregated Properties ****************************************
108:
109: /**
110: * Checks and answers if the underlying Album is non-<code>null</code>
111: * and classical. This property is intended to be used with a variety
112: * of presentation styles that indicate that a composer is absent
113: * and cannot be edited. For example a presentations may choose
114: * to switch the view's enablement or the editable state, or it
115: * may hide or show a field or editor section.
116: *
117: * @return true if this model's current Album is non-<code>null</code>
118: * and classical.
119: */
120: public boolean isComposerEnabled() {
121: return Boolean.TRUE.equals(getModel(
122: Album.PROPERTYNAME_CLASSICAL).getValue());
123: }
124:
125: // Event Handling *********************************************************
126:
127: /**
128: * Handles changes in the <em>classical</em> property.
129: * Just notifies listeners about a change in the aggregated property
130: * <em>composerEnabled</em>.
131: */
132: private final class ClassicalChangeHandler implements
133: PropertyChangeListener {
134:
135: /**
136: * The Album's classical property has changed. Notifies listeners
137: * about a change in the "composerEnabled" property. Fires an event
138: * that uses <code>null</code> as old value, and the current value
139: * of this model's "composerEnabled" property as new value.
140: *
141: * @param evt the event that describes the classical change
142: */
143: public void propertyChange(PropertyChangeEvent evt) {
144: firePropertyChange(PROPERTYNAME_COMPOSER_ENABLED, null,
145: Boolean.valueOf(isComposerEnabled()));
146: }
147: }
148:
149: }
|