Christoffer Reijer Christoffer Reijer - 3 months ago 31
C# Question

Prevent editing of NSTextField by double right-click

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!

Answer Source

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