|
|
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.