Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mouseDown: in a custom NSTextField inside an NSTableView

I have a view-based NSTableView. Each view in the table has a custom text field.

I'd like to fire an action when the user clicks on the text field (label) inside the table's view (imagine having a hyperlink with a custom action in each table cell).

I've created a basic NSTextField subclass to catch mouse events. However, they only fire on the second click, not the first click.

I tried using an NSButton and that fires right away.

Here's the code for the custom label:

@implementation HyperlinkTextField

- (void)mouseDown:(NSEvent *)theEvent {
    NSLog(@"link mouse down");
}

- (void)mouseUp:(NSEvent *)theEvent {
    NSLog(@"link mouse up");
}

- (BOOL)acceptsFirstResponder {
    return YES;
}

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
    return YES;
}
@end
like image 538
Mark Avatar asked Mar 23 '12 14:03

Mark


3 Answers

Had the same problem. The accepted answer here didn't work for me. After much struggle, it magically worked when I selected "None" as against the default "Regular" with the other option being "Source List" for the "Highlight" option of the table view in IB!

Edit: The accepted answer turns out to be misleading as the method is to be overloaded for the table view and not for the text field as the answer suggests. It is given more clearly at https://stackoverflow.com/a/13579469/804616 but in any case, being more specific feels a bit hacky.

like image 90
trss Avatar answered Nov 09 '22 12:11

trss


It turned out that NSTableView and NSOultineView handle the first responder status for NSTextField instances differently than for an NSButton.

The key to get the label to respond to the first click like a button is to overwrite [NSResponder validateProposedFirstResponder:forEvent:] to return YES in case of my custom text field class.

Documentation:

http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html#//apple_ref/occ/instm/NSResponder/validateProposedFirstResponder:forEvent:

like image 7
Mark Avatar answered Nov 09 '22 11:11

Mark


The behavior that you're seeing is because the table view is the first responder, which it should be or the row won't change when you click on the label -- this is the behavior that a user expects when clicking on a table row. Instead of subclassing the label, I think it would be better to subclass the table view and override mouseDown: there. After calling the super's implementation of mouseDown:, you can do a hit test to check that the user clicked over the label.

@implementation CustomTable

- (void)mouseDown:(NSEvent *)theEvent
{
    [super mouseDown:theEvent];
    NSPoint point = [self convertPoint:theEvent.locationInWindow fromView:nil];
    NSView *theView = [self hitTest:point];
    if ([theView isKindOfClass:[NSTextField class]])
    {
         NSLog(@"%@",[(NSTextField *)theView stringValue]);
    }
}

@end
like image 1
rdelmar Avatar answered Nov 09 '22 10:11

rdelmar