Question

I am using MonoMac/C# and have an NSOutlineView where some of the items are editable. So if you select an item and then click it again (slow double click) the NSTextField of the row enter edit mode. My problem is that this happens even if you right-click the item. You can even mix left-clicks and right-clicks to enter edit mode.

This is pretty annoying since you would sometime select a row and then right-click it, then a second after the context menu appears, the row enter edit mode.

Is there a way to restrict either the NSOutlineView or the NSTextFields inside it, to only enter edit mode using the left mouse button (in addition to pressing Enter while the row is selected)?

Thanks!

Was it helpful?

Solution

The approach I used was overriding the "RightMouseDown" method [1, 2]. After attempting to do so in the NSOutlineView and the NSTableCellView with no luck, the trick was to do go down to the lower level in the hierarchy to the NSTextField. It turns out the NSWindow object uses SendEvent to dispatch events directly to the view that is closest to the mouse event [3], so the events proceed from innermost view to outermost view.

You can change the desired NSTextField in the OutlineView in Xcode to use this custom class:

public partial class CustomTextField : NSTextField
{
    #region Constructors

    // Called when created from unmanaged code
    public CustomTextField (IntPtr handle) : base (handle)
    {
        Initialize ();
    }
    // Called when created directly from a XIB file
    [Export ("initWithCoder:")]
    public CustomTextField (NSCoder coder) : base (coder)
    {
        Initialize ();
    }
    // Shared initialization code
    void Initialize ()
    {
    }

    #endregion

    public override void RightMouseDown (NSEvent theEvent)
    {
        NextResponder.RightMouseDown (theEvent);
    }
}

Because "RightMouseDown" does not call base.RightMouseDown(), the click is completely ignored by the NSTextField logic. Calling NextResponder.RightMouseDown() allows the event to percolate up through the view hierarchy so that it can still trigger the context menu.

[1]https://developer.apple.com/library/mac/documentation/cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html#//apple_ref/occ/instm/NSView/rightMouseDown: [2]https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/HandlingMouseEvents/HandlingMouseEvents.html [3]https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW21

OTHER TIPS

The answer above by @salgarcia can be adapted to native Swift 3 code, as follows:

import AppKit

class CustomTextField: NSTextField {

    override func rightMouseDown(with event: NSEvent) {

        // Right-clicking when the outline view row is already
        // selected won't cause the text field to go into edit 
        // mode. Still can be edited by pressing Return while the
        // row is selected, as long as the textfield it is set to 
        // 'Editable' (in the storyboard or programmatically):

        nextResponder?.rightMouseDown(with: event)
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top