Principes de base des menus

Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures

Pour obtenir une explication rapide de la création de menus natifs dans une application AIR et des exemples de code, voir les articles de démarrage rapide suivants dans Adobe Developer Connection :

Les classes de menus natifs vous permettent d’accéder aux fonctions de menu natif du système d’exploitation sur lequel s’exécute votre application. Des objets NativeMenu peuvent être utilisés pour les menus d’application (sous Mac OS X), les menus de fenêtre (sous Windows et Linux), les menus contextuels et les menus en incrustation.

En dehors d’AIR, vous disposez des classes de menus contextuels pour modifier le menu contextuel automatiquement affiché par Flash Player lorsqu’un utilisateur clique avec le bouton droit de la souris ou en maintenant la touche Commande enfoncée sur un objet de votre application. (Aucun menu contextuel automatique ne s’affiche pour les applications AIR.)

Classes de menus

Les classes de menus sont les suivantes :

Types de menus

AIR prend en charge les types de menus suivants :

Menus contextuels
Un menu contextuel s’affiche lorsque l’utilisateur clique avec le bouton droit de la souris ou en maintenant la touche Commande enfoncée sur un objet interactif dans du contenu SWF ou sur un élément de document dans du contenu HTML.

Un menu contextuel s’affiche automatiquement dans le moteur d’exécution Flash Player. Vous disposez des classes ContextMenu et ContextMenuItem pour ajouter vos propres commandes au menu. Vous pouvez également supprimer certaines des commandes intégrées, mais pas toutes.

Dans le moteur d’exécution AIR, vous pouvez créer un menu contextuel à l’aide de la classe NativeMenu ou ContextMenu. Un contenu HTML dans AIR vous permet d’utiliser les API Webkit HTML et JavaScript pour ajouter des menus contextuels aux éléments HTML.

Menus d’application (AIR uniquement)
Un menu d’application est un menu global qui s’applique à la totalité de l’application. Les menus d’application sont pris en charge par Mac OS X, mais pas par Windows ni Linux. Sous Mac OS x, le système d’exploitation crée automatiquement un menu d’application. Vous pouvez utiliser l’API de menus d’AIR pour ajouter des éléments et des sous-menus aux menus standard. Vous pouvez ajouter des écouteurs pour gérer les commandes de menu existantes et vous pouvez supprimer des éléments existants.

Menus de fenêtre (AIR uniquement)
Un menu de fenêtre est associé à une fenêtre unique et s’affiche sous la barre de titre. Pour ajouter des menus à une fenêtre, vous créez un objet NativeMenu et l’affectez à la propriété menu de l’objet NativeWindow. Les menus de fenêtre sont pris en charge par les systèmes d’exploitation Windows et Linux, mais pas par Mac OS X. Les menus de fenêtre natifs ne peuvent être utilisés qu’avec les fenêtres disposant d’un chrome système.

Menus d’icônes de la barre d’état système et du Dock (AIR uniquement)
Similaires aux menus contextuels, les menus d’icône sont affectés à l’icône d’une application dans le Dock de Mac OS X ou dans la zone de notification de la barre des tâches de Windows et Linux. Les menus d’icônes de la barre d’état système et du Dock utilisent la classe NativeMenu. Sous Mac OS X, les éléments du menu sont ajoutés au-dessus des éléments standard du système d’exploitation. Sous Windows et Linux, le menu standard n’existe pas.

Menus en incrustation (AIR uniquement)
Un menu en incrustation AIR est similaire à un menu contextuel mais il n’est pas nécessairement associé à un objet ou composant d’application spécifique. Vous pouvez afficher des menus en incrustation n’importe où dans une fenêtre en appelant la méthode display() de tout objet NativeMenu.

Menus personnalisés
Les menus natifs sont dessinés entièrement par le système d’exploitation et, en tant que tels, existent en dehors des modèles de rendu Flash et HTML. Au lieu d’utiliser des menus natifs, vous pouvez créer des menus personnalisés non natifs à l’aide de MXML, ActionScript, ou JavaScript (dans AIR). Les menus de ce type doivent s’afficher complètement dans le contenu d’une application.

Menus Flex
La structure Adobe® Flex™ propose un ensemble de composants de menu Flex. Les menus Flex sont dessinés par le moteur d’exécution plutôt que par le système d’exploitation et ne sont pas des menus natifs . Il est possible d’utiliser un composant de menu Flex pour des fenêtres Flex sans chrome système. Autre avantage, vous pouvez spécifier des menus par déclaration au format MXML. Si vous utilisez la structure Flex, faites appel aux classes de menu Flex pour les menus de fenêtre plutôt qu’aux classes natives.

