home *** CD-ROM | disk | FTP | other *** search
- /* SelectionInsertionAssocation.m created by cfeder on Tue 08-Nov-1994 */
-
- #import "SelectionInsertionAssociation.h"
-
- @interface NSArray (_arrayWithObjectsNotInArray)
- - (NSArray *)arrayWithObjectsNotInArray:other;
- - (NSArray *)arrayOfSelectionIndexesForObjects:other;
- @end
-
- @implementation NSArray (_arrayWithObjectsNotInArray)
- - (NSArray *)arrayWithObjectsNotInArray:other
- {
- // Tremendously inefficient brain-dead implementation
- NSMutableArray *result = [NSMutableArray array];
- int i, count = [self count];
- for(i=0; i<count; i++) {
- id object = [self objectAtIndex:i];
- if ([other indexOfObjectIdenticalTo:object] == NSNotFound)
- [result addObject:object];
- }
- return result;
- }
-
- - (NSArray *)arrayOfSelectionIndexesForObjects:other
- {
- // look up each of objects in other and return their indices in our array
- NSMutableArray *result = [NSMutableArray array];
- int i, count = [other count];
- for(i=0; i<count; i++) {
- id object = [other objectAtIndex:i];
- unsigned idx = [self indexOfObjectIdenticalTo:object];
- if ( idx != NSNotFound)
- [result addObject:[NSNumber numberWithUnsignedInt:idx]];
- }
- return result;
- }
- @end
-
-
- // silly association to tell us about changes in the destination
- @interface _SIMessager : EOAssociation
- {
- }
- - initWithController:(EOController *)aController
- key: (NSString *)aKey destination: aDest;
- @end
-
- @implementation SelectionInsertionAssociation
- // Our controller is the one we perform insert and delete operations on.
- // Our destination is the controller that provides us with selected objects
-
- - initWithController:(EOController *)aController
- key: (NSString *)aKey destination: aDest
- {
- [super initWithController:aController key: aKey destination:aDest];
-
- // Our destination is a controller and we want to know when it changes.
- // We use another association to pass on relevant events from it.
- [destination addAssociation:[[[_SIMessager alloc] initWithController:destination key:nil destination:self] autorelease]];
- return self;
- }
-
- - (void)updateSelection
- {
- NSArray *allObjects = [destination allObjects];
- NSArray *destinationObjects = [controller allObjects];
-
- [destination setSelectionIndexes:[allObjects arrayOfSelectionIndexesForObjects:destinationObjects]];
- }
-
- - (void)contentsDidChange
- {
- if (!ignoreNotifications)
- [self updateSelection];
- }
-
- - (void)selectionDidChange
- {
- if (!ignoreNotifications)
- [self updateSelection];
- }
-
- - (void)contentsDidChangeInController:(EOController *)aController
- {
- // who cares
- }
-
- - (void)selectionDidChangeInController:(EOController *)aController
- {
- // Our selection changed. Perform relevant insertions and deletions in our
- // destination.
- NSArray *selectedObjects = [destination selectedObjects];
- NSArray *destinationObjects = [controller allObjects];
- NSArray *added = [selectedObjects arrayWithObjectsNotInArray:destinationObjects];
- NSArray *removed = [destinationObjects arrayWithObjectsNotInArray:selectedObjects];
- int i, count;
-
- ignoreNotifications = YES;
-
- // We do deletions before insertions so that the right thing happens for
- // to-one detail relationships (insert before delete would, for a moment,
- // put two objects at the destination of a to-one)
- for(i=0,count=[removed count]; i<count; i++) {
- id object = [removed objectAtIndex:i];
- unsigned idx = [[controller allObjects] indexOfObjectIdenticalTo:object];
- if (idx != NSNotFound)
- [controller deleteObjectAtIndex:idx];
- }
-
- for(i=0,count=[added count]; i<count; i++) {
- id object = [added objectAtIndex:i];
- [controller insertObject:object atIndex:0];
- }
-
- ignoreNotifications = NO;
- }
- @end
-
-
- @implementation _SIMessager
- - initWithController:(EOController *)aController
- key: (NSString *)aKey destination: aDest
- // destination is object we forward association messages to
- // key is not used
- {
- return [super initWithController:aController key: aKey destination:aDest];
- }
-
- - (void)selectionDidChange
- {
- [destination selectionDidChangeInController:[self controller]];
- }
- - (void)contentsDidChange
- {
- [destination contentsDidChangeInController:[self controller]];
- }
- @end
-
-