net.wotonomy.ui.swing
Class TreeModelAssociation

java.lang.Object
  extended by net.wotonomy.control.EODelayedObserver
      extended by net.wotonomy.ui.EOAssociation
          extended by net.wotonomy.ui.swing.TreeModelAssociation
All Implemented Interfaces:
java.util.EventListener, java.util.Observer, javax.swing.event.TreeSelectionListener, javax.swing.tree.TreeModel, net.wotonomy.control.EOObserving
Direct Known Subclasses:
TreeAssociation

public class TreeModelAssociation
extends net.wotonomy.ui.EOAssociation
implements javax.swing.tree.TreeModel, javax.swing.event.TreeSelectionListener

TreeModelAssociation binds a JTree or similar component that uses a TreeModel to a display group's list of displayable objects, each of which may have a list of child objects managed by another display group, and so on. TreeModelAssociation works exactly like a ListAssociation, with the additional capability to specify a "Children" aspect, that will allow child objects to be retrieved from a parent display group.

This class acts as the TreeModel for the controlled component: calling yourcomponent.getModel() will return this association. The tree model methods on this class are public and may be used to affect changes on the controlled components.

The titles display group's contents are inserted into a new display group that acts as the root node. After that point, changes in the titles display group will cause the tree model to reset itself, creating a new display group for the root node.

If a separate display group is bound to the children aspect, it will be used to hold the selected objects and their siblings and selection will be maintained there, and the titles display group selection will not be updated. Any editing or detail associations should in that case be attached to the children display group, not the titles group.

Each node in the tree is an EODisplayGroup that contains the child objects of the object it represents in the tree. These objects can be programmatically inserted, updated, or removed using DisplayGroup methods. Each node's takes its parent group's sortOrderings until a sort ordering is explicitly specified - setting a sort ordering to null will resume using the parent group's sort ordering.

Each node in the tree also implements MutableTreeNode. The value that a node represents is the titles property value of the object in the parent's displayed objects list at the index corresponding to the index of the node. Calling toString on a node returns the string representation of the titles property value, and setUserObject will update that value directly in the corresponding object. Moving a node from one parent to another will remove the actual object in the parent display group and insert it into the destination display group.

In short, any nodes obtained from this class' implementation of TreeModel may be cast as either EODisplayGroup or MutableTreeNode and maybe be programmatically manipulated in either manner.

Version:
$Revision: 904 $
Author:
michael@mpowers.net, $Author: cgruber $

Field Summary
protected  boolean childrenGroupChanged
           
protected  boolean isListening
           
protected  boolean titlesGroupChanged
           
 
Fields inherited from class net.wotonomy.ui.EOAssociation
ActionAspect, ArgumentAspect, aspectToGroup, aspectToKey, AttributeAspectSignature, AttributeToManyAspectSignature, AttributeToOneAspectSignature, AttributeToOneToManyAspectSignature, BoldAspect, ChildrenAspect, control, DestinationAspect, EditableAspect, EnabledAspect, IconAspect, IsLeafAspect, ItalicAspect, LabelAspect, NullAspectSignature, ObjectsAspect, ParentAspect, SelectedObjectAspect, SelectedTitleAspect, SourceAspect, TitlesAspect, ToManyAspectSignature, ToOneAspectSignature, ToOneToManyAspectSignature, URLAspect, ValueAspect, VisibleAspect
 
Fields inherited from class net.wotonomy.control.EODelayedObserver
ObserverNumberOfPriorities, ObserverPriorityFifth, ObserverPriorityFirst, ObserverPriorityFourth, ObserverPriorityImmediate, ObserverPriorityLater, ObserverPrioritySecond, ObserverPrioritySixth, ObserverPriorityThird
 
Constructor Summary
TreeModelAssociation(java.lang.Object anObject)
          Constructor expecting a JTree or any other object that has void setModel(TreeModel) and TreeModel getSelectionModel() methods.
TreeModelAssociation(java.lang.Object anObject, java.lang.Object aRootLabel)
          Constructor expecting a JTree or similar component and specifying a label for the root node.
 
Method Summary
protected  void addAsListener()
           
 void addTreeModelListener(javax.swing.event.TreeModelListener aListener)
           
static net.wotonomy.foundation.NSArray aspects()
          Returns a List that describes the aspects supported by this class.
static net.wotonomy.foundation.NSArray aspectSignatures()
          Returns a List of aspect signatures whose contents correspond with the aspects list.
