Re: Cocoa Custom NSCell Binding Issue
Re: Cocoa Custom NSCell Binding Issue
- Subject: Re: Cocoa Custom NSCell Binding Issue
- From: mmalcolm crawford <email@hidden>
- Date: Tue, 17 Jan 2006 04:50:37 -0800
*As far as I can tell* (I need to clarify this with engineering to
find out how accurate this is, but perhaps others may be able to make
progress given the example), the main issue is:
You must not override
- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
ofView:(NSView *)controlView untilMouseUp:(BOOL)flag
unless you call super. If you rely on overriding this method, then
you may have to modify your code somewhat...
As an example, take the ClockControl project from <file:///Developer/
Examples/AppKit/ClockControl/>, and modify the ClockCell class
(defined in ClockControl.{h,m}) as follows:
In ClockControl.h
@interface ClockCell : NSActionCell {
NSCalendarDate *time;
NSRect trackingFrame; // add instance variable
}
// add this declaration
-(void)updateForMouseAtPoint:(NSPoint)point inView:(NSView *)
controlView;
In ClockControl.m
replace the methods
- (BOOL)trackMouseForTimeChangeEvent:(NSEvent *)theEvent inRect:
(NSRect)cellFrame ofView:(NSView *)controlView
and
- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
ofView:(NSView *)controlView untilMouseUp:(BOOL)flag
with
- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
ofView:(NSView *)controlView untilMouseUp:(BOOL)flag {
NSPoint locationInCellFrame = [controlView convertPoint:
[theEvent locationInWindow] fromView:nil];
if ( PointIsInClockFace(locationInCellFrame, cellFrame) ) {
trackingFrame = [controlView convertRect: cellFrame
fromView:nil];
// If the mouse click happened on the clock face, drag the
hour hand around.
[super trackMouse:theEvent inRect:cellFrame
ofView:controlView untilMouseUp:flag];
} else {
// ... otherwise, just toggle, the AM/PM indication.
[self toggleAmPm:nil];
}
return YES;
}
- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
{
[self updateForMouseAtPoint:startPoint inView:controlView];
return YES;
}
- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint
inView:(NSView *)controlView
{
[self updateForMouseAtPoint:currentPoint inView:controlView];
return YES;
}
- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:
(NSView *)controlView mouseIsUp:(BOOL)flag
{
if ([self isEnabled]) {
[self updateForMouseAtPoint:stopPoint inView:controlView];
if (flag && (![self isContinuous])) {
[[self target] performSelector:[self action]
withObject:self];
}
}
[super stopTracking:lastPoint at:stopPoint inView:controlView
mouseIsUp:flag];
}
-(void)updateForMouseAtPoint:(NSPoint)point inView:(NSView *)controlView
{
float radius = MIN(NSWidth(trackingFrame), NSHeight
(trackingFrame))/2.0;
float centerX = floor(NSMinX(trackingFrame)+radius+.5);
float centerY = floor(NSMinY(trackingFrame)+radius+.5);
NSPoint centerPoint = NSMakePoint(centerX, centerY);
float angleFromNorth = 0.0;
NSPoint mousePoint = [controlView convertPoint: point
fromView:nil];
// For each movement, update the position of the hour hand by
adjusting our time.
angleFromNorth = AngleFromNorth(centerPoint, mousePoint, NO);
[self setHourHandByAngleFromNorth:angleFromNorth];
[(NSControl *)controlView updateCell: self];
}
This should give you a ClockCell class that you can use in a table
view with bindings.
Caveat: This approach works (modulo a glitch shared by the
original...) for this example, but as noted at the outset I haven't
verified that this is strictly correct or guaranteed to work for
other cells (although I have created from scratch a test cell class
that follows the same pattern, and it also works). The example is
given solely as a pointer towards a possible solution...
In particular, note that the way you establish the binding is also
important. Bindings established in Interface Builder are unlikely to
work. Instead you establish them programmatically:
MyCell *myCell = [[[MyCell alloc] initImageCell:nil] autorelease];
NSTableColumn *myCellColumn = [tableView
tableColumnWithIdentifier:@"myCell"];
[myCellColumn setDataCell:myCell];
[myCellColumn bind:@"value" toObject:arrayController
withKeyPath:@"arrangedObjects.key" options:nil];
It may be that you *must not* establish any bindings for the column
in Interface Builder, otherwise an option may be set for the column
that prevents it from working for the custom cell.
mmalc
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden