First step was to make the tools inherit from NSResponder:
@interface BWTool : NSResponder
{
// blah
}
// ... more blah
@end // BWTool
Then, in the view class where the tool gets set, put the tool in the responder chain by setting its next responder to be the view's current next responder. If a different tool gets set, take the current tool's next responder and give it to the new tool. Otherwise the view gets its original next responder back:
- (void) setTool: (BWTool *) newTool
{
NSResponder *nextResponder;
// this is the next element in the chain
if (currentTool != nil) {
nextResponder = [currentTool nextResponder];
} else {
nextResponder = [self nextResponder];
}
// decide who gets to point to the next responder
if (newTool != nil) {
// stick the tool into the chain
[self setNextResponder: newTool];
[newTool setNextResponder: nextResponder];
} else {
// cut the tool out of the chain (if there was one)
[self setNextResponder: nextResponder];
}
[newTool retain];
[currentTool release];
currentTool = newTool;
} // setDrawTool
And now tools can have action methods, and menu items that enable and disable appropriately.
- (NSString*) title
{
return (title);
} // title
- (void) setTitle: (NSString *) newTitle
{
[title autorelease];
title = [newTitle copy];
} // setTitle
For maximum safety in the face of threads, use this:
- (NSString *) title
{
return [[title retain] autorelease];
} // title
This puts title into the current thread's autorelease pool, so title is protected from being destroyed by someone else in another thread.
- (void) setTitle: (NSString *) newTitle
{
// use a mutex or NSLock to protect this
if (title != newtitle) {
[title release];
title = [newTitle copy];
}
} // setTitle
By making a copy of the object, you're protected from another thread changing the value underneath you.id instance variable in your class, and make methods to set and get it:
id delegate;
...
-(void) setDelegate: (id) del
{
delegate = del; // you don't need to retain it
} // setDelegate
- (id) delegate
{
return (delegate);
} // delegate
NSObject so the compiler won't generate warnings, and also to document the delegate methods you support:@interface NSObject(BWStitchViewDelegate) - (BOOL) shouldHandleStuff: (NSData *) data; @end
...
if ([delegate respondsToSelector: @selector(shouldHandleStuff:)]) {
BOOL blah;
blah = [delegate shouldHandleStuff: somedata];
if (blah) ...
}
- (BOOL) respondsToSelector: (SEL) aSelector
{
NSLog (@"%s", (char *) aSelector);
return ([super respondsToSelector: aSelector]);
} // respondsToSelector
This takes advantage of an implementation detail where the SEL is actually a pointer to a C string
[themStitches sortUsingSelector: @selector(compareByRowLocation:)];
And this selector on the BWCrossStitch class:
- (NSComparisonResult) compareByRowLocation: (BWCrossStitch *) thing2;Figure out which is lesser or greater, and return one of these. Note that
self is the object's logical value, not the actual value of the self pointer.
NSOrderedAsending if self < thing2
NSOrderedDescending if self > thing2
NSOrderedSame if self == thing2