static net.wotonomy.foundation.NSArray associationClassesSuperseded()
          Returns a List of EOAssociation subclasses that, for the objects that are usable for this association, are less suitable than this association.
 void bindAspect(java.lang.String anAspect, net.wotonomy.ui.EODisplayGroup aDisplayGroup, java.lang.String aKey)
          Binds the specified aspect of this association to the specified key on the specified display group.
 void breakConnection()
          Breaks the connection between this association and its object.
 boolean canBindAspect(java.lang.String anAspect, net.wotonomy.ui.EODisplayGroup aDisplayGroup, java.lang.String aKey)
          Returns whether this association can bind to the specified display group on the specified key for the specified aspect.
 DisplayGroupNode createNode(net.wotonomy.ui.EODisplayGroup aParentGroup, java.lang.Object anObject)
          Creates and returns a new display group node.
 void establishConnection()
          Establishes a connection between this association and the controlled object.
protected  void fireRootStructureChanged()
           
 void fireTreeNodesChanged(java.lang.Object source, java.lang.Object[] path, int[] childIndices, java.lang.Object[] children)
          Fires a tree nodes changed event to all listeners.
 void fireTreeNodesInserted(java.lang.Object source, java.lang.Object[] path, int[] childIndices, java.lang.Object[] children)
          Fires a tree nodes inserted event to all listeners.
 void fireTreeNodesRemoved(java.lang.Object source, java.lang.Object[] path, int[] childIndices, java.lang.Object[] children)
          Fires a tree nodes removed event to all listeners.
 void fireTreeStructureChanged(java.lang.Object source, java.lang.Object[] path, int[] childIndices, java.lang.Object[] children)
          Fires a tree structure changed event to all listeners.
 java.lang.Object getChild(java.lang.Object parent, int index)
           
 int getChildCount(java.lang.Object parent)
           
 int getIndexOfChild(java.lang.Object parent, java.lang.Object child)
           
 java.lang.Object getNodeForObject(java.lang.Object anObject)
          Returns the first node found that represents the specified object, or null if not found.
 java.lang.Object getObjectForNode(java.lang.Object aNode)
          Returns the object represented by the specified node which must be a display group node from this tree.
 javax.swing.tree.TreePath getPathForNode(java.lang.Object aNode)
          Returns the tree path for the specified node, which must be a display group node from this tree.
 javax.swing.tree.TreePath getPathForObject(java.lang.Object anObject)
          Returns the first tree path for the node that represents the specified object, or null if the object does not exist in this tree.
 javax.swing.tree.TreePath[] getPathsForObject(java.lang.Object anObject)
          Returns the tree path for the node that represents the specified object, or null if the object does not exist in this tree.
 java.lang.Object getRoot()
           
 java.lang.Object getRootLabel()
          Gets the current root label.
 boolean isInsertingAfter()
          Determines where new objects programmatically inserted into the children display group should be inserted, based on the value of insertingChild.
 boolean isInsertingChild()
          Gets whether new objects programmatically inserted into the children display group should be inserted as a child of the first selected node.
 boolean isLeaf(java.lang.Object node)
           
 boolean isSelectionPaintedImmediately()
          Determines whether the selection should be painted immediately after the user clicks and therefore before the children display group is updated.
static boolean isUsableWithObject(java.lang.Object anObject)
          Returns whether this class can control the specified object.
 boolean isVisible(java.lang.Object node)
          Returns whether this node is visible in the UI.
protected  java.lang.Object objectDeletedFromChildrenGroup(java.lang.Object anObject)
          Called to by the children group's data source when it receives a deleteObject message, usually after an object has been deleted from the children display group.
protected  java.lang.Object objectInsertedIntoChildrenGroup(java.lang.Object anObject)
          Called to by the children group's data source when it receives an insertObject message, usually after an object has been inserted into the children display group.
static net.wotonomy.foundation.NSArray objectKeysTaken()
          Returns a List of properties of the controlled object that are controlled by this class.
protected  net.wotonomy.foundation.NSArray objectsFetchedIntoChildrenGroup()
          Called to by the children group's data source to populate it with all selected nodes and their siblings.
 void objectWillChange(java.lang.Object anObject)
          Overridden to better discriminate what is changed.
static java.lang.String primaryAspect()
          Returns the aspect that is considered primary or default.
 void processRecentChanges()
          Tells the children display group to refetch, so that it reflects any changes that were made in the node tree, and then updates the selection in the selection model.
