/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.uitools.app.swing;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JToggleButton.ToggleButtonModel;
import javax.swing.event.ChangeListener;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ValueModel;
import org.eclipse.persistence.tools.workbench.utility.string.StringTools;
/**
* This javax.swing.ButtonModel can be used to keep a listener
* (e.g. a JCheckBox or a JRadioButton) in synch with a PropertyValueModel
* on a boolean.
*/
public class ToggleButtonModelAdapter extends ToggleButtonModel {
/**
* The default setting for the toggle button; for when the underlying model is null.
* The default [default value] is false (i.e. the toggle button is unchecked/empty).
*/
protected boolean defaultValue;
/** A value model on the underlying model boolean. */
protected PropertyValueModel booleanHolder;
/**
* A listener that allows us to synchronize with
* changes made to the underlying model boolean.
*/
protected PropertyChangeListener booleanChangeListener;
// ********** constructors **********
/**
* Default constructor - initialize stuff.
*/
private ToggleButtonModelAdapter() {
super();
this.initialize();
}
/**
* Constructor - the boolean holder is required.
*/
public ToggleButtonModelAdapter(PropertyValueModel booleanHolder, boolean defaultValue) {
this();
if (booleanHolder == null) {
throw new NullPointerException();
}
this.booleanHolder = booleanHolder;
// postpone listening to the underlying model
// until we have listeners ourselves...
this.defaultValue = defaultValue;
}
/**
* Constructor - the boolean holder is required.
* The default value will be false.
*/
public ToggleButtonModelAdapter(PropertyValueModel booleanHolder) {
this(booleanHolder, false);
}
// ********** initialization **********
protected void initialize() {
this.booleanChangeListener = this.buildBooleanChangeListener();
}
protected PropertyChangeListener buildBooleanChangeListener() {
return new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
ToggleButtonModelAdapter.this.booleanChanged(e);
}
public String toString() {
return "boolean listener";
}
};
}
// ********** ButtonModel implementation **********
/**
* Extend to update the underlying model if necessary.
* @see javax.swing.ButtonModel#setSelected(boolean)
*/
public void setSelected(boolean b) {
if (this.isSelected() != b) { // stop the recursion!
super.setSelected(b);//put the super call first, otherwise the following gets called twice
this.booleanHolder.setValue(Boolean.valueOf(b));
}
}
/**
* Extend to start listening to the underlying model if necessary.
* @see javax.swing.ButtonModel#addActionListener(java.awt.event.ActionListener)
*/
public void addActionListener(ActionListener l) {
if (this.hasNoListeners()) {
this.engageModel();
}
super.addActionListener(l);
}
/**
* Extend to stop listening to the underlying model if appropriate.
* @see javax.swing.ButtonModel#removeActionListener(java.awt.event.ActionListener)
*/
public void removeActionListener(ActionListener l) {
super.removeActionListener(l);
if (this.hasNoListeners()) {
this.disengageModel();
}
}
/**
* Extend to start listening to the underlying model if necessary.
* @see java.awt.ItemSelectable#addItemListener(java.awt.event.ItemListener)
*/
public void addItemListener(ItemListener l) {
if (this.hasNoListeners()) {
this.engageModel();
}
super.addItemListener(l);
}
/**
* Extend to stop listening to the underlying model if appropriate.
* @see java.awt.ItemSelectable#removeItemListener(java.awt.event.ItemListener)
*/
public void removeItemListener(ItemListener l) {
super.removeItemListener(l);
if (this.hasNoListeners()) {
this.disengageModel();
}
}
/**
* Extend to start listening to the underlying model if necessary.
* @see javax.swing.ButtonModel#addChangeListener(javax.swing.event.ChangeListener)
*/
public void addChangeListener(ChangeListener l) {
if (this.hasNoListeners()) {
this.engageModel();
}
super.addChangeListener(l);
}
/**
* Extend to stop listening to the underlying model if appropriate.
* @see javax.swing.ButtonModel#removeChangeListener(javax.swing.event.ChangeListener)
*/
public void removeChangeListener(ChangeListener l) {
super.removeChangeListener(l);
if (this.hasNoListeners()) {
this.disengageModel();
}
}
// ********** queries **********
/**
* Return whether we have no listeners at all.
*/
protected boolean hasNoListeners() {
return this.listenerList.getListenerCount() == 0;
}
protected boolean getDefaultValue() {
return this.defaultValue;
}
// ********** behavior **********
/**
* Synchronize with the specified value.
* If it is null, use the default value (which is typically false).
*/
protected void setSelected(Boolean value) {
if (value == null) {
this.setSelected(this.getDefaultValue());
} else {
this.setSelected(value.booleanValue());
}
}
/**
* The underlying model has changed - synchronize accordingly.
*/
protected void booleanChanged(PropertyChangeEvent e) {
this.setSelected((Boolean) e.getNewValue());
}
protected void engageModel() {
this.booleanHolder.addPropertyChangeListener(ValueModel.VALUE, this.booleanChangeListener);
this.setSelected((Boolean) this.booleanHolder.getValue());
}
protected void disengageModel() {
this.booleanHolder.removePropertyChangeListener(ValueModel.VALUE, this.booleanChangeListener);
}
// ********** standard methods **********
public String toString() {
return StringTools.buildToStringFor(this, this.booleanHolder);
}
}