diff options
Diffstat (limited to 'common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing')
16 files changed, 0 insertions, 4336 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/AbstractTreeModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/AbstractTreeModel.java deleted file mode 100644 index 0a3ab42d06..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/AbstractTreeModel.java +++ /dev/null @@ -1,216 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2008 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.common.utility.internal.model.value.swing; - -import java.io.Serializable; -import javax.swing.event.EventListenerList; -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; -import javax.swing.tree.TreeModel; - -/** - * Abstract class that should have been provided by the JDK - * (à la javax.swing.AbstractListModel). This class provides: - * - support for a collection of listeners - * - a number of convenience methods for firing events for those listeners - */ -public abstract class AbstractTreeModel - implements TreeModel, Serializable -{ - /** Our listeners. */ - protected final EventListenerList listenerList; - - - // ********** constructors/initialization ********** - - protected AbstractTreeModel() { - super(); - this.listenerList = new EventListenerList(); - } - - - // ********** partial TreeModel implementation ********** - - public void addTreeModelListener(TreeModelListener l) { - this.listenerList.add(TreeModelListener.class, l); - } - - public void removeTreeModelListener(TreeModelListener l) { - this.listenerList.remove(TreeModelListener.class, l); - } - - - // ********** queries ********** - - /** - * Return the model's current collection of listeners. - * (There seems to be a pattern of making this type of method public; - * although it should probably be protected....) - */ - public TreeModelListener[] treeModelListeners() { - return this.listenerList.getListeners(TreeModelListener.class); - } - - /** - * Return whether this model has no listeners. - */ - protected boolean hasNoTreeModelListeners() { - return this.listenerList.getListenerCount(TreeModelListener.class) == 0; - } - - /** - * Return whether this model has any listeners. - */ - protected boolean hasTreeModelListeners() { - return ! this.hasNoTreeModelListeners(); - } - - - // ********** behavior ********** - - /** - * Notify listeners of a model change. - * A significant property of the nodes changed, but the nodes themselves - * are still the same objects. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeNodesChanged(Object[] path, int[] childIndices, Object[] children) { - // guaranteed to return a non-null array - Object[] listeners = this.listenerList.getListenerList(); - TreeModelEvent event = null; - // process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==TreeModelListener.class) { - // lazily create the event - if (event == null) { - event = new TreeModelEvent(this, path, childIndices, children); - } - ((TreeModelListener) listeners[i+1]).treeNodesChanged(event); - } - } - } - - - /** - * Notify listeners of a model change. - * A significant property of the node changed, but the node itself is the same object. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeNodeChanged(Object[] path, int childIndex, Object child) { - this.fireTreeNodesChanged(path, new int[] {childIndex}, new Object[] {child}); - } - - /** - * Notify listeners of a model change. - * A significant property of the root changed, but the root itself is the same object. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeRootChanged(Object root) { - this.fireTreeNodesChanged(new Object[] {root}, null, null); - } - - /** - * Notify listeners of a model change. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeNodesInserted(Object[] path, int[] childIndices, Object[] children) { - // guaranteed to return a non-null array - Object[] listeners = this.listenerList.getListenerList(); - TreeModelEvent event = null; - // process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==TreeModelListener.class) { - // lazily create the event - if (event == null) { - event = new TreeModelEvent(this, path, childIndices, children); - } - ((TreeModelListener) listeners[i+1]).treeNodesInserted(event); - } - } - } - - /** - * Notify listeners of a model change. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeNodeInserted(Object[] path, int childIndex, Object child) { - this.fireTreeNodesInserted(path, new int[] {childIndex}, new Object[] {child}); - } - - /** - * Notify listeners of a model change. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeNodesRemoved(Object[] path, int[] childIndices, Object[] children) { - // guaranteed to return a non-null array - Object[] listeners = this.listenerList.getListenerList(); - TreeModelEvent event = null; - // process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==TreeModelListener.class) { - // lazily create the event - if (event == null) { - event = new TreeModelEvent(this, path, childIndices, children); - } - ((TreeModelListener) listeners[i+1]).treeNodesRemoved(event); - } - } - } - - /** - * Notify listeners of a model change. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeNodeRemoved(Object[] path, int childIndex, Object child) { - this.fireTreeNodesRemoved(path, new int[] {childIndex}, new Object[] {child}); - } - - /** - * Notify listeners of a model change. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeStructureChanged(Object[] path) { - // guaranteed to return a non-null array - Object[] listeners = this.listenerList.getListenerList(); - TreeModelEvent event = null; - // process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==TreeModelListener.class) { - // lazily create the event - if (event == null) { - event = new TreeModelEvent(this, path); - } - ((TreeModelListener) listeners[i+1]).treeStructureChanged(event); - } - } - } - - /** - * Notify listeners of a model change. - * @see javax.swing.event.TreeModelEvent - * @see javax.swing.event.TreeModelListener - */ - protected void fireTreeRootReplaced(Object newRoot) { - this.fireTreeStructureChanged(new Object[] {newRoot}); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/CheckBoxModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/CheckBoxModelAdapter.java deleted file mode 100644 index 78069cd6b0..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/CheckBoxModelAdapter.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2008 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.common.utility.internal.model.value.swing; - -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.ButtonModel can be used to keep a listener - * (e.g. a JCheckBox) in synch with a PropertyValueModel that - * holds a boolean. - * - * Maybe not the richest class in our toolbox, but it was the - * victim of refactoring.... ~bjv - */ -public class CheckBoxModelAdapter - extends ToggleButtonModelAdapter -{ - - // ********** constructors ********** - - /** - * Constructor - the boolean holder is required. - */ - public CheckBoxModelAdapter(WritablePropertyValueModel<Boolean> booleanHolder, boolean defaultValue) { - super(booleanHolder, defaultValue); - } - - /** - * Constructor - the boolean holder is required. - * The default value will be false. - */ - public CheckBoxModelAdapter(WritablePropertyValueModel<Boolean> booleanHolder) { - super(booleanHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ColumnAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ColumnAdapter.java deleted file mode 100644 index e101823abc..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ColumnAdapter.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2008 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.common.utility.internal.model.value.swing; - -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - - -/** - * This adapter is used by the table model adapter to - * convert a model object into the models used for each of - * the cells for the object's corresponding row in the table. - */ -public interface ColumnAdapter { - /** - * Return the number of columns in the table. - * Typically this is static. - */ - int columnCount(); - - /** - * Return the name of the specified column. - */ - String columnName(int index); - - /** - * Return the class of the specified column. - */ - Class<?> columnClass(int index); - - /** - * Return whether the specified column is editable. - * Typically this is the same for every row. - */ - boolean columnIsEditable(int index); - - /** - * Return the cell models for the specified subject - * that corresponds to a single row in the table. - */ - WritablePropertyValueModel<Object>[] cellModels(Object subject); - -}
\ No newline at end of file diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ComboBoxModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ComboBoxModelAdapter.java deleted file mode 100644 index 7cb5f7d88e..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ComboBoxModelAdapter.java +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import javax.swing.ComboBoxModel; -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.CollectionValueModel; -import org.eclipse.jpt.common.utility.model.value.ListValueModel; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.ComboBoxModel can be used to keep a ListDataListener - * (e.g. a JComboBox) in synch with a ListValueModel (or a CollectionValueModel). - * For combo boxes, the model object that holds the current selection is - * typically a different model object than the one that holds the collection - * of choices. - * - * For example, a MWReference (the selectionOwner) has an attribute - * "sourceTable" (the collectionOwner) - * which holds on to a collection of MWDatabaseFields. When the selection - * is changed this model will keep the listeners aware of the changes. - * The inherited list model will keep its listeners aware of changes to the - * collection model - * - * In addition to the collection holder required by the superclass, - * an instance of this ComboBoxModel must be supplied with a - * selection holder, which is a PropertyValueModel that provides access - * to the selection (typically a PropertyAspectAdapter). - */ -public class ComboBoxModelAdapter - extends ListModelAdapter - implements ComboBoxModel -{ - protected final WritablePropertyValueModel<Object> selectionHolder; - protected final PropertyChangeListener selectionListener; - - - // ********** constructors ********** - - /** - * Constructor - the list holder and selection holder are required; - */ - public ComboBoxModelAdapter(ListValueModel<?> listHolder, WritablePropertyValueModel<Object> selectionHolder) { - super(listHolder); - if (selectionHolder == null) { - throw new NullPointerException(); - } - this.selectionHolder = selectionHolder; - this.selectionListener = this.buildSelectionListener(); - } - - /** - * Constructor - the collection holder and selection holder are required; - */ - public ComboBoxModelAdapter(CollectionValueModel<?> collectionHolder, WritablePropertyValueModel<Object> selectionHolder) { - super(collectionHolder); - if (selectionHolder == null) { - throw new NullPointerException(); - } - this.selectionHolder = selectionHolder; - this.selectionListener = this.buildSelectionListener(); - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildSelectionListener() { - return new AWTPropertyChangeListenerWrapper(this.buildSelectionListener_()); - } - - protected PropertyChangeListener buildSelectionListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - // notify listeners that the selection has changed - ComboBoxModelAdapter.this.fireSelectionChanged(); - } - @Override - public String toString() { - return "selection listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** ComboBoxModel implementation ********** - - public Object getSelectedItem() { - return this.selectionHolder.getValue(); - } - - public void setSelectedItem(Object selectedItem) { - this.selectionHolder.setValue(selectedItem); - } - - - // ********** behavior ********** - - /** - * Extend to engage the selection holder. - */ - @Override - protected void engageModel() { - super.engageModel(); - this.selectionHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.selectionListener); - } - - /** - * Extend to disengage the selection holder. - */ - @Override - protected void disengageModel() { - this.selectionHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.selectionListener); - super.disengageModel(); - } - - /** - * Notify the listeners that the selection has changed. - */ - protected void fireSelectionChanged() { - // I guess this will work... - this.fireContentsChanged(this, -1, -1); - } - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.selectionHolder + ":" + this.listHolder); //$NON-NLS-1$ - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/DateSpinnerModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/DateSpinnerModelAdapter.java deleted file mode 100644 index 61ef8cee8f..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/DateSpinnerModelAdapter.java +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import java.util.Calendar; -import java.util.Date; -import javax.swing.SpinnerDateModel; -import javax.swing.event.ChangeListener; -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.SpinnerDateModel can be used to keep a ChangeListener - * (e.g. a JSpinner) in synch with a PropertyValueModel that holds a date. - * - * This class must be a sub-class of SpinnerDateModel because of some - * crappy jdk code.... ~bjv - * @see javax.swing.JSpinner#createEditor(javax.swing.SpinnerModel) - * - * If this class needs to be modified, it would behoove us to review the - * other, similar classes: - * @see ListSpinnerModelAdapter - * @see NumberSpinnerModelAdapter - */ -public class DateSpinnerModelAdapter - extends SpinnerDateModel -{ - - /** - * The default spinner value; used when the underlying model date value is null. - * The default is the current date. - */ - private final Date defaultValue; - - /** A value model on the underlying date. */ - private final WritablePropertyValueModel<Object> dateHolder; - - /** A listener that allows us to synchronize with changes made to the underlying date. */ - private final PropertyChangeListener dateChangeListener; - - - // ********** constructors ********** - - /** - * Constructor - the date holder is required. - * The default spinner value is the current date. - */ - public DateSpinnerModelAdapter(WritablePropertyValueModel<Object> dateHolder) { - this(dateHolder, new Date()); - } - - /** - * Constructor - the date holder and default value are required. - */ - public DateSpinnerModelAdapter(WritablePropertyValueModel<Object> dateHolder, Date defaultValue) { - this(dateHolder, null, null, Calendar.DAY_OF_MONTH, defaultValue); - } - - /** - * Constructor - the date holder is required. - * The default spinner value is the current date. - */ - public DateSpinnerModelAdapter(WritablePropertyValueModel<Object> dateHolder, Comparable<?> start, Comparable<?> end, int calendarField) { - this(dateHolder, start, end, calendarField, new Date()); - } - - /** - * Constructor - the date holder is required. - */ - public DateSpinnerModelAdapter(WritablePropertyValueModel<Object> dateHolder, Comparable<?> start, Comparable<?> end, int calendarField, Date defaultValue) { - super(dateHolder.getValue() == null ? defaultValue : (Date) dateHolder.getValue(), start, end, calendarField); - this.dateHolder = dateHolder; - this.dateChangeListener = this.buildDateChangeListener(); - // postpone listening to the underlying date - // until we have listeners ourselves... - this.defaultValue = defaultValue; - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildDateChangeListener() { - return new AWTPropertyChangeListenerWrapper(this.buildDateChangeListener_()); - } - - protected PropertyChangeListener buildDateChangeListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - DateSpinnerModelAdapter.this.synchronize(event.getNewValue()); - } - @Override - public String toString() { - return "date listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** SpinnerModel implementation ********** - - /** - * Extend to check whether this method is being called before we - * have any listeners. - * This is necessary because some crappy jdk code gets the value - * from the model *before* listening to the model. ~bjv - * @see javax.swing.JSpinner.DefaultEditor(javax.swing.JSpinner) - */ - @Override - public Object getValue() { - if (this.getChangeListeners().length == 0) { - // sorry about this "lateral" call to super ~bjv - super.setValue(this.spinnerValueOf(this.dateHolder.getValue())); - } - return super.getValue(); - } - - /** - * Extend to update the underlying date directly. - * The resulting event will be ignored: @see #synchronize(Object). - */ - @Override - public void setValue(Object value) { - super.setValue(value); - this.dateHolder.setValue(value); - } - - /** - * Extend to start listening to the underlying date if necessary. - */ - @Override - public void addChangeListener(ChangeListener listener) { - if (this.getChangeListeners().length == 0) { - this.dateHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.dateChangeListener); - this.synchronize(this.dateHolder.getValue()); - } - super.addChangeListener(listener); - } - - /** - * Extend to stop listening to the underlying date if appropriate. - */ - @Override - public void removeChangeListener(ChangeListener listener) { - super.removeChangeListener(listener); - if (this.getChangeListeners().length == 0) { - this.dateHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.dateChangeListener); - } - } - - - // ********** queries ********** - - protected Date getDefaultValue() { - return this.defaultValue; - } - - /** - * Convert to a non-null value. - */ - protected Object spinnerValueOf(Object value) { - return (value == null) ? this.getDefaultValue() : value; - } - - - // ********** behavior ********** - - /** - * Set the spinner value if it has changed. - */ - void synchronize(Object value) { - Object newValue = this.spinnerValueOf(value); - // check to see whether the spinner date has already been synchronized - // (via #setValue()) - if ( ! this.getValue().equals(newValue)) { - this.setValue(newValue); - } - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.dateHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/DocumentAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/DocumentAdapter.java deleted file mode 100644 index 1f7f4043de..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/DocumentAdapter.java +++ /dev/null @@ -1,375 +0,0 @@ -/******************************************************************************* - * 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.common.utility.internal.model.value.swing; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.util.EventObject; - -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.EventListenerList; -import javax.swing.event.UndoableEditEvent; -import javax.swing.event.UndoableEditListener; -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.Element; -import javax.swing.text.PlainDocument; -import javax.swing.text.Position; -import javax.swing.text.Segment; - -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.text.Document can be used to keep a DocumentListener - * (e.g. a JTextField) in synch with a PropertyValueModel that holds a string. - * - * NB: This model should only be used for "small" documents; - * i.e. documents used by text fields, not text panes. - * @see #synchronizeDelegate(String) - */ -public class DocumentAdapter - implements Document, Serializable -{ - - /** The delegate document whose behavior we "enhance". */ - protected final Document delegate; - - /** A listener that allows us to forward any changes made to the delegate document. */ - protected final CombinedListener delegateListener; - - /** A value model on the underlying model string. */ - protected final WritablePropertyValueModel<String> stringHolder; - - /** A listener that allows us to synchronize with changes made to the underlying model string. */ - protected transient PropertyChangeListener stringListener; - - /** The event listener list for the document. */ - protected final EventListenerList listenerList = new EventListenerList(); - - private static final long serialVersionUID = 1L; - - - // ********** constructors ********** - - /** - * Constructor - the string holder is required. - * Wrap the specified document. - */ - public DocumentAdapter(WritablePropertyValueModel<String> stringHolder, Document delegate) { - super(); - if (stringHolder == null || delegate == null) { - throw new NullPointerException(); - } - this.stringHolder = stringHolder; - // postpone listening to the underlying model string - // until we have listeners ourselves... - this.delegate = delegate; - this.stringListener = this.buildStringListener(); - this.delegateListener = this.buildDelegateListener(); - } - - /** - * Constructor - the string holder is required. - * Wrap a plain document. - */ - public DocumentAdapter(WritablePropertyValueModel<String> stringHolder) { - this(stringHolder, new PlainDocument()); - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildStringListener() { - return new AWTPropertyChangeListenerWrapper(this.buildStringListener_()); - } - - protected PropertyChangeListener buildStringListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - DocumentAdapter.this.stringChanged(event); - } - @Override - public String toString() { - return "string listener"; //$NON-NLS-1$ - } - }; - } - - protected CombinedListener buildDelegateListener() { - return new InternalListener(); - } - - - // ********** Document implementation ********** - - public int getLength() { - return this.delegate.getLength(); - } - - /** - * Extend to start listening to the underlying models if necessary. - */ - public void addDocumentListener(DocumentListener listener) { - if (this.listenerList.getListenerCount(DocumentListener.class) == 0) { - this.delegate.addDocumentListener(this.delegateListener); - this.engageStringHolder(); - } - this.listenerList.add(DocumentListener.class, listener); - } - - /** - * Extend to stop listening to the underlying models if appropriate. - */ - public void removeDocumentListener(DocumentListener listener) { - this.listenerList.remove(DocumentListener.class, listener); - if (this.listenerList.getListenerCount(DocumentListener.class) == 0) { - this.disengageStringHolder(); - this.delegate.removeDocumentListener(this.delegateListener); - } - } - - /** - * Extend to start listening to the delegate document if necessary. - */ - public void addUndoableEditListener(UndoableEditListener listener) { - if (this.listenerList.getListenerCount(UndoableEditListener.class) == 0) { - this.delegate.addUndoableEditListener(this.delegateListener); - } - this.listenerList.add(UndoableEditListener.class, listener); - } - - /** - * Extend to stop listening to the delegate document if appropriate. - */ - public void removeUndoableEditListener(UndoableEditListener listener) { - this.listenerList.remove(UndoableEditListener.class, listener); - if (this.listenerList.getListenerCount(UndoableEditListener.class) == 0) { - this.delegate.removeUndoableEditListener(this.delegateListener); - } - } - - public Object getProperty(Object key) { - return this.delegate.getProperty(key); - } - - public void putProperty(Object key, Object value) { - this.delegate.putProperty(key, value); - } - - /** - * Extend to update the underlying model string directly. - * The resulting event will be ignored: @see #synchronizeDelegate(String). - */ - public void remove(int offset, int len) throws BadLocationException { - this.delegate.remove(offset, len); - this.stringHolder.setValue(this.delegate.getText(0, this.delegate.getLength())); - } - - /** - * Extend to update the underlying model string directly. - * The resulting event will be ignored: @see #synchronizeDelegate(String). - */ - public void insertString(int offset, String insertedString, AttributeSet a) throws BadLocationException { - this.delegate.insertString(offset, insertedString, a); - this.stringHolder.setValue(this.delegate.getText(0, this.delegate.getLength())); - } - - public String getText(int offset, int length) throws BadLocationException { - return this.delegate.getText(offset, length); - } - - public void getText(int offset, int length, Segment txt) throws BadLocationException { - this.delegate.getText(offset, length, txt); - } - - public Position getStartPosition() { - return this.delegate.getStartPosition(); - } - - public Position getEndPosition() { - return this.delegate.getEndPosition(); - } - - public Position createPosition(int offs) throws BadLocationException { - return this.delegate.createPosition(offs); - } - - public Element[] getRootElements() { - return this.delegate.getRootElements(); - } - - public Element getDefaultRootElement() { - return this.delegate.getDefaultRootElement(); - } - - public void render(Runnable r) { - this.delegate.render(r); - } - - - // ********** queries ********** - - public DocumentListener[] documentListeners() { - return this.listenerList.getListeners(DocumentListener.class); - } - - public UndoableEditListener[] undoableEditListeners() { - return this.listenerList.getListeners(UndoableEditListener.class); - } - - - // ********** behavior ********** - - /** - * A third party has modified the underlying model string. - * Synchronize the delegate document accordingly. - */ - protected void stringChanged(PropertyChangeEvent event) { - this.synchronizeDelegate((String) event.getNewValue()); - } - - /** - * Replace the document's entire text string with the new string. - */ - protected void synchronizeDelegate(String s) { - try { - int len = this.delegate.getLength(); - // check to see whether the delegate has already been synchronized - // (via #insertString() or #remove()) - if ( ! this.delegate.getText(0, len).equals(s)) { - this.delegate.remove(0, len); - this.delegate.insertString(0, s, null); - } - } catch (BadLocationException ex) { - throw new IllegalStateException(ex.getMessage()); // this should not happen... - } - } - - protected void engageStringHolder() { - this.stringHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.stringListener); - this.synchronizeDelegate(this.stringHolder.getValue()); - } - - protected void disengageStringHolder() { - this.stringHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.stringListener); - } - - protected void delegateChangedUpdate(DocumentEvent event) { - // no need to lazy-initialize the event; - // we wouldn't get here if we did not have listeners... - DocumentEvent ee = new InternalDocumentEvent(this, event); - DocumentListener[] listeners = this.documentListeners(); - for (int i = listeners.length; i-- > 0; ) { - listeners[i].changedUpdate(ee); - } - } - - protected void delegateInsertUpdate(DocumentEvent event) { - // no need to lazy-initialize the event; - // we wouldn't get here if we did not have listeners... - DocumentEvent ee = new InternalDocumentEvent(this, event); - DocumentListener[] listeners = this.documentListeners(); - for (int i = listeners.length; i-- > 0; ) { - listeners[i].insertUpdate(ee); - } - } - - protected void delegateRemoveUpdate(DocumentEvent event) { - // no need to lazy-initialize the event; - // we wouldn't get here if we did not have listeners... - DocumentEvent ee = new InternalDocumentEvent(this, event); - DocumentListener[] listeners = this.documentListeners(); - for (int i = listeners.length; i-- > 0; ) { - listeners[i].removeUpdate(ee); - } - } - - protected void delegateUndoableEditHappened(UndoableEditEvent event) { - // no need to lazy-initialize the event; - // we wouldn't get here if we did not have listeners... - UndoableEditEvent ee = new UndoableEditEvent(this, event.getEdit()); - UndoableEditListener[] listeners = this.undoableEditListeners(); - for (int i = listeners.length; i-- > 0; ) { - listeners[i].undoableEditHappened(ee); - } - } - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.stringHolder); - } - - private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { - // read in any hidden stuff - s.defaultReadObject(); - this.stringListener = this.buildStringListener(); - } - - -// ********** inner class ********** - - protected interface CombinedListener extends DocumentListener, UndoableEditListener, Serializable { - // just consolidate the two interfaces - } - - protected class InternalListener implements CombinedListener { - private static final long serialVersionUID = 1L; - public void changedUpdate(DocumentEvent event) { - DocumentAdapter.this.delegateChangedUpdate(event); - } - public void insertUpdate(DocumentEvent event) { - DocumentAdapter.this.delegateInsertUpdate(event); - } - public void removeUpdate(DocumentEvent event) { - DocumentAdapter.this.delegateRemoveUpdate(event); - } - public void undoableEditHappened(UndoableEditEvent event) { - DocumentAdapter.this.delegateUndoableEditHappened(event); - } - } - - protected static class InternalDocumentEvent - extends EventObject - implements DocumentEvent - { - protected DocumentEvent delegate; - - protected InternalDocumentEvent(Document document, DocumentEvent delegate) { - super(document); - this.delegate = delegate; - } - public ElementChange getChange(Element elem) { - return this.delegate.getChange(elem); - } - public Document getDocument() { - return (Document) this.source; - } - public int getLength() { - return this.delegate.getLength(); - } - public int getOffset() { - return this.delegate.getOffset(); - } - public EventType getType() { - return this.delegate.getType(); - } - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ListModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ListModelAdapter.java deleted file mode 100644 index 2d1c1e4b5d..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ListModelAdapter.java +++ /dev/null @@ -1,292 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import javax.swing.AbstractListModel; -import javax.swing.event.ListDataListener; - -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTListChangeListenerWrapper; -import org.eclipse.jpt.common.utility.internal.model.value.CollectionListValueModelAdapter; -import org.eclipse.jpt.common.utility.model.event.ListAddEvent; -import org.eclipse.jpt.common.utility.model.event.ListChangeEvent; -import org.eclipse.jpt.common.utility.model.event.ListClearEvent; -import org.eclipse.jpt.common.utility.model.event.ListMoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListRemoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListReplaceEvent; -import org.eclipse.jpt.common.utility.model.listener.ListChangeListener; -import org.eclipse.jpt.common.utility.model.value.CollectionValueModel; -import org.eclipse.jpt.common.utility.model.value.ListValueModel; - -/** - * This javax.swing.ListModel can be used to keep a ListDataListener - * (e.g. a JList) in synch with a ListValueModel (or a CollectionValueModel). - * - * An instance of this ListModel *must* be supplied with a value model, - * which is a ListValueModel on the bound list or a CollectionValueModel - * on the bound collection. This is required - the list (or collection) - * itself can be null, but the value model that holds it cannot. - */ -public class ListModelAdapter - extends AbstractListModel -{ - /** A value model on the underlying model list. */ - protected ListValueModel<?> listHolder; - - /** - * Cache the size of the list for "dramatic" changes. - * @see #listChanged(ListChangeEvent) - */ - protected int listSize; - - /** A listener that allows us to forward changes made to the underlying model list. */ - protected final ListChangeListener listChangeListener; - - - // ********** constructors ********** - - /** - * Default constructor - initialize stuff. - */ - private ListModelAdapter() { - super(); - this.listSize = 0; - this.listChangeListener = this.buildListChangeListener(); - } - - /** - * Constructor - the list holder is required. - */ - public ListModelAdapter(ListValueModel<?> listHolder) { - this(); - this.setModel(listHolder); - } - - /** - * Constructor - the collection holder is required. - */ - public ListModelAdapter(CollectionValueModel<?> collectionHolder) { - this(); - this.setModel(collectionHolder); - } - - - // ********** initialization ********** - - protected ListChangeListener buildListChangeListener() { - return new AWTListChangeListenerWrapper(this.buildListChangeListener_()); - } - - protected ListChangeListener buildListChangeListener_() { - return new ListChangeListener() { - public void itemsAdded(ListAddEvent event) { - ListModelAdapter.this.itemsAdded(event); - } - public void itemsRemoved(ListRemoveEvent event) { - ListModelAdapter.this.itemsRemoved(event); - } - public void itemsReplaced(ListReplaceEvent event) { - ListModelAdapter.this.itemsReplaced(event); - } - public void itemsMoved(ListMoveEvent event) { - ListModelAdapter.this.itemsMoved(event); - } - public void listCleared(ListClearEvent event) { - ListModelAdapter.this.listCleared(); - } - public void listChanged(ListChangeEvent event) { - ListModelAdapter.this.listChanged(); - } - @Override - public String toString() { - return "list listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** ListModel implementation ********** - - public int getSize() { - return this.listHolder.size(); - } - - public Object getElementAt(int index) { - return this.listHolder.get(index); - } - - /** - * Extend to start listening to the underlying model list if necessary. - */ - @Override - public void addListDataListener(ListDataListener l) { - if (this.hasNoListDataListeners()) { - this.engageModel(); - this.listSize = this.listHolder.size(); - } - super.addListDataListener(l); - } - - /** - * Extend to stop listening to the underlying model list if appropriate. - */ - @Override - public void removeListDataListener(ListDataListener l) { - super.removeListDataListener(l); - if (this.hasNoListDataListeners()) { - this.disengageModel(); - this.listSize = 0; - } - } - - - // ********** public API ********** - - /** - * Return the underlying list model. - */ - public ListValueModel<?> model() { - return this.listHolder; - } - - /** - * Set the underlying list model. - */ - public void setModel(ListValueModel<?> listHolder) { - if (listHolder == null) { - throw new NullPointerException(); - } - boolean hasListeners = this.hasListDataListeners(); - if (hasListeners) { - this.disengageModel(); - } - this.listHolder = listHolder; - if (hasListeners) { - this.engageModel(); - this.listChanged(); - } - } - - /** - * Set the underlying collection model. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void setModel(CollectionValueModel<?> collectionHolder) { - this.setModel(new CollectionListValueModelAdapter(collectionHolder)); - } - - - // ********** queries ********** - - /** - * Return whether this model has no listeners. - */ - protected boolean hasNoListDataListeners() { - return this.getListDataListeners().length == 0; - } - - /** - * Return whether this model has any listeners. - */ - protected boolean hasListDataListeners() { - return ! this.hasNoListDataListeners(); - } - - - // ********** behavior ********** - - protected void engageModel() { - this.listHolder.addListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener); - } - - protected void disengageModel() { - this.listHolder.removeListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener); - } - - - - // ********** list change support ********** - - /** - * Items were added to the underlying model list. - * Notify listeners of the changes. - */ - protected void itemsAdded(ListAddEvent event) { - int start = event.getIndex(); - int end = start + event.getItemsSize() - 1; - this.fireIntervalAdded(this, start, end); - this.listSize += event.getItemsSize(); - } - - /** - * Items were removed from the underlying model list. - * Notify listeners of the changes. - */ - protected void itemsRemoved(ListRemoveEvent event) { - int start = event.getIndex(); - int end = start + event.getItemsSize() - 1; - this.fireIntervalRemoved(this, start, end); - this.listSize -= event.getItemsSize(); - } - - /** - * Items were replaced in the underlying model list. - * Notify listeners of the changes. - */ - protected void itemsReplaced(ListReplaceEvent event) { - int start = event.getIndex(); - int end = start + event.getItemsSize() - 1; - this.fireContentsChanged(this, start, end); - } - - /** - * Items were moved in the underlying model list. - * Notify listeners of the changes. - */ - protected void itemsMoved(ListMoveEvent event) { - int start = Math.min(event.getSourceIndex(), event.getTargetIndex()); - int end = Math.max(event.getSourceIndex(), event.getTargetIndex()) + event.getLength() - 1; - this.fireContentsChanged(this, start, end); - } - - /** - * The underlying model list was cleared. - * Notify listeners of the changes. - */ - protected void listCleared() { - if (this.listSize != 0) { - this.fireIntervalRemoved(this, 0, this.listSize - 1); - this.listSize = 0; - } - } - - /** - * The underlying model list has changed "dramatically". - * Notify listeners of the changes. - */ - protected void listChanged() { - if (this.listSize != 0) { - this.fireIntervalRemoved(this, 0, this.listSize - 1); - } - this.listSize = this.listHolder.size(); - if (this.listSize != 0) { - this.fireIntervalAdded(this, 0, this.listSize - 1); - } - } - - - // ********** Object overrides ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.listHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ListSpinnerModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ListSpinnerModelAdapter.java deleted file mode 100644 index af3e0b0187..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ListSpinnerModelAdapter.java +++ /dev/null @@ -1,218 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import java.util.Arrays; -import java.util.List; -import javax.swing.SpinnerListModel; -import javax.swing.event.ChangeListener; -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.SpinnerListModel can be used to keep a ChangeListener - * (e.g. a JSpinner) in synch with a PropertyValueModel that holds a value - * in the list. - * - * This class must be a sub-class of SpinnerListModel because of some - * crappy jdk code.... ~bjv - * @see javax.swing.JSpinner#createEditor(javax.swing.SpinnerModel) - * - * NB: This model should only be used for values that have a reasonably - * inexpensive #equals() implementation. - * @see #synchronize(Object) - * - * If this class needs to be modified, it would behoove us to review the - * other, similar classes: - * @see DateSpinnerModelAdapter - * @see NumberSpinnerModelAdapter - */ -public class ListSpinnerModelAdapter - extends SpinnerListModel -{ - - /** - * The default spinner value; used when the underlying model value is null. - * The default is the first item on the list. - */ - private final Object defaultValue; - - /** A value model on the underlying value. */ - private final WritablePropertyValueModel<Object> valueHolder; - - /** A listener that allows us to synchronize with changes made to the underlying value. */ - private final PropertyChangeListener valueChangeListener; - - - // ********** constructors ********** - - /** - * Constructor - the value holder is required. - * Use the model value itself as the default spinner value. - */ - public ListSpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder) { - this(valueHolder, valueHolder.getValue()); - } - - /** - * Constructor - the value holder is required. - */ - public ListSpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder, Object defaultValue) { - this(valueHolder, new Object[] {defaultValue}, defaultValue); - } - - /** - * Constructor - the value holder is required. - * Use the first item in the list of values as the default spinner value. - */ - public ListSpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder, Object[] values) { - this(valueHolder, values, values[0]); - } - - /** - * Constructor - the value holder is required. - */ - public ListSpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder, Object[] values, Object defaultValue) { - this(valueHolder, Arrays.asList(values), defaultValue); - } - - /** - * Constructor - the value holder is required. - * Use the first item in the list of values as the default spinner value. - */ - public ListSpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder, List<Object> values) { - this(valueHolder, values, values.get(0)); - } - - /** - * Constructor - the value holder is required. - */ - public ListSpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder, List<Object> values, Object defaultValue) { - super(values); - this.valueHolder = valueHolder; - this.valueChangeListener = this.buildValueChangeListener(); - // postpone listening to the underlying value - // until we have listeners ourselves... - this.defaultValue = defaultValue; - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildValueChangeListener() { - return new AWTPropertyChangeListenerWrapper(this.buildValueChangeListener_()); - } - - protected PropertyChangeListener buildValueChangeListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - ListSpinnerModelAdapter.this.synchronize(event.getNewValue()); - } - @Override - public String toString() { - return "value listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** SpinnerModel implementation ********** - - /** - * Extend to check whether this method is being called before we - * have any listeners. - * This is necessary because some crappy jdk code gets the value - * from the model *before* listening to the model. ~bjv - * @see javax.swing.JSpinner.DefaultEditor(javax.swing.JSpinner) - */ - @Override - public Object getValue() { - if (this.getChangeListeners().length == 0) { - // sorry about this "lateral" call to super ~bjv - super.setValue(this.spinnerValueOf(this.valueHolder.getValue())); - } - return super.getValue(); - } - - /** - * Extend to update the underlying value directly. - * The resulting event will be ignored: @see #synchronize(Object). - */ - @Override - public void setValue(Object value) { - super.setValue(value); - this.valueHolder.setValue(value); - } - - /** - * Extend to start listening to the underlying value if necessary. - */ - @Override - public void addChangeListener(ChangeListener listener) { - if (this.getChangeListeners().length == 0) { - this.valueHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.valueChangeListener); - this.synchronize(this.valueHolder.getValue()); - } - super.addChangeListener(listener); - } - - /** - * Extend to stop listening to the underlying value if appropriate. - */ - @Override - public void removeChangeListener(ChangeListener listener) { - super.removeChangeListener(listener); - if (this.getChangeListeners().length == 0) { - this.valueHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.valueChangeListener); - } - } - - - // ********** queries ********** - - protected Object getDefaultValue() { - return this.defaultValue; - } - - /** - * Convert to a non-null value. - */ - protected Object spinnerValueOf(Object value) { - return (value == null) ? this.getDefaultValue() : value; - } - - - // ********** behavior ********** - - /** - * Set the spinner value if it has changed. - */ - void synchronize(Object value) { - Object newValue = this.spinnerValueOf(value); - // check to see whether the spinner value has already been synchronized - // (via #setValue()) - if ( ! this.getValue().equals(newValue)) { - this.setValue(newValue); - } - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.valueHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/NumberSpinnerModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/NumberSpinnerModelAdapter.java deleted file mode 100644 index 4a624639b5..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/NumberSpinnerModelAdapter.java +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * 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.common.utility.internal.model.value.swing; - -import javax.swing.SpinnerNumberModel; -import javax.swing.event.ChangeListener; -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.SpinnerNumberModel can be used to keep a ChangeListener - * (e.g. a JSpinner) in synch with a PropertyValueModel that holds a number. - * - * This class must be a sub-class of SpinnerNumberModel because of some - * crappy jdk code.... ~bjv - * @see javax.swing.JSpinner#createEditor(javax.swing.SpinnerModel) - * - * If this class needs to be modified, it would behoove us to review the - * other, similar classes: - * @see DateSpinnerModelAdapter - * @see ListSpinnerModelAdapter - */ -public class NumberSpinnerModelAdapter - extends SpinnerNumberModel -{ - - /** - * The default spinner value; used when the - * underlying model number value is null. - */ - private final Number defaultValue; - - /** A value model on the underlying number. */ - private final WritablePropertyValueModel<Number> numberHolder; - - /** - * A listener that allows us to synchronize with - * changes made to the underlying number. - */ - private final PropertyChangeListener numberChangeListener; - - - // ********** constructors ********** - - /** - * Constructor - the number holder is required. - * The default spinner value is zero. - * The step size is one. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder) { - this(numberHolder, 0); - } - - /** - * Constructor - the number holder is required. - * The step size is one. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder, int defaultValue) { - this(numberHolder, null, null, Integer.valueOf(1), Integer.valueOf(defaultValue)); - } - - /** - * Constructor - the number holder is required. - * Use the minimum value as the default spinner value. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder, int minimum, int maximum, int stepSize) { - this(numberHolder, minimum, maximum, stepSize, minimum); - } - - /** - * Constructor - the number holder is required. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder, int minimum, int maximum, int stepSize, int defaultValue) { - this(numberHolder, Integer.valueOf(minimum), Integer.valueOf(maximum), Integer.valueOf(stepSize), Integer.valueOf(defaultValue)); - } - - /** - * Constructor - the number holder is required. - * Use the minimum value as the default spinner value. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder, double minimum, double maximum, double stepSize) { - this(numberHolder, minimum, maximum, stepSize, minimum); - } - - /** - * Constructor - the number holder is required. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder, double minimum, double maximum, double stepSize, double defaultValue) { - this(numberHolder, Double.valueOf(minimum), Double.valueOf(maximum), Double.valueOf(stepSize), Double.valueOf(defaultValue)); - } - - /** - * Constructor - the number holder is required. - */ - public NumberSpinnerModelAdapter(WritablePropertyValueModel<Number> numberHolder, Comparable<?> minimum, Comparable<?> maximum, Number stepSize, Number defaultValue) { - super(numberHolder.getValue() == null ? defaultValue : (Number) numberHolder.getValue(), minimum, maximum, stepSize); - this.numberHolder = numberHolder; - this.numberChangeListener = this.buildNumberChangeListener(); - // postpone listening to the underlying number - // until we have listeners ourselves... - this.defaultValue = defaultValue; - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildNumberChangeListener() { - return new AWTPropertyChangeListenerWrapper(this.buildNumberChangeListener_()); - } - - protected PropertyChangeListener buildNumberChangeListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - NumberSpinnerModelAdapter.this.synchronize(event.getNewValue()); - } - @Override - public String toString() { - return "number listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** SpinnerModel implementation ********** - - /** - * Extend to check whether this method is being called before we - * have any listeners. - * This is necessary because some crappy jdk code gets the value - * from the model *before* listening to the model. ~bjv - * @see javax.swing.JSpinner.DefaultEditor(javax.swing.JSpinner) - */ - @Override - public Object getValue() { - if (this.getChangeListeners().length == 0) { - // sorry about this "lateral" call to super ~bjv - super.setValue(this.spinnerValueOf(this.numberHolder.getValue())); - } - return super.getValue(); - } - - /** - * Extend to update the underlying number directly. - * The resulting event will be ignored: @see #synchronizeDelegate(Object). - */ - @Override - public void setValue(Object value) { - super.setValue(value); - this.numberHolder.setValue((Number) value); - } - - /** - * Extend to start listening to the underlying number if necessary. - */ - @Override - public void addChangeListener(ChangeListener listener) { - if (this.getChangeListeners().length == 0) { - this.numberHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.numberChangeListener); - this.synchronize(this.numberHolder.getValue()); - } - super.addChangeListener(listener); - } - - /** - * Extend to stop listening to the underlying number if appropriate. - */ - @Override - public void removeChangeListener(ChangeListener listener) { - super.removeChangeListener(listener); - if (this.getChangeListeners().length == 0) { - this.numberHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.numberChangeListener); - } - } - - - // ********** queries ********** - - protected Number getDefaultValue() { - return this.defaultValue; - } - - /** - * Convert to a non-null value. - */ - protected Object spinnerValueOf(Object value) { - return (value == null) ? this.getDefaultValue() : value; - } - - - // ********** behavior ********** - - /** - * Set the spinner value if it has changed. - */ - void synchronize(Object value) { - Object newValue = this.spinnerValueOf(value); - // check to see whether the date has already been synchronized - // (via #setValue()) - if ( ! this.getValue().equals(newValue)) { - this.setValue(newValue); - } - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.numberHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ObjectListSelectionModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ObjectListSelectionModel.java deleted file mode 100644 index 81647b2842..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ObjectListSelectionModel.java +++ /dev/null @@ -1,427 +0,0 @@ -/******************************************************************************* - * 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.common.utility.internal.model.value.swing; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import javax.swing.DefaultListSelectionModel; -import javax.swing.ListModel; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; -import javax.swing.event.ListSelectionListener; -import org.eclipse.jpt.common.utility.internal.CollectionTools; - -/** - * This ListSelectionModel is aware of the ListModel and - * provides convenience methods to access and set the - * selected *objects*, as opposed to the selected *indexes*. - */ -public class ObjectListSelectionModel - extends DefaultListSelectionModel -{ - /** The list model referenced by the list selection model. */ - private final ListModel listModel; - - /** A listener that allows us to clear the selection when the list model has changed. */ - private final ListDataListener listDataListener; - - - // ********** constructors ********** - - /** - * Construct a list selection model for the specified list model. - */ - public ObjectListSelectionModel(ListModel listModel) { - super(); - this.listModel = listModel; - this.listDataListener = this.buildListDataListener(); - } - - - // ********** initialization ********** - - private ListDataListener buildListDataListener() { - return new ListDataListener() { - public void intervalAdded(ListDataEvent event) { - // this does not affect the selection - } - public void intervalRemoved(ListDataEvent event) { - // this does not affect the selection - } - public void contentsChanged(ListDataEvent event) { - ObjectListSelectionModel.this.listModelContentsChanged(event); - } - @Override - public String toString() { - return "list data listener"; //$NON-NLS-1$ - } - }; - } - - /** - * Typically, the selection does not need to be cleared when the - * contents of the list have changed. Most of the time this just - * means an item has changed in a way that affects its display string - * or icon. We typically only use the class for edits involving - * single selection. - * A subclass can override this method if the selection - * should be cleared because a change could mean the selection is invalid. - */ - protected void listModelContentsChanged(@SuppressWarnings("unused") ListDataEvent event) { - /**this.clearSelection();*/ - } - - - // ********** ListSelectionModel implementation ********** - - @Override - public void addListSelectionListener(ListSelectionListener l) { - if (this.hasNoListSelectionListeners()) { - this.listModel.addListDataListener(this.listDataListener); - } - super.addListSelectionListener(l); - } - - @Override - public void removeListSelectionListener(ListSelectionListener l) { - super.removeListSelectionListener(l); - if (this.hasNoListSelectionListeners()) { - this.listModel.removeListDataListener(this.listDataListener); - } - } - - - // ********** queries ********** - - /** - * Return whether this model has no listeners. - */ - protected boolean hasNoListSelectionListeners() { // private-protected - return this.getListSelectionListeners().length == 0; - } - - /** - * Return the list model referenced by the list selection model. - */ - public ListModel getListModel() { - return this.listModel; - } - - public int selectedValuesSize() { - int min = this.getMinSelectionIndex(); - int max = this.getMaxSelectionIndex(); - - if ((min < 0) || (max < 0)) { - return 0; - } - - int n = 0; - int count = this.getListModel().getSize(); - for (int i = min; i <= max; i++) { - if (this.isSelectedIndex(i) && (i < count)) { - n++; - } - } - return n; - } - - /** - * Return the first selected value. - * Return null if the selection is empty. - */ - public Object selectedValue() { - int index = this.getMinSelectionIndex(); - if (index == -1) { - return null; - } - if (this.getListModel().getSize() <= index) { - return null; - } - return this.getListModel().getElementAt(index); - } - - /** - * Return an array of the selected values. - */ - public Object[] selectedValues() { - int min = this.getMinSelectionIndex(); - int max = this.getMaxSelectionIndex(); - - if ((min < 0) || (max < 0)) { - return new Object[0]; - } - - int maxSize = (max - min) + 1; - Object[] temp = new Object[maxSize]; - int n = 0; - int count = this.getListModel().getSize(); - for (int i = min; i <= max; i++) { - if (this.isSelectedIndex(i) && (i < count)) { - temp[n++] = this.getListModel().getElementAt(i); - } - } - if (n == maxSize) { - // all the elements in the range were selected - return temp; - } - // only some of the elements in the range were selected - Object[] result = new Object[n]; - System.arraycopy(temp, 0, result, 0, n); - return result; - } - - /** - * Return an array of the selected indices in order. - */ - public int[] selectedIndices() { - int min = this.getMinSelectionIndex(); - int max = this.getMaxSelectionIndex(); - - if ((min < 0) || (max < 0)) { - return new int[0]; - } - - int maxSize = (max - min) + 1; - int[] temp = new int[maxSize]; - int n = 0; - int count = this.getListModel().getSize(); - for (int i = min; i <= max; i++) { - if (this.isSelectedIndex(i) && (i < count)) { - temp[n++] = i; - } - } - if (n == maxSize) { - // all the elements in the range were selected - Arrays.sort(temp); - return temp; - } - // only some of the elements in the range were selected - int[] result = new int[n]; - System.arraycopy(temp, 0, result, 0, n); - Arrays.sort(result); - return result; - } - - /** - * Set the selected value. - */ - public void setSelectedValue(Object object) { - this.setSelectedValues(CollectionTools.singletonIterator(object)); - } - - /** - * Set the current set of selected objects to the specified objects. - * @see javax.swing.ListSelectionModel#setSelectionInterval(int, int) - */ - public void setSelectedValues(Iterator<?> objects) { - this.setValueIsAdjusting(true); - this.clearSelection(); - this.addSelectedValuesInternal(objects); - this.setValueIsAdjusting(false); - } - - /** - * Set the current set of selected objects to the specified objects. - * @see javax.swing.ListSelectionModel#setSelectionInterval(int, int) - */ - public void setSelectedValues(Collection<?> objects) { - this.setSelectedValues(objects.iterator()); - } - - /** - * Set the current set of selected objects to the specified objects. - * @see javax.swing.ListSelectionModel#setSelectionInterval(int, int) - */ - public void setSelectedValues(Object[] objects) { - this.setSelectedValues(CollectionTools.iterator(objects)); - } - - /** - * Add the specified object to the current set of selected objects. - * @see javax.swing.ListSelectionModel#addSelectionInterval(int, int) - */ - public void addSelectedValue(Object object) { - this.addSelectedValues(CollectionTools.singletonIterator(object)); - } - - /** - * Add the specified objects to the current set of selected objects. - * @see javax.swing.ListSelectionModel#addSelectionInterval(int, int) - */ - public void addSelectedValues(Iterator<?> objects) { - this.setValueIsAdjusting(true); - this.addSelectedValuesInternal(objects); - this.setValueIsAdjusting(false); - } - - /** - * Add the specified objects to the current set of selected objects. - * @see javax.swing.ListSelectionModel#addSelectionInterval(int, int) - */ - public void addSelectedValues(Collection<?> objects) { - this.addSelectedValues(objects.iterator()); - } - - /** - * Add the specified objects to the current set of selected objects. - * @see javax.swing.ListSelectionModel#addSelectionInterval(int, int) - */ - public void addSelectedValues(Object[] objects) { - this.addSelectedValues(CollectionTools.iterator(objects)); - } - - /** - * Remove the specified object from the current set of selected objects. - * @see javax.swing.ListSelectionModel#removeSelectionInterval(int, int) - */ - public void removeSelectedValue(Object object) { - this.removeSelectedValues(CollectionTools.singletonIterator(object)); - } - - /** - * Remove the specified objects from the current set of selected objects. - * @see javax.swing.ListSelectionModel#removeSelectionInterval(int, int) - */ - public void removeSelectedValues(Iterator<?> objects) { - this.setValueIsAdjusting(true); - ListModel lm = this.getListModel(); - int lmSize = lm.getSize(); - while (objects.hasNext()) { - int index = this.indexOf(objects.next(), lm, lmSize); - this.removeSelectionInterval(index, index); - } - this.setValueIsAdjusting(false); - } - - /** - * Remove the specified objects from the current set of selected objects. - * @see javax.swing.ListSelectionModel#removeSelectionInterval(int, int) - */ - public void removeSelectedValues(Collection<?> objects) { - this.removeSelectedValues(objects.iterator()); - } - - /** - * Remove the specified objects from the current set of selected objects. - * @see javax.swing.ListSelectionModel#removeSelectionInterval(int, int) - */ - public void removeSelectedValues(Object[] objects) { - this.removeSelectedValues(CollectionTools.iterator(objects)); - } - - /** - * @see javax.swing.ListSelectionModel#getAnchorSelectionIndex() - * Return null if the anchor selection is empty. - */ - public Object getAnchorSelectedValue() { - int index = this.getAnchorSelectionIndex(); - if (index == -1) { - return null; - } - return this.getListModel().getElementAt(index); - } - - /** - * @see javax.swing.ListSelectionModel#setAnchorSelectionIndex(int) - */ - public void setAnchorSelectedValue(Object object) { - this.setAnchorSelectionIndex(this.indexOf(object)); - } - - /** - * @see javax.swing.ListSelectionModel#getLeadSelectionIndex() - * Return null if the lead selection is empty. - */ - public Object getLeadSelectedValue() { - int index = this.getLeadSelectionIndex(); - if (index == -1) { - return null; - } - return this.getListModel().getElementAt(index); - } - - /** - * @see javax.swing.ListSelectionModel#setLeadSelectionIndex(int) - */ - public void setLeadSelectedValue(Object object) { - this.setLeadSelectionIndex(this.indexOf(object)); - } - - /** - * @see javax.swing.ListSelectionModel#getMaxSelectionIndex() - * Return null if the max selection is empty. - */ - public Object getMaxSelectedValue() { - int index = this.getMaxSelectionIndex(); - if (index == -1) { - return null; - } - return this.getListModel().getElementAt(index); - } - - /** - * @see javax.swing.ListSelectionModel#getMinSelectionIndex() - * Return null if the min selection is empty. - */ - public Object getMinSelectedValue() { - int index = this.getMinSelectionIndex(); - if (index == -1) { - return null; - } - return this.getListModel().getElementAt(index); - } - - /** - * @see javax.swing.ListSelectionModel#isSelectedIndex(int) - */ - public boolean valueIsSelected(Object object) { - return this.isSelectedIndex(this.indexOf(object)); - } - - /** - * Add the specified objects to the current set of selected objects, - * without wrapping the actions in "adjusting" events. - */ - private void addSelectedValuesInternal(Iterator<?> objects) { - ListModel lm = this.getListModel(); - int listModelSize = lm.getSize(); - while (objects.hasNext()) { - int index = this.indexOf(objects.next(), lm, listModelSize); - this.addSelectionInterval(index, index); - } - } - - /** - * Return the index in the list model of the specified object. - * Return -1 if the object is not in the list model. - */ - private int indexOf(Object object) { - ListModel lm = this.getListModel(); - return this.indexOf(object, lm, lm.getSize()); - } - - /** - * Return the index in the list model of the specified object. - * Return -1 if the object is not in the list model. - */ - // we're just jerking around with performance optimizations here - // (in memory of Phil...); - // call this method inside loops that do not modify the listModel - private int indexOf(Object object, ListModel lm, int listModelSize) { - for (int i = listModelSize; i-- > 0; ) { - if (lm.getElementAt(i).equals(object)) { - return i; - } - } - return -1; - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/PrimitiveListTreeModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/PrimitiveListTreeModel.java deleted file mode 100644 index 9fe9fca0e8..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/PrimitiveListTreeModel.java +++ /dev/null @@ -1,239 +0,0 @@ -/******************************************************************************* - * 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.common.utility.internal.model.value.swing; - -import java.util.ArrayList; -import java.util.Iterator; - -import javax.swing.event.TreeModelListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.MutableTreeNode; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTListChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.ListAddEvent; -import org.eclipse.jpt.common.utility.model.event.ListChangeEvent; -import org.eclipse.jpt.common.utility.model.event.ListClearEvent; -import org.eclipse.jpt.common.utility.model.event.ListMoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListRemoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListReplaceEvent; -import org.eclipse.jpt.common.utility.model.listener.ListChangeListener; -import org.eclipse.jpt.common.utility.model.value.ListValueModel; - -/** - * This TreeModel implementation provides a tree with a "null" root that - * has a set of "primitive" children. These "primitive" children do not have - * children themselves, making the tree a maximum of 2 levels deep. - * This model automatically synchronizes the root's children with a - * ListValueModel that holds a collection of primitive (non-model) objects - * (e.g. Strings). - * - * This is useful for providing an "editable" list of primitives. Since the JDK - * does not provide us with an editable listbox, we must use an editable tree. - * We wrap everything in DefaultMutableTreeNodes. - * - * Subclasses must implement #primitiveChanged(int, Object) and update - * the model appropriately. This method is called when the user edits the - * list directly and presses <Enter>. - * - * The JTree using this model must be configured as "editable": - * tree.setEditable(true); - */ -// TODO convert to use an adapter instead of requiring subclass -public abstract class PrimitiveListTreeModel - extends DefaultTreeModel -{ - /** a model on the list of primitives */ - private final ListValueModel<?> listHolder; - - /** a listener that handles the adding, removing, and replacing of the primitives */ - private final ListChangeListener listChangeListener; - - - // ********** constructors ********** - - /** - * Public constructor - the list holder is required - */ - public PrimitiveListTreeModel(ListValueModel<?> listHolder) { - super(new DefaultMutableTreeNode(null, true)); // true = the root can have children - if (listHolder == null) { - throw new NullPointerException(); - } - this.listHolder = listHolder; - this.listChangeListener = this.buildListChangeListener(); - // postpone listening to the model until we have listeners ourselves - } - - protected ListChangeListener buildListChangeListener() { - return new AWTListChangeListenerWrapper(this.buildListChangeListener_()); - } - - protected ListChangeListener buildListChangeListener_() { - return new PrimitiveListChangeListener(); - } - - - // ********** behavior ********** - - /** - * Subclasses should override this method to update the - * model appropriately. The primitive at the specified index was - * edited directly by the user and the new value is as specified. - * Convert the value appropriately and place it in the model. - */ - protected abstract void primitiveChanged(int index, Object newValue); - - - // ********** TreeModel implementation ********** - - /** - * Override to change the underlying model instead of changing the node directly. - */ - @Override - public void valueForPathChanged(TreePath path, Object newValue) { - TreeNode node = (TreeNode) path.getLastPathComponent(); - int index = ((TreeNode) this.getRoot()).getIndex(node); - this.primitiveChanged(index, newValue); - } - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public void addTreeModelListener(TreeModelListener l) { - if (this.getTreeModelListeners().length == 0) { - this.listHolder.addListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener); - this.synchronizeList(); - } - super.addTreeModelListener(l); - } - - /** - * Extend to stop listening to the underlying model if appropriate. - */ - @Override - public void removeTreeModelListener(TreeModelListener l) { - super.removeTreeModelListener(l); - if (this.getTreeModelListeners().length == 0) { - this.listHolder.removeListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener); - } - } - - - // ********** behavior ********** - - /** - * Synchronize our list of nodes with the list of primitives - */ - void synchronizeList() { - this.clearList(); - this.buildList(); - } - - void clearList() { - int childcount = this.root.getChildCount(); - for (int i = childcount - 1; i >= 0; i--) { - this.removeNodeFromParent((MutableTreeNode)this.root.getChildAt(i)); - } - } - - private void buildList() { - for (Iterator<?> stream = this.listHolder.iterator(); stream.hasNext(); ) { - this.addPrimitive(stream.next()); - } - } - - /** - * Add the specified primitive to the end of the list. - */ - private void addPrimitive(Object primitive) { - this.insertPrimitive(this.root.getChildCount(), primitive); - } - - /** - * Create a node for the specified primitive - * and insert it as a child of the root. - */ - void insertPrimitive(int index, Object primitive) { - DefaultMutableTreeNode node = new DefaultMutableTreeNode(primitive, false); // don't allow children on the child node - this.insertNodeInto(node, (MutableTreeNode) this.root, index); - } - - /** - * Remove node at the specified index. - */ - MutableTreeNode removeNode(int index) { - MutableTreeNode node = (MutableTreeNode) this.root.getChildAt(index); - this.removeNodeFromParent(node); - return node; - } - - /** - * Replace the user object of the node at childIndex. - */ - void replacePrimitive(int index, Object primitive) { - MutableTreeNode node = (MutableTreeNode) this.root.getChildAt(index); - node.setUserObject(primitive); - this.nodeChanged(node); - } - - - // ********** inner class ********** - - private class PrimitiveListChangeListener implements ListChangeListener { - PrimitiveListChangeListener() { - super(); - } - - public void itemsAdded(ListAddEvent event) { - int i = event.getIndex(); - for (Object item : event.getItems()) { - PrimitiveListTreeModel.this.insertPrimitive(i++, item); - } - } - - public void itemsRemoved(ListRemoveEvent event) { - for (int i = 0; i < event.getItemsSize(); i++) { - PrimitiveListTreeModel.this.removeNode(event.getIndex()); - } - } - - public void itemsReplaced(ListReplaceEvent event) { - int i = event.getIndex(); - for (Object item : event.getNewItems()) { - PrimitiveListTreeModel.this.replacePrimitive(i++, item); - } - } - - public void itemsMoved(ListMoveEvent event) { - ArrayList<MutableTreeNode> temp = new ArrayList<MutableTreeNode>(event.getLength()); - for (int i = 0; i < event.getLength(); i++) { - temp.add(PrimitiveListTreeModel.this.removeNode(event.getSourceIndex())); - } - int i = event.getTargetIndex(); - for (MutableTreeNode node : temp) { - PrimitiveListTreeModel.this.insertPrimitive(i++, node); - } - } - - public void listCleared(ListClearEvent event) { - PrimitiveListTreeModel.this.clearList(); - } - - public void listChanged(ListChangeEvent event) { - PrimitiveListTreeModel.this.synchronizeList(); - } - - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/RadioButtonModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/RadioButtonModelAdapter.java deleted file mode 100644 index 83d3113454..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/RadioButtonModelAdapter.java +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * 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.common.utility.internal.model.value.swing; - -import org.eclipse.jpt.common.utility.internal.BidiFilter; -import org.eclipse.jpt.common.utility.internal.BidiTransformer; -import org.eclipse.jpt.common.utility.internal.model.value.FilteringWritablePropertyValueModel; -import org.eclipse.jpt.common.utility.internal.model.value.TransformationWritablePropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.ButtonModel can be used to keep a listener - * (e.g. a JRadioButton) in synch with a (typically shared) - * PropertyValueModel that holds one value out of a set of values. - * - * NOTE: Do *not* use this model with a ButtonGroup, since the - * shared value holder and the wrappers built by this adapter will - * keep the appropriate radio button checked. Also, this allows - * us to uncheck all the radio buttons in a group when the shared - * value is null. - */ -public class RadioButtonModelAdapter - extends ToggleButtonModelAdapter -{ - - // ********** constructors ********** - - /** - * Constructor - the value holder is required. - */ - public RadioButtonModelAdapter(WritablePropertyValueModel<Object> valueHolder, Object buttonValue, boolean defaultValue) { - super(buildBooleanHolder(valueHolder, buttonValue), defaultValue); - } - - /** - * Constructor - the value holder is required. - * The default value will be false. - */ - public RadioButtonModelAdapter(WritablePropertyValueModel<Object> valueHolder, Object buttonValue) { - super(buildBooleanHolder(valueHolder, buttonValue)); - } - - - // ********** static methods ********** - - /** - * Build up a set of wrappers that will convert the - * specified value holder and button value to/from a boolean. - * - * If the value holder's value matches the button value, - * the wrapper will return true. Likewise, if the value holder's - * value is set to true, the wrapper will set the value holder's - * value to the button value. - */ - public static WritablePropertyValueModel<Boolean> buildBooleanHolder(WritablePropertyValueModel<Object> valueHolder, Object buttonValue) { - WritablePropertyValueModel<Object> filteringPVM = new FilteringWritablePropertyValueModel<Object>(valueHolder, new RadioButtonFilter(buttonValue)); - return new TransformationWritablePropertyValueModel<Object, Boolean>(filteringPVM, new RadioButtonTransformer(buttonValue)); - } - - - // ********** overrides ********** - - /** - * The user cannot de-select a radio button - the user - * can only *select* a radio button. Only the model can - * cause a radio button to be de-selected. We use the - * ARMED flag to indicate whether we are being de-selected - * by the user. - */ - @Override - public void setSelected(boolean b) { - // do not allow the user to de-select a radio button - // radio buttons can - if ((b == false) && this.isArmed()) { - return; - } - super.setSelected(b); - } - - - // ********** inner classes ********** - - /** - * This filter will only pass through a new value to the wrapped - * value holder when it matches the configured button value. - */ - public static class RadioButtonFilter implements BidiFilter<Object> { - private Object buttonValue; - - public RadioButtonFilter(Object buttonValue) { - super(); - this.buttonValue = buttonValue; - } - - /** - * always return the wrapped value - */ - public boolean accept(Object value) { - return true; - } - - /** - * pass through the value to the wrapped property value model - * *only* when it matches our button value - */ - public boolean reverseAccept(Object value) { - return (value != null) && value.equals(this.buttonValue); - } - - } - - /** - * This transformer will convert the wrapped value to Boolean.TRUE - * when it matches the configured button value. - */ - public static class RadioButtonTransformer implements BidiTransformer<Object, Boolean> { - private Object buttonValue; - - public RadioButtonTransformer(Object buttonValue) { - super(); - this.buttonValue = buttonValue; - } - - /** - * if the wrapped value matches our button value return true, - * if it is some other value return false; - * but if it is null simply pass it through because it will cause the - * button model's default value to be used - */ - public Boolean transform(Object value) { - return (value == null) ? null : Boolean.valueOf(value.equals(this.buttonValue)); - } - - /** - * if the new value is true, pass through the our button value; - * otherwise pass through null - */ - public Object reverseTransform(Boolean value) { - return (value.booleanValue()) ? this.buttonValue : null; - } - - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/SpinnerModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/SpinnerModelAdapter.java deleted file mode 100644 index 2490cae9d4..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/SpinnerModelAdapter.java +++ /dev/null @@ -1,207 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import javax.swing.AbstractSpinnerModel; -import javax.swing.SpinnerModel; -import javax.swing.SpinnerNumberModel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This javax.swing.SpinnerModel can be used to keep a ChangeListener - * (e.g. a JSpinner) in synch with a PropertyValueModel that holds a value. - * - * Note: it is likely you want to use one of the following classes instead of - * this one: - * DateSpinnerModelAdapter - * NumberSpinnerModelAdapter - * ListSpinnerModelAdapter - * - * NB: This model should only be used for values that have a fairly - * inexpensive #equals() implementation. - * @see #synchronizeDelegate(Object) - */ -public class SpinnerModelAdapter - extends AbstractSpinnerModel -{ - /** The delegate spinner model whose behavior we "enhance". */ - protected final SpinnerModel delegate; - - /** A listener that allows us to forward any changes made to the delegate spinner model. */ - protected final ChangeListener delegateListener; - - /** A value model on the underlying value. */ - protected final WritablePropertyValueModel<Object> valueHolder; - - /** A listener that allows us to synchronize with changes made to the underlying value. */ - protected final PropertyChangeListener valueListener; - - - // ********** constructors ********** - - /** - * Constructor - the value holder and delegate are required. - */ - public SpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder, SpinnerModel delegate) { - super(); - if (valueHolder == null || delegate == null) { - throw new NullPointerException(); - } - this.valueHolder = valueHolder; - this.delegate = delegate; - // postpone listening to the underlying value - // until we have listeners ourselves... - this.valueListener = this.buildValueListener(); - this.delegateListener = this.buildDelegateListener(); - } - - /** - * Constructor - the value holder is required. - * This will wrap a simple number spinner model. - */ - public SpinnerModelAdapter(WritablePropertyValueModel<Object> valueHolder) { - this(valueHolder, new SpinnerNumberModel()); - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildValueListener() { - return new AWTPropertyChangeListenerWrapper(this.buildValueListener_()); - } - - protected PropertyChangeListener buildValueListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - SpinnerModelAdapter.this.valueChanged(event); - } - @Override - public String toString() { - return "value listener"; //$NON-NLS-1$ - } - }; - } - - /** - * expand access a bit for inner class - */ - @Override - protected void fireStateChanged() { - super.fireStateChanged(); - } - - protected ChangeListener buildDelegateListener() { - return new ChangeListener() { - public void stateChanged(ChangeEvent event) { - // forward the event, with this as the source - SpinnerModelAdapter.this.fireStateChanged(); - } - @Override - public String toString() { - return "delegate listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** SpinnerModel implementation ********** - - public Object getValue() { - return this.delegate.getValue(); - } - - /** - * Extend to update the underlying value directly. - * The resulting event will be ignored: @see #synchronizeDelegate(Object). - */ - public void setValue(Object value) { - this.delegate.setValue(value); - this.valueHolder.setValue(value); - } - - public Object getNextValue() { - return this.delegate.getNextValue(); - } - - public Object getPreviousValue() { - return this.delegate.getPreviousValue(); - } - - /** - * Extend to start listening to the underlying value if necessary. - */ - @Override - public void addChangeListener(ChangeListener listener) { - if (this.listenerList.getListenerCount(ChangeListener.class) == 0) { - this.delegate.addChangeListener(this.delegateListener); - this.engageValueHolder(); - } - super.addChangeListener(listener); - } - - /** - * Extend to stop listening to the underlying value if appropriate. - */ - @Override - public void removeChangeListener(ChangeListener listener) { - super.removeChangeListener(listener); - if (this.listenerList.getListenerCount(ChangeListener.class) == 0) { - this.disengageValueHolder(); - this.delegate.removeChangeListener(this.delegateListener); - } - } - - - // ********** behavior ********** - - /** - * A third party has modified the underlying value. - * Synchronize the delegate model accordingly. - */ - protected void valueChanged(PropertyChangeEvent event) { - this.synchronizeDelegate(event.getNewValue()); - } - - /** - * Set the delegate's value if it has changed. - */ - protected void synchronizeDelegate(Object value) { - // check to see whether the delegate has already been synchronized - // (via #setValue()) - if ( ! this.delegate.getValue().equals(value)) { - this.delegate.setValue(value); - } - } - - protected void engageValueHolder() { - this.valueHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.valueListener); - this.synchronizeDelegate(this.valueHolder.getValue()); - } - - protected void disengageValueHolder() { - this.valueHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.valueListener); - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.valueHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/TableModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/TableModelAdapter.java deleted file mode 100644 index 8c29c1364b..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/TableModelAdapter.java +++ /dev/null @@ -1,420 +0,0 @@ -/******************************************************************************* - * 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.common.utility.internal.model.value.swing; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.swing.event.TableModelListener; -import javax.swing.table.AbstractTableModel; - -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTListChangeListenerWrapper; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.internal.model.value.CollectionListValueModelAdapter; -import org.eclipse.jpt.common.utility.model.event.ListAddEvent; -import org.eclipse.jpt.common.utility.model.event.ListChangeEvent; -import org.eclipse.jpt.common.utility.model.event.ListClearEvent; -import org.eclipse.jpt.common.utility.model.event.ListMoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListRemoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListReplaceEvent; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.ListChangeListener; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.CollectionValueModel; -import org.eclipse.jpt.common.utility.model.value.ListValueModel; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * This TableModel can be used to keep a TableModelListener (e.g. a JTable) - * in synch with a ListValueModel that holds a collection of model objects, - * each of which corresponds to a row in the table. - * Typically, each column of the table will be bound to a different aspect - * of the contained model objects. - * - * For example, a MWTable has an attribute 'databaseFields' that holds - * a collection of MWDatabaseFields that would correspond to the rows of - * a JTable; and each MWDatabaseField has a number - * of attributes (e.g. name, type, size) that can be bound to the columns of - * a row in the JTable. As these database fields are added, removed, and - * changed, this model will keep the listeners aware of the changes. - * - * An instance of this TableModel must be supplied with a - * list holder (e.g. the 'databaseFields'), which is a value - * model on the bound collection This is required - the - * collection itself can be null, but the list value model that - * holds it is required. Typically this list will be sorted (@see - * SortedListValueModelAdapter). - * - * This TableModel must also be supplied with a ColumnAdapter that - * will be used to configure the headers, renderers, editors, and contents - * of the various columns. - * - * Design decision: - * Cell listener options (from low space/high time to high space/low time): - * - 1 cell listener listening to every cell (this is the current implementation) - * - 1 cell listener per row - * - 1 cell listener per cell - */ -public class TableModelAdapter<E> - extends AbstractTableModel -{ - /** - * a list of user objects that are converted to - * rows via the column adapter - */ - private ListValueModel<? extends E> listHolder; - private final ListChangeListener listChangeListener; - - /** - * each row is an array of cell models - */ - // declare as ArrayList so we can use #ensureCapacity(int) - private final ArrayList<WritablePropertyValueModel<Object>[]> rows; - - /** - * client-supplied adapter that provides with the various column - * settings and converts the objects in the LVM - * into an array of cell models - */ - private final ColumnAdapter columnAdapter; - - /** - * the single listener that listens to every cell's model - */ - private final PropertyChangeListener cellListener; - - - // ********** constructors ********** - - /** - * Construct a table model adapter for the specified objects - * and adapter. - */ - public TableModelAdapter(ListValueModel<? extends E> listHolder, ColumnAdapter columnAdapter) { - super(); - if (listHolder == null) { - throw new NullPointerException(); - } - this.listHolder = listHolder; - this.columnAdapter = columnAdapter; - this.listChangeListener = this.buildListChangeListener(); - this.rows = new ArrayList<WritablePropertyValueModel<Object>[]>(); - this.cellListener = this.buildCellListener(); - } - - /** - * Construct a table model adapter for the specified objects - * and adapter. - */ - public TableModelAdapter(CollectionValueModel<? extends E> collectionHolder, ColumnAdapter columnAdapter) { - this(new CollectionListValueModelAdapter<E>(collectionHolder), columnAdapter); - } - - - // ********** initialization ********** - - protected ListChangeListener buildListChangeListener() { - return new AWTListChangeListenerWrapper(this.buildListChangeListener_()); - } - - protected ListChangeListener buildListChangeListener_() { - return new ListChangeListener() { - public void itemsAdded(ListAddEvent event) { - TableModelAdapter.this.addRows(event.getIndex(), event.getItemsSize(), this.getItems(event)); - } - public void itemsRemoved(ListRemoveEvent event) { - TableModelAdapter.this.removeRows(event.getIndex(), event.getItemsSize()); - } - public void itemsReplaced(ListReplaceEvent event) { - TableModelAdapter.this.replaceRows(event.getIndex(), this.getNewItems(event)); - } - public void itemsMoved(ListMoveEvent event) { - TableModelAdapter.this.moveRows(event.getTargetIndex(), event.getSourceIndex(), event.getLength()); - } - public void listCleared(ListClearEvent event) { - TableModelAdapter.this.clearTable(); - } - public void listChanged(ListChangeEvent event) { - TableModelAdapter.this.rebuildTable(); - } - // minimized scope of suppressed warnings - @SuppressWarnings("unchecked") - protected Iterable<Object> getItems(ListAddEvent event) { - return (Iterable<Object>) event.getItems(); - } - // minimized scope of suppressed warnings - @SuppressWarnings("unchecked") - protected Iterable<Object> getNewItems(ListReplaceEvent event) { - return (Iterable<Object>) event.getNewItems(); - } - @Override - public String toString() { - return "list listener"; //$NON-NLS-1$ - } - }; - } - - - protected PropertyChangeListener buildCellListener() { - return new AWTPropertyChangeListenerWrapper(this.buildCellListener_()); - } - - protected PropertyChangeListener buildCellListener_() { - return new PropertyChangeListener() { - @SuppressWarnings("unchecked") - public void propertyChanged(PropertyChangeEvent event) { - TableModelAdapter.this.cellChanged((WritablePropertyValueModel<Object>) event.getSource()); - } - @Override - public String toString() { - return "cell listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** TableModel implementation ********** - - public int getColumnCount() { - return this.columnAdapter.columnCount(); - } - - public int getRowCount() { - return this.rows.size(); - } - - @Override - public String getColumnName(int column) { - return this.columnAdapter.columnName(column); - } - - @Override - public Class<?> getColumnClass(int columnIndex) { - return this.columnAdapter.columnClass(columnIndex); - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return this.columnAdapter.columnIsEditable(columnIndex); - } - - public Object getValueAt(int rowIndex, int columnIndex) { - WritablePropertyValueModel<Object>[] row = this.rows.get(rowIndex); - return row[columnIndex].getValue(); - } - - @Override - public void setValueAt(Object value, int rowIndex, int columnIndex) { - WritablePropertyValueModel<Object>[] row = this.rows.get(rowIndex); - row[columnIndex].setValue(value); - } - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public void addTableModelListener(TableModelListener l) { - if (this.hasNoTableModelListeners()) { - this.engageModel(); - } - super.addTableModelListener(l); - } - - /** - * Extend to stop listening to the underlying model if necessary. - */ - @Override - public void removeTableModelListener(TableModelListener l) { - super.removeTableModelListener(l); - if (this.hasNoTableModelListeners()) { - this.disengageModel(); - } - } - - - // ********** public API ********** - - /** - * Return the underlying list model. - */ - public ListValueModel<? extends E> getModel() { - return this.listHolder; - } - - /** - * Set the underlying list model. - */ - public void setModel(ListValueModel<E> listHolder) { - if (listHolder == null) { - throw new NullPointerException(); - } - boolean hasListeners = this.hasTableModelListeners(); - if (hasListeners) { - this.disengageModel(); - } - this.listHolder = listHolder; - if (hasListeners) { - this.engageModel(); - this.fireTableDataChanged(); - } - } - - /** - * Set the underlying collection model. - */ - public void setModel(CollectionValueModel<E> collectionHolder) { - this.setModel(new CollectionListValueModelAdapter<E>(collectionHolder)); - } - - - // ********** queries ********** - - /** - * Return whether this model has no listeners. - */ - protected boolean hasNoTableModelListeners() { - return this.listenerList.getListenerCount(TableModelListener.class) == 0; - } - - /** - * Return whether this model has any listeners. - */ - protected boolean hasTableModelListeners() { - return ! this.hasNoTableModelListeners(); - } - - - // ********** behavior ********** - - /** - * Start listening to the list of objects and the various aspects - * of the objects that make up the rows. - */ - private void engageModel() { - this.listHolder.addListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener); - this.engageAllCells(); - } - - /** - * Convert the objects into rows and listen to the cells. - */ - private void engageAllCells() { - this.rows.ensureCapacity(this.listHolder.size()); - for (Iterator<? extends E> stream = this.listHolder.iterator(); stream.hasNext(); ) { - WritablePropertyValueModel<Object>[] row = this.columnAdapter.cellModels(stream.next()); - this.engageRow(row); - this.rows.add(row); - } - } - - /** - * Listen to the cells in the specified row. - */ - private void engageRow(WritablePropertyValueModel<Object>[] row) { - for (int i = row.length; i-- > 0; ) { - row[i].addPropertyChangeListener(PropertyValueModel.VALUE, this.cellListener); - } - } - - /** - * Stop listening. - */ - private void disengageModel() { - this.disengageAllCells(); - this.listHolder.removeListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener); - } - - private void disengageAllCells() { - for (WritablePropertyValueModel<Object>[] row : this.rows) { - this.disengageRow(row); - } - this.rows.clear(); - } - - private void disengageRow(WritablePropertyValueModel<Object>[] row) { - for (int i = row.length; i-- > 0; ) { - row[i].removePropertyChangeListener(PropertyValueModel.VALUE, this.cellListener); - } - } - - /** - * brute-force search for the cell(s) that changed... - */ - void cellChanged(WritablePropertyValueModel<Object> cellHolder) { - for (int i = this.rows.size(); i-- > 0; ) { - WritablePropertyValueModel<Object>[] row = this.rows.get(i); - for (int j = row.length; j-- > 0; ) { - if (row[j] == cellHolder) { - this.fireTableCellUpdated(i, j); - } - } - } - } - - /** - * convert the items to rows - */ - void addRows(int index, int size, Iterable<Object> items) { - List<WritablePropertyValueModel<Object>[]> newRows = new ArrayList<WritablePropertyValueModel<Object>[]>(size); - for (Object item : items) { - WritablePropertyValueModel<Object>[] row = this.columnAdapter.cellModels(item); - this.engageRow(row); - newRows.add(row); - } - this.rows.addAll(index, newRows); - this.fireTableRowsInserted(index, index + size - 1); - } - - void removeRows(int index, int size) { - for (int i = 0; i < size; i++) { - this.disengageRow(this.rows.remove(index)); - } - this.fireTableRowsDeleted(index, index + size - 1); - } - - void replaceRows(int index, Iterable<Object> items) { - int i = index; - for (Object item : items) { - WritablePropertyValueModel<Object>[] row = this.rows.get(i); - this.disengageRow(row); - row = this.columnAdapter.cellModels(item); - this.engageRow(row); - this.rows.set(i, row); - i++; - } - this.fireTableRowsUpdated(index, i - 1); - } - - void moveRows(int targetIndex, int sourceIndex, int length) { - ArrayList<WritablePropertyValueModel<Object>[]> temp = new ArrayList<WritablePropertyValueModel<Object>[]>(length); - for (int i = 0; i < length; i++) { - temp.add(this.rows.remove(sourceIndex)); - } - this.rows.addAll(targetIndex, temp); - - int start = Math.min(targetIndex, sourceIndex); - int end = Math.max(targetIndex, sourceIndex) + length - 1; - this.fireTableRowsUpdated(start, end); - } - - void clearTable() { - this.disengageAllCells(); - this.fireTableDataChanged(); - } - - void rebuildTable() { - this.disengageAllCells(); - this.engageAllCells(); - this.fireTableDataChanged(); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ToggleButtonModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ToggleButtonModelAdapter.java deleted file mode 100644 index 044b2658a5..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/ToggleButtonModelAdapter.java +++ /dev/null @@ -1,224 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import java.awt.event.ActionListener; -import java.awt.event.ItemListener; -import javax.swing.JToggleButton.ToggleButtonModel; -import javax.swing.event.ChangeListener; -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel; - -/** - * 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 final boolean defaultValue; - - /** A value model on the underlying model boolean. */ - protected final WritablePropertyValueModel<Boolean> booleanHolder; - - /** - * A listener that allows us to synchronize with - * changes made to the underlying model boolean. - */ - protected final PropertyChangeListener booleanChangeListener; - - - // ********** constructors ********** - - /** - * Constructor - the boolean holder is required. - */ - public ToggleButtonModelAdapter(WritablePropertyValueModel<Boolean> booleanHolder, boolean defaultValue) { - super(); - if (booleanHolder == null) { - throw new NullPointerException(); - } - this.booleanHolder = booleanHolder; - this.booleanChangeListener = this.buildBooleanChangeListener(); - // 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(WritablePropertyValueModel<Boolean> booleanHolder) { - this(booleanHolder, false); - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildBooleanChangeListener() { - return new AWTPropertyChangeListenerWrapper(this.buildBooleanChangeListener_()); - } - - protected PropertyChangeListener buildBooleanChangeListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - ToggleButtonModelAdapter.this.booleanChanged(event); - } - @Override - public String toString() { - return "boolean listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** ButtonModel implementation ********** - - /** - * Extend to update the underlying model if necessary. - */ - @Override - 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. - */ - @Override - public void addActionListener(ActionListener l) { - if (this.hasNoListeners()) { - this.engageModel(); - } - super.addActionListener(l); - } - - /** - * Extend to stop listening to the underlying model if appropriate. - */ - @Override - public void removeActionListener(ActionListener l) { - super.removeActionListener(l); - if (this.hasNoListeners()) { - this.disengageModel(); - } - } - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public void addItemListener(ItemListener l) { - if (this.hasNoListeners()) { - this.engageModel(); - } - super.addItemListener(l); - } - - /** - * Extend to stop listening to the underlying model if appropriate. - */ - @Override - public void removeItemListener(ItemListener l) { - super.removeItemListener(l); - if (this.hasNoListeners()) { - this.disengageModel(); - } - } - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public void addChangeListener(ChangeListener l) { - if (this.hasNoListeners()) { - this.engageModel(); - } - super.addChangeListener(l); - } - - /** - * Extend to stop listening to the underlying model if appropriate. - */ - @Override - 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 event) { - this.setSelected((Boolean) event.getNewValue()); - } - - protected void engageModel() { - this.booleanHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.booleanChangeListener); - this.setSelected(this.booleanHolder.getValue()); - } - - protected void disengageModel() { - this.booleanHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.booleanChangeListener); - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.booleanHolder); - } - -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/TreeModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/TreeModelAdapter.java deleted file mode 100644 index 12f0faf3a7..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/swing/TreeModelAdapter.java +++ /dev/null @@ -1,914 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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.common.utility.internal.model.value.swing; - -import java.util.ArrayList; -import java.util.IdentityHashMap; -import java.util.List; - -import javax.swing.event.TreeModelListener; -import javax.swing.tree.TreePath; - -import org.eclipse.jpt.common.utility.internal.StringTools; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTListChangeListenerWrapper; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper; -import org.eclipse.jpt.common.utility.internal.model.listener.awt.AWTStateChangeListenerWrapper; -import org.eclipse.jpt.common.utility.internal.model.value.StaticPropertyValueModel; -import org.eclipse.jpt.common.utility.model.event.ListAddEvent; -import org.eclipse.jpt.common.utility.model.event.ListChangeEvent; -import org.eclipse.jpt.common.utility.model.event.ListClearEvent; -import org.eclipse.jpt.common.utility.model.event.ListEvent; -import org.eclipse.jpt.common.utility.model.event.ListMoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListRemoveEvent; -import org.eclipse.jpt.common.utility.model.event.ListReplaceEvent; -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.event.StateChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.ListChangeListener; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.listener.StateChangeListener; -import org.eclipse.jpt.common.utility.model.value.ListValueModel; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.TreeNodeValueModel; - -/** - * This javax.swing.tree.TreeModel can be used to keep a TreeModelListener - * (e.g. a JTree) in synch with a tree of TreeNodeValueModel objects. Unlike - * javax.swing.tree.DefaultTreeModel, you do not add and remove nodes with - * methods implemented here. You can add and remove nodes by adding and - * removing them directly to/from the nodes (or, more typically, the domain - * objects the nodes are wrapping and listening to). - * - * Due to limitations in JTree, the root of the tree can never be null, - * which, typically, should not be a problem. (If you want to display an empty - * tree you can set the JTree's treeModel to null.) - */ -public class TreeModelAdapter<T> - extends AbstractTreeModel -{ - /** - * A value model on the underlying tree's root node and its - * corresponding listener. This allows clients to swap out - * the entire tree. Due to limitations in JTree, the root should - * never be set to null while we have listeners. - */ - private final PropertyValueModel<TreeNodeValueModel<T>> rootHolder; - private final PropertyChangeListener rootListener; - - /** - * A listener that notifies us when a node's internal - * "state" changes (as opposed to the node's value or list of - * children), allowing us to forward notification to our listeners. - */ - private final StateChangeListener nodeStateListener; - - /** - * A listener that notifies us when a node's "value" - * changes (as opposed to the node's state or list of - * children), allowing us to forward notification to our listeners. - * Typically, this will only happen with nodes that hold - * primitive data. - */ - private final PropertyChangeListener nodeValueListener; - - /** - * A listener that notifies us when an underlying node's - * "list" of children changes, allowing us to keep our - * internal tree in synch with the underlying tree model. - */ - private final ListChangeListener childrenListener; - - /* these attributes make up our internal tree */ - /** - * The root cannot be null while we have listeners, which is - * most of the time. The root is cached so we can disengage - * from it when it has been swapped out. - */ - private TreeNodeValueModel<T> root; - - /** - * Map the nodes to their lists of children. - * We cache these so we can swap out the entire list of children - * when we receive a #listChanged() event (which does not include - * the items that were affected). - * @see EventChangePolicy#rebuildChildren() - */ - final IdentityHashMap<TreeNodeValueModel<T>, List<TreeNodeValueModel<T>>> childrenLists; - - /** - * Map the children models to their parents. - * We cache these so we can figure out the "real" source of the - * list change events (the parent). - * @see EventChangePolicy#parent() - */ - final IdentityHashMap<ListValueModel<TreeNodeValueModel<T>>, TreeNodeValueModel<T>> parents; - - - // ********** constructors ********** - - /** - * Construct a tree model for the specified root. - */ - public TreeModelAdapter(PropertyValueModel<TreeNodeValueModel<T>> rootHolder) { - super(); - if (rootHolder == null) { - throw new NullPointerException(); - } - this.rootHolder = rootHolder; - this.rootListener = this.buildRootListener(); - this.nodeStateListener = this.buildNodeStateListener(); - this.nodeValueListener = this.buildNodeValueListener(); - this.childrenListener = this.buildChildrenListener(); - this.childrenLists = new IdentityHashMap<TreeNodeValueModel<T>, List<TreeNodeValueModel<T>>>(); - this.parents = new IdentityHashMap<ListValueModel<TreeNodeValueModel<T>>, TreeNodeValueModel<T>>(); - } - - /** - * Construct a tree model for the specified root. - */ - public TreeModelAdapter(TreeNodeValueModel<T> root) { - this(new StaticPropertyValueModel<TreeNodeValueModel<T>>(root)); - } - - - // ********** initialization ********** - - protected PropertyChangeListener buildRootListener() { - return new AWTPropertyChangeListenerWrapper(this.buildRootListener_()); - } - - protected PropertyChangeListener buildRootListener_() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - TreeModelAdapter.this.rootChanged(); - } - @Override - public String toString() { - return "root listener"; //$NON-NLS-1$ - } - }; - } - - protected PropertyChangeListener buildNodeValueListener() { - return new AWTPropertyChangeListenerWrapper(this.buildNodeValueListener_()); - } - - protected PropertyChangeListener buildNodeValueListener_() { - return new PropertyChangeListener() { - @SuppressWarnings("unchecked") - public void propertyChanged(PropertyChangeEvent event) { - TreeModelAdapter.this.nodeChanged((TreeNodeValueModel<T>) event.getSource()); - } - @Override - public String toString() { - return "node value listener"; //$NON-NLS-1$ - } - }; - } - - protected StateChangeListener buildNodeStateListener() { - return new AWTStateChangeListenerWrapper(this.buildNodeStateListener_()); - } - - protected StateChangeListener buildNodeStateListener_() { - return new StateChangeListener() { - @SuppressWarnings("unchecked") - public void stateChanged(StateChangeEvent event) { - TreeModelAdapter.this.nodeChanged((TreeNodeValueModel<T>) event.getSource()); - } - @Override - public String toString() { - return "node state listener"; //$NON-NLS-1$ - } - }; - } - - protected ListChangeListener buildChildrenListener() { - return new AWTListChangeListenerWrapper(this.buildChildrenListener_()); - } - - protected ListChangeListener buildChildrenListener_() { - return new ListChangeListener() { - public void itemsAdded(ListAddEvent event) { - new AddEventChangePolicy(event).addChildren(); - } - public void itemsRemoved(ListRemoveEvent event) { - new RemoveEventChangePolicy(event).removeChildren(); - } - public void itemsReplaced(ListReplaceEvent event) { - new ReplaceEventChangePolicy(event).replaceChildren(); - } - public void itemsMoved(ListMoveEvent event) { - new MoveEventChangePolicy(event).moveChildren(); - } - public void listCleared(ListClearEvent event) { - new ClearEventChangePolicy(event).clearChildren(); - } - public void listChanged(ListChangeEvent event) { - new ChangeEventChangePolicy(event).rebuildChildren(); - } - @Override - public String toString() { - return "children listener"; //$NON-NLS-1$ - } - }; - } - - - // ********** TreeModel implementation ********** - - public Object getRoot() { - return this.root; - } - - @SuppressWarnings("unchecked") - public Object getChild(Object parent, int index) { - return ((TreeNodeValueModel<T>) parent).child(index); - } - - @SuppressWarnings("unchecked") - public int getChildCount(Object parent) { - return ((TreeNodeValueModel<T>) parent).childrenSize(); - } - - @SuppressWarnings("unchecked") - public boolean isLeaf(Object node) { - return ((TreeNodeValueModel<T>) node).isLeaf(); - } - - @SuppressWarnings("unchecked") - public void valueForPathChanged(TreePath path, Object newValue) { - ((TreeNodeValueModel<T>) path.getLastPathComponent()).setValue((T) newValue); - } - - @SuppressWarnings("unchecked") - public int getIndexOfChild(Object parent, Object child) { - return ((TreeNodeValueModel<T>) parent).indexOfChild((TreeNodeValueModel<T>) child); - } - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public void addTreeModelListener(TreeModelListener l) { - if (this.hasNoTreeModelListeners()) { - this.engageModel(); - } - super.addTreeModelListener(l); - } - - /** - * Extend to stop listening to the underlying model if appropriate. - */ - @Override - public void removeTreeModelListener(TreeModelListener l) { - super.removeTreeModelListener(l); - if (this.hasNoTreeModelListeners()) { - this.disengageModel(); - } - } - - - // ********** behavior ********** - - /** - * Listen to the root and all the other nodes - * in the underlying tree model. - */ - private void engageModel() { - this.rootHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.rootListener); - this.root = this.rootHolder.getValue(); - if (this.root == null) { - throw new NullPointerException(); // the root cannot be null while we have listeners - } - this.engageNode(this.root); - this.addRoot(); - } - - /** - * Add the root and all of the nodes to the underlying tree. - */ - private void addRoot() { - this.addNode(0, this.root); - } - - /** - * Stop listening to the root and all the other - * nodes in the underlying tree model. - */ - private void disengageModel() { - this.removeRoot(); - this.disengageNode(this.root); - this.root = null; - this.rootHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.rootListener); - } - - /** - * Remove the root and all of the nodes from the underlying tree. - */ - private void removeRoot() { - this.removeNode(0, this.root); - } - - /** - * The root has been swapped. - * This method is a bit gnarly because the API for notifying listeners - * that the root has changed is a bit inconsistent with that used for - * non-root nodes. - */ - void rootChanged() { - TreeNodeValueModel<T> newRoot = this.rootHolder.getValue(); - if (newRoot == null) { - throw new NullPointerException(); // the root cannot be null while we have listeners - } - // remove all the current root's children from the tree - // and remove the it from the internal tree - this.removeRoot(); - - // save the old root and swap in the new root - TreeNodeValueModel<T> oldRoot = this.root; - this.root = newRoot; - - // we must be listening to both the old and new roots when we fire the event - // because their values can be affected by whether they have listeners - this.engageNode(this.root); - this.fireTreeRootReplaced(this.root); - // now we can stop listening to the old root - this.disengageNode(oldRoot); - - // add the new root to the internal tree and - // add all its children to the tree also - this.addRoot(); - } - - /** - * Either the "value" or the "state" of the specified node has changed, - * forward notification to our listeners. - */ - void nodeChanged(TreeNodeValueModel<T> node) { - TreeNodeValueModel<T> parent = node.parent(); - if (parent == null) { - this.fireTreeRootChanged(node); - } else { - this.fireTreeNodeChanged(parent.path(), parent.indexOfChild(node), node); - } - } - - /** - * Listen to the nodes, notify our listeners that the nodes were added, - * and then add the nodes to our internal tree. - * We must listen to the nodes before notifying anybody, because - * adding a listener can change the value of a node. - */ - void addChildren(TreeNodeValueModel<T>[] path, int[] childIndices, TreeNodeValueModel<T>[] children) { - int len = childIndices.length; - for (int i = 0; i < len; i++) { - this.engageNode(children[i]); - } - this.fireTreeNodesInserted(path, childIndices, children); - for (int i = 0; i < len; i++) { - this.addNode(childIndices[i], children[i]); - } - } - - /** - * Listen to the node and its children model. - */ - private void engageNode(TreeNodeValueModel<T> node) { - node.addStateChangeListener(this.nodeStateListener); - node.addPropertyChangeListener(PropertyValueModel.VALUE, this.nodeValueListener); - node.childrenModel().addListChangeListener(ListValueModel.LIST_VALUES, this.childrenListener); - } - - /** - * Add the node to our internal tree; - * then recurse down through the node's children, - * adding them to the internal tree also. - */ - private void addNode(int index, TreeNodeValueModel<T> node) { - this.addNodeToInternalTree(node.parent(), index, node, node.childrenModel()); - new NodeChangePolicy(node).addChildren(); - } - - /** - * Add the specified node to our internal tree. - */ - private void addNodeToInternalTree(TreeNodeValueModel<T> parent, int index, TreeNodeValueModel<T> node, ListValueModel<TreeNodeValueModel<T>> childrenModel) { - List<TreeNodeValueModel<T>> siblings = this.childrenLists.get(parent); - if (siblings == null) { - siblings = new ArrayList<TreeNodeValueModel<T>>(); - this.childrenLists.put(parent, siblings); - } - siblings.add(index, node); - - this.parents.put(childrenModel, node); - } - - /** - * Remove nodes from our internal tree, notify our listeners that the - * nodes were removed, then stop listening to the nodes. - * We must listen to the nodes until after notifying anybody, because - * removing a listener can change the value of a node. - */ - void removeChildren(TreeNodeValueModel<T>[] path, int[] childIndices, TreeNodeValueModel<T>[] children) { - int len = childIndices.length; - for (int i = 0; i < len; i++) { - // the indices slide down a notch each time we remove a child - this.removeNode(childIndices[i] - i, children[i]); - } - this.fireTreeNodesRemoved(path, childIndices, children); - for (int i = 0; i < len; i++) { - this.disengageNode(children[i]); - } - } - - /** - * First, recurse down through the node's children, - * removing them from our internal tree; - * then remove the node itself from our internal tree. - */ - private void removeNode(int index, TreeNodeValueModel<T> node) { - new NodeChangePolicy(node).removeChildren(); - this.removeNodeFromInternalTree(node.parent(), index, node.childrenModel()); - } - - /** - * Remove the specified node from our internal tree. - */ - private void removeNodeFromInternalTree(TreeNodeValueModel<T> parent, int index, ListValueModel<TreeNodeValueModel<T>> childrenModel) { - this.parents.remove(childrenModel); - - List<TreeNodeValueModel<T>> siblings = this.childrenLists.get(parent); - siblings.remove(index); - if (siblings.isEmpty()) { - this.childrenLists.remove(parent); - } - } - - /** - * Stop listening to the node and its children model. - */ - private void disengageNode(TreeNodeValueModel<T> node) { - node.childrenModel().removeListChangeListener(ListValueModel.LIST_VALUES, this.childrenListener); - node.removePropertyChangeListener(PropertyValueModel.VALUE, this.nodeValueListener); - node.removeStateChangeListener(this.nodeStateListener); - } - - void moveChildren(TreeNodeValueModel<T> parent, int targetIndex, int sourceIndex, int length) { - List<TreeNodeValueModel<T>> childrenList = this.childrenLists.get(parent); - ArrayList<TreeNodeValueModel<T>> temp = new ArrayList<TreeNodeValueModel<T>>(length); - for (int i = 0; i < length; i++) { - temp.add(childrenList.remove(sourceIndex)); - } - childrenList.addAll(targetIndex, temp); - - this.fireTreeStructureChanged(parent.path()); - } - - - // ********** standard methods ********** - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.root); - } - - - // ********** inner classes ********** - - /** - * Coalesce some of the common change policy behavior. - */ - abstract class ChangePolicy { - - ChangePolicy() { - super(); - } - - /** - * Add the current set of children. - */ - void addChildren() { - TreeModelAdapter.this.addChildren(this.parent().path(), this.childIndices(), this.childArray()); - } - - /** - * Remove the current set of children. - */ - void removeChildren() { - TreeModelAdapter.this.removeChildren(this.parent().path(), this.childIndices(), this.childArray()); - } - - /** - * Return an array of the indices of the current set of children, - * which should be contiguous. - */ - int[] childIndices() { - return this.buildIndices(this.childrenStartIndex(), this.childrenSize()); - } - - /** - * Return an array of the current set of children. - */ - TreeNodeValueModel<T>[] childArray() { - return this.buildArray(this.getChildren(), this.childrenSize()); - } - - /** - * Build an array to hold the elements in the specified iterator. - * If they are different sizes, something is screwed up... - */ - TreeNodeValueModel<T>[] buildArray(Iterable<TreeNodeValueModel<T>> elements, int size) { - @SuppressWarnings("unchecked") - TreeNodeValueModel<T>[] array = new TreeNodeValueModel[size]; - int i = 0; - for (TreeNodeValueModel<T> element : elements) { - array[i++] = element; - } - return array; - } - - /** - * Return a set of indices, starting at zero and - * continuing for the specified size. - */ - int[] buildIndices(int size) { - return buildIndices(0, size); - } - - /** - * Return a set of indices, starting at the specified index and - * continuing for the specified size. - */ - int[] buildIndices(int start, int size) { - int[] indices = new int[size]; - int index = start; - for (int i = 0; i < size; i++) { - indices[i] = index++; - } - return indices; - } - - /** - * Return the parent of the current set of children. - */ - abstract TreeNodeValueModel<T> parent(); - - /** - * Return the starting index for the current set of children. - */ - abstract int childrenStartIndex(); - - /** - * Return the size of the current set of children. - */ - abstract int childrenSize(); - - /** - * Return the current set of children. - */ - abstract Iterable<TreeNodeValueModel<T>> getChildren(); - - } - - - /** - * Wraps a ListEvent for adding, removing, replacing, - * and changing children. - */ - abstract class EventChangePolicy extends ChangePolicy { - final ListEvent event; - - EventChangePolicy(ListEvent event) { - super(); - this.event = event; - } - - /** - * Map the ListChangeEvent's source to the corresponding parent. - */ - @Override - TreeNodeValueModel<T> parent() { - return TreeModelAdapter.this.parents.get(this.event.getSource()); - } - - } - - - /** - * Wraps a ListAddEvent for adding children. - */ - class AddEventChangePolicy extends EventChangePolicy { - - AddEventChangePolicy(ListAddEvent event) { - super(event); - } - - private ListAddEvent getEvent() { - return (ListAddEvent) this.event; - } - - /** - * The ListAddEvent's item index is the children start index. - */ - @Override - int childrenStartIndex() { - return this.getEvent().getIndex(); - } - - /** - * The ListAddEvent's size is the children size. - */ - @Override - int childrenSize() { - return this.getEvent().getItemsSize(); - } - - /** - * The ListAddEvent's items are the children. - */ - @Override - @SuppressWarnings("unchecked") - Iterable<TreeNodeValueModel<T>> getChildren() { - return (Iterable<TreeNodeValueModel<T>>) this.getEvent().getItems(); - } - - } - - - /** - * Wraps a ListRemoveEvent for adding children. - */ - class RemoveEventChangePolicy extends EventChangePolicy { - - RemoveEventChangePolicy(ListRemoveEvent event) { - super(event); - } - - private ListRemoveEvent getEvent() { - return (ListRemoveEvent) this.event; - } - - /** - * The ListRemoveEvent's item index is the children start index. - */ - @Override - int childrenStartIndex() { - return this.getEvent().getIndex(); - } - - /** - * The ListRemoveEvent's size is the children size. - */ - @Override - int childrenSize() { - return this.getEvent().getItemsSize(); - } - - /** - * The ListRemoveEvent's items are the children. - */ - @Override - @SuppressWarnings("unchecked") - Iterable<TreeNodeValueModel<T>> getChildren() { - return (Iterable<TreeNodeValueModel<T>>) this.getEvent().getItems(); - } - - } - - - /** - * Wraps a ListReplaceEvent for replacing children. - */ - class ReplaceEventChangePolicy extends EventChangePolicy { - - ReplaceEventChangePolicy(ListReplaceEvent event) { - super(event); - } - - private ListReplaceEvent getEvent() { - return (ListReplaceEvent) this.event; - } - - /** - * The ListReplaceEvent's item index is the children start index. - */ - @Override - int childrenStartIndex() { - return this.getEvent().getIndex(); - } - - /** - * The ListReplaceEvent's size is the children size. - */ - @Override - int childrenSize() { - return this.getEvent().getItemsSize(); - } - - /** - * The ListReplaceEvent's items are the children. - */ - @Override - @SuppressWarnings("unchecked") - Iterable<TreeNodeValueModel<T>> getChildren() { - return (Iterable<TreeNodeValueModel<T>>) this.getEvent().getNewItems(); - } - - /** - * Remove the old nodes and add the new ones. - */ - void replaceChildren() { - TreeNodeValueModel<T>[] parentPath = this.parent().path(); - int[] childIndices = this.childIndices(); - TreeModelAdapter.this.removeChildren(parentPath, childIndices, this.getOldChildren()); - TreeModelAdapter.this.addChildren(parentPath, childIndices, this.childArray()); - } - - TreeNodeValueModel<T>[] getOldChildren() { - return this.buildArray(this.getOldItems(), this.getEvent().getItemsSize()); - } - - // minimized scope of suppressed warnings - @SuppressWarnings("unchecked") - protected Iterable<TreeNodeValueModel<T>> getOldItems() { - return (Iterable<TreeNodeValueModel<T>>) this.getEvent().getOldItems(); - } - - } - - - /** - * Wraps a ListMoveEvent for moving children. - */ - class MoveEventChangePolicy extends EventChangePolicy { - - MoveEventChangePolicy(ListMoveEvent event) { - super(event); - } - - private ListMoveEvent getEvent() { - return (ListMoveEvent) this.event; - } - - void moveChildren() { - TreeModelAdapter.this.moveChildren(this.parent(), this.getEvent().getTargetIndex(), this.getEvent().getSourceIndex(), this.getEvent().getLength()); - } - - @Override - int childrenStartIndex() { - throw new UnsupportedOperationException(); - } - - @Override - int childrenSize() { - throw new UnsupportedOperationException(); - } - - @Override - Iterable<TreeNodeValueModel<T>> getChildren() { - throw new UnsupportedOperationException(); - } - - } - - - /** - * Wraps a ListClearEvent for clearing children. - */ - class ClearEventChangePolicy extends EventChangePolicy { - - ClearEventChangePolicy(ListClearEvent event) { - super(event); - } - - /** - * Clear all the nodes. - */ - void clearChildren() { - TreeNodeValueModel<T> parent = this.parent(); - TreeNodeValueModel<T>[] parentPath = parent.path(); - List<TreeNodeValueModel<T>> childrenList = TreeModelAdapter.this.childrenLists.get(parent); - int[] childIndices = this.buildIndices(childrenList.size()); - TreeNodeValueModel<T>[] childArray = this.buildArray(childrenList, childrenList.size()); - TreeModelAdapter.this.removeChildren(parentPath, childIndices, childArray); - } - - @Override - int childrenStartIndex() { - throw new UnsupportedOperationException(); - } - - @Override - int childrenSize() { - throw new UnsupportedOperationException(); - } - - @Override - Iterable<TreeNodeValueModel<T>> getChildren() { - throw new UnsupportedOperationException(); - } - - } - - - /** - * Wraps a ListChangeEvent for clearing children. - */ - class ChangeEventChangePolicy extends EventChangePolicy { - - ChangeEventChangePolicy(ListChangeEvent event) { - super(event); - } - - /** - * Remove all the old nodes and add all the new nodes. - */ - void rebuildChildren() { - TreeNodeValueModel<T> parent = this.parent(); - TreeNodeValueModel<T>[] parentPath = parent.path(); - List<TreeNodeValueModel<T>> childrenList = TreeModelAdapter.this.childrenLists.get(parent); - int[] childIndices = this.buildIndices(childrenList.size()); - TreeNodeValueModel<T>[] childArray = this.buildArray(childrenList, childrenList.size()); - TreeModelAdapter.this.removeChildren(parentPath, childIndices, childArray); - - childIndices = this.buildIndices(parent.childrenModel().size()); - childArray = this.buildArray(parent.childrenModel(), parent.childrenSize()); - TreeModelAdapter.this.addChildren(parentPath, childIndices, childArray); - } - - @Override - int childrenStartIndex() { - throw new UnsupportedOperationException(); - } - - @Override - int childrenSize() { - throw new UnsupportedOperationException(); - } - - @Override - Iterable<TreeNodeValueModel<T>> getChildren() { - throw new UnsupportedOperationException(); - } - - } - - - /** - * Wraps a TreeNodeValueModel for adding and removing its children. - */ - class NodeChangePolicy extends ChangePolicy { - private final TreeNodeValueModel<T> node; - - NodeChangePolicy(TreeNodeValueModel<T> node) { - super(); - this.node = node; - } - - /** - * The node itself is the parent. - */ - @Override - TreeNodeValueModel<T> parent() { - return this.node; - } - - /** - * Since we will always be dealing with all of the node's - * children, the children start index is always zero. - */ - @Override - int childrenStartIndex() { - return 0; - } - - /** - * Since we will always be dealing with all of the node's - * children, the children size is always equal to the size - * of the children model. - */ - @Override - int childrenSize() { - return this.node.childrenModel().size(); - } - - /** - * Since we will always be dealing with all of the node's - * children, the children are all the objects held by - * the children model. - */ - @Override - Iterable<TreeNodeValueModel<T>> getChildren() { - return this.node.childrenModel(); - } - - } - -} |