Is it possible to change the names of NSTableView columns by double clicking on the columns headers? Any suggestions on the best way to do this.
I am trying:
editWithFrame:inView:editor:delegate:event:
.I'm not entirely sure why this distorts the text, but when you double click the header it makes the text look like this, no field editor appears,
In the AppDelegate,
-(void)awakeFromNib
{
...
[_tableView setDoubleAction:@selector(doubleClickInTableView:)];
...
}
-(void) doubleClickInTableView:(id)sender
{
NSInteger row = [_tableView clickedRow];
NSInteger column = [_tableView clickedColumn];
if(row == -1){
/* Want to edit the column header on double-click */
NSTableColumn *tableColumn = [[_tableView tableColumns] objectAtIndex:column];
NSTableHeaderView *headerView = [_tableView headerView];
NSTableHeaderCell *headerCell = [tableColumn headerCell];
NSRect cellFrame = [headerView headerRectOfColumn:column];
NSText * fieldEditor = [[headerView window] fieldEditor:YES forObject:nil];
[headerCell editWithFrame:cellFrame inView:headerView editor:fieldEditor delegate:headerCell event:nil];
}
}
These constants define table row edges on which row actions are attached. They are used by the tableView:rowActionsForRow:edge: delegate method. Posted whenever a column is moved by user action in an NSTableView object. Posted whenever a column is resized in an NSTableView object.
For example, the delegate supports table column management, type-to-select functionality, row selection and editing, custom tracking, and custom views for individual columns and rows. To learn more about the table view delegate, see NSTableViewDelegate.
To learn about the methods that an NSTableView object uses to provide and access the contents of its data source object, see NSTableViewDataSource. To customize a table view’s behavior without subclassing NSTableView, use the methods defined by the NSTableViewDelegate protocol.
Table views are displayed in scroll views. Beginning with macOS v10.7, you can use NSView objects (most commonly customized NSTableCellView objects) instead of cells for specifying rows and columns. You can still use NSCell objects for each row and column item if you prefer.
it seems doable
what you see in your screenshot is the window's field editor overlaying your cell's textfield
the editor has a transparent background so that's why it's messed up
so here's the deal :
you will need to have your own NSTableHeaderCell subclass to act as the field editor's delegate :
@interface NBETableHeaderCell () <NSTextViewDelegate>
@end
@implementation NBETableHeaderCell
- (void)textDidEndEditing:(NSNotification *)notification
{
NSTextView *editor = notification.object;
// Update the title, kill the focus ring, end editing
[self setTitle:editor.string];
[self setHighlighted:NO];
[self endEditing:editor];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
if([self isHighlighted])
{
[self drawFocusRingMaskWithFrame:cellFrame inView:controlView.superview];
}
[super drawWithFrame:cellFrame inView:controlView];
}
- (void)drawFocusRingMaskWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
[controlView lockFocus];
NSSetFocusRingStyle(NSFocusRingOnly);
[[NSBezierPath bezierPathWithRect:cellFrame] fill];
[controlView unlockFocus];
}
@end
in the app delegate's awakeFromNib don't forget to set the NSTableHeaderCell to Editable !
- (void)awakeFromNib
{
NSTableColumn *newCol = [[NSTableColumn alloc] initWithIdentifier:@"whatever"];
NBETableHeaderCell *hc = [[NBETableHeaderCell alloc] initTextCell:@"Default header text"];
[hc setEditable:YES];
[hc setUsesSingleLineMode:YES];
[hc setScrollable:NO];
[hc setLineBreakMode:NSLineBreakByTruncatingTail];
[newCol setHeaderCell:hc];
[self.tableView addTableColumn:newCol];
[self.tableView setDoubleAction:@selector(doubleClickInTableView:)];
}
for the rest, you were nearly there
after calling selectWithFrame, we customize the editor to have a nice white opaque background,
so that we don't see the textview beneath it
as for the focus ring : it is the cell's job,
we just set the cell in highlighted state so it knows it has to draw the ring now
- (void)doubleClickInTableView:(id)sender
{
NSInteger row = [_tableView clickedRow];
NSInteger column = [_tableView clickedColumn];
if(row == -1&& column >= 0)
{
NSTableColumn *tableColumn = [[_tableView tableColumns] objectAtIndex:column];
NSTableHeaderView *headerView = [_tableView headerView];
NBETableHeaderCell *headerCell = [tableColumn headerCell];
// cellEditor is basically a unique NSTextView shared by the window
// that adjusts its style to the field calling him
// it stands above the text field's view giving the illusion that you are editing it
// and if it has no background you will see the editor's NSTextView overlaying the TextField
// wich is why you have that nasty bold text effect in your screenshot
id cellEditor = [self.window fieldEditor:YES forObject:self.tableView];
[headerCell setHighlighted:YES];
[headerCell selectWithFrame:[headerView headerRectOfColumn:column]
inView:headerView
editor:cellEditor
delegate:headerCell
start:0
length:headerCell.stringValue.length];
[cellEditor setBackgroundColor:[NSColor whiteColor]];
[cellEditor setDrawsBackground:YES];
}
}
some more info about the field editor here : http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/WinPanel/Tasks/UsingWindowFieldEditor.html
the only thing missing now to make it complete is that the field editor's frame won't update if you resize the cell while editing…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With