Re: Binding to custom NSCell [Solved]
Re: Binding to custom NSCell [Solved]
- Subject: Re: Binding to custom NSCell [Solved]
- From: Ken Tozier <email@hidden>
- Date: Thu, 12 Feb 2009 23:53:34 -0500
After looking at NSActionCell, I noticed the "setControlView" method
and this seems to be the missing link. NSActionCell sets it's control
view while NSCell does not. When I manually set the control view for
my custom cell to the table that contains it, viola! It works.
So, for any other NSCell subclassers out there, the progression of
steps is
MyCell *cell = [[[MYCell alloc] init] autorelease];
NSTableColumn *column = [[[NSTableColumn alloc] init] autorelease];
NSTableView *table = [[NSTableView alloc] initWithFrame: aFrame];
[cell setControlView: table];
[column setDataCell: cell];
[table addTableColumn: column];
[column bind: @"value" toObject: arrayController withKeyPath:
@"arrangedObjects.<key>" options: nil];
Hope this saves someone else a lost couple of days figuring this out...
On Feb 12, 2009, at 11:32 PM, Ken Tozier wrote:
Just for kicks, I tried stepping back a level and making my cell a
subclass of NSActionCell and that works too. So it seems that
whatever magic Apple is performing happens inside NSActionCell.
On Feb 12, 2009, at 11:09 PM, Ken Tozier wrote:
Hmmm. Making my cell a subclass of NSTextFieldCell solved the
problem.
I would dearly love to get a look at the the source for
NSTextFieldCell to see what it's doing, behind-the-scenes, that
makes this binding work. In general, it would be a boon to
developers if Apple would open up the source for these types of
core AppKit classes. It's not like NSTextFieldCell is some cutting
edge class and would be a great way for developers to see how to
create subclasses "the right way."
Anyway, thanks for the tip, it works perfectly now. Just wish I
knew why...
-Ken
On Feb 12, 2009, at 6:18 PM, Corbin Dunn wrote:
On Feb 12, 2009, at 1:18 PM, Ken Tozier wrote:
24 hours later, still completely stumped on this one. The
sticking point seems to be that Apple's NSTextFieldCell is doing
something that is not clearly defined in the Key-Value Observing/
Key-Value coding documentation to allow the following to work
Your best bet is to probably just subclass NSTextFieldCell --
which is probably correct for your cell, since you want to draw
some text and other sub cells. Modify the rect that you want the
text to draw in, and just call [super] to do the real drawing work.
[column bind: @"value" toObject: arrayController withKeyPath:
@"arrangedObjects.name" options: nil];
I suspect that all I'm missing is some required accessor, but
nowhere in the documentation does Apple offer a step by step
example on how to write a bindable custom NSCell subclass. What
methods are absolutely required? What methods are optional?
Please do log a bug requesting our documentation be clarified for
how to do this, and also log a bug saying that you can't bind the
value parameter of a plain NSCell. If you can, also enclose your
test project/code.
thank you!
corbin
Here's my custom cell code. Where am I going wrong?
Thanks for any help
@interface PMXDocumentCell : NSCell
{
NSButtonCell *addButton;
NSImage *backImage,
*backSelectedImage,
*addButtonImage,
*addButtonSelectedImage,
*currentBackImage;
NSString *documentName;
NSDictionary *textAttributes;
}
+ (id) documentCell;
- (void) initImages;
- (void) initSubCells;
- (NSString *) documentName;
- (void) setDocumentName:(NSString *) inName;
- (id) objectValue;
- (void) setObjectValue:(id) inObject;
@end
#define ADD_BUTTON_SIZE 17
@implementation PMXDocumentCell
+ (id) documentCell
{
return [[[PMXDocumentCell alloc]
init]
autorelease];
}
- (id) init
{
self = [super init];
if (self)
{
[self initImages];
[self initSubCells];
currentBackImage = backImage;
textAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSColor blackColor], NSForegroundColorAttributeName,
[NSFont systemFontOfSize:13], NSFontAttributeName,
nil];
}
return self;
}
- (void) initImages
{
NSBundle *bundle = [NSBundle bundleForClass: [self class]];
NSString *path;
path = [bundle pathForResource: @"add_button" ofType: @"png"];
addButtonImage = [[NSImage alloc] initWithContentsOfFile: path];
path = [bundle pathForResource: @"add_button_white" ofType:
@"png"];
addButtonSelectedImage = [[NSImage alloc]
initWithContentsOfFile: path];
path = [bundle pathForResource: @"toolbar_25" ofType: @"png"];
backImage = [[NSImage alloc] initWithContentsOfFile: path];
path = [bundle pathForResource: @"toolbar_25_focus" ofType:
@"png"];
backSelectedImage = [[NSImage alloc] initWithContentsOfFile:
path];
// set resizing
[addButtonImage setScalesWhenResized: YES];
[addButtonSelectedImage setScalesWhenResized: YES];
[backImage setScalesWhenResized: YES];
[backSelectedImage setScalesWhenResized: YES];
// size button images
[addButtonImage setSize: NSMakeSize(ADD_BUTTON_SIZE,
ADD_BUTTON_SIZE)];
[addButtonSelectedImage setSize: NSMakeSize(ADD_BUTTON_SIZE,
ADD_BUTTON_SIZE)];
}
- (void) initSubCells
{
addButton = [[NSButtonCell alloc] init];
[addButton setBordered: NO];
[addButton setButtonType: NSMomentaryChangeButton];
[addButton setImage: addButtonImage];
[addButton setAlternateImage: addButtonSelectedImage];
}
- (void) drawWithFrame:(NSRect) inCellFrame
inView:(NSView *) inControlView
{
NSRect buttonFrame = NSMakeRect(inCellFrame.size.width -
ADD_BUTTON_SIZE - 6, inCellFrame.origin.y, ADD_BUTTON_SIZE,
ADD_BUTTON_SIZE),
nameFrame = NSMakeRect(6, inCellFrame.origin.y,
inCellFrame.size.width - ADD_BUTTON_SIZE - 12 , ADD_BUTTON_SIZE);
NSPoint textPoint = NSMakePoint(inCellFrame.origin.x + 1,
inCellFrame.origin.y);
currentBackImage = [self isHighlighted] ? backSelectedImage :
backImage ;
[currentBackImage drawAtPoint: inCellFrame.origin
fromRect: NSZeroRect
operation: NSCompositeSourceOver
fraction: 1.0];
[addButton drawWithFrame: buttonFrame
inView: inControlView];
[documentName drawInRect: nameFrame
withAttributes: textAttributes];
}
- (NSString *) objectValue
{
return documentName;
}
- (void) setObjectValue:(id) inObject
{
if (inObject == nil)
inObject = @"document name";
if ([inObject isKindOfClass: [NSString class]])
[self setStringValue: inObject];
else
[NSException raise: NSInvalidArgumentException format: @"%@
Invalid object %@", NSStringFromSelector(_cmd), inObject];
}
- (NSString *) documentName
{
return documentName;
}
- (void) setDocumentName:(NSString *) inName
{
[inName retain];
[documentName release];
documentName = inName;
// Tell control view to redisplay us.
[(NSControl *)[self controlView] updateCell: self];
}
@end
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden