|
|
1.1 ! root 1: /* ! 2: AppManager.m created by enoyau on Fri 13-Jan-1995 ! 3: ! 4: You may freely copy, distribute, and reuse the code in this example. ! 5: NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 6: fitness for any particular use. ! 7: */ ! 8: ! 9: #import "AppManager.h" ! 10: #import "Employee.h" ! 11: ! 12: // A property added to the EMPLOYEE table in the PEOPLE demo database. ! 13: // This property is needed to avoid concurrent update to the same record. ! 14: #define lockProperty @"lock" ! 15: ! 16: @interface AppManager(private) ! 17: - (void)_updateDisplay; ! 18: @end ! 19: ! 20: @implementation AppManager(private) ! 21: ! 22: // Responsible for keeping the lock button states up-to-date and to ! 23: // allow/disallow editing in the tableview. ! 24: - (void)_updateDisplay ! 25: { ! 26: id currentSelection = [[eoController selectedObjects] objectAtIndex:0]; ! 27: ! 28: BOOL isEditable = [currentSelection isEditable]; ! 29: BOOL isLocked = [currentSelection isLocked]; ! 30: ! 31: [lockButton setTitle:isLocked ? "Unlock" : "Lock"]; ! 32: [lockButton setEnabled:(!isLocked) || isEditable]; ! 33: ! 34: [tableView setTarget:isLocked ? nil : lockButton]; ! 35: if([tableView isEditable] != isEditable) { ! 36: [tableView setEditable:isEditable]; ! 37: if(!isEditable) { ! 38: [tableView perform:@selector(display) ! 39: with:nil ! 40: afterDelay:0 ! 41: cancelPrevious:NO]; ! 42: } ! 43: } ! 44: return; ! 45: } ! 46: ! 47: @end ! 48: ! 49: @implementation AppManager ! 50: ! 51: // This notification is sent to AppManager by the DEONotificationCenter. ! 52: - (void)databaseChange:(DEONotification *)notification ! 53: { ! 54: id eoObject = [notification notificationObject]; ! 55: ! 56: if( !([EOFault isFault:eoObject] || [notification isLocal]) ) { ! 57: EODatabaseDataSource *eoDatabasedataSource; ! 58: EODatabaseChannel *eoDatabaseChannel; ! 59: EODatabaseContext *eoDatabaseContext; ! 60: BOOL autoTransaction = NO; ! 61: ! 62: eoDatabasedataSource =(EODatabaseDataSource*)[eoController dataSource]; ! 63: eoDatabaseChannel = [eoDatabasedataSource databaseChannel]; ! 64: eoDatabaseContext = [eoDatabaseChannel databaseContext]; ! 65: ! 66: // refetch the EO from the database server to preserve data integrity. ! 67: if (![eoDatabaseContext transactionNestingLevel]) { ! 68: [eoDatabaseContext beginTransaction]; ! 69: autoTransaction = YES; ! 70: } ! 71: ! 72: [eoDatabaseChannel refetchObject:eoObject]; ! 73: ! 74: if (autoTransaction) [eoDatabaseContext commitTransaction]; ! 75: ! 76: // redisplay the data. If editing is not ended, wait until it is done ! 77: // (by changing the selection or the state of the lock) ! 78: if([tableView isEditable]) { ! 79: needRedisplay = YES; ! 80: } else { ! 81: [eoController redisplay]; ! 82: [self _updateDisplay]; ! 83: } ! 84: } ! 85: return; ! 86: } ! 87: ! 88: // Update the lock value in the database when lock button is pressed. ! 89: - toggleLockOnSelection:sender ! 90: { ! 91: if([lockButton isEnabled]) { ! 92: id currentSelection; ! 93: NSArray *keys; ! 94: NSMutableDictionary *objectValue; ! 95: ! 96: currentSelection = [[eoController selectedObjects] objectAtIndex:0]; ! 97: keys = [NSArray arrayWithObject:lockProperty]; ! 98: objectValue = [[[currentSelection valuesForKeys:keys] mutableCopy] autorelease]; ! 99: ! 100: if([[objectValue objectForKey:lockProperty] isEqual:[EONull null]]) { ! 101: [objectValue setObject:lockString forKey:lockProperty]; ! 102: } else { ! 103: [objectValue setObject:[EONull null] forKey:lockProperty]; ! 104: } ! 105: ! 106: [eoController setValues:objectValue forObject:currentSelection]; ! 107: ! 108: [self _updateDisplay]; ! 109: } ! 110: return self; ! 111: } ! 112: @end ! 113: ! 114: @implementation AppManager(EOControllerDelegate) ! 115: - (void)controllerDidChangeSelection:(EOController *)controller ! 116: { ! 117: if(needRedisplay) { ! 118: [eoController redisplay]; ! 119: needRedisplay = NO; ! 120: } ! 121: [self _updateDisplay]; ! 122: } ! 123: @end ! 124: ! 125: @implementation AppManager(EOApplicationDelegate) ! 126: - appDidInit:sender ! 127: { ! 128: EODatabaseDataSource *eoDatabaseDataSource; ! 129: EODatabaseChannel *eoDatabaseChannel; ! 130: EOAdaptorContext *eoAdaptorContext; ! 131: ! 132: eoDatabaseDataSource = [eoController dataSource]; ! 133: eoDatabaseChannel = [eoDatabaseDataSource databaseChannel]; ! 134: eoAdaptorContext = [[eoDatabaseChannel adaptorChannel] adaptorContext]; ! 135: ! 136: // Set up as the delegate of EOController, EODatabaseChannel, ! 137: // and EOAdaptorContext ! 138: [(EOController*)eoController setDelegate:self]; ! 139: [eoDatabaseChannel setDelegate:self]; // EO updates, inserts and deletes. ! 140: [eoAdaptorContext setDelegate:self]; // Transactions begin, commit or rollback. ! 141: ! 142: // Put an ImageFormatter in column 0 ! 143: [[tableView columnAt:0] setFormatter:[[NXImageFormatter alloc] init]]; ! 144: ! 145: // A double click will lock the current selection to start the ! 146: // editing mode ! 147: [tableView setTarget:lockButton]; ! 148: [tableView setDoubleAction:@selector(performClick:)]; ! 149: ! 150: // Set up the Distributed Entreprise Object notification center ! 151: deoNotificationCenter = ! 152: [[DEONotificationCenter alloc] ! 153: initWithDatabaseChannel:eoDatabaseChannel ! 154: entity:[eoDatabaseDataSource entity]]; ! 155: ! 156: // Register for notification whenever objects of this entity are updated ! 157: [deoNotificationCenter addObserver:self ! 158: selector:@selector(databaseChange:) ! 159: notificationName:DEOUpdate ! 160: object:nil]; ! 161: ! 162: // Update instance variables ! 163: transactions = [NSMutableArray new]; ! 164: needRedisplay = NO; ! 165: lockString = [[NSString alloc] initWithFormat:@"%s-%@-%d", ! 166: NXUserName(), ! 167: [DEONotificationCenter localHostname], ! 168: NXProcessID]; ! 169: ! 170: [Employee setLocalLockString:lockString]; ! 171: ! 172: // Force the first fetch ! 173: [eoController fetch:self]; ! 174: ! 175: [self _updateDisplay]; ! 176: return self; ! 177: } ! 178: ! 179: - appWillTerminate:sender ! 180: { ! 181: [transactions release]; ! 182: [lockString release]; ! 183: [deoNotificationCenter removeObserver:self]; ! 184: [deoNotificationCenter release]; ! 185: return self; ! 186: } ! 187: @end ! 188: ! 189: // We keep a list of all objects updated in the current transaction ! 190: // and post notification of the changes when the transaction commits. ! 191: // A more complete implementation could also keep track of insertions ! 192: // and deletions. ! 193: @implementation AppManager(EOAdaptorContextDelegate) ! 194: - (void)adaptorContextDidBegin:context ! 195: { ! 196: [transactions addObject:[NSMutableArray array]]; ! 197: } ! 198: ! 199: - (void)adaptorContextDidCommit:context ! 200: { ! 201: NSMutableDictionary *commitedTransaction = [transactions lastObject]; ! 202: id enumerator, current; ! 203: ! 204: [transactions removeLastObject]; ! 205: if([transactions count]) { ! 206: [[transactions lastObject] addObjectsFromArray:commitedTransaction]; ! 207: } else { ! 208: enumerator = [commitedTransaction objectEnumerator]; ! 209: while(current = [enumerator nextObject]) { ! 210: [deoNotificationCenter postNotificationName:DEOUpdate object:current]; ! 211: } ! 212: } ! 213: } ! 214: ! 215: // If the transaction rolls back, there is no notification. ! 216: - (void)adaptorContextDidRollback:context ! 217: { ! 218: [transactions removeLastObject]; ! 219: } ! 220: ! 221: @end ! 222: ! 223: @implementation AppManager(EODatabaseChannelDelegate) ! 224: - (void)databaseChannel:channel didUpdateObject:anEO ! 225: { ! 226: [(NSMutableArray *)[transactions lastObject] addObject:anEO]; ! 227: } ! 228: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.