L'Xtra MUI (des boîtes de dialogue facilement ?)
La création de boîtes de dialogue a toujours été
l'enfer du développeur Director. Nombreux sont ceux qui,
sur Macintosh, préféraient faire appel aux ressources
du système plutôt que d'utiliser les MIAW peu maniables
et coûteuses en mémoire. Leur projet y perdait sa portabilité.
Livrée avec la version 6 de Director, l'Xtra MUI prétend
résoudre ce dilemme et faciliter enfin la création
de dialogues élégants indépendants de la plate-forme
utilisée. Un seul effort exigé, mais de taille :
la manipulation de listes de propriétés imbriquées.
Suivez-nous :
Créer une alerte simple
Mui autorise la création de nombreux types pré définis
de dialogues : Alerte, Dialogue d'ouverture ou d'enregistrement
de fichier, dialogue de saisie d'une URL. L'Xtra permet aussi la
création pure et simple d'une boîte dont tous les paramètres
sont définis par le développeur. Dans tous les cas,
Une instance de MUI devra être créée et les
paramètres nécessaires devront lui être passés
sous forme de liste de propriétés. Un exemple ?
Nous voulons une boîte d'alerte bien spécifique dont
nous devons définir l'aspect. Nous devons choisir les boutons
et, parmi eux, celui qui sera le bouton par défaut, nous
devons désigner l'icône, le message que l'alerte affichera,
décider si la boîte sera déplaçable,
enfin afficher un intitulé dans sa barre de titre. L'objet
recevra ces indications sous la forme d'une liste (DetailDeLAlerte)
où chaque propriété (#buttons, #default, #icon,
#message, #movable, #title) se voit associée une valeur(#YesNo,
TRUE, "bonjour",...).
set DetailDeLAlerte to [#buttons:#YesNo, #default: 2, #icon:#caution,
#message:"êtes-vous sûr ?", #movable:true, #title:"Confirmation
requise"]
Nous détaillerons plus tard les valeurs possibles pour chaque
propriété. Voyons vite à quoi notre alerte
ressemble et pour ce faire, invoquons l'Xtra et créons un
enfant CRAPO.
set CRAPO to new(xtra "MUI")
Les méthodes de l'objet sont connues par la commande put
mMessageList(xtra "MUI") saisie dans la fenêtre message. Celle
dont nous avons besoin est d'utilisation simple : Nous passons
en paramètre la liste DetailDeLAlerte
alert(CRAPO, DetailDeLAlerte)
résultat :
La boîte est déplaçable, le deuxième
bouton est le bouton par défaut, l'icône affichée
est familière aux utilisateurs. C'est presque beau !
Maintenant après le clic de l'utilisateur nous connaissons
son choix avec autant de facilité :
put the result
-- 1
L'utilisateur a cliqué sur le premier bouton "Yes".
On n'oublie pas de détruire l'objet devenu inutile.
set CRAPO to 0
Quelles sont les possibilités de personnalisation offertes
par la méthode alert ? Chaque propriétés
peut, dans la liste de propriété qu'il faut transmettre,
se voir associer différentes valeurs :
#buttons:
#Ok
#OkCancel
#AbortRetryIgnore -- plantage quasi assuré
sous MacOS
#YesNoCancel
#YesNo
#RetryCancel -- plantage
quasi assuré sous MacOS
#default:
0 -- aucun bouton par défaut
1 -- le premier bouton est le bouton par défaut
2 -- le deuxième bouton est le bouton par défaut
3 -- le troisième...
#icon:
0 -- aucune icône
#stop
#note
#caution
#question
#error
#message:
"une chaîne entre guillemets" Pour imposer un retour à
la ligne, insérer ..." & RETURN & "...
#movable:
true
false
#title :
"un intitulé entre guillemets, qui sera affiché
dans la barre de titre"
Une fois la liste des propriétés de la boîte
de dialogue constituée, on peut aisément modifier
la valeur affectée à l'une de ces propriétés :
set the message of DetailDeLAlerte to "nouveau message"
set the movable of DetailDeLAlerte to false
...
La même alerte peut donc resservir à un autre usage.
MUI permet aussi la création de boîtes de dialogue
où de fenêtres plus personnelles mais la mise en uvre
de l'Xtra se révèle alors beaucoup plus ardue. Seuls
les plus résolus suivront le Crapo jusque là :
Créer un dialogue personnalisé
Pour créer notre fenêtre personnalisée, il
nous faut bien sûr commencer par créer une instance
de MUI.
set CRAPO to new(xtra "MUI")
Les méthodes Run et Stop affiche et masque une fenêtre
modale. Mais l'on ne peut les appeler avant d'avoir défini
la dite fenêtre. Cette description devra être passée
à l'objet sous la forme d'une liste de deux propriétés :
#windowPropList et #windowItemList.
#windowPropList
Il s'agit d'une liste propriétés décrivant
l'aspect général et extérieur de la fenêtre.
#windowItemList
C'est une liste linéaire de listes de propriétés.
Chaque liste de propriétés reprenant pour le décrire
le détail d'un élément du dialogue.
On a donc le shéma suivant :
et en Lingo :
set DescriptionDeLaFenetre to
[
#windowPropList
:
[
liste des propriétés de la fenêtre],
#windowItemList
:
[
[liste
des propriétés du premier élément de
la fenêtre],
[liste
des propriétés du deuxième élément
de la fenêtre],
[liste
des propriétés du troisième élément
de la fenêtre],
[liste
des propriétés du troisième élément
de la fenêtre],
...]
]
Nous voilà prévenu ! la manipulation de ces listes
imbriquées risque fort de nous être difficile et nous
avons tout intérêt à procéder par ordre.
Nous commençons par définir les propriétés
de la fenêtre dans une variable "ProprieteDeLaFenetre".
Définir la fenêtre
La fonction GetWindowPropList renvoie une liste pré définie
de propriétés et de valeurs par défaut. Il
est plus rapide de partir d'une liste pré définie
obtenue par GetWindowPropList et de la modifier à notre convenance.
set ProprieteDeLaFenetre to GetWindowPropList(CRAPO)
On demande sans attendre de voir la liste ainsi créée.
put ProprieteDeLaFenetre
-- [#type: #normal, #name: "window", #callback: "nothing", #mode:
#data, #xPosition: 100, #yPosition: 120, #width: 200, #height: 210,
#modal: 1, #toolTips: 0, #closeBox: 1, #canZoom: 0]
Il n'entre pas dans notre but ici de détailler toutes ces
propriétés. La propriété #mode ayant
pour valeur #data, la boite sera dimensionnée, positionnée,
et construite automatiquement en fonction de son contenu (avec #mode:#pixel
nous devrions placer chaque objet avec précision, avec #dialogunit
la boîte serait dimensionnée de façon à
s'adapter au bureau). #toolTips est une fonction que notre version
de MUI ne supporte pas. Il s'agirait dans les version future de
permettre l'apparition d'une bulle d'aide au dessus des éléments
de dialogue. La propriété #closeBox détermine
sur PC si la boîte doit ou non présenter une case de
fermeture. Sur Mac changer cette valeur n'a aucun effet. Nous n'avons
besoin que de changer l'intitulé de la barre de titre. Nous
souhaitons aussi des dimensions automatiquement calculées
pour cette fenêtre :
set the name of ProprieteDeLaFenetre to "le CrapoWeb"
set the width of ProprieteDeLaFenetre to 0
set the height of ProprieteDeLaFenetre to 0
-- ceci a pour effet de
laisser le système
-- d'exploitation dimensionner
la fenêtre
Définir les éléments de la fenêtre
Chaque élément (contrôle, bouton, zone de texte...)
de la fenêtre est défini par un liste de propriétés
renseignant sur son type, ses attributs... Il y aura donc autant
de listes de propriétés qu'il y aura d'éléments.
On regroupera toutes ces listes de propriétés dans
une liste linéaire "ProprietesDesElements"
set ProprietesDesElements to []
Nous devons maintenant produire une à une les listes de
propriétés des éléments que nous souhaitons
utiliser et les ajouter aussitôt à ProprietesDesElements.
Pour produire la liste des propriétés d'un élément
quelconque nous partirons à chaque fois de la liste par défaut
obtenue par la fonction GetItemPropList. GetItemPropList renvoie
une liste de propriétés aux valeurs par défaut,
que nous modifierons si besoin est.
set PremierElement to GetItemPropList(CRAPO)
on veut voir la liste créée par défaut :
put PremierElement
-- [#value: 0, #type: #checkBox, #attributes: [], #title:
"title", #tip: "tip", #locH: 20, #locV: 24, #width: 200, #height:
210, #enabled: 1]
La propriété #type définit le type de l'élément.
Voici quelques unes des valeurs que peut prendre cette propriétés :#bitmap,
#checkBox, #radioButton, ,#PopupList , #IntegerSliderH, #editText
,...
#attributes requiert une liste (encore!) définissant plus
précisément l'élément. Les attributs
disponibles dépendent étroitement du type de l'élément.
Pour un élément de type texte par exemple, la propriété
#attributes peut se voir associée la liste suivante :
#attributes : [#textSize:#Normal, #textStyle:[ #bold,
#italic]]
Parmi les attributs utilisables : #valueList : ["choix un",
"choix deux"] , pour une menu; #bitmapStyle : [#bitmapIcon:#caution],
pour un élément de type bitmap, #layoutStyle : []
enfin qui ne sert qu'en mode construction automatique (#data ou
#pixel), pour forcer malgré tout, un aspect de l'élément.
On notera que tous les attributs disponibles ne sont pas documentés
par Macromedia. Certains attributs sont sans effet sur l'une ou
l'autre plateforme ou sur les deux !
#title est une chaîne de caractère donnant l'intitulé
de l'élément. Ex: un bouton., une case à
cocher. Tous les types n'en font pas usage.
#loch, #locv, #width et #height seront modifiés sans effet
si la fenêtre est dessinée automatiquement (c'est-à-dire
si dans les propriétés de la fenêtre, voir
plus haut, le mode est #data et non #pixel (ou #dialogUnit sous
Windows). nous ignorerons ici #loch, #locv...
#enabled determine l'état actif (disponible) ou indisponible
de l'élément
Le premier élément de la fenêtre (tout comme
le dernier) a un statut particulier dans la construction de la fenêtre
et nous ne devons nous préoccuper que de sa propriété
#type :
set the type of PremierElement = #windowBegin
Enfin nous l'ajoutons à la liste ProprietesDesElements.
add ProprietesDesElements , PremierElement
----------------------------------------------------------------
On définit maintenant les propriétés du premier
contrôle, deuxième élément , premier
objet visible du dialogue. Nous choisissons de faire apparaître
un curseur horizontal. Nous ne modifions de la liste des propriétés
par défaut obtenue par GetItemPropList que celles qui nous
intéressent:
set LeCurseur to GetItemPropList(CRAPO)
set the type of LeCurseur to #integerSliderH
set the attributes of LeCurseur to
[#valueRange: [#min:0.0, #max:100.0, #jump:5.0, #acceleration:0.5],
#sliderStyle:[#ticks]]
Les attributs disponibles d'un slider" sont nombreux. Certains
comme #jump et #Acceleration ne sont pas documentés par Macromedia.
On peut conjecturer qu'il s'agit d'options permettant d'utiliser
un slider comme jauge d'attente. On ne les cite ici que pour mémoire.
Leur présence n'aura aucun effet pour ce qui nous concerne.
Il existe de même une propriété #increment que
notre version de MUI ignore superbement. La propriété
#sliderStyle est plus interessante pour nous, elle détermine
le type d'affichage du curseur : avec ou sans graduation et/ou
avec ou sans valeur numérique d'accompagnement. L'affichage
le plus complet s'obtiendrait ainsi #sliderStyle:[#ticks,#value].
On ajoute aussitôt la liste de propriétés définissant
le curseur à ProprietesDesElements,
add ProprietesDesElements, LeCurseur
----------------------------------------------------------------
Pour les troisième et quatrième éléments
on souhaite classiquement deux boutons de validation et d'annulation.
On les définit un à un de la même façon.
set BoutonOk to GetItemPropList(CRAPO)
set the type of BoutonOk = #pushButton
set the title of BoutonOk = "D'accord"
add ProprietesDesElements, BoutonOk
------------------------------------------------------------------
set BoutonAnnuler to GetItemPropList(crapo)
set the type of BoutonAnnuler = #pushButton
set the title of BoutonAnnuler = "Pas d'accord"
add ProprietesDesElements, BoutonAnnuler
------------------------------------------------------------------
Dernier élément, enfin, son type DOIT être
windowEnd.
set DernierElement to GetItemPropList(crapo)
set the type of DernierElement = #windowEnd
add ProprietesDesElements, DernierElement
Afficher la fenêtre
On dispose désormais des deux listes requises : ProprieteDeLaFenetre,
une liste de propriétés définissant la fenêtre
elle-même et ProprietesDesElements,
une liste linéaire de 5 listes de propriétés
dont chacune définit un élément de la fenêtre.
Nous sommes en mesure de passer à l'objet CRAPO ces listes
en paramètre.
set DescriptionDeLaFenetre to [#windowPropList
: ProprieteDeLaFenetre, #windowItemList
: ProprietesDesElements]
La méthode Initialize instruit l'objet CRAPO des caractéristiques
de notre fenêtre.
Initialize(CRAPO, DescriptionDeLaFenetre)
La méthode Run, affiche une fenêtre de type modale
(Stop la supprime).
Run(CRAPO)
Le résultat, il faut bien le dire et ce en dépit
de tous nos efforts, n'est pas très réussi :
La touche Esc fait disparaître cette ébauche. Nous
avons voulu aller vite et nous contenter des valeurs par défaut.
peut-être notre fenêtre gagnerait-elle à être
un peu repensée. Les propriétés sont toutes
accessibles désormais et se prêtent à de multiples
essais et tâtonnements (nos modification sont en rouge ici).
Nous pourrions entre autres changement créer un groupe
horizontal rassemblant les deux boutons mais alors c'est la liste
ProprietesDesElements tout entière qu'il nous faut modifier.
Deux éléments, dont seul le type importe #groupHBegin
et #groupHEnd, doivent être insérés dans notre
liste.
set ProprietesDesElements to []
set PremierElement to GetItemPropList(CRAPO)
set the type of PremierElement = #windowBegin
add ProprietesDesElements , PremierElement
-------------------------------------------
---------------------Définition du curseur
set LeCurseur to GetItemPropList(CRAPO)
set the type of LeCurseur to #integerSliderH
-- on modifie la propriété #attributes
-- Les propriétés #width et #height sont sans utilité
dès lors que
-- la fenêtre (voir ProprieteDeLaFenetre) est en mode #data
set the attributes of LeCurseur to [#valueRange: [#min:0.0,
#max:300, #increment: 10], #sliderStyle:[#value],
#LayoutStyle:[#centerH]]
-- on affecte une valeur par défaut au curseur
set the value of leCurseur to 10
add ProprietesDesElements, LeCurseur
-----------------------------------------------
----------------------- Création
d'un groupe
set DebutDeGroupeHorizontal to GetItemPropList(CRAPO)
set the type of DebutDeGroupeHorizontal to #groupHBegin
add ProprietesDesElements, DebutDeGroupeHorizontal
----------------------------------------------------------
set BoutonAnnuler to GetItemPropList(CRAPO)
set the type of BoutonAnnuler = #pushButton
set the title of BoutonAnnuler = "Annuler"
add ProprietesDesElements, BoutonAnnuler
---------------------------------------------------------
set BoutonOk to GetItemPropList(CRAPO)
set the type of BoutonOk = #defaultPushButton
set the title of BoutonOk = "Redéfinir"
add ProprietesDesElements, BoutonOk
--------------------------------------------------
-------------------- Fin du groupe
set FinDeGroupeHorizontal to GetItemPropList(CRAPO)
set the type of FinDeGroupeHorizontal to #groupHEnd
add ProprietesDesElements, FinDeGroupeHorizontal
------------------------------------------------------------------
set DernierElement to GetItemPropList(CRAPO)
set the type of DernierElement = #windowEnd
add ProprietesDesElements, DernierElement
Les modifications faites, on en instruit l'instance CRAPO puis
on affiche la fenêtre de nouveau.
Initialize(CRAPO, DescriptionDeLaFenetre)
Run(CRAPO)
En l'absence de gestionnaire d'événements attribué
(propriété #callback de la liste ProprieteDeLaFenetre,
voir plus bas), la touche Esc seule (sur Mac) fait disparaître
la boîte.
Gérer les événements utilisateurs
Comparée à la facilité de création
d'une interface dans ResEdit, Les listes imbriquées de MUI
n'ont que bien peu de chance de séduire le développeur
Mac. Seule la portabilité des dialogues sur toute plate-forme
comme aussi, on va le voir, la possibilité de récupérer
des entrées utilisateurs complexes (choix dans une liste
déroulante, saisie dans une zone de texte, action sur un
curseur...) sans écrire une ligne de C justifient notre Xtra.
Voyons ce qu'il en est de la gestion des événements
utilisateurs. Reprenons notre script. Nous allons modifier une des
propriétés de la fenêtre afin que TOTO soit
le gestionnaire appelé par l'objet CRAPO lorsque la boîte
de dialogue enregistre un événement.
on VASY
global CRAPO
if not objectP(CRAPO) then
set CRAPO to new(xtra "MUI")
set ProprieteDeLaFenetre to GetWindowPropList(CRAPO)
set the name of ProprieteDeLaFenetre to "le CrapoWeb"
set the callback of ProprieteDeLaFenetre
to "TOTO"
set ProprietesDesElements to []
set PremierElement to GetItemPropList(CRAPO)
set the type of PremierElement = #windowBegin
add ProprietesDesElements , PremierElement
--------------------------------------------------------
set LeCurseur to GetItemPropList(CRAPO)
set the type of LeCurseur to ...
...
...
...
...
set the type of DernierElement = #windowEnd
add ProprietesDesElements, DernierElement
set DescriptionDeLaFenetre to [#windowPropList : ProprieteDeLaFenetre,
#windowItemList : ProprietesDesElements]
Initialize(CRAPO, DescriptionDeLaFenetre)
Run(CRAPO)
end if
end
Dès l'ouverture du dialogue et pendant l'utilisateur en
manipule les contrôles, TOTO est incessamment appelé.
Lorsque l'objet invoque le gestionnaire TOTO, il lui transmet trois
arguments essentiels. Ces arguments décrivent respectivement
le type d'événement ( ouverture de la fenêtre,
déplacement d'un contrôle, clic...), Le numéro
d'ordre de l'élément concerné par l'événement
("void" si l'événement est l'ouverture de la fenêtre)
enfin la liste des propriétés définissant cet
élément (permettant ainsi de connaître les modifications
subies). On peut utiliser chacun de ces arguments indifféremment
afin de connaître les événements utilisateur
et d'y réagir.
Les types d'événement sont retournés par des
symboles. Ce peuvent-être : #windowOpening signalant
l'ouverture de la boîte, #itemChanged, qui indique une modification
quelconque, #itemClicked, #windowClosed, etc.
on TOTO QuelSymboledEvenement, QuelElementConcerne, ProprietesDelElementConcerne
case QuelSymboledEvenement of
#windowOpening :
beep
-- on salue ainsi le premier évènement utilisateur
!
#itemChanged : -- un élément a été
modifié, on ne sait lequel encore
if the type of ProprietesDelElementConcerne = #integerSliderH
then
-- on vérifie que l'évènement
concerne
-- notre curseur en sondant
-- la liste de propriétés
transmise
set VALEURMODIFIEE to the value of ProprietesDelElementConcerne
-- on enregistre le choix utilisateur
dans
-- la variable VALEURMODIFIEE
end if
#itemClicked :
-- ici deux cas sont possibles,
-- pour les distinguer on utilise
indifférement
-- l'un ou l'autre des arguments
passés,
-- QuelElementConcerne ou ProprietesDelElementConcerne.
if QuelElementConcerne = 4 then FermeLaFenetre
-- le bouton annuler est le quatrième
de la liste
-- Le gestionnaire FermeLaFenetre
-- executera les opérations
-- de nettoyage (destruction de
l'objet CRAPO)
if the title of ProprietesDelElementConcerne = "Redéfinir"
then
FermeLaFenetre
Utilise VALEURMODIFIEE
-- le gestionnaire utilise se
charge de traiter l'entrée utilisateur
end if
otherwise :
nothing
end case
end
Plus encore que la portabilité du code, C'est cette facilité
avec laquelle on récupère les entrées utilisateurs
complexes qui fait de l'Xtra MUI un outil intéressant. Pour
quel autre raison sinon, voudrait-on se perdre dans ce dédale
de listes imbriquées ?
LXtra MUI fait partie du package Director 6. Elle est chargée
au lancement de l'application. La version de MUI livrée avec
Director 6.0x est notoirement boguée. Macromedia soi-même
note que les modes de création du dialogue #pixel et #dialogUnit
y sont intervertis.
Pour une étude détaillée de la programmation
mui, on se reportera aux quelques exemples
rassemblés par le Crapo. L'Xtra EasyDialog
permet la création de dialogue en WYSIWYG puis la génération
automatique d'un script MUI dans la distribution Director. Un bon
moyen d'étudier la programmation MUI.
Le saviez-vous ? un dialogue MUI ne se comporte pas tout à
fait comme un dialogue système. On peut, au moins sur Mac
et sur D6, déformer ses contrôles lors que, le dialogue
étant affiché, on clique sur l'un d'entre eux avec
les touches Commande, Contrôle, Shift et Option enfoncées.
Parfaitement inutile !
<
Sommaire
|