Menus par défaut (AIR uniquement)

Les menus par défaut suivants sont proposés par le système d’exploitation ou une classe AIR intégrée :

  • Menu d’application sous Mac OS X

  • Menu d’icône du Dock sous Mac OS X

  • Menu contextuel associé au texte et aux images sélectionnés dans du contenu HTML

  • Menu contextuel associé au texte sélectionné dans un objet TextField (ou un objet étendant TextField)

Présentation des menus contextuels

Dans du contenu SWF, il est possible d’associer un menu contextuel à tout objet qui hérite des propriétés ou méthodes de InteractiveObject en affectant un objet menu à sa propriété contextMenu . Plusieurs commandes sont incluses par défaut, notamment des commandes d’avance, de recul, d’impression, de qualité et de zoom. Dans le moteur d’exécution AIR, l’objet menu affecté à contextMenu peut être de type NativeMenu ou ContextMenu. Dans le moteur d’exécution Flash Player, seule la classe ContextMenu est disponible.

Vous pouvez écouter les événements des menus natifs ou des menus contextuels lorsque vous utilisez les classes ContextMenu et ContextMenuItem ; les deux sont distribués. L’un des avantages des propriétés de l’objet ContextMenuEvent est que contextMenuOwner identifie l’objet auquel le menu est associé et mouseTarget identifie l’objet sur lequel l’utilisateur a cliqué pour ouvrir le menu. Ces informations ne sont pas disponibles avec l’objet NativeMenuEvent.

L’exemple suivant crée un sprite et l’ajoute à un menu contextuel edit simple :

var sprite:Sprite = new Sprite(); 
sprite.contextMenu = createContextMenu() 
private function createContextMenu():ContextMenu{ 
    var editContextMenu:ContextMenu = new ContextMenu(); 
    var cutItem:ContextMenuItem = new ContextMenuItem("Cut") 
    cutItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, doCutCommand); 
    editContextMenu.customItems.push(cutItem); 
     
    var copyItem:ContextMenuItem = new ContextMenuItem("Copy") 
    copyItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, doCopyCommand);             
    editContextMenu.customItems.push(copyItem); 
     
    var pasteItem:ContextMenuItem = new ContextMenuItem("Paste") 
    pasteItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, doPasteCommand); 
    editContextMenu.customItems.push(pasteItem); 
         
    return editContextMenu 
} 
private function doCutCommand(event:ContextMenuEvent):void{trace("cut");} 
private function doCopyCommand(event:ContextMenuEvent):void{trace("copy");} 
private function doPasteCommand(event:ContextMenuEvent):void{trace("paste");}
Remarque : contrairement au contenu SWF affiché dans un environnement de navigateur, dans AIR, les menus contextuels ne possèdent pas de commandes intégrées.

Personnalisation d’un menu contextuel Flash Player

Dans un navigateur ou un fichier de projection, les menus contextuels associés à un contenu SWF contiennent systématiquement des éléments intégrés. Vous pouvez supprimer toutes ces commandes par défaut du menu, à l’exception des commandes Paramètres et A propos. Lorsque vous définissez la propriété Stage showDefaultContextMenu sur false , ces commandes sont supprimées du menu contextuel.

Pour créer un menu contextuel personnalisé pour un objet d’affichage particulier, créez une occurrence de la classe ContextMenu, appelez la méthode hideBuiltInItems() et affectez cette occurrence à la propriété contextMenu de cette occurrence de DisplayObject. L’exemple suivant crée un carré dessiné dynamiquement avec une commande de menu contextuel qui permet de modifier sa couleur au hasard :

var square:Sprite = new Sprite(); 
square.graphics.beginFill(0x000000); 
square.graphics.drawRect(0,0,100,100); 
square.graphics.endFill(); 
square.x = 
square.y = 10; 
addChild(square); 
 
var menuItem:ContextMenuItem = new ContextMenuItem("Change Color"); 
menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,changeColor); 
var customContextMenu:ContextMenu = new ContextMenu(); 
customContextMenu.hideBuiltInItems(); 
customContextMenu.customItems.push(menuItem); 
square.contextMenu = customContextMenu; 
 
function changeColor(event:ContextMenuEvent):void 
{ 
    square.transform.colorTransform = getRandomColor(); 
} 
function getRandomColor():ColorTransform 
{ 
    return new ColorTransform(Math.random(), Math.random(),         Math.random(),1,(Math.random() * 512) - 255,         (Math.random() * 512) -255, (Math.random() * 512) - 255, 0); 
}

Structure de menu natif (AIR)

La structure des menus natifs est par nature hiérarchique. Les objets NativeMenu contiennent des objets enfant NativeMenuItem. Les objets NativeMenuItem qui représentent des sous-menus peuvent eux aussi contenir des objets NativeMenu. L’objet menu du niveau supérieur ou racine de la structure représente la barre de menus des menus d’application et de fenêtre. (Les menus contextuels, d’icônes et en incrustation ne possèdent pas de barre de menus.)

Le schéma suivant illustre la structure d’un menu typique. Le menu racine représente la barre de menus et contient deux éléments de menu référençant les sous-menus Fichier et Modifier . Le sous-menu Fichier de cette structure contient deux éléments de commande et un élément référençant le sous-menu Ouvrir l’élément récent qui, lui-même, contient trois éléments. Le sous-menu Modifier contient trois commandes et un séparateur.

Pour définir un sous-menu, vous devez disposer d’un objet NativeMenu et d’un objet NativeMenuItem. L’objet NativeMenuItem définit le libellé affiché dans le menu parent et permet à l’utilisateur d’ouvrir le sous-menu. L’objet NativeMenu sert de conteneur des éléments du sous-menu. Par le biais de sa propriété submenu , l’objet NativeMenuItem référence l’objet NativeMenu.

Vous trouverez un exemple de code qui crée ce menu à la section Exemple de menu natif : menu de fenêtre et d’application (AIR) .

Evénements de menu

Les objets NativeMenu et NativeMenuItem distribuent tous deux des événements preparing , displaying , et select :

Preparing : lorsque l’objet est sur le point de démarrer une interaction utilisateur, le menu et les sous-menus correspondants distribuent un événement preparing à tout écouteur enregistré. Parmi les interactions figurent l’ouverture du menu et la sélection d’une option par le biais d’un raccourci clavier.
Remarque : l’événement preparing n’est disponible que dans Adobe AIR 2.6 et les versions ultérieures.
Displaying :
juste avant son affichage, un menu et ses options distribuent un événement displaying à tout écouteur enregistré.

Les événements preparing et displaying permettent de mettre à jour le contenu du menu ou l’apparence de l’option avant son affichage à l’intention de l’utilisateur. Par exemple, dans l’écouteur de l’événement displaying d’un menu « Ouvrir un fichier récent », vous pourriez modifier les options de menu en fonction de la liste actuelle de documents affichés récemment.

Si vous supprimez l’option de menu dont le raccourci clavier a déclenché un événement preparing , l’interaction de menu est annulée et aucun événement select n’est distribué.

Les propriétés target et currentTarget de l’événement correspondent toutes deux à l’objet auquel est associé l’écouteur, c’est-à-dire au menu en tant que tel ou à l’une de ses options.

L’événement preparing est distribué avant l’événement displaying . Vous écoutez généralement l’un des deux événements, mais non les deux à la fois.

Sélection :
lorsque l’utilisateur choisit une commande, l’élément distribue un événement select à tout écouteur enregistré. Les sous-menus ou les séparateurs ne distribuent jamais d’événements select car il est impossible de les sélectionner.

Un événement select remonte d’un élément de menu vers son menu conteneur ou jusqu’au menu racine. Vous pouvez écouter les événements select directement sur un élément ou plus haut dans la structure de menu. Lorsque vous écoutez un événement select sur un menu, vous pouvez identifier l’élément sélectionné à l’aide de la propriété target de l’événement. Lorsque l’événement remonte dans la hiérarchie de menu, la propriété currentTarget de l’objet événement identifie l’objet menu actuel.

Remarque : les objets ContextMenu et ContextMenuItem distribuent des événements menuItemSelect et menuSelect , ainsi que des événements select , preparing et displaying .

Equivalents clavier des commandes de menus natifs (AIR)

Vous pouvez affecter un équivalent clavier (parfois appelé accélérateur) à une commande de menu. L’élément de menu distribue un événement select à tout écouteur enregistré lorsque l’utilisateur appuie sur la touche ou la combinaison de touches. Le menu contenant l’élément doit appartenir au menu de l’application ou de la fenêtre active pour la commande à appeler.

L’équivalent clavier se compose de deux parties : une chaîne représentant la touche principale et un tableau de touches de modification sur lesquelles il est également nécessaire d’appuyer. Pour affecter une touche principale, définissez la propriété keyEquivalent de l’élément de menu sur la chaîne à caractère unique correspondant à cette touche. Si vous utilisez une majuscule, la touche Maj est automatiquement ajoutée au tableau de touches de modification.

