I have text fields inside a custom view inside an NSOutlineView
. Editing one of these cells requires a single click, a pause, and another single click. The first single click selects the table view row, and the second single click draws the cursor in the field. Double-clicking the cell, which lets you edit in a cell-based table view, only selects the row.
The behavior I want: one click to change the selection and edit.
What do I need to override to obtain this behavior?
I've read some other posts:
- The
NSTextField
flyweight pattern wouldn't seem to apply to view-based table views, where the cell views are all instantiated from nibs. - I tried subclassing
NSTextField
like this solution describes, but my overriddenmouseDown
method is not called. OverriddenawakeFromNib
andviewWillDraw
(mentioned in this post) are called. Of coursemouseDown
is called if I put the text field somewhere outside a table view.
By comparison, a NSSegmentedControl
in my cell view changes its value without first selecting the row.
Here's the working solution adapted from the accepted response:
In outline view subclass:
-(void)mouseDown:(NSEvent *)theEvent {
[super mouseDown:theEvent];
// Forward the click to the row's cell view
NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
NSInteger row = [self rowAtPoint:selfPoint];
if (row>=0) [(CellViewSubclass *)[self viewAtColumn:0 row:row makeIfNecessary:NO]
mouseDownForTextFields:theEvent];
}
In table cell view subclass:
// Respond to clicks within text fields only, because other clicks will be duplicates of events passed to mouseDown
- (void)mouseDownForTextFields:(NSEvent *)theEvent {
// If shift or command are being held, we're selecting rows, so ignore
if ((NSCommandKeyMask | NSShiftKeyMask) & [theEvent modifierFlags]) return;
NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
for (NSView *subview in [self subviews])
if ([subview isKindOfClass:[NSTextField class]])
if (NSPointInRect(selfPoint, [subview frame]))
[[self window] makeFirstResponder:subview];
}
mouseDownForTextFields
method instead. I could connect all the get fields to an outlet collection, which I'd have to do for each view style (seven of them). Is there a way I can get them all programmatically, instead? – Triboluminescence