protected  void removeAsListener()
           
 void removeTreeModelListener(javax.swing.event.TreeModelListener aListener)
           
 java.lang.Object rootLabel()
          Gets the current root label.
 void setInsertingAfter(boolean after)
          Determines where new objects programmatically inserted into the children display group should be inserted, based on the value of insertingChild.
 void setInsertingChild(boolean asChild)
          Sets whether new objects programmatically inserted into the children display group should be inserted as a child of the first selected node.
 void setRootLabel(java.lang.Object aLabel)
          Sets the root label.
 void setSelectionPaintedImmediately(boolean isImmediate)
          Sets whether the selection should be painted immediately.
 void subjectChanged()
          Called when either the selection or the contents of an associated display group have changed.
 void valueChanged(javax.swing.event.TreeSelectionEvent e)
           
 void valueForPathChanged(javax.swing.tree.TreePath path, java.lang.Object newValue)
           
 
Methods inherited from class net.wotonomy.ui.EOAssociation
associationClassesForObject, copyMatchingBindingsFromAssociation, displayGroupForAspect, displayGroupKeyForAspect, displayName, endEditing, object, setValueForAspect, setValueForAspectAtIndex, shouldEndEditing, shouldEndEditingAtIndex, valueForAspect, valueForAspectAtIndex
 
Methods inherited from class net.wotonomy.control.EODelayedObserver
discardPendingNotification, observerQueue, priority, update
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

isListening

protected boolean isListening

titlesGroupChanged

protected boolean titlesGroupChanged

childrenGroupChanged

protected boolean childrenGroupChanged
Constructor Detail

TreeModelAssociation

public TreeModelAssociation(java.lang.Object anObject)
Constructor expecting a JTree or any other object that has void setModel(TreeModel) and TreeModel getSelectionModel() methods. This tree association will be used for the TreeModel. The root node will be labeled "Root".

As an alternate way to use a TreeModelAssociation, you may pass a TreeSelectionModel to the constructor and then manually set your component to use this class as its TreeModel.


TreeModelAssociation

public TreeModelAssociation(java.lang.Object anObject,
                            java.lang.Object aRootLabel)
Constructor expecting a JTree or similar component and specifying a label for the root node.

Method Detail

rootLabel

public java.lang.Object rootLabel()
Gets the current root label.


getRootLabel

public java.lang.Object getRootLabel()
Gets the current root label.


setRootLabel

public void setRootLabel(java.lang.Object aLabel)
Sets the root label.


aspectSignatures

public static net.wotonomy.foundation.NSArray aspectSignatures()
Returns a List of aspect signatures whose contents correspond with the aspects list. Each element is a string whose characters represent a capability of the corresponding aspect. An empty signature "" means that the aspect can bind without needing a key. This implementation returns "A1M" for each element in the aspects array.


aspects

public static net.wotonomy.foundation.NSArray aspects()
Returns a List that describes the aspects supported by this class. Each element in the list is the string name of the aspect. This implementation returns an empty list.


associationClassesSuperseded

public static net.wotonomy.foundation.NSArray associationClassesSuperseded()
Returns a List of EOAssociation subclasses that, for the objects that are usable for this association, are less suitable than this association.


isUsableWithObject

public static boolean isUsableWithObject(java.lang.Object anObject)
Returns whether this class can control the specified object.


objectKeysTaken

public static net.wotonomy.foundation.NSArray objectKeysTaken()
Returns a List of properties of the controlled object that are controlled by this class. For example, "stringValue", or "selected".


primaryAspect

public static java.lang.String primaryAspect()
Returns the aspect that is considered primary or default. This is typically "value" or somesuch.


canBindAspect

public boolean canBindAspect(java.lang.String anAspect,
                             net.wotonomy.ui.EODisplayGroup aDisplayGroup,
                             java.lang.String aKey)
Returns whether this association can bind to the specified display group on the specified key for the specified aspect.

Overrides:
canBindAspect in class net.wotonomy.ui.EOAssociation

bindAspect

public void bindAspect(java.lang.String anAspect,
                       net.wotonomy.ui.EODisplayGroup aDisplayGroup,
                       java.lang.String aKey)
Binds the specified aspect of this association to the specified key on the specified display group.

Overrides:
bindAspect in class net.wotonomy.ui.EOAssociation

establishConnection

public void establishConnection()
Establishes a connection between this association and the controlled object. Subclasses should begin listening for events from their controlled object here.

Overrides:
establishConnection in class net.wotonomy.ui.EOAssociation

fireRootStructureChanged

protected void fireRootStructureChanged()

breakConnection

public void breakConnection()
Breaks the connection between this association and its object. Override to stop listening for events from the object.

Overrides:
breakConnection in class net.wotonomy.ui.EOAssociation

addAsListener

protected void addAsListener()

removeAsListener

protected void removeAsListener()

objectWillChange

public void objectWillChange(java.lang.Object anObject)
Overridden to better discriminate what is changed.

Specified by:
objectWillChange in interface net.wotonomy.control.EOObserving
Overrides:
objectWillChange in class net.wotonomy.control.EODelayedObserver

subjectChanged

public void subjectChanged()
Called when either the selection or the contents of an associated display group have changed.

Overrides:
subjectChanged in class net.wotonomy.ui.EOAssociation

getNodeForObject

public java.lang.Object getNodeForObject(java.lang.Object anObject)
Returns the first node found that represents the specified object, or null if not found. This implementation simply calls getPathForObject.


getObjectForNode

public java.lang.Object getObjectForNode(java.lang.Object aNode)
Returns the object represented by the specified node which must be a display group node from this tree.


getPathForNode

public javax.swing.tree.TreePath getPathForNode(java.lang.Object aNode)
Returns the tree path for the specified node, which must be a display group node from this tree.


getPathForObject

public javax.swing.tree.TreePath getPathForObject(java.lang.Object anObject)
Returns the first tree path for the node that represents the specified object, or null if the object does not exist in this tree. This implementation does a breadth-first search of the tree for the object, looking only at nodes that have been loaded. This means that if the object does not exist in the tree, the entire tree must be traversed.


getPathsForObject

public javax.swing.tree.TreePath[] getPathsForObject(java.lang.Object anObject)
Returns the tree path for the node that represents the specified object, or null if the object does not exist in this tree. This implementation does a breadth-first search of the tree for the object, looking only at nodes that have been loaded. This means that the entire tree is traversed.


valueChanged

public void valueChanged(javax.swing.event.TreeSelectionEvent e)
Specified by:
valueChanged in interface javax.swing.event.TreeSelectionListener

isSelectionPaintedImmediately

public boolean isSelectionPaintedImmediately()
Determines whether the selection should be painted immediately after the user clicks and therefore before the children display group is updated. When the children group is bound to many associations or is bound to a master-detail association, updating the display group can take a perceptibly long time. This property defaults to false.

See Also:
setSelectionPaintedImmediately(boolean)

setSelectionPaintedImmediately

public void setSelectionPaintedImmediately(boolean isImmediate)
Sets whether the selection should be painted immediately. Setting this property to true will let the tree paint first before the display group is updated. This means that any tree selection listers will also be notified before the display group is updated and will have to invokeLater if they want to see the updated display group.


getRoot

public java.lang.Object getRoot()
Specified by:
getRoot in interface javax.swing.tree.TreeModel

getChild

public java.lang.Object getChild(java.lang.Object parent,
                                 int index)
Specified by:
getChild in interface javax.swing.tree.TreeModel

getChildCount

public int getChildCount(java.lang.Object parent)
Specified by:
getChildCount in interface javax.swing.tree.TreeModel

isLeaf

public boolean isLeaf(java.lang.Object node)
Specified by:
isLeaf in interface javax.swing.tree.TreeModel

isVisible

public boolean isVisible(java.lang.Object node)
Returns whether this node is visible in the UI. This implementation returns true.

Subclasses should return false if they can determine that the node is not displayed or expanded or otherwise visible. Non-visible nodes will fetch only when they are shown.


valueForPathChanged

public void valueForPathChanged(javax.swing.tree.TreePath path,
                                java.lang.Object newValue)
Specified by:
valueForPathChanged in interface javax.swing.tree.TreeModel

getIndexOfChild

public int getIndexOfChild(java.lang.Object parent,
                           java.lang.Object child)
Specified by:
getIndexOfChild in interface javax.swing.tree.TreeModel

addTreeModelListener

public void addTreeModelListener(javax.swing.event.TreeModelListener aListener)
Specified by:
addTreeModelListener in interface javax.swing.tree.TreeModel

removeTreeModelListener

public void removeTreeModelListener(javax.swing.event.TreeModelListener aListener)
Specified by:
removeTreeModelListener in interface javax.swing.tree.TreeModel

