blob: d62fea973ce1ad61ef5319160ddadc1d5ea8871c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2009 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.ui.internal.utility.swt;
import org.eclipse.jpt.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
/**
* This binding can be used to keep a check-box, toggle button, or radio button
* "selection" synchronized with a model boolean.
*
* @see WritablePropertyValueModel
* @see Button
*/
@SuppressWarnings("nls")
final class BooleanButtonModelBinding {
// ***** model
/** A value model on the underlying model boolean. */
private final WritablePropertyValueModel<Boolean> booleanHolder;
/**
* A listener that allows us to synchronize the button's selection state with
* the model boolean.
*/
private final PropertyChangeListener booleanChangeListener;
/**
* The default setting for the check-box/toggle button/radio button;
* for when the underlying model is <code>null</code>.
* The default [default value] is <code>false</code> (i.e. the check-box
* is unchecked/toggle button popped out/radio button unchecked).
*/
private final boolean defaultValue;
// ***** UI
/** The check-box/toggle button/radio button we synchronize with the model boolean. */
private final Button button;
/**
* A listener that allows us to synchronize the model boolean with
* the button's selection state.
*/
private final SelectionListener buttonSelectionListener;
/**
* A listener that allows us to stop listening to stuff when the button
* is disposed. (Critical for preventing memory leaks.)
*/
private final DisposeListener buttonDisposeListener;
// ********** constructor **********
/**
* Constructor - the boolean holder and button are required.
*/
BooleanButtonModelBinding(WritablePropertyValueModel<Boolean> booleanHolder, Button button, boolean defaultValue) {
super();
if ((booleanHolder == null) || (button == null)) {
throw new NullPointerException();
}
this.booleanHolder = booleanHolder;
this.button = button;
this.defaultValue = defaultValue;
this.booleanChangeListener = this.buildBooleanChangeListener();
this.booleanHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.booleanChangeListener);
this.buttonSelectionListener = this.buildButtonSelectionListener();
this.button.addSelectionListener(this.buttonSelectionListener);
this.buttonDisposeListener = this.buildButtonDisposeListener();
this.button.addDisposeListener(this.buttonDisposeListener);
this.setButtonSelection(this.booleanHolder.getValue());
}
// ********** initialization **********
private PropertyChangeListener buildBooleanChangeListener() {
return new SWTPropertyChangeListenerWrapper(this.buildBooleanChangeListener_());
}
private PropertyChangeListener buildBooleanChangeListener_() {
return new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent event) {
BooleanButtonModelBinding.this.booleanChanged(event);
}
@Override
public String toString() {
return "boolean listener";
}
};
}
private SelectionListener buildButtonSelectionListener() {
return new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
BooleanButtonModelBinding.this.buttonSelected(event);
}
@Override
public String toString() {
return "button selection listener";
}
};
}
private DisposeListener buildButtonDisposeListener() {
return new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
BooleanButtonModelBinding.this.buttonDisposed(event);
}
@Override
public String toString() {
return "button dispose listener";
}
};
}
// ********** behavior **********
/**
* The model has changed - synchronize the button.
* If the new model value is null, use the binding's default value
* (which is typically false).
*/
void booleanChanged(PropertyChangeEvent event) {
this.setButtonSelection((Boolean) event.getNewValue());
}
private void setButtonSelection(Boolean b) {
if ( ! this.button.isDisposed()) {
this.button.setSelection(this.booleanValue(b));
}
}
private boolean booleanValue(Boolean b) {
return (b != null) ? b.booleanValue() : this.getDefaultValue();
}
private boolean getDefaultValue() {
return this.defaultValue;
}
/**
* The button has been "selected" - synchronize the model.
*/
void buttonSelected(@SuppressWarnings("unused") SelectionEvent event) {
if ( ! this.button.isDisposed()) {
this.booleanHolder.setValue(Boolean.valueOf(this.button.getSelection()));
}
}
// ********** dispose **********
void buttonDisposed(@SuppressWarnings("unused") DisposeEvent event) {
// the button is not yet "disposed" when we receive this event
// so we can still remove our listeners
this.button.removeSelectionListener(this.buttonSelectionListener);
this.button.removeDisposeListener(this.buttonDisposeListener);
this.booleanHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.booleanChangeListener);
}
// ********** standard methods **********
@Override
public String toString() {
return StringTools.buildToStringFor(this, this.booleanHolder);
}
}