home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * Controller for the Ledger Document. * * Author: Kris Younger, NeXT Systems Engineering * 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 "LedgerController.h" #import "Transaction.h" #import <dbkit/dbkit.h> #import "JFTableVectorConfiguration.h" #import "JFTableViewLoader.h" #import "KAYEditableFormatter.h" #define XOFFSET 30.0 // Offset of subsequent windows #define YOFFSET -30.0 @implementation LedgerController - append:sender { id newXaction; int handle; newXaction = [[Transaction alloc] init]; [accountStore startTransaction]; handle = [account addRecord:newXaction]; [accountStore commitTransaction]; if (sender != myFormatter) [self ping:sender]; return self; } - appendThis:anObj { int handle; [accountStore startTransaction]; handle = [account addRecord:anObj]; [accountStore commitTransaction]; return self; } - commit:sender { int r; id o; r = [tableView selectedRowAfter:DB_NoIndex]; if (r != DB_NoIndex) { o = (Transaction *)[postingList objectAt:r]; [accountStore startTransaction]; [account replaceRecord:[o handle] with:o]; [accountStore commitTransaction]; if (r == ([postingList count] - 1)) { [self doBalance]; if (sender != myFormatter) [self ping:self]; } else [self doFullerBalance:self]; }; return self; } - copy:sender { return self; } - cut:sender { return self; } - paste:sender { return self; } - selectAll:sender { return self; } - initWith:aRecordManager named:(const char *)aName { char path[MAXPATHLEN + 1]; int i; if ([[NXBundle mainBundle] getPath:path forResource:"LedgerController" ofType:"nib"]) { window = [NXApp loadNibFile:path owner:self]; /* * Put the window offset from the previous document window... If no * previous window exists, or the main window is undetermined, then */ if ([[[NXApp mainWindow] delegate] respondsTo:@selector(isLedger)] == YES) { NXRect winFrame, winLoc; [[NXApp mainWindow] getFrame:&winFrame]; [[window class] getContentRect:&winLoc forFrameRect:&winFrame style:[window style]]; [window moveTo:NX_X(&winLoc) + XOFFSET:NX_Y(&winLoc) + YOFFSET]; } /* the tvLoader is an object which takes a list of objects and a list of configuration objects (see below) which work to load the tableview when it requests it. */ tvLoader = [[JFTableViewLoader alloc] init]; account = aRecordManager; accountName = aName; [account getBlock:&i andStore:&accountStore]; [tvLoader setTableView:tableView]; [[tableView setGridVisible:YES] setDelegate:self]; [[tableView window] setTitle:accountName]; #ifdef NEVEREVER /* useful in making window positions sticky on the * desktop. */ [[tableView window] setFrameAutosaveName:accountName]; [[tableView window] setFrameUsingName:accountName]; #endif myFormatter = [[KAYEditableFormatter alloc] init]; [myFormatter setController:self]; [[tableView window] disableFlushWindow]; [self buildConfigurationList]; /* go check out the method, it loads a list full of "bindings" binding a tableview column to an ivar inside of the Transaction object. essentially, letting us use a list of objects instead of a recordlist. */ [tvLoader setConfigurationList:configList]; [myFormatter setColumnLimit:[configList count] - 1]; [[tableView window] reenableFlushWindow]; [[tableView window] flushWindowIfNeeded]; for (i = 0; i < [configList count]; i++) { [[tableView columnAt:i] setFormatter:myFormatter]; }; doFullBalance = NO; } else { NXRunAlertPanel("Oops!", "No LedgerController nib file", "OK", NULL, NULL); return nil; } return self; } - findPostings { int handle; id config; IXPostingCursor *cursor; BOOL isValid; /* since the Transaction objects are serialized by creation (handled in the main delegate), this method uses the attribute "tSerial" to get a sorted-ascending ordering. The postingList is what we use load the tableview */ config = [[tableView columnAt:0] identifier]; cursor = [account cursorForAttributeNamed: [[configList objectAt:(int)config] ivarName]]; if (cursor == nil) cursor = [account cursorForAttributeNamed:"tSerial"]; postingList = [postingList free]; postingList = [[IXPostingList alloc] initWithSource:account]; for (isValid = [cursor setFirst]; isValid; isValid = [cursor setNext]) for (handle = [cursor setFirstHandle]; handle; handle = [cursor setNextHandle]) [postingList addHandle:handle withWeight:0]; [cursor free]; return postingList; } - makeKey:sender { [self doBalance]; [self ping:self]; return self; } - (const char *)accountName { return accountName; } - doBalance { double cBalance = 0.0; char buf[256]; int i, k, h, m; id obj; postingList = [self findPostings]; k = [postingList count]; [accountStore startTransaction]; if (((k - 2) <= 0) || (doFullBalance == YES)) { m = 0; cBalance = 0.0; } else { m = (k - 2); h = [postingList handleOfObjectAt:(m - 1)]; obj = [account readRecord:h fromZone:[self zone]]; strcpy(buf,[obj tBalance]); cBalance += atof(buf); }; for (i = m; i < k; i++) { h = [postingList handleOfObjectAt:i]; obj = [account readRecord:h fromZone:[self zone]]; cBalance += [obj tAmount]; sprintf(buf, "%.2f", cBalance); [obj setTBalance:buf]; [account replaceRecord:[obj handle] with:obj]; [obj free]; } [accountStore commitTransaction]; sprintf(buf, "%.2f", cBalance); [balanceTF setStringValue:buf]; return self; } - doFullerBalance:sender { doFullBalance = YES; [self doBalance]; [self ping:self]; doFullBalance = NO; return self; } - ping:sender { [window makeKeyAndOrderFront:self]; [[tableView window] disableFlushWindow]; /* DBTV ignores autodisplay */ postingList = [self findPostings]; [tvLoader setDataList:postingList]; [tableView scrollRowToVisible:[tableView rowCount] - 1]; [tableView editFieldAt:[tableView rowCount] - 1:0]; [[tableView window] reenableFlushWindow]; [[tableView window] flushWindowIfNeeded]; return self; } - void:sender { int r, h; id o, p; r = [tableView selectedRowAfter:DB_NoIndex]; if (r != DB_NoIndex) { o = (Transaction *)[postingList objectAt:r]; p = [[Transaction alloc] init]; [accountStore startTransaction]; h = [account addRecord:p]; [p becomeVoided:o]; [account replaceRecord:[o handle] with:o]; [account replaceRecord:[p handle] with:p]; [accountStore commitTransaction]; [self doBalance]; [self ping:self]; }; return self; } - closeAccount:sender { [window performClose:self]; return self; } - windowWillClose:sender { return self; } - tableView:sender movedColumnFrom:(unsigned int)old to:(unsigned int)new { if (new == 0) [self ping:self]; return self; } - buildConfigurationList { configList = [[List alloc] init]; [configList addObject:[[JFTableVectorConfiguration alloc] initDataClassName:"Transaction" titleName:"Date" ivarName:"tDate"]]; [configList addObject:[[JFTableVectorConfiguration alloc] initDataClassName:"Transaction" titleName:"REF" ivarName:"tNumber"]]; [configList addObject:[[JFTableVectorConfiguration alloc] initDataClassName:"Transaction" titleName:"Description" ivarName:"tMemo"]]; [configList addObject:[[JFTableVectorConfiguration alloc] initDataClassName:"Transaction" titleName:"Debit" ivarName:"tDebit"]]; [configList addObject:[[JFTableVectorConfiguration alloc] initDataClassName:"Transaction" titleName:"Credit" ivarName:"tCredit"]]; [configList addObject:[[JFTableVectorConfiguration alloc] initDataClassName:"Transaction" titleName:"Balance" ivarName:"tBalance"]]; return self; } @end