如何实现NSCollectionView的上下文菜单

Eug*_*din 7 macos cocoa contextmenu nscollectionview

在我的OSX应用程序中,我有一个集合视图,它是一个子类NSCollectionView.

除了上下文菜单之外,我对这些事情都感到满意,我还想不通.

所以我想要的是:

  • 右键单击集合视图项将显示上下文菜单
  • 从菜单中选取的选项(删除,编辑等)将应用于执行点击的项目.

我知道怎么做,NSOutlineView或者NSTableView不是为了集合视图.

我无法弄清楚如何获取项目的索引点击.

有没有人对我如何实现这个有任何想法?

任何形式的帮助都非常感谢!

Ken*_*ses 5

我使用的一种方法是不尝试将上下文菜单操作应用于单击的一个特定项目,而是应用于所选项目。然后,我将单击的项目添加到选择中。

我将自定义视图用于收集项视图。自定义视图类item在其自己的集合视图项上有一个出口,我将其连接到NIB中。它还会覆盖-rightMouseDown:使该项目添加到选择中:

- (void) rightMouseDown:(NSEvent*)event
{
    NSCollectionView* parent = self.item.collectionView;
    NSUInteger index = NSNotFound;
    NSUInteger count = parent.content.count;
    for (NSUInteger i = 0; i < count; i++)
    {
        if ([parent itemAtIndex:i] == self.item)
        {
            index = i;
            break;
        }
    }

    NSMutableIndexSet* selectionIndexes = [[parent.selectionIndexes mutableCopy] autorelease];
    if (index != NSNotFound && ![selectionIndexes containsIndex:index])
    {
        [selectionIndexes addIndex:index];
        parent.selectionIndexes = selectionIndexes;
    }

    return [super rightMouseDown:event];
}
Run Code Online (Sandbox Code Playgroud)

如果您愿意,可以将其添加到选择中,而不是将其添加到选择中。如果是这样,请勿修改选择。如果不是,则仅用该项目替换选择(使其成为唯一的选择项目)。

或者,您可以在项目视图而不是集合视图上设置上下文菜单。然后,菜单项可以定位到项目视图或集合视图项目。

最后,您可以继承NSCollectionView并覆盖-menuForEvent:。您仍将呼叫super并返回返回的菜单,但是您可以借此机会在其位置记录事件和/或项目。要确定这一点,您可以执行以下操作:

- (NSMenu*) menuForEvent:(NSEvent*)event
{
    _clickedItemIndex = NSNotFound;
    NSPoint point = [self convertPoint:event.locationInWindow fromView:nil];
    NSUInteger count = self.content.count;
    for (NSUInteger i = 0; i < count; i++)
    {
        NSRect itemFrame = [self frameForItemAtIndex:i];
        if (NSMouseInRect(point, itemFrame, self.isFlipped))
        {
            _clickedItemIndex = i;
            break;
        }
    }

    return [super menuForEvent:event];
}
Run Code Online (Sandbox Code Playgroud)


Div*_*Lee 5

基本上我们所有的解决方案都能够满足需求,但我想对swift3+做一个补充,我认为这是一个完整的解决方案。

/// ??NSCollectionView?????????
class ANCollectionView: NSCollectionView {
    // ??????
    weak open var ANDelegate: ANCollectionViewDelegate?

    override func menu(for event: NSEvent) -> NSMenu? {
        var menu = super.menu(for: event);
        let point = self.convert(event.locationInWindow, from: nil)
        let indexPath = self.indexPathForItem(at: point);
        if ANDelegate != nil{
            menu = ANDelegate?.collectionView(self, menu: menu, at: indexPath);
        }
        return menu;
    }
}

/// ??NSCollectionView???
protocol ANCollectionViewDelegate : NSObjectProtocol {
    func collectionView(_ collectionView:NSCollectionView, menu:NSMenu?, at indexPath: IndexPath?) -> NSMenu?
}
Run Code Online (Sandbox Code Playgroud)

这是我写的一个扩展,希望对大家有帮助。