home *** CD-ROM | disk | FTP | other *** search
- /*
- AppManager.m created by enoyau on Fri 13-Jan-1995
-
- You may freely copy, distribute, and reuse the code in this example.
- NeXT disclaims any warranty of any kind, expressed or implied, as to its
- fitness for any particular use.
- */
-
- #import "AppManager.h"
- #import "Employee.h"
-
- // A property added to the EMPLOYEE table in the PEOPLE demo database.
- // This property is needed to avoid concurrent update to the same record.
- #define lockProperty @"lock"
-
- @interface AppManager(private)
- - (void)_updateDisplay;
- @end
-
- @implementation AppManager(private)
-
- // Responsible for keeping the lock button states up-to-date and to
- // allow/disallow editing in the tableview.
- - (void)_updateDisplay
- {
- id currentSelection = [[eoController selectedObjects] objectAtIndex:0];
-
- BOOL isEditable = [currentSelection isEditable];
- BOOL isLocked = [currentSelection isLocked];
-
- [lockButton setTitle:isLocked ? "Unlock" : "Lock"];
- [lockButton setEnabled:(!isLocked) || isEditable];
-
- [tableView setTarget:isLocked ? nil : lockButton];
- if([tableView isEditable] != isEditable) {
- [tableView setEditable:isEditable];
- if(!isEditable) {
- [tableView perform:@selector(display)
- with:nil
- afterDelay:0
- cancelPrevious:NO];
- }
- }
- return;
- }
-
- @end
-
- @implementation AppManager
-
- // This notification is sent to AppManager by the DEONotificationCenter.
- - (void)databaseChange:(DEONotification *)notification
- {
- id eoObject = [notification notificationObject];
-
- if( !([EOFault isFault:eoObject] || [notification isLocal]) ) {
- EODatabaseDataSource *eoDatabasedataSource;
- EODatabaseChannel *eoDatabaseChannel;
- EODatabaseContext *eoDatabaseContext;
- BOOL autoTransaction = NO;
-
- eoDatabasedataSource =(EODatabaseDataSource*)[eoController dataSource];
- eoDatabaseChannel = [eoDatabasedataSource databaseChannel];
- eoDatabaseContext = [eoDatabaseChannel databaseContext];
-
- // refetch the EO from the database server to preserve data integrity.
- if (![eoDatabaseContext transactionNestingLevel]) {
- [eoDatabaseContext beginTransaction];
- autoTransaction = YES;
- }
-
- [eoDatabaseChannel refetchObject:eoObject];
-
- if (autoTransaction) [eoDatabaseContext commitTransaction];
-
- // redisplay the data. If editing is not ended, wait until it is done
- // (by changing the selection or the state of the lock)
- if([tableView isEditable]) {
- needRedisplay = YES;
- } else {
- [eoController redisplay];
- [self _updateDisplay];
- }
- }
- return;
- }
-
- // Update the lock value in the database when lock button is pressed.
- - toggleLockOnSelection:sender
- {
- if([lockButton isEnabled]) {
- id currentSelection;
- NSArray *keys;
- NSMutableDictionary *objectValue;
-
- currentSelection = [[eoController selectedObjects] objectAtIndex:0];
- keys = [NSArray arrayWithObject:lockProperty];
- objectValue = [[[currentSelection valuesForKeys:keys] mutableCopy] autorelease];
-
- if([[objectValue objectForKey:lockProperty] isEqual:[EONull null]]) {
- [objectValue setObject:lockString forKey:lockProperty];
- } else {
- [objectValue setObject:[EONull null] forKey:lockProperty];
- }
-
- [eoController setValues:objectValue forObject:currentSelection];
-
- [self _updateDisplay];
- }
- return self;
- }
- @end
-
- @implementation AppManager(EOControllerDelegate)
- - (void)controllerDidChangeSelection:(EOController *)controller
- {
- if(needRedisplay) {
- [eoController redisplay];
- needRedisplay = NO;
- }
- [self _updateDisplay];
- }
- @end
-
- @implementation AppManager(EOApplicationDelegate)
- - appDidInit:sender
- {
- EODatabaseDataSource *eoDatabaseDataSource;
- EODatabaseChannel *eoDatabaseChannel;
- EOAdaptorContext *eoAdaptorContext;
-
- eoDatabaseDataSource = [eoController dataSource];
- eoDatabaseChannel = [eoDatabaseDataSource databaseChannel];
- eoAdaptorContext = [[eoDatabaseChannel adaptorChannel] adaptorContext];
-
- // Set up as the delegate of EOController, EODatabaseChannel,
- // and EOAdaptorContext
- [(EOController*)eoController setDelegate:self];
- [eoDatabaseChannel setDelegate:self]; // EO updates, inserts and deletes.
- [eoAdaptorContext setDelegate:self]; // Transactions begin, commit or rollback.
-
- // Put an ImageFormatter in column 0
- [[tableView columnAt:0] setFormatter:[[NXImageFormatter alloc] init]];
-
- // A double click will lock the current selection to start the
- // editing mode
- [tableView setTarget:lockButton];
- [tableView setDoubleAction:@selector(performClick:)];
-
- // Set up the Distributed Entreprise Object notification center
- deoNotificationCenter =
- [[DEONotificationCenter alloc]
- initWithDatabaseChannel:eoDatabaseChannel
- entity:[eoDatabaseDataSource entity]];
-
- // Register for notification whenever objects of this entity are updated
- [deoNotificationCenter addObserver:self
- selector:@selector(databaseChange:)
- notificationName:DEOUpdate
- object:nil];
-
- // Update instance variables
- transactions = [NSMutableArray new];
- needRedisplay = NO;
- lockString = [[NSString alloc] initWithFormat:@"%s-%@-%d",
- NXUserName(),
- [DEONotificationCenter localHostname],
- NXProcessID];
-
- [Employee setLocalLockString:lockString];
-
- // Force the first fetch
- [eoController fetch:self];
-
- [self _updateDisplay];
- return self;
- }
-
- - appWillTerminate:sender
- {
- [transactions release];
- [lockString release];
- [deoNotificationCenter removeObserver:self];
- [deoNotificationCenter release];
- return self;
- }
- @end
-
- // We keep a list of all objects updated in the current transaction
- // and post notification of the changes when the transaction commits.
- // A more complete implementation could also keep track of insertions
- // and deletions.
- @implementation AppManager(EOAdaptorContextDelegate)
- - (void)adaptorContextDidBegin:context
- {
- [transactions addObject:[NSMutableArray array]];
- }
-
- - (void)adaptorContextDidCommit:context
- {
- NSMutableDictionary *commitedTransaction = [transactions lastObject];
- id enumerator, current;
-
- [transactions removeLastObject];
- if([transactions count]) {
- [[transactions lastObject] addObjectsFromArray:commitedTransaction];
- } else {
- enumerator = [commitedTransaction objectEnumerator];
- while(current = [enumerator nextObject]) {
- [deoNotificationCenter postNotificationName:DEOUpdate object:current];
- }
- }
- }
-
- // If the transaction rolls back, there is no notification.
- - (void)adaptorContextDidRollback:context
- {
- [transactions removeLastObject];
- }
-
- @end
-
- @implementation AppManager(EODatabaseChannelDelegate)
- - (void)databaseChannel:channel didUpdateObject:anEO
- {
- [(NSMutableArray *)[transactions lastObject] addObject:anEO];
- }
- @end
-