I have a custom cell for a NSTableView. My cell is a subclass of NSActionCell and contains three sub-cells, each a NSTextFieldCell. Two are at the top of my cell, placed next to each other and contain only one line of text, the third is below them and takes up the rest of the cells space (there can be multiple lines). Now I have two things I can't get to work:
I would be glad if you could point me to the right direction to accomplish these things.
Here's the code for my custom cell:
- All of the sub-cells should be editable, however I couldn't find a way to do so.
- I would like to be able to adjust the row height, so I somehow need to figure out the height that the third cell needs to display it's text.
I would be glad if you could point me to the right direction to accomplish these things.
Here's the code for my custom cell:
Code:
//
// SESubtitleCell.h
// Custom Table Cell
//
#import <Cocoa/Cocoa.h>
@interface SESubtitleCell : NSActionCell
{
@private
NSTextFieldCell *startTimeCell;
NSTextFieldCell *endTimeCell;
NSTextFieldCell *subtitleTextCell;
}
@property (retain) NSString *startTime;
@property (retain) NSString *endTime;
@property (retain) NSString *subtitleText;
@end
Code:
//
// SESubtitleCell.m
// Custom Table Cell
//
#import "SESubtitleCell.h"
static const CGFloat _SESubtitleCellSubtitleTextLeftInset = 4.0;
static const CGFloat _SESubtitleCellSubtitleTextTopInset = 5.0;
static const CGFloat _SESubtitleCellTimeTopInset = 3.0;
static const CGFloat _SESubtitleCellTimeHeight = 15.0;
static const CGFloat _SESubtitleCellTimeWidth = 80.0;
static const CGFloat _SESubtitleCellStartTimeInset = 4.0;
static const CGFloat _SESubtitleCellEndTimeInset = 7.0;
@interface SESubtitleCell (private)
- (NSRect)_subtitleFrameForInteriorFrame:(NSRect)frame;
- (NSRect)_startTimeFrameForInteriorFrame:(NSRect)frame;
- (NSRect)_endTimeFrameForInteriorFrame:(NSRect)frame;
- (void)_ensureAllCellsCreated;
- (void)_ensureStartTimeCellCreated;
- (void)_ensureEndTimeCellCreated;
- (void)_ensureSubtitleTextCellCreated;
@end
@implementation SESubtitleCell
- (id)copyWithZone:(NSZone *)zone
{
SESubtitleCell *result = [super copyWithZone:zone];
if (result == nil)
return nil;
result->startTimeCell = [startTimeCell copyWithZone:zone];
result->endTimeCell = [endTimeCell copyWithZone:zone];
result->subtitleTextCell = [subtitleTextCell copyWithZone:zone];
return result;
}
- (void)dealloc
{
[startTimeCell release];
[endTimeCell release];
[super dealloc];
}
// MARK: -
// MARK: Getters and Setters
@dynamic startTime;
@dynamic endTime;
@dynamic subtitleText;
- (NSString *)startTime
{
return [startTimeCell title];
}
- (void)setStartTime:(NSString *)newStartTime
{
[self _ensureStartTimeCellCreated];
[startTimeCell setTitle:newStartTime];
}
- (NSString *)endTime
{
return [endTimeCell title];
}
- (void)setEndTime:(NSString *)newEndTime
{
[self _ensureEndTimeCellCreated];
[endTimeCell setTitle:newEndTime];
}
- (NSString *)subtitleText
{
return [subtitleTextCell title];
}
- (void)setSubtitleText:(NSString *)newSubtitleText
{
[self _ensureSubtitleTextCellCreated];
[subtitleTextCell setTitle:newSubtitleText];
}
// MARK: -
// MARK: Override some setters that must be set for the sub-cells too
- (void)setControlView:(NSView *)controlView
{
[super setControlView:controlView];
[self _ensureAllCellsCreated];
[startTimeCell setControlView:controlView];
[endTimeCell setControlView:controlView];
[subtitleTextCell setControlView:controlView];
}
- (void)setBackgroundStyle:(NSBackgroundStyle)style
{
[super setBackgroundStyle:style];
[self _ensureAllCellsCreated];
[startTimeCell setBackgroundStyle:style];
[endTimeCell setBackgroundStyle:style];
[subtitleTextCell setBackgroundStyle:style];
}
// MARK: -
// MARK: Calculate the frames for drawing
- (NSRect)_subtitleFrameForInteriorFrame:(NSRect)frame
{
NSRect result = frame;
result.origin.x = _SESubtitleCellSubtitleTextLeftInset;
result.size.width = NSMaxX(frame) - NSMinX(result);
result.origin.y = NSMaxY([self _startTimeFrameForInteriorFrame:frame]) + _SESubtitleCellSubtitleTextTopInset;
result.size.height = NSMaxY(frame) - NSMinY(result);
return result;
}
- (NSRect)_startTimeFrameForInteriorFrame:(NSRect)frame
{
NSRect result = frame;
result.origin.x = _SESubtitleCellStartTimeInset;
result.size.width = _SESubtitleCellTimeWidth;
result.origin.y = NSMinY(frame) + _SESubtitleCellTimeTopInset;
result.size.height = _SESubtitleCellTimeHeight;
return result;
}
- (NSRect)_endTimeFrameForInteriorFrame:(NSRect)frame
{
NSRect starTimeFrame = [self _startTimeFrameForInteriorFrame:frame];
NSRect result = starTimeFrame;
result.origin.x = NSMaxX(starTimeFrame) + _SESubtitleCellEndTimeInset;
return result;
}
// MARK: Draw
- (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView *)controlView
{
[self _ensureAllCellsCreated];
NSRect startTimeFrame = [self _startTimeFrameForInteriorFrame:frame];
[startTimeCell drawWithFrame:startTimeFrame inView:controlView];
NSRect endTimeFrame = [self _endTimeFrameForInteriorFrame:frame];
[endTimeCell drawWithFrame:endTimeFrame inView:controlView];
NSRect titleFrame = [self _subtitleFrameForInteriorFrame:frame];
[subtitleTextCell drawInteriorWithFrame:titleFrame inView:controlView];
}
// MARK: -
// MARK: Hit Testing
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)frame ofView:(NSView *)controlView
{
[self _ensureAllCellsCreated];
NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
NSRect startTimeFrame = [self _startTimeFrameForInteriorFrame:frame];
if (NSPointInRect(point, startTimeFrame))
return [startTimeCell hitTestForEvent:event inRect:startTimeFrame ofView:controlView];
NSRect endTimeFrame = [self _endTimeFrameForInteriorFrame:frame];
if (NSPointInRect(point, endTimeFrame))
return [endTimeCell hitTestForEvent:event inRect:endTimeFrame ofView:controlView];
NSRect subtitleFrame = [self _subtitleFrameForInteriorFrame:frame];
if (NSPointInRect(point, subtitleFrame))
return [subtitleTextCell hitTestForEvent:event inRect:subtitleFrame ofView:controlView];
return NSCellHitNone;
}
// MARK: -
// MARK: Set Object Value
- (void)setObjectValue:(id <NSCopying>)obj
{
[super setObjectValue:obj];
[self _ensureAllCellsCreated];
if (obj) {
[startTimeCell bind:@"title" toObject:[self objectValue] withKeyPath:@"startTime" options:nil];
[endTimeCell bind:@"title" toObject:[self objectValue] withKeyPath:@"endTime" options:nil];
[subtitleTextCell bind:@"title" toObject:[self objectValue] withKeyPath:@"subtitle" options:nil];
}
}
// MARK: -
// MARK: Create the sub-cells
- (void)_ensureAllCellsCreated
{
[self _ensureStartTimeCellCreated];
[self _ensureEndTimeCellCreated];
[self _ensureSubtitleTextCellCreated];
}
- (void)_ensureStartTimeCellCreated
{
if (startTimeCell == nil) {
startTimeCell = [[NSTextFieldCell alloc] init];
[startTimeCell setControlView:self.controlView];
[startTimeCell setBackgroundStyle:self.backgroundStyle];
[startTimeCell setTextColor:[NSColor grayColor]];
}
}
- (void)_ensureEndTimeCellCreated
{
if (endTimeCell == nil) {
endTimeCell = [[NSTextFieldCell alloc] init];
[endTimeCell setControlView:self.controlView];
[endTimeCell setBackgroundStyle:self.backgroundStyle];
[endTimeCell setTextColor:[NSColor grayColor]];
}
}
- (void)_ensureSubtitleTextCellCreated
{
if (subtitleTextCell == nil) {
subtitleTextCell = [[NSTextFieldCell alloc] init];
[subtitleTextCell setControlView:self.controlView];
[subtitleTextCell setBackgroundStyle:self.backgroundStyle];
}
}
@end