All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jgoodies.binding.util.ChangeTracker Maven / Gradle / Ivy

Go to download

The JGoodies Binding library connects object properties to Swing user interface components. And it helps you represent the state and behavior of a presentation independently of the GUI components used in the interface.

There is a newer version: 2.13.0
Show newest version
/*
 * Copyright (c) 2002-2013 JGoodies Software GmbH. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  o Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  o Neither the name of JGoodies Software GmbH nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jgoodies.binding.util;

import static com.jgoodies.common.base.Preconditions.checkNotNull;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import com.jgoodies.binding.beans.BeanUtils;
import com.jgoodies.binding.beans.Model;
import com.jgoodies.binding.beans.PropertyNotBindableException;
import com.jgoodies.binding.value.ValueModel;


/**
 * Tracks changes in a set of bound bean properties. The tracker itself
 * provides a read-only bound bean property changed that indicates
 * whether one of the observed properties has changed. The changed state
 * can be reset to {@code false} using {@code #reset}.

* * The tracker can observe readable bound bean properties if and only if * the bean provides the optional support for listening on named properties * as described in section 7.4.5 of the * Java Bean * Specification. The bean class must provide the following pair of methods: *

 * public void addPropertyChangeListener(String name, PropertyChangeListener l);
 * public void removePropertyChangeListener(String name, PropertyChangeListener l);
 * 

* * Example:

 * ChangeTracker tracker = new ChangeTracker();
 * tracker.observe(address, "street");
 * tracker.observe(address, "city");
 * tracker.addPropertyChangeListener(new PropertyChangeListener() {
 *
 *     public void propertyChange(PropertyChangeEvent evt) {
 *         System.out.println("Change state: " + evt.getNewValue());
 *     }
 * });
 *
 * // Change the first ValueModel
 * System.out.println(tracker.isChanged()); // Prints "false"
 * address.setStreet("Belsenplatz");        // Prints "Change state: true"
 * System.out.println(tracker.isChanged()); // Prints "true"
 * tracker.reset();                         // Prints "Change state: false"
 * System.out.println(tracker.isChanged()); // Prints "false"
 * 

* * Note: The classes {@code BeanAdapter} and * {@code PresentationModel} already provide support for tracking changes. * Typical binding code can use these classes and there seems to be no need * to use the ChangeTracker. * * @author Karsten Lentzsch * @version $Revision: 1.8 $ * * @see ValueModel */ public final class ChangeTracker extends Model { // Property Names ********************************************************* /** * The name of the read-only bound bean property that * indicates whether one of the observed properties has changed. * * @see #isChanged() */ public static final String PROPERTY_CHANGED = "changed"; // Instance Fields ******************************************************** /** * Listens to property changes and updates the changed property. */ private final PropertyChangeListener updateHandler; /** * Indicates whether a registered model has changed. */ private boolean changed = false; // Instance Creation ***************************************************** /** * Constructs a change tracker with change state set to {@code false}. */ public ChangeTracker() { updateHandler = new UpdateHandler(); } // Accessing the Changed State ******************************************** /** * Answers whether one of the registered ValueModels has changed * since this tracker has been reset last time. * * @return true if an observed property has changed since the last reset */ public boolean isChanged() { return changed; } /** * Resets this tracker's changed state to {@code false}. */ public void reset() { setChanged(false); } private void setChanged(boolean newValue) { boolean oldValue = isChanged(); changed = newValue; firePropertyChange(PROPERTY_CHANGED, oldValue, newValue); } // Registering ************************************************************* /** * Observes the specified readable bound bean property in the given bean. * * @param bean the bean to be observed * @param propertyName the name of the readable bound bean property * @throws NullPointerException if the bean or propertyName is null * @throws PropertyNotBindableException if this tracker can't add * the PropertyChangeListener from the bean * * @see #retractInterestFor(Object, String) */ public void observe(Object bean, String propertyName) { checkNotNull(bean, "The bean must not be null."); checkNotNull(propertyName, "The property name must not be null."); BeanUtils.addPropertyChangeListener(bean, propertyName, updateHandler); } /** * Observes value changes in the given ValueModel. * * @param valueModel the ValueModel to observe * @throws NullPointerException if the valueModel is null * * @see #retractInterestFor(ValueModel) */ public void observe(ValueModel valueModel) { checkNotNull(valueModel, "The ValueModel must not be null."); valueModel.addValueChangeListener(updateHandler); } /** * Retracts interest for the specified readable bound bean property * in the given bean. * * @param bean the bean to be observed * @param propertyName the name of the readable bound bean property * @throws NullPointerException if the bean or propertyName is null * @throws PropertyNotBindableException if this tracker can't remove * the PropertyChangeListener from the bean * * @see #observe(Object, String) */ public void retractInterestFor(Object bean, String propertyName) { checkNotNull(bean, "The bean must not be null."); checkNotNull(propertyName, "The property name must not be null."); BeanUtils.removePropertyChangeListener(bean, propertyName, updateHandler); } /** * Retracts interest for value changes in the given ValueModel. * * @param valueModel the ValueModel to observe * @throws NullPointerException if the valueModel is null * * @see #retractInterestFor(ValueModel) */ public void retractInterestFor(ValueModel valueModel) { checkNotNull(valueModel, "The ValueModel must not be null."); valueModel.removeValueChangeListener(updateHandler); } // Private Helper Code **************************************************** /** * Listens to model changes and updates the changed state. */ private final class UpdateHandler implements PropertyChangeListener { /** * A registered ValueModel has changed. * Updates the changed state. If the property that changed is * 'changed' we assume that this is another changed state and * forward only changes to true. For all other property names, * we just update our changed state to true. * * @param evt the event that describes the property change */ @Override public void propertyChange(PropertyChangeEvent evt) { String propertyName = evt.getPropertyName(); if (!PROPERTY_CHANGED.equals(propertyName) || ((Boolean) evt.getNewValue()).booleanValue()) { setChanged(true); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy