Différer l'ouverture d'un PopUpMenu
Bonjour,
J'expérimente le même problème que celui rencontré (en 2005) ici:
http://lists.apple.com/archives/cocoa-dev/2005/Nov/msg02088.html
Il n'a malheureusement pas reçu de réponse en huit ans. En deux mots:
Quand vous placez un NSPopUpButtonCell dans une NSTableView, le popUp s'ouvre AVANT que la sélection dans la tableView ait changé.
Si vous faites dépendre le contenu du popUp de la sélection de la ligne dans la tableView, vous vous retrouvez avec un temps de retard.
Solution 1: différer l'ouverture du popUp avec un block qui appelle [super] quelques nanosecondes plus tard. Mais là je sèche parce que je ne sais pas quelle méthode surcharger.
Solution 2: farcir le popUp avec d'autres bindings que ceux que j'utilise actuellement (le popUp contient le NSSet de l'entité sélectionnée dans la table, je passe donc par un contrôleur différent de celui de la table et je branche son content set à myTable.selection.theSet.
Voyez-vous autre chose à faire?
Réponses
Bonjour,
Je ne vois pas le souci, que la ligne soit déjà sélectionner ou pas il faudra remplir le popupmenu avec les données en conséquence !
Une alternative serait que quand l'utilisateur clique sur le popupmenu alors qu'il n'est pas sélectionner alors tu la sélectionnes et tu annule l'apparition du menu ?
devulder,
Le fait est que lorsque l'utilisateur clique sur le pop menu de la ligne " mettons, 3 " alors que la ligne 2 est sélectionnée, le pop menu affiche le contenu propre à la deux, puis la ligne 3 est sélectionnée. Si je reclique au même endroit, le contenu du pop up sera correct.
Le problème est que le menu est bindé sur la sélection de la table. Or cette sélection n'a pas encore été mise à jour (probablement que le pop menu intercepte l'event et réagit immédiatement, puis rend la main et la tableView change alors la sélection).
Pour répondre à ta question, c'est partiellement ça, sauf que je ne veux pas annuler l'apparition du menu mais la différer (disons la reporter jusqu'à la fin de la boucle d'événement en cours). ça je sais faire, mais je ne vois pas quelle méthode différer au juste, ni même si c'est possible...
vu sur le net, cette méthode pour afficher ton propre menu et t'affranchir des bindings
une possible piste ?
On doit pouvoir faire la même chose dans la méthode déléguée:
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)col row:(NSInteger)rowIndex
Les valeurs de bind de la tableView ne sont pas selection (qui représente la selection) mais arrangedObjects qui représente les lignes.
Relis la doc de binding sur les tableView.
Sors nous un sample code si tu n'y arrive pas.
Bon je reprends.
@mpergand et devulder:
Je pense qu'on peut s'en tirer sans la datasource
@yoann:
Ce n'est pas le contrôleur de la NSTableView que je bonde à .selection, mais le contrôleur du popMenu. Si je binde la colonne à myTable.arrangedObjects.entitesB, j'obtiens une bouillie (un NSSet brut) qui n'entre pas dans un popUpMenuCell... ou du moins, je n'arrive pas à l'y faire tenir. Je définis donc un contrôleur séparé, dont je binde le contentSet à l'entité A sélectionnée, puis je binde le popUp à ce contrôleur.
Alors, où est-ce que je me goure?
Il ne faut pas travailler avec NSSet sur les binding, ce n'est pas fait pour.
Tiens, voilà un exemple fonctionnel si j'ai bien compris ce que tu cherche à faire.
Merci yoann d'avoir pris le temps de rédiger ce petit exemple !
(Un bémol pour le "fonctionnel", j'obtiens
quand je touche au popup, mais bon...)
Oui et non... Après tout, il y a bien un "content set" possible dans les bindings d'un contrôleur. Le seul souci, c'est que le NSSet est désordonné, mais il a d'autres avantages, comme l'unicité des contenus. L'ordre ne m'intéresse pas dans ce cas particulier, et si jamais il doit y avoir un NSOrderedSet (jamais essayé).
Une précision: mon code produit exactement le résultat attendu, il n'y a que cette histoire de popup qui doit bénéficier d'une priorité de premier ordre pour passer devant tout le monde comme ça. Probablement voulu par Apple pour garantir la réactivité de l'interface...
Petit erreur du fait de l'utilisation de la nouvelle syntaxe des dictionnaires. Les item représentant les lignes n'étaient pas mutable. Corrige de cette manière :
Oui mais non. Je te parle d'expérience ici. Les binding s'arrange assez mal des NSSet. Et l'ordonnancement de ces données est obligatoire pour l'affichage.
Si tu tiens absolument à garder un NSSet en source il faut le convertir avec un valueTransformer en array pour les binding et faire particulièrement attention à la gestion de l'item sélectionné.
Ton code produit exactement le résultat attendu sauf quand il ne le fait pas, donc il ne marche pas. Le problème est que tu t'y prend mal pour faire marcher la chose, c'est tout.
Fait les choses comme je te le conseil et tu verra que ça marchera.
Ah ça... Je n'aurais pas ouvert ce sujet sinon
Je vais reprendre tout ça à tête reposée en adaptant ton exemple (le tien travaille avec un array unique, moi j'en ai deux à gérer).
P.S. Mon popUp ne fait qu'indiquer la liste des entités B auxquelles appartient l'entité A sélectionnée, et non d'en sélectionner une (de toute façon c'est une relation plusieurs-à -plusieurs).
Mais il me vient à l'esprit en relisant tout ça qu'en fait il serait peut-être plus conforme, HIG parlant, d'utiliser un popOver (le problème c'est que je devrais le mettre à la bonne taille moi-même pour afficher la liste). Sans compter que je n'aurais plus à me battre avec cette fichue popUpMenuCell...
Affaire à suivre.