fireTreeNodesChanged

public void fireTreeNodesChanged(java.lang.Object source,
                                 java.lang.Object[] path,
                                 int[] childIndices,
                                 java.lang.Object[] children)
Fires a tree nodes changed event to all listeners. Provided as a convenience if you need to make manual changes to the tree model.


fireTreeNodesInserted

public void fireTreeNodesInserted(java.lang.Object source,
                                  java.lang.Object[] path,
                                  int[] childIndices,
                                  java.lang.Object[] children)
Fires a tree nodes inserted event to all listeners. Provided as a convenience if you need to make manual changes to the tree model.


fireTreeNodesRemoved

public void fireTreeNodesRemoved(java.lang.Object source,
                                 java.lang.Object[] path,
                                 int[] childIndices,
                                 java.lang.Object[] children)
Fires a tree nodes removed event to all listeners. Provided as a convenience if you need to make manual changes to the tree model.


fireTreeStructureChanged

public void fireTreeStructureChanged(java.lang.Object source,
                                     java.lang.Object[] path,
                                     int[] childIndices,
                                     java.lang.Object[] children)
Fires a tree structure changed event to all listeners. Provided as a convenience if you need to make manual changes to the tree model.


createNode

public DisplayGroupNode createNode(net.wotonomy.ui.EODisplayGroup aParentGroup,
                                   java.lang.Object anObject)
Creates and returns a new display group node.


isInsertingChild

public boolean isInsertingChild()
Gets whether new objects programmatically inserted into the children display group should be inserted as a child of the first selected node. If false, new objects are inserted as siblings of the first selected node. Default value is true.


setInsertingChild

public void setInsertingChild(boolean asChild)
Sets whether new objects programmatically inserted into the children display group should be inserted as a child of the first selected node. If false, new objects are inserted as siblings of the first selected node. Default value is true.


isInsertingAfter

public boolean isInsertingAfter()
Determines where new objects programmatically inserted into the children display group should be inserted, based on the value of insertingChild. If insertingChild, isInsertingAfter causes objects to be inserted at the end of the selected node's child list; otherwise, objects are inserted at the beginning of the list. If inserting as a sibling, isInsertingAfter causes objects to be inserted before the selected node in the selected node's parent's child list; otherwise, objects are inserted after the selected node in the child list. Default value is true.


setInsertingAfter

public void setInsertingAfter(boolean after)
Determines where new objects programmatically inserted into the children display group should be inserted, based on the value of insertingChild. If insertingChild, isInsertingAfter causes objects to be inserted at the end of the selected node's child list; otherwise, objects are inserted at the beginning of the list. If inserting as a sibling, isInsertingAfter causes objects to be inserted before the selected node in the selected node's parent's child list; otherwise, objects are inserted after the selected node in the child list. Default value is true.


objectInsertedIntoChildrenGroup

protected java.lang.Object objectInsertedIntoChildrenGroup(java.lang.Object anObject)
Called to by the children group's data source when it receives an insertObject message, usually after an object has been inserted into the children display group. Return the object that should be passed to the titles display group's data source's implementation of insertObject, or return null to prevent that method from being called.

This implementation inserts the specified object into the tree as determined by calling isInsertingChild and isInsertingAfter, then returns the unmodified object. If there's no selection, or no selection model, the root node is assumed to be selected. And if the root node is selected, the new node will obviously be inserted as a child. Override to customize.


objectDeletedFromChildrenGroup

protected java.lang.Object objectDeletedFromChildrenGroup(java.lang.Object anObject)
Called to by the children group's data source when it receives a deleteObject message, usually after an object has been deleted from the children display group. Return the object that should be passed to the titles display group's data source's implementation of deleteObject, or return null to prevent that method from being called.

This implementation deletes all instances of the selected object from the tree nodes that are currently loaded, and returns the unmodified object. Override to customize.


objectsFetchedIntoChildrenGroup

protected net.wotonomy.foundation.NSArray objectsFetchedIntoChildrenGroup()
Called to by the children group's data source to populate it with all selected nodes and their siblings. To customize, override this method, or specify a different data source for the children display group.


processRecentChanges

public void processRecentChanges()
Tells the children display group to refetch, so that it reflects any changes that were made in the node tree, and then updates the selection in the selection model. Triggered in response to willChange().



Copyright © 2006 null. All Rights Reserved.