com.jgoodies.binding.value.Trigger Maven / Gradle / Ivy
Show all versions of jgoodies-binding Show documentation
/*
* Copyright (c) 2002-2015 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.value;
import static com.jgoodies.common.base.Preconditions.checkArgument;
/**
* A ValueModel implementation that is intended to be used as trigger channel
* for instances of BufferedValueModel. API users shall trigger commit and flush
* events using {@code #triggerCommit} and {@code #triggerFlush}.
*
* This Trigger class works around an inconvenient situation when using
* a general ValueHolder as trigger channel of a BufferedValueModel.
* BufferedValueHolder performs commit and flush events only if the trigger
* channel value reports a change. And a ValueHolder doesn't report a change
* if {@code #setValue} tries to set the current value. For example
* if you set {@code Boolean.TRUE} twice, the latter doesn't fire
* a property change event. The methods {@code #triggerCommit} and
* {@code #triggerFlush} check for the current state and guarantee
* that the appropriate {@code PropertyChangeEvent} is fired.
* On the other hand, the implementation minimizes the number of events
* necessary to commit or flush buffered values.
*
* Constraints: The value is of type {@code Boolean}.
*
* The following example delays the commit of a buffered value:
*
* ValueModel subject = new ValueHolder();
* Trigger trigger = new Trigger();
* BufferedValueModel buffer = new BufferedValueModel(subject, trigger);
*
* buffer.setValue("value");
* ...
* trigger.triggerCommit();
*
*
* @author Karsten Lentzsch
* @version $Revision: 1.10 $
*
* @see BufferedValueModel
*/
public final class Trigger extends AbstractValueModel {
private static final Boolean COMMIT = Boolean.TRUE;
private static final Boolean FLUSH = Boolean.FALSE;
private static final Boolean NEUTRAL = null;
/**
* Holds the current trigger state.
*/
private Boolean value;
// Instance Creation ******************************************************
/**
* Constructs a Trigger set to neutral.
*/
public Trigger() {
value = NEUTRAL;
}
// ValueModel Implementation **********************************************
/**
* Returns a Boolean that indicates the current trigger state.
*
* @return a Boolean that indicates the current trigger state
*/
@Override
public Object getValue() {
return value;
}
/**
* Sets a new Boolean value and rejects all non-Boolean values.
* Fires no change event if the new value is equal to the
* previously set value.
*
* This method is not intended to be used by API users.
* Instead you should trigger commit and flush events by invoking
* {@code #triggerCommit} or {@code #triggerFlush}.
*
* @param newValue the Boolean value to be set
* @throws IllegalArgumentException if the newValue is not a Boolean
*/
@Override
public void setValue(Object newValue) {
checkArgument(newValue == null || newValue instanceof Boolean,
"Trigger values must be of type Boolean.");
Object oldValue = value;
value = (Boolean) newValue;
fireValueChange(oldValue, newValue);
}
// Triggering *************************************************************
/**
* Triggers a commit event in BufferedValueModels that share this Trigger.
* Sets the value to {@code Boolean.TRUE} and ensures that listeners
* are notified about a value change to this new value. If necessary
* the value is temporarily set to {@code null}. This way it minimizes
* the number of PropertyChangeEvents fired by this Trigger.
*/
public void triggerCommit() {
if (COMMIT.equals(getValue())) {
setValue(NEUTRAL);
}
setValue(COMMIT);
}
/**
* Triggers a flush event in BufferedValueModels that share this Trigger.
* Sets the value to {@code Boolean.FALSE} and ensures that listeners
* are notified about a value change to the new value. If necessary
* the value is temporarily set to {@code null}. This way it minimizes
* the number of PropertyChangeEvents fired by this Trigger.
*/
public void triggerFlush() {
if (FLUSH.equals(getValue())) {
setValue(NEUTRAL);
}
setValue(FLUSH);
}
}