summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.ui/src/main/java/net/wotonomy
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/src/main/java/net/wotonomy
parentff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff)
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.ui/src/main/java/net/wotonomy')
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DebuggingDelegate.java488
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DelegateAdapter.java380
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DisplayGroup.java490
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EOAssociation.java880
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EODisplayGroup.java4040
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/GenericAssociation.java586
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java605
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MirrorDetailAssociation.java134
-rw-r--r--projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/ObservableArray.java486
9 files changed, 3570 insertions, 4519 deletions
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DebuggingDelegate.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DebuggingDelegate.java
index 8e9fae2..3512c2a 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DebuggingDelegate.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DebuggingDelegate.java
@@ -24,310 +24,200 @@ import net.wotonomy.control.EODataSource;
import net.wotonomy.foundation.NSArray;
import net.wotonomy.foundation.NSNotification;
- /**
- * A display group delegate that prints messages for each
- * of the delegate methods.
- *
- * @author michael@mpowers.net
- * @author $Author: cgruber $
- * @version $Revision: 904 $
- */
- public class DebuggingDelegate implements EODisplayGroup.Delegate
- {
- /**
- * Called when the specified data source fails
- * to create an object for the specified display group.
- */
- public void displayGroupCreateObjectFailed (
- EODisplayGroup aDisplayGroup,
- EODataSource aDataSource )
- {
- report( "displayGroupCreateObjectFailed",
- aDisplayGroup,
- new Object[] { aDataSource } );
- }
-
- /**
- * Called after the specified display group's
- * data source is changed.
- */
- public void displayGroupDidChangeDataSource (
- EODisplayGroup aDisplayGroup )
- {
- report( "displayGroupDidChangeDataSource",
- aDisplayGroup,
- new Object[] { } );
- }
-
- /**
- * Called after the specified display group's
- * selection has changed.
- */
- public void displayGroupDidChangeSelectedObjects (
- EODisplayGroup aDisplayGroup )
- {
- report( "displayGroupDidChangeSelectedObjects",
- aDisplayGroup,
- new Object[] { } );
- }
-
- /**
- * Called after the specified display group's
- * selection has changed.
- */
- public void displayGroupDidChangeSelection (
- EODisplayGroup aDisplayGroup )
- {
- report( "displayGroupDidChangeSelection",
- aDisplayGroup,
- new Object[] { } );
- }
-
- /**
- * Called after the specified object display group's
- * selection has changed.
- */
- public void displayGroupDidDeleteObject (
- EODisplayGroup aDisplayGroup,
- Object anObject )
- {
- report( "displayGroupDidDeleteObject",
- aDisplayGroup,
- new Object[] { anObject } );
- }
-
- /**
- * Called after the specified display group
- * has fetched the specified object list.
- */
- public void displayGroupDidFetchObjects (
- EODisplayGroup aDisplayGroup,
- List anObjectList )
- {
- report( "displayGroupDidFetchObjects",
- aDisplayGroup,
- new Object[] { anObjectList } );
- }
-
- /**
- * Called after the specified display group
- * has inserted the specified object into
- * its internal object list.
- */
- public void displayGroupDidInsertObject (
- EODisplayGroup aDisplayGroup,
- Object anObject )
- {
- report( "displayGroupDidInsertObject",
- aDisplayGroup,
- new Object[] { anObject } );
- }
-
- /**
- * Called after the specified display group
- * has set the specified value for the specified
- * object and key.
- */
- public void displayGroupDidSetValueForObject (
- EODisplayGroup aDisplayGroup,
- Object aValue,
- Object anObject,
- String aKey )
- {
- report( "displayGroupDidSetValueForObject",
- aDisplayGroup,
- new Object[] { aValue, anObject, aKey } );
- }
-
- /**
- * Called by the specified display group to
- * determine what objects should be displayed
- * for the objects in the specified list.
- * @return An NSArray containing the objects
- * to be displayed for the objects in the
- * specified list.
- */
- public NSArray displayGroupDisplayArrayForObjects (
- EODisplayGroup aDisplayGroup,
- List aList )
- {
- return get( "displayGroupDisplayArrayForObjects",
- aDisplayGroup,
- aList );
- }
-
- /**
- * Called by the specified display group before
- * it attempts to change the selection.
- * This implementation returns true.
- * @return True to allow the selection to change,
- * false otherwise.
- */
- public boolean displayGroupShouldChangeSelection (
- EODisplayGroup aDisplayGroup,
- List aSelectionList )
- {
- return ask( "displayGroupShouldChangeSelection",
- aDisplayGroup,
- new Object[] { aSelectionList } );
- }
-
- /**
- * Called by the specified display group before
- * it attempts to delete the specified object.
- * This implementation returns true.
- * @return True to allow the object to be deleted
- * false to prevent the deletion.
- */
- public boolean displayGroupShouldDeleteObject (
- EODisplayGroup aDisplayGroup,
- Object anObject )
- {
- return ask( "displayGroupShouldDeleteObject",
- aDisplayGroup,
- new Object[] { anObject } );
- }
-
- /**
- * Called by the specified display group before
- * it attempts display the specified alert to
- * the user.
- * This implementation returns true.
- * @return True to allow the message to be
- * displayed, false if you want to handle the
- * alert yourself and suppress the display group's
- * notification.
- */
- public boolean displayGroupShouldDisplayAlert (
- EODisplayGroup aDisplayGroup,
- String aTitle,
- String aMessage )
- {
- return ask( "displayGroupShouldDisplayAlert",
- aDisplayGroup,
- new Object[] { aTitle, aMessage } );
- }
-
- /**
- * Called by the specified display group before
- * it attempts fetch objects.
- * This implementation returns true.
- * @return True to allow the fetch to take place,
- * false to prevent the fetch.
- */
- public boolean displayGroupShouldFetch (
- EODisplayGroup aDisplayGroup )
- {
- return ask( "displayGroupShouldFetch",
- aDisplayGroup,
- new Object[] { } );
- }
-
- /**
- * Called by the specified display group before
- * it attempts to insert the specified object.
- * This implementation returns true.
- * @return True to allow the object to be inserted
- * false to prevent the insertion.
- */
- public boolean displayGroupShouldInsertObject (
- EODisplayGroup aDisplayGroup,
- Object anObject,
- int anIndex )
- {
- return ask( "displayGroupShouldInsertObject",
- aDisplayGroup,
- new Object[] { anObject, new Integer( anIndex ) } );
- }
-
- /**
- * No idea what this might indicate,
- * nor what the notification indicates.
- * This implementation returns true.
- */
- public boolean displayGroupShouldRedisplay (
- EODisplayGroup aDisplayGroup,
- NSNotification aNotification )
- {
- return ask( "displayGroupShouldRedisplay",
- aDisplayGroup,
- new Object[] { aNotification } );
- }
-
- /**
- * No idea what this might indicate,
- * nor what the notification indicates.
- */
- public boolean displayGroupShouldRefetch (
- EODisplayGroup aDisplayGroup,
- NSNotification aNotification )
- {
- return ask( "displayGroupShouldRefetch",
- aDisplayGroup,
- new Object[] { aNotification } );
- }
-
- /**
- * This method is called by all delegate methods that
- * return void.
- * This implementation calls System.out.println.
- * Override to customize or replace the output.
- */
- protected void report( String aTitle,
- EODisplayGroup aDisplayGroup,
- Object[] aParameterArray )
- {
- String result = aTitle + " : " + aDisplayGroup;
- for ( int i = 0; i < aParameterArray.length; i++ )
- {
- result += " : " + aParameterArray[i];
- }
- System.out.println( result );
- }
-
- /**
- * This method is called by displayGroupDisplayArrayForObjects.
- * This implementation calls report
- * and returns a copy of the specified list.
- */
- protected NSArray get( String aTitle,
- EODisplayGroup aDisplayGroup,
- List anObjectList )
- {
- report( aTitle, aDisplayGroup, new Object[] { anObjectList } );
- return new NSArray( anObjectList );
- }
-
- /**
- * This method is called by the methods that
- * return a boolean.
- * This implementation calls report and return true.
- */
- protected boolean ask( String aTitle,
- EODisplayGroup aDisplayGroup,
- Object[] aParameterArray )
- {
- report( aTitle, aDisplayGroup, aParameterArray );
- return true;
- }
-
-
- }
+/**
+ * A display group delegate that prints messages for each of the delegate
+ * methods.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class DebuggingDelegate implements EODisplayGroup.Delegate {
+ /**
+ * Called when the specified data source fails to create an object for the
+ * specified display group.
+ */
+ public void displayGroupCreateObjectFailed(EODisplayGroup aDisplayGroup, EODataSource aDataSource) {
+ report("displayGroupCreateObjectFailed", aDisplayGroup, new Object[] { aDataSource });
+ }
+
+ /**
+ * Called after the specified display group's data source is changed.
+ */
+ public void displayGroupDidChangeDataSource(EODisplayGroup aDisplayGroup) {
+ report("displayGroupDidChangeDataSource", aDisplayGroup, new Object[] {});
+ }
+
+ /**
+ * Called after the specified display group's selection has changed.
+ */
+ public void displayGroupDidChangeSelectedObjects(EODisplayGroup aDisplayGroup) {
+ report("displayGroupDidChangeSelectedObjects", aDisplayGroup, new Object[] {});
+ }
+
+ /**
+ * Called after the specified display group's selection has changed.
+ */
+ public void displayGroupDidChangeSelection(EODisplayGroup aDisplayGroup) {
+ report("displayGroupDidChangeSelection", aDisplayGroup, new Object[] {});
+ }
+
+ /**
+ * Called after the specified object display group's selection has changed.
+ */
+ public void displayGroupDidDeleteObject(EODisplayGroup aDisplayGroup, Object anObject) {
+ report("displayGroupDidDeleteObject", aDisplayGroup, new Object[] { anObject });
+ }
+
+ /**
+ * Called after the specified display group has fetched the specified object
+ * list.
+ */
+ public void displayGroupDidFetchObjects(EODisplayGroup aDisplayGroup, List anObjectList) {
+ report("displayGroupDidFetchObjects", aDisplayGroup, new Object[] { anObjectList });
+ }
+
+ /**
+ * Called after the specified display group has inserted the specified object
+ * into its internal object list.
+ */
+ public void displayGroupDidInsertObject(EODisplayGroup aDisplayGroup, Object anObject) {
+ report("displayGroupDidInsertObject", aDisplayGroup, new Object[] { anObject });
+ }
+
+ /**
+ * Called after the specified display group has set the specified value for the
+ * specified object and key.
+ */
+ public void displayGroupDidSetValueForObject(EODisplayGroup aDisplayGroup, Object aValue, Object anObject,
+ String aKey) {
+ report("displayGroupDidSetValueForObject", aDisplayGroup, new Object[] { aValue, anObject, aKey });
+ }
+
+ /**
+ * Called by the specified display group to determine what objects should be
+ * displayed for the objects in the specified list.
+ *
+ * @return An NSArray containing the objects to be displayed for the objects in
+ * the specified list.
+ */
+ public NSArray displayGroupDisplayArrayForObjects(EODisplayGroup aDisplayGroup, List aList) {
+ return get("displayGroupDisplayArrayForObjects", aDisplayGroup, aList);
+ }
+
+ /**
+ * Called by the specified display group before it attempts to change the
+ * selection. This implementation returns true.
+ *
+ * @return True to allow the selection to change, false otherwise.
+ */
+ public boolean displayGroupShouldChangeSelection(EODisplayGroup aDisplayGroup, List aSelectionList) {
+ return ask("displayGroupShouldChangeSelection", aDisplayGroup, new Object[] { aSelectionList });
+ }
+
+ /**
+ * Called by the specified display group before it attempts to delete the
+ * specified object. This implementation returns true.
+ *
+ * @return True to allow the object to be deleted false to prevent the deletion.
+ */
+ public boolean displayGroupShouldDeleteObject(EODisplayGroup aDisplayGroup, Object anObject) {
+ return ask("displayGroupShouldDeleteObject", aDisplayGroup, new Object[] { anObject });
+ }
+
+ /**
+ * Called by the specified display group before it attempts display the
+ * specified alert to the user. This implementation returns true.
+ *
+ * @return True to allow the message to be displayed, false if you want to
+ * handle the alert yourself and suppress the display group's
+ * notification.
+ */
+ public boolean displayGroupShouldDisplayAlert(EODisplayGroup aDisplayGroup, String aTitle, String aMessage) {
+ return ask("displayGroupShouldDisplayAlert", aDisplayGroup, new Object[] { aTitle, aMessage });
+ }
+
+ /**
+ * Called by the specified display group before it attempts fetch objects. This
+ * implementation returns true.
+ *
+ * @return True to allow the fetch to take place, false to prevent the fetch.
+ */
+ public boolean displayGroupShouldFetch(EODisplayGroup aDisplayGroup) {
+ return ask("displayGroupShouldFetch", aDisplayGroup, new Object[] {});
+ }
+
+ /**
+ * Called by the specified display group before it attempts to insert the
+ * specified object. This implementation returns true.
+ *
+ * @return True to allow the object to be inserted false to prevent the
+ * insertion.
+ */
+ public boolean displayGroupShouldInsertObject(EODisplayGroup aDisplayGroup, Object anObject, int anIndex) {
+ return ask("displayGroupShouldInsertObject", aDisplayGroup, new Object[] { anObject, new Integer(anIndex) });
+ }
+
+ /**
+ * No idea what this might indicate, nor what the notification indicates. This
+ * implementation returns true.
+ */
+ public boolean displayGroupShouldRedisplay(EODisplayGroup aDisplayGroup, NSNotification aNotification) {
+ return ask("displayGroupShouldRedisplay", aDisplayGroup, new Object[] { aNotification });
+ }
+
+ /**
+ * No idea what this might indicate, nor what the notification indicates.
+ */
+ public boolean displayGroupShouldRefetch(EODisplayGroup aDisplayGroup, NSNotification aNotification) {
+ return ask("displayGroupShouldRefetch", aDisplayGroup, new Object[] { aNotification });
+ }
+
+ /**
+ * This method is called by all delegate methods that return void. This
+ * implementation calls System.out.println. Override to customize or replace the
+ * output.
+ */
+ protected void report(String aTitle, EODisplayGroup aDisplayGroup, Object[] aParameterArray) {
+ String result = aTitle + " : " + aDisplayGroup;
+ for (int i = 0; i < aParameterArray.length; i++) {
+ result += " : " + aParameterArray[i];
+ }
+ System.out.println(result);
+ }
+
+ /**
+ * This method is called by displayGroupDisplayArrayForObjects. This
+ * implementation calls report and returns a copy of the specified list.
+ */
+ protected NSArray get(String aTitle, EODisplayGroup aDisplayGroup, List anObjectList) {
+ report(aTitle, aDisplayGroup, new Object[] { anObjectList });
+ return new NSArray(anObjectList);
+ }
+
+ /**
+ * This method is called by the methods that return a boolean. This
+ * implementation calls report and return true.
+ */
+ protected boolean ask(String aTitle, EODisplayGroup aDisplayGroup, Object[] aParameterArray) {
+ report(aTitle, aDisplayGroup, aParameterArray);
+ return true;
+ }
+
+}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.2 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.2 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.1 2001/01/24 14:37:24 mpowers
- * Contributing a delegate useful for debugging.
+ * Revision 1.1 2001/01/24 14:37:24 mpowers Contributing a delegate useful for
+ * debugging.
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DelegateAdapter.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DelegateAdapter.java
index ed572f4..e801406 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DelegateAdapter.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DelegateAdapter.java
@@ -24,234 +24,168 @@ import net.wotonomy.control.EODataSource;
import net.wotonomy.foundation.NSArray;
import net.wotonomy.foundation.NSNotification;
- /**
- * A convenience class for creating display group delegates.
- * All methods of the delegate interface are implemented
- * to do nothing.
- *
- * @author michael@mpowers.net
- * @author $Author: cgruber $
- * @version $Revision: 904 $
- */
- public class DelegateAdapter implements EODisplayGroup.Delegate
- {
- /**
- * Called when the specified data source fails
- * to create an object for the specified display group.
- */
- public void displayGroupCreateObjectFailed (
- EODisplayGroup aDisplayGroup,
- EODataSource aDataSource )
- {
-
- }
-
- /**
- * Called after the specified display group's
- * data source is changed.
- */
- public void displayGroupDidChangeDataSource (
- EODisplayGroup aDisplayGroup )
- {
-
- }
-
- /**
- * Called after the specified display group's
- * selection has changed.
- */
- public void displayGroupDidChangeSelectedObjects (
- EODisplayGroup aDisplayGroup )
- {
-
- }
-
- /**
- * Called after the specified display group's
- * selection has changed.
- */
- public void displayGroupDidChangeSelection (
- EODisplayGroup aDisplayGroup )
- {
-
- }
-
- /**
- * Called after the specified object display group's
- * selection has changed.
- */
- public void displayGroupDidDeleteObject (
- EODisplayGroup aDisplayGroup,
- Object anObject )
- {
-
- }
-
- /**
- * Called after the specified display group
- * has fetched the specified object list.
- */
- public void displayGroupDidFetchObjects (
- EODisplayGroup aDisplayGroup,
- List anObjectList )
- {
-
- }
-
- /**
- * Called after the specified display group
- * has inserted the specified object into
- * its internal object list.
- */
- public void displayGroupDidInsertObject (
- EODisplayGroup aDisplayGroup,
- Object anObject )
- {
-
- }
-
- /**
- * Called after the specified display group
- * has set the specified value for the specified
- * object and key.
- */
- public void displayGroupDidSetValueForObject (
- EODisplayGroup aDisplayGroup,
- Object aValue,
- Object anObject,
- String aKey )
- {
-
- }
-
- /**
- * Called by the specified display group to
- * determine what objects should be displayed
- * for the objects in the specified list.
- * @return An NSArray containing the objects
- * to be displayed for the objects in the
- * specified list.
- */
- public NSArray displayGroupDisplayArrayForObjects (
- EODisplayGroup aDisplayGroup,
- List aList )
- {
- return new NSArray( aList );
- }
-
- /**
- * Called by the specified display group before
- * it attempts to change the selection.
- * This implementation returns true.
- * @return True to allow the selection to change,
- * false otherwise.
- */
- public boolean displayGroupShouldChangeSelection (
- EODisplayGroup aDisplayGroup,
- List aSelectionList )
- {
- return true;
- }
-
- /**
- * Called by the specified display group before
- * it attempts to delete the specified object.
- * This implementation returns true.
- * @return True to allow the object to be deleted
- * false to prevent the deletion.
- */
- public boolean displayGroupShouldDeleteObject (
- EODisplayGroup aDisplayGroup,
- Object anObject )
- {
- return true;
- }
-
- /**
- * Called by the specified display group before
- * it attempts display the specified alert to
- * the user.
- * This implementation returns true.
- * @return True to allow the message to be
- * displayed, false if you want to handle the
- * alert yourself and suppress the display group's
- * notification.
- */
- public boolean displayGroupShouldDisplayAlert (
- EODisplayGroup aDisplayGroup,
- String aTitle,
- String aMessage )
- {
- return true;
- }
-
- /**
- * Called by the specified display group before
- * it attempts fetch objects.
- * This implementation returns true.
- * @return True to allow the fetch to take place,
- * false to prevent the fetch.
- */
- public boolean displayGroupShouldFetch (
- EODisplayGroup aDisplayGroup )
- {
- return true;
- }
-
- /**
- * Called by the specified display group before
- * it attempts to insert the specified object.
- * This implementation returns true.
- * @return True to allow the object to be inserted
- * false to prevent the insertion.
- */
- public boolean displayGroupShouldInsertObject (
- EODisplayGroup aDisplayGroup,
- Object anObject,
- int anIndex )
- {
- return true;
- }
-
- /**
- * No idea what this might indicate,
- * nor what the notification indicates.
- * This implementation returns true.
- */
- public boolean displayGroupShouldRedisplay (
- EODisplayGroup aDisplayGroup,
- NSNotification aNotification )
- {
- return true;
- }
-
- /**
- * No idea what this might indicate,
- * nor what the notification indicates.
- */
- public boolean displayGroupShouldRefetch (
- EODisplayGroup aDisplayGroup,
- NSNotification aNotification )
- {
- return true;
- }
-
- }
+/**
+ * A convenience class for creating display group delegates. All methods of the
+ * delegate interface are implemented to do nothing.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class DelegateAdapter implements EODisplayGroup.Delegate {
+ /**
+ * Called when the specified data source fails to create an object for the
+ * specified display group.
+ */
+ public void displayGroupCreateObjectFailed(EODisplayGroup aDisplayGroup, EODataSource aDataSource) {
+
+ }
+
+ /**
+ * Called after the specified display group's data source is changed.
+ */
+ public void displayGroupDidChangeDataSource(EODisplayGroup aDisplayGroup) {
+
+ }
+
+ /**
+ * Called after the specified display group's selection has changed.
+ */
+ public void displayGroupDidChangeSelectedObjects(EODisplayGroup aDisplayGroup) {
+
+ }
+
+ /**
+ * Called after the specified display group's selection has changed.
+ */
+ public void displayGroupDidChangeSelection(EODisplayGroup aDisplayGroup) {
+
+ }
+
+ /**
+ * Called after the specified object display group's selection has changed.
+ */
+ public void displayGroupDidDeleteObject(EODisplayGroup aDisplayGroup, Object anObject) {
+
+ }
+
+ /**
+ * Called after the specified display group has fetched the specified object
+ * list.
+ */
+ public void displayGroupDidFetchObjects(EODisplayGroup aDisplayGroup, List anObjectList) {
+
+ }
+
+ /**
+ * Called after the specified display group has inserted the specified object
+ * into its internal object list.
+ */
+ public void displayGroupDidInsertObject(EODisplayGroup aDisplayGroup, Object anObject) {
+
+ }
+
+ /**
+ * Called after the specified display group has set the specified value for the
+ * specified object and key.
+ */
+ public void displayGroupDidSetValueForObject(EODisplayGroup aDisplayGroup, Object aValue, Object anObject,
+ String aKey) {
+
+ }
+
+ /**
+ * Called by the specified display group to determine what objects should be
+ * displayed for the objects in the specified list.
+ *
+ * @return An NSArray containing the objects to be displayed for the objects in
+ * the specified list.
+ */
+ public NSArray displayGroupDisplayArrayForObjects(EODisplayGroup aDisplayGroup, List aList) {
+ return new NSArray(aList);
+ }
+
+ /**
+ * Called by the specified display group before it attempts to change the
+ * selection. This implementation returns true.
+ *
+ * @return True to allow the selection to change, false otherwise.
+ */
+ public boolean displayGroupShouldChangeSelection(EODisplayGroup aDisplayGroup, List aSelectionList) {
+ return true;
+ }
+
+ /**
+ * Called by the specified display group before it attempts to delete the
+ * specified object. This implementation returns true.
+ *
+ * @return True to allow the object to be deleted false to prevent the deletion.
+ */
+ public boolean displayGroupShouldDeleteObject(EODisplayGroup aDisplayGroup, Object anObject) {
+ return true;
+ }
+
+ /**
+ * Called by the specified display group before it attempts display the
+ * specified alert to the user. This implementation returns true.
+ *
+ * @return True to allow the message to be displayed, false if you want to
+ * handle the alert yourself and suppress the display group's
+ * notification.
+ */
+ public boolean displayGroupShouldDisplayAlert(EODisplayGroup aDisplayGroup, String aTitle, String aMessage) {
+ return true;
+ }
+
+ /**
+ * Called by the specified display group before it attempts fetch objects. This
+ * implementation returns true.
+ *
+ * @return True to allow the fetch to take place, false to prevent the fetch.
+ */
+ public boolean displayGroupShouldFetch(EODisplayGroup aDisplayGroup) {
+ return true;
+ }
+
+ /**
+ * Called by the specified display group before it attempts to insert the
+ * specified object. This implementation returns true.
+ *
+ * @return True to allow the object to be inserted false to prevent the
+ * insertion.
+ */
+ public boolean displayGroupShouldInsertObject(EODisplayGroup aDisplayGroup, Object anObject, int anIndex) {
+ return true;
+ }
+
+ /**
+ * No idea what this might indicate, nor what the notification indicates. This
+ * implementation returns true.
+ */
+ public boolean displayGroupShouldRedisplay(EODisplayGroup aDisplayGroup, NSNotification aNotification) {
+ return true;
+ }
+
+ /**
+ * No idea what this might indicate, nor what the notification indicates.
+ */
+ public boolean displayGroupShouldRefetch(EODisplayGroup aDisplayGroup, NSNotification aNotification) {
+ return true;
+ }
+
+}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.2 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.2 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.1 2001/01/24 14:23:17 mpowers
- * Contributing DelegateAdapter.
+ * Revision 1.1 2001/01/24 14:23:17 mpowers Contributing DelegateAdapter.
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DisplayGroup.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DisplayGroup.java
index 9fcbe34..d7dd8d8 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DisplayGroup.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/DisplayGroup.java
@@ -25,276 +25,236 @@ import net.wotonomy.control.EODataSource;
import net.wotonomy.control.EOQualifier;
/**
-* DisplayGroup provides an abstraction of a user interface,
-* comprising of an ordered collection of data objects, some
-* of which are displayed, and of those some are selected.
-* This class extends EODisplayGroup to provide java-friendly
-* convenience methods.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class DisplayGroup extends EODisplayGroup
-{
- /**
- * Returns the current data source backing this display group,
- * or null if no dataSource is currently used.
- */
- public EODataSource getDataSource()
- {
- return super.dataSource();
- }
-
- /**
- * Returns the current delegate for this display group,
- * or null if no delegate is currently set.
- */
- public Object getDelegate()
- {
- return delegate();
- }
-
- /**
- * Returns the current string matching format.
- * If not set, defaults to "%@*".
- */
- public String getDefaultStringMatchFormat()
- {
- return defaultStringMatchFormat();
- }
-
- /**
- * Returns the current string matching operator.
- * If not set, defaults to "caseInsensitiveLike".
- */
- public String getdefaultStringMatchOperator()
- {
- return defaultStringMatchOperator();
- }
-
- /**
- * Returns a Map of default values that are applied
- * to new objects that are inserted into the list.
- */
- public Map getInsertedObjectDefaultValues()
- {
- return insertedObjectDefaultValues();
- }
-
- /**
- * Returns the keys that were declared when read from
- * an external resource file.
- */
- public List getLocalKeys()
- {
- return localKeys();
- }
-
- /**
- * Returns the List of sort orderings for this display group.
- */
- public List getSortOrderings ()
- {
- return sortOrderings();
- }
-
- /**
- * Returns a qualifier that will be applied all the objects
- * in this display group to determine which objects will
- * be displayed.
- */
- public EOQualifier getQualifier ()
- {
- return qualifier();
- }
-
- /**
- * Returns a new qualifier built from the three query
- * value maps: greater than, equal to, and less than.
- */
- public EOQualifier getQualifierFromQueryValues ()
- {
- return qualifierFromQueryValues();
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to binding query values.
- */
- public Map getQueryBindingValues()
- {
- return queryBindingValues();
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to operator values.
- */
- public Map getQueryOperatorValues()
- {
- return queryOperatorValues();
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to query values that will be used to test for equality.
- */
- public Map getEqualToQueryValues()
- {
- return equalToQueryValues();
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to query values that will be used to test for greater value.
- */
- public Map getGreaterThanQueryValues()
- {
- return greaterThanQueryValues();
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to query values that will be used to test for lesser value.
- */
- public Map getLessThanQueryValues()
- {
- return lessThanQueryValues();
- }
-
- /**
- * Returns the association that is currently being edited,
- * or null if no editing is taking place.
- */
- public EOAssociation getEditingAssociation ()
- {
- return editingAssociation();
- }
-
- /**
- * Returns a List of associations that are observing
- * this display group.
- */
- public List getObservingAssociations()
- {
- return observingAssociations();
- }
-
- /**
- * Returns a List containing all objects managed by the display group.
- * This includes those objects not visible due to disqualification.
- */
- public List getAllObjects()
- {
- return allObjects();
- }
-
- /**
- * Returns a List of all objects in the display group
- * that are currently displayed by the associations.
- * The list is a copy of the internal displayed object list.
- */
- public List getDisplayedObjects()
- {
- return displayedObjects();
- }
-
- /**
- * Returns the currently selected object, or null if
- * there is no selection.
- */
- public Object getSelectedObject()
- {
- return selectedObject();
- }
-
- /**
- * Returns a List containing all selected objects, if any.
- * Returns an empty list if no objects are selected.
- */
- public List getSelectedObjects()
- {
- return selectedObjects();
- }
-
- /**
- * Returns a List containing the indexes of all selected
- * objects, if any. The list contains instances of
- * java.lang.Number; call intValue() retrieve the index.
- */
- public List getSelectionIndexes()
- {
- return selectionIndexes();
- }
-
- /**
- * Returns the index of the changed object. If more than
- * one object has changed, -1 is returned.
- */
- public int getUpdatedObjectIndex()
- {
- return updatedObjectIndex();
- }
-
- /**
- * Returns a value on the selected object for the specified key.
- */
- public Object getSelectedObjectValueForKey ( String aKey )
- {
- return selectedObjectValueForKey( aKey );
- }
-
- /**
- * Returns the value for the specified key on the specified object.
- */
- public Object getValueForObject ( Object anObject, String aKey )
- {
- return valueForObject( anObject, aKey );
- }
-
- /**
- * Calls valueForObject() for the object at the specified index.
- */
- public Object getValueForObjectAtIndex ( int anIndex, String aKey )
- {
- return valueForObjectAtIndex( anIndex, aKey );
- }
-
- /**
- * Specifies the default string matching format for all
- * display groups.
- */
- public static String getGlobalDefaultStringMatchFormat ()
- {
- return globalDefaultStringMatchFormat();
- }
-
- /**
- * Specifies the default string matching operator for all
- * display groups.
- */
- public static String getGlobalDefaultStringMatchOperator ()
- {
- return globalDefaultStringMatchOperator();
- }
-}
+ * DisplayGroup provides an abstraction of a user interface, comprising of an
+ * ordered collection of data objects, some of which are displayed, and of those
+ * some are selected. This class extends EODisplayGroup to provide java-friendly
+ * convenience methods.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class DisplayGroup extends EODisplayGroup {
+ /**
+ * Returns the current data source backing this display group, or null if no
+ * dataSource is currently used.
+ */
+ public EODataSource getDataSource() {
+ return super.dataSource();
+ }
+
+ /**
+ * Returns the current delegate for this display group, or null if no delegate
+ * is currently set.
+ */
+ public Object getDelegate() {
+ return delegate();
+ }
+
+ /**
+ * Returns the current string matching format. If not set, defaults to "%@*".
+ */
+ public String getDefaultStringMatchFormat() {
+ return defaultStringMatchFormat();
+ }
+
+ /**
+ * Returns the current string matching operator. If not set, defaults to
+ * "caseInsensitiveLike".
+ */
+ public String getdefaultStringMatchOperator() {
+ return defaultStringMatchOperator();
+ }
+
+ /**
+ * Returns a Map of default values that are applied to new objects that are
+ * inserted into the list.
+ */
+ public Map getInsertedObjectDefaultValues() {
+ return insertedObjectDefaultValues();
+ }
+
+ /**
+ * Returns the keys that were declared when read from an external resource file.
+ */
+ public List getLocalKeys() {
+ return localKeys();
+ }
+
+ /**
+ * Returns the List of sort orderings for this display group.
+ */
+ public List getSortOrderings() {
+ return sortOrderings();
+ }
+
+ /**
+ * Returns a qualifier that will be applied all the objects in this display
+ * group to determine which objects will be displayed.
+ */
+ public EOQualifier getQualifier() {
+ return qualifier();
+ }
+
+ /**
+ * Returns a new qualifier built from the three query value maps: greater than,
+ * equal to, and less than.
+ */
+ public EOQualifier getQualifierFromQueryValues() {
+ return qualifierFromQueryValues();
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to binding query values.
+ */
+ public Map getQueryBindingValues() {
+ return queryBindingValues();
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to operator values.
+ */
+ public Map getQueryOperatorValues() {
+ return queryOperatorValues();
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to query values that will be
+ * used to test for equality.
+ */
+ public Map getEqualToQueryValues() {
+ return equalToQueryValues();
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to query values that will be
+ * used to test for greater value.
+ */
+ public Map getGreaterThanQueryValues() {
+ return greaterThanQueryValues();
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to query values that will be
+ * used to test for lesser value.
+ */
+ public Map getLessThanQueryValues() {
+ return lessThanQueryValues();
+ }
+
+ /**
+ * Returns the association that is currently being edited, or null if no editing
+ * is taking place.
+ */
+ public EOAssociation getEditingAssociation() {
+ return editingAssociation();
+ }
+
+ /**
+ * Returns a List of associations that are observing this display group.
+ */
+ public List getObservingAssociations() {
+ return observingAssociations();
+ }
+
+ /**
+ * Returns a List containing all objects managed by the display group. This
+ * includes those objects not visible due to disqualification.
+ */
+ public List getAllObjects() {
+ return allObjects();
+ }
+
+ /**
+ * Returns a List of all objects in the display group that are currently
+ * displayed by the associations. The list is a copy of the internal displayed
+ * object list.
+ */
+ public List getDisplayedObjects() {
+ return displayedObjects();
+ }
+
+ /**
+ * Returns the currently selected object, or null if there is no selection.
+ */
+ public Object getSelectedObject() {
+ return selectedObject();
+ }
+
+ /**
+ * Returns a List containing all selected objects, if any. Returns an empty list
+ * if no objects are selected.
+ */
+ public List getSelectedObjects() {
+ return selectedObjects();
+ }
+
+ /**
+ * Returns a List containing the indexes of all selected objects, if any. The
+ * list contains instances of java.lang.Number; call intValue() retrieve the
+ * index.
+ */
+ public List getSelectionIndexes() {
+ return selectionIndexes();
+ }
+
+ /**
+ * Returns the index of the changed object. If more than one object has changed,
+ * -1 is returned.
+ */
+ public int getUpdatedObjectIndex() {
+ return updatedObjectIndex();
+ }
+
+ /**
+ * Returns a value on the selected object for the specified key.
+ */
+ public Object getSelectedObjectValueForKey(String aKey) {
+ return selectedObjectValueForKey(aKey);
+ }
+
+ /**
+ * Returns the value for the specified key on the specified object.
+ */
+ public Object getValueForObject(Object anObject, String aKey) {
+ return valueForObject(anObject, aKey);
+ }
+
+ /**
+ * Calls valueForObject() for the object at the specified index.
+ */
+ public Object getValueForObjectAtIndex(int anIndex, String aKey) {
+ return valueForObjectAtIndex(anIndex, aKey);
+ }
+
+ /**
+ * Specifies the default string matching format for all display groups.
+ */
+ public static String getGlobalDefaultStringMatchFormat() {
+ return globalDefaultStringMatchFormat();
+ }
+
+ /**
+ * Specifies the default string matching operator for all display groups.
+ */
+ public static String getGlobalDefaultStringMatchOperator() {
+ return globalDefaultStringMatchOperator();
+ }
+}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.2 2002/05/17 15:01:49 mpowers
- * Implemented dynamic lookup of delegate methods so delegates no longer
- * need to implement the DisplayGroup.Delegate interface.
+ * Revision 1.2 2002/05/17 15:01:49 mpowers Implemented dynamic lookup of
+ * delegate methods so delegates no longer need to implement the
+ * DisplayGroup.Delegate interface.
*
- * Revision 1.1 2002/03/26 21:24:43 mpowers
- * Contributing DisplayGroup as convenience for people coming from java.
+ * Revision 1.1 2002/03/26 21:24:43 mpowers Contributing DisplayGroup as
+ * convenience for people coming from java.
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EOAssociation.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EOAssociation.java
index 635c5b9..8fb0527 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EOAssociation.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EOAssociation.java
@@ -27,36 +27,34 @@ import net.wotonomy.foundation.NSMutableArray;
import net.wotonomy.foundation.NSMutableDictionary;
/**
-* Associations observe DisplayGroups and associate
-* a user interface component with one or more keys
-* on the objects in the display group. <br><br>
-*
-* Associations are created with a ui component in
-* the constructor. Then, one or more aspects are
-* bound to display groups and/or property keys with
-* the bindAspect() method. Finally, the association
-* is initialized with the establishConnection()
-* method. <br><br>
-*
-* Per the openstep convention, you do not need to
-* retain a reference to the association after it is
-* created; the association will be garbage-collected
-* when the ui component is garbage-collected. <br><br>
-*
-* (Because java components don't have delegates like
-* openstep components do, java-based associations
-* will likely need to implement some sort of listener
-* and add itself to the component's list of listeners
-* so that the component will have a strong reference
-* (and the only reference) to the association.) <br><br>
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class EOAssociation extends EODelayedObserver
-{
- // aspect constants
+ * Associations observe DisplayGroups and associate a user interface component
+ * with one or more keys on the objects in the display group. <br>
+ * <br>
+ *
+ * Associations are created with a ui component in the constructor. Then, one or
+ * more aspects are bound to display groups and/or property keys with the
+ * bindAspect() method. Finally, the association is initialized with the
+ * establishConnection() method. <br>
+ * <br>
+ *
+ * Per the openstep convention, you do not need to retain a reference to the
+ * association after it is created; the association will be garbage-collected
+ * when the ui component is garbage-collected. <br>
+ * <br>
+ *
+ * (Because java components don't have delegates like openstep components do,
+ * java-based associations will likely need to implement some sort of listener
+ * and add itself to the component's list of listeners so that the component
+ * will have a strong reference (and the only reference) to the association.)
+ * <br>
+ * <br>
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class EOAssociation extends EODelayedObserver {
+ // aspect constants
public static final String ActionAspect = "action";
public static final String EnabledAspect = "enabled";
public static final String SourceAspect = "source";
@@ -77,489 +75,405 @@ public class EOAssociation extends EODelayedObserver
public static final String ObjectsAspect = "objects"; // not in spec
public static final String LabelAspect = "label"; // not in spec
public static final String IconAspect = "icon"; // not in spec
-
+
public static final String AttributeAspectSignature = "A";
public static final String NullAspectSignature = "";
- public static final String AttributeToOneAspectSignature = "A1";
+ public static final String AttributeToOneAspectSignature = "A1";
public static final String ToOneAspectSignature = "1";
- public static final String AttributeToOneToManyAspectSignature = "A1M";
+ public static final String AttributeToOneToManyAspectSignature = "A1M";
public static final String ToOneToManyAspectSignature = "1M";
public static final String AttributeToManyAspectSignature = "AM";
public static final String ToManyAspectSignature = "M";
-
- protected Object control;
- protected NSMutableDictionary aspectToGroup;
- protected NSMutableDictionary aspectToKey;
-
- /**
- * Default constructor.
- */
- public EOAssociation ()
- {
- aspectToGroup = new NSMutableDictionary();
- aspectToKey = new NSMutableDictionary();
- control = null;
- }
-
- /**
- * Constructor specifying the object to be controlled by this
- * association. Does not establish connection.
- */
- public EOAssociation ( Object anObject )
- {
- this();
- control = anObject;
- }
-
- /**
- * 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. <ul>
- * <li>"A" attribute: the aspect can be bound to
- * an attribute.</li>
- * <li>"1" to-one: the aspect can be bound to a
- * property that returns a single object.</li>
- * <li>"M" to-one: the aspect can be bound to a
- * property that returns multiple objects.</li>
- * </ul>
- * An empty signature "" means that the aspect can
- * bind without needing a key.
- * This implementation returns "A1M" for each
- * element in the aspects array.
- */
- public static NSArray aspectSignatures ()
- {
- int size = aspects().count();
- NSMutableArray result = new NSMutableArray();
- for ( int i = 0; i < size; i++ )
- {
- result.addObject( AttributeToOneToManyAspectSignature );
- }
- return result;
- }
-
- /**
- * 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.
- *
- * TODO: Is this static in the WebObjects published API? If not, fix.
- */
- public static NSArray aspects ()
- {
- return new NSArray();
- }
-
- /**
- * Returns all registered subclasses of EOAssociation
- * for which usableWithObject with the specified object
- * returns true. You should only call this method on
- * the EOAssociation class.
- */
- public static NSArray associationClassesForObject (
- Object anObject )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Returns a List of EOAssociation subclasses that,
- * for the objects that are usable for this association,
- * are less suitable than this association.
- * This implementation returns an empty list.
- */
- public static NSArray associationClassesSuperseded ()
- {
- return new NSArray();
- }
-
-
- /**
- * Binds the specified aspect of this association to the
- * specified key on the specified display group.
- */
- public void bindAspect (
- String anAspect, EODisplayGroup aDisplayGroup, String aKey )
- {
+
+ protected Object control;
+ protected NSMutableDictionary aspectToGroup;
+ protected NSMutableDictionary aspectToKey;
+
+ /**
+ * Default constructor.
+ */
+ public EOAssociation() {
+ aspectToGroup = new NSMutableDictionary();
+ aspectToKey = new NSMutableDictionary();
+ control = null;
+ }
+
+ /**
+ * Constructor specifying the object to be controlled by this association. Does
+ * not establish connection.
+ */
+ public EOAssociation(Object anObject) {
+ this();
+ control = anObject;
+ }
+
+ /**
+ * 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.
+ * <ul>
+ * <li>"A" attribute: the aspect can be bound to an attribute.</li>
+ * <li>"1" to-one: the aspect can be bound to a property that returns a single
+ * object.</li>
+ * <li>"M" to-one: the aspect can be bound to a property that returns multiple
+ * objects.</li>
+ * </ul>
+ * An empty signature "" means that the aspect can bind without needing a key.
+ * This implementation returns "A1M" for each element in the aspects array.
+ */
+ public static NSArray aspectSignatures() {
+ int size = aspects().count();
+ NSMutableArray result = new NSMutableArray();
+ for (int i = 0; i < size; i++) {
+ result.addObject(AttributeToOneToManyAspectSignature);
+ }
+ return result;
+ }
+
+ /**
+ * 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.
+ *
+ * TODO: Is this static in the WebObjects published API? If not, fix.
+ */
+ public static NSArray aspects() {
+ return new NSArray();
+ }
+
+ /**
+ * Returns all registered subclasses of EOAssociation for which usableWithObject
+ * with the specified object returns true. You should only call this method on
+ * the EOAssociation class.
+ */
+ public static NSArray associationClassesForObject(Object anObject) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Returns a List of EOAssociation subclasses that, for the objects that are
+ * usable for this association, are less suitable than this association. This
+ * implementation returns an empty list.
+ */
+ public static NSArray associationClassesSuperseded() {
+ return new NSArray();
+ }
+
+ /**
+ * Binds the specified aspect of this association to the specified key on the
+ * specified display group.
+ */
+ public void bindAspect(String anAspect, EODisplayGroup aDisplayGroup, String aKey) {
// unattach old group, if any
- EODisplayGroup oldGroup = displayGroupForAspect( anAspect );
- if ( oldGroup != null )
- {
- EOObserverCenter.removeObserver( this, oldGroup );
+ EODisplayGroup oldGroup = displayGroupForAspect(anAspect);
+ if (oldGroup != null) {
+ EOObserverCenter.removeObserver(this, oldGroup);
}
// attach new group
- if ( aDisplayGroup != null )
- {
- aspectToGroup.setObjectForKey( aDisplayGroup, anAspect );
- }
- else
- {
- aspectToGroup.removeObjectForKey( anAspect );
+ if (aDisplayGroup != null) {
+ aspectToGroup.setObjectForKey(aDisplayGroup, anAspect);
+ } else {
+ aspectToGroup.removeObjectForKey(anAspect);
}
// attach new key
- if ( aKey != null )
- {
- aspectToKey.setObjectForKey( aKey, anAspect );
+ if (aKey != null) {
+ aspectToKey.setObjectForKey(aKey, anAspect);
+ } else {
+ aspectToKey.removeObjectForKey(anAspect);
}
- else
- {
- aspectToKey.removeObjectForKey( anAspect );
+ }
+
+ /**
+ * Breaks the connection between this association and its object. Override to
+ * stop listening for events from the object, but remember to call this method.
+ * This implementation unregisters this association from observing each bound
+ * display group.
+ */
+ public void breakConnection() {
+ discardPendingNotification();
+ Enumeration e = aspectToGroup.objectEnumerator();
+ while (e.hasMoreElements()) {
+ EOObserverCenter.removeObserver(this, e.nextElement());
}
- }
-
- /**
- * Breaks the connection between this association and
- * its object. Override to stop listening for events
- * from the object, but remember to call this method.
- * This implementation unregisters this association
- * from observing each bound display group.
- */
- public void breakConnection ()
- {
- discardPendingNotification();
- Enumeration e = aspectToGroup.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- EOObserverCenter.removeObserver( this, e.nextElement() );
+ }
+
+ /**
+ * Returns whether this association can bind to the specified display group on
+ * the specified key for the specified aspect. This implementation returns
+ * false.
+ */
+ public boolean canBindAspect(String anAspect, EODisplayGroup aDisplayGroup, String aKey) {
+ return false;
+ }
+
+ /**
+ * Copies the binding for each aspect in this association that has a matching
+ * aspect in the specified association.
+ */
+ public void copyMatchingBindingsFromAssociation(EOAssociation anAssociation) {
+ // FIXME: this is broken: aspects() returns EOAssociation.aspects()
+ // NOTE: This is actually quite crazy - should this even be static? -ceg
+ NSMutableArray ourAspects = new NSMutableArray(this.aspects());
+ NSArray theirAspects = anAssociation.aspects();
+
+ String aspect;
+ Enumeration e = ourAspects.objectEnumerator();
+ while (e.hasMoreElements()) {
+ aspect = e.nextElement().toString();
+ if (theirAspects.containsObject(aspect)) {
+ this.bindAspect(aspect, anAssociation.displayGroupForAspect(aspect),
+ anAssociation.displayGroupKeyForAspect(aspect));
+ }
}
- }
-
- /**
- * Returns whether this association can bind to the
- * specified display group on the specified key for
- * the specified aspect.
- * This implementation returns false.
- */
- public boolean canBindAspect (
- String anAspect, EODisplayGroup aDisplayGroup, String aKey)
- {
- return false;
- }
-
- /**
- * Copies the binding for each aspect in this association
- * that has a matching aspect in the specified association.
- */
- public void copyMatchingBindingsFromAssociation (
- EOAssociation anAssociation )
- {
- //FIXME: this is broken: aspects() returns EOAssociation.aspects()
- //NOTE: This is actually quite crazy - should this even be static? -ceg
- NSMutableArray ourAspects = new NSMutableArray( this.aspects() );
- NSArray theirAspects = anAssociation.aspects();
-
- String aspect;
- Enumeration e = ourAspects.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- aspect = e.nextElement().toString();
- if ( theirAspects.containsObject( aspect ) )
- {
- this.bindAspect(
- aspect,
- anAssociation.displayGroupForAspect( aspect ),
- anAssociation.displayGroupKeyForAspect( aspect ) );
- }
- }
- }
-
- /**
- * Returns the display group that is bound the specified
- * aspect, or null if no display group is currently
- * bound to that aspect.
- */
- public EODisplayGroup displayGroupForAspect ( String anAspect )
- {
- return (EODisplayGroup) aspectToGroup.objectForKey( anAspect );
- }
-
- /**
- * Returns the key for the display group bound to the
- * specified aspect, or null if no display group is currently
- * bound to that aspect.
- */
- public String displayGroupKeyForAspect ( String anAspect )
- {
- return (String) aspectToKey.objectForKey( anAspect );
- }
-
- /**
- * The human-readable descriptive name for this association.
- * This implementation returns the class name.
- */
- public String displayName () // was static - can static method get class name?
- {
- String className = getClass().getName();
- int index = className.lastIndexOf( "." );
- if ( index == -1 ) return className;
- return className.substring( index+1 );
- }
-
- /**
- * Forces this association to cause the object to
- * stop editing and validate the user's input.
- * This implementation returns true.
- * @return false if there were problems validating,
- * or true to continue.
- */
- public boolean endEditing ()
- {
- return true;
- }
-
- /**
- * Establishes a connection between this association
- * and the controlled object. Subclasses should populate
- * their controlled object from the display group and begin
- * listening for events from their controlled object here,
- * but remember to call this method. Any existing value
- * in the controlled object will be overwritten.
- * This implementation registers this assocation to
- * observer changes to each of the bound display groups.
- */
- public void establishConnection ()
- {
- Enumeration e = aspectToGroup.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- EOObserverCenter.addObserver( this, e.nextElement() );
+ }
+
+ /**
+ * Returns the display group that is bound the specified aspect, or null if no
+ * display group is currently bound to that aspect.
+ */
+ public EODisplayGroup displayGroupForAspect(String anAspect) {
+ return (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ }
+
+ /**
+ * Returns the key for the display group bound to the specified aspect, or null
+ * if no display group is currently bound to that aspect.
+ */
+ public String displayGroupKeyForAspect(String anAspect) {
+ return (String) aspectToKey.objectForKey(anAspect);
+ }
+
+ /**
+ * The human-readable descriptive name for this association. This implementation
+ * returns the class name.
+ */
+ public String displayName() // was static - can static method get class name?
+ {
+ String className = getClass().getName();
+ int index = className.lastIndexOf(".");
+ if (index == -1)
+ return className;
+ return className.substring(index + 1);
+ }
+
+ /**
+ * Forces this association to cause the object to stop editing and validate the
+ * user's input. This implementation returns true.
+ *
+ * @return false if there were problems validating, or true to continue.
+ */
+ public boolean endEditing() {
+ return true;
+ }
+
+ /**
+ * Establishes a connection between this association and the controlled object.
+ * Subclasses should populate their controlled object from the display group and
+ * begin listening for events from their controlled object here, but remember to
+ * call this method. Any existing value in the controlled object will be
+ * overwritten. This implementation registers this assocation to observer
+ * changes to each of the bound display groups.
+ */
+ public void establishConnection() {
+ Enumeration e = aspectToGroup.objectEnumerator();
+ while (e.hasMoreElements()) {
+ EOObserverCenter.addObserver(this, e.nextElement());
}
- }
-
- /**
- * Returns whether this class can control the specified
- * object. This implementation returns false.
- */
- public static boolean isUsableWithObject ( Object anObject )
- {
- return false;
- }
-
- /**
- * Returns the object that is currently controlled by this
- * association, or null if no object is currently controlled.
- */
- public Object object ()
- {
- return control;
- }
-
- /**
- * Returns a List of properties of the controlled object
- * that are controlled by this class. For example,
- * "stringValue", or "selected".
- * This implementation returns an empty list.
- */
- public static NSArray objectKeysTaken ()
- {
- return new NSArray();
- }
-
- /**
- * Returns the aspect that is considered primary
- * or default. This is typically "value" or somesuch.
- * This implementation returns null.
- */
- public static String primaryAspect ()
- {
- return null;
- }
-
- /**
- * Writes the specified value for the display group
- * and key currently bound to the specified aspect.
- * This implementation calls
- * EODisplayGroup.setSelectedObjectValue().
- * @return True if the value was successfully set,
- * otherwise false.
- */
- public boolean setValueForAspect (
- Object aValue,
- String anAspect )
- {
- EODisplayGroup group = (EODisplayGroup)
- aspectToGroup.objectForKey( anAspect );
- if ( group == null ) return false;
- String key = (String)
- aspectToKey.objectForKey( anAspect );
- if ( key == null ) return false;
-
- //FIXME: is this the right method to call
- return group.setSelectedObjectValue( aValue, key );
- }
-
-
- /**
- * Writes the specified value for the display group
- * and key currently bound to the specified aspect,
- * at the specified index (assuming it's an indexed
- * property).
- * This implementation calls
- * EODisplayGroup.setValueForObjectAtIndex().
- * @return True if the value was successfully set,
- * otherwise false.
- */
- public boolean setValueForAspectAtIndex (
- Object aValue,
- String anAspect,
- int anIndex )
- {
- EODisplayGroup group = (EODisplayGroup)
- aspectToGroup.objectForKey( anAspect );
- if ( group == null ) return false;
- String key = (String)
- aspectToKey.objectForKey( anAspect );
- if ( key == null ) return false;
-
- //FIXME: is this the right method to call?
- return group.setValueForObjectAtIndex( aValue, anIndex, key );
- }
-
- /**
- * Called by subclasses to notify that the user's input
- * failed validation. Notifies the display group for
- * the aspect, returning the result.
- * This implementation calls
- * EODisplayGroup.associationFailedToValidateValue()
- * with the display group's selected object.
- * @return True if the user should be allowed to continue,
- * meaning that the display group with handle user notification,
- * otherwise false meaning the caller should notify the user.
- */
- public boolean shouldEndEditing (
- String anAspect,
- String anInvalidInput,
- String anErrorDescription )
- {
- EODisplayGroup group = (EODisplayGroup)
- aspectToGroup.objectForKey( anAspect );
- if ( group == null ) return false;
- String key = (String)
- aspectToKey.objectForKey( anAspect );
- if ( key == null ) return false;
- return group.associationFailedToValidateValue(
- this, anInvalidInput, key,
- group.selectedObject(), //FIXME: is this correct?
- anErrorDescription );
- }
-
- /**
- * Called by subclasses to notify that the user's input
- * failed validation. Notifies the display group for
- * the aspect, returning the result.
- * This implementation calls
- * EODisplayGroup.associationFailedToValidateValue()
- * with the object in the display group's displayed
- * objects array at the specified index.
- * @return True if the user should be allowed to continue,
- * meaning that the display group with handle user notification,
- * otherwise false meaning the caller should notify the user.
- */
- public boolean shouldEndEditingAtIndex (
- String anAspect,
- String anInvalidInput,
- String anErrorDescription,
- int anIndex )
- {
- EODisplayGroup group = (EODisplayGroup)
- aspectToGroup.objectForKey( anAspect );
- if ( group == null ) return false;
- String key = (String)
- aspectToKey.objectForKey( anAspect );
- if ( key == null ) return false;
- return group.associationFailedToValidateValue(
- this, anInvalidInput, key,
- group.displayedObjects().objectAtIndex( anIndex ),
- //FIXME: is this correct?
- anErrorDescription );
- }
-
- /**
- * Called when either the selection or the contents of
- * an associated display group have changed.
- * This implementation does nothing.
- */
- public void subjectChanged ()
- {
- // does nothing
- }
-
- /**
- * Returns the current value for the display group
- * and key associated with the specified aspect.
- */
- public Object valueForAspect ( String anAspect )
- {
- EODisplayGroup group = (EODisplayGroup)
- aspectToGroup.objectForKey( anAspect );
- if ( group == null ) return null;
- String key = (String)
- aspectToKey.objectForKey( anAspect );
- if ( key == null ) return null;
-
- //FIXME: is this correct? use selected object?
- return group.valueForObject( group.selectedObject(), key );
- }
-
- /**
- * Returns the current value for the display group
- * and key associated with the specified aspect,
- * and the specified index (assuming multiple values).
- */
- public Object valueForAspectAtIndex (
- String anAspect, int anIndex )
- {
- EODisplayGroup group = (EODisplayGroup)
- aspectToGroup.objectForKey( anAspect );
- if ( group == null ) return null;
- String key = (String)
- aspectToKey.objectForKey( anAspect );
- if ( key == null ) return null;
-
- //FIXME: is this the right method to call?
- return group.valueForObjectAtIndex( anIndex, key );
- }
-
+ }
+
+ /**
+ * Returns whether this class can control the specified object. This
+ * implementation returns false.
+ */
+ public static boolean isUsableWithObject(Object anObject) {
+ return false;
+ }
+
+ /**
+ * Returns the object that is currently controlled by this association, or null
+ * if no object is currently controlled.
+ */
+ public Object object() {
+ return control;
+ }
+
+ /**
+ * Returns a List of properties of the controlled object that are controlled by
+ * this class. For example, "stringValue", or "selected". This implementation
+ * returns an empty list.
+ */
+ public static NSArray objectKeysTaken() {
+ return new NSArray();
+ }
+
+ /**
+ * Returns the aspect that is considered primary or default. This is typically
+ * "value" or somesuch. This implementation returns null.
+ */
+ public static String primaryAspect() {
+ return null;
+ }
+
+ /**
+ * Writes the specified value for the display group and key currently bound to
+ * the specified aspect. This implementation calls
+ * EODisplayGroup.setSelectedObjectValue().
+ *
+ * @return True if the value was successfully set, otherwise false.
+ */
+ public boolean setValueForAspect(Object aValue, String anAspect) {
+ EODisplayGroup group = (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ if (group == null)
+ return false;
+ String key = (String) aspectToKey.objectForKey(anAspect);
+ if (key == null)
+ return false;
+
+ // FIXME: is this the right method to call
+ return group.setSelectedObjectValue(aValue, key);
+ }
+
+ /**
+ * Writes the specified value for the display group and key currently bound to
+ * the specified aspect, at the specified index (assuming it's an indexed
+ * property). This implementation calls
+ * EODisplayGroup.setValueForObjectAtIndex().
+ *
+ * @return True if the value was successfully set, otherwise false.
+ */
+ public boolean setValueForAspectAtIndex(Object aValue, String anAspect, int anIndex) {
+ EODisplayGroup group = (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ if (group == null)
+ return false;
+ String key = (String) aspectToKey.objectForKey(anAspect);
+ if (key == null)
+ return false;
+
+ // FIXME: is this the right method to call?
+ return group.setValueForObjectAtIndex(aValue, anIndex, key);
+ }
+
+ /**
+ * Called by subclasses to notify that the user's input failed validation.
+ * Notifies the display group for the aspect, returning the result. This
+ * implementation calls EODisplayGroup.associationFailedToValidateValue() with
+ * the display group's selected object.
+ *
+ * @return True if the user should be allowed to continue, meaning that the
+ * display group with handle user notification, otherwise false meaning
+ * the caller should notify the user.
+ */
+ public boolean shouldEndEditing(String anAspect, String anInvalidInput, String anErrorDescription) {
+ EODisplayGroup group = (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ if (group == null)
+ return false;
+ String key = (String) aspectToKey.objectForKey(anAspect);
+ if (key == null)
+ return false;
+ return group.associationFailedToValidateValue(this, anInvalidInput, key, group.selectedObject(), // FIXME: is
+ // this
+ // correct?
+ anErrorDescription);
+ }
+
+ /**
+ * Called by subclasses to notify that the user's input failed validation.
+ * Notifies the display group for the aspect, returning the result. This
+ * implementation calls EODisplayGroup.associationFailedToValidateValue() with
+ * the object in the display group's displayed objects array at the specified
+ * index.
+ *
+ * @return True if the user should be allowed to continue, meaning that the
+ * display group with handle user notification, otherwise false meaning
+ * the caller should notify the user.
+ */
+ public boolean shouldEndEditingAtIndex(String anAspect, String anInvalidInput, String anErrorDescription,
+ int anIndex) {
+ EODisplayGroup group = (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ if (group == null)
+ return false;
+ String key = (String) aspectToKey.objectForKey(anAspect);
+ if (key == null)
+ return false;
+ return group.associationFailedToValidateValue(this, anInvalidInput, key,
+ group.displayedObjects().objectAtIndex(anIndex),
+ // FIXME: is this correct?
+ anErrorDescription);
+ }
+
+ /**
+ * Called when either the selection or the contents of an associated display
+ * group have changed. This implementation does nothing.
+ */
+ public void subjectChanged() {
+ // does nothing
+ }
+
+ /**
+ * Returns the current value for the display group and key associated with the
+ * specified aspect.
+ */
+ public Object valueForAspect(String anAspect) {
+ EODisplayGroup group = (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ if (group == null)
+ return null;
+ String key = (String) aspectToKey.objectForKey(anAspect);
+ if (key == null)
+ return null;
+
+ // FIXME: is this correct? use selected object?
+ return group.valueForObject(group.selectedObject(), key);
+ }
+
+ /**
+ * Returns the current value for the display group and key associated with the
+ * specified aspect, and the specified index (assuming multiple values).
+ */
+ public Object valueForAspectAtIndex(String anAspect, int anIndex) {
+ EODisplayGroup group = (EODisplayGroup) aspectToGroup.objectForKey(anAspect);
+ if (group == null)
+ return null;
+ String key = (String) aspectToKey.objectForKey(anAspect);
+ if (key == null)
+ return null;
+
+ // FIXME: is this the right method to call?
+ return group.valueForObjectAtIndex(anIndex, key);
+ }
+
}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.7 2005/05/11 15:21:53 cgruber
- * Change enum to enumeration, since enum is now a keyword as of Java 5.0
+ * Revision 1.7 2005/05/11 15:21:53 cgruber Change enum to enumeration, since
+ * enum is now a keyword as of Java 5.0
*
* A few other comments in the code.
*
- * Revision 1.6 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.6 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.5 2003/06/06 20:29:45 mpowers
- * Now dequeuing the association when connection is broken.
- * Coalesced change events had been processed even after breaking connection.
+ * Revision 1.5 2003/06/06 20:29:45 mpowers Now dequeuing the association when
+ * connection is broken. Coalesced change events had been processed even after
+ * breaking connection.
*
- * Revision 1.4 2001/03/06 23:43:46 mpowers
- * Implemented icon aspect for text association.
+ * Revision 1.4 2001/03/06 23:43:46 mpowers Implemented icon aspect for text
+ * association.
*
- * Revision 1.3 2001/02/17 16:52:05 mpowers
- * Changes in imports to support building with jdk1.1 collections.
+ * Revision 1.3 2001/02/17 16:52:05 mpowers Changes in imports to support
+ * building with jdk1.1 collections.
*
- * Revision 1.2 2001/01/25 17:46:11 mpowers
- * Clarified usage and gc expectations.
+ * Revision 1.2 2001/01/25 17:46:11 mpowers Clarified usage and gc expectations.
*
- * Revision 1.1.1.1 2000/12/21 15:48:07 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:48:07 mpowers Contributing wotonomy.
*
- * Revision 1.11 2000/12/20 16:25:39 michael
- * Added log to all files.
+ * Revision 1.11 2000/12/20 16:25:39 michael Added log to all files.
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EODisplayGroup.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EODisplayGroup.java
index ed65b1c..fd80713 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EODisplayGroup.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/EODisplayGroup.java
@@ -51,2309 +51,1867 @@ import net.wotonomy.foundation.internal.Duplicator;
import net.wotonomy.foundation.internal.WotonomyException;
/**
-* EODisplayGroup provides an abstraction of a user interface,
-* comprising of an ordered collection of data objects, some
-* of which are displayed, and of those some are selected.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class EODisplayGroup extends Observable
- implements EOObserving, EOEditingContext.Editor
-{
- /**
- * Notification sent when the display group is about to fetch.
- */
- public static final String DisplayGroupWillFetchNotification
- = "DisplayGroupWillFetchNotification";
-
- private static boolean
- globalDefaultForValidatesChangesImmediately = true;
- private static String
- globalDefaultStringMatchFormat = "caseInsensitiveLike";
- private static String
- globalDefaultStringMatchOperator = "%@*";
-
- protected NSMutableArray allObjects;
- protected NSArray allObjectsProxy;
- protected NSMutableArray displayedObjects;
- protected NSArray displayedObjectsProxy;
- protected NSMutableArray selectedObjects;
- protected NSArray selectedObjectsProxy;
- protected NSMutableArray selectedIndexes;
-
- private String defaultStringMatchOperator;
- private String defaultStringMatchFormat;
-
- private boolean validatesChangesImmediately;
- private Object delegate;
- private EODataSource dataSource;
- private EOAssociation editingAssociation;
- private EOQualifier qualifier;
- private NSMutableArray sortOrderings;
- private NSArray sortOrderingsProxy;
-
- private NSArray localKeys;
- private NSDictionary insertedObjectDefaultValues;
- private boolean fetchesOnLoad;
- private boolean selectsFirstObjectAfterFetch;
- private boolean usesOptimisticRefresh;
- private boolean inQueryMode;
-
- // change detection: package access for helper classes
- boolean contentsChanged;
- boolean selectionChanged;
- int updatedObjectIndex;
-
- // this property is not in the spec
- private boolean compareByReference = false;
-
- private EOObserving lastGroupObserver;
-
- /**
- * Creates a new display group.
- */
- public EODisplayGroup ()
- {
- validatesChangesImmediately =
- globalDefaultForValidatesChangesImmediately();
- defaultStringMatchOperator =
- globalDefaultStringMatchFormat();
- defaultStringMatchFormat =
- globalDefaultStringMatchOperator();
-
- allObjects = new ObservableArray( this );
- allObjectsProxy = NSArray.arrayBackedByList( allObjects );
- displayedObjects = new NSMutableArray();
- displayedObjectsProxy = NSArray.arrayBackedByList( displayedObjects );
- selectedObjects = new NSMutableArray();
- selectedObjectsProxy = NSArray.arrayBackedByList( selectedObjects );
- sortOrderings = new NSMutableArray();
- sortOrderingsProxy = NSArray.arrayBackedByList( sortOrderings );
- selectedIndexes = new NSMutableArray();
-
- delegate = null;
- dataSource = null;
- editingAssociation = null;
- qualifier = null;
-
- localKeys = new NSArray(); // not implemented
- insertedObjectDefaultValues = new NSDictionary();
- fetchesOnLoad = false; // not implemented
- selectsFirstObjectAfterFetch = false;
- usesOptimisticRefresh = false;
- inQueryMode = false; // not implemented
-
- contentsChanged = false;
- selectionChanged = false;
- updatedObjectIndex = -1;
-
- // create our private delayed observer
- lastGroupObserver = new LastGroupObserver( this );
- EOObserverCenter.addObserver( lastGroupObserver, this );
- }
-
-
-
- // specify optional data source
-
- /**
- * Sets the data source that will be used by
- * this display group.
- */
- public void setDataSource ( EODataSource aDataSource )
- {
- if ( ( dataSource != null )
- && ( dataSource.editingContext() != null ) )
- {
- // un-register for notifications from existing parent store
- NSNotificationCenter.defaultCenter().removeObserver(
- this, null, dataSource.editingContext() );
- dataSource.editingContext().removeEditor( this );
- if ( dataSource.editingContext().messageHandler() == this )
- {
- dataSource.editingContext().setMessageHandler( null );
- }
-
- }
-
- dataSource = aDataSource;
-
- if ( ( dataSource != null )
- && ( dataSource.editingContext() != null ) )
- {
- // register for notifications from parent store
- NSNotificationCenter.defaultCenter().addObserver(
- this, new NSSelector( "objectsInvalidatedInEditingContext",
- new Class[] { NSNotification.class } ),
- null, dataSource.editingContext() );
-
- // add ourselves as editor
- dataSource.editingContext().addEditor( this );
-
- // add ourselves as message handler if no such handler exists
- if ( dataSource.editingContext().messageHandler() == null )
- {
- dataSource.editingContext().setMessageHandler( this );
- }
- }
- }
-
- /**
- * Returns the current data source backing this display group,
- * or null if no dataSource is currently used.
- */
- public EODataSource dataSource ()
- {
- return dataSource;
- }
-
-
-
- // specify optional delegate
-
- /**
- * Sets the display group delegate that
- * will be used by this display group.
- */
- public void setDelegate ( Object aDelegate )
- {
- delegate = aDelegate;
- }
-
- /**
- * Returns the current delegate for this display group,
- * or null if no delegate is currently set.
- */
- public Object delegate ()
- {
- return delegate;
- }
-
-
-
- // display group configuration
-
- /**
- * Returns the current string matching format.
- * If not set, defaults to "%@*".
- */
- public String defaultStringMatchFormat ()
- {
- return defaultStringMatchFormat;
- }
-
- /**
- * Returns the current string matching operator.
- * If not set, defaults to "caseInsensitiveLike".
- */
- public String defaultStringMatchOperator ()
- {
- return defaultStringMatchOperator;
- }
-
- /**
- * Sets the display group and associations to edit a
- * "query by example" query object. This method is
- * used for target/action connections.
- */
- public void enterQueryMode ( Object aSender )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Returns whether this display group should immediate
- * fetch when loaded.
- */
- public boolean fetchesOnLoad ()
- {
- return fetchesOnLoad;
- }
-
- /**
- * Returns whether this display group is in "query by
- * example" mode.
- */
- public boolean inQueryMode ()
- {
- return inQueryMode;
- }
-
- /**
- * Returns a Map of default values that are applied
- * to new objects that are inserted into the list.
- */
- public NSDictionary insertedObjectDefaultValues ()
- {
- return insertedObjectDefaultValues;
- }
-
- /**
- * Returns the keys that were declared when read from
- * an external resource file.
- */
- public NSArray localKeys ()
- {
- return localKeys;
- }
-
- /**
- * Sets whether this display group will select the
- * first object in the list after a fetch.
- */
- public boolean selectsFirstObjectAfterFetch ()
- {
- return selectsFirstObjectAfterFetch;
- }
-
- /**
- * Sets the default string matching format that
- * will be used by this display group.
- */
- public void setDefaultStringMatchFormat ( String aFormat )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets the default string matching operator that
- * will be used by this display group.
- */
- public void setDefaultStringMatchOperator ( String anOperator )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets whether this display group will fetch objects
- * from its data source on load.
- */
- public void setFetchesOnLoad ( boolean willFetch )
- {
- fetchesOnLoad = willFetch;
- }
-
- /**
- * Sets whether this display group is in "query by example"
- * mode. If true, all associations will bind to a special
- * "example" object.
- */
- public void setInQueryMode ( boolean isInQueryMode )
- {
- inQueryMode = isInQueryMode;
- }
-
- /**
- * Sets the mapping that contains the values that will
- * be applied to new objects inserted into the display group.
- */
- public void setInsertedObjectDefaultValues ( Map aMap )
- {
- insertedObjectDefaultValues = new NSDictionary( aMap );
- }
-
- /**
- * Sets the keys that are declared when instantiated from
- * an external resource file.
- */
- public void setLocalKeys ( List aKeyList )
- {
- localKeys = new NSArray( (Collection) aKeyList );
- }
-
- /**
- * Sets whether the first object in the list will be
- * selected after a fetch.
- */
- public void setSelectsFirstObjectAfterFetch (
- boolean selectsFirst )
- {
- selectsFirstObjectAfterFetch = selectsFirst;
- }
-
- /**
- * Sets the order of the keys by which this display group
- * will be ordered after a fetch or after a call to
- * updateDisplayedObjects(). The elements in the display
- * group will be sorted first by the first key, within
- * the first key, by the second key, and so on.
- */
- public void setSortOrderings ( List aList )
- {
- sortOrderings.removeAllObjects();
-
- Object o;
- Iterator it = aList.iterator();
- while ( it.hasNext() )
- {
- o = it.next();
- // handle the convenience of specifying just a key
- if ( ! ( o instanceof EOSortOrdering ) )
- {
- o = new EOSortOrdering(
- o.toString(), EOSortOrdering.CompareAscending );
- }
- sortOrderings.add( o );
- }
- }
-
- /**
- * Sets whether only changed objects are refreshed (optimistic),
- * or whether all objects are refreshed (pessimistic, default).
- * By default, when the display group receives notification that
- * one of its objects has changed, updateDisplayedObjects is called.
- */
- public void setUsesOptimisticRefresh ( boolean isOptimistic )
- {
- usesOptimisticRefresh = isOptimistic;
- }
-
- /**
- * Sets whether changes made by associations are validated
- * immediately, or when changes are saved.
- */
- public void setValidatesChangesImmediately (
- boolean validatesImmediately )
- {
- validatesChangesImmediately = validatesImmediately;
- }
-
- /**
- * Returns a read-only List of sort orderings for this display group.
- */
- public NSArray sortOrderings ()
- {
- return sortOrderingsProxy;
- }
-
- /**
- * Returns whether this display group refreshes only
- * the changed objects or all objects on refresh.
- */
- public boolean usesOptimisticRefresh ()
- {
- return usesOptimisticRefresh;
- }
-
- /**
- * Returns whether this display group validates changes
- * immediately. Otherwise, validation should occur when
- * changes are saved. Default is the global default,
- * which is initially true.
- */
- public boolean validatesChangesImmediately ()
- {
- return validatesChangesImmediately;
- }
-
-
- // qualification
-
- /**
- * Returns a qualifier that will be applied all the objects
- * in this display group to determine which objects will
- * be displayed.
- */
- public EOQualifier qualifier ()
- {
- return qualifier;
- }
-
- /**
- * Returns a new qualifier built from the three query
- * value maps: greater than, equal to, and less than.
- */
- public EOQualifier qualifierFromQueryValues ()
- {
- //TODO: assemble qualifier from query values
-
- return new EOQualifier()
- {
- // use inner class until we actually implement one
- public EOQualifier qualifierWithBindings(
- Map aMap,
- boolean requireAll )
- {
- return null;
- }
- public Throwable
- validateKeysWithRootClassDescription( Class aClass )
- {
- return null;
- }
- public boolean evaluateWithObject(Object o)
- {
- return false;
- }
- };
- }
-
- /**
- * Calls qualifierFromQueryValues(), applies the result
- * to the data source, and calls fetch().
- */
- public void qualifyDataSource ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Calls qualifierFromQueryValues(), sets the qualifier
- * with setQualifier(), and calls updateDisplayedObjects().
- */
- public void qualifyDisplayGroup ()
- {
- setQualifier( qualifierFromQueryValues() );
- updateDisplayedObjects();
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to binding query values.
- */
- public NSDictionary queryBindingValues ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to operator values.
- */
- public NSDictionary queryOperatorValues ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets the qualifier that will be used by
- * updateDisplayedObjects() to filter displayed objects.
- */
- public void setQualifier ( EOQualifier aQualifier )
- {
- qualifier = aQualifier;
- }
-
- /**
- * Sets the mapping that contains the mappings of keys
- * to binding values.
- */
- public void setQueryBindingValues ( Map aMap )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets the mapping that contains the mappings of keys
- * to operator values.
- */
- public void setQueryOperatorValues ( Map aMap )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
-
-
- // qualifier query values
-
- /**
- * Returns a Map containing the mappings of keys
- * to query values that will be used to test for equality.
- */
- public NSDictionary equalToQueryValues ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to query values that will be used to test for greater value.
- */
- public NSDictionary greaterThanQueryValues ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Returns a Map containing the mappings of keys
- * to query values that will be used to test for lesser value.
- */
- public NSDictionary lessThanQueryValues ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets the Map that contains the mappings of keys
- * to query values that will be used to test for equality.
- */
- public void setEqualToQueryValues ( Map aMap )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets the mapping that contains the mappings of keys
- * to query values that will be used to test for greater value.
- */
- public void setGreaterThanQueryValues ( Map aMap )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- /**
- * Sets the mapping that contains the mappings of keys
- * to query values that will be used to test for lesser value.
- */
- public void setLessThanQueryValues ( Map aMap )
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
-
- // interface to associations
-
- /**
- * Called by an association when it begins editing.
- */
- public void associationDidBeginEditing ( EOAssociation anAssociation )
- { // System.out.println( "EODisplayGroup.associationDidBeginEditing: " + anAssociation );
- if ( dataSource != null )
- {
- if ( dataSource.editingContext() != null )
- {
- dataSource.editingContext().setMessageHandler( this );
- }
- }
- editingAssociation = anAssociation;
- }
-
- /**
- * Called by an association when it is finished editing.
- */
- public void associationDidEndEditing ( EOAssociation anAssociation )
- { // System.out.println( "EODisplayGroup.associationDidEndEditing: " + anAssociation );
- editingAssociation = null;
- }
-
- /**
- * Called by associations to determine whether the contents
- * of any objects have been changed. Returns true if the
- * contents have changed and not all observers have been
- * notified.
- */
- public boolean contentsChanged ()
- {
- return contentsChanged;
- }
-
- /**
- * Called by associations to determine whether the
- * selection has been changed. Returns true if the
- * selection has changed and not all observers have
- * been notified.
- */
- public boolean selectionChanged ()
- {
- return selectionChanged;
- }
-
- /**
- * Called by an association when a user-specified value fails the association's
- * validation rules. This implementation returns true, unless the delegate
- * prevents this.
- * @return True to allow the association to handle user notification,
- * otherwise return false to let the association know that the
- * display group notified the user.
- */
- public boolean associationFailedToValidateValue (
- EOAssociation anAssociation,
- String aValue,
- String aKey,
- Object anObject,
- String anErrorDescription )
- {
- Object result = notifyDelegate(
- "displayGroupShouldDisplayAlert",
- new Class[] { EODisplayGroup.class, String.class, String.class },
- new Object[] { this, "Validation Failed", anErrorDescription } );
- if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) )
- {
- return true;
- }
- return false;
- }
-
- /**
- * Called by an association to determine whether it should enable
- * a component that displayes a value for the specified key.
- * @return true if an object is selected, or if
- * the specified key is a query key. Otherwise false.
- */
- public boolean enabledToSetSelectedObjectValueForKey ( String aKey )
- {
- if ( ( aKey != null ) && ( aKey.startsWith( "@" ) ) ) return true;
- return ( selectedObject() != null );
- }
-
-
- // association management
-
- /**
- * Returns the association that is currently being edited,
- * or null if no editing is taking place.
- */
- public EOAssociation editingAssociation ()
- {
- return editingAssociation;
- }
-
- /**
- * Asks the association currently editing to stop editing.
- * @returns true if editing was stopped, false if the
- * association refused to stop editing (if a modal dialog
- * is displayed or a value failed to validate).
- */
- public boolean endEditing ()
- {
- if ( editingAssociation == null ) return true;
- return editingAssociation.endEditing();
- }
-
- /**
- * Returns a read-only List of associations that are observing
- * this display group.
- */
- public NSArray observingAssociations ()
- {
- NSArray observers =
- EOObserverCenter.observersForObject( this );
- NSMutableArray result = new NSMutableArray();
-
- Object o;
- Enumeration e = observers.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- o = e.nextElement();
- if ( o instanceof EOAssociation )
- {
- result.addObject( o );
- }
- }
- return result;
- }
-
-
-
- // object management
-
- /**
- * Returns a read-only List containing all objects managed by the display group.
- * This includes those objects not visible due to disqualification.
- */
- public NSArray allObjects ()
- { //System.out.println( "avoided allocation: allObjects" );
- return allObjectsProxy;
- }
-
- /**
- * Clears the current selection.
- * @return True is the selection was cleared,
- * False if the selection could not be cleared
- * @see #setSelectionIndexes
- */
- public boolean clearSelection ()
- {
- Object result = notifyDelegate(
- "displayGroupShouldChangeSelection",
- new Class[] { EODisplayGroup.class, List.class },
- new Object[] { this, new NSArray( selectedObjects ) } );
- if ( ( result != null ) && ( Boolean.FALSE.equals( result ) ) )
- {
- return false;
- }
-
- selectionChanged = true;
- willChange();
-
- selectedObjects.removeAllObjects();
- selectedIndexes.removeAllObjects();
-
- notifyDelegate(
- "displayGroupDidChangeSelection",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
- notifyDelegate(
- "displayGroupDidChangeSelectedObjects",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
-
- return true;
- }
-
- /**
- * Deletes the object at the specified index,
- * notifying the delegate before and after the operation,
- * and then updating the selection if needed.
- * @return True if delete was successful, false if the
- * object was not deleted.
- */
- public boolean deleteObjectAtIndex ( int anIndex )
- {
- Object target = displayedObjects.objectAtIndex( anIndex );
-
- Object result = notifyDelegate(
- "displayGroupShouldDeleteObject",
- new Class[] { EODisplayGroup.class, Object.class },
- new Object[] { this, target } );
- if ( ( result != null ) && ( Boolean.FALSE.equals( result ) ) )
- {
- return false;
- }
-
- contentsChanged = true;
-
- deleteObjectAtIndexNoNotify( anIndex );
-
- if ( dataSource != null )
- {
- dataSource.deleteObject( target );
- }
-
- notifyDelegate(
- "displayGroupDidDeleteObject",
- new Class[] { EODisplayGroup.class, Object.class },
- new Object[] { this, target } );
-
- return true;
- }
-
- private void deleteObjectAtIndexNoNotify ( int anIndex )
- {
- Object target = displayedObjects.objectAtIndex( anIndex );
-
- int i;
-
- // remove from selected objects if necessary
- i = indexOf( selectedObjects, target );
- if ( i != NSArray.NotFound )
- {
- selectionChanged = true;
- willChange(); // notify before removing
- selectedObjects.removeObjectAtIndex( i );
- selectedIndexes.remove( new Integer( i ) ); // comps by value
- }
- else // notify - no selection change needed
- {
- willChange();
- }
-
- // remove from all objects
- i = indexOf( allObjects, target );
- if ( i != NSArray.NotFound )
- {
- allObjects.removeObjectAtIndex( i );
- }
- else // otherwise should never happen
- {
+ * EODisplayGroup provides an abstraction of a user interface, comprising of an
+ * ordered collection of data objects, some of which are displayed, and of those
+ * some are selected.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class EODisplayGroup extends Observable implements EOObserving, EOEditingContext.Editor {
+ /**
+ * Notification sent when the display group is about to fetch.
+ */
+ public static final String DisplayGroupWillFetchNotification = "DisplayGroupWillFetchNotification";
+
+ private static boolean globalDefaultForValidatesChangesImmediately = true;
+ private static String globalDefaultStringMatchFormat = "caseInsensitiveLike";
+ private static String globalDefaultStringMatchOperator = "%@*";
+
+ protected NSMutableArray allObjects;
+ protected NSArray allObjectsProxy;
+ protected NSMutableArray displayedObjects;
+ protected NSArray displayedObjectsProxy;
+ protected NSMutableArray selectedObjects;
+ protected NSArray selectedObjectsProxy;
+ protected NSMutableArray selectedIndexes;
+
+ private String defaultStringMatchOperator;
+ private String defaultStringMatchFormat;
+
+ private boolean validatesChangesImmediately;
+ private Object delegate;
+ private EODataSource dataSource;
+ private EOAssociation editingAssociation;
+ private EOQualifier qualifier;
+ private NSMutableArray sortOrderings;
+ private NSArray sortOrderingsProxy;
+
+ private NSArray localKeys;
+ private NSDictionary insertedObjectDefaultValues;
+ private boolean fetchesOnLoad;
+ private boolean selectsFirstObjectAfterFetch;
+ private boolean usesOptimisticRefresh;
+ private boolean inQueryMode;
+
+ // change detection: package access for helper classes
+ boolean contentsChanged;
+ boolean selectionChanged;
+ int updatedObjectIndex;
+
+ // this property is not in the spec
+ private boolean compareByReference = false;
+
+ private EOObserving lastGroupObserver;
+
+ /**
+ * Creates a new display group.
+ */
+ public EODisplayGroup() {
+ validatesChangesImmediately = globalDefaultForValidatesChangesImmediately();
+ defaultStringMatchOperator = globalDefaultStringMatchFormat();
+ defaultStringMatchFormat = globalDefaultStringMatchOperator();
+
+ allObjects = new ObservableArray(this);
+ allObjectsProxy = NSArray.arrayBackedByList(allObjects);
+ displayedObjects = new NSMutableArray();
+ displayedObjectsProxy = NSArray.arrayBackedByList(displayedObjects);
+ selectedObjects = new NSMutableArray();
+ selectedObjectsProxy = NSArray.arrayBackedByList(selectedObjects);
+ sortOrderings = new NSMutableArray();
+ sortOrderingsProxy = NSArray.arrayBackedByList(sortOrderings);
+ selectedIndexes = new NSMutableArray();
+
+ delegate = null;
+ dataSource = null;
+ editingAssociation = null;
+ qualifier = null;
+
+ localKeys = new NSArray(); // not implemented
+ insertedObjectDefaultValues = new NSDictionary();
+ fetchesOnLoad = false; // not implemented
+ selectsFirstObjectAfterFetch = false;
+ usesOptimisticRefresh = false;
+ inQueryMode = false; // not implemented
+
+ contentsChanged = false;
+ selectionChanged = false;
+ updatedObjectIndex = -1;
+
+ // create our private delayed observer
+ lastGroupObserver = new LastGroupObserver(this);
+ EOObserverCenter.addObserver(lastGroupObserver, this);
+ }
+
+ // specify optional data source
+
+ /**
+ * Sets the data source that will be used by this display group.
+ */
+ public void setDataSource(EODataSource aDataSource) {
+ if ((dataSource != null) && (dataSource.editingContext() != null)) {
+ // un-register for notifications from existing parent store
+ NSNotificationCenter.defaultCenter().removeObserver(this, null, dataSource.editingContext());
+ dataSource.editingContext().removeEditor(this);
+ if (dataSource.editingContext().messageHandler() == this) {
+ dataSource.editingContext().setMessageHandler(null);
+ }
+
+ }
+
+ dataSource = aDataSource;
+
+ if ((dataSource != null) && (dataSource.editingContext() != null)) {
+ // register for notifications from parent store
+ NSNotificationCenter.defaultCenter().addObserver(this,
+ new NSSelector("objectsInvalidatedInEditingContext", new Class[] { NSNotification.class }), null,
+ dataSource.editingContext());
+
+ // add ourselves as editor
+ dataSource.editingContext().addEditor(this);
+
+ // add ourselves as message handler if no such handler exists
+ if (dataSource.editingContext().messageHandler() == null) {
+ dataSource.editingContext().setMessageHandler(this);
+ }
+ }
+ }
+
+ /**
+ * Returns the current data source backing this display group, or null if no
+ * dataSource is currently used.
+ */
+ public EODataSource dataSource() {
+ return dataSource;
+ }
+
+ // specify optional delegate
+
+ /**
+ * Sets the display group delegate that will be used by this display group.
+ */
+ public void setDelegate(Object aDelegate) {
+ delegate = aDelegate;
+ }
+
+ /**
+ * Returns the current delegate for this display group, or null if no delegate
+ * is currently set.
+ */
+ public Object delegate() {
+ return delegate;
+ }
+
+ // display group configuration
+
+ /**
+ * Returns the current string matching format. If not set, defaults to "%@*".
+ */
+ public String defaultStringMatchFormat() {
+ return defaultStringMatchFormat;
+ }
+
+ /**
+ * Returns the current string matching operator. If not set, defaults to
+ * "caseInsensitiveLike".
+ */
+ public String defaultStringMatchOperator() {
+ return defaultStringMatchOperator;
+ }
+
+ /**
+ * Sets the display group and associations to edit a "query by example" query
+ * object. This method is used for target/action connections.
+ */
+ public void enterQueryMode(Object aSender) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Returns whether this display group should immediate fetch when loaded.
+ */
+ public boolean fetchesOnLoad() {
+ return fetchesOnLoad;
+ }
+
+ /**
+ * Returns whether this display group is in "query by example" mode.
+ */
+ public boolean inQueryMode() {
+ return inQueryMode;
+ }
+
+ /**
+ * Returns a Map of default values that are applied to new objects that are
+ * inserted into the list.
+ */
+ public NSDictionary insertedObjectDefaultValues() {
+ return insertedObjectDefaultValues;
+ }
+
+ /**
+ * Returns the keys that were declared when read from an external resource file.
+ */
+ public NSArray localKeys() {
+ return localKeys;
+ }
+
+ /**
+ * Sets whether this display group will select the first object in the list
+ * after a fetch.
+ */
+ public boolean selectsFirstObjectAfterFetch() {
+ return selectsFirstObjectAfterFetch;
+ }
+
+ /**
+ * Sets the default string matching format that will be used by this display
+ * group.
+ */
+ public void setDefaultStringMatchFormat(String aFormat) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets the default string matching operator that will be used by this display
+ * group.
+ */
+ public void setDefaultStringMatchOperator(String anOperator) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets whether this display group will fetch objects from its data source on
+ * load.
+ */
+ public void setFetchesOnLoad(boolean willFetch) {
+ fetchesOnLoad = willFetch;
+ }
+
+ /**
+ * Sets whether this display group is in "query by example" mode. If true, all
+ * associations will bind to a special "example" object.
+ */
+ public void setInQueryMode(boolean isInQueryMode) {
+ inQueryMode = isInQueryMode;
+ }
+
+ /**
+ * Sets the mapping that contains the values that will be applied to new objects
+ * inserted into the display group.
+ */
+ public void setInsertedObjectDefaultValues(Map aMap) {
+ insertedObjectDefaultValues = new NSDictionary(aMap);
+ }
+
+ /**
+ * Sets the keys that are declared when instantiated from an external resource
+ * file.
+ */
+ public void setLocalKeys(List aKeyList) {
+ localKeys = new NSArray((Collection) aKeyList);
+ }
+
+ /**
+ * Sets whether the first object in the list will be selected after a fetch.
+ */
+ public void setSelectsFirstObjectAfterFetch(boolean selectsFirst) {
+ selectsFirstObjectAfterFetch = selectsFirst;
+ }
+
+ /**
+ * Sets the order of the keys by which this display group will be ordered after
+ * a fetch or after a call to updateDisplayedObjects(). The elements in the
+ * display group will be sorted first by the first key, within the first key, by
+ * the second key, and so on.
+ */
+ public void setSortOrderings(List aList) {
+ sortOrderings.removeAllObjects();
+
+ Object o;
+ Iterator it = aList.iterator();
+ while (it.hasNext()) {
+ o = it.next();
+ // handle the convenience of specifying just a key
+ if (!(o instanceof EOSortOrdering)) {
+ o = new EOSortOrdering(o.toString(), EOSortOrdering.CompareAscending);
+ }
+ sortOrderings.add(o);
+ }
+ }
+
+ /**
+ * Sets whether only changed objects are refreshed (optimistic), or whether all
+ * objects are refreshed (pessimistic, default). By default, when the display
+ * group receives notification that one of its objects has changed,
+ * updateDisplayedObjects is called.
+ */
+ public void setUsesOptimisticRefresh(boolean isOptimistic) {
+ usesOptimisticRefresh = isOptimistic;
+ }
+
+ /**
+ * Sets whether changes made by associations are validated immediately, or when
+ * changes are saved.
+ */
+ public void setValidatesChangesImmediately(boolean validatesImmediately) {
+ validatesChangesImmediately = validatesImmediately;
+ }
+
+ /**
+ * Returns a read-only List of sort orderings for this display group.
+ */
+ public NSArray sortOrderings() {
+ return sortOrderingsProxy;
+ }
+
+ /**
+ * Returns whether this display group refreshes only the changed objects or all
+ * objects on refresh.
+ */
+ public boolean usesOptimisticRefresh() {
+ return usesOptimisticRefresh;
+ }
+
+ /**
+ * Returns whether this display group validates changes immediately. Otherwise,
+ * validation should occur when changes are saved. Default is the global
+ * default, which is initially true.
+ */
+ public boolean validatesChangesImmediately() {
+ return validatesChangesImmediately;
+ }
+
+ // qualification
+
+ /**
+ * Returns a qualifier that will be applied all the objects in this display
+ * group to determine which objects will be displayed.
+ */
+ public EOQualifier qualifier() {
+ return qualifier;
+ }
+
+ /**
+ * Returns a new qualifier built from the three query value maps: greater than,
+ * equal to, and less than.
+ */
+ public EOQualifier qualifierFromQueryValues() {
+ // TODO: assemble qualifier from query values
+
+ return new EOQualifier() {
+ // use inner class until we actually implement one
+ public EOQualifier qualifierWithBindings(Map aMap, boolean requireAll) {
+ return null;
+ }
+
+ public Throwable validateKeysWithRootClassDescription(Class aClass) {
+ return null;
+ }
+
+ public boolean evaluateWithObject(Object o) {
+ return false;
+ }
+ };
+ }
+
+ /**
+ * Calls qualifierFromQueryValues(), applies the result to the data source, and
+ * calls fetch().
+ */
+ public void qualifyDataSource() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Calls qualifierFromQueryValues(), sets the qualifier with setQualifier(), and
+ * calls updateDisplayedObjects().
+ */
+ public void qualifyDisplayGroup() {
+ setQualifier(qualifierFromQueryValues());
+ updateDisplayedObjects();
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to binding query values.
+ */
+ public NSDictionary queryBindingValues() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to operator values.
+ */
+ public NSDictionary queryOperatorValues() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets the qualifier that will be used by updateDisplayedObjects() to filter
+ * displayed objects.
+ */
+ public void setQualifier(EOQualifier aQualifier) {
+ qualifier = aQualifier;
+ }
+
+ /**
+ * Sets the mapping that contains the mappings of keys to binding values.
+ */
+ public void setQueryBindingValues(Map aMap) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets the mapping that contains the mappings of keys to operator values.
+ */
+ public void setQueryOperatorValues(Map aMap) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ // qualifier query values
+
+ /**
+ * Returns a Map containing the mappings of keys to query values that will be
+ * used to test for equality.
+ */
+ public NSDictionary equalToQueryValues() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to query values that will be
+ * used to test for greater value.
+ */
+ public NSDictionary greaterThanQueryValues() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Returns a Map containing the mappings of keys to query values that will be
+ * used to test for lesser value.
+ */
+ public NSDictionary lessThanQueryValues() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets the Map that contains the mappings of keys to query values that will be
+ * used to test for equality.
+ */
+ public void setEqualToQueryValues(Map aMap) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets the mapping that contains the mappings of keys to query values that will
+ * be used to test for greater value.
+ */
+ public void setGreaterThanQueryValues(Map aMap) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ /**
+ * Sets the mapping that contains the mappings of keys to query values that will
+ * be used to test for lesser value.
+ */
+ public void setLessThanQueryValues(Map aMap) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ // interface to associations
+
+ /**
+ * Called by an association when it begins editing.
+ */
+ public void associationDidBeginEditing(EOAssociation anAssociation) { // System.out.println(
+ // "EODisplayGroup.associationDidBeginEditing:
+ // " + anAssociation );
+ if (dataSource != null) {
+ if (dataSource.editingContext() != null) {
+ dataSource.editingContext().setMessageHandler(this);
+ }
+ }
+ editingAssociation = anAssociation;
+ }
+
+ /**
+ * Called by an association when it is finished editing.
+ */
+ public void associationDidEndEditing(EOAssociation anAssociation) { // System.out.println(
+ // "EODisplayGroup.associationDidEndEditing: " +
+ // anAssociation );
+ editingAssociation = null;
+ }
+
+ /**
+ * Called by associations to determine whether the contents of any objects have
+ * been changed. Returns true if the contents have changed and not all observers
+ * have been notified.
+ */
+ public boolean contentsChanged() {
+ return contentsChanged;
+ }
+
+ /**
+ * Called by associations to determine whether the selection has been changed.
+ * Returns true if the selection has changed and not all observers have been
+ * notified.
+ */
+ public boolean selectionChanged() {
+ return selectionChanged;
+ }
+
+ /**
+ * Called by an association when a user-specified value fails the association's
+ * validation rules. This implementation returns true, unless the delegate
+ * prevents this.
+ *
+ * @return True to allow the association to handle user notification, otherwise
+ * return false to let the association know that the display group
+ * notified the user.
+ */
+ public boolean associationFailedToValidateValue(EOAssociation anAssociation, String aValue, String aKey,
+ Object anObject, String anErrorDescription) {
+ Object result = notifyDelegate("displayGroupShouldDisplayAlert",
+ new Class[] { EODisplayGroup.class, String.class, String.class },
+ new Object[] { this, "Validation Failed", anErrorDescription });
+ if ((result == null) || (Boolean.TRUE.equals(result))) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Called by an association to determine whether it should enable a component
+ * that displayes a value for the specified key.
+ *
+ * @return true if an object is selected, or if the specified key is a query
+ * key. Otherwise false.
+ */
+ public boolean enabledToSetSelectedObjectValueForKey(String aKey) {
+ if ((aKey != null) && (aKey.startsWith("@")))
+ return true;
+ return (selectedObject() != null);
+ }
+
+ // association management
+
+ /**
+ * Returns the association that is currently being edited, or null if no editing
+ * is taking place.
+ */
+ public EOAssociation editingAssociation() {
+ return editingAssociation;
+ }
+
+ /**
+ * Asks the association currently editing to stop editing.
+ *
+ * @returns true if editing was stopped, false if the association refused to
+ * stop editing (if a modal dialog is displayed or a value failed to
+ * validate).
+ */
+ public boolean endEditing() {
+ if (editingAssociation == null)
+ return true;
+ return editingAssociation.endEditing();
+ }
+
+ /**
+ * Returns a read-only List of associations that are observing this display
+ * group.
+ */
+ public NSArray observingAssociations() {
+ NSArray observers = EOObserverCenter.observersForObject(this);
+ NSMutableArray result = new NSMutableArray();
+
+ Object o;
+ Enumeration e = observers.objectEnumerator();
+ while (e.hasMoreElements()) {
+ o = e.nextElement();
+ if (o instanceof EOAssociation) {
+ result.addObject(o);
+ }
+ }
+ return result;
+ }
+
+ // object management
+
+ /**
+ * Returns a read-only List containing all objects managed by the display group.
+ * This includes those objects not visible due to disqualification.
+ */
+ public NSArray allObjects() { // System.out.println( "avoided allocation: allObjects" );
+ return allObjectsProxy;
+ }
+
+ /**
+ * Clears the current selection.
+ *
+ * @return True is the selection was cleared, False if the selection could not
+ * be cleared
+ * @see #setSelectionIndexes
+ */
+ public boolean clearSelection() {
+ Object result = notifyDelegate("displayGroupShouldChangeSelection",
+ new Class[] { EODisplayGroup.class, List.class }, new Object[] { this, new NSArray(selectedObjects) });
+ if ((result != null) && (Boolean.FALSE.equals(result))) {
+ return false;
+ }
+
+ selectionChanged = true;
+ willChange();
+
+ selectedObjects.removeAllObjects();
+ selectedIndexes.removeAllObjects();
+
+ notifyDelegate("displayGroupDidChangeSelection", new Class[] { EODisplayGroup.class }, new Object[] { this });
+ notifyDelegate("displayGroupDidChangeSelectedObjects", new Class[] { EODisplayGroup.class },
+ new Object[] { this });
+
+ return true;
+ }
+
+ /**
+ * Deletes the object at the specified index, notifying the delegate before and
+ * after the operation, and then updating the selection if needed.
+ *
+ * @return True if delete was successful, false if the object was not deleted.
+ */
+ public boolean deleteObjectAtIndex(int anIndex) {
+ Object target = displayedObjects.objectAtIndex(anIndex);
+
+ Object result = notifyDelegate("displayGroupShouldDeleteObject",
+ new Class[] { EODisplayGroup.class, Object.class }, new Object[] { this, target });
+ if ((result != null) && (Boolean.FALSE.equals(result))) {
+ return false;
+ }
+
+ contentsChanged = true;
+
+ deleteObjectAtIndexNoNotify(anIndex);
+
+ if (dataSource != null) {
+ dataSource.deleteObject(target);
+ }
+
+ notifyDelegate("displayGroupDidDeleteObject", new Class[] { EODisplayGroup.class, Object.class },
+ new Object[] { this, target });
+
+ return true;
+ }
+
+ private void deleteObjectAtIndexNoNotify(int anIndex) {
+ Object target = displayedObjects.objectAtIndex(anIndex);
+
+ int i;
+
+ // remove from selected objects if necessary
+ i = indexOf(selectedObjects, target);
+ if (i != NSArray.NotFound) {
+ selectionChanged = true;
+ willChange(); // notify before removing
+ selectedObjects.removeObjectAtIndex(i);
+ selectedIndexes.remove(new Integer(i)); // comps by value
+ } else // notify - no selection change needed
+ {
+ willChange();
+ }
+
+ // remove from all objects
+ i = indexOf(allObjects, target);
+ if (i != NSArray.NotFound) {
+ allObjects.removeObjectAtIndex(i);
+ } else // otherwise should never happen
+ {
// throw new WotonomyException(
// "Displayed object not found in allObjects" );
- }
-
- // remove from displayed objects
- displayedObjects.removeObjectAtIndex( anIndex );
- }
-
- /**
- * Deletes the currently selected objects.
- * This implementation calls deleteObjectAtIndex() for
- * each index in the selection list, immediately returning
- * false if any delete operation fails.
- * @return True if all selected objects were deleted,
- * false if any deletion failed.
- */
- public boolean deleteSelection ()
- {
- int i;
- boolean result = true;
-
- Enumeration e = new NSArray( selectedObjects ).objectEnumerator();
- while ( e.hasMoreElements() )
- {
- i = indexOf( displayedObjects, e.nextElement() );
- if ( i == NSArray.NotFound )
- {
- // should never happen
- throw new WotonomyException(
- "Selected object not found in displayedObjects" );
- }
- result = result && deleteObjectAtIndex( i );
- }
-
- return result;
- }
-
- /**
- * Returns a read-only List of all objects in the display group
- * that are currently displayed by the associations.
- */
- public NSArray displayedObjects ()
- { // System.out.println( "avoided allocation: displayedObjects" );
- return displayedObjectsProxy;
- }
-
- /**
- * Requests a list of objects from the DataSource
- * and calls setObjectArray to populate the list.
- * More specifically, calls endEditing(), asks the
- * delegate, fetches the objects, notifies the delegate,
- * and populates the list.
- */
- public boolean fetch ()
- {
- endEditing();
-
- if ( dataSource == null )
- {
- return false;
- }
-
- Object result = notifyDelegate(
- "displayGroupShouldFetch",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
- if ( ( result != null ) && ( Boolean.FALSE.equals( result ) ) )
- {
- return false;
- }
-
- NSNotificationCenter.defaultCenter().postNotification(
- DisplayGroupWillFetchNotification, this, new NSDictionary() );
-
- NSArray objectList = dataSource.fetchObjects();
-
- notifyDelegate(
- "displayGroupDidFetchObjects",
- new Class[] { EODisplayGroup.class, List.class },
- new Object[] { this, objectList } );
-
- if ( selectsFirstObjectAfterFetch )
- {
- //note: there's a good chance this logic ought to be in master-detail assoc:
- // we're doing this because changes in the master object trigger a refetch
- // on the child display group which annoyingly changes the selection.
- NSArray original = new NSArray( allObjects );
- setObjectArray( objectList );
- if ( displayedObjects.size() > 0
- && !original.equals( allObjects ) ) // don't change if no change
- {
- setSelectionIndexes( new NSArray( new Integer( 0 ) ) );
- }
- }
- else
- {
- setObjectArray( objectList );
- }
-
- return true;
- }
-
- /**
- * Creates a new object at the specified index.
- * Calls insertObjectAtIndex() with the result
- * from sending createObject() to the data source.
- * Presents a JOptionPane if the create fails, unless
- * the delegate implements displayGroupCreateObjectFailed.
- * @return the newly created object.
- */
- public Object insertNewObjectAtIndex ( int anIndex )
- {
- Object result = null;
- if ( dataSource != null )
- {
- result = dataSource.createObject();
- }
- if ( result != null )
- {
- if ( insertedObjectDefaultValues != null )
- {
- Duplicator.writePropertiesForObject(
- insertedObjectDefaultValues, result );
- }
- insertObjectAtIndex( result, anIndex );
- }
- else // create failed
- {
- if ( delegate() != null )
- {
- NSSelector selector = new NSSelector(
- "displayGroupCreateObjectFailed",
- new Class[] { EODisplayGroup.class, EODataSource.class } );
- if ( selector.implementedByObject( delegate() ) )
- {
- try
- {
- selector.invoke( delegate(), new Object[] { this, dataSource } );
- return result;
- }
- catch ( Exception exc )
- {
- System.err.println( "Error notifying delegate: displayGroupCreateObjectFailed" );
- exc.printStackTrace();
- }
- }
- }
-
- // no delegate or delegate does not implement displayGroupCreateObjectFailed
-
- String message = "Data source could not create new object";
- Object delegateResult = notifyDelegate(
- "displayGroupShouldDisplayAlert",
- new Class[] { EODisplayGroup.class, String.class, String.class },
- new Object[] { this, "Error", message } );
- if ( ( delegateResult == null ) || ( Boolean.TRUE.equals( delegateResult ) ) )
- {
- JOptionPane.showMessageDialog( null, message );
- }
- }
- return result;
- }
-
- /**
- * Inserts the specified object into the list at
- * the specified index.
- */
- public void insertObjectAtIndex ( Object anObject, int anIndex )
- {
- Object result = notifyDelegate(
- "displayGroupShouldInsertObject",
- new Class[] { EODisplayGroup.class, Object.class, int.class },
- new Object[] { this, anObject, new Integer(anIndex) } );
- if ( ( result != null ) && ( Boolean.FALSE.equals( result ) ) )
- {
- return;
- }
-
- contentsChanged = true;
- updatedObjectIndex = anIndex;
- willChange();
-
-
- // add to all objects
- if ( anIndex == displayedObjects.size() )
- {
- allObjects.addObject( anObject );
- }
- else // insert before same object
- {
- Object target = displayedObjects.objectAtIndex( anIndex );
- int targetIndex = indexOf( allObjects, target );
- if ( targetIndex != NSArray.NotFound )
- {
- allObjects.insertObjectAtIndex( anObject, targetIndex );
- }
- else // should never happen
- {
- throw new WotonomyException(
- "Could not find displayed object in all objects list: "
- + target );
- }
- }
-
- // add to displayed objects
- displayedObjects.insertObjectAtIndex( anObject, anIndex );
-
- if ( dataSource != null )
- {
- if ( dataSource instanceof OrderedDataSource )
- {
- ((OrderedDataSource)dataSource).insertObjectAtIndex(
- anObject, anIndex );
- }
- else
- {
- dataSource.insertObject( anObject );
- }
- }
-
- notifyDelegate(
- "displayGroupDidInsertObject",
- new Class[] { EODisplayGroup.class, Object.class },
- new Object[] { this, anObject } );
- }
-
- /**
- * Sets contentsChanged to true and notifies all observers.
- */
- public void redisplay ()
- {
- contentsChanged = true;
- willChange();
- }
-
- /**
- * Sets the selection to the next displayed object after the current
- * selection. If the last object is selected, or if no object
- * is selected, then the first object becomes selected.
- * If multiple items are selected, the first selected item is
- * considered the selected item for the purposes of this method.
- * Does not call redisplay().
- * @return true if an object was selected.
- */
- public boolean selectNext ()
- {
- int count = displayedObjects.count();
- if ( count == 0 ) return false;
- if ( count == 1 )
- {
- selectObject( displayedObjects.objectAtIndex( 0 ) );
- return true;
- }
-
- int i = -1;
- Object selectedObject = selectedObject();
- if ( selectedObject != null )
- {
- i = indexOf( displayedObjects, selectedObject );
- }
- if ( i == NSArray.NotFound ) i = -1;
-
- // select next object
- i++;
- if ( i != displayedObjects.count() )
- {
- // set to next object
- selectedObject = displayedObjects.objectAtIndex( i );
- }
- else // out of range
- {
- // set to null
- selectedObject = displayedObjects.objectAtIndex( 0 );
- }
-
- return selectObject( selectedObject );
- }
-
- /**
- * Sets the selection to the specified object.
- * If the specified object is null or does not exist
- * in the list of displayed objects, the selection
- * will be cleared.
- * @return true if the object was selected.
- */
- public boolean selectObject ( Object anObject )
- {
- if ( ( anObject == null ) ||
- ( indexOf( displayedObjects, anObject )
- == NSArray.NotFound ) )
- {
- clearSelection();
- return false;
- }
-
- selectObjectsIdenticalTo( new NSArray( new Object[] { anObject } ) );
- return true;
- }
-
- /**
- * Sets the selection to the specified objects.
- * If the specified list is null or if none of the objects
- * in the list exist in the list of displayed objects, the
- * selection will be cleared.
- * @return true if all specified objects were selected.
- */
- public boolean selectObjectsIdenticalTo ( List anObjectList )
- {
- // optimization: check for resetting of selection
- if ( ( anObjectList != null ) && ( selectedObjects.size() == anObjectList.size() ) )
- {
- boolean identical = true;
- int size = selectedObjects.size();
- for ( int i = 0; ( i < size ) && identical; i++ )
- {
- // compare by reference
- if ( anObjectList.get( i ) != selectedObjects.get( i ) )
- {
- identical = false;
- }
- else if ( displayedObjects.indexOfIdenticalObject(
- anObjectList.get( i ) ) == NSArray.NotFound )
- {
- identical = false;
- }
- }
- if ( identical )
- {
- return true;
- }
- }
-
- Object result = notifyDelegate(
- "displayGroupShouldChangeSelection",
- new Class[] { EODisplayGroup.class, List.class },
- new Object[] { this, anObjectList } );
- if ( ( result != null ) && ( Boolean.FALSE.equals( result ) ) )
- {
- // need to notify the calling component
- // to revert back to the previous selection
- selectionChanged = true;
- willChange();
- return false;
- }
-
- int i;
- selectionChanged = true;
- willChange();
- Object o;
- selectedObjects.removeAllObjects();
- selectedIndexes.removeAllObjects();
- Iterator it = anObjectList.iterator();
- while ( it.hasNext() )
- {
- o = it.next();
- if ( ( i = displayedObjects.indexOfIdenticalObject( o ) )
- != NSArray.NotFound )
- {
- selectedObjects.addObject( o );
- selectedIndexes.addObject( new Integer( i ) );
- }
- }
-
- notifyDelegate(
- "displayGroupDidChangeSelection",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
- notifyDelegate(
- "displayGroupDidChangeSelectedObjects",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
-
- return true;
- }
-
- /**
- * Sets the selection to the previous displayed object before the current
- * selection. If the first object is selected, or if no object
- * is selected, then the last object becomes selected.
- * If multiple items are selected, the first selected item is
- * considered the selected item for the purposes of this method.
- * Does not call redisplay().
- * @return true if an object was selected.
- */
- public boolean selectPrevious ()
- {
- int i = displayedObjects.count();
- if ( i == 0 ) return false;
- if ( i == 1 )
- {
- selectObject( displayedObjects.objectAtIndex( 0 ) );
- return true;
- }
-
- Object selectedObject = selectedObject();
- if ( selectedObject != null )
- {
- i = indexOf( displayedObjects, selectedObject );
- }
- if ( i == NSArray.NotFound ) i = displayedObjects.count();
-
- // select next object
- i--;
- if ( i < 0 )
- {
- // out of range - select last object
- i = displayedObjects.count() - 1;
- }
-
- return selectObject( displayedObjects.objectAtIndex( i ) );
- }
-
- /**
- * Returns the currently selected object, or null if
- * there is no selection.
- */
- public Object selectedObject ()
- {
- if ( selectedObjects.count() == 0 )
- {
- return null;
- }
- return selectedObjects.objectAtIndex( 0 );
- }
-
- /**
- * Returns a read-only List containing all selected objects, if any.
- * Returns an empty list if no objects are selected.
- */
- public NSArray selectedObjects ()
- { // System.out.println( "avoided allocation: selectedObjects" );
- return selectedObjectsProxy;
- }
-
- /**
- * Returns a read-only List containing the indexes of all selected
- * objects, if any. The list contains instances of
- * java.lang.Number; call intValue() to retrieve the index.
- */
- public NSArray selectionIndexes ()
- {
+ }
+
+ // remove from displayed objects
+ displayedObjects.removeObjectAtIndex(anIndex);
+ }
+
+ /**
+ * Deletes the currently selected objects. This implementation calls
+ * deleteObjectAtIndex() for each index in the selection list, immediately
+ * returning false if any delete operation fails.
+ *
+ * @return True if all selected objects were deleted, false if any deletion
+ * failed.
+ */
+ public boolean deleteSelection() {
+ int i;
+ boolean result = true;
+
+ Enumeration e = new NSArray(selectedObjects).objectEnumerator();
+ while (e.hasMoreElements()) {
+ i = indexOf(displayedObjects, e.nextElement());
+ if (i == NSArray.NotFound) {
+ // should never happen
+ throw new WotonomyException("Selected object not found in displayedObjects");
+ }
+ result = result && deleteObjectAtIndex(i);
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a read-only List of all objects in the display group that are
+ * currently displayed by the associations.
+ */
+ public NSArray displayedObjects() { // System.out.println( "avoided allocation: displayedObjects" );
+ return displayedObjectsProxy;
+ }
+
+ /**
+ * Requests a list of objects from the DataSource and calls setObjectArray to
+ * populate the list. More specifically, calls endEditing(), asks the delegate,
+ * fetches the objects, notifies the delegate, and populates the list.
+ */
+ public boolean fetch() {
+ endEditing();
+
+ if (dataSource == null) {
+ return false;
+ }
+
+ Object result = notifyDelegate("displayGroupShouldFetch", new Class[] { EODisplayGroup.class },
+ new Object[] { this });
+ if ((result != null) && (Boolean.FALSE.equals(result))) {
+ return false;
+ }
+
+ NSNotificationCenter.defaultCenter().postNotification(DisplayGroupWillFetchNotification, this,
+ new NSDictionary());
+
+ NSArray objectList = dataSource.fetchObjects();
+
+ notifyDelegate("displayGroupDidFetchObjects", new Class[] { EODisplayGroup.class, List.class },
+ new Object[] { this, objectList });
+
+ if (selectsFirstObjectAfterFetch) {
+ // note: there's a good chance this logic ought to be in master-detail assoc:
+ // we're doing this because changes in the master object trigger a refetch
+ // on the child display group which annoyingly changes the selection.
+ NSArray original = new NSArray(allObjects);
+ setObjectArray(objectList);
+ if (displayedObjects.size() > 0 && !original.equals(allObjects)) // don't change if no change
+ {
+ setSelectionIndexes(new NSArray(new Integer(0)));
+ }
+ } else {
+ setObjectArray(objectList);
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates a new object at the specified index. Calls insertObjectAtIndex() with
+ * the result from sending createObject() to the data source. Presents a
+ * JOptionPane if the create fails, unless the delegate implements
+ * displayGroupCreateObjectFailed.
+ *
+ * @return the newly created object.
+ */
+ public Object insertNewObjectAtIndex(int anIndex) {
+ Object result = null;
+ if (dataSource != null) {
+ result = dataSource.createObject();
+ }
+ if (result != null) {
+ if (insertedObjectDefaultValues != null) {
+ Duplicator.writePropertiesForObject(insertedObjectDefaultValues, result);
+ }
+ insertObjectAtIndex(result, anIndex);
+ } else // create failed
+ {
+ if (delegate() != null) {
+ NSSelector selector = new NSSelector("displayGroupCreateObjectFailed",
+ new Class[] { EODisplayGroup.class, EODataSource.class });
+ if (selector.implementedByObject(delegate())) {
+ try {
+ selector.invoke(delegate(), new Object[] { this, dataSource });
+ return result;
+ } catch (Exception exc) {
+ System.err.println("Error notifying delegate: displayGroupCreateObjectFailed");
+ exc.printStackTrace();
+ }
+ }
+ }
+
+ // no delegate or delegate does not implement displayGroupCreateObjectFailed
+
+ String message = "Data source could not create new object";
+ Object delegateResult = notifyDelegate("displayGroupShouldDisplayAlert",
+ new Class[] { EODisplayGroup.class, String.class, String.class },
+ new Object[] { this, "Error", message });
+ if ((delegateResult == null) || (Boolean.TRUE.equals(delegateResult))) {
+ JOptionPane.showMessageDialog(null, message);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Inserts the specified object into the list at the specified index.
+ */
+ public void insertObjectAtIndex(Object anObject, int anIndex) {
+ Object result = notifyDelegate("displayGroupShouldInsertObject",
+ new Class[] { EODisplayGroup.class, Object.class, int.class },
+ new Object[] { this, anObject, new Integer(anIndex) });
+ if ((result != null) && (Boolean.FALSE.equals(result))) {
+ return;
+ }
+
+ contentsChanged = true;
+ updatedObjectIndex = anIndex;
+ willChange();
+
+ // add to all objects
+ if (anIndex == displayedObjects.size()) {
+ allObjects.addObject(anObject);
+ } else // insert before same object
+ {
+ Object target = displayedObjects.objectAtIndex(anIndex);
+ int targetIndex = indexOf(allObjects, target);
+ if (targetIndex != NSArray.NotFound) {
+ allObjects.insertObjectAtIndex(anObject, targetIndex);
+ } else // should never happen
+ {
+ throw new WotonomyException("Could not find displayed object in all objects list: " + target);
+ }
+ }
+
+ // add to displayed objects
+ displayedObjects.insertObjectAtIndex(anObject, anIndex);
+
+ if (dataSource != null) {
+ if (dataSource instanceof OrderedDataSource) {
+ ((OrderedDataSource) dataSource).insertObjectAtIndex(anObject, anIndex);
+ } else {
+ dataSource.insertObject(anObject);
+ }
+ }
+
+ notifyDelegate("displayGroupDidInsertObject", new Class[] { EODisplayGroup.class, Object.class },
+ new Object[] { this, anObject });
+ }
+
+ /**
+ * Sets contentsChanged to true and notifies all observers.
+ */
+ public void redisplay() {
+ contentsChanged = true;
+ willChange();
+ }
+
+ /**
+ * Sets the selection to the next displayed object after the current selection.
+ * If the last object is selected, or if no object is selected, then the first
+ * object becomes selected. If multiple items are selected, the first selected
+ * item is considered the selected item for the purposes of this method. Does
+ * not call redisplay().
+ *
+ * @return true if an object was selected.
+ */
+ public boolean selectNext() {
+ int count = displayedObjects.count();
+ if (count == 0)
+ return false;
+ if (count == 1) {
+ selectObject(displayedObjects.objectAtIndex(0));
+ return true;
+ }
+
+ int i = -1;
+ Object selectedObject = selectedObject();
+ if (selectedObject != null) {
+ i = indexOf(displayedObjects, selectedObject);
+ }
+ if (i == NSArray.NotFound)
+ i = -1;
+
+ // select next object
+ i++;
+ if (i != displayedObjects.count()) {
+ // set to next object
+ selectedObject = displayedObjects.objectAtIndex(i);
+ } else // out of range
+ {
+ // set to null
+ selectedObject = displayedObjects.objectAtIndex(0);
+ }
+
+ return selectObject(selectedObject);
+ }
+
+ /**
+ * Sets the selection to the specified object. If the specified object is null
+ * or does not exist in the list of displayed objects, the selection will be
+ * cleared.
+ *
+ * @return true if the object was selected.
+ */
+ public boolean selectObject(Object anObject) {
+ if ((anObject == null) || (indexOf(displayedObjects, anObject) == NSArray.NotFound)) {
+ clearSelection();
+ return false;
+ }
+
+ selectObjectsIdenticalTo(new NSArray(new Object[] { anObject }));
+ return true;
+ }
+
+ /**
+ * Sets the selection to the specified objects. If the specified list is null or
+ * if none of the objects in the list exist in the list of displayed objects,
+ * the selection will be cleared.
+ *
+ * @return true if all specified objects were selected.
+ */
+ public boolean selectObjectsIdenticalTo(List anObjectList) {
+ // optimization: check for resetting of selection
+ if ((anObjectList != null) && (selectedObjects.size() == anObjectList.size())) {
+ boolean identical = true;
+ int size = selectedObjects.size();
+ for (int i = 0; (i < size) && identical; i++) {
+ // compare by reference
+ if (anObjectList.get(i) != selectedObjects.get(i)) {
+ identical = false;
+ } else if (displayedObjects.indexOfIdenticalObject(anObjectList.get(i)) == NSArray.NotFound) {
+ identical = false;
+ }
+ }
+ if (identical) {
+ return true;
+ }
+ }
+
+ Object result = notifyDelegate("displayGroupShouldChangeSelection",
+ new Class[] { EODisplayGroup.class, List.class }, new Object[] { this, anObjectList });
+ if ((result != null) && (Boolean.FALSE.equals(result))) {
+ // need to notify the calling component
+ // to revert back to the previous selection
+ selectionChanged = true;
+ willChange();
+ return false;
+ }
+
+ int i;
+ selectionChanged = true;
+ willChange();
+ Object o;
+ selectedObjects.removeAllObjects();
+ selectedIndexes.removeAllObjects();
+ Iterator it = anObjectList.iterator();
+ while (it.hasNext()) {
+ o = it.next();
+ if ((i = displayedObjects.indexOfIdenticalObject(o)) != NSArray.NotFound) {
+ selectedObjects.addObject(o);
+ selectedIndexes.addObject(new Integer(i));
+ }
+ }
+
+ notifyDelegate("displayGroupDidChangeSelection", new Class[] { EODisplayGroup.class }, new Object[] { this });
+ notifyDelegate("displayGroupDidChangeSelectedObjects", new Class[] { EODisplayGroup.class },
+ new Object[] { this });
+
+ return true;
+ }
+
+ /**
+ * Sets the selection to the previous displayed object before the current
+ * selection. If the first object is selected, or if no object is selected, then
+ * the last object becomes selected. If multiple items are selected, the first
+ * selected item is considered the selected item for the purposes of this
+ * method. Does not call redisplay().
+ *
+ * @return true if an object was selected.
+ */
+ public boolean selectPrevious() {
+ int i = displayedObjects.count();
+ if (i == 0)
+ return false;
+ if (i == 1) {
+ selectObject(displayedObjects.objectAtIndex(0));
+ return true;
+ }
+
+ Object selectedObject = selectedObject();
+ if (selectedObject != null) {
+ i = indexOf(displayedObjects, selectedObject);
+ }
+ if (i == NSArray.NotFound)
+ i = displayedObjects.count();
+
+ // select next object
+ i--;
+ if (i < 0) {
+ // out of range - select last object
+ i = displayedObjects.count() - 1;
+ }
+
+ return selectObject(displayedObjects.objectAtIndex(i));
+ }
+
+ /**
+ * Returns the currently selected object, or null if there is no selection.
+ */
+ public Object selectedObject() {
+ if (selectedObjects.count() == 0) {
+ return null;
+ }
+ return selectedObjects.objectAtIndex(0);
+ }
+
+ /**
+ * Returns a read-only List containing all selected objects, if any. Returns an
+ * empty list if no objects are selected.
+ */
+ public NSArray selectedObjects() { // System.out.println( "avoided allocation: selectedObjects" );
+ return selectedObjectsProxy;
+ }
+
+ /**
+ * Returns a read-only List containing the indexes of all selected objects, if
+ * any. The list contains instances of java.lang.Number; call intValue() to
+ * retrieve the index.
+ */
+ public NSArray selectionIndexes() {
// return selectedIndexes;
- int i;
- NSMutableArray result = new NSMutableArray();
- Enumeration e = selectedObjects.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- i = indexOf( displayedObjects, e.nextElement() );
- if ( i != NSArray.NotFound )
- {
- result.addObject( new Integer( i ) );
- }
- else
- {
- System.err.println(
- "Should never happen: selected objects not in displayed objects" );
- new RuntimeException().printStackTrace( System.err );
- }
- }
- return result;
- }
-
- /**
- * Sets the objects managed by this display group.
- * updateDisplayedObjects() is called to filter the
- * display objects. The previous selection will be
- * maintained if possible. The data source is not
- * notified.
- */
- public void setObjectArray ( List anObjectList )
- {
- if ( anObjectList == null ) anObjectList = new NSArray();
-
- Object result = notifyDelegate(
- "displayGroupDisplayArrayForObjects",
- new Class[] { EODisplayGroup.class, List.class },
- new Object[] { this, anObjectList } );
- if ( result != null )
- {
- anObjectList = (List) result;
- }
-
- contentsChanged = true;
- willChange();
-
- NSArray oldSelectedObjects = new NSArray( selectedObjects ); // copy
-
- // reset allObjects to new list
- allObjects.removeAllObjects();
- allObjects.addObjectsFromArray( anObjectList );
-
- // update the displayed object list
- updateDisplayedObjects();
-
- // restore the selection if possible
- selectObjectsIdenticalTo( oldSelectedObjects );
- }
-
- /**
- * Sets the currently selected object, or clears the
- * selection if the object is not found or is null.
- * Note: it's not clear how this differs from
- * selectObject in the spec. It is recommended that
- * you call selectObject for now.
- */
- public void setSelectedObject ( Object anObject )
- {
- selectObject( anObject );
- }
-
- /**
- * Sets the current selection to the specified objects.
- * The previous selection is cleared, and any objects
- * in the display group that are in the specified list
- * are then selected. If no items in the specified list
- * are found in the display group, then the selection is
- * effectively cleared.
- * Note: it's not clear how this differs from
- * selectObjectsIdenticalTo in the spec.
- * It is recommended that you call that method for now.
- */
- public void setSelectedObjects ( List aList )
- {
- selectObjectsIdenticalTo( aList );
- }
-
- /**
- * Sets the current selection to the objects at the
- * specified indexes. Items in the list are assumed
- * to be instances of java.lang.Number.
- * The previous selection is cleared, and any objects
- * in the display group that are in the specified list
- * are then selected. If no items in the specified list
- * are found in the display group, then the selection is
- * effectively cleared.
- */
- public boolean setSelectionIndexes ( List aList )
- {
- Object o;
- int index;
- NSMutableArray objects = new NSMutableArray();
- Iterator it = aList.iterator();
- while ( it.hasNext() )
- {
- index = ((Number)it.next()).intValue();
- if ( index < displayedObjects.count() )
- {
- o = displayedObjects.objectAtIndex( index );
- if ( o != null )
- {
- objects.add( o );
- }
- }
- }
- return selectObjectsIdenticalTo( objects );
- }
-
- /**
- * Applies the qualifier to all objects and sorts
- * the results to update the list of displayed objects.
- * Observing associations are notified to reflect the changes.
- */
- public void updateDisplayedObjects ()
- {
- contentsChanged = true;
- updatedObjectIndex = -1;
- willChange();
-
- displayedObjects.removeAllObjects();
-
- displayedObjects.addObjectsFromArray( allObjects );
-
- // apply qualifier, if any
- if ( qualifier() != null )
- {
- EOQualifier.filterArrayWithQualifier(
- displayedObjects, qualifier() );
- }
-
- // apply sort orderings, if any
- NSArray orderings = sortOrderings();
- if ( orderings != null )
- {
- if ( orderings.count() > 0 )
- {
- selectionChanged = true;
- willChange();
- EOSortOrdering.sortArrayUsingKeyOrderArray(
- displayedObjects, orderings );
- }
- }
-
- // make sure the selectedObjects is a subset of displayedObjects
- int i;
- Object o;
- Iterator it = new LinkedList( selectedObjects ).iterator();
- boolean removeflag = false;
- selectedIndexes.removeAllObjects();
- while ( it.hasNext() )
- {
- o = it.next();
- if ( ( i = displayedObjects.indexOfIdenticalObject( o ) )
- == NSArray.NotFound )
- {
- selectedObjects.removeIdenticalObject( o );
- removeflag = true;
- }
- else
- {
- selectedIndexes.addObject( new Integer( i ) );
- }
- }
-
- //Note: it is important to put the
- //selectionChanged = true line below remove.
- if (removeflag)
- {
- selectionChanged = true;
- willChange();
-
- notifyDelegate(
- "displayGroupDidChangeSelection",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
- notifyDelegate(
- "displayGroupDidChangeSelectedObjects",
- new Class[] { EODisplayGroup.class },
- new Object[] { this } );
- }
- }
-
- /**
- * Returns the index of the changed object. If more than
- * one object has changed, -1 is returned.
- */
- public int updatedObjectIndex ()
- {
- return updatedObjectIndex;
- }
-
- // getting and setting values in objects
-
- /**
- * Returns a value on the selected object for the specified key.
- */
- public Object selectedObjectValueForKey ( String aKey )
- {
- Object selectedObject = selectedObject();
- if ( selectedObject == null ) return null;
- return valueForObject( selectedObject, aKey );
- }
-
- /**
- * Sets the specified value for the specified key on
- * all selected objects.
- */
- public boolean setSelectedObjectValue (
- Object aValue, String aKey )
- {
- Object selectedObject = selectedObject();
- if ( selectedObject == null ) return false;
- return setValueForObject( aValue, selectedObject, aKey );
- }
-
- /**
- * Sets the specified value for the specified key on
- * the specified object. Validations may be triggered,
- * and error dialogs may appear to the user.
- * @return True if the value was set successfully,
- * false if the value could not be set and the update
- * operation should not continue.
- */
- public boolean setValueForObject (
- Object aValue, Object anObject, String aKey )
- {
- // notify object's observers:
- // this includes us, and will notify our observers
- EOObserverCenter.notifyObserversObjectWillChange( anObject );
-
- //TODO: if key is null, need to remove old object
- // and add new object instead of simply replacing it.
-
- try
- {
- if ( anObject instanceof EOKeyValueCoding )
- {
- ((EOKeyValueCoding)anObject).takeValueForKey( aValue, aKey );
- }
- else
- {
- EOKeyValueCodingSupport.takeValueForKey( anObject, aValue, aKey );
- }
- }
- catch ( RuntimeException exc )
- {
- Object result = notifyDelegate(
- "displayGroupShouldDisplayAlert",
- new Class[] { EODisplayGroup.class, String.class, String.class },
- new Object[] { this, "Error", exc.getMessage() } );
- if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) )
- {
- throw exc;
- }
- return false;
- }
-
- notifyDelegate(
- "displayGroupDidSetValueForObject",
- new Class[] { EODisplayGroup.class, Object.class, Object.class, String.class },
- new Object[] { this, aValue, anObject, aKey } );
-
- return true;
- }
-
- /**
- * Calls setValueForObject() for the object at
- * the specified index.
- */
- public boolean setValueForObjectAtIndex (
- Object aValue, int anIndex, String aKey )
- {
- return setValueForObject(
- aValue, displayedObjects.objectAtIndex( anIndex ), aKey );
- }
-
- /**
- * Returns the value for the specified key on the specified object.
- */
- public Object valueForObject ( Object anObject, String aKey )
- {
- // empty string is considered the identity property
- if ( aKey == null ) return anObject;
- if ( aKey.equals( "" ) ) return anObject;
-
- try
- {
- if ( anObject instanceof EOKeyValueCoding )
- {
- return ((EOKeyValueCoding)anObject).valueForKey( aKey );
- }
- else
- {
- return EOKeyValueCodingSupport.valueForKey( anObject, aKey );
- }
- }
- catch ( RuntimeException exc )
- {
- Object result = notifyDelegate(
- "displayGroupShouldDisplayAlert",
- new Class[] { EODisplayGroup.class, String.class, String.class },
- new Object[] { this, "Error", exc.getMessage() } );
- if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) )
- {
- throw exc;
- }
- return null;
- }
- }
-
- /**
- * Calls valueForObject() for the object at the specified index.
- */
- public Object valueForObjectAtIndex ( int anIndex, String aKey )
- {
- Object o = displayedObjects.objectAtIndex( anIndex );
- return valueForObject( o, aKey );
- }
-
- /**
- * Prints out the list of displayed objects.
- */
- public String toString()
- {
- return displayedObjects.toString();
- }
-
-
- /**
- * Handles notifications from the data source's editing context,
- * looking for InvalidatedAllObjectsInStoreNotification and
- * ObjectsChangedInEditingContextNotification, refetching in
- * the former case and updating displayed objects in the latter.
- * Note: This method is not in the public specification.
- */
- public void objectsInvalidatedInEditingContext( NSNotification aNotification )
- {
- if ( EOObjectStore.InvalidatedAllObjectsInStoreNotification
- .equals( aNotification.name() ) )
- {
- Object result = notifyDelegate(
- "displayGroupShouldRefetch",
- new Class[] { EODisplayGroup.class, NSNotification.class },
- new Object[] { this, aNotification } );
- if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) )
- {
- fetch();
- }
- }
- else
- if ( EOEditingContext.ObjectsChangedInEditingContextNotification
- .equals( aNotification.name() ) )
- {
- Object result = notifyDelegate(
- "displayGroupShouldRedisplay",
- new Class[] { EODisplayGroup.class, NSNotification.class },
- new Object[] { this, aNotification } );
- if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) )
- {
- int index;
- Enumeration e;
- boolean didChange = false;
- NSDictionary userInfo = aNotification.userInfo();
-
- // inserts are ignored
-
- // mark updated objects as updated
- NSArray updates = (NSArray) userInfo.objectForKey(
- EOObjectStore.UpdatedKey );
- e = updates.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- index = indexOf( displayedObjects, e.nextElement() );
- if ( index != NSArray.NotFound )
- {
- //System.out.println( "EODisplayGroup: updated: " + index );
- if ( ! didChange )
- {
- didChange = true;
- contentsChanged = true;
- willChange();
- updatedObjectIndex = index;
- }
- else
- {
- updatedObjectIndex = -1;
- }
- }
- }
-
- // treat invalidated objects as updated
- NSArray invalidates = (NSArray) userInfo.objectForKey(
- EOObjectStore.InvalidatedKey );
- e = invalidates.objectEnumerator();
- while ( e.hasMoreElements() )
- {
- index = indexOf( displayedObjects, e.nextElement() );
- if ( index != NSArray.NotFound )
- {
- //System.out.println( "EODisplayGroup: invalidated: " + index );
- if ( ! didChange )
- {
- didChange = true;
- contentsChanged = true;
- willChange();
- updatedObjectIndex = index;
- }
- else
- {
- updatedObjectIndex = -1;
- }
- }
- }
-
- // remove deletes from display group if they exist
- NSArray deletes = (NSArray) userInfo.objectForKey(
- EOObjectStore.DeletedKey );
- e = deletes.objectEnumerator();
- Object o;
- while ( e.hasMoreElements() )
- {
- o = e.nextElement();
- index = indexOf( displayedObjects, o );
- if ( index != NSArray.NotFound )
- {
- //System.out.println( "EODisplayGroup: deleted: " + o );
- deleteObjectAtIndexNoNotify( index );
- }
- }
-
- if ( !usesOptimisticRefresh() )
- {
- updateDisplayedObjects();
- }
- }
- }
-
- }
-
- // static methods
-
- /**
- * Specifies the default behavior for whether changes
- * should be validated immediately for all display groups.
- */
- public static boolean
- globalDefaultForValidatesChangesImmediately ()
- {
- return globalDefaultForValidatesChangesImmediately;
- }
-
- /**
- * Specifies the default string matching format for all
- * display groups.
- */
- public static String globalDefaultStringMatchFormat ()
- {
- return globalDefaultStringMatchFormat;
- }
-
- /**
- * Specifies the default string matching operator for all
- * display groups.
- */
- public static String globalDefaultStringMatchOperator ()
- {
- return globalDefaultStringMatchOperator;
- }
-
- /**
- * Sets the default behavior for validating changes
- * for all display groups.
- */
- public static void
- setGlobalDefaultForValidatesChangesImmediately (
- boolean validatesImmediately )
- {
- globalDefaultForValidatesChangesImmediately =
- validatesImmediately;
- }
-
- /**
- * Sets the default string matching format that
- * will be used by all display groups.
- */
- public static void
- setGlobalDefaultStringMatchFormat ( String aFormat )
- {
- globalDefaultStringMatchFormat = aFormat;
- }
-
- /**
- * Sets the default string matching operator that
- * will be used by all display groups.
- */
- public static void
- setGlobalDefaultStringMatchOperator ( String anOperator )
- {
- globalDefaultStringMatchOperator = anOperator;
- }
-
- /**
- * Needed because we don't inherit from NSObject.
- * Calls EOObserverCenter.notifyObserversObjectWillChange.
- */
- protected void willChange()
- {
- EOObserverCenter.notifyObserversObjectWillChange( this );
- }
-
- /**
- * Called by LastGroupObserver to clear flags.
- */
- protected void processRecentChanges()
- {
- contentsChanged = false;
- selectionChanged = false;
- }
-
- /**
- * Returns the index of the specified object in the
- * specified NSArray, comparing by value or by reference
- * as determined by the private instance variable
- * compareByReference. If not found, returns NSArray.NotFound.
- */
- private int indexOf( NSArray anArray, Object anObject )
- {
- if ( compareByReference )
- {
- return anArray.indexOfIdenticalObject( anObject );
- }
- else
- {
- return anArray.indexOf( anObject );
- }
- }
-
- // interface EOObserving
-
- /**
- * Receives notifications of changes from objects that
- * are managed by this display group. This implementation
- * sets updatedObjectIndex and contentsChanged as appropriate.
- */
- public void objectWillChange(Object anObject)
- {
- int index = indexOf( displayedObjects, anObject );
- if ( index != NSArray.NotFound )
- {
- updatedObjectIndex = index;
- contentsChanged = true;
- willChange();
- }
- }
-
- // interface EOEditingContext.Editor
-
- /**
- * Called before the editing context begins to save changes.
- * This implementation calls endEditing().
- */
- public void editingContextWillSaveChanges(
- EOEditingContext anEditingContext )
- {
- endEditing();
- }
-
- /**
- * Called to determine whether this editor has changes
- * that have not been committed to the object in the context.
- */
- public boolean editorHasChangesForEditingContext(
- EOEditingContext anEditingContext )
- {
- return ( editingAssociation() != null );
- }
-
- // interface EOEditingContext.MessageHandler
-
- /**
- * Called to display a message for an error that occurred
- * in the specified editing context. If the delegate allows,
- * this implementation presents an informational JOptionPane.
- * Override to customize.
- */
- public void editingContextPresentErrorMessage(
- EOEditingContext anEditingContext,
- String aMessage )
- {
- Object result = notifyDelegate(
- "displayGroupShouldDisplayAlert",
- new Class[] { EODisplayGroup.class, String.class, String.class },
- new Object[] { this, "Error", aMessage } );
- if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) )
- {
- JOptionPane.showMessageDialog( null, aMessage );
- }
- }
-
- /**
- * Called by the specified object store to determine whether
- * fetching should continue, where count is the current count
- * and limit is the limit as specified by the fetch specification.
- * This implementation presents an JOptionPane allowing the user
- * to specify whether to continue. Override to customize.
- */
- public boolean editingContextShouldContinueFetching(
- EOEditingContext anEditingContext,
- int count,
- int limit,
- EOObjectStore anObjectStore )
- {
- return ( JOptionPane.showConfirmDialog( null,
- "Fetch limit reached: do you wish to continue?",
- "Continue?",
- JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION );
- }
-
- /**
- * Sends the specified message to the delegate.
- * Returns the return value of the method,
- * or null if no return value or no delegate
- * or no implementation.
- */
- private Object notifyDelegate(
- String aMethodName, Class[] types, Object[] params )
- {
- try
- {
- Object delegate = delegate();
- if ( delegate == null ) return null;
- return NSSelector.invoke(
- aMethodName, types, delegate, params );
- }
- catch ( NoSuchMethodException e )
- {
- // ignore: not implemented
- }
- catch ( Exception exc )
- {
- // log to standard error
- System.err.println(
- "Error while messaging delegate: " +
- delegate + " : " + aMethodName );
- exc.printStackTrace();
- }
-
- return null;
- }
-
- /**
- * DisplayGroups can delegate important decisions to a Delegate.
- * Note that DisplayGroup doesn't require its delegates to implement
- * this interface: rather, this interface defines the methods that
- * DisplayGroup will attempt to invoke dynamically on its delegate.
- * The delegate may choose to implement only a subset of the methods
- * on the interface.
- */
- public interface Delegate
- {
- /**
- * Called when the specified data source fails
- * to create an object for the specified display group.
- */
- void displayGroupCreateObjectFailed (
- EODisplayGroup aDisplayGroup,
- EODataSource aDataSource );
-
- /**
- * Called after the specified display group's
- * data source is changed.
- */
- void displayGroupDidChangeDataSource (
- EODisplayGroup aDisplayGroup );
-
- /**
- * Called after a change occurs in the specified
- * display group's selected objects.
- */
- void displayGroupDidChangeSelectedObjects (
- EODisplayGroup aDisplayGroup );
-
- /**
- * Called after the specified display group's
- * selection has changed.
- */
- void displayGroupDidChangeSelection (
- EODisplayGroup aDisplayGroup );
-
- /**
- * Called after the specified display group has
- * deleted the specified object.
- */
- void displayGroupDidDeleteObject (
- EODisplayGroup aDisplayGroup,
- Object anObject );
-
- /**
- * Called after the specified display group
- * has fetched the specified object list.
- */
- void displayGroupDidFetchObjects (
- EODisplayGroup aDisplayGroup,
- List anObjectList );
-
- /**
- * Called after the specified display group
- * has inserted the specified object into
- * its internal object list.
- */
- void displayGroupDidInsertObject (
- EODisplayGroup aDisplayGroup,
- Object anObject );
-
- /**
- * Called after the specified display group
- * has set the specified value for the specified
- * object and key.
- */
- void displayGroupDidSetValueForObject (
- EODisplayGroup aDisplayGroup,
- Object aValue,
- Object anObject,
- String aKey );
-
- /**
- * Called by the specified display group to
- * determine what objects should be displayed
- * for the objects in the specified list.
- * @return An NSArray containing the objects
- * to be displayed for the objects in the
- * specified list.
- */
- NSArray displayGroupDisplayArrayForObjects (
- EODisplayGroup aDisplayGroup,
- List aList );
-
- /**
- * Called by the specified display group before
- * it attempts to change the selection.
- * @return True to allow the selection to change,
- * false otherwise.
- */
- boolean displayGroupShouldChangeSelection (
- EODisplayGroup aDisplayGroup,
- List aSelectionList );
-
- /**
- * Called by the specified display group before
- * it attempts to delete the specified object.
- * @return True to allow the object to be deleted
- * false to prevent the deletion.
- */
- boolean displayGroupShouldDeleteObject (
- EODisplayGroup aDisplayGroup,
- Object anObject );
-
- /**
- * Called by the specified display group before
- * it attempts display the specified alert to
- * the user.
- * @return True to allow the message to be
- * displayed, false if you want to handle the
- * alert yourself and suppress the display group's
- * notification.
- */
- boolean displayGroupShouldDisplayAlert (
- EODisplayGroup aDisplayGroup,
- String aTitle,
- String aMessage );
-
- /**
- * Called by the specified display group before
- * it attempts fetch objects.
- * @return True to allow the fetch to take place,
- * false to prevent the fetch.
- */
- boolean displayGroupShouldFetch (
- EODisplayGroup aDisplayGroup );
-
- /**
- * Called by the specified display group before
- * it attempts to insert the specified object.
- * @return True to allow the object to be inserted
- * false to prevent the insertion.
- */
- boolean displayGroupShouldInsertObject (
- EODisplayGroup aDisplayGroup,
- Object anObject,
- int anIndex );
-
- /**
- * Called by the specified display group when
- * it receives the specified
- * ObjectsChangedInEditingContextNotification.
- * @return True to allow the display group to
- * update the display (recommended), false
- * to prevent the update.
- */
- boolean displayGroupShouldRedisplay (
- EODisplayGroup aDisplayGroup,
- NSNotification aNotification );
-
- /**
- * Called by the specified display group when
- * it receives the specified
- * InvalidatedAllObjectsInStoreNotification.
- * @return True to allow the display group to
- * refetch (recommended), false to prevent the
- * refetch.
- */
- boolean displayGroupShouldRefetch (
- EODisplayGroup aDisplayGroup,
- NSNotification aNotification );
-
- }
+ int i;
+ NSMutableArray result = new NSMutableArray();
+ Enumeration e = selectedObjects.objectEnumerator();
+ while (e.hasMoreElements()) {
+ i = indexOf(displayedObjects, e.nextElement());
+ if (i != NSArray.NotFound) {
+ result.addObject(new Integer(i));
+ } else {
+ System.err.println("Should never happen: selected objects not in displayed objects");
+ new RuntimeException().printStackTrace(System.err);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Sets the objects managed by this display group. updateDisplayedObjects() is
+ * called to filter the display objects. The previous selection will be
+ * maintained if possible. The data source is not notified.
+ */
+ public void setObjectArray(List anObjectList) {
+ if (anObjectList == null)
+ anObjectList = new NSArray();
+
+ Object result = notifyDelegate("displayGroupDisplayArrayForObjects",
+ new Class[] { EODisplayGroup.class, List.class }, new Object[] { this, anObjectList });
+ if (result != null) {
+ anObjectList = (List) result;
+ }
+
+ contentsChanged = true;
+ willChange();
+
+ NSArray oldSelectedObjects = new NSArray(selectedObjects); // copy
+
+ // reset allObjects to new list
+ allObjects.removeAllObjects();
+ allObjects.addObjectsFromArray(anObjectList);
+
+ // update the displayed object list
+ updateDisplayedObjects();
+
+ // restore the selection if possible
+ selectObjectsIdenticalTo(oldSelectedObjects);
+ }
+
+ /**
+ * Sets the currently selected object, or clears the selection if the object is
+ * not found or is null. Note: it's not clear how this differs from selectObject
+ * in the spec. It is recommended that you call selectObject for now.
+ */
+ public void setSelectedObject(Object anObject) {
+ selectObject(anObject);
+ }
+
+ /**
+ * Sets the current selection to the specified objects. The previous selection
+ * is cleared, and any objects in the display group that are in the specified
+ * list are then selected. If no items in the specified list are found in the
+ * display group, then the selection is effectively cleared. Note: it's not
+ * clear how this differs from selectObjectsIdenticalTo in the spec. It is
+ * recommended that you call that method for now.
+ */
+ public void setSelectedObjects(List aList) {
+ selectObjectsIdenticalTo(aList);
+ }
+
+ /**
+ * Sets the current selection to the objects at the specified indexes. Items in
+ * the list are assumed to be instances of java.lang.Number. The previous
+ * selection is cleared, and any objects in the display group that are in the
+ * specified list are then selected. If no items in the specified list are found
+ * in the display group, then the selection is effectively cleared.
+ */
+ public boolean setSelectionIndexes(List aList) {
+ Object o;
+ int index;
+ NSMutableArray objects = new NSMutableArray();
+ Iterator it = aList.iterator();
+ while (it.hasNext()) {
+ index = ((Number) it.next()).intValue();
+ if (index < displayedObjects.count()) {
+ o = displayedObjects.objectAtIndex(index);
+ if (o != null) {
+ objects.add(o);
+ }
+ }
+ }
+ return selectObjectsIdenticalTo(objects);
+ }
+
+ /**
+ * Applies the qualifier to all objects and sorts the results to update the list
+ * of displayed objects. Observing associations are notified to reflect the
+ * changes.
+ */
+ public void updateDisplayedObjects() {
+ contentsChanged = true;
+ updatedObjectIndex = -1;
+ willChange();
+
+ displayedObjects.removeAllObjects();
+
+ displayedObjects.addObjectsFromArray(allObjects);
+
+ // apply qualifier, if any
+ if (qualifier() != null) {
+ EOQualifier.filterArrayWithQualifier(displayedObjects, qualifier());
+ }
+
+ // apply sort orderings, if any
+ NSArray orderings = sortOrderings();
+ if (orderings != null) {
+ if (orderings.count() > 0) {
+ selectionChanged = true;
+ willChange();
+ EOSortOrdering.sortArrayUsingKeyOrderArray(displayedObjects, orderings);
+ }
+ }
+
+ // make sure the selectedObjects is a subset of displayedObjects
+ int i;
+ Object o;
+ Iterator it = new LinkedList(selectedObjects).iterator();
+ boolean removeflag = false;
+ selectedIndexes.removeAllObjects();
+ while (it.hasNext()) {
+ o = it.next();
+ if ((i = displayedObjects.indexOfIdenticalObject(o)) == NSArray.NotFound) {
+ selectedObjects.removeIdenticalObject(o);
+ removeflag = true;
+ } else {
+ selectedIndexes.addObject(new Integer(i));
+ }
+ }
+
+ // Note: it is important to put the
+ // selectionChanged = true line below remove.
+ if (removeflag) {
+ selectionChanged = true;
+ willChange();
+
+ notifyDelegate("displayGroupDidChangeSelection", new Class[] { EODisplayGroup.class },
+ new Object[] { this });
+ notifyDelegate("displayGroupDidChangeSelectedObjects", new Class[] { EODisplayGroup.class },
+ new Object[] { this });
+ }
+ }
+
+ /**
+ * Returns the index of the changed object. If more than one object has changed,
+ * -1 is returned.
+ */
+ public int updatedObjectIndex() {
+ return updatedObjectIndex;
+ }
+
+ // getting and setting values in objects
+
+ /**
+ * Returns a value on the selected object for the specified key.
+ */
+ public Object selectedObjectValueForKey(String aKey) {
+ Object selectedObject = selectedObject();
+ if (selectedObject == null)
+ return null;
+ return valueForObject(selectedObject, aKey);
+ }
+
+ /**
+ * Sets the specified value for the specified key on all selected objects.
+ */
+ public boolean setSelectedObjectValue(Object aValue, String aKey) {
+ Object selectedObject = selectedObject();
+ if (selectedObject == null)
+ return false;
+ return setValueForObject(aValue, selectedObject, aKey);
+ }
+
+ /**
+ * Sets the specified value for the specified key on the specified object.
+ * Validations may be triggered, and error dialogs may appear to the user.
+ *
+ * @return True if the value was set successfully, false if the value could not
+ * be set and the update operation should not continue.
+ */
+ public boolean setValueForObject(Object aValue, Object anObject, String aKey) {
+ // notify object's observers:
+ // this includes us, and will notify our observers
+ EOObserverCenter.notifyObserversObjectWillChange(anObject);
+
+ // TODO: if key is null, need to remove old object
+ // and add new object instead of simply replacing it.
+
+ try {
+ if (anObject instanceof EOKeyValueCoding) {
+ ((EOKeyValueCoding) anObject).takeValueForKey(aValue, aKey);
+ } else {
+ EOKeyValueCodingSupport.takeValueForKey(anObject, aValue, aKey);
+ }
+ } catch (RuntimeException exc) {
+ Object result = notifyDelegate("displayGroupShouldDisplayAlert",
+ new Class[] { EODisplayGroup.class, String.class, String.class },
+ new Object[] { this, "Error", exc.getMessage() });
+ if ((result == null) || (Boolean.TRUE.equals(result))) {
+ throw exc;
+ }
+ return false;
+ }
+
+ notifyDelegate("displayGroupDidSetValueForObject",
+ new Class[] { EODisplayGroup.class, Object.class, Object.class, String.class },
+ new Object[] { this, aValue, anObject, aKey });
+
+ return true;
+ }
+
+ /**
+ * Calls setValueForObject() for the object at the specified index.
+ */
+ public boolean setValueForObjectAtIndex(Object aValue, int anIndex, String aKey) {
+ return setValueForObject(aValue, displayedObjects.objectAtIndex(anIndex), aKey);
+ }
+
+ /**
+ * Returns the value for the specified key on the specified object.
+ */
+ public Object valueForObject(Object anObject, String aKey) {
+ // empty string is considered the identity property
+ if (aKey == null)
+ return anObject;
+ if (aKey.equals(""))
+ return anObject;
+
+ try {
+ if (anObject instanceof EOKeyValueCoding) {
+ return ((EOKeyValueCoding) anObject).valueForKey(aKey);
+ } else {
+ return EOKeyValueCodingSupport.valueForKey(anObject, aKey);
+ }
+ } catch (RuntimeException exc) {
+ Object result = notifyDelegate("displayGroupShouldDisplayAlert",
+ new Class[] { EODisplayGroup.class, String.class, String.class },
+ new Object[] { this, "Error", exc.getMessage() });
+ if ((result == null) || (Boolean.TRUE.equals(result))) {
+ throw exc;
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Calls valueForObject() for the object at the specified index.
+ */
+ public Object valueForObjectAtIndex(int anIndex, String aKey) {
+ Object o = displayedObjects.objectAtIndex(anIndex);
+ return valueForObject(o, aKey);
+ }
+
+ /**
+ * Prints out the list of displayed objects.
+ */
+ public String toString() {
+ return displayedObjects.toString();
+ }
+
+ /**
+ * Handles notifications from the data source's editing context, looking for
+ * InvalidatedAllObjectsInStoreNotification and
+ * ObjectsChangedInEditingContextNotification, refetching in the former case and
+ * updating displayed objects in the latter. Note: This method is not in the
+ * public specification.
+ */
+ public void objectsInvalidatedInEditingContext(NSNotification aNotification) {
+ if (EOObjectStore.InvalidatedAllObjectsInStoreNotification.equals(aNotification.name())) {
+ Object result = notifyDelegate("displayGroupShouldRefetch",
+ new Class[] { EODisplayGroup.class, NSNotification.class }, new Object[] { this, aNotification });
+ if ((result == null) || (Boolean.TRUE.equals(result))) {
+ fetch();
+ }
+ } else if (EOEditingContext.ObjectsChangedInEditingContextNotification.equals(aNotification.name())) {
+ Object result = notifyDelegate("displayGroupShouldRedisplay",
+ new Class[] { EODisplayGroup.class, NSNotification.class }, new Object[] { this, aNotification });
+ if ((result == null) || (Boolean.TRUE.equals(result))) {
+ int index;
+ Enumeration e;
+ boolean didChange = false;
+ NSDictionary userInfo = aNotification.userInfo();
+
+ // inserts are ignored
+
+ // mark updated objects as updated
+ NSArray updates = (NSArray) userInfo.objectForKey(EOObjectStore.UpdatedKey);
+ e = updates.objectEnumerator();
+ while (e.hasMoreElements()) {
+ index = indexOf(displayedObjects, e.nextElement());
+ if (index != NSArray.NotFound) {
+ // System.out.println( "EODisplayGroup: updated: " + index );
+ if (!didChange) {
+ didChange = true;
+ contentsChanged = true;
+ willChange();
+ updatedObjectIndex = index;
+ } else {
+ updatedObjectIndex = -1;
+ }
+ }
+ }
+
+ // treat invalidated objects as updated
+ NSArray invalidates = (NSArray) userInfo.objectForKey(EOObjectStore.InvalidatedKey);
+ e = invalidates.objectEnumerator();
+ while (e.hasMoreElements()) {
+ index = indexOf(displayedObjects, e.nextElement());
+ if (index != NSArray.NotFound) {
+ // System.out.println( "EODisplayGroup: invalidated: " + index );
+ if (!didChange) {
+ didChange = true;
+ contentsChanged = true;
+ willChange();
+ updatedObjectIndex = index;
+ } else {
+ updatedObjectIndex = -1;
+ }
+ }
+ }
+
+ // remove deletes from display group if they exist
+ NSArray deletes = (NSArray) userInfo.objectForKey(EOObjectStore.DeletedKey);
+ e = deletes.objectEnumerator();
+ Object o;
+ while (e.hasMoreElements()) {
+ o = e.nextElement();
+ index = indexOf(displayedObjects, o);
+ if (index != NSArray.NotFound) {
+ // System.out.println( "EODisplayGroup: deleted: " + o );
+ deleteObjectAtIndexNoNotify(index);
+ }
+ }
+
+ if (!usesOptimisticRefresh()) {
+ updateDisplayedObjects();
+ }
+ }
+ }
+
+ }
+
+ // static methods
+
+ /**
+ * Specifies the default behavior for whether changes should be validated
+ * immediately for all display groups.
+ */
+ public static boolean globalDefaultForValidatesChangesImmediately() {
+ return globalDefaultForValidatesChangesImmediately;
+ }
+
+ /**
+ * Specifies the default string matching format for all display groups.
+ */
+ public static String globalDefaultStringMatchFormat() {
+ return globalDefaultStringMatchFormat;
+ }
+
+ /**
+ * Specifies the default string matching operator for all display groups.
+ */
+ public static String globalDefaultStringMatchOperator() {
+ return globalDefaultStringMatchOperator;
+ }
+
+ /**
+ * Sets the default behavior for validating changes for all display groups.
+ */
+ public static void setGlobalDefaultForValidatesChangesImmediately(boolean validatesImmediately) {
+ globalDefaultForValidatesChangesImmediately = validatesImmediately;
+ }
+
+ /**
+ * Sets the default string matching format that will be used by all display
+ * groups.
+ */
+ public static void setGlobalDefaultStringMatchFormat(String aFormat) {
+ globalDefaultStringMatchFormat = aFormat;
+ }
+
+ /**
+ * Sets the default string matching operator that will be used by all display
+ * groups.
+ */
+ public static void setGlobalDefaultStringMatchOperator(String anOperator) {
+ globalDefaultStringMatchOperator = anOperator;
+ }
+
+ /**
+ * Needed because we don't inherit from NSObject. Calls
+ * EOObserverCenter.notifyObserversObjectWillChange.
+ */
+ protected void willChange() {
+ EOObserverCenter.notifyObserversObjectWillChange(this);
+ }
+
+ /**
+ * Called by LastGroupObserver to clear flags.
+ */
+ protected void processRecentChanges() {
+ contentsChanged = false;
+ selectionChanged = false;
+ }
+
+ /**
+ * Returns the index of the specified object in the specified NSArray, comparing
+ * by value or by reference as determined by the private instance variable
+ * compareByReference. If not found, returns NSArray.NotFound.
+ */
+ private int indexOf(NSArray anArray, Object anObject) {
+ if (compareByReference) {
+ return anArray.indexOfIdenticalObject(anObject);
+ } else {
+ return anArray.indexOf(anObject);
+ }
+ }
+
+ // interface EOObserving
+
+ /**
+ * Receives notifications of changes from objects that are managed by this
+ * display group. This implementation sets updatedObjectIndex and
+ * contentsChanged as appropriate.
+ */
+ public void objectWillChange(Object anObject) {
+ int index = indexOf(displayedObjects, anObject);
+ if (index != NSArray.NotFound) {
+ updatedObjectIndex = index;
+ contentsChanged = true;
+ willChange();
+ }
+ }
+
+ // interface EOEditingContext.Editor
+
+ /**
+ * Called before the editing context begins to save changes. This implementation
+ * calls endEditing().
+ */
+ public void editingContextWillSaveChanges(EOEditingContext anEditingContext) {
+ endEditing();
+ }
+
+ /**
+ * Called to determine whether this editor has changes that have not been
+ * committed to the object in the context.
+ */
+ public boolean editorHasChangesForEditingContext(EOEditingContext anEditingContext) {
+ return (editingAssociation() != null);
+ }
+
+ // interface EOEditingContext.MessageHandler
+
+ /**
+ * Called to display a message for an error that occurred in the specified
+ * editing context. If the delegate allows, this implementation presents an
+ * informational JOptionPane. Override to customize.
+ */
+ public void editingContextPresentErrorMessage(EOEditingContext anEditingContext, String aMessage) {
+ Object result = notifyDelegate("displayGroupShouldDisplayAlert",
+ new Class[] { EODisplayGroup.class, String.class, String.class },
+ new Object[] { this, "Error", aMessage });
+ if ((result == null) || (Boolean.TRUE.equals(result))) {
+ JOptionPane.showMessageDialog(null, aMessage);
+ }
+ }
+
+ /**
+ * Called by the specified object store to determine whether fetching should
+ * continue, where count is the current count and limit is the limit as
+ * specified by the fetch specification. This implementation presents an
+ * JOptionPane allowing the user to specify whether to continue. Override to
+ * customize.
+ */
+ public boolean editingContextShouldContinueFetching(EOEditingContext anEditingContext, int count, int limit,
+ EOObjectStore anObjectStore) {
+ return (JOptionPane.showConfirmDialog(null, "Fetch limit reached: do you wish to continue?", "Continue?",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION);
+ }
+
+ /**
+ * Sends the specified message to the delegate. Returns the return value of the
+ * method, or null if no return value or no delegate or no implementation.
+ */
+ private Object notifyDelegate(String aMethodName, Class[] types, Object[] params) {
+ try {
+ Object delegate = delegate();
+ if (delegate == null)
+ return null;
+ return NSSelector.invoke(aMethodName, types, delegate, params);
+ } catch (NoSuchMethodException e) {
+ // ignore: not implemented
+ } catch (Exception exc) {
+ // log to standard error
+ System.err.println("Error while messaging delegate: " + delegate + " : " + aMethodName);
+ exc.printStackTrace();
+ }
+
+ return null;
+ }
+
+ /**
+ * DisplayGroups can delegate important decisions to a Delegate. Note that
+ * DisplayGroup doesn't require its delegates to implement this interface:
+ * rather, this interface defines the methods that DisplayGroup will attempt to
+ * invoke dynamically on its delegate. The delegate may choose to implement only
+ * a subset of the methods on the interface.
+ */
+ public interface Delegate {
+ /**
+ * Called when the specified data source fails to create an object for the
+ * specified display group.
+ */
+ void displayGroupCreateObjectFailed(EODisplayGroup aDisplayGroup, EODataSource aDataSource);
+
+ /**
+ * Called after the specified display group's data source is changed.
+ */
+ void displayGroupDidChangeDataSource(EODisplayGroup aDisplayGroup);
+
+ /**
+ * Called after a change occurs in the specified display group's selected
+ * objects.
+ */
+ void displayGroupDidChangeSelectedObjects(EODisplayGroup aDisplayGroup);
+
+ /**
+ * Called after the specified display group's selection has changed.
+ */
+ void displayGroupDidChangeSelection(EODisplayGroup aDisplayGroup);
+
+ /**
+ * Called after the specified display group has deleted the specified object.
+ */
+ void displayGroupDidDeleteObject(EODisplayGroup aDisplayGroup, Object anObject);
+
+ /**
+ * Called after the specified display group has fetched the specified object
+ * list.
+ */
+ void displayGroupDidFetchObjects(EODisplayGroup aDisplayGroup, List anObjectList);
+
+ /**
+ * Called after the specified display group has inserted the specified object
+ * into its internal object list.
+ */
+ void displayGroupDidInsertObject(EODisplayGroup aDisplayGroup, Object anObject);
+
+ /**
+ * Called after the specified display group has set the specified value for the
+ * specified object and key.
+ */
+ void displayGroupDidSetValueForObject(EODisplayGroup aDisplayGroup, Object aValue, Object anObject,
+ String aKey);
+
+ /**
+ * Called by the specified display group to determine what objects should be
+ * displayed for the objects in the specified list.
+ *
+ * @return An NSArray containing the objects to be displayed for the objects in
+ * the specified list.
+ */
+ NSArray displayGroupDisplayArrayForObjects(EODisplayGroup aDisplayGroup, List aList);
+
+ /**
+ * Called by the specified display group before it attempts to change the
+ * selection.
+ *
+ * @return True to allow the selection to change, false otherwise.
+ */
+ boolean displayGroupShouldChangeSelection(EODisplayGroup aDisplayGroup, List aSelectionList);
+
+ /**
+ * Called by the specified display group before it attempts to delete the
+ * specified object.
+ *
+ * @return True to allow the object to be deleted false to prevent the deletion.
+ */
+ boolean displayGroupShouldDeleteObject(EODisplayGroup aDisplayGroup, Object anObject);
+
+ /**
+ * Called by the specified display group before it attempts display the
+ * specified alert to the user.
+ *
+ * @return True to allow the message to be displayed, false if you want to
+ * handle the alert yourself and suppress the display group's
+ * notification.
+ */
+ boolean displayGroupShouldDisplayAlert(EODisplayGroup aDisplayGroup, String aTitle, String aMessage);
+
+ /**
+ * Called by the specified display group before it attempts fetch objects.
+ *
+ * @return True to allow the fetch to take place, false to prevent the fetch.
+ */
+ boolean displayGroupShouldFetch(EODisplayGroup aDisplayGroup);
+
+ /**
+ * Called by the specified display group before it attempts to insert the
+ * specified object.
+ *
+ * @return True to allow the object to be inserted false to prevent the
+ * insertion.
+ */
+ boolean displayGroupShouldInsertObject(EODisplayGroup aDisplayGroup, Object anObject, int anIndex);
+
+ /**
+ * Called by the specified display group when it receives the specified
+ * ObjectsChangedInEditingContextNotification.
+ *
+ * @return True to allow the display group to update the display (recommended),
+ * false to prevent the update.
+ */
+ boolean displayGroupShouldRedisplay(EODisplayGroup aDisplayGroup, NSNotification aNotification);
+
+ /**
+ * Called by the specified display group when it receives the specified
+ * InvalidatedAllObjectsInStoreNotification.
+ *
+ * @return True to allow the display group to refetch (recommended), false to
+ * prevent the refetch.
+ */
+ boolean displayGroupShouldRefetch(EODisplayGroup aDisplayGroup, NSNotification aNotification);
+
+ }
}
- /**
- * A private class that will serve to clear the contentsChanged
- * and selectionChanged flags after all Associations have been
- * notified.
- */
- class LastGroupObserver extends EODelayedObserver
- {
- Reference ref;
-
- public LastGroupObserver( EODisplayGroup aDisplayGroup )
- {
- ref = new WeakReference( aDisplayGroup );
- }
-
- /**
- * We want to be informed last, after all Associations
- * have been notified to changes in the DisplayGroup.
- */
- public int priority()
- {
- return ObserverPrioritySixth;
- }
-
- /**
- * After all Associations have been notified,
- * clear the contentsChanged and selectionChanged flags.
- */
- public void subjectChanged ()
- {
- EODisplayGroup group = (EODisplayGroup) ref.get();
- if ( group != null )
- {
- group.processRecentChanges();
- }
- }
- }
+/**
+ * A private class that will serve to clear the contentsChanged and
+ * selectionChanged flags after all Associations have been notified.
+ */
+class LastGroupObserver extends EODelayedObserver {
+ Reference ref;
+
+ public LastGroupObserver(EODisplayGroup aDisplayGroup) {
+ ref = new WeakReference(aDisplayGroup);
+ }
+
+ /**
+ * We want to be informed last, after all Associations have been notified to
+ * changes in the DisplayGroup.
+ */
+ public int priority() {
+ return ObserverPrioritySixth;
+ }
+
+ /**
+ * After all Associations have been notified, clear the contentsChanged and
+ * selectionChanged flags.
+ */
+ public void subjectChanged() {
+ EODisplayGroup group = (EODisplayGroup) ref.get();
+ if (group != null) {
+ group.processRecentChanges();
+ }
+ }
+}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.51 2004/01/28 18:35:40 mpowers
- * Slight optimization: only comparing list in fetch if we have to.
+ * Revision 1.51 2004/01/28 18:35:40 mpowers Slight optimization: only comparing
+ * list in fetch if we have to.
*
- * Revision 1.50 2004/01/27 20:42:30 mpowers
- * No longer reselecting first after fetch if contents are identical.
+ * Revision 1.50 2004/01/27 20:42:30 mpowers No longer reselecting first after
+ * fetch if contents are identical.
*
- * Revision 1.49 2003/12/18 11:37:45 mpowers
- * Now calling qualifier internally.
+ * Revision 1.49 2003/12/18 11:37:45 mpowers Now calling qualifier internally.
*
- * Revision 1.48 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.48 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.47 2003/01/18 23:30:42 mpowers
- * WODisplayGroup now compiles.
+ * Revision 1.47 2003/01/18 23:30:42 mpowers WODisplayGroup now compiles.
*
- * Revision 1.46 2002/10/24 21:15:36 mpowers
- * New implementations of NSArray and subclasses.
+ * Revision 1.46 2002/10/24 21:15:36 mpowers New implementations of NSArray and
+ * subclasses.
*
- * Revision 1.45 2002/10/24 18:20:20 mpowers
- * Because NSArray is read-only, we are returning our internal representations
- * to callers of allObjects(), displayedObjects(), and selectedObjects().
+ * Revision 1.45 2002/10/24 18:20:20 mpowers Because NSArray is read-only, we
+ * are returning our internal representations to callers of allObjects(),
+ * displayedObjects(), and selectedObjects().
*
- * Revision 1.44 2002/08/06 18:20:25 mpowers
- * Now posting DisplayGroupWillFetch notifications before fetch.
- * Implemented support for usesOptimisticRefresh.
- * No longer supporting inserted/updated/deleted lists: not part of spec.
+ * Revision 1.44 2002/08/06 18:20:25 mpowers Now posting DisplayGroupWillFetch
+ * notifications before fetch. Implemented support for usesOptimisticRefresh. No
+ * longer supporting inserted/updated/deleted lists: not part of spec.
*
- * Revision 1.43 2002/05/17 15:01:49 mpowers
- * Implemented dynamic lookup of delegate methods so delegates no longer
- * need to implement the DisplayGroup.Delegate interface.
+ * Revision 1.43 2002/05/17 15:01:49 mpowers Implemented dynamic lookup of
+ * delegate methods so delegates no longer need to implement the
+ * DisplayGroup.Delegate interface.
*
- * Revision 1.42 2002/03/26 21:46:06 mpowers
- * Contributing EditingContext as a java-friendly convenience.
+ * Revision 1.42 2002/03/26 21:46:06 mpowers Contributing EditingContext as a
+ * java-friendly convenience.
*
- * Revision 1.41 2002/03/11 03:17:56 mpowers
- * Provided control point for coalesced changes.
+ * Revision 1.41 2002/03/11 03:17:56 mpowers Provided control point for
+ * coalesced changes.
*
- * Revision 1.40 2002/03/05 23:18:28 mpowers
- * Added documentation.
- * Added isSelectionPaintedImmediate and isSelectionTracking attributes
- * to TableAssociation.
- * Added getTableAssociation to TableColumnAssociation.
+ * Revision 1.40 2002/03/05 23:18:28 mpowers Added documentation. Added
+ * isSelectionPaintedImmediate and isSelectionTracking attributes to
+ * TableAssociation. Added getTableAssociation to TableColumnAssociation.
*
- * Revision 1.39 2002/02/19 22:26:04 mpowers
- * Implemented EOEditingContext.MessageHandler support.
+ * Revision 1.39 2002/02/19 22:26:04 mpowers Implemented
+ * EOEditingContext.MessageHandler support.
*
- * Revision 1.38 2002/02/19 16:37:38 mpowers
- * Implemented support for EOEditingContext.Editor
+ * Revision 1.38 2002/02/19 16:37:38 mpowers Implemented support for
+ * EOEditingContext.Editor
*
- * Revision 1.37 2001/12/11 22:17:48 mpowers
- * Now properly handling exceptions in valueForObject.
- * No longer trying to retain selection based only on index.
+ * Revision 1.37 2001/12/11 22:17:48 mpowers Now properly handling exceptions in
+ * valueForObject. No longer trying to retain selection based only on index.
*
- * Revision 1.36 2001/11/08 21:42:00 mpowers
- * Now we know what to do with shouldRefetch and shouldRedisplay.
+ * Revision 1.36 2001/11/08 21:42:00 mpowers Now we know what to do with
+ * shouldRefetch and shouldRedisplay.
*
- * Revision 1.35 2001/11/04 18:26:58 mpowers
- * Fixed bug where exceptions were not properly reported when updating
- * a value and the display group did not have a delegate.
+ * Revision 1.35 2001/11/04 18:26:58 mpowers Fixed bug where exceptions were not
+ * properly reported when updating a value and the display group did not have a
+ * delegate.
*
- * Revision 1.34 2001/11/02 20:59:36 mpowers
- * Now correctly ensuring selected objects are a subset of displayed objects.
+ * Revision 1.34 2001/11/02 20:59:36 mpowers Now correctly ensuring selected
+ * objects are a subset of displayed objects.
*
- * Revision 1.33 2001/10/30 22:56:45 mpowers
- * Added support for EOQualifier.
+ * Revision 1.33 2001/10/30 22:56:45 mpowers Added support for EOQualifier.
*
- * Revision 1.32 2001/10/23 22:27:53 mpowers
- * Now running at ObserverPrioritySixth.
+ * Revision 1.32 2001/10/23 22:27:53 mpowers Now running at
+ * ObserverPrioritySixth.
*
- * Revision 1.31 2001/10/23 18:45:05 mpowers
- * Rolling back changes.
+ * Revision 1.31 2001/10/23 18:45:05 mpowers Rolling back changes.
*
- * Revision 1.28 2001/08/22 19:23:41 mpowers
- * No longer asserting objects in all objects list.
+ * Revision 1.28 2001/08/22 19:23:41 mpowers No longer asserting objects in all
+ * objects list.
*
- * Revision 1.27 2001/07/30 16:17:01 mpowers
- * Minor code cleanup.
+ * Revision 1.27 2001/07/30 16:17:01 mpowers Minor code cleanup.
*
- * Revision 1.26 2001/07/10 22:49:07 mpowers
- * Fixed bug in optimization for selectObjectsIdenticalTo (found by Dongzhi).
+ * Revision 1.26 2001/07/10 22:49:07 mpowers Fixed bug in optimization for
+ * selectObjectsIdenticalTo (found by Dongzhi).
*
- * Revision 1.25 2001/06/19 15:40:21 mpowers
- * Now only changing the selection if the new selection is different
- * from the old.
+ * Revision 1.25 2001/06/19 15:40:21 mpowers Now only changing the selection if
+ * the new selection is different from the old.
*
- * Revision 1.24 2001/05/24 17:36:15 mpowers
- * Fixed problem with selectedObjectsIdenticalTo: it was using compare
- * by value instead of compare by reference.
+ * Revision 1.24 2001/05/24 17:36:15 mpowers Fixed problem with
+ * selectedObjectsIdenticalTo: it was using compare by value instead of compare
+ * by reference.
*
- * Revision 1.23 2001/05/18 21:09:19 mpowers
- * Now throwing exceptions if the delegate cannot handle error from update.
+ * Revision 1.23 2001/05/18 21:09:19 mpowers Now throwing exceptions if the
+ * delegate cannot handle error from update.
*
- * Revision 1.22 2001/05/14 15:26:12 mpowers
- * Now checking for null delegate before and after selection change.
+ * Revision 1.22 2001/05/14 15:26:12 mpowers Now checking for null delegate
+ * before and after selection change.
*
- * Revision 1.21 2001/05/08 18:47:34 mpowers
- * Minor fixes for d3.
+ * Revision 1.21 2001/05/08 18:47:34 mpowers Minor fixes for d3.
*
- * Revision 1.20 2001/04/29 22:02:45 mpowers
- * Work on id transposing between editing contexts.
+ * Revision 1.20 2001/04/29 22:02:45 mpowers Work on id transposing between
+ * editing contexts.
*
- * Revision 1.19 2001/04/13 16:38:09 mpowers
- * Alpha3 release.
+ * Revision 1.19 2001/04/13 16:38:09 mpowers Alpha3 release.
*
- * Revision 1.18 2001/04/03 20:36:01 mpowers
- * Fixed refaulting/reverting/invalidating to be self-consistent.
+ * Revision 1.18 2001/04/03 20:36:01 mpowers Fixed
+ * refaulting/reverting/invalidating to be self-consistent.
*
- * Revision 1.17 2001/03/29 03:31:13 mpowers
- * No longer using Introspector.
+ * Revision 1.17 2001/03/29 03:31:13 mpowers No longer using Introspector.
*
- * Revision 1.16 2001/02/27 03:32:18 mpowers
- * Implemented default values for new objects.
+ * Revision 1.16 2001/02/27 03:32:18 mpowers Implemented default values for new
+ * objects.
*
- * Revision 1.15 2001/02/27 02:11:17 mpowers
- * Now throwing exception when cloning fails.
- * Removed debugging printlns.
+ * Revision 1.15 2001/02/27 02:11:17 mpowers Now throwing exception when cloning
+ * fails. Removed debugging printlns.
*
- * Revision 1.14 2001/02/26 22:41:51 mpowers
- * Implemented null placeholder classes.
- * Duplicator now uses NSNull.
- * No longer catching base exception class.
+ * Revision 1.14 2001/02/26 22:41:51 mpowers Implemented null placeholder
+ * classes. Duplicator now uses NSNull. No longer catching base exception class.
*
- * Revision 1.13 2001/02/26 15:53:22 mpowers
- * Fine-tuning notification firing.
+ * Revision 1.13 2001/02/26 15:53:22 mpowers Fine-tuning notification firing.
* Child display groups now update properly after parent save or invalidate.
*
- * Revision 1.12 2001/02/22 20:55:06 mpowers
- * Implemented notification handling.
+ * Revision 1.12 2001/02/22 20:55:06 mpowers Implemented notification handling.
*
- * Revision 1.11 2001/02/21 20:40:42 mpowers
- * setObjectArray now falls back to index when trying to retain the
- * same selection.
+ * Revision 1.11 2001/02/21 20:40:42 mpowers setObjectArray now falls back to
+ * index when trying to retain the same selection.
*
- * Revision 1.10 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.10 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.9 2001/02/17 17:23:49 mpowers
- * More changes to support compiling with jdk1.1 collections.
+ * Revision 1.9 2001/02/17 17:23:49 mpowers More changes to support compiling
+ * with jdk1.1 collections.
*
- * Revision 1.8 2001/02/17 16:52:05 mpowers
- * Changes in imports to support building with jdk1.1 collections.
+ * Revision 1.8 2001/02/17 16:52:05 mpowers Changes in imports to support
+ * building with jdk1.1 collections.
*
- * Revision 1.7 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.7 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.6 2001/01/24 14:23:05 mpowers
- * Added support for OrderedDataSource.
+ * Revision 1.6 2001/01/24 14:23:05 mpowers Added support for OrderedDataSource.
*
- * Revision 1.5 2001/01/12 17:21:37 mpowers
- * Implicit creation of EOSortOrderings now happens in setSortOrderings.
+ * Revision 1.5 2001/01/12 17:21:37 mpowers Implicit creation of EOSortOrderings
+ * now happens in setSortOrderings.
*
- * Revision 1.4 2001/01/11 20:34:26 mpowers
- * Implemented EOSortOrdering and added support in framework.
- * Added header-click to sort table columns.
+ * Revision 1.4 2001/01/11 20:34:26 mpowers Implemented EOSortOrdering and added
+ * support in framework. Added header-click to sort table columns.
*
- * Revision 1.3 2001/01/10 22:49:44 mpowers
- * Implemented similarly named selection methods instead of
- * throwing exceptions.
+ * Revision 1.3 2001/01/10 22:49:44 mpowers Implemented similarly named
+ * selection methods instead of throwing exceptions.
*
- * Revision 1.2 2001/01/09 20:12:52 mpowers
- * Moved inner classes to package access.
+ * Revision 1.2 2001/01/09 20:12:52 mpowers Moved inner classes to package
+ * access.
*
- * Revision 1.1.1.1 2000/12/21 15:48:20 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:48:20 mpowers Contributing wotonomy.
*
- * Revision 1.21 2000/12/20 16:25:39 michael
- * Added log to all files.
+ * Revision 1.21 2000/12/20 16:25:39 michael Added log to all files.
*
- * Revision 1.20 2000/12/15 15:04:42 michael
- * Added doc.
+ * Revision 1.20 2000/12/15 15:04:42 michael Added doc.
*
- * Revision 1.19 2000/12/11 13:32:48 michael
- * Finish the much better TreeAssociation implementation.
- * TreeAssociation now has no gui dependencies.
+ * Revision 1.19 2000/12/11 13:32:48 michael Finish the much better
+ * TreeAssociation implementation. TreeAssociation now has no gui dependencies.
*
- * Revision 1.18 2000/12/05 17:41:46 michael
- * Broadcasts selection change after delegate refuses selection change
- * so the initiating association gets refreshed.
+ * Revision 1.18 2000/12/05 17:41:46 michael Broadcasts selection change after
+ * delegate refuses selection change so the initiating association gets
+ * refreshed.
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/GenericAssociation.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/GenericAssociation.java
index 3a4ff08..3310f19 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/GenericAssociation.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/GenericAssociation.java
@@ -28,346 +28,282 @@ import net.wotonomy.control.EOObserverCenter;
import net.wotonomy.foundation.NSArray;
/**
-* GenericAssociation binds one or more properties on an
-* observable object to a display group. The controlled
-* object is expected to use the ObserverCenter and will
-* be observed by this association. <br><br>
-*
-* Bindings for this association are <i>generic</i>: the
-* name of the aspect will be treated as a property key
-* on the displayed object(s) and synchronized with the
-* bound property on the controlled object. <br><br>
-*
-* NOTE: because we cannot assume that the controlled
-* object will retain a reference to this association,
-* you must explicitly retain a reference to prevent
-* the association from getting garbage collected.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class GenericAssociation extends EOAssociation
-{
- protected boolean objectModified;
- protected Set aspectsModified;
-
- static final NSArray aspects =
- new NSArray( new Object[] {
- } );
- static final NSArray aspectSignatures =
- new NSArray( new Object[] {
- } );
- static final NSArray objectKeysTaken =
- new NSArray( new Object[] {
- } );
-
- /**
- * Constructor specifying the object to be controlled by this
- * association. Does not establish connection.
- */
- public GenericAssociation ( Object anObject )
- {
- super( anObject );
- objectModified = false;
- aspectsModified = new HashSet();
- }
-
- /**
- * 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. <ul>
- * <li>"A" attribute: the aspect can be bound to
- * an attribute.</li>
- * <li>"1" to-one: the aspect can be bound to a
- * property that returns a single object.</li>
- * <li>"M" to-one: the aspect can be bound to a
- * property that returns multiple objects.</li>
- * </ul>
- * An empty signature "" means that the aspect can
- * bind without needing a key.
- * This implementation returns "A1M" for each
- * element in the aspects array.
- */
- public static NSArray aspectSignatures ()
- {
- return aspectSignatures;
- }
-
- /**
- * 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.
- */
- public static NSArray aspects ()
- {
- return aspects;
- }
-
- /**
- * Returns a List of EOAssociation subclasses that,
- * for the objects that are usable for this association,
- * are less suitable than this association.
- */
- public static NSArray associationClassesSuperseded ()
- {
- return new NSArray();
- }
-
- /**
- * Returns whether this class can control the specified
- * object.
- */
- public static boolean isUsableWithObject ( Object anObject )
- {
- return true;
- }
-
- /**
- * Returns a List of properties of the controlled object
- * that are controlled by this class. For example,
- * "stringValue", or "selected".
- */
- public static NSArray objectKeysTaken ()
- {
- return objectKeysTaken;
- }
-
- /**
- * Returns the aspect that is considered primary
- * or default. This is typically "value" or somesuch.
- */
- public static String primaryAspect ()
- {
- return "";
- }
-
- /**
- * Returns whether this association can bind to the
- * specified display group on the specified key for
- * the specified aspect.
- */
- public boolean canBindAspect (
- String anAspect, EODisplayGroup aDisplayGroup, String aKey)
- {
- return true;
- }
-
- /**
- * Establishes a connection between this association
- * and the controlled object. This implementation
- * registers with ObserverCenter for change notifications
- * from the controlled object.
- */
- public void establishConnection ()
- {
- EOObserverCenter.addObserver( this, object() );
- super.establishConnection();
-
+ * GenericAssociation binds one or more properties on an observable object to a
+ * display group. The controlled object is expected to use the ObserverCenter
+ * and will be observed by this association. <br>
+ * <br>
+ *
+ * Bindings for this association are <i>generic</i>: the name of the aspect will
+ * be treated as a property key on the displayed object(s) and synchronized with
+ * the bound property on the controlled object. <br>
+ * <br>
+ *
+ * NOTE: because we cannot assume that the controlled object will retain a
+ * reference to this association, you must explicitly retain a reference to
+ * prevent the association from getting garbage collected.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class GenericAssociation extends EOAssociation {
+ protected boolean objectModified;
+ protected Set aspectsModified;
+
+ static final NSArray aspects = new NSArray(new Object[] {});
+ static final NSArray aspectSignatures = new NSArray(new Object[] {});
+ static final NSArray objectKeysTaken = new NSArray(new Object[] {});
+
+ /**
+ * Constructor specifying the object to be controlled by this association. Does
+ * not establish connection.
+ */
+ public GenericAssociation(Object anObject) {
+ super(anObject);
+ objectModified = false;
+ aspectsModified = new HashSet();
+ }
+
+ /**
+ * 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.
+ * <ul>
+ * <li>"A" attribute: the aspect can be bound to an attribute.</li>
+ * <li>"1" to-one: the aspect can be bound to a property that returns a single
+ * object.</li>
+ * <li>"M" to-one: the aspect can be bound to a property that returns multiple
+ * objects.</li>
+ * </ul>
+ * An empty signature "" means that the aspect can bind without needing a key.
+ * This implementation returns "A1M" for each element in the aspects array.
+ */
+ public static NSArray aspectSignatures() {
+ return aspectSignatures;
+ }
+
+ /**
+ * 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.
+ */
+ public static NSArray aspects() {
+ return aspects;
+ }
+
+ /**
+ * Returns a List of EOAssociation subclasses that, for the objects that are
+ * usable for this association, are less suitable than this association.
+ */
+ public static NSArray associationClassesSuperseded() {
+ return new NSArray();
+ }
+
+ /**
+ * Returns whether this class can control the specified object.
+ */
+ public static boolean isUsableWithObject(Object anObject) {
+ return true;
+ }
+
+ /**
+ * Returns a List of properties of the controlled object that are controlled by
+ * this class. For example, "stringValue", or "selected".
+ */
+ public static NSArray objectKeysTaken() {
+ return objectKeysTaken;
+ }
+
+ /**
+ * Returns the aspect that is considered primary or default. This is typically
+ * "value" or somesuch.
+ */
+ public static String primaryAspect() {
+ return "";
+ }
+
+ /**
+ * Returns whether this association can bind to the specified display group on
+ * the specified key for the specified aspect.
+ */
+ public boolean canBindAspect(String anAspect, EODisplayGroup aDisplayGroup, String aKey) {
+ return true;
+ }
+
+ /**
+ * Establishes a connection between this association and the controlled object.
+ * This implementation registers with ObserverCenter for change notifications
+ * from the controlled object.
+ */
+ public void establishConnection() {
+ EOObserverCenter.addObserver(this, object());
+ super.establishConnection();
+
// forces update from bindings
subjectChanged();
- }
-
- /**
- * Breaks the connection between this association and
- * its object. Override to stop listening for events
- * from the object.
- */
- public void breakConnection ()
- {
- EOObserverCenter.removeObserver( this, object() );
- super.breakConnection();
- }
-
- /**
- * Overridden to track which observed object is changing.
- */
- public void objectWillChange( Object anObject )
- {
- if ( object() == anObject )
- {
- objectModified = true;
- }
- else
- {
- aspectsModified.add( aspectToGroup.allKeysForObject( anObject ) );
- }
- }
-
- /**
- * Called when either the selection or the contents
- * of an associated display group have changed.
- */
- public void subjectChanged ()
- {
- String aspect;
- String key;
- Object value;
- EODisplayGroup displayGroup;
- Iterator iterator;
-
- iterator = aspectsModified.iterator();
- while ( iterator.hasNext() )
- {
- aspect = (String) iterator.next();
- key = displayGroupKeyForAspect( aspect );
- displayGroup = displayGroupForAspect( aspect );
-
- value = readValueFromDisplayGroupForKey( displayGroup, key );
- writeValueForKey( object(), value, key );
- }
- aspectsModified.clear();
-
- if ( objectModified )
- {
- iterator = aspectToGroup.keySet().iterator();
- while ( iterator.hasNext() )
- {
- aspect = (String) iterator.next();
- key = displayGroupKeyForAspect( aspect );
- value = readValueForKey( object(), key );
- displayGroup = displayGroupForAspect( aspect );
- displayGroup.setSelectedObjectValue( value, key );
- }
- }
- }
-
- protected Object readValueForKey( Object object, String key )
- {
- if ( object instanceof EOKeyValueCoding )
- {
- return ((EOKeyValueCoding)object).valueForKey( key );
- }
- return EOKeyValueCodingSupport.valueForKey( object, key );
- }
-
- protected void writeValueForKey( Object object, Object value, String key )
- {
- if ( object instanceof EOKeyValueCoding )
- {
- ((EOKeyValueCoding)object).takeValueForKey( value, key );
- }
- else
- {
- EOKeyValueCodingSupport.takeValueForKey( object, value, key );
- }
- }
-
- protected Object readValueFromDisplayGroupForKey(
- EODisplayGroup displayGroup, String key )
- {
- Object value;
-
- if ( displayGroup.selectedObjects().size() > 1 )
- {
- // if there're more than one object selected, set
- // the value to blank for all of them.
- Object previousValue;
-
- Iterator indexIterator = displayGroup.selectionIndexes().
- iterator();
-
- // get value for the first selected object.
- int initialIndex = ( (Integer)indexIterator.next() ).intValue();
- previousValue = displayGroup.valueForObjectAtIndex(
- initialIndex, key );
- value = null;
-
- // go through the rest of the selected objects, compare each
- // value with the previous one. continue comparing if two
- // values are equal, break the while loop if they're different.
- // the final value will be the common value of all selected objects
- // if there is one, or be blank if there is not.
- while ( indexIterator.hasNext() )
- {
- int index = ( (Integer)indexIterator.next() ).intValue();
- Object currentValue = displayGroup.valueForObjectAtIndex(
- index, key );
- if ( currentValue != null && !currentValue.equals( previousValue ) )
- {
- value = null;
- break;
- }
- else
- {
- // currentValue is the same as the previous one
- value = currentValue;
- }
-
- } // end while
-
- } else {
-
- value = displayGroup.selectedObjectValueForKey( key );
- } // end checking size of displayGroup
-
- return value;
- }
-
+ }
+
/**
- * Writes the value currently in the component
- * to the selected object in the display group
- * bound to the value aspect.
- * @return false if there were problems validating,
- * or true to continue.
- */
- protected boolean writeValueForAspect( Object value, String aspect )
- {
- EODisplayGroup displayGroup =
- displayGroupForAspect( aspect );
- if ( displayGroup != null )
- {
- String key = displayGroupKeyForAspect( aspect );
-
- boolean returnValue = true;
- Iterator selectedIterator = displayGroup.selectionIndexes().iterator();
- while ( selectedIterator.hasNext() )
- {
- int index = ( (Integer)selectedIterator.next() ).intValue();
-
- if ( !displayGroup.setValueForObjectAtIndex( value, index, key ) )
- {
- returnValue = false;
- }
- }
- return returnValue;
+ * Breaks the connection between this association and its object. Override to
+ * stop listening for events from the object.
+ */
+ public void breakConnection() {
+ EOObserverCenter.removeObserver(this, object());
+ super.breakConnection();
+ }
+
+ /**
+ * Overridden to track which observed object is changing.
+ */
+ public void objectWillChange(Object anObject) {
+ if (object() == anObject) {
+ objectModified = true;
+ } else {
+ aspectsModified.add(aspectToGroup.allKeysForObject(anObject));
+ }
+ }
+
+ /**
+ * Called when either the selection or the contents of an associated display
+ * group have changed.
+ */
+ public void subjectChanged() {
+ String aspect;
+ String key;
+ Object value;
+ EODisplayGroup displayGroup;
+ Iterator iterator;
+
+ iterator = aspectsModified.iterator();
+ while (iterator.hasNext()) {
+ aspect = (String) iterator.next();
+ key = displayGroupKeyForAspect(aspect);
+ displayGroup = displayGroupForAspect(aspect);
+
+ value = readValueFromDisplayGroupForKey(displayGroup, key);
+ writeValueForKey(object(), value, key);
+ }
+ aspectsModified.clear();
+
+ if (objectModified) {
+ iterator = aspectToGroup.keySet().iterator();
+ while (iterator.hasNext()) {
+ aspect = (String) iterator.next();
+ key = displayGroupKeyForAspect(aspect);
+ value = readValueForKey(object(), key);
+ displayGroup = displayGroupForAspect(aspect);
+ displayGroup.setSelectedObjectValue(value, key);
+ }
+ }
+ }
+
+ protected Object readValueForKey(Object object, String key) {
+ if (object instanceof EOKeyValueCoding) {
+ return ((EOKeyValueCoding) object).valueForKey(key);
+ }
+ return EOKeyValueCodingSupport.valueForKey(object, key);
+ }
+
+ protected void writeValueForKey(Object object, Object value, String key) {
+ if (object instanceof EOKeyValueCoding) {
+ ((EOKeyValueCoding) object).takeValueForKey(value, key);
+ } else {
+ EOKeyValueCodingSupport.takeValueForKey(object, value, key);
+ }
+ }
+
+ protected Object readValueFromDisplayGroupForKey(EODisplayGroup displayGroup, String key) {
+ Object value;
+
+ if (displayGroup.selectedObjects().size() > 1) {
+ // if there're more than one object selected, set
+ // the value to blank for all of them.
+ Object previousValue;
+
+ Iterator indexIterator = displayGroup.selectionIndexes().iterator();
+
+ // get value for the first selected object.
+ int initialIndex = ((Integer) indexIterator.next()).intValue();
+ previousValue = displayGroup.valueForObjectAtIndex(initialIndex, key);
+ value = null;
+
+ // go through the rest of the selected objects, compare each
+ // value with the previous one. continue comparing if two
+ // values are equal, break the while loop if they're different.
+ // the final value will be the common value of all selected objects
+ // if there is one, or be blank if there is not.
+ while (indexIterator.hasNext()) {
+ int index = ((Integer) indexIterator.next()).intValue();
+ Object currentValue = displayGroup.valueForObjectAtIndex(index, key);
+ if (currentValue != null && !currentValue.equals(previousValue)) {
+ value = null;
+ break;
+ } else {
+ // currentValue is the same as the previous one
+ value = currentValue;
+ }
+
+ } // end while
+
+ } else {
+
+ value = displayGroup.selectedObjectValueForKey(key);
+ } // end checking size of displayGroup
+
+ return value;
+ }
+
+ /**
+ * Writes the value currently in the component to the selected object in the
+ * display group bound to the value aspect.
+ *
+ * @return false if there were problems validating, or true to continue.
+ */
+ protected boolean writeValueForAspect(Object value, String aspect) {
+ EODisplayGroup displayGroup = displayGroupForAspect(aspect);
+ if (displayGroup != null) {
+ String key = displayGroupKeyForAspect(aspect);
+
+ boolean returnValue = true;
+ Iterator selectedIterator = displayGroup.selectionIndexes().iterator();
+ while (selectedIterator.hasNext()) {
+ int index = ((Integer) selectedIterator.next()).intValue();
+
+ if (!displayGroup.setValueForObjectAtIndex(value, index, key)) {
+ returnValue = false;
+ }
+ }
+ return returnValue;
}
return false;
}
- /**
- * Forces this association to cause the object to
- * stop editing and validate the user's input.
- * @return false if there were problems validating,
- * or true to continue.
- */
- public boolean endEditing ()
- {
- return false;
+ /**
+ * Forces this association to cause the object to stop editing and validate the
+ * user's input.
+ *
+ * @return false if there were problems validating, or true to continue.
+ */
+ public boolean endEditing() {
+ return false;
//! return writeValueToDisplayGroup();
- }
-
+ }
+
}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.3 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.3 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.2 2001/11/08 19:51:24 mpowers
- * Draft implementation.
+ * Revision 1.2 2001/11/08 19:51:24 mpowers Draft implementation.
*
- * Revision 1.1 2001/11/02 23:15:04 mpowers
- * Contributing "generic association".
+ * Revision 1.1 2001/11/02 23:15:04 mpowers Contributing "generic association".
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java
index 2aea8d3..54cd04e 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java
@@ -27,380 +27,303 @@ import net.wotonomy.foundation.NSArray;
import net.wotonomy.foundation.NSMutableArray;
/**
-* MasterDetailAssociation binds a display group to a property
-* on the selected object of another display group.
-* Bindings are:
-* <ul>
-* <li>parent: The property on the selected object of the
-* bound display group that is expected to be an indexed property.</li>
-* </ul>
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 904 $
-*/
-public class MasterDetailAssociation extends EOAssociation
-{
- static final NSArray aspects =
- new NSArray( new Object[] {
- ParentAspect
- } );
- static final NSArray aspectSignatures =
- new NSArray( new Object[] {
- AttributeToOneAspectSignature
- } );
- static final NSArray objectKeysTaken =
- new NSArray( new Object[] {
- "allObjects"
- } );
-
- /**
- * Used to be notified of changes to objects in the
- * controlled display group. requalify() should place
- * all objects fetched into the controlled group into
- * this array.
- * Otherwise, the parent object is only marked as
- * changed for inserts and deletes.
- */
- protected NSMutableArray observableArray;
-
- /**
- * Constructor expecting an EODisplayGroup.
- * If the controlled display group does not have a data source,
- * a new PropertyDataSource will be used.
- */
- public MasterDetailAssociation ( Object anObject )
- {
- super( anObject );
- observableArray = new ObservableArray( this );
- }
-
- /**
- * 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. <ul>
- * <li>"A" attribute: the aspect can be bound to
- * an attribute.</li>
- * <li>"1" to-one: the aspect can be bound to a
- * property that returns a single object.</li>
- * <li>"M" to-one: the aspect can be bound to a
- * property that returns multiple objects.</li>
- * </ul>
- * An empty signature "" means that the aspect can
- * bind without needing a key.
- * This implementation returns "A1M" for each
- * element in the aspects array.
- */
- public static NSArray aspectSignatures ()
- {
- return aspectSignatures;
- }
-
- /**
- * 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.
- */
- public static NSArray aspects ()
- {
- return aspects;
- }
-
- /**
- * Returns a List of EOAssociation subclasses that,
- * for the objects that are usable for this association,
- * are less suitable than this association.
- */
- public static NSArray associationClassesSuperseded ()
- {
- return new NSArray();
- }
-
- /**
- * Returns whether this class can control the specified
- * object.
- */
- public static boolean isUsableWithObject ( Object anObject )
- {
- return ( anObject instanceof EODisplayGroup );
- }
-
- /**
- * Returns a List of properties of the controlled object
- * that are controlled by this class. For example,
- * "stringValue", or "selected".
- */
- public static NSArray objectKeysTaken ()
- {
- return objectKeysTaken;
- }
-
- /**
- * Returns the aspect that is considered primary
- * or default. This is typically "value" or somesuch.
- */
- public static String primaryAspect ()
- {
- return ParentAspect;
- }
-
- /**
- * Returns whether this association can bind to the
- * specified display group on the specified key for
- * the specified aspect.
- */
- public boolean canBindAspect (
- String anAspect, EODisplayGroup aDisplayGroup, String aKey)
- {
- return ( aspects.containsObject( anAspect ) );
- }
-
- /**
- * Establishes a connection between this association
- * and the controlled object. Subclasses should begin
- * listening for events from their controlled object here.
- */
- public void establishConnection ()
- {
- //NOTE: if nothing refers to this assocation, it gets gc'd.
- // otherwise, this is not needed.
- component().addObserver( this );
-
- EODisplayGroup displayGroup =
- displayGroupForAspect( ParentAspect );
- String key =
- displayGroupKeyForAspect( ParentAspect );
-
- // obtain and qualify new data source from existing source if necessary
- if ( component().dataSource() == null )
- {
- if ( ( displayGroup != null ) && ( displayGroup.dataSource() != null ) )
- {
- component().setDataSource(
- displayGroup.dataSource().
- dataSourceQualifiedByKey( key ) );
- }
- }
-
- // set up proxy data source if necessary
- if ( component().dataSource() == null )
- {
- // get context and class desc from master group
- EOEditingContext editingContext = null;
- EOClassDescription classDesc = null;
- if ( displayGroup != null )
- {
- EODataSource dataSource = displayGroup.dataSource();
- if ( dataSource != null )
- {
- editingContext = dataSource.editingContext();
- EOClassDescription parentDesc = dataSource.classDescriptionForObjects();
- if ( parentDesc != null )
- {
- classDesc = parentDesc.classDescriptionForDestinationKey( key );
- }
- }
- }
-
- //FIXME: should this be called DetailDataSource?
- component().setDataSource(
- new PropertyDataSource( editingContext, classDesc ) );
- }
-
- super.establishConnection();
+ * MasterDetailAssociation binds a display group to a property on the selected
+ * object of another display group. Bindings are:
+ * <ul>
+ * <li>parent: The property on the selected object of the bound display group
+ * that is expected to be an indexed property.</li>
+ * </ul>
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 904 $
+ */
+public class MasterDetailAssociation extends EOAssociation {
+ static final NSArray aspects = new NSArray(new Object[] { ParentAspect });
+ static final NSArray aspectSignatures = new NSArray(new Object[] { AttributeToOneAspectSignature });
+ static final NSArray objectKeysTaken = new NSArray(new Object[] { "allObjects" });
+
+ /**
+ * Used to be notified of changes to objects in the controlled display group.
+ * requalify() should place all objects fetched into the controlled group into
+ * this array. Otherwise, the parent object is only marked as changed for
+ * inserts and deletes.
+ */
+ protected NSMutableArray observableArray;
+
+ /**
+ * Constructor expecting an EODisplayGroup. If the controlled display group does
+ * not have a data source, a new PropertyDataSource will be used.
+ */
+ public MasterDetailAssociation(Object anObject) {
+ super(anObject);
+ observableArray = new ObservableArray(this);
+ }
+
+ /**
+ * 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.
+ * <ul>
+ * <li>"A" attribute: the aspect can be bound to an attribute.</li>
+ * <li>"1" to-one: the aspect can be bound to a property that returns a single
+ * object.</li>
+ * <li>"M" to-one: the aspect can be bound to a property that returns multiple
+ * objects.</li>
+ * </ul>
+ * An empty signature "" means that the aspect can bind without needing a key.
+ * This implementation returns "A1M" for each element in the aspects array.
+ */
+ public static NSArray aspectSignatures() {
+ return aspectSignatures;
+ }
+
+ /**
+ * 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.
+ */
+ public static NSArray aspects() {
+ return aspects;
+ }
+
+ /**
+ * Returns a List of EOAssociation subclasses that, for the objects that are
+ * usable for this association, are less suitable than this association.
+ */
+ public static NSArray associationClassesSuperseded() {
+ return new NSArray();
+ }
+
+ /**
+ * Returns whether this class can control the specified object.
+ */
+ public static boolean isUsableWithObject(Object anObject) {
+ return (anObject instanceof EODisplayGroup);
+ }
+
+ /**
+ * Returns a List of properties of the controlled object that are controlled by
+ * this class. For example, "stringValue", or "selected".
+ */
+ public static NSArray objectKeysTaken() {
+ return objectKeysTaken;
+ }
+
+ /**
+ * Returns the aspect that is considered primary or default. This is typically
+ * "value" or somesuch.
+ */
+ public static String primaryAspect() {
+ return ParentAspect;
+ }
+
+ /**
+ * Returns whether this association can bind to the specified display group on
+ * the specified key for the specified aspect.
+ */
+ public boolean canBindAspect(String anAspect, EODisplayGroup aDisplayGroup, String aKey) {
+ return (aspects.containsObject(anAspect));
+ }
+
+ /**
+ * Establishes a connection between this association and the controlled object.
+ * Subclasses should begin listening for events from their controlled object
+ * here.
+ */
+ public void establishConnection() {
+ // NOTE: if nothing refers to this assocation, it gets gc'd.
+ // otherwise, this is not needed.
+ component().addObserver(this);
+
+ EODisplayGroup displayGroup = displayGroupForAspect(ParentAspect);
+ String key = displayGroupKeyForAspect(ParentAspect);
+
+ // obtain and qualify new data source from existing source if necessary
+ if (component().dataSource() == null) {
+ if ((displayGroup != null) && (displayGroup.dataSource() != null)) {
+ component().setDataSource(displayGroup.dataSource().dataSourceQualifiedByKey(key));
+ }
+ }
+
+ // set up proxy data source if necessary
+ if (component().dataSource() == null) {
+ // get context and class desc from master group
+ EOEditingContext editingContext = null;
+ EOClassDescription classDesc = null;
+ if (displayGroup != null) {
+ EODataSource dataSource = displayGroup.dataSource();
+ if (dataSource != null) {
+ editingContext = dataSource.editingContext();
+ EOClassDescription parentDesc = dataSource.classDescriptionForObjects();
+ if (parentDesc != null) {
+ classDesc = parentDesc.classDescriptionForDestinationKey(key);
+ }
+ }
+ }
+
+ // FIXME: should this be called DetailDataSource?
+ component().setDataSource(new PropertyDataSource(editingContext, classDesc));
+ }
+
+ super.establishConnection();
requalify();
- }
-
- /**
- * Breaks the connection between this association and
- * its object. Override to stop listening for events
- * from the object.
- */
- public void breakConnection ()
- {
- //NOTE: if nothing refers to this assocation, it gets gc'd.
- // otherwise, this is not needed.
- component().deleteObserver( this );
-
- super.breakConnection();
- }
-
- /**
- * Called when either the selection or the contents
- * of an associated display group have changed.
- */
- public void subjectChanged ()
- {
+ }
+
+ /**
+ * Breaks the connection between this association and its object. Override to
+ * stop listening for events from the object.
+ */
+ public void breakConnection() {
+ // NOTE: if nothing refers to this assocation, it gets gc'd.
+ // otherwise, this is not needed.
+ component().deleteObserver(this);
+
+ super.breakConnection();
+ }
+
+ /**
+ * Called when either the selection or the contents of an associated display
+ * group have changed.
+ */
+ public void subjectChanged() {
EODisplayGroup displayGroup;
// parent aspect
- displayGroup = displayGroupForAspect( ParentAspect );
- if ( displayGroup != null )
- {
- if ( displayGroup.selectionChanged() )
- {
- requalify();
+ displayGroup = displayGroupForAspect(ParentAspect);
+ if (displayGroup != null) {
+ if (displayGroup.selectionChanged()) {
+ requalify();
+ } else if (displayGroup.contentsChanged()) {
+ requalify();
}
- else
- if ( displayGroup.contentsChanged() )
- {
- requalify();
+ }
+ }
+
+ /**
+ * Overridden to intercept notifications of changes to objects in the controlled
+ * display group and broadcast a change on the parent group's selected object.
+ * All other notifications are passed to the super implementation.
+ */
+ public void objectWillChange(Object anObject) {
+ // if child display group is notifying
+ if (!(anObject instanceof EODisplayGroup)) {
+ // mark parent group's object as changed
+ EODisplayGroup displayGroup = displayGroupForAspect(ParentAspect);
+ if (displayGroup != null) {
+ Object selected = displayGroup.selectedObject();
+ if (selected != null) {
+ // only notify if childrenKey is an attribute of parentDesc
+ // (and therefore not a toOne or toMany relationship)
+ EOClassDescription parentDesc = EOClassDescription.classDescriptionForClass(selected.getClass());
+ String key = displayGroupKeyForAspect(ParentAspect);
+ if (key != null) {
+ int idx = key.indexOf('.');
+ if (idx != -1)
+ key = key.substring(0, idx);
+ if (parentDesc.attributeKeys().contains(key)) {
+ // only notify if we are an attribute key
+ EOObserverCenter.notifyObserversObjectWillChange(selected);
+ }
+ }
+ }
}
+ } else // display group is notifying
+ {
+ // call super so subjectChanged will be called
+ super.objectWillChange(anObject);
}
- }
-
- /**
- * Overridden to intercept notifications of changes to objects
- * in the controlled display group and broadcast a change on the
- * parent group's selected object. All other notifications are
- * passed to the super implementation.
- */
- public void objectWillChange ( Object anObject )
- {
- // if child display group is notifying
- if ( ! ( anObject instanceof EODisplayGroup ) )
- {
- // mark parent group's object as changed
- EODisplayGroup displayGroup = displayGroupForAspect( ParentAspect );
- if ( displayGroup != null )
- {
- Object selected = displayGroup.selectedObject();
- if ( selected != null )
- {
- // only notify if childrenKey is an attribute of parentDesc
- // (and therefore not a toOne or toMany relationship)
- EOClassDescription parentDesc =
- EOClassDescription.classDescriptionForClass(
- selected.getClass() );
- String key = displayGroupKeyForAspect( ParentAspect );
- if ( key != null )
- {
- int idx = key.indexOf( '.' );
- if ( idx != -1 ) key = key.substring( 0, idx );
- if ( parentDesc.attributeKeys().contains( key ) )
- {
- // only notify if we are an attribute key
- EOObserverCenter.notifyObserversObjectWillChange( selected );
- }
- }
- }
- }
- }
- else // display group is notifying
- {
- // call super so subjectChanged will be called
- super.objectWillChange( anObject );
- }
- }
-
- /**
- * Called by subjectChanged() to requalify the controlled
- * display group with the selected object and the bound key.
- */
- protected void requalify()
- {
+ }
+
+ /**
+ * Called by subjectChanged() to requalify the controlled display group with the
+ * selected object and the bound key.
+ */
+ protected void requalify() {
EODisplayGroup component = component();
- EODisplayGroup displayGroup = displayGroupForAspect( ParentAspect );
- String key = displayGroupKeyForAspect( ParentAspect );
-
- if ( ( displayGroup.selectedObject() != null )
- && ( component.dataSource() != null ) )
- {
- component.dataSource().qualifyWithRelationshipKey(
- key, displayGroup.selectedObject() );
+ EODisplayGroup displayGroup = displayGroupForAspect(ParentAspect);
+ String key = displayGroupKeyForAspect(ParentAspect);
+
+ if ((displayGroup.selectedObject() != null) && (component.dataSource() != null)) {
+ component.dataSource().qualifyWithRelationshipKey(key, displayGroup.selectedObject());
component.fetch();
- observableArray.setArray( component.allObjects() );
- }
- else // no selection or no data source, clear
+ observableArray.setArray(component.allObjects());
+ } else // no selection or no data source, clear
{
- component.setObjectArray( null );
- observableArray.removeAllObjects();
+ component.setObjectArray(null);
+ observableArray.removeAllObjects();
}
- component.updateDisplayedObjects();
+ component.updateDisplayedObjects();
+ }
+
+ /**
+ * This implementation returns ObserverPrioritySecond so that master detail
+ * assocations are notified before other associations.
+ */
+ public int priority() {
+ return ObserverPrioritySecond;
}
-
- /**
- * This implementation returns ObserverPrioritySecond
- * so that master detail assocations are notified before
- * other associations.
- */
- public int priority ()
- {
- return ObserverPrioritySecond;
- }
// convenience
- private EODisplayGroup component()
- {
- return (EODisplayGroup) object();
- }
-
+ private EODisplayGroup component() {
+ return (EODisplayGroup) object();
+ }
+
}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.14 2004/02/04 20:00:49 mpowers
- * Improved change notification for dotted key paths.
+ * Revision 1.14 2004/02/04 20:00:49 mpowers Improved change notification for
+ * dotted key paths.
*
- * Revision 1.13 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.13 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.12 2001/10/26 18:39:05 mpowers
- * Now a delayed observer with a higher priority, so that it is processed
- * before other associations.
+ * Revision 1.12 2001/10/26 18:39:05 mpowers Now a delayed observer with a
+ * higher priority, so that it is processed before other associations.
*
- * Revision 1.11 2001/06/26 21:39:33 mpowers
- * Added check for null component data source before requalifying.
+ * Revision 1.11 2001/06/26 21:39:33 mpowers Added check for null component data
+ * source before requalifying.
*
- * Revision 1.10 2001/05/21 14:04:15 mpowers
- * No longer changing a detail group's data source if it's already specified.
+ * Revision 1.10 2001/05/21 14:04:15 mpowers No longer changing a detail group's
+ * data source if it's already specified.
*
- * Revision 1.9 2001/05/18 21:08:46 mpowers
- * Now calling updateDisplayedObjects on detail after master changes.
+ * Revision 1.9 2001/05/18 21:08:46 mpowers Now calling updateDisplayedObjects
+ * on detail after master changes.
*
- * Revision 1.8 2001/05/14 15:26:42 mpowers
- * Modified logic for controlled groups that have no data source already set.
+ * Revision 1.8 2001/05/14 15:26:42 mpowers Modified logic for controlled groups
+ * that have no data source already set.
*
- * Revision 1.7 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.7 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.6 2001/04/29 02:29:31 mpowers
- * Debugging relationship faulting.
+ * Revision 1.6 2001/04/29 02:29:31 mpowers Debugging relationship faulting.
*
- * Revision 1.4 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.4 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.3 2001/01/18 16:57:18 mpowers
- * Fixed problem with losing connection: the association was getting
- * garbage collected because nothing referred to it. All other associations
- * make themselves listeners of their controlled object, and that has been
- * the only thing keeping them from getting gc'd. This will need to be fixed.
+ * Revision 1.3 2001/01/18 16:57:18 mpowers Fixed problem with losing
+ * connection: the association was getting garbage collected because nothing
+ * referred to it. All other associations make themselves listeners of their
+ * controlled object, and that has been the only thing keeping them from getting
+ * gc'd. This will need to be fixed.
*
- * Revision 1.2 2001/01/17 23:06:09 mpowers
- * TreeAssociation now modifies the contents of the children display
- * group rather than adding items to the titles display group.
+ * Revision 1.2 2001/01/17 23:06:09 mpowers TreeAssociation now modifies the
+ * contents of the children display group rather than adding items to the titles
+ * display group.
*
- * Revision 1.1.1.1 2000/12/21 15:48:23 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:48:23 mpowers Contributing wotonomy.
*
- * Revision 1.5 2000/12/20 16:25:40 michael
- * Added log to all files.
+ * Revision 1.5 2000/12/20 16:25:40 michael Added log to all files.
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MirrorDetailAssociation.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MirrorDetailAssociation.java
index aeac376..b81f9e2 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MirrorDetailAssociation.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MirrorDetailAssociation.java
@@ -17,90 +17,76 @@ License along with this library; if not, see http://www.gnu.org
*/
package net.wotonomy.ui;
+
import net.wotonomy.foundation.NSArray;
/**
-* This master detail association synchronizes the contents
-* and selection of the master group into the detail group.
-*/
-public class MirrorDetailAssociation extends MasterDetailAssociation{
+ * This master detail association synchronizes the contents and selection of the
+ * master group into the detail group.
+ */
+public class MirrorDetailAssociation extends MasterDetailAssociation {
- /**
- * Standard constructor specifying the detail display group.
- * @param displayGroup the detail display group of this
- * Master-Detail Association
- */
- public MirrorDetailAssociation(EODisplayGroup displayGroup){
- super(displayGroup);
- }
+ /**
+ * Standard constructor specifying the detail display group.
+ *
+ * @param displayGroup the detail display group of this Master-Detail
+ * Association
+ */
+ public MirrorDetailAssociation(EODisplayGroup displayGroup) {
+ super(displayGroup);
+ }
- /**
- * Called by subjectChanged() to requalify the controlled
- * display group with the indexed object and the bound key.
- * This implementation ignores both and sets the object array
- * of the detail group to the displayed objects of the master
- * and sets the selection to match.
- */
- protected void requalify()
- {
- EODisplayGroup detail = (EODisplayGroup) object();
- EODisplayGroup master =
- displayGroupForAspect( ParentAspect );
+ /**
+ * Called by subjectChanged() to requalify the controlled display group with the
+ * indexed object and the bound key. This implementation ignores both and sets
+ * the object array of the detail group to the displayed objects of the master
+ * and sets the selection to match.
+ */
+ protected void requalify() {
+ EODisplayGroup detail = (EODisplayGroup) object();
+ EODisplayGroup master = displayGroupForAspect(ParentAspect);
- if ( master != null )
- {
- NSArray masterObjects = master.displayedObjects();
- NSArray detailObjects = detail.displayedObjects();
- int size = masterObjects.size();
- boolean different = false;
-
- // see if lists contain the same object instances
- if ( size == detailObjects.size() )
- {
- for ( int i = 0; i < size; i++ )
- {
- if ( masterObjects.objectAtIndex(i)
- != detailObjects.objectAtIndex(i) )
- {
- different = true;
- break;
- }
- }
- }
- else // different sizes
- {
- different = true;
- }
-
- // if different, sync contents and selection with master
- if ( different )
- {
- detail.setObjectArray( masterObjects );
- detail.setSelectionIndexes( master.selectionIndexes() );
- }
- else // if selection changed, sync selection with master
- if ( master.selectionChanged() )
- {
- detail.setSelectionIndexes( master.selectionIndexes() );
- }
- }
- else // no bound display group, clear
- {
- detail.setObjectArray( null );
- }
- }
+ if (master != null) {
+ NSArray masterObjects = master.displayedObjects();
+ NSArray detailObjects = detail.displayedObjects();
+ int size = masterObjects.size();
+ boolean different = false;
+
+ // see if lists contain the same object instances
+ if (size == detailObjects.size()) {
+ for (int i = 0; i < size; i++) {
+ if (masterObjects.objectAtIndex(i) != detailObjects.objectAtIndex(i)) {
+ different = true;
+ break;
+ }
+ }
+ } else // different sizes
+ {
+ different = true;
+ }
+
+ // if different, sync contents and selection with master
+ if (different) {
+ detail.setObjectArray(masterObjects);
+ detail.setSelectionIndexes(master.selectionIndexes());
+ } else // if selection changed, sync selection with master
+ if (master.selectionChanged()) {
+ detail.setSelectionIndexes(master.selectionIndexes());
+ }
+ } else // no bound display group, clear
+ {
+ detail.setObjectArray(null);
+ }
+ }
}
/*
- * $Log$
- * Revision 1.1 2006/02/16 13:22:22 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * $Log$ Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.2 2001/07/05 22:13:28 mpowers
- * Now only updating if master has actually changed.
+ * Revision 1.2 2001/07/05 22:13:28 mpowers Now only updating if master has
+ * actually changed.
*
- * Revision 1.1 2001/05/29 19:57:47 mpowers
- * Added some neglected files.
+ * Revision 1.1 2001/05/29 19:57:47 mpowers Added some neglected files.
*
*
*/
-
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/ObservableArray.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/ObservableArray.java
index a398e97..e18ed3b 100644
--- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/ObservableArray.java
+++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/ObservableArray.java
@@ -28,322 +28,272 @@ import net.wotonomy.foundation.NSMutableArray;
import net.wotonomy.foundation.NSRange;
/**
-* A package class that extends NSMutableArray but makes use
-* of the fact that wotonomy's implementation extends ArrayList
-* to intercept insertions and deletion and register and
-* unregister objects for change notifications as appropriate.
-* Since we can't be sure of ArrayList's implementation, we're
-* forced to override each and every add and remove method,
-* some of which probably call each other. However,
-* EOObserverCenter will only register us once per object.
-*/
-class ObservableArray extends NSMutableArray
-{
- EOObserving observer;
-
- ObservableArray( EOObserving anObserver )
- {
- observer = anObserver;
- }
-
+ * A package class that extends NSMutableArray but makes use of the fact that
+ * wotonomy's implementation extends ArrayList to intercept insertions and
+ * deletion and register and unregister objects for change notifications as
+ * appropriate. Since we can't be sure of ArrayList's implementation, we're
+ * forced to override each and every add and remove method, some of which
+ * probably call each other. However, EOObserverCenter will only register us
+ * once per object.
+ */
+class ObservableArray extends NSMutableArray {
+ EOObserving observer;
+
+ ObservableArray(EOObserving anObserver) {
+ observer = anObserver;
+ }
+
/**
- * Removes the last object from the array.
- */
- public void removeLastObject ()
- {
- remove( count() - 1 );
- }
+ * Removes the last object from the array.
+ */
+ public void removeLastObject() {
+ remove(count() - 1);
+ }
/**
- * Removes the object at the specified index.
- */
- public void removeObjectAtIndex (int index)
- {
- remove( index );
- }
+ * Removes the object at the specified index.
+ */
+ public void removeObjectAtIndex(int index) {
+ remove(index);
+ }
/**
- * Adds all objects in the specified collection.
- */
- public void addObjectsFromArray (Collection aCollection)
- {
- addAll( aCollection );
- }
+ * Adds all objects in the specified collection.
+ */
+ public void addObjectsFromArray(Collection aCollection) {
+ addAll(aCollection);
+ }
/**
- * Removes all objects from the array.
- */
- public void removeAllObjects ()
- {
- clear();
- }
+ * Removes all objects from the array.
+ */
+ public void removeAllObjects() {
+ clear();
+ }
/**
- * Removes all objects equivalent to the specified object
- * within the range of specified indices.
- */
- public void removeObject (Object anObject, NSRange aRange)
- {
- if ( ( anObject == null ) || ( aRange == null ) ) return;
-
- int loc = aRange.location();
- int max = aRange.maxRange();
- for ( int i = loc; i < max; i++ )
- {
- if ( anObject.equals( get( i ) ) )
- {
- remove( i );
- i = i - 1;
- max = max - 1;
- }
- }
- }
+ * Removes all objects equivalent to the specified object within the range of
+ * specified indices.
+ */
+ public void removeObject(Object anObject, NSRange aRange) {
+ if ((anObject == null) || (aRange == null))
+ return;
+
+ int loc = aRange.location();
+ int max = aRange.maxRange();
+ for (int i = loc; i < max; i++) {
+ if (anObject.equals(get(i))) {
+ remove(i);
+ i = i - 1;
+ max = max - 1;
+ }
+ }
+ }
/**
- * Removes all instances of the specified object within the
- * range of specified indices, comparing by reference.
- */
- public void removeIdenticalObject (Object anObject, NSRange aRange)
- {
- if ( ( anObject == null ) || ( aRange == null ) ) return;
-
- int loc = aRange.location();
- int max = aRange.maxRange();
- for ( int i = loc; i < max; i++ )
- {
- if ( anObject == get( i ) )
- {
- remove( i );
- i = i - 1;
- max = max - 1;
- }
- }
- }
+ * Removes all instances of the specified object within the range of specified
+ * indices, comparing by reference.
+ */
+ public void removeIdenticalObject(Object anObject, NSRange aRange) {
+ if ((anObject == null) || (aRange == null))
+ return;
+
+ int loc = aRange.location();
+ int max = aRange.maxRange();
+ for (int i = loc; i < max; i++) {
+ if (anObject == get(i)) {
+ remove(i);
+ i = i - 1;
+ max = max - 1;
+ }
+ }
+ }
/**
- * Removes all objects in the specified collection from the array.
- */
- public void removeObjectsInArray (Collection aCollection)
- {
- removeAll( aCollection );
- }
+ * Removes all objects in the specified collection from the array.
+ */
+ public void removeObjectsInArray(Collection aCollection) {
+ removeAll(aCollection);
+ }
/**
- * Removes all objects in the indices within the specified range
- * from the array.
- */
- public void removeObjectsInRange (NSRange aRange)
- {
- if ( aRange == null ) return;
-
- for ( int i = 0; i < aRange.length(); i++ )
- {
- remove( aRange.location() );
- }
- }
+ * Removes all objects in the indices within the specified range from the array.
+ */
+ public void removeObjectsInRange(NSRange aRange) {
+ if (aRange == null)
+ return;
+
+ for (int i = 0; i < aRange.length(); i++) {
+ remove(aRange.location());
+ }
+ }
/**
- * Replaces objects in the current range with objects from
- * the specified range of the specified array. If currentRange
- * is larger than otherRange, the extra objects are removed.
- * If otherRange is larger than currentRange, the extra objects
- * are added.
- */
- public void replaceObjectsInRange (NSRange currentRange,
- List otherArray, NSRange otherRange)
- {
- if ( ( currentRange == null ) || ( otherArray == null ) ||
- ( otherRange == null ) ) return;
-
+ * Replaces objects in the current range with objects from the specified range
+ * of the specified array. If currentRange is larger than otherRange, the extra
+ * objects are removed. If otherRange is larger than currentRange, the extra
+ * objects are added.
+ */
+ public void replaceObjectsInRange(NSRange currentRange, List otherArray, NSRange otherRange) {
+ if ((currentRange == null) || (otherArray == null) || (otherRange == null))
+ return;
+
// transform otherRange if out of bounds for array
- if ( otherRange.maxRange() > otherArray.size() )
- {
+ if (otherRange.maxRange() > otherArray.size()) {
// TODO: Test this logic.
- int loc = Math.min( otherRange.location(), otherArray.size() - 1 );
- otherRange = new NSRange( loc, otherArray.size() - loc );
+ int loc = Math.min(otherRange.location(), otherArray.size() - 1);
+ otherRange = new NSRange(loc, otherArray.size() - loc);
}
-
+
Object o;
- List subList = subList(
- currentRange.location(), currentRange.maxRange() );
+ List subList = subList(currentRange.location(), currentRange.maxRange());
int otherIndex = otherRange.location();
// TODO: Test this logic.
- for ( int i = 0; i < subList.size(); i++ )
- {
- if ( otherIndex < otherRange.maxRange() )
- { // set object
- subList.set( i, otherArray.get( otherIndex ) );
- }
- else
- { // remove extra elements from currentRange
- subList.remove( i );
- i--;
+ for (int i = 0; i < subList.size(); i++) {
+ if (otherIndex < otherRange.maxRange()) { // set object
+ subList.set(i, otherArray.get(otherIndex));
+ } else { // remove extra elements from currentRange
+ subList.remove(i);
+ i--;
}
otherIndex++;
}
// TODO: Test this logic.
- for ( int i = otherIndex; i < otherRange.maxRange(); i++ )
- {
- add( otherArray.get( i ) );
+ for (int i = otherIndex; i < otherRange.maxRange(); i++) {
+ add(otherArray.get(i));
}
}
/**
- * Clears the current array and then populates it with the
- * contents of the specified collection.
- */
- public void setArray (Collection aCollection)
- {
- clear();
- addAll( aCollection );
- }
+ * Clears the current array and then populates it with the contents of the
+ * specified collection.
+ */
+ public void setArray(Collection aCollection) {
+ clear();
+ addAll(aCollection);
+ }
/**
- * Removes all objects equivalent to the specified object.
- */
- public void removeObject (Object anObject)
- {
- remove( anObject );
- }
+ * Removes all objects equivalent to the specified object.
+ */
+ public void removeObject(Object anObject) {
+ remove(anObject);
+ }
/**
- * Removes all occurences of the specified object,
- * comparing by reference.
- */
- public void removeIdenticalObject (Object anObject)
- {
- EOObserverCenter.removeObserver( observer, anObject );
- super.removeIdenticalObject( anObject );
- }
+ * Removes all occurences of the specified object, comparing by reference.
+ */
+ public void removeIdenticalObject(Object anObject) {
+ EOObserverCenter.removeObserver(observer, anObject);
+ super.removeIdenticalObject(anObject);
+ }
/**
- * Inserts the specified object into this array at the
- * specified index.
- */
- public void insertObjectAtIndex (Object anObject, int anIndex)
- {
- add( anIndex, anObject );
- }
-
+ * Inserts the specified object into this array at the specified index.
+ */
+ public void insertObjectAtIndex(Object anObject, int anIndex) {
+ add(anIndex, anObject);
+ }
+
/**
- * Replaces the object at the specified index with the
- * specified object.
- */
- public void replaceObjectAtIndex (int anIndex, Object anObject)
- {
- set( anIndex, anObject );
- }
+ * Replaces the object at the specified index with the specified object.
+ */
+ public void replaceObjectAtIndex(int anIndex, Object anObject) {
+ set(anIndex, anObject);
+ }
/**
- * Adds the specified object to the end of this array.
- */
- public void addObject (Object anObject)
- {
- add( anObject );
- }
-
- // interface List: mutators
-
- public void add(int index, Object element)
- {
- EOObserverCenter.addObserver( observer, element );
- super.add( index, element );
- }
-
- public boolean add(Object o)
- {
- EOObserverCenter.addObserver( observer, o );
- return super.add(o);
- }
-
- public boolean addAll(Collection coll)
- {
- Iterator it = coll.iterator();
- while ( it.hasNext() )
- {
- EOObserverCenter.addObserver( observer, it.next() );
- }
- return super.addAll(coll);
- }
-
- public boolean addAll(int index, Collection c)
- {
- Iterator it = c.iterator();
- while ( it.hasNext() )
- {
- EOObserverCenter.addObserver( observer, it.next() );
- }
- return super.addAll( index, c );
- }
-
- public void clear()
- {
- Iterator it = iterator();
- while ( it.hasNext() )
- {
- EOObserverCenter.removeObserver( observer, it.next() );
- }
- super.clear();
- }
-
- public Object remove(int index)
- {
- EOObserverCenter.removeObserver( observer, get(index) );
- return super.remove( index );
- }
-
- public boolean remove(Object o)
- {
- EOObserverCenter.removeObserver( observer, o );
- return super.remove(o);
- }
-
- public boolean removeAll(Collection coll)
- {
- Iterator it = coll.iterator();
- while ( it.hasNext() )
- {
- EOObserverCenter.removeObserver( observer, it.next() );
- }
- return super.removeAll(coll);
- }
-
- public boolean retainAll(Collection coll)
- {
- throw new UnsupportedOperationException();
- }
-
- public Object set(int index, Object element)
- {
- EOObserverCenter.removeObserver( observer, get(index) );
- EOObserverCenter.addObserver( observer, element );
- return super.set( index, element );
- }
+ * Adds the specified object to the end of this array.
+ */
+ public void addObject(Object anObject) {
+ add(anObject);
+ }
+
+ // interface List: mutators
+
+ public void add(int index, Object element) {
+ EOObserverCenter.addObserver(observer, element);
+ super.add(index, element);
+ }
+
+ public boolean add(Object o) {
+ EOObserverCenter.addObserver(observer, o);
+ return super.add(o);
+ }
+
+ public boolean addAll(Collection coll) {
+ Iterator it = coll.iterator();
+ while (it.hasNext()) {
+ EOObserverCenter.addObserver(observer, it.next());
+ }
+ return super.addAll(coll);
+ }
+
+ public boolean addAll(int index, Collection c) {
+ Iterator it = c.iterator();
+ while (it.hasNext()) {
+ EOObserverCenter.addObserver(observer, it.next());
+ }
+ return super.addAll(index, c);
+ }
+
+ public void clear() {
+ Iterator it = iterator();
+ while (it.hasNext()) {
+ EOObserverCenter.removeObserver(observer, it.next());
+ }
+ super.clear();
+ }
+
+ public Object remove(int index) {
+ EOObserverCenter.removeObserver(observer, get(index));
+ return super.remove(index);
+ }
+
+ public boolean remove(Object o) {
+ EOObserverCenter.removeObserver(observer, o);
+ return super.remove(o);
+ }
+
+ public boolean removeAll(Collection coll) {
+ Iterator it = coll.iterator();
+ while (it.hasNext()) {
+ EOObserverCenter.removeObserver(observer, it.next());
+ }
+ return super.removeAll(coll);
+ }
+
+ public boolean retainAll(Collection coll) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object set(int index, Object element) {
+ EOObserverCenter.removeObserver(observer, get(index));
+ EOObserverCenter.addObserver(observer, element);
+ return super.set(index, element);
+ }
}
/*
- * $Log$
- * Revision 1.2 2006/02/18 23:14:35 cgruber
- * Update imports and maven dependencies.
+ * $Log$ Revision 1.2 2006/02/18 23:14:35 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.3 2003/08/06 23:07:52 chochos
- * general code cleanup (mostly, removing unused imports)
+ * Revision 1.3 2003/08/06 23:07:52 chochos general code cleanup (mostly,
+ * removing unused imports)
*
- * Revision 1.2 2002/10/24 21:15:36 mpowers
- * New implementations of NSArray and subclasses.
+ * Revision 1.2 2002/10/24 21:15:36 mpowers New implementations of NSArray and
+ * subclasses.
*
- * Revision 1.1 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.1 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.1 2001/01/24 14:37:24 mpowers
- * Contributing a delegate useful for debugging.
+ * Revision 1.1 2001/01/24 14:37:24 mpowers Contributing a delegate useful for
+ * debugging.
*
*
*/
-