【问题标题】:NSPathControl with popups for each component of the path?NSPathControl 与路径的每个组件的弹出窗口?
【发布时间】:2012-10-03 12:41:21
【问题描述】:

Apple's sample code 和阅读the docs 我看不出有什么办法可以将NSPathControl 配置为类似于例如Xcode 编辑器窗口中的“跳转栏”:

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

任何人有幸使用NSPathControlDelegate 监听点击并在临时窗口中显示菜单来伪造此类行为?

似乎是一种常见的设计,人们甚至会期望一些 OSS 实现 - 但还没有这样的运气,还没有用谷歌搜索它..

【问题讨论】:

    标签: objective-c cocoa nspathcontrol


    【解决方案1】:

    我创建了一个 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];
    }
    

    【讨论】:

      【解决方案2】:

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

      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
      

      【讨论】:

      • selectedMenuItemIndex 将始终为 0。
      猜你喜欢
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多