Wednesday, October 14, 2009

Instant Cocoa: Checkbook project 6




Balancing act


The balance is calculated in two different ways depending on the value of the segmented control. One is the standard way, and one is the way you would balance your checkbook by hand against the bank statement, only counting those items which have cleared the bank and appear in the statement. The mode is set in the UI and read using an IBOutlet to the object myUISettings.

The math of the balance methods is trivial. We get the starting balance from the value of the first item. If we're doing clearedOnly and the initial transactions are not clear, then we must skip down to find one that is clear. Here is how we add:


// slower than molasses
- (NSNumber *)addX:(NSNumber *)x
Y:(NSNumber *)y
isDeposit:(NSNumber *)d {
if ([d boolValue]) {
f = [x floatValue] + [y floatValue];
}
else { f = [x floatValue] - [y floatValue]; }
return [NSNumber numberWithFloat:f];
}


Overall, this is probably pretty slow code, and that's a worry because the method is triggered by any user edit of the amount or clicking of a cleared checkbox, or of the segmented control. It's slow because it converts back and forth to NSNumbers. Still, it seems to be fast enough at present. If we have a thousand checks it may need modification.

My one good idea


I had an inspiration when dealing with a problem in the presentation of the balance in the UI. In the special mode, I wanted to send an NSNumber (the formatter expects that), but send nothing (have no display) when the item isn't cleared. That doesn't work because the formatter wants a number, and if it's zero it displays ".00."

You can't send a string sometimes and a number other times. I could use a formatter to deal with this, but then I'd have to worry about doing right justification correctly and it's a mess.

The solution I came up with is to bind the text color of the value to the clear key. I initially planned to use white on white---the amount would be displayed but it would be invisible. Then I found I actually like the grayed-out look.

Here is ColorTransformerTwo (note the "Two", "2" results in a duplicate symbol error). We set the global flag clearedOnly by hand when it changes, because we don't want to poll the UI every time we're going to display a balance.


#import "ColorTransformerTwo.h"

@implementation ColorTransformerTwo

bool clearedOnly;
NSColor *color;
NSColorList *CL;

- (id)init {
self = [super init];
if (self == nil) return nil;
CL = [NSColorList colorListNamed:@"Crayons"];
color = [CL colorWithKey:@"Silver"];
return self;
}

- (void)awakeFromNib {
clearedOnly = NO;
}

- (void)setFlag:(bool)flag{
clearedOnly = flag;
}

+ (Class)transformedValueClass{
return [NSColor class];
}

- (NSColor *)transformedValue:(id)value {
//NSLog(@"#2 transformedValue %@", value);
if (nil == value) { return nil; }

if (!(clearedOnly)) { return [NSColor blackColor]; }
if ([value boolValue]) { return [NSColor blueColor]; }
return color;
}

@end