2017-07-29 5 views
1

Tout le monde a discuté sur la façon de se débarrasser du contour bleu pendant le clic droit ... mais moi.NSOutlineAfficher comment afficher le contour bleu pendant le clic droit

Au lieu de cela, J'essaie d'afficher le contour bleu.

Je n'ai pas obtenu de contour lorsque j'ai cliqué avec le bouton droit sur ma ligne de vue générale. Le menu est apparu mais le contour n'était pas.

Vous pouvez voir que le contour bleu est pas visible dans cette image ci-dessous:

enter image description here



Voici ce que je suis en train de réaliser.

Blue outline


Mise à jour

Voilà comment je mis à exécution les NSMenu. J'ai sous-classé le NSOutlineView et fait un nouveau protocole pour remplacer NSOutlineViewDelegate.

Cette idée était de rendre simple en laissant le NSOutlineView demander le NSMenu pour chaque article, afin que nous puissions implémenter un menu différent pour chaque article. Cela fonctionne mais la vue de contour bleue n'apparaît pas pendant le clic droit.

KRMenuOutlineView.swift

import Cocoa 

@objc protocol KRMenuOutlineViewDelegate: NSOutlineViewDelegate { 
    // This method will ask NSMenu for each item in outline view 
    func outlineView(_ outlineView: KRMenuOutlineView, menuFor item: Any, event: NSEvent) -> NSMenu? 
} 

class KRMenuOutlineView: NSOutlineView { 

    override var delegate: NSOutlineViewDelegate? { 
     didSet { 
      if let newValue = delegate { 
       /* 
       * Swift doesn't support overriding inherited properties with different type 
       * like Objective C Does, therefore we need internal delegate. 
       */ 
       internalDelegate = unsafeBitCast(newValue, to: KRMenuOutlineViewDelegate.self) 
      } else { 
       internalDelegate = nil 
      } 
     } 
    } 

    private var internalDelegate: KRMenuOutlineViewDelegate? 

    override func menu(for event: NSEvent) -> NSMenu? { 
     let point = self.convert(event.locationInWindow, from: nil) 
     if let item = self.item(atRow: self.row(at: point)) { 
      return self.internalDelegate?.outlineView(self, menuFor: item, event: event) 
     } 
     return super.menu(for: event) 
    } 
} 

Puis, je l'utilise dans mon contrôleur de vue comme celui-ci:

KRTreeViewController.swift

extension KRTreeViewController: KRMenuOutlineViewDelegate { 
    func outlineView(_ outlineView: KRMenuOutlineView, menuFor item: Any, event: NSEvent) -> NSMenu? { 
      let menu = NSMenu(title: "Contextual Menu") 
      menu.delegate = self 

      let key = String(utf16CodeUnits: [unichar(NSBackspaceCharacter)], count: 1) as String 
      let deleteMenuItem = menu.addItem(withTitle: "Delete", 
               action: #selector(didClickMenuItem(_:)), 
               keyEquivalent: key) 
      deleteMenuItem.representedObject = myItem 
      deleteMenuItem.target = self 

      return menu 
    } 

    @objc fileprivate func didClickMenuItem(_ menuItem: NSMenuItem) { 
     // ... 
    } 
} 
+0

Nous ne savons pas ce que vous avez fait pour faire disparaître le contour bleu. Comment avez-vous implémenté le menu contextuel? Avez-vous fait quelque chose pour modifier un comportement par défaut de 'NSOutlineView'? – Willeke

+0

@Willeke J'ai mis à jour ma question. –

+0

Essayez d'appeler 'super.menu (for: event)' avant de retourner votre propre menu. – Willeke

Répondre

1

Comment afficher correctement un contexte menu:

Si vous avez créé votre menu à l'aide d'un storyboard: Tout d'abord, allez dans le storyboard et ajoutez le menu au viewController qui contient le outlineView. Puis en faire un @IBOutlet afin que vous puissiez le référencer plus tard.

Dans une méthode comme viewDidLoad(), ajoutez le menu à outlineView en appelant

outlineView.menu = myMenu 

où myMenu peut être soit celui que vous avez créé dans Interface Builder ou dans le code.

Vous pouvez exécuter l'application maintenant et devrait voir le contour bleu autour de la cellule.

Le problème est maintenant que vous ne savez pas sur quelle cellule l'utilisateur a cliqué. Pour résoudre ce problème, définissez-vous en tant que délégué de myMenu et adoptez le protocole NSMenuDelegate.

func menuNeedsUpdate(_ menu: NSMenu) { 
    let row = self.outlineView.clickedRow 

    guard row != -1 else { return } 
    for item in menu.items { 
     item.representedObject = row 
    } 
} 

Ici, vous pouvez faire ce dont vous avez besoin.Cette implémentation définit rowIndex comme representatedObject de chaque élément de menu. Gardez à l'esprit que cela ne fonctionne que sur les outlineViews statiques (ceux qui ne changent pas en arrière-plan) et les menus qui ne font qu'un niveau de profondeur.

Vous pouvez également stocker l'index ou l'objet représenté par la cellule (si outlineView n'est pas statique) dans une variable locale.

+0

Merci pour votre réponse, en utilisant cette solution, comment pouvons-nous limiter à montrer le menu seulement pour l'article spécifique dans 'NSOutlineView'? J'ai également mis à jour ma question montrant l'implémentation du code. –

+0

Que faire si je ** n'ai pas ** créé le menu en utilisant un storyboard? J'ai commenté tous les dépassements dans ma sous-classe de vue de plan et le contour bleu ne montre toujours pas ... –

+0

@Nicolas Miari: Vous pouvez simplement créer le menu dans le code. Par exemple, dans 'viewDidLoad()', créez votre menu et appelez 'outlineView.menu = myMenu'. Le reste devrait être comme décrit ci-dessus. – mangerlahn