Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSCollectionView doesn't popup context menu?

I've bounded the menu to the NSCollectionView in interface builder. But when I CTRL+click (right click) on it the menu is not showing.

I've tried adding some method to the NSCollectionView subclass. None of them is invoked:

+ (NSMenu*)defaultMenu
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
- (void)rightMouseDown:(NSEvent *)theEvent
- (void)sendEvent:(NSEvent *)theEvent

The only method which is invoked is:

- (NSView *)hitTest:(NSPoint)aPoint

Which means that the NSCollectionView receives the mouse events.

I've also tried to add the same methods to the subclass of NSCollectionViewItem, and the result is the same. Only hitTest: is called.

like image 750
aneuryzm Avatar asked Feb 11 '16 10:02

aneuryzm


3 Answers

I had the same issue with the "new" NSCollectionView. The contextual menu is set up in the xib, and it is actually correctly triggered by an actual right-click on the mouse, and also by double-finger tab on the trackpad (if the user has set that option in the System Preferences), but not by control-click. Thus it seems like a legitimate bug or limitation with NSCollectionView, maybe dependent on how it is set up.

In any case, here is a shorter solution, this one in Swift, that assumes you have otherwise set up the contextual menu using the menu outlet for the collection view (or you have it set up as outlined in Apple's documentation).

You will need to create a subclass of NSCollectionView and choose the subclass for the collection view in the xib. Here is the code for the subclass:

import Cocoa

class MyCollectionView: NSCollectionView {

    /// Fixes the behavior of collection view with control-click, that does not properly trigger the contextual menu.
    override func mouseDown(with event: NSEvent) {
        super.mouseDown(with: event)
        if event.type == .rightMouseDown || event.modifierFlags.contains(.control) {
            rightMouseDown(with: event)
        }
    }

}
like image 62
charles Avatar answered Oct 23 '22 16:10

charles


This works for me:

@interface MyCollectionView : NSView
-(void)mouseDown:(NSEvent *)theEvent;
@end

@implementation MyCollectionView

-(void)mouseDown:(NSEvent *)theEvent
{

    NSMenu *theMenu = [[NSMenu alloc] initWithTitle:@"Contextual Menu"];
    [theMenu insertItemWithTitle:@"Beep" action:@selector(beep) keyEquivalent:@"" atIndex:0];
    [theMenu insertItemWithTitle:@"Honk" action:@selector(honk) keyEquivalent:@"" atIndex:1];

    [NSMenu popUpContextMenu:theMenu withEvent:theEvent forView:self];

    [super mouseDown:theEvent];

}

-(void)beep{

}

-(void)honk{

}

@end

I hope this helps.

like image 1
Jonas Avatar answered Oct 23 '22 15:10

Jonas


Subclass the NSCollectionView

class OSCollectionView: NSCollectionView {

    
    override func menu(for event: NSEvent) -> NSMenu? {
        print("menu() called")
        let menu = NSMenu()
        menu.addItem(NSMenuItem(title: "Create a clone", action: #selector(clone(_:)), keyEquivalent: ""))
        return menu
    }
    
    
    @objc
    func clone(_ sender: Any){
        //editDelegate?.terminateAndReplace(self)
        print("Clone item")
    }
}
like image 1
Duncan Groenewald Avatar answered Oct 23 '22 14:10

Duncan Groenewald