2009-08-21 11 views
18

Wie fügen Sie die Fähigkeit hinzu, mit der rechten Maustaste auf eine Zeile in einem NSOutlineView zu klicken, damit Sie ein Objekt oder eine andere Aktivität löschen können. (zB wenn man mit der rechten Maustaste auf einen Ordner in der Apple Mail App klickt)Wie fügen Sie NSOutlineView Kontextmenü hinzu (dh Rechtsklickmenü)

Ich denke, ich bin halb da, ich habe eine Unterklasse von NSOutlineView, die es mir erlaubt, den Rechtsklick zu erfassen und ein Kontextmenü basierend auf dem anzuzeigen die ausgewählte Zeile und nicht die Zeile, auf die die Maus klickt.

Entschuldigung, wenn die Antwort offensichtlich ist, kann ich gerade keine Hilfe online oder in der Dokumentation finden.

Vielen Dank für die Antwort auf die Leere, es mir, dies zu verwenden führen:

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

Ohne läuft es, das sieht aus wie es sollte gut funktionieren. Nicht wahr? Wenn nicht, welches Problem haben Sie damit? –

+4

Verwenden Sie das Präfix NS auch nicht für Ihre eigenen Klassen. Wenn Apple einer zukünftigen Version von Cocoa eine NSContextOutlineView-Klasse hinzufügt, kollidieren ihre Klasse und Ihre Klasse, und Ihre App wird wahrscheinlich nicht ausgeführt. –

+1

Ich denke, das Problem mit dem geposteten Code ist, dass es die selectedRow verwendet und nicht die Zeile, auf der der rechte/ctrl-Klick ausgeführt wurde. Das kann die ausgewählte Zeile sein oder nicht. – VoidPointer

Antwort

21

In Ihrem menuForEvent Methode können Sie herausfinden, welche Zeile der Klick aufgetreten auf. Sie können, dass als Parameter an Ihre Standardmenü Methode übergeben - es vielleicht nennen defaultMenuForRow:

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

Jetzt können Sie das Menü für die Reihe bauen Sie für den Fall gefunden ...

-(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;   
} 

Auch, wie bereits in den Kommentaren erwähnt, sollten Sie nicht wirklich das NS-Präfix für Ihre eigenen Klassen verwenden. Es gibt ein Potential für einen Zusammenstoß in der Zukunft plus es alle verwirren, die an Ihrem Code sucht - auch selbst :)

hoffe, das hilft ...

+0

Danke so sehr! So viele Dinge sind so einfach zu machen, aber nur wenn du weißt wie! – Jacob

+0

Sad müssen wir 'NSOutlineView' ableiten, um dies zu erreichen. Diese Funktionalität sollte bereits im Delegate-Protokoll enthalten sein :-) –

-1

Wenn Sie es vorziehen, können Sie das Menü anhängen können die einzelne Zelle Ansicht oder Zeilenansicht und baut es mit Interface Builder:

@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

Hier ist ein Swift 2.0 Beispiel, die eine Unterklasse verwendet und erweitert die Standard-NSOutlineDelegate so können Sie Ihre Menüs in den Delegaten definieren.

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!) 
    } 

} 
Verwandte Themen