Pergunta

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

Foi útil?

Solução 2

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.

Outras dicas

I would do this by embedding the text field and a custom view in an NSBox, which would be set to the custom type, initially with no background color or border (so it would be invisible). Initially, the custom view would be on top and it would have a mouseDown: method that would receive the first click. In that method you could rearrange the box's subviews so that the text field would then be on top and receive the next clicks. If you wanted, the box could be somewhat bigger than the text field so you could give it a background color or other drawing that would look like a custom activation ring around the text field. In the text field's controlTextDidEndEditing: method, you could reset the system back to the beginning state, so it would be ready for the next time you click on it.

After Edit: Here is the code I'm using in my overlay class:

@implementation Overlay

static NSComparisonResult rdComparator( NSView *view1, NSView *view2, void *context ) {
    if ([view1 isKindOfClass:[NSTextField class]])
        return NSOrderedDescending;
    else if ([view2 isKindOfClass:[NSTextField class]])
        return NSOrderedAscending;
    return NSOrderedSame;
}


-(void)mouseDown:(NSEvent *)theEvent {
    self.box.fillColor = [NSColor redColor];
    NSView *contentView = self.box.subviews.lastObject;
    [contentView sortSubviewsUsingFunction:rdComparator context:nil];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top