Search code examples
cocoanstextfielddouble-clicknseventclick-counting

Change NSTextField's behavior for multiple clicks in a row


I have a NSTextField which is nested by a custom view and I want to change the default behavior of multiple clicks in a row (double click, tripple click etc.), similarly to the behavior of text nodes MindNode (see the image below).

I want the first click to "activate" the text field and then go on from the beginning (like reseting the click count of the event).

I have following ideas, but I don't know how to implement them and if they actually make sense:

  • Somehow change the time using +[NSEvent doubleClickInterval] and slow down the second click.
  • Reduce the click count programmatically?
  • Make the NSTextField non-selectable using -hitTest:, forward the click to the superview, change some parameter of the text field and accept the next clicks. In this case, the click count of the second click is still 2.
  • Override -mouseDown: and not call super. This breaks the NSTextField's selection functionality.

I hope there is an easier way to achieve this, which I have overlooked.

Thanks for your answers!

Here is a graphical representation of the problem: Changing the behavior of multiple click for NSTextField


Solution

  • I've solved it by subclassing NSTextField and decrementing click count of mouse down events programmatically. Using a boolean property of the subclass I am able to turn this special behavior on and off.

    - (void)mouseDown:(NSEvent *)theEvent
    {
        if (self.specialBehavior) {
            theEvent = [NSEvent mouseEventWithType:theEvent.type
                                          location:theEvent.locationInWindow
                                     modifierFlags:theEvent.modifierFlags
                                         timestamp:theEvent.timestamp
                                      windowNumber:theEvent.windowNumber
                                           context:theEvent.context
                                       eventNumber:theEvent.eventNumber
                                        clickCount:theEvent.clickCount - 1
                                          pressure:theEvent.pressure];
        }
    
        [super mouseDown:theEvent];
    }
    

    To simplify this long method call, I wrote a category method for NSEvent which decrements the click count of an event.