Reputation: 175
I need to add one checkbox in NSTableView column header. i am able to add checkbox in all rows for the above column. but i need at the column header level. i need to do a selectall functionality, but unable to add one checkbox at table header level. Any sample code or ideas will be helpful.
Thanks, Subrat
Upvotes: 4
Views: 2465
Reputation: 1367
Using a custom NSCell
instance doesn't work for the simple reason that the NSTableHeaderView
that co-ordinates the NSHeaderCell
instances handles all of the mouse event processing. Hence cell buttons in table headers never respond to mouse events.
The solution is to add the required NSControl
instances to a custom NSTableHeaderView
. The custom subclass can be set on the table view in IB. Controls are added to identified table columns like so:
[(BPTableHeaderView *)self.tableView.headerView addSubview:self.passwordTableHeaderButton
columnIdentifier:@"password"
alignment:NSLayoutAttributeRight];
Any NSView
instance can be added to a column header though is likely that adding an NSControl
instance will be most common.
NSTableHeaderView
subclass.
@interface BPTableHeaderView : NSTableHeaderView
- (void)addSubview:(NSView *)view columnIdentifier:(NSString *)identifier alignment:(NSLayoutAttribute)alignment;
@end
@interface BPTableHeaderView()
// collections
@property (strong) NSMutableDictionary<NSString *, NSDictionary *> *store;
// primitives
@property (assign, nonatomic) BOOL subviewsVisible;
@end
@implementation BPTableHeaderView
- (id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit
{
_subviewsVisible = YES;
_store = [NSMutableDictionary new];
}
#pragma mark -
#pragma mark Accessors
- (void)setSubviewsVisible:(BOOL)subviewsVisible
{
if (_subviewsVisible == subviewsVisible) return;
_subviewsVisible = subviewsVisible;
for (NSString *identifier in self.store.allKeys) {
NSDictionary *info = self.store[identifier];
NSView *view = info[@"view"];
view.hidden = !_subviewsVisible;
}
}
#pragma mark -
#pragma mark Drawing
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
if (self.draggedColumn != -1 || self.resizedColumn != -1) {
[self layoutSubviews];
}
}
#pragma mark -
#pragma mark View management
- (void)addSubview:(NSView *)view columnIdentifier:(NSString *)identifier alignment:(NSLayoutAttribute)alignment
{
self.store[identifier] = @{@"view" : view, @"alignment" : @(alignment)};
[self addSubview:view];
self.needsLayout = YES;
}
#pragma mark -
#pragma mark Layout
- (void)layout
{
[super layout];
[self layoutSubviews];
}
- (void)layoutSubviews
{
for (NSString *identifier in self.store.allKeys)
{
// info
NSDictionary *info = self.store[identifier];
NSView *view = info[@"view"];
NSLayoutAttribute alignment = [info[@"alignment"] integerValue];
// views and cells
NSTableColumn *column = [self.tableView tableColumnWithIdentifier:identifier];
NSTableHeaderCell *headerCell = column.headerCell;
NSInteger idx = [self.tableView.tableColumns indexOfObject:column];
if (idx == NSNotFound) continue;
// rects
NSRect headerRect = [self headerRectOfColumn:idx];
NSRect sortIndicatorRect = NSZeroRect;
if (column.sortDescriptorPrototype) {
sortIndicatorRect = [headerCell sortIndicatorRectForBounds:headerRect];
}
// position view
NSPoint viewOrigin = NSMakePoint(0, 0);
CGFloat y = (headerRect.size.height - view.frame.size.height)/2;
CGFloat xDelta = 3;
if (alignment == NSLayoutAttributeLeft) {
viewOrigin = NSMakePoint(headerRect.origin.x + xDelta, y);
}
else {
viewOrigin = NSMakePoint(headerRect.origin.x + headerRect.size.width - view.frame.size.width - sortIndicatorRect.size.width - 5, y);
}
[view setFrameOrigin:viewOrigin];
}
}
@end
Upvotes: 1
Reputation: 22930
Create subclass of NSButtonCell
@interface CheckboxHeaderCell : NSButtonCell {
NSButtonCell *cellCheckBox;
NSColor *bkColor;
}
-(void)setTitle:(NSString *)title;
-(void)setBkColor:(NSColor *)color;
-(BOOL)getState;
-(void)onClick;
@end
@implementation CheckboxHeaderCell
- (id)init
{
if (self = [super init])
{
bkColor = nil;
cellCheckBox = [[ NSButtonCell alloc] init];
[cellCheckBox setTitle:@""];
[cellCheckBox setButtonType:NSSwitchButton];
[cellCheckBox setBordered:NO];
[cellCheckBox setImagePosition:NSImageRight];
[cellCheckBox setAlignment:NSLeftTextAlignment];
[cellCheckBox setObjectValue:[NSNumber numberWithInt:0]];
[cellCheckBox setControlSize:NSSmallControlSize];
[cellCheckBox setFont:[NSFont systemFontOfSize:[NSFont
smallSystemFontSize]]];
}
return self;
}
- (void)dealloc
{
[cellCheckBox release];
[bkColor release];
[super dealloc];
}
-(void)setTitle:(NSString *)title
{
[cellCheckBox setTitle:title];
}
-(void)setBkColor:(NSColor *)color
{
[color retain];
[bkColor release];
bkColor = color;
}
-(BOOL)getState
{
return [[cellCheckBox objectValue] boolValue];
}
-(void)onClick
{
BOOL state = ![[cellCheckBox objectValue] boolValue];
[cellCheckBox setObjectValue:[NSNumber numberWithBool:state]];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
if (bkColor != nil)
[cellCheckBox setBackgroundColor:bkColor];
[cellCheckBox drawWithFrame:cellFrame inView:controlView] ;
}
@end
How to use:
CheckboxHeaderCell *mHeaderCell = [[CheckboxHeaderCell alloc] init];
NSTableColumn *checkBoxColumn = [mOutlineView tableColumnWithIdentifier:@"state"];
[checkBoxColumn setHeaderCell:mHeaderCell];
- (void)tableView: (NSTableView *)tableView didClickTableColumn:(NSTableColumn *)tableColumn
{
NSLog(@"didClickTableColumn");
CheckboxHeaderCell *headerCell = [tableColumn headerCell];
[headerCell onClick];
}
Upvotes: 2