2009-08-21 15 views
18

NSOutlineViewの行を右クリックする方法を追加すると、オブジェクトや他のアクティビティを削除することができます。 (Apple Mailアプリでフォルダを右クリックしたときと同じように)NSOutlineViewにコンテキストセンシティブメニューを追加するにはどうすればいいですか(つまり右クリックメニュー)

私は半分しかありませんが、私はNSOutlineViewのサブクラスを持っていますので、右クリックをキャッチしてコンテキストメニューを表示できますマウスがクリックしている行ではなく、選択された行です。

@implementation NSContextOutlineView 

    - (NSMenu *)defaultMenu { 
     if([self selectedRow] < 0) return nil; 
     NSMenu *theMenu = [[[NSMenu alloc] initWithTitle:@"Model browser context menu"] autorelease]; 
     [theMenu insertItemWithTitle:@"Add package" action:@selector(addSite:) keyEquivalent:@"" atIndex:0]; 
     NSString* deleteItem = [NSString stringWithFormat: @"Remove '%i'", [self selectedRow]]; 
     [theMenu insertItemWithTitle: deleteItem action:@selector(removeSite:) keyEquivalent:@"" atIndex:1]; 
     return theMenu; 
    } 

    - (NSMenu *)menuForEvent:(NSEvent *)theEvent { 
     return [self defaultMenu]; 
    } 
@end 

申し訳ありませんが、答えが明らかな場合は、このオンラインまたはドキュメントのヘルプを見つけることができません。あなたはクリックをオンに発生した行を見つけることができますmenuForEvent方法で

- (NSMenu *)menuForEvent:(NSEvent *)theEvent { 
    NSPoint pt = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 
    id item = [self itemAtRow: [self rowAtPoint:pt]]; 
    return [self defaultMenuFor: item]; 
} 
+0

これを実行しないと、正常に動作するはずです。それはありませんか?もしそうでなければ、あなたはそれでどんな問題を抱えていますか? –

+4

また、独自のクラスにNSプレフィックスを使用しないでください。 AppleがNSContextOutlineViewクラスを将来のバージョンのCocoaに追加すると、クラスとクラスが衝突し、おそらくあなたのアプリは動かないでしょう。 –

+1

私は、投稿されたコードの問題は、selectedRowを使用し、正しい/ ctrl-clickが実行された行ではないことです。それは選択された行であってもなくてもよい。 – VoidPointer

答えて

21

:答えをvoidに

おかげで、これを使用して私をリードしています。あなたのdefaultMenuメソッドのパラメータとしてあることを渡すことができます - 多分defaultMenuForRowそれを呼び出す:今、あなたはあなたがイベントで見つかった行のメニューを構築することができ

-(NSMenu*)menuForEvent:(NSEvent*)evt 
{ 
    NSPoint pt = [self convertPoint:[evt locationInWindow] fromView:nil]; 
    int row=[self rowAtPoint:pt]; 
    return [self defaultMenuForRow:row]; 
} 

...

-(NSMenu*)defaultMenuForRow:(int)row 
{ 
    if (row < 0) return nil; 

    NSMenu *theMenu = [[[NSMenu alloc] 
           initWithTitle:@"Model browser context menu"] 
           autorelease]; 
    [theMenu insertItemWithTitle:@"Add package" 
          action:@selector(addSite:) 
        keyEquivalent:@"" 
         atIndex:0]; 
    [theMenu insertItemWithTitle:[NSString stringWithFormat:@"Remove '%i'", row] 
          action:@selector(removeSite:) 
        keyEquivalent:@"" 
         atIndex:0]; 
    // you'll need to find a way of getting the information about the 
    // row that is to be removed to the removeSite method 
    // assuming that an ivar 'contextRow' is used for this 
    contextRow = row; 

    return theMenu;   
} 

また、コメントで既に述べたように、自分のクラスではNSプレフィックスを使用しないでください。そこ将来の衝突の可能性があるプラスそれはあなたのコードを見ている皆を混乱させます - あなたが希望する場合、自分自身を含め:)このことができます

希望...

+0

ありがとうございます!こういったことの多くはとても簡単ですが、一度しか知りません! – Jacob

+0

これを達成するには、NSOutlineViewをサブクラス化する必要があります。この機能は既にデリゲートプロトコルに含まれている必要があります:-) –

-1

、あなたはにメニューを添付することができます個々の細胞ビューまたは行の表示とインターフェイスビルダーでそれを構築する:ここで

@implementation BSMotleyOutlineView 

-(NSMenu *)menuForEvent:(NSEvent *)event 
{ 
    NSPoint pt = [self convertPoint:[event locationInWindow] fromView:nil]; 
    NSInteger row = [self rowAtPoint:pt]; 
    if (row >= 0) { 
     NSTableRowView* rowView = [self rowViewAtRow:row makeIfNecessary:NO]; 
     if (rowView) { 
      NSInteger col = [self columnAtPoint:pt]; 
      if (col >= 0) { 
       NSTableCellView* cellView = [rowView viewAtColumn:col]; 
       NSMenu* cellMenu = cellView.menu; 
       if(cellMenu) { 
        return cellMenu; 
       } 
      } 
      NSMenu* rowMenu = rowView.menu; 
      if (rowMenu) { 
       return rowMenu; 
      } 
     } 
    } 
    return [super menuForEvent:event]; 
} 
@end 
8

は、サブクラスを使用していますので、あなたがデリゲートであなたのメニューを定義することができ、デフォルトNSOutlineDelegateを拡張スウィフト2.0の例です。

protocol MenuOutlineViewDelegate : NSOutlineViewDelegate { 
    func outlineView(outlineView: NSOutlineView, menuForItem item: AnyObject) -> NSMenu? 
} 

class MenuOutlineView: NSOutlineView { 

    override func menuForEvent(event: NSEvent) -> NSMenu? { 
     let point = self.convertPoint(event.locationInWindow, fromView: nil) 
     let row = self.rowAtPoint(point) 
     let item = self.itemAtRow(row) 

     if (item == nil) { 
      return nil 
     } 

     return (self.delegate() as! MenuOutlineViewDelegate).outlineView(self, menuForItem: item!) 
    } 

} 
関連する問題