summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
commit40a9d99496e098562f090fb7ffce9e749011b131 (patch)
tree437df24d65470582e943e494a52db8ed65a881ae /projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java
parentff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff)
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java')
-rw-r--r--projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java2452
1 files changed, 1094 insertions, 1358 deletions
diff --git a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java
index 1756285..d530f36 100644
--- a/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java
+++ b/projects/net.wotonomy.ui.swing/src/main/java/net/wotonomy/ui/swing/DisplayGroupNode.java
@@ -46,901 +46,727 @@ import net.wotonomy.ui.EODisplayGroup;
import net.wotonomy.ui.swing.TreeModelAssociation.DelegatingTreeDataSource;
/**
-* DisplayGroupNodes are used as nodes in the
-* TreeModelAssociation's implementation of TreeModel,
-* and is tightly coupled with TreeModelAssociation
-* and MasterDetailAssociation. <br><br>
-*
-* Even though it is no longer package access,
-* don't rely on this class because we want to
-* have the option of completely replacing this
-* approach in the future.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
- abstract public class DisplayGroupNode
- extends EODisplayGroup
- {
- protected TreeModelAssociation parentAssociation;
- protected EODelayedObserver targetObserver;
- protected NSMutableDictionary childNodes;
- protected EODisplayGroup parentGroup;
- protected Object target;
- protected boolean isFetched;
- protected boolean isFetchNeeded;
- protected boolean useParentOrderings;
- protected boolean useParentQualifier;
-
- /**
- * Constructor for all nodes.
- * Root node must have a null target.
- */
- public DisplayGroupNode(
- TreeModelAssociation aParentAssociation,
- EODisplayGroup aParentGroup,
- Object aTarget )
- {
+ * DisplayGroupNodes are used as nodes in the TreeModelAssociation's
+ * implementation of TreeModel, and is tightly coupled with TreeModelAssociation
+ * and MasterDetailAssociation. <br>
+ * <br>
+ *
+ * Even though it is no longer package access, don't rely on this class because
+ * we want to have the option of completely replacing this approach in the
+ * future.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+abstract public class DisplayGroupNode extends EODisplayGroup {
+ protected TreeModelAssociation parentAssociation;
+ protected EODelayedObserver targetObserver;
+ protected NSMutableDictionary childNodes;
+ protected EODisplayGroup parentGroup;
+ protected Object target;
+ protected boolean isFetched;
+ protected boolean isFetchNeeded;
+ protected boolean useParentOrderings;
+ protected boolean useParentQualifier;
+
+ /**
+ * Constructor for all nodes. Root node must have a null target.
+ */
+ public DisplayGroupNode(TreeModelAssociation aParentAssociation, EODisplayGroup aParentGroup, Object aTarget) {
//new net.wotonomy.ui.swing.util.StackTraceInspector( ""+aTarget );
//System.out.println( "DisplayGroupNode.new: " + aTarget );
- parentAssociation = aParentAssociation;
- target = null;
- targetObserver = null;
- parentGroup = aParentGroup;
- childNodes = new NSMutableDictionary();
- isFetched = false;
- isFetchNeeded = false;
- useParentOrderings = true;
- useParentQualifier = true;
-
- EODataSource parentSource = null;
- if ( parentGroup != null )
- {
- parentSource = parentGroup.dataSource();
- }
- else
- if ( parentAssociation.titlesDisplayGroup != null )
- {
- parentSource = parentAssociation.titlesDisplayGroup.dataSource();
- }
-
- // create child datasource
- if ( aTarget != null ) // not root node
- {
- if ( parentAssociation.childrenKey != null )
- {
- if ( parentSource == null )
- {
- throw new WotonomyException(
- "Need a data source when children aspect is bound." );
- }
-
- NSArray displayedObjects = parentGroup.displayedObjects();
- EODataSource childSource = parentSource.dataSourceQualifiedByKey(
- parentAssociation.childrenKey );
- childSource.qualifyWithRelationshipKey(
- parentAssociation.childrenKey, aTarget );
-
- // create new display group using child data source
- this.setDataSource( childSource );
-
- // establish observer for target object
- setTarget( aTarget );
- }
- else // only titles is bound
- {
- // establish observer for target object
- setTarget( aTarget );
-
- setDataSource( new PropertyDataSource()
- {
- public NSArray fetchObjects()
- {
- return new NSArray();
- }
- } );
- }
- }
- else // else root node
- {
- // root node uses PropertyDataSource by default
- if ( parentSource == null )
- {
- setDataSource( new PropertyDataSource()
- {
- public NSArray fetchObjects()
- {
- if ( parentGroup != null )
- {
- return parentGroup.displayedObjects();
- }
- return null;
- }
- } );
- }
- else
- {
- // root node uses parent source directly
- setDataSource( parentSource );
- }
- }
- }
-
- /**
- * Overridden to unregister as an editor of the editing context,
- * since we don't directly present a user interface.
- */
- public void setDataSource ( EODataSource aDataSource )
- {
- super.setDataSource( aDataSource );
- if ( ( aDataSource != null )
- && ( aDataSource.editingContext() != null ) )
- {
- aDataSource.editingContext().removeEditor( this );
- }
- }
-
- /**
- * Returns whether the node should call fetch().
- */
- protected boolean isFetched()
- {
- if ( isFetchNeeded() )
- {
- setFetchNeeded( false );
- fetch();
- }
- return isFetched;
- }
-
- /**
- * Sets whether the node should call fetch().
- */
- protected void setFetched( boolean fetched )
- {
+ parentAssociation = aParentAssociation;
+ target = null;
+ targetObserver = null;
+ parentGroup = aParentGroup;
+ childNodes = new NSMutableDictionary();
+ isFetched = false;
+ isFetchNeeded = false;
+ useParentOrderings = true;
+ useParentQualifier = true;
+
+ EODataSource parentSource = null;
+ if (parentGroup != null) {
+ parentSource = parentGroup.dataSource();
+ } else if (parentAssociation.titlesDisplayGroup != null) {
+ parentSource = parentAssociation.titlesDisplayGroup.dataSource();
+ }
+
+ // create child datasource
+ if (aTarget != null) // not root node
+ {
+ if (parentAssociation.childrenKey != null) {
+ if (parentSource == null) {
+ throw new WotonomyException("Need a data source when children aspect is bound.");
+ }
+
+ NSArray displayedObjects = parentGroup.displayedObjects();
+ EODataSource childSource = parentSource.dataSourceQualifiedByKey(parentAssociation.childrenKey);
+ childSource.qualifyWithRelationshipKey(parentAssociation.childrenKey, aTarget);
+
+ // create new display group using child data source
+ this.setDataSource(childSource);
+
+ // establish observer for target object
+ setTarget(aTarget);
+ } else // only titles is bound
+ {
+ // establish observer for target object
+ setTarget(aTarget);
+
+ setDataSource(new PropertyDataSource() {
+ public NSArray fetchObjects() {
+ return new NSArray();
+ }
+ });
+ }
+ } else // else root node
+ {
+ // root node uses PropertyDataSource by default
+ if (parentSource == null) {
+ setDataSource(new PropertyDataSource() {
+ public NSArray fetchObjects() {
+ if (parentGroup != null) {
+ return parentGroup.displayedObjects();
+ }
+ return null;
+ }
+ });
+ } else {
+ // root node uses parent source directly
+ setDataSource(parentSource);
+ }
+ }
+ }
+
+ /**
+ * Overridden to unregister as an editor of the editing context, since we don't
+ * directly present a user interface.
+ */
+ public void setDataSource(EODataSource aDataSource) {
+ super.setDataSource(aDataSource);
+ if ((aDataSource != null) && (aDataSource.editingContext() != null)) {
+ aDataSource.editingContext().removeEditor(this);
+ }
+ }
+
+ /**
+ * Returns whether the node should call fetch().
+ */
+ protected boolean isFetched() {
+ if (isFetchNeeded()) {
+ setFetchNeeded(false);
+ fetch();
+ }
+ return isFetched;
+ }
+
+ /**
+ * Sets whether the node should call fetch().
+ */
+ protected void setFetched(boolean fetched) {
//System.out.println( "DisplayGroupNode.setFetched: " + fetched + " : " + this + " : " + target );
//net.wotonomy.ui.swing.util.StackTraceInspector.printShortStackTrace();
- isFetched = fetched;
- }
-
- /**
- * Returns whether the node is in need of a refetch.
- */
- protected boolean isFetchNeeded()
- {
- return isFetchNeeded;
- }
-
- /**
- * Returns whether the node should call fetch().
- */
- protected void setFetchNeeded( boolean fetchNeeded )
- {
+ isFetched = fetched;
+ }
+
+ /**
+ * Returns whether the node is in need of a refetch.
+ */
+ protected boolean isFetchNeeded() {
+ return isFetchNeeded;
+ }
+
+ /**
+ * Returns whether the node should call fetch().
+ */
+ protected void setFetchNeeded(boolean fetchNeeded) {
//System.out.println( "DisplayGroupNode.setFetchNeeded: " + fetchNeeded + " : " + this + " : " + target );
//net.wotonomy.ui.swing.util.StackTraceInspector.printShortStackTrace();
- isFetchNeeded = fetchNeeded;
- }
-
- /**
- * Subclasses should override this method to fire an appropriate insertion event.
- */
- protected void fireNodesInserted( Object[] path, int[] indexes, Object[] objects )
- {
+ isFetchNeeded = fetchNeeded;
+ }
+
+ /**
+ * Subclasses should override this method to fire an appropriate insertion
+ * event.
+ */
+ protected void fireNodesInserted(Object[] path, int[] indexes, Object[] objects) {
//System.out.println( "fireNodesInserted: " + this );
- parentAssociation.fireTreeNodesInserted(
- this, path, indexes, objects );
- }
-
- /**
- * Subclasses should override this method to fire an appropriate change event.
- */
- protected void fireNodesChanged( Object[] path, int[] indexes, Object[] objects )
- {
+ parentAssociation.fireTreeNodesInserted(this, path, indexes, objects);
+ }
+
+ /**
+ * Subclasses should override this method to fire an appropriate change event.
+ */
+ protected void fireNodesChanged(Object[] path, int[] indexes, Object[] objects) {
//System.out.println( "fireNodesChanged: " + this );
- parentAssociation.fireTreeNodesChanged(
- this, path, indexes, objects );
- }
-
- /**
- * Subclasses should override this method to fire an appropriate deletion event.
- */
- protected void fireNodesRemoved( Object[] path, int[] indexes, Object[] objects )
- {
+ parentAssociation.fireTreeNodesChanged(this, path, indexes, objects);
+ }
+
+ /**
+ * Subclasses should override this method to fire an appropriate deletion event.
+ */
+ protected void fireNodesRemoved(Object[] path, int[] indexes, Object[] objects) {
//System.out.println( "fireNodesRemoved: " + this );
- parentAssociation.fireTreeNodesRemoved(
- this, path, indexes, objects );
- }
-
- /**
- * Subclasses should override this method to fire an appropriate event.
- */
- protected void fireStructureChanged( Object[] path, int[] indexes, Object[] objects )
- {
- parentAssociation.fireTreeStructureChanged(
- this, path, indexes, objects );
- }
-
- /**
- * Overridden to broadcast a tree event after super executes.
- */
- public void insertObjectAtIndex ( Object anObject, int anIndex )
- {
- int count = getChildCount(); // gets old count
- if ( target == null )
- {
- // if root node, forward to parent:
- // circumventing delegating data source, if any
- EODataSource dataSource = parentGroup.dataSource();
- if ( dataSource instanceof DelegatingTreeDataSource )
- {
- parentGroup.setDataSource(
- ((DelegatingTreeDataSource)dataSource).delegateDataSource );
- }
- parentGroup.insertObjectAtIndex( anObject, anIndex );
- if ( dataSource instanceof DelegatingTreeDataSource )
- {
- parentGroup.setDataSource( dataSource );
- }
- return; // prevent event from firing (?)
- }
- else // not root node
- {
- super.insertObjectAtIndex( anObject, anIndex );
- }
- }
-
- /**
- * Overridden to broadcast a tree event after super executes.
- */
- public boolean deleteObjectAtIndex ( int anIndex )
- {
- boolean result;
- Object node = getChildNodeAt( anIndex );
- if ( target == null )
- {
- // if root node, forward to parent:
- result = parentGroup.deleteObjectAtIndex( anIndex );
- }
- else // not root node
- {
- result = super.deleteObjectAtIndex( anIndex );
- }
-
- return result;
- }
-
- /**
- * Returns the child node that corresponds to the
- * specified index, creating it if necessary.
- * The index must be within bounds or an exception
- * is thrown.
- */
- public DisplayGroupNode getChildNodeAt( int anIndex )
- {
- boolean wasFetched = isFetched();
- if ( ! wasFetched ) fetch();
- Object o = displayedObjects.objectAtIndex( anIndex );
- DisplayGroupNode result = getChildNodeForObject( o );
- if ( result == null )
- {
- result = createChildNodeForObject( o );
- }
- return result;
- }
-
- /**
- * Returns a child node that corresponds to the
- * specified object, returning null if not found.
- */
- protected DisplayGroupNode getChildNodeForObject( Object anObject )
- {
- return (DisplayGroupNode)
- childNodes.objectForKey( new ReferenceKey( anObject ) );
- }
-
- /**
- * Creates a child node that corresponds to the
- * specified object.
- */
- private DisplayGroupNode createChildNodeForObject( Object anObject )
- {
- DisplayGroupNode result = parentAssociation.createNode( this, anObject );
- childNodes.setObjectForKey( result, new ReferenceKey( anObject ) );
- return result;
- }
-
- /**
- * Returns a tree path of all DisplayGroupNodes leading
- * to this node, including the root node (but excluding the
- * titles display group).
- */
- public TreePath treePath()
- {
- List path = new LinkedList();
- EODisplayGroup node = this;
- while ( node instanceof DisplayGroupNode )
- {
- // insert at head of list
- path.add( 0, node );
- node = ((DisplayGroupNode)node).parentGroup;
- }
- return new TreePath( path.toArray() );
- }
-
- /**
- * Overridden to return the parent group's
- * sort ordering if useParentOrderings is true.
- * useParentOrderings is true by default.
- */
- public NSArray sortOrderings()
- {
- if ( ( useParentOrderings )
- && ( parentGroup != null ) )
- {
- return parentGroup.sortOrderings();
- }
- return super.sortOrderings();
- }
-
- /**
- * Overridden to set useParentOrderings to false,
- * or true if aList is null.
- */
- public void setSortOrderings ( List aList )
- {
- if ( aList == null )
- {
- useParentOrderings = true;
- }
- else
- {
- useParentOrderings = false;
- super.setSortOrderings( aList );
- }
- }
-
- /**
- * Overridden to return the parent group's
- * qualifier if useParentQualifier is true.
- * useParentQualifier is true by default.
- */
- public EOQualifier qualifier()
- {
- if ( ( useParentQualifier )
- && ( parentGroup != null ) )
- {
- return parentGroup.qualifier();
- }
- return super.qualifier();
- }
-
- /**
- * Overridden to set useParentQualifier to false,
- * or true if aList is null.
- */
- public void setQualifier ( EOQualifier aQualifier )
- {
- if ( aQualifier == null )
- {
- useParentQualifier = true;
- }
- else
- {
- useParentQualifier = false;
- super.setQualifier( aQualifier );
- }
- }
-
- /**
- * Overridden to set isFetched to true.
- */
- public boolean fetch()
- {
+ parentAssociation.fireTreeNodesRemoved(this, path, indexes, objects);
+ }
+
+ /**
+ * Subclasses should override this method to fire an appropriate event.
+ */
+ protected void fireStructureChanged(Object[] path, int[] indexes, Object[] objects) {
+ parentAssociation.fireTreeStructureChanged(this, path, indexes, objects);
+ }
+
+ /**
+ * Overridden to broadcast a tree event after super executes.
+ */
+ public void insertObjectAtIndex(Object anObject, int anIndex) {
+ int count = getChildCount(); // gets old count
+ if (target == null) {
+ // if root node, forward to parent:
+ // circumventing delegating data source, if any
+ EODataSource dataSource = parentGroup.dataSource();
+ if (dataSource instanceof DelegatingTreeDataSource) {
+ parentGroup.setDataSource(((DelegatingTreeDataSource) dataSource).delegateDataSource);
+ }
+ parentGroup.insertObjectAtIndex(anObject, anIndex);
+ if (dataSource instanceof DelegatingTreeDataSource) {
+ parentGroup.setDataSource(dataSource);
+ }
+ return; // prevent event from firing (?)
+ } else // not root node
+ {
+ super.insertObjectAtIndex(anObject, anIndex);
+ }
+ }
+
+ /**
+ * Overridden to broadcast a tree event after super executes.
+ */
+ public boolean deleteObjectAtIndex(int anIndex) {
+ boolean result;
+ Object node = getChildNodeAt(anIndex);
+ if (target == null) {
+ // if root node, forward to parent:
+ result = parentGroup.deleteObjectAtIndex(anIndex);
+ } else // not root node
+ {
+ result = super.deleteObjectAtIndex(anIndex);
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the child node that corresponds to the specified index, creating it
+ * if necessary. The index must be within bounds or an exception is thrown.
+ */
+ public DisplayGroupNode getChildNodeAt(int anIndex) {
+ boolean wasFetched = isFetched();
+ if (!wasFetched)
+ fetch();
+ Object o = displayedObjects.objectAtIndex(anIndex);
+ DisplayGroupNode result = getChildNodeForObject(o);
+ if (result == null) {
+ result = createChildNodeForObject(o);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a child node that corresponds to the specified object, returning null
+ * if not found.
+ */
+ protected DisplayGroupNode getChildNodeForObject(Object anObject) {
+ return (DisplayGroupNode) childNodes.objectForKey(new ReferenceKey(anObject));
+ }
+
+ /**
+ * Creates a child node that corresponds to the specified object.
+ */
+ private DisplayGroupNode createChildNodeForObject(Object anObject) {
+ DisplayGroupNode result = parentAssociation.createNode(this, anObject);
+ childNodes.setObjectForKey(result, new ReferenceKey(anObject));
+ return result;
+ }
+
+ /**
+ * Returns a tree path of all DisplayGroupNodes leading to this node, including
+ * the root node (but excluding the titles display group).
+ */
+ public TreePath treePath() {
+ List path = new LinkedList();
+ EODisplayGroup node = this;
+ while (node instanceof DisplayGroupNode) {
+ // insert at head of list
+ path.add(0, node);
+ node = ((DisplayGroupNode) node).parentGroup;
+ }
+ return new TreePath(path.toArray());
+ }
+
+ /**
+ * Overridden to return the parent group's sort ordering if useParentOrderings
+ * is true. useParentOrderings is true by default.
+ */
+ public NSArray sortOrderings() {
+ if ((useParentOrderings) && (parentGroup != null)) {
+ return parentGroup.sortOrderings();
+ }
+ return super.sortOrderings();
+ }
+
+ /**
+ * Overridden to set useParentOrderings to false, or true if aList is null.
+ */
+ public void setSortOrderings(List aList) {
+ if (aList == null) {
+ useParentOrderings = true;
+ } else {
+ useParentOrderings = false;
+ super.setSortOrderings(aList);
+ }
+ }
+
+ /**
+ * Overridden to return the parent group's qualifier if useParentQualifier is
+ * true. useParentQualifier is true by default.
+ */
+ public EOQualifier qualifier() {
+ if ((useParentQualifier) && (parentGroup != null)) {
+ return parentGroup.qualifier();
+ }
+ return super.qualifier();
+ }
+
+ /**
+ * Overridden to set useParentQualifier to false, or true if aList is null.
+ */
+ public void setQualifier(EOQualifier aQualifier) {
+ if (aQualifier == null) {
+ useParentQualifier = true;
+ } else {
+ useParentQualifier = false;
+ super.setQualifier(aQualifier);
+ }
+ }
+
+ /**
+ * Overridden to set isFetched to true.
+ */
+ public boolean fetch() {
//System.out.println( "DisplayGroupNode.fetch: " + this + " : " );
//if ( getClass().getName().indexOf( "Activity" ) != -1 )
//{
// new net.wotonomy.ui.swing.util.StackTraceInspector( this.toString() );
//}
- // set flag
- setFetched( true );
+ // set flag
+ setFetched(true);
- // skip root node
- if ( target == null ) return true;
+ // skip root node
+ if (target == null)
+ return true;
- // requalify
- dataSource().qualifyWithRelationshipKey(
- parentAssociation.childrenKey, target );
+ // requalify
+ dataSource().qualifyWithRelationshipKey(parentAssociation.childrenKey, target);
- // call to super
- return super.fetch();
+ // call to super
+ return super.fetch();
//boolean result = super.fetch();
//System.out.println( displayedObjects() );
//return result;
- }
-
- /**
- * Returns the object at the appropriate index
- * in the parent display group.
- */
- public Object object()
- {
- // if root node
- if ( target == null )
- {
- return parentAssociation.rootLabel();
- }
- return target;
- }
-
- /**
- * Returns the string value of the title property
- * on the object in the parent display group corresponding
- * to this index. The tree renderer asks JTrees to
- * call this method to retrieve a value for display.
- */
- public String toString()
- {
- Object result = getUserObject();
- if ( result == null ) result = "[null]";
- return result.toString();
- }
-
- // parts of interface TreeNode
-
- public int getChildCount()
- {
- if ( ! isFetched() ) fetch();
+ }
+
+ /**
+ * Returns the object at the appropriate index in the parent display group.
+ */
+ public Object object() {
+ // if root node
+ if (target == null) {
+ return parentAssociation.rootLabel();
+ }
+ return target;
+ }
+
+ /**
+ * Returns the string value of the title property on the object in the parent
+ * display group corresponding to this index. The tree renderer asks JTrees to
+ * call this method to retrieve a value for display.
+ */
+ public String toString() {
+ Object result = getUserObject();
+ if (result == null)
+ result = "[null]";
+ return result.toString();
+ }
+
+ // parts of interface TreeNode
+
+ public int getChildCount() {
+ if (!isFetched())
+ fetch();
//if ( toString().indexOf("154.16406")!=-1){
//System.out.println( "getChildCount: " + displayedObjects.count() + " : " + this );
//new RuntimeException().printStackTrace();
//net.wotonomy.ui.swing.util.StackTraceInspector.printShortStackTrace();
//}
- return displayedObjects.count();
- }
-
- public int getIndex(DisplayGroupNode node)
- {
- if ( ! isFetched() ) fetch();
- return displayedObjects.indexOfObject(
- ((DisplayGroupNode)node).target );
- }
-
- public boolean getAllowsChildren()
- {
- return true;
- }
-
- public boolean isLeaf()
- {
- // if not root node and isLeaf aspect is bound
- if ( ( target != null )
- && ( parentGroup != null )
- && ( parentAssociation.leafKey != null ) )
- {
- Object value;
- if ( parentAssociation.leafDisplayGroup != null )
- {
- value = parentGroup.valueForObject(
- target, parentAssociation.leafKey );
- }
- else
- {
- value = parentAssociation.leafKey;
- }
-
- // getBoolean returns true for zero, among other things
- Object result = ValueConverter.getBoolean( value );
- if ( result != null )
- {
- return ((Boolean)result).booleanValue();
- }
- }
-
- // otherwise, we have to fetch and return count
- return ( getChildCount() == 0 );
- }
-
- public Enumeration children()
- {
- int count = getChildCount();
- Vector v = new Vector();
- for ( int i = 0; i < count; i++ )
- {
- v.add( getChildNodeAt( i ) );
- }
- return v.elements();
- }
-
- // parts of interface MutableTreeNode
-
- public void insert(DisplayGroupNode aChild, int anIndex)
- {
- insertObjectAtIndex(
- ((DisplayGroupNode)aChild).object(), anIndex );
- }
-
- public void remove(int index)
- {
- deleteObjectAtIndex( index );
- }
-
- /**
- * Removes the node at the index corresponding
- * to the index of the object.
- */
- public void remove(DisplayGroupNode node)
- {
- remove( getIndex( node ) );
- }
-
- /**
- * Removes our object from the parent display group.
- */
- public void removeFromParent()
- {
- int index = parentGroup.displayedObjects().indexOfIdenticalObject( target );
- if ( index != NSArray.NotFound )
- {
- parentGroup.deleteObjectAtIndex( index );
- }
- else
- {
- throw new WotonomyException(
- "Object not found in parent group: " + target );
- }
- }
-
- /**
- * Removes our object from the parent display group
- * and adds it to the end of the specified node's children.
- */
- public void setParent(DisplayGroupNode newParent)
- {
- removeFromParent();
- newParent.insertObjectAtIndex(
- object(), newParent.displayedObjects.size() );
- }
-
- /**
- * Returns the value of the displayed property in the parent display group
- * at the index that corresponds to the index of this node.
- */
- public Object getUserObject()
- {
- return valueForKey( parentAssociation.titlesKey );
- }
-
- /**
- * Sets the value of the displayed property in the parent display group
- * at the index that corresponds to the index of this node.
- */
- public void setUserObject( Object aValue )
- {
- setValueForKey( aValue, parentAssociation.titlesKey );
- }
-
- /**
- * Returns a value from the object in the parent display group
- * at the index that corresponds to the index of this node.
- * For the root node, if the titles key is specified, the root
- * label is returned, otherwise null is returned.
- */
- public Object valueForKey( String aKey )
- {
- // if root node
- if ( target == null )
- {
- // compare by ref is okay for strings
- if ( aKey == parentAssociation.titlesKey )
- {
- return parentAssociation.rootLabel();
- }
- return null;
- }
- return parentGroup.valueForObject( target, aKey );
- }
-
- /**
- * Sets a value on the object in the parent display group
- * at the index that corresponds to the index of this node.
- * For the root node, this method only works if aKey is the
- * titlesAspect's key, otherwise does nothing.
- */
- public void setValueForKey(Object aValue, String aKey)
- {
- // if root node, return.
- if ( target == null )
- {
- // compare by ref is okay for strings
- if ( aKey == parentAssociation.titlesKey )
- {
- parentAssociation.setRootLabel( aValue );
-
- // how to handle root node? tree event docs don't say.
- fireNodesChanged ( treePath().getPath(),
- new int[] { 0 },
- new Object[] { this } );
- }
- return;
- }
-
- parentGroup.setValueForObject(
- aValue, target, aKey );
- }
-
- /**
- * Perform any clean up in this method.
- * The node will not be reused after this method is called.
- * This implementation removes itself from the parent's
- * set of child nodes, sets target and datasource to null,
- * and then calls disposeChildNodes().
- */
- protected void dispose()
- { //System.out.println( "dispose: " + this.getClass().getName() + " : " + this );
- if ( parentGroup != null )
- {
- ((DisplayGroupNode)parentGroup).childNodes.remove(
- new ReferenceKey( target ) );
- }
- setTarget( (Object) null );
- setDataSource( null );
- disposeChildNodes();
- }
-
- /**
- * Calls dispose() on all child nodes.
- */
- protected void disposeChildNodes()
- {
- Iterator i = new LinkedList(childNodes.values()).iterator();
- while ( i.hasNext() )
- {
- ((DisplayGroupNode) i.next()).dispose();
- }
- }
-
- /**
- * Called after the target object posts a change notification.
- * This implementation re-fetches which triggers
- * updateDisplayedObjects to broadcast any tree events.
- * This method marks the parent object as changed if:
- * (1) this object is not registered in the editing context
- * of the titles display group's data source (if any), AND
- * (2) the children key is not in the list of attributes
- * of the parent object's EOClassDescription.
- */
- public void targetChanged()
- {
- // if not root node
- if ( target != null )
- {
- // if we're not root and not fetched, stop here.
- //FIXME: with this, some nodes have old values when moved.
- //FIXME: without this, nodes are unnecessarily fetched.
- //FIXME: might have parent modify isFetched of certain child nodes.
- if ( isFetched() )
- {
- fetch();
- }
- else // not fetched - just update the display
- {
- updateDisplayedObjects();
- }
-/*
-//disabling this for performance reasons:
-//might reenable later or find an alternate approach
- // check to see if we need to mark the parent object as changed
- EOEditingContext context = dataSource().editingContext();
- if ( ( context == null )
- || ( context.globalIDForObject( target ) == null ) )
- {
- DisplayGroupNode parentNode = (DisplayGroupNode) parentGroup;
- if ( parentNode.target != null )
- {
- // only notify if childrenKey is an attribute of parentDesc
- // (and therefore not a toOne or toMany relationship)
- EOClassDescription parentDesc =
- EOClassDescription.classDescriptionForClass(
- parentNode.target.getClass() );
- if ( parentDesc.attributeKeys().contains( parentAssociation.childrenKey ) )
- {
- // only notify if no context is already observing the object
- // and we are an attribute key
- EOObserverCenter.notifyObserversObjectWillChange( parentNode.target );
- }
- }
- }
-*/
- }
- else // root node
- {
- setObjectArray( parentAssociation.titlesDisplayGroup.displayedObjects() );
- }
-
- // finally, broadcast change event for this node
- // even though we're not sure if the displayed value changed.
- fireNodeChanged();
- }
-
- /**
- * Fires a change event for this node.
- */
- public void fireNodeChanged()
- {
- // if not root node
- if ( target != null )
- {
- int index = ((DisplayGroupNode)parentGroup).getIndex( this );
- if ( ( index != -1 )
- && ( treePath().getParentPath() != null ) )
- {
- fireNodesChanged (
- treePath().getParentPath().getPath(),
- new int[] { index },
- new Object[] { this } );
- }
- }
- }
-
-Object[] previouslyDisplayedObjects = new Object[0];
- /**
- * Overridden to call to super, fire any tree events, and then
- * call updateDisplayedObjects on all fetched child nodes.
- * This method compares this node's displayed objects against
- * the list of child nodes, synchronizes them, and then broadcasts
- * only the necessary events to bring the view component up to date.
- */
- public void updateDisplayedObjects()
- {
+ return displayedObjects.count();
+ }
+
+ public int getIndex(DisplayGroupNode node) {
+ if (!isFetched())
+ fetch();
+ return displayedObjects.indexOfObject(((DisplayGroupNode) node).target);
+ }
+
+ public boolean getAllowsChildren() {
+ return true;
+ }
+
+ public boolean isLeaf() {
+ // if not root node and isLeaf aspect is bound
+ if ((target != null) && (parentGroup != null) && (parentAssociation.leafKey != null)) {
+ Object value;
+ if (parentAssociation.leafDisplayGroup != null) {
+ value = parentGroup.valueForObject(target, parentAssociation.leafKey);
+ } else {
+ value = parentAssociation.leafKey;
+ }
+
+ // getBoolean returns true for zero, among other things
+ Object result = ValueConverter.getBoolean(value);
+ if (result != null) {
+ return ((Boolean) result).booleanValue();
+ }
+ }
+
+ // otherwise, we have to fetch and return count
+ return (getChildCount() == 0);
+ }
+
+ public Enumeration children() {
+ int count = getChildCount();
+ Vector v = new Vector();
+ for (int i = 0; i < count; i++) {
+ v.add(getChildNodeAt(i));
+ }
+ return v.elements();
+ }
+
+ // parts of interface MutableTreeNode
+
+ public void insert(DisplayGroupNode aChild, int anIndex) {
+ insertObjectAtIndex(((DisplayGroupNode) aChild).object(), anIndex);
+ }
+
+ public void remove(int index) {
+ deleteObjectAtIndex(index);
+ }
+
+ /**
+ * Removes the node at the index corresponding to the index of the object.
+ */
+ public void remove(DisplayGroupNode node) {
+ remove(getIndex(node));
+ }
+
+ /**
+ * Removes our object from the parent display group.
+ */
+ public void removeFromParent() {
+ int index = parentGroup.displayedObjects().indexOfIdenticalObject(target);
+ if (index != NSArray.NotFound) {
+ parentGroup.deleteObjectAtIndex(index);
+ } else {
+ throw new WotonomyException("Object not found in parent group: " + target);
+ }
+ }
+
+ /**
+ * Removes our object from the parent display group and adds it to the end of
+ * the specified node's children.
+ */
+ public void setParent(DisplayGroupNode newParent) {
+ removeFromParent();
+ newParent.insertObjectAtIndex(object(), newParent.displayedObjects.size());
+ }
+
+ /**
+ * Returns the value of the displayed property in the parent display group at
+ * the index that corresponds to the index of this node.
+ */
+ public Object getUserObject() {
+ return valueForKey(parentAssociation.titlesKey);
+ }
+
+ /**
+ * Sets the value of the displayed property in the parent display group at the
+ * index that corresponds to the index of this node.
+ */
+ public void setUserObject(Object aValue) {
+ setValueForKey(aValue, parentAssociation.titlesKey);
+ }
+
+ /**
+ * Returns a value from the object in the parent display group at the index that
+ * corresponds to the index of this node. For the root node, if the titles key
+ * is specified, the root label is returned, otherwise null is returned.
+ */
+ public Object valueForKey(String aKey) {
+ // if root node
+ if (target == null) {
+ // compare by ref is okay for strings
+ if (aKey == parentAssociation.titlesKey) {
+ return parentAssociation.rootLabel();
+ }
+ return null;
+ }
+ return parentGroup.valueForObject(target, aKey);
+ }
+
+ /**
+ * Sets a value on the object in the parent display group at the index that
+ * corresponds to the index of this node. For the root node, this method only
+ * works if aKey is the titlesAspect's key, otherwise does nothing.
+ */
+ public void setValueForKey(Object aValue, String aKey) {
+ // if root node, return.
+ if (target == null) {
+ // compare by ref is okay for strings
+ if (aKey == parentAssociation.titlesKey) {
+ parentAssociation.setRootLabel(aValue);
+
+ // how to handle root node? tree event docs don't say.
+ fireNodesChanged(treePath().getPath(), new int[] { 0 }, new Object[] { this });
+ }
+ return;
+ }
+
+ parentGroup.setValueForObject(aValue, target, aKey);
+ }
+
+ /**
+ * Perform any clean up in this method. The node will not be reused after this
+ * method is called. This implementation removes itself from the parent's set of
+ * child nodes, sets target and datasource to null, and then calls
+ * disposeChildNodes().
+ */
+ protected void dispose() { // System.out.println( "dispose: " + this.getClass().getName() + " : " + this );
+ if (parentGroup != null) {
+ ((DisplayGroupNode) parentGroup).childNodes.remove(new ReferenceKey(target));
+ }
+ setTarget((Object) null);
+ setDataSource(null);
+ disposeChildNodes();
+ }
+
+ /**
+ * Calls dispose() on all child nodes.
+ */
+ protected void disposeChildNodes() {
+ Iterator i = new LinkedList(childNodes.values()).iterator();
+ while (i.hasNext()) {
+ ((DisplayGroupNode) i.next()).dispose();
+ }
+ }
+
+ /**
+ * Called after the target object posts a change notification. This
+ * implementation re-fetches which triggers updateDisplayedObjects to broadcast
+ * any tree events. This method marks the parent object as changed if: (1) this
+ * object is not registered in the editing context of the titles display group's
+ * data source (if any), AND (2) the children key is not in the list of
+ * attributes of the parent object's EOClassDescription.
+ */
+ public void targetChanged() {
+ // if not root node
+ if (target != null) {
+ // if we're not root and not fetched, stop here.
+ // FIXME: with this, some nodes have old values when moved.
+ // FIXME: without this, nodes are unnecessarily fetched.
+ // FIXME: might have parent modify isFetched of certain child nodes.
+ if (isFetched()) {
+ fetch();
+ } else // not fetched - just update the display
+ {
+ updateDisplayedObjects();
+ }
+ /*
+ * //disabling this for performance reasons: //might reenable later or find an
+ * alternate approach // check to see if we need to mark the parent object as
+ * changed EOEditingContext context = dataSource().editingContext(); if ( (
+ * context == null ) || ( context.globalIDForObject( target ) == null ) ) {
+ * DisplayGroupNode parentNode = (DisplayGroupNode) parentGroup; if (
+ * parentNode.target != null ) { // only notify if childrenKey is an attribute
+ * of parentDesc // (and therefore not a toOne or toMany relationship)
+ * EOClassDescription parentDesc = EOClassDescription.classDescriptionForClass(
+ * parentNode.target.getClass() ); if ( parentDesc.attributeKeys().contains(
+ * parentAssociation.childrenKey ) ) { // only notify if no context is already
+ * observing the object // and we are an attribute key
+ * EOObserverCenter.notifyObserversObjectWillChange( parentNode.target ); } } }
+ */
+ } else // root node
+ {
+ setObjectArray(parentAssociation.titlesDisplayGroup.displayedObjects());
+ }
+
+ // finally, broadcast change event for this node
+ // even though we're not sure if the displayed value changed.
+ fireNodeChanged();
+ }
+
+ /**
+ * Fires a change event for this node.
+ */
+ public void fireNodeChanged() {
+ // if not root node
+ if (target != null) {
+ int index = ((DisplayGroupNode) parentGroup).getIndex(this);
+ if ((index != -1) && (treePath().getParentPath() != null)) {
+ fireNodesChanged(treePath().getParentPath().getPath(), new int[] { index }, new Object[] { this });
+ }
+ }
+ }
+
+ Object[] previouslyDisplayedObjects = new Object[0];
+
+ /**
+ * Overridden to call to super, fire any tree events, and then call
+ * updateDisplayedObjects on all fetched child nodes. This method compares this
+ * node's displayed objects against the list of child nodes, synchronizes them,
+ * and then broadcasts only the necessary events to bring the view component up
+ * to date.
+ */
+ public void updateDisplayedObjects() {
//System.out.println( "updateDisplayedObjects: " + " : " + this );
//net.wotonomy.ui.swing.util.StackTraceInspector.printShortStackTrace();
//new RuntimeException().printStackTrace();
- super.updateDisplayedObjects();
-
- // diff lists
- boolean proceed = true;
- Object[] oldObjects = previouslyDisplayedObjects;
- Object[] newObjects = displayedObjects.toArray();
- if ( oldObjects.length == newObjects.length )
- {
- proceed = false;
- for ( int i = 0; i < newObjects.length; i++ )
- {
- if ( oldObjects[i] != newObjects[i] )
- {
- proceed = true;
- break;
- }
- }
- }
-
- // this should be set before firing the change events
- // in case some clients end up calling this again.
- previouslyDisplayedObjects = newObjects;
-
- DisplayGroupNode node;
- Iterator i = childNodes.values().iterator();
- while ( i.hasNext() )
- {
- node = (DisplayGroupNode) i.next();
- if ( !node.isFetchNeeded() )
- {
- node.updateDisplayedObjects();
- }
- }
-
- if ( proceed )
- {
+ super.updateDisplayedObjects();
+
+ // diff lists
+ boolean proceed = true;
+ Object[] oldObjects = previouslyDisplayedObjects;
+ Object[] newObjects = displayedObjects.toArray();
+ if (oldObjects.length == newObjects.length) {
+ proceed = false;
+ for (int i = 0; i < newObjects.length; i++) {
+ if (oldObjects[i] != newObjects[i]) {
+ proceed = true;
+ break;
+ }
+ }
+ }
+
+ // this should be set before firing the change events
+ // in case some clients end up calling this again.
+ previouslyDisplayedObjects = newObjects;
+
+ DisplayGroupNode node;
+ Iterator i = childNodes.values().iterator();
+ while (i.hasNext()) {
+ node = (DisplayGroupNode) i.next();
+ if (!node.isFetchNeeded()) {
+ node.updateDisplayedObjects();
+ }
+ }
+
+ if (proceed) {
//System.out.println( "DisplayGroupNode.firingEventsForChanges: " );
//new RuntimeException().printStackTrace();
- fireEventsForChanges( oldObjects, newObjects );
- }
-
- }
-
- /**
- * Called by processRecentChanges to analyze the
- * differences between the lists and broadcast the
- * appropriate events.
- */
- protected void fireEventsForChanges(
- Object[] oldObjects, Object[] newObjects )
- {
- // structure changed causes havoc while
- // establishing connection in some cases
- //if ( oldObjects.length == 0 || newObjects.length == 0 )
- //{
- // fireStructureChanged( treePath().getPath(), null, null );
- // return;
- //}
-
- int insertCount = 0;
- int deleteCount = 0;
- Object[] inserts = new Object[ newObjects.length ];
- Object[] deletes = new Object[ oldObjects.length ];
-
- int i;
- int n = -1, o = -1; // last match
- int n1 = 0, o1 = 0; // current match test
- int n2 = 0, o2 = 0; // scan ahead
-
- while ( o1 < oldObjects.length && n1 < newObjects.length )
- {
- if ( newObjects[n1] == oldObjects[o1] )
- {
- // mark as match and continue
- o = o1;
- n = n1;
- }
- else
- {
- // scan ahead for the next match, if any
- o2 = o1;
- n2 = n1;
-
- while ( o2 < oldObjects.length || n2 < newObjects.length )
- {
- if ( o2 < oldObjects.length && newObjects[n1] == oldObjects[o2] )
- {
- // run o1 to o2: mark as deletes
- for ( i = o1; i < o2; i++ )
- { // System.out.println( "delete : " + i );
- deletes[i] = oldObjects[i];
- deleteCount++;
- }
- o1 = o2; // reset test
- o = o1; // set match
- n = n1; // set match
- break;
- }
- if ( n2 < newObjects.length && newObjects[n2] == oldObjects[o1] )
- {
- // run n1 to n2: mark as inserts
- for ( i = n1; i < n2; i++ )
- { // System.out.println( "insert : " + i );
- inserts[i] = newObjects[i];
- insertCount++;
- }
- n1 = n2; // reset test
- n = n1; // set match
- o = o1; // set match
- break;
- }
- o2++;
- n2++;
- }
- }
- if (n != n1)
- {
- inserts[n1] = newObjects[n1];
- insertCount++;
- deletes[o1] = oldObjects[o1];
- deleteCount++;
- //increment even though no match:
- //the new object was marked as inserted and
- //the old object was marked as deleted.
- n = n1;
- o = o1;
- }
- o1++;
- n1++;
- }
-
- // run o to end of oldObjects: mark as deletes
- for ( i = o+1; i < oldObjects.length; i++ )
- { // System.out.println( "delete : " + i );
- deletes[i] = oldObjects[i];
- deleteCount++;
- }
-
- // run n to end of newObjects: mark as inserts
- for ( i = n+1; i < newObjects.length; i++ )
- { // System.out.println( "insert : " + i );
- inserts[i] = newObjects[i];
- insertCount++;
- }
+ fireEventsForChanges(oldObjects, newObjects);
+ }
+
+ }
+
+ /**
+ * Called by processRecentChanges to analyze the differences between the lists
+ * and broadcast the appropriate events.
+ */
+ protected void fireEventsForChanges(Object[] oldObjects, Object[] newObjects) {
+ // structure changed causes havoc while
+ // establishing connection in some cases
+ // if ( oldObjects.length == 0 || newObjects.length == 0 )
+ // {
+ // fireStructureChanged( treePath().getPath(), null, null );
+ // return;
+ // }
+
+ int insertCount = 0;
+ int deleteCount = 0;
+ Object[] inserts = new Object[newObjects.length];
+ Object[] deletes = new Object[oldObjects.length];
+
+ int i;
+ int n = -1, o = -1; // last match
+ int n1 = 0, o1 = 0; // current match test
+ int n2 = 0, o2 = 0; // scan ahead
+
+ while (o1 < oldObjects.length && n1 < newObjects.length) {
+ if (newObjects[n1] == oldObjects[o1]) {
+ // mark as match and continue
+ o = o1;
+ n = n1;
+ } else {
+ // scan ahead for the next match, if any
+ o2 = o1;
+ n2 = n1;
+
+ while (o2 < oldObjects.length || n2 < newObjects.length) {
+ if (o2 < oldObjects.length && newObjects[n1] == oldObjects[o2]) {
+ // run o1 to o2: mark as deletes
+ for (i = o1; i < o2; i++) { // System.out.println( "delete : " + i );
+ deletes[i] = oldObjects[i];
+ deleteCount++;
+ }
+ o1 = o2; // reset test
+ o = o1; // set match
+ n = n1; // set match
+ break;
+ }
+ if (n2 < newObjects.length && newObjects[n2] == oldObjects[o1]) {
+ // run n1 to n2: mark as inserts
+ for (i = n1; i < n2; i++) { // System.out.println( "insert : " + i );
+ inserts[i] = newObjects[i];
+ insertCount++;
+ }
+ n1 = n2; // reset test
+ n = n1; // set match
+ o = o1; // set match
+ break;
+ }
+ o2++;
+ n2++;
+ }
+ }
+ if (n != n1) {
+ inserts[n1] = newObjects[n1];
+ insertCount++;
+ deletes[o1] = oldObjects[o1];
+ deleteCount++;
+ // increment even though no match:
+ // the new object was marked as inserted and
+ // the old object was marked as deleted.
+ n = n1;
+ o = o1;
+ }
+ o1++;
+ n1++;
+ }
+
+ // run o to end of oldObjects: mark as deletes
+ for (i = o + 1; i < oldObjects.length; i++) { // System.out.println( "delete : " + i );
+ deletes[i] = oldObjects[i];
+ deleteCount++;
+ }
+
+ // run n to end of newObjects: mark as inserts
+ for (i = n + 1; i < newObjects.length; i++) { // System.out.println( "insert : " + i );
+ inserts[i] = newObjects[i];
+ insertCount++;
+ }
//System.out.println( "done : "
//+ o + " : " + o1 + " : " + o2 + " :: " + n + " : " + n1 + " : " + n2 );
@@ -948,571 +774,481 @@ Object[] previouslyDisplayedObjects = new Object[0];
//System.out.println( new NSArray( inserts ) );
//System.out.println( new NSArray( deletes ) );
//System.out.println( new NSArray( oldObjects ) );
-
- int c;
- Object[] nodes;
- int[] indices;
-
- // broadcast delete event
- c = 0;
- nodes = new Object[ deleteCount ];
- indices = new int[ deleteCount ];
- for ( i = 0; i < deletes.length; i++ )
- {
- if ( deletes[i] != null )
- {
- indices[c] = i;
- nodes[c] = getChildNodeForObject( deletes[i] );
- c++;
- }
- }
- if ( c > 0 )
- {
+
+ int c;
+ Object[] nodes;
+ int[] indices;
+
+ // broadcast delete event
+ c = 0;
+ nodes = new Object[deleteCount];
+ indices = new int[deleteCount];
+ for (i = 0; i < deletes.length; i++) {
+ if (deletes[i] != null) {
+ indices[c] = i;
+ nodes[c] = getChildNodeForObject(deletes[i]);
+ c++;
+ }
+ }
+ if (c > 0) {
// fireNodeChanged(); // force the jtree to get the correct child count
- fireNodesRemoved( treePath().getPath(), indices, nodes );
- }
- deletes = nodes; // retain for dispose check
-
- // broadcast insert event
- c = 0;
- nodes = new Object[ insertCount ];
- indices = new int[ insertCount ];
- for ( i = 0; i < inserts.length; i++ )
- {
- if ( inserts[i] != null )
- {
- indices[c] = i;
- nodes[c] = getChildNodeForObject( inserts[i] );
- if ( nodes[c] == null )
- {
- nodes[c] = createChildNodeForObject( newObjects[i] );
- }
- c++;
- }
- }
- if ( c > 0 )
- {
- fireNodesInserted( treePath().getPath(), indices, nodes );
- }
-
- // dispose any delete nodes not on insert list
- int j;
- boolean found;
- for ( i = 0; i < deletes.length; i++ )
- {
- for ( j = 0; j < nodes.length; j++ )
- {
- if ( deletes[i] == nodes[j] ) break;
- }
-
- // did not break early, so not found, so dispose
- if ( j == nodes.length )
- {
- ((DisplayGroupNode)deletes[i]).dispose();
- }
- }
- }
-
- /**
- * Sets the target object and creates an registers a target observer.
- * If target was not previously null, the existing observer is unregistered.
- * Protected access so subclasses and TreeModelAssociation can update our target.
- */
- public void setTarget( Object aTarget )
- {
- if ( target != null )
- {
- EOObserverCenter.removeObserver( targetObserver, target );
- targetObserver.discardPendingNotification();
- }
-
- if ( aTarget != null )
- {
- target = aTarget;
- targetObserver = new TargetObserver( this );
- EOObserverCenter.addObserver( targetObserver, target );
- }
- }
-
- /**
- * Returns the parent display group, or null if parent is root.
- */
- public DisplayGroupNode getParentGroup()
- {
- if ( parentGroup instanceof DisplayGroupNode )
- {
- return (DisplayGroupNode)parentGroup;
- }
- // presumably the root node
- return null;
- }
-
- /**
- * Gets all descendants of the this node.
- */
- public List getDescendants()
- {
- return getDescendants( this, true );
- }
-
- /**
- * Gets only the descendants of the this node
- * whose children has been loaded - no fetching
- * will occur. Useful for load-on-demand trees.
- */
- public List getLoadedDescendants()
- {
- return getDescendants( this, false );
- }
-
- // breadth first traversal implementation
-
- /**
- * Returns a list of all descendants of the
- * specified node. Unfetched nodes are traversed
- * only if forceLoad is true.
- * This implementation is a breadth-first traversal
- * of the nodes starting at the specified node.
- */
- static private List getDescendants( DisplayGroupNode aNode, boolean forceLoad )
- {
- if ( !forceLoad && !aNode.isFetched ) return NSArray.EmptyArray;
-
- LinkedList result = new LinkedList();
- LinkedList queue = new LinkedList();
-
- queue.add( aNode );
- while ( ! queue.isEmpty() )
- {
- checkNode( (DisplayGroupNode) queue.removeFirst(),
- queue, result, forceLoad );
- }
-
- return result;
- }
-
- /**
- * Adds each fetched child node of the specified node to
- * the result set (optionally forcing the child node to load)
- * and adding child node to the end of the queue.
- */
- static private void checkNode( DisplayGroupNode aNode,
- LinkedList aQueue, LinkedList aResult, boolean forceLoad )
- {
- DisplayGroupNode child;
- int count = aNode.getChildCount();
-
- for ( int i = 0; i < count; i++ )
- {
- child = aNode.getChildNodeAt( i );
-
- // add to queue if node has fetched children
- if ( ( !child.isFetched ) && ( forceLoad ) )
- {
- child.fetch();
- }
- if ( child.isFetched )
- {
- aQueue.addLast( child );
- }
-
- aResult.add( child );
- }
- }
-
- /**
- * Overridden to not fetch on InvalidateAllObjectsInStoreNotification
- * unless we've already been fetched, preserving the load-on-demand
- * functionality.
- */
- public void objectsInvalidatedInEditingContext( NSNotification aNotification )
- {
- if ( EOObjectStore.InvalidatedAllObjectsInStoreNotification
- .equals( aNotification.name() ) )
- {
+ fireNodesRemoved(treePath().getPath(), indices, nodes);
+ }
+ deletes = nodes; // retain for dispose check
+
+ // broadcast insert event
+ c = 0;
+ nodes = new Object[insertCount];
+ indices = new int[insertCount];
+ for (i = 0; i < inserts.length; i++) {
+ if (inserts[i] != null) {
+ indices[c] = i;
+ nodes[c] = getChildNodeForObject(inserts[i]);
+ if (nodes[c] == null) {
+ nodes[c] = createChildNodeForObject(newObjects[i]);
+ }
+ c++;
+ }
+ }
+ if (c > 0) {
+ fireNodesInserted(treePath().getPath(), indices, nodes);
+ }
+
+ // dispose any delete nodes not on insert list
+ int j;
+ boolean found;
+ for (i = 0; i < deletes.length; i++) {
+ for (j = 0; j < nodes.length; j++) {
+ if (deletes[i] == nodes[j])
+ break;
+ }
+
+ // did not break early, so not found, so dispose
+ if (j == nodes.length) {
+ ((DisplayGroupNode) deletes[i]).dispose();
+ }
+ }
+ }
+
+ /**
+ * Sets the target object and creates an registers a target observer. If target
+ * was not previously null, the existing observer is unregistered. Protected
+ * access so subclasses and TreeModelAssociation can update our target.
+ */
+ public void setTarget(Object aTarget) {
+ if (target != null) {
+ EOObserverCenter.removeObserver(targetObserver, target);
+ targetObserver.discardPendingNotification();
+ }
+
+ if (aTarget != null) {
+ target = aTarget;
+ targetObserver = new TargetObserver(this);
+ EOObserverCenter.addObserver(targetObserver, target);
+ }
+ }
+
+ /**
+ * Returns the parent display group, or null if parent is root.
+ */
+ public DisplayGroupNode getParentGroup() {
+ if (parentGroup instanceof DisplayGroupNode) {
+ return (DisplayGroupNode) parentGroup;
+ }
+ // presumably the root node
+ return null;
+ }
+
+ /**
+ * Gets all descendants of the this node.
+ */
+ public List getDescendants() {
+ return getDescendants(this, true);
+ }
+
+ /**
+ * Gets only the descendants of the this node whose children has been loaded -
+ * no fetching will occur. Useful for load-on-demand trees.
+ */
+ public List getLoadedDescendants() {
+ return getDescendants(this, false);
+ }
+
+ // breadth first traversal implementation
+
+ /**
+ * Returns a list of all descendants of the specified node. Unfetched nodes are
+ * traversed only if forceLoad is true. This implementation is a breadth-first
+ * traversal of the nodes starting at the specified node.
+ */
+ static private List getDescendants(DisplayGroupNode aNode, boolean forceLoad) {
+ if (!forceLoad && !aNode.isFetched)
+ return NSArray.EmptyArray;
+
+ LinkedList result = new LinkedList();
+ LinkedList queue = new LinkedList();
+
+ queue.add(aNode);
+ while (!queue.isEmpty()) {
+ checkNode((DisplayGroupNode) queue.removeFirst(), queue, result, forceLoad);
+ }
+
+ return result;
+ }
+
+ /**
+ * Adds each fetched child node of the specified node to the result set
+ * (optionally forcing the child node to load) and adding child node to the end
+ * of the queue.
+ */
+ static private void checkNode(DisplayGroupNode aNode, LinkedList aQueue, LinkedList aResult, boolean forceLoad) {
+ DisplayGroupNode child;
+ int count = aNode.getChildCount();
+
+ for (int i = 0; i < count; i++) {
+ child = aNode.getChildNodeAt(i);
+
+ // add to queue if node has fetched children
+ if ((!child.isFetched) && (forceLoad)) {
+ child.fetch();
+ }
+ if (child.isFetched) {
+ aQueue.addLast(child);
+ }
+
+ aResult.add(child);
+ }
+ }
+
+ /**
+ * Overridden to not fetch on InvalidateAllObjectsInStoreNotification unless
+ * we've already been fetched, preserving the load-on-demand functionality.
+ */
+ public void objectsInvalidatedInEditingContext(NSNotification aNotification) {
+ if (EOObjectStore.InvalidatedAllObjectsInStoreNotification.equals(aNotification.name())) {
//System.out.println( "DisplayGroupNode.objectsInvalidatedInEditingContext: " + aNotification.name() );
- if ( parentAssociation.isVisible( this ) && targetObserver != null )
- {
- targetObserver.objectWillChange( target ); // force ui to update
- fireNodeChanged();
- }
- else // make sure we fetch children when we do become visible
- setFetchNeeded( true );
- return;
- }
- else
- if ( ( EOEditingContext.ObjectsChangedInEditingContextNotification
- .equals( aNotification.name() ) )
- || ( EOEditingContext.EditingContextDidSaveChangesNotification
- .equals( aNotification.name() ) ) )
- {
- int index;
- Enumeration e;
- boolean didChange = false;
- NSDictionary userInfo = aNotification.userInfo();
-
- // if our target object was deleted
- NSArray deletes = (NSArray) userInfo.objectForKey(
- EOObjectStore.DeletedKey );
- if ( deletes.indexOfIdenticalObject( target ) != NSArray.NotFound )
- {
+ if (parentAssociation.isVisible(this) && targetObserver != null) {
+ targetObserver.objectWillChange(target); // force ui to update
+ fireNodeChanged();
+ } else // make sure we fetch children when we do become visible
+ setFetchNeeded(true);
+ return;
+ } else if ((EOEditingContext.ObjectsChangedInEditingContextNotification.equals(aNotification.name()))
+ || (EOEditingContext.EditingContextDidSaveChangesNotification.equals(aNotification.name()))) {
+ int index;
+ Enumeration e;
+ boolean didChange = false;
+ NSDictionary userInfo = aNotification.userInfo();
+
+ // if our target object was deleted
+ NSArray deletes = (NSArray) userInfo.objectForKey(EOObjectStore.DeletedKey);
+ if (deletes.indexOfIdenticalObject(target) != NSArray.NotFound) {
//System.out.println( "DisplayGroupNode.objectsInvalidatedInEditingContext: delete: " + this + " : " + aNotification.name() );
- if ( parentAssociation.isVisible( this ) && targetObserver != null )
- {
- targetObserver.objectWillChange( target ); // force ui to update
- fireNodeChanged();
- }
- else // make sure we fetch children when we do become visible
- setFetchNeeded( true );
- return;
- }
-
- // if our target object was invalidated
- NSArray invalidates = (NSArray) userInfo.objectForKey(
- EOObjectStore.InvalidatedKey );
- if ( invalidates != null &&
- invalidates.indexOfIdenticalObject( target ) != NSArray.NotFound )
- {
+ if (parentAssociation.isVisible(this) && targetObserver != null) {
+ targetObserver.objectWillChange(target); // force ui to update
+ fireNodeChanged();
+ } else // make sure we fetch children when we do become visible
+ setFetchNeeded(true);
+ return;
+ }
+
+ // if our target object was invalidated
+ NSArray invalidates = (NSArray) userInfo.objectForKey(EOObjectStore.InvalidatedKey);
+ if (invalidates != null && invalidates.indexOfIdenticalObject(target) != NSArray.NotFound) {
//System.out.println( "DisplayGroupNode.objectsInvalidatedInEditingContext: invalidate: " + this + " : " + aNotification.name() );
- if ( parentAssociation.isVisible( this ) && targetObserver != null )
- {
- targetObserver.objectWillChange( target ); // force ui to update
- fireNodeChanged();
- }
- else // make sure we fetch children when we do become visible
- setFetchNeeded( true );
- return;
- }
-
- // if our target object was updated, set fetchNeeded plus fire changed event
- NSArray updates = (NSArray) userInfo.objectForKey(
- EOObjectStore.UpdatedKey );
- if ( updates.indexOfIdenticalObject( target ) != NSArray.NotFound )
- {
- if ( parentAssociation.isVisible( this ) && targetObserver != null )
- {
- targetObserver.objectWillChange( target ); // force ui to update
- fireNodeChanged();
- if ( object() instanceof Component ) ((Component)object()).repaint();
- }
- else // make sure we fetch children when we do become visible
- setFetchNeeded( true );
- return;
- }
- }
-
- super.objectsInvalidatedInEditingContext( aNotification );
-
- }
-
- // inner classes
-
- /**
- * Private class used to force a hashmap to
- * perform key comparisons by reference.
- */
- private class ReferenceKey
- {
- private int hashCode;
- private Object referent;
-
- public ReferenceKey( Object anObject )
- {
- referent = anObject;
- hashCode = anObject.hashCode();
- }
-
- /**
- * Returns the actual key's hash code.
- */
- public int hashCode()
- {
- return hashCode;
- }
-
- /**
- * Compares by reference.
- */
- public boolean equals( Object anObject )
- {
- if ( anObject instanceof ReferenceKey )
- {
- return ((ReferenceKey)anObject).referent == referent;
- }
- return false;
- }
- }
-
- /**
- * A private class to observe the target object of this node.
- */
- private class TargetObserver extends EODelayedObserver
- {
- Reference ref;
-
- /**
- * Pass in the display group node that will be updated
- * when the target changes.
- */
- public TargetObserver( DisplayGroupNode aDisplayGroup )
- {
- ref = new WeakReference( aDisplayGroup );
- }
-
- /**
- * Repopulate our display group, and calculate the deltas
- * so we can broadcast appropriate events.
- */
- public void subjectChanged ()
- {
- DisplayGroupNode node = (DisplayGroupNode) ref.get();
- if ( node == null ) return; // node is null if gc'd.
- //FIXME: should un-register self from observer center??
-
- node.targetChanged();
- }
- }
+ if (parentAssociation.isVisible(this) && targetObserver != null) {
+ targetObserver.objectWillChange(target); // force ui to update
+ fireNodeChanged();
+ } else // make sure we fetch children when we do become visible
+ setFetchNeeded(true);
+ return;
+ }
+
+ // if our target object was updated, set fetchNeeded plus fire changed event
+ NSArray updates = (NSArray) userInfo.objectForKey(EOObjectStore.UpdatedKey);
+ if (updates.indexOfIdenticalObject(target) != NSArray.NotFound) {
+ if (parentAssociation.isVisible(this) && targetObserver != null) {
+ targetObserver.objectWillChange(target); // force ui to update
+ fireNodeChanged();
+ if (object() instanceof Component)
+ ((Component) object()).repaint();
+ } else // make sure we fetch children when we do become visible
+ setFetchNeeded(true);
+ return;
+ }
+ }
+
+ super.objectsInvalidatedInEditingContext(aNotification);
+
+ }
+
+ // inner classes
+
+ /**
+ * Private class used to force a hashmap to perform key comparisons by
+ * reference.
+ */
+ private class ReferenceKey {
+ private int hashCode;
+ private Object referent;
+
+ public ReferenceKey(Object anObject) {
+ referent = anObject;
+ hashCode = anObject.hashCode();
+ }
+
+ /**
+ * Returns the actual key's hash code.
+ */
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * Compares by reference.
+ */
+ public boolean equals(Object anObject) {
+ if (anObject instanceof ReferenceKey) {
+ return ((ReferenceKey) anObject).referent == referent;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * A private class to observe the target object of this node.
+ */
+ private class TargetObserver extends EODelayedObserver {
+ Reference ref;
+
+ /**
+ * Pass in the display group node that will be updated when the target changes.
+ */
+ public TargetObserver(DisplayGroupNode aDisplayGroup) {
+ ref = new WeakReference(aDisplayGroup);
+ }
+
+ /**
+ * Repopulate our display group, and calculate the deltas so we can broadcast
+ * appropriate events.
+ */
+ public void subjectChanged() {
+ DisplayGroupNode node = (DisplayGroupNode) ref.get();
+ if (node == null)
+ return; // node is null if gc'd.
+ // FIXME: should un-register self from observer center??
+
+ node.targetChanged();
+ }
+ }
}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:19:05 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:19:05 cgruber Update imports and maven
+ * dependencies.
*
- * Revision 1.1 2006/02/16 13:22:22 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.64 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.64 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.63 2003/06/06 14:20:07 mpowers
- * getLoadedDescendants was forcing a fetch of the node it was called on.
+ * Revision 1.63 2003/06/06 14:20:07 mpowers getLoadedDescendants was forcing a
+ * fetch of the node it was called on.
*
- * Revision 1.62 2003/06/03 14:48:33 mpowers
- * Clean-up of notification handling for updates/invalidation/etc.
- * Now fetching immediately on notification if the node is visible.
- * This averts the infamous IndexOutOfBoundsException that occurs
- * if fetching happens during repaint, because the BasicTreeUI is
- * caching the number of child nodes before painting begins.
+ * Revision 1.62 2003/06/03 14:48:33 mpowers Clean-up of notification handling
+ * for updates/invalidation/etc. Now fetching immediately on notification if the
+ * node is visible. This averts the infamous IndexOutOfBoundsException that
+ * occurs if fetching happens during repaint, because the BasicTreeUI is caching
+ * the number of child nodes before painting begins.
*
- * Revision 1.61 2003/01/18 23:33:29 mpowers
- * Fixing the build.
+ * Revision 1.61 2003/01/18 23:33:29 mpowers Fixing the build.
*
- * Revision 1.60 2002/05/31 15:03:10 mpowers
- * Fixes for the previous fix. Fat props to yjcheung.
+ * Revision 1.60 2002/05/31 15:03:10 mpowers Fixes for the previous fix. Fat
+ * props to yjcheung.
*
- * Revision 1.59 2002/05/28 15:31:36 mpowers
- * Fix for updateDisplayedObjects for a subtle case where a node appears in
- * the position that another node was moved from.
+ * Revision 1.59 2002/05/28 15:31:36 mpowers Fix for updateDisplayedObjects for
+ * a subtle case where a node appears in the position that another node was
+ * moved from.
*
- * Revision 1.58 2002/05/24 14:42:02 mpowers
- * Prevent repeat events from firing if firing events loops back.
+ * Revision 1.58 2002/05/24 14:42:02 mpowers Prevent repeat events from firing
+ * if firing events loops back.
*
- * Revision 1.57 2002/04/23 19:12:28 mpowers
- * Reimplemented fireEventsForChanges. Fitter and happier.
+ * Revision 1.57 2002/04/23 19:12:28 mpowers Reimplemented fireEventsForChanges.
+ * Fitter and happier.
*
- * Revision 1.56 2002/04/19 21:18:45 mpowers
- * Removed tree event coalescing, which was causing way too many problems.
- * The fireChangeEvent algorithm is way faster than before, so we should
- * still be better off than before. At least now, we don't have to track
- * whether the view component has encountered a particular node.
+ * Revision 1.56 2002/04/19 21:18:45 mpowers Removed tree event coalescing,
+ * which was causing way too many problems. The fireChangeEvent algorithm is way
+ * faster than before, so we should still be better off than before. At least
+ * now, we don't have to track whether the view component has encountered a
+ * particular node.
*
- * Revision 1.55 2002/04/19 20:53:22 mpowers
- * Now firing event fewer events in fireEventsForChanges.
+ * Revision 1.55 2002/04/19 20:53:22 mpowers Now firing event fewer events in
+ * fireEventsForChanges.
*
- * Revision 1.54 2002/04/15 21:52:50 mpowers
- * Tightening up TreeModelAssociation and DisplayGroupNode.
- * Now only firing root structure changed once.
- * Now disposing of root's children.
- * Better event coalescing.
+ * Revision 1.54 2002/04/15 21:52:50 mpowers Tightening up TreeModelAssociation
+ * and DisplayGroupNode. Now only firing root structure changed once. Now
+ * disposing of root's children. Better event coalescing.
*
- * Revision 1.53 2002/04/12 20:35:20 mpowers
- * Now correctly setting parent display group and data source on creation.
+ * Revision 1.53 2002/04/12 20:35:20 mpowers Now correctly setting parent
+ * display group and data source on creation.
*
- * Revision 1.52 2002/04/10 21:20:04 mpowers
- * Better handling for tree nodes when working with editing contexts.
- * Better handling for invalidation. No longer broadcasting events
- * when nodes have not been "registered" in the tree.
+ * Revision 1.52 2002/04/10 21:20:04 mpowers Better handling for tree nodes when
+ * working with editing contexts. Better handling for invalidation. No longer
+ * broadcasting events when nodes have not been "registered" in the tree.
*
- * Revision 1.51 2002/04/03 20:13:36 mpowers
- * Now differentiating between node instantiation caused by model expansion
- * (user initiated) and by modifications to the model.
- * Dispose now disposes all children.
+ * Revision 1.51 2002/04/03 20:13:36 mpowers Now differentiating between node
+ * instantiation caused by model expansion (user initiated) and by modifications
+ * to the model. Dispose now disposes all children.
*
- * Revision 1.50 2002/03/23 16:20:27 mpowers
- * Optimized processRecentChanges, minimized tree events.
+ * Revision 1.50 2002/03/23 16:20:27 mpowers Optimized processRecentChanges,
+ * minimized tree events.
*
- * Revision 1.49 2002/03/11 03:15:06 mpowers
- * Optimized processRecentChanges, minimize event firing, coalescing changes.
- * Still need a better diff algorithm to avoid removing nodes.
+ * Revision 1.49 2002/03/11 03:15:06 mpowers Optimized processRecentChanges,
+ * minimize event firing, coalescing changes. Still need a better diff algorithm
+ * to avoid removing nodes.
*
- * Revision 1.48 2002/03/10 00:59:39 mpowers
- * Interim version: coalesces calls to process recent changes.
- * Still does not handle rearranged nodes.
+ * Revision 1.48 2002/03/10 00:59:39 mpowers Interim version: coalesces calls to
+ * process recent changes. Still does not handle rearranged nodes.
*
- * Revision 1.47 2002/03/09 17:33:45 mpowers
- * Nodes now track their child nodes by reference, not index.
+ * Revision 1.47 2002/03/09 17:33:45 mpowers Nodes now track their child nodes
+ * by reference, not index.
*
- * Revision 1.46 2002/03/08 23:19:07 mpowers
- * Added getParentGroup to DisplayGroupNode.
+ * Revision 1.46 2002/03/08 23:19:07 mpowers Added getParentGroup to
+ * DisplayGroupNode.
*
- * Revision 1.45 2002/03/06 13:04:16 mpowers
- * Implemented cascading qualifiers in tree nodes.
+ * Revision 1.45 2002/03/06 13:04:16 mpowers Implemented cascading qualifiers in
+ * tree nodes.
*
- * Revision 1.44 2002/02/27 23:19:17 mpowers
- * Refactoring of TreeAssociation to create TreeModelAssociation parent.
+ * Revision 1.44 2002/02/27 23:19:17 mpowers Refactoring of TreeAssociation to
+ * create TreeModelAssociation parent.
*
- * Revision 1.42 2002/02/19 22:28:46 mpowers
- * DisplayGroupNodes immediately unregister themselves as editors.
+ * Revision 1.42 2002/02/19 22:28:46 mpowers DisplayGroupNodes immediately
+ * unregister themselves as editors.
*
- * Revision 1.41 2002/02/13 16:27:38 mpowers
- * Exposing setTarget.
+ * Revision 1.41 2002/02/13 16:27:38 mpowers Exposing setTarget.
*
- * Revision 1.40 2001/11/02 20:55:46 mpowers
- * Now using fixed index to send node removed events. This preserves the
- * expanded state of the nodes in the corresponding jtree.
+ * Revision 1.40 2001/11/02 20:55:46 mpowers Now using fixed index to send node
+ * removed events. This preserves the expanded state of the nodes in the
+ * corresponding jtree.
*
- * Revision 1.39 2001/09/21 21:09:25 mpowers
- * Exposed more fields as protected.
+ * Revision 1.39 2001/09/21 21:09:25 mpowers Exposed more fields as protected.
*
- * Revision 1.38 2001/09/19 15:36:08 mpowers
- * Refined behavior for isFetched after notification handling.
+ * Revision 1.38 2001/09/19 15:36:08 mpowers Refined behavior for isFetched
+ * after notification handling.
*
- * Revision 1.37 2001/09/13 14:51:18 mpowers
- * DisplayGroupNodes now dispose themselves and mark their parent for update
- * when they receive notification that their target has been deleted.
+ * Revision 1.37 2001/09/13 14:51:18 mpowers DisplayGroupNodes now dispose
+ * themselves and mark their parent for update when they receive notification
+ * that their target has been deleted.
*
- * Revision 1.36 2001/09/10 14:10:24 mpowers
- * Fix for notification handling.
+ * Revision 1.36 2001/09/10 14:10:24 mpowers Fix for notification handling.
*
- * Revision 1.35 2001/07/30 16:17:01 mpowers
- * Minor code cleanup.
+ * Revision 1.35 2001/07/30 16:17:01 mpowers Minor code cleanup.
*
- * Revision 1.34 2001/07/18 22:13:39 mpowers
- * getLoadedDescendants now works as advertised.
- * Now correctly handling invalidateAllObjects notification.
+ * Revision 1.34 2001/07/18 22:13:39 mpowers getLoadedDescendants now works as
+ * advertised. Now correctly handling invalidateAllObjects notification.
*
- * Revision 1.33 2001/07/18 13:03:32 mpowers
- * TreeNodes now refetch only on demand. Previously, once a node had
- * been fetched, it was always refetched after an invalidate, even if
- * the node was not being displayed.
+ * Revision 1.33 2001/07/18 13:03:32 mpowers TreeNodes now refetch only on
+ * demand. Previously, once a node had been fetched, it was always refetched
+ * after an invalidate, even if the node was not being displayed.
*
- * Revision 1.32 2001/06/18 14:10:28 mpowers
- * Cleaned up event firing: no longer firing insert or remove events twice.
+ * Revision 1.32 2001/06/18 14:10:28 mpowers Cleaned up event firing: no longer
+ * firing insert or remove events twice.
*
- * Revision 1.31 2001/06/09 16:15:39 mpowers
- * Revised the targetChanged scheme because oldObjects and newObjects were
- * identical after the target object is invalidated.
+ * Revision 1.31 2001/06/09 16:15:39 mpowers Revised the targetChanged scheme
+ * because oldObjects and newObjects were identical after the target object is
+ * invalidated.
*
- * Revision 1.30 2001/05/21 22:17:19 mpowers
- * Fix for tree out-of-synch problems when nodes are inserted.
+ * Revision 1.30 2001/05/21 22:17:19 mpowers Fix for tree out-of-synch problems
+ * when nodes are inserted.
*
- * Revision 1.29 2001/05/18 21:07:46 mpowers
- * Playing with refresh options.
+ * Revision 1.29 2001/05/18 21:07:46 mpowers Playing with refresh options.
*
- * Revision 1.28 2001/05/14 15:25:43 mpowers
- * DisplayGroupNodes now only respond to InvalidateAllObjectsInStore
- * if they are already fetched.
+ * Revision 1.28 2001/05/14 15:25:43 mpowers DisplayGroupNodes now only respond
+ * to InvalidateAllObjectsInStore if they are already fetched.
*
- * Revision 1.27 2001/05/08 19:55:58 mpowers
- * Fix for node children not refreshing after sibling was inserted.
+ * Revision 1.27 2001/05/08 19:55:58 mpowers Fix for node children not
+ * refreshing after sibling was inserted.
*
- * Revision 1.26 2001/05/08 18:47:34 mpowers
- * Minor fixes for d3.
+ * Revision 1.26 2001/05/08 18:47:34 mpowers Minor fixes for d3.
*
- * Revision 1.25 2001/05/06 22:22:55 mpowers
- * Debugging.
+ * Revision 1.25 2001/05/06 22:22:55 mpowers Debugging.
*
- * Revision 1.24 2001/05/04 14:42:58 mpowers
- * Now getting stored values in KeyValueCoding.
- * MasterDetail now marks dirty based on whether it's an attribute
- * or relation.
- * Implemented editing context marker.
+ * Revision 1.24 2001/05/04 14:42:58 mpowers Now getting stored values in
+ * KeyValueCoding. MasterDetail now marks dirty based on whether it's an
+ * attribute or relation. Implemented editing context marker.
*
- * Revision 1.23 2001/05/02 18:00:43 mpowers
- * Removed debug code.
+ * Revision 1.23 2001/05/02 18:00:43 mpowers Removed debug code.
*
- * Revision 1.22 2001/05/02 17:31:20 mpowers
- * DisplayGroupNode now does a better job determining when to mark its
- * parent dirty.
+ * Revision 1.22 2001/05/02 17:31:20 mpowers DisplayGroupNode now does a better
+ * job determining when to mark its parent dirty.
*
- * Revision 1.21 2001/05/01 00:52:32 mpowers
- * Implemented breadth-first traversal of tree for node.
+ * Revision 1.21 2001/05/01 00:52:32 mpowers Implemented breadth-first traversal
+ * of tree for node.
*
- * Revision 1.20 2001/04/26 01:15:19 mpowers
- * Major clean-up of DisplayGroupNode: fitter, happier, more productive.
+ * Revision 1.20 2001/04/26 01:15:19 mpowers Major clean-up of DisplayGroupNode:
+ * fitter, happier, more productive.
*
- * Revision 1.19 2001/04/22 23:13:35 mpowers
- * Minor bug.
+ * Revision 1.19 2001/04/22 23:13:35 mpowers Minor bug.
*
- * Revision 1.18 2001/04/22 23:05:33 mpowers
- * Totally revised DisplayGroupNode so each object gets its own node
- * (so the nodes are no longer fixed by index).
+ * Revision 1.18 2001/04/22 23:05:33 mpowers Totally revised DisplayGroupNode so
+ * each object gets its own node (so the nodes are no longer fixed by index).
*
- * Revision 1.17 2001/04/21 23:05:12 mpowers
- * A fairly major revisiting. I've decided to scrap the pass-thru approach
- * where every node simply represents an index and not an object.
- * The next update will have each node correspond to a specific object.
+ * Revision 1.17 2001/04/21 23:05:12 mpowers A fairly major revisiting. I've
+ * decided to scrap the pass-thru approach where every node simply represents an
+ * index and not an object. The next update will have each node correspond to a
+ * specific object.
*
- * Revision 1.16 2001/04/13 16:37:37 mpowers
- * Handling bounds checking.
+ * Revision 1.16 2001/04/13 16:37:37 mpowers Handling bounds checking.
*
- * Revision 1.15 2001/04/03 20:36:01 mpowers
- * Fixed refaulting/reverting/invalidating to be self-consistent.
+ * Revision 1.15 2001/04/03 20:36:01 mpowers Fixed
+ * refaulting/reverting/invalidating to be self-consistent.
*
- * Revision 1.14 2001/03/27 17:45:51 mpowers
- * More index bounds checking.
+ * Revision 1.14 2001/03/27 17:45:51 mpowers More index bounds checking.
*
- * Revision 1.13 2001/03/22 21:25:42 mpowers
- * Fixed some nasty issues with jtree's internal state and array bounds.
+ * Revision 1.13 2001/03/22 21:25:42 mpowers Fixed some nasty issues with
+ * jtree's internal state and array bounds.
*
- * Revision 1.12 2001/03/19 22:18:58 mpowers
- * Root node now mirrors contents of titles display group.
+ * Revision 1.12 2001/03/19 22:18:58 mpowers Root node now mirrors contents of
+ * titles display group.
*
- * Revision 1.11 2001/03/19 21:38:36 mpowers
- * Improved redisplay after edit. Editing nodes off root now works.
+ * Revision 1.11 2001/03/19 21:38:36 mpowers Improved redisplay after edit.
+ * Editing nodes off root now works.
*
- * Revision 1.10 2001/03/09 22:08:38 mpowers
- * Removed unused line.
+ * Revision 1.10 2001/03/09 22:08:38 mpowers Removed unused line.
*
- * Revision 1.9 2001/03/07 16:41:04 mpowers
- * Now checking size of parent displayed objects array so that we don't
- * get array out of bounds execeptions from isLeaf() or object() when
- * those messages are called after the TreeAssociation fires a
- * nodesDeleted event. I believe that JTree is mistakenly rendering
- * those nodes one last time before erasing them.
+ * Revision 1.9 2001/03/07 16:41:04 mpowers Now checking size of parent
+ * displayed objects array so that we don't get array out of bounds execeptions
+ * from isLeaf() or object() when those messages are called after the
+ * TreeAssociation fires a nodesDeleted event. I believe that JTree is
+ * mistakenly rendering those nodes one last time before erasing them.
*
- * Revision 1.8 2001/03/06 23:21:27 mpowers
- * Now only notifying parent if the object is not registered in the
- * editing context, if any.
+ * Revision 1.8 2001/03/06 23:21:27 mpowers Now only notifying parent if the
+ * object is not registered in the editing context, if any.
*
- * Revision 1.7 2001/02/20 16:38:55 mpowers
- * MasterDetailAssociations now observe their controlled display group's
- * objects for changes to that the parent object will be marked as updated.
- * Before, only inserts and deletes to an object's items are registered.
- * Also, moved ObservableArray to package access.
+ * Revision 1.7 2001/02/20 16:38:55 mpowers MasterDetailAssociations now observe
+ * their controlled display group's objects for changes to that the parent
+ * object will be marked as updated. Before, only inserts and deletes to an
+ * object's items are registered. Also, moved ObservableArray to package access.
*
- * Revision 1.6 2001/02/17 16:52:05 mpowers
- * Changes in imports to support building with jdk1.1 collections.
+ * Revision 1.6 2001/02/17 16:52:05 mpowers Changes in imports to support
+ * building with jdk1.1 collections.
*
- * Revision 1.5 2001/01/31 17:59:52 mpowers
- * Fixed isLeaf aspect of TreeAssociation.
+ * Revision 1.5 2001/01/31 17:59:52 mpowers Fixed isLeaf aspect of
+ * TreeAssociation.
*
- * Revision 1.4 2001/01/25 02:16:25 mpowers
- * TreeAssociation now returns DisplayGroupNode.getUserObject.
+ * Revision 1.4 2001/01/25 02:16:25 mpowers TreeAssociation now returns
+ * DisplayGroupNode.getUserObject.
*
- * Revision 1.3 2001/01/24 18:14:40 mpowers
- * Fixed problem with leaving children aspect unspecified.
+ * Revision 1.3 2001/01/24 18:14:40 mpowers Fixed problem with leaving children
+ * aspect unspecified.
*
- * Revision 1.2 2001/01/24 16:35:37 mpowers
- * Improved documentation on TreeAssociation.
- * SortOrderings are now inherited from parent nodes.
- * Updates after sorting are still lost on TreeController.
+ * Revision 1.2 2001/01/24 16:35:37 mpowers Improved documentation on
+ * TreeAssociation. SortOrderings are now inherited from parent nodes. Updates
+ * after sorting are still lost on TreeController.
*
- * Revision 1.1 2001/01/24 14:17:12 mpowers
- * Major revision to TreeAssociation. Can now add and remove nodes.
- * DisplayGroupNode is now it's own class.
+ * Revision 1.1 2001/01/24 14:17:12 mpowers Major revision to TreeAssociation.
+ * Can now add and remove nodes. DisplayGroupNode is now it's own class.
*
*
*/
-