|
|
1.1 ! root 1: /* ! 2: * Main Delegate ! 3: * ! 4: * Author: Kris Younger, NeXT Systems Engineering ! 5: * You may freely copy, distribute and reuse the code in this example. ! 6: * NeXT disclaims any warranty of any kind, expressed or implied, as to ! 7: * its fitness for any particular use. ! 8: */ ! 9: ! 10: #import "MainDelegate.h" ! 11: #import "GlobalThings.h" ! 12: #import "Transaction.h" ! 13: #import "LedgerController.h" ! 14: ! 15: #import <ansi/time.h> ! 16: #import <objc/hashtable.h> ! 17: ! 18: @implementation MainDelegate ! 19: ! 20: - findAccount:sender ! 21: { ! 22: char *name; ! 23: id matrix; ! 24: int i; ! 25: ! 26: name = (char *)[editField stringValue]; ! 27: if ([self getAccountNamed:name] != nil) { ! 28: matrix = [listBrowser matrixInColumn:0]; ! 29: for (i = [matrix cellCount]; i--;) ! 30: if (!strcmp(name, [[matrix cellAt:i :0] stringValue])) { ! 31: [matrix selectCellAt:i :0]; ! 32: [self pickAccount:listBrowser]; ! 33: break; ! 34: } ! 35: } ! 36: ! 37: return self; ! 38: } ! 39: ! 40: - addAccount:sender ! 41: { ! 42: id newRM, firstx; ! 43: int h; ! 44: const char *aName; ! 45: id accountStore; ! 46: ! 47: aName = [editField stringValue]; ! 48: if ([accountsStoreDirectory hasEntryNamed:aName] == NO) { ! 49: [accountsStoreDirectory getBlock:&h andStore:&accountStore]; ! 50: [accountStore startTransaction]; ! 51: [accountsStoreDirectory addEntryNamed:aName ofClass:[IXRecordManager class]]; ! 52: newRM = [accountsStoreDirectory openEntryNamed:aName]; ! 53: [self addAllAttributes:newRM]; ! 54: [accountsHashTable insertKey:aName value:newRM]; ! 55: /* post an original transaction */ ! 56: firstx = [[Transaction alloc] init]; ! 57: [firstx setTMemo:"Initial Value."]; ! 58: [firstx setTAmount:0.0]; ! 59: h = [newRM addRecord:firstx]; ! 60: [accountStore commitTransaction]; ! 61: } else { ! 62: NXRunAlertPanel("Alert", "An account by that name already exists.", "OK", NULL, NULL); ! 63: return nil; ! 64: } ! 65: [self ping:self]; ! 66: return self; ! 67: } ! 68: ! 69: - appDidInit:sender ! 70: { ! 71: ! 72: if ([self openDatabase]) { ! 73: } else { ! 74: [self initSchema]; ! 75: [self openDatabase]; ! 76: } ! 77: ! 78: [self makeListKey:self]; ! 79: return self; ! 80: } ! 81: ! 82: - appWillTerminate:sender ! 83: { ! 84: [self closeDatabase]; ! 85: return self; ! 86: } ! 87: ! 88: - closeAccount:sender ! 89: { ! 90: id ledger; ! 91: ! 92: [self findAccount:sender]; ! 93: if ((currentAccount != NULL) && (currentAccount != nil)) { ! 94: if ([ledgersHashTable isKey:currentAccountName] == YES) { ! 95: ledger = [ledgersHashTable valueForKey:currentAccountName]; ! 96: [ledgersHashTable removeKey:currentAccountName]; ! 97: [(LedgerController *) ledger closeAccount:self]; ! 98: [(LedgerController *) ledger free]; ! 99: }; ! 100: }; ! 101: return self; ! 102: } ! 103: ! 104: - doubleClickAccount:sender ! 105: { ! 106: [self pickAccount:sender]; ! 107: [self openAccount:sender]; ! 108: return self; ! 109: } ! 110: ! 111: - makeListKey:sender ! 112: { ! 113: [listBrowser loadColumnZero]; ! 114: [listBrowser setDoubleAction:@selector(doubleClickAccount:)]; ! 115: [listWindow makeKeyAndOrderFront:self]; ! 116: [editField selectText:self]; ! 117: return self; ! 118: } ! 119: ! 120: - openAccount:sender ! 121: { ! 122: id newAccount; ! 123: ! 124: [self findAccount:sender]; ! 125: if ((currentAccount != NULL) && (currentAccount != nil)) { ! 126: if ([ledgersHashTable isKey:currentAccountName] == YES) { ! 127: [(id)[ledgersHashTable valueForKey:currentAccountName] makeKey:self]; ! 128: } else { ! 129: newAccount = [[LedgerController alloc] initWith:currentAccount ! 130: named:currentAccountName]; ! 131: [ledgersHashTable insertKey:currentAccountName value:newAccount]; ! 132: [newAccount makeKey:self]; ! 133: }; ! 134: } ! 135: return self; ! 136: } ! 137: ! 138: - ping:sender ! 139: { ! 140: [self makeListKey:sender]; ! 141: return self; ! 142: } ! 143: ! 144: - pickAccount:sender ! 145: { ! 146: BOOL isSelected; ! 147: ! 148: isSelected = NO; ! 149: currentAccount = [self getAccountNamed:[[[sender matrixInColumn:0] selectedCell] stringValue]]; ! 150: if ((currentAccount != NULL) && (currentAccount != nil)) { ! 151: isSelected = YES; ! 152: currentAccountName = [[[sender matrixInColumn:0] selectedCell] stringValue]; ! 153: currentAccountName = NXUniqueString(currentAccountName); ! 154: } ! 155: ! 156: if (isSelected == YES) { ! 157: [openButton setEnabled:YES]; ! 158: [closeButton setEnabled:YES]; ! 159: [editField setStringValue:currentAccountName]; ! 160: [removeButton setEnabled:YES]; ! 161: } else { ! 162: [addButton setEnabled:NO]; ! 163: [removeButton setEnabled:NO]; ! 164: [openButton setEnabled:NO]; ! 165: [closeButton setEnabled:NO]; ! 166: } ! 167: return self; ! 168: } ! 169: ! 170: - removeAccount:sender ! 171: { ! 172: id account; ! 173: id accountStore; ! 174: unsigned block; ! 175: ! 176: [self closeAccount:self]; ! 177: if ((currentAccount != NULL) && (currentAccount != nil)) { ! 178: if ((account = [self getAccountNamed:currentAccountName]) != nil) { ! 179: [accountsStoreDirectory getBlock:&block andStore:&accountStore]; ! 180: [accountStore startTransaction]; ! 181: [accountsStoreDirectory removeName:currentAccountName]; ! 182: [accountsHashTable removeKey:currentAccountName]; ! 183: [account freeFromStore]; ! 184: [accountStore commitTransaction]; ! 185: }; ! 186: }; ! 187: [self ping:self]; ! 188: return self; ! 189: } ! 190: ! 191: - (const char *)todaysDate ! 192: { ! 193: char buffer[32]; ! 194: struct tm *timeptr; ! 195: time_t timer; ! 196: ! 197: time(&timer); ! 198: timeptr = localtime(&timer); ! 199: strftime(buffer, sizeof(buffer), "%Y/%m/%d", timeptr); ! 200: return NXUniqueString(buffer); ! 201: } ! 202: ! 203: - (int)consumeSerial ! 204: { ! 205: return [globalThings consumeSerial]; ! 206: } ! 207: ! 208: - (int)browser:b fillMatrix:m inColumn:(int)c ! 209: { ! 210: int cnt; ! 211: int i; ! 212: id t; ! 213: ! 214: if (list) ! 215: free(list); ! 216: list = [self listOfAccountNames]; ! 217: i = cnt = 0; ! 218: if (list != NULL) ! 219: while (list[i]) { ! 220: [m addRow]; ! 221: t = [m cellAt:i :0]; ! 222: [t setStringValue:list[i]]; ! 223: [t setLoaded:YES]; ! 224: [t setLeaf:YES]; ! 225: cnt += 1; ! 226: i += 1; ! 227: }; ! 228: ! 229: return cnt; ! 230: } ! 231: ! 232: - initSchema ! 233: { ! 234: id tmpSC; ! 235: int handle; ! 236: ! 237: /* create main Archive */ ! 238: NXRunAlertPanel("Welcome.", "Creating Ledger.store.", "OK", NULL, NULL); ! 239: mainStoreDirectory = [[IXStoreDirectory alloc] ! 240: initWithName:"Archive" inFile:"Ledger.store"]; ! 241: [mainStoreDirectory getBlock:&handle andStore:&mainStoreHandle]; ! 242: if ([mainStoreDirectory hasEntryNamed:"Accounts"] == NO) { ! 243: accountsStoreDirectory = [mainStoreDirectory ! 244: addEntryNamed:"Accounts" ofClass:[IXStoreDirectory class]]; ! 245: } ! 246: if ([mainStoreDirectory hasEntryNamed:"Globals"] == NO) { ! 247: tmpSC = [mainStoreDirectory addEntryNamed:"Globals" ofClass:[IXRecordManager class]]; ! 248: [tmpSC addAttributeNamed:"Globals" forSelector:@selector(identification)]; ! 249: globalThings = (GlobalThings *)[[GlobalThings alloc] init]; ! 250: [tmpSC addRecord:globalThings]; ! 251: } ! 252: /* the following two lines enable transactions in the storeFile. */ ! 253: [mainStoreHandle startTransaction]; ! 254: [mainStoreHandle commitTransaction]; ! 255: [mainStoreDirectory free]; ! 256: return self; ! 257: } ! 258: ! 259: - openDatabase ! 260: { ! 261: int handle; ! 262: id cursor; ! 263: ! 264: if (mainStoreDirectory = [[IXStoreDirectory alloc] initFromName:"Archive" ! 265: inFile:"Ledger.store" forWriting:YES]) { ! 266: [mainStoreDirectory getBlock:&handle andStore:&mainStoreHandle]; ! 267: [mainStoreHandle startTransaction]; ! 268: [mainStoreHandle commitTransaction]; ! 269: if ([mainStoreDirectory hasEntryNamed:"Accounts"] == YES) { ! 270: accountsStoreDirectory = [mainStoreDirectory openEntryNamed:"Accounts"]; ! 271: } ! 272: if ([mainStoreDirectory hasEntryNamed:"Globals"] == YES) { ! 273: globalThingsRecordManager = [mainStoreDirectory openEntryNamed:"Globals"]; ! 274: } ! 275: cursor = [globalThingsRecordManager cursorForAttributeNamed:"Globals"]; ! 276: if ([cursor setKey:(void *)GLOBALVARIDENT ! 277: andLength:(strlen(GLOBALVARIDENT) + 1)] == YES) { ! 278: handle = [cursor setFirstHandle]; ! 279: globalThings = [globalThingsRecordManager readRecord:handle fromZone:[self zone]]; ! 280: } ! 281: [cursor free]; ! 282: accountsHashTable = [[HashTable alloc] initKeyDesc:"*"]; ! 283: ledgersHashTable = [[HashTable alloc] initKeyDesc:"*"]; ! 284: } ! 285: if (mainStoreDirectory == nil) ! 286: return nil; ! 287: return self; ! 288: } ! 289: ! 290: - closeDatabase ! 291: { ! 292: [mainStoreHandle startTransaction]; ! 293: [globalThingsRecordManager replaceRecord:[globalThings handle] with:globalThings]; ! 294: [mainStoreHandle commitTransaction]; ! 295: [mainStoreDirectory free]; ! 296: return self; ! 297: } ! 298: ! 299: - (char **)listOfAccountNames ! 300: { ! 301: return [accountsStoreDirectory entries]; ! 302: } ! 303: ! 304: - getAccountNamed:(const char *)aName ! 305: { ! 306: id account = nil; ! 307: ! 308: if ([accountsStoreDirectory hasEntryNamed:aName] == YES) { ! 309: aName = NXUniqueString(aName); ! 310: if ((account = [accountsHashTable valueForKey:aName]) == nil) { ! 311: if ((account = [accountsStoreDirectory openEntryNamed:aName]) != nil) ! 312: [accountsHashTable insertKey:aName value:account]; ! 313: }; ! 314: }; ! 315: return account; ! 316: } ! 317: ! 318: - (BOOL)textWillChange:textObject ! 319: { ! 320: [addButton setEnabled:YES]; ! 321: return NO; ! 322: } ! 323: ! 324: - (BOOL)textWillEnd:textObject ! 325: { ! 326: [self findAccount:listBrowser]; ! 327: [self openAccount:listBrowser]; ! 328: return NO; ! 329: } ! 330: ! 331: - textDidChange:textObject ! 332: { ! 333: currentAccount = nil; ! 334: currentAccountName = NULL; ! 335: return self; ! 336: } ! 337: ! 338: - addAllAttributes:aRecMgr ! 339: { ! 340: [mainStoreHandle startTransaction]; ! 341: [aRecMgr addAttributeNamed:"tSerial" forSelector:@selector(tSerial)]; ! 342: [aRecMgr addAttributeNamed:"tNumber" forSelector:@selector(tNumber)]; ! 343: [aRecMgr addAttributeNamed:"tDate" forSelector:@selector(tDate)]; ! 344: [aRecMgr addAttributeNamed:"tMemo" forSelector:@selector(tMemo)]; ! 345: [aRecMgr addAttributeNamed:"tDebit" forSelector:@selector(tDebit)]; ! 346: [aRecMgr addAttributeNamed:"tCredit" forSelector:@selector(tCredit)]; ! 347: [mainStoreHandle commitTransaction]; ! 348: return self; ! 349: } ! 350: ! 351: ! 352: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.