NSPathControl是否包含路径的每个组件的弹出窗口?

时间:2012-10-03 12:41:22

标签: objective-c cocoa nspathcontrol

Apple's sample code和阅读the docs,我发现无法将NSPathControl配置为与例如NSPathControlDelegate相似' 跳栏'在Xcode编辑器窗口中:

Xcode Editor custom path control

即。让它代表一个路径(或其他类型的层次结构),并使路径的每个组件成为一个可点击的弹出窗口来导航层次结构..?

使用{{1}}听取点击并在临时窗口中显示菜单时,是否有运气伪造此类行为?

看起来像一个普通的设计,人们甚至可以期待一些OSS实现 - 但没有这样的运气,但谷歌搜索它..

2 个答案:

答案 0 :(得分:4)

我创建了NSPathControl的子类,以便我可以使用mouseDown:在正确的位置弹出组件单元格的上下文菜单。我还在菜单中添加了一个代表,以便按需创建更深层次的菜单。

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

    NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];


    NSPathCell *cell = self.cell;
    NSPathComponentCell *componentCell = [cell pathComponentCellAtPoint:point
                                                              withFrame:self.bounds
                                                                 inView:self];

    NSRect componentRect = [cell rectOfPathComponentCell:componentCell
                                               withFrame:self.bounds
                                                  inView:self];

    NSMenu *menu = [componentCell menuForEvent:event
                                        inRect:componentRect
                                        ofView:self];

    if (menu.numberOfItems > 0) {
        NSUInteger selectedMenuItemIndex = 0;
        for (NSUInteger menuItemIndex = 0; menuItemIndex < menu.numberOfItems; menuItemIndex++) {
            if ([[menu itemAtIndex:menuItemIndex] state] == NSOnState) {
                selectedMenuItemIndex = menuItemIndex;
                break;
            }
        }

        NSMenuItem *selectedMenuItem = [menu itemAtIndex:selectedMenuItemIndex];
        [menu popUpMenuPositioningItem:selectedMenuItem
                            atLocation:NSMakePoint(NSMinX(componentRect) - 17, NSMinY(componentRect) + 2)
                                inView:self];
    }
}

- (NSMenu *)menuForEvent:(NSEvent *)event {
    if (event.type != NSLeftMouseDown) {
        return nil;
    }
    return [super menuForEvent:event];
}

答案 1 :(得分:2)

我稍微扩展了Stephan的答案,以适应懒洋洋地加载菜单项。我创建了一个小协议来调用菜单,而不是必须提前为每个单元格构建菜单:

NSPathControlExtended.h

@protocol NSPathControlExtendedDelegate <NSPathControlDelegate>

@required
- (NSMenu *)pathControl:(NSPathControl *)pathControl menuForCell:(NSPathComponentCell *)cell;

@end

@interface NSPathControlExtended : NSPathControl

@property (weak) id <NSPathControlExtendedDelegate> delegate;

@end

NSPathControlExtended.m

#import "NSPathControlExtended.h"

@implementation NSPathControlExtended

@synthesize delegate;

- (instancetype)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    // Drawing code here.
}

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

    NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];


    NSPathCell *cell = self.cell;
    NSPathComponentCell *componentCell = [cell pathComponentCellAtPoint:point
                                                              withFrame:self.bounds
                                                                 inView:self];

    NSRect componentRect = [cell rectOfPathComponentCell:componentCell
                                               withFrame:self.bounds
                                                  inView:self];

    NSMenu *menu = [delegate pathControl:self menuForCell:componentCell];

    if (menu.numberOfItems > 0) {
        NSUInteger selectedMenuItemIndex = 0;
        for (NSUInteger menuItemIndex = 0; menuItemIndex < menu.numberOfItems; menuItemIndex++) {
            if ([[menu itemAtIndex:menuItemIndex] state] == NSOnState) {
                selectedMenuItemIndex = menuItemIndex;
                break;
            }
        }

        NSMenuItem *selectedMenuItem = [menu itemAtIndex:selectedMenuItemIndex];
        [menu popUpMenuPositioningItem:selectedMenuItem
                            atLocation:NSMakePoint(NSMinX(componentRect) - 17, NSMinY(componentRect) + 2)
                                inView:self];
    }
}

- (NSMenu *)menuForEvent:(NSEvent *)event {
    if (event.type != NSLeftMouseDown) {
        return nil;
    }
    return [super menuForEvent:event];
}

@end