Gestion du menu avec une application NSDocument based

olofolof Membre
19:08 modifié dans API AppKit #1
'jour !

J'ai une application NSDocument based. J'ai ajouté un item de menu dans le menu fichier pour faire des exports. Ca marche bien, sauf que cet item n'est jamais grisé. Il est accessible même quand aucun document n'est ouvert.

Y'a-t-il un moyen de gérer ça automatiquement ???

Merci

Réponses

  • aranaudaranaud Membre
    août 2006 modifié #2
    Je présume qut tu as rajouté quelque par
    - (void)exports:(id)sender
    


    Il faut mettre cette action dans une classe qui est chargé en même temps que ton document. Et qui n'est plus chargé quand aucun document n'est chargé.

    edit: j'ai oublié de dit qui fallait rajouter l'action dans l'object FirstResponder.

    Nota : j'avais aussi essayé avec - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem mais sa me prenait la tête.
  • 19:08 modifié #3
    Il y a plus simple: il faut implémenter la méthode
    [tt]- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem[/tt]

    Maintenant la question est de savoir où. La doc précise que cette méthode est appelée successivement sur une série d'objets:

    - The responder chain for the window in which the view that triggered the context menu resides, starting with the view.
    - The window itself.
    - The window's delegate.
    - The NSApplication object.
    - The NSApplication object's delegate.


    Donc si ton document est le délégué de la fenêtre active, tu y implémentes la méthodes et tu renvoies YES. Puis tu implémentes cette méthode dans le délégué de l'application et tu renvoies NO. Pour identifier l'item, le plus prudent est de le faire sur base sur tag ou de l'action:

    [tt]- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem {
    if ([menuItem action] == @selector(exports:)) return NO;
    return YES;
    }[/tt]
  • olofolof Membre
    19:08 modifié #4
    Ok, comme je débute tout ça n'est pas complètement clair pour moi.

    Sans me soucier de l'état (grisé ou non) de cet item de menu, j'avais instancié ma classe qui sous-classe NSDocumentController dans le NIB MainMenu. Dans cette classe, j'avais ajouté la méthode -(IBAction)export:(id)sender et cette méthode faisait :

    <br />-(IBAction)export:(id)sender {<br />	[NSApp sendAction:@selector(exportXML:) to:nil from:sender];<br />}<br />
    


    la méthode exportXML se trouvant dans ma classe qui sous-classe NSDocument.

    Est-ce juste ???
  • août 2006 modifié #5
    Si tu utilises cette méthode, ce qui est le plus intelligent, NSApp va tenter de trouver un object répondant à  exportXML: en utilisant la même chaine que ce qui est utilisé pour la validation des menus (à  deux exceptions près: avant d'arriver à  la fenêtre, il va tester toutes les superview du firstResponder, et il teste la keyWindow, puis la mainWindow - qui peuvent être différentes si tu as un inspecteur par exemple). Donc si ton document est le délégué de la fenêtre active, c'est bon.
  • olofolof Membre
    19:08 modifié #6
    Ok, donc, maintenant, j'ai ajouté ça à  ma classe qui sous-classe NSDocumentController :

    <br />-(BOOL)validateMenuItem:(id &lt;NSMenuItem&gt;)aMenuItem {<br />	if ([aMenuItem action] == @selector(export:)) {<br />		return NO;<br />	}<br />	return YES;<br />}<br />
    


    Grâce à  ça, quand je n'ai pas de document ouvert, l'item du menu est grisé.

    Je continue, j'ajoute ça à  ma classe qui sous-classe NSDocument :

    <br />-(BOOL)validateMenuItem:(id &lt;NSMenuItem&gt;)aMenuItem {<br />	if ([aMenuItem action] == @selector(export:)) {<br />		return YES;<br />	}<br />	return NO;<br />}<br />
    


    Comme ça ne fonctionn pas, j'ai ajouté le log suivant avant le if, dans le code ci-dessus :

    <br />NSLog(@&quot;CaveDoc : %@&quot;,[aMenuItem description]);<br />
    


    Et quand j'ai un document ouvert et que "j'ouvre" le menu Fichier, j'ai les infos suivantes dans le log :

    <br />2006-08-20 18:00:22.194 Gestquave[6134] CaveDoc : &lt;MenuItem: 0x3237d0 Sauvegarder&gt;<br />2006-08-20 18:00:22.195 Gestquave[6134] CaveDoc : &lt;MenuItem: 0x323f60 Sauvegarder sous...&gt;<br />2006-08-20 18:00:22.195 Gestquave[6134] CaveDoc : &lt;MenuItem: 0x323ff0 Revenir à  la version enregistrée&gt;<br />2006-08-20 18:00:22.195 Gestquave[6134] CaveDoc : &lt;MenuItem: 0x324ca0 Format d&#39;impression...&gt;<br />2006-08-20 18:00:22.195 Gestquave[6134] CaveDoc : &lt;MenuItem: 0x324220 Imprimer...&gt;<br />
    


    Rien qui concerne mon menu Exporter. Faut-il faire quelque chose de spécial sur mon item de menu ???
  • Eddy58Eddy58 Membre
    août 2006 modifié #7
    Je pense qu'il ne te reste plus qu'à  placer deux
    [tt]
       [monMenu update];[/tt]
    aux endroits appropriés (lors de l'ouverture d'un document et lors de la fermeture du dernier document) pour raffraichir ton menu. :)
  • 19:08 modifié #8
    Non les méthodes de validation de menu sont en fait appelées à  "chaque event". Donc c'est un peu inutile d'appeler update. Je pense que le problème vient du fait que tu as définis une target (tiré un outlet sur autre chose que le firstResponder), et donc il sort du circuit que j'ai cité.
  • olofolof Membre
    19:08 modifié #9
    En effet, le lien que j'ai fait dans IB est entre mon menu item et ma classe qui sous-classe NSDocumentController. Je ne peux pas faire de lien avec le FirstResponder (y'a pas mes méthode dedans !!!).

    Merci pour votre aide !!!
  • CouhoulinnCouhoulinn Membre
    19:08 modifié #10
    Bonjour (long time no see)

    Et comment fait-on dans une application document-based pour ajouter des menuitems dans un sous-menu dynamiquement. Et pour modifier les titres de menuitems?
  • Philippe49Philippe49 Membre
    19:08 modifié #11
    dans 1200924475:

    Bonjour (long time no see)

    Et comment fait-on dans une application document-based pour ajouter des menuitems dans un sous-menu dynamiquement. Et pour modifier les titres de menuitems?


    On utilise les méthodes dédiées de NSMenu :

    Par exemple :
    Setting up Menu Commands
    – insertItem:atIndex: 
    – insertItemWithTitle:action:keyEquivalent:atIndex: 
    – addItem: 
    – addItemWithTitle:action:keyEquivalent: 
    – removeItem: 
    – removeItemAtIndex: 
    – itemChanged: 
  • CouhoulinnCouhoulinn Membre
    19:08 modifié #12
    ça je connais... ;)

    C'est juste que dans une document-based application, pas vraiment moyen de faire des liens entre le nib du document et le nib du mainmenu...

    D'où l'utilité d'utiliser validateMenuItem: en lieu et place de setEnabled: ;)

    Enfin, j'ai trouvé ce matin une combine...

    Dans le awakeFromNib: du document, on récupère les adresses des nsmenuitems que l'on veut utiliser directement. drawerMenu et voicesMenu sont des NSMenuItem* objets de ma classe dérivée de NSDocument :

    drawerMenu = [[[[NSApp mainMenu] itemWithTitle:@&quot;View&quot;] submenu] itemWithTitle:@&quot;Show Phoneme List&quot;];<br />voicesMenu = [[[[NSApp mainMenu] itemWithTitle:@&quot;Lexicon&quot;] submenu] itemWithTitle:@&quot;Voice&quot;];
    


    Après, on peut s'amuser à  faire des setTitle: et autres joyeusetés :)
  • Philippe49Philippe49 Membre
    janvier 2008 modifié #13
    dans 1200991686:


    C'est juste que dans une document-based application, pas vraiment moyen de faire des liens entre le nib du document et le nib du mainmenu...




    Ce qui me semble bizarre dans ta question c'est l'attribution des rôles. Pour moi ce n'est pas vraiment à  une instance de NSDocument de changer l'interface, mais cela incombe à  un contrôleur général de l'application.

    Donc ton code fonctionne, mais je préférerais pour ma part que la gestion des menus reste l'attribution d'un super-controller de l'application (via [NSApp delegate] par exemple)




  • Philippe49Philippe49 Membre
    19:08 modifié #14
Connectez-vous ou Inscrivez-vous pour répondre.