Sous Mac OS X, la touche Commande ( Keyboard.COMMAND ) est la touche de modification par défaut. Sous Windows et Linux, il s’agit de la touche Ctrl ( Keyboard.CONTROL ). Ces touches par défaut sont automatiquement ajoutées au tableau de touches de modification. Pour utiliser d’autres touches de modification, affectez un nouveau tableau contenant les codes de touche souhaités à la propriété keyEquivalentModifiers . Le tableau par défaut est remplacé. Que vous utilisiez les touches de modification par défaut ou votre propre tableau de touches de modification, la touche Maj est ajoutée si la chaîne que vous affectez à la propriété keyEquivalent est une lettre majuscule. Les constantes correspondant aux codes de touche à utiliser pour les touches de modification sont définies dans la classe Keyboard.

La chaîne d’équivalent clavier affectée est automatiquement affichée en regard du nom de l’élément de menu. Le format varie selon le système d’exploitation et les préférences système de l’utilisateur.

Remarque : si vous affectez la valeur Keyboard.COMMAND à un tableau de touches de modification sous Windows, aucun équivalent clavier n’est affiché dans le menu. En revanche, il est impératif d’utiliser la touche Ctrl pour activer la commande de menu.

L’exemple suivant affecte l’équivalent clavier Ctrl+Maj+G à un élément de menu :

var item:NativeMenuItem = new NativeMenuItem("Ungroup"); 
item.keyEquivalent = "G"; 

L’exemple suivant affecte l’équivalent clavier Ctrl+Maj+G en définissant directement le tableau de modification :

var item:NativeMenuItem = new NativeMenuItem("Ungroup"); 
item.keyEquivalent = "G"; 
item.keyEquivalentModifiers = [Keyboard.CONTROL]; 
Remarque : les équivalents clavier sont uniquement déclenchés pour les menus d’application et de fenêtre. Un équivalent clavier ajouté à un menu contextuel ou à un menu en incrustation est indiqué dans le libellé du menu, mais la commande de menu associée n’est jamais appelée.

Mnémoniques (AIR)

Les mnémoniques font partie de l’interface clavier du système d’exploitation pour les menus. Linux, Mac OS X et Windows permettent d’ouvrir des menus et de sélectionner des commandes par le biais du clavier mais il existe quelques petites différences.

Sous Mac OS X, l’utilisateur saisit la ou les deux premières lettres du menu ou de la commande et appuie sur Entrée. La propriété mnemonicIndex est ignorée.

Sous Windows, seule une lettre est significative. Par défaut, elle correspond au premier caractère du libellé mais si vous affectez une mnémonique à un élément de menu, la lettre désignée devient le caractère significatif. Si deux éléments d’un menu possèdent le même caractère significatif (qu’une mnémonique ait été affectée ou non), l’interaction avec le menu à partir du clavier change légèrement. Plutôt que d’appuyer sur une seule lettre pour sélectionner le menu ou la commande, l’utilisateur appuie sur la lettre autant de fois que nécessaire pour mettre en évidence l’élément souhaité, puis il appuie sur la touche Entrée pour confirmer la sélection. Pour garantir un comportement cohérent, il est préférable d’affecter une seule mnémonique à chaque élément d’un menu sous Windows.

Sous Linux, aucune mnémonique n’est fournie par défaut. Pour fournir une mnémonique, vous devez définir la valeur de la propriété mnemonicIndex d’un élément de menu.

Spécifiez le caractère mnémonique en tant qu’index dans la chaîne de libellé. L’index du premier caractère d’un libellé est 0. Ainsi pour utiliser le « r » comme mnémonique d’un menu intitulé « Format », vous définissez la propriété mnemonicIndex sur 2.

var item:NativeMenuItem = new NativeMenuItem("Format"); 
item.mnemonicIndex = 2; 

Etat d’un élément de menu

Les éléments de menu possèdent deux propriétés d’état : checked (coché) et enabled (activé) :

checked
Définissez cette propriété sur true pour afficher une coche en regard du libellé de l’élément.
var item:NativeMenuItem = new NativeMenuItem("Format"); 
item.checked = true; 

enabled
Faites basculer la valeur entre true et false pour vérifier si la commande est activée. Les éléments désactivés sont affichés « en grisé » et ne distribuent pas d’événements select .
var item:NativeMenuItem = new NativeMenuItem("Format"); 
item.enabled = false; 

Rattachement d’un objet à un élément de menu

La propriété data de la classe NativeMenuItem vous permet de référencer un objet arbitraire dans chaque élément. Par exemple, dans un menu « Ouvrir un fichier récent », vous pourriez affecter l’objet File associé à chaque document à chaque élément de menu.

var file:File = File.applicationStorageDirectory.resolvePath("GreatGatsby.pdf") 
var menuItem:NativeMenuItem = docMenu.addItem(new NativeMenuItem(file.name)); 
menuItem.data = file;