2015-07-18 14 views
5

Praticamente tutto il NSStatusItem è stato deprecato per 10.10 e il comportamento del sottostante NSStatusBarButton sembra confondere.Mantenimento di un NSStatusBarButton evidenziato mentre il popover è visualizzato

Attualmente sto lavorando a un'applicazione nella barra dei menu. Quando l'utente fa clic sull'icona della barra dei menu per l'app, un metodo nella mia applicazione delegato viene chiamato tramite azione di destinazione che visualizza un NSPopover (o lo chiude se è già visibile) con alcune informazioni.

Normalmente, se è stato associato, ad esempio, un NSMenu con un NSStatusItem quando l'utente fa clic sull'icona della barra dei menu, l'icona rimane evidenziata in blu fino alla chiusura del menu. Allo stesso modo, facendo clic sull'icona del volume di sistema, si apre un dispositivo di scorrimento e si evidenzia l'icona blu finché la vista contenente il cursore non scompare.

Tuttavia, dal momento che sono l'unico ad aprire NSPopover, il sistema evidenzia invece l'icona blu sul mouse in basso, quindi lo restituisce normale al mouse su dopo che il mio metodo è stato chiamato. Significa che non c'è niente che possa sembrare su quel loop per mantenere il momento saliente. Voglio che l'icona continui a essere evidenziata al passaggio del mouse e ritorni alla normalità solo quando lo dico (cioè quando chiudo il mio popover.)

Non ho idea di come farlo. Ho provato con

[self.statusItem.button setHighlighted: YES]; 
//or [self.statusItem.button highlight: YES]; 

quando ricevo il mouse su evento nella mia app delegato e aprire il popover. Il problema è che il sistema ha ancora, apparentemente, evidenziato questo frame/loop dal precedente mouse down e immediatamente dopo averlo impostato su evidenziato, lo imposta su unhighlighted a causa del mouse. Posso aggirare questo incapsulando questo in un metodo ed eseguendo il metodo usando un timer o un selettore ritardato una frazione di secondo dopo. Questo mi consente di mantenere l'icona evidenziata ma introduce uno sfarfallio; l'icona viene evidenziata automaticamente quando il mouse si abbassa, quando il mouse si solleva lo illumina per un fotogramma, quindi il mio metodo lo evidenzia nuovamente.

Ho anche capito forse avrei potuto usare il deprecato setHighlightMode: e impostarlo su NO per evitare che l'icona venga evidenziata automaticamente sullo scatto, quindi utilizzando setHighlighted:/highlighted: impostarlo manualmente, ma che non funziona neanche. Allo stesso modo, ho pensato che forse questo avrebbe funzionato così:

NSButtonCell* cell = (NSButtonCell*)self.statusItem.button.cell; 
cell.highlightsBy = NSNoCellMask; 

Ma indipendentemente clic su di esso evidenzia automaticamente l'icona e dehighlights sul mouse in alto a destra dopo il mio metodo viene chiamato.

Fondamentalmente:

  1. Il comportamento indesiderato evidenziazione automatica di NSStatusBarButton interferisce con l'impostazione manuale dello stato evidenziato, a meno che non ritardo modificando manualmente che introduce una breve sfarfallio.
  2. L'unica cosa che sembra disattivare correttamente questo comportamento automatico è deprecato setHighlightMode:, ma questo sembra impedire l'evidenziazione, manuale o no.
  3. L'unico lavoro intorno sembra essere quella di aggiungere una visualizzazione secondaria alla NSButtonCell, aggiungere un listener di eventi per il mouse e quindi impostare lo stato clou della superview come da qui: NSStatusBarButton keep highlighted ma potrebbe pensare che ci sarebbe un modo più semplice per ... disabilitare l'evidenziazione automatica del tutto.

tl; dr: C'è un modo per me di ottenere facilmente il pieno controllo su quando e quando non è il mio menu barra delle icone è evidenziata, in modo che io possa avere evidenziare naturalmente mentre il mio NSPopover è visualizzati?

+1

Alcune cose da provare: 1) Aggiungere un menu vuoto all'elemento. 2) Chiama '-popUpStatusItemMenu:' con un menu vuoto. 3) Esegui un loop di messaggi interno ('[NSApp nextEventMatchingMask: ...]' e '[NSApp sendEvent: ...]') per impedire che il gestore di clic venga restituito fino a quando il pop-over non viene eliminato. –

+0

Proverò quelli quando avrò tempo, grazie. – Metabble

+0

Non andare con il menu vuoto. Chiamare popUp non sembra fare nulla. Sembra anche che il menu vuoto mangi le chiamate che normalmente verrebbero inviate anche al selettore .action dell'elemento di stato. Non sono sicuro che il ciclo dei messaggi interni funzionerebbe, ma non sarebbe molto più semplice della soluzione di sottoview nel post collegato ... – Metabble

risposta

7

Ho risolto questo problema non impostando la proprietà del selettore di azioni NSStatusItem. Invece ho usato NSEvent 's addLocalMonitorForEventsMatchingMask:handler:. Nel blocco gestore, controllo se il numero event.locationInWindow è compreso tra .bounds. Se è così, invio il messaggio allo .action manualmente e quindi restituisco nil per impedire la trasmissione dell'evento. Se non rientra nei limiti dell'icona di stato, restituisco event in modo che venga trasmesso normalmente. Nel mio metodo di gestione dei clic, utilizzo [self.statusItem.button highlight: YES/NO] quando il mio popover viene visualizzato/chiuso.

TL; DR:

In applicationDidFinishLaunching:

__block AppDelegate* appDelegate = self; 
[NSEvent addLocalMonitorForEventsMatchingMask: NSEventMaskFromType(NSLeftMouseDown) handler:^NSEvent* (NSEvent* event){ 
    if (NSPointInRect(event.locationInWindow, appDelegate.statusItem.button.bounds)){ 
     [appDelegate clickedMenuBarIcon: event]; 
     return nil; 
    } 
    return event; 
}]; 

In clickedMenuBarIcon: posso quindi impostare lo stato di evidenziazione. Dal momento che ho restituito nil nel mio blocco gestore ha impedito l'inoltro dell'evento, quindi l'evidenziazione automatica non si verifica mai e posso eseguirla manualmente.


Se ci sono dei bug associati a questo, gradirei qualsiasi consiglio.

+0

forse testare 'e.window == statusItem.button.window' è più affidabile? – Nozama

Problemi correlati