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 type 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 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 fait disparaître la boîte (sur Mac).
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 (un telle
chose existe-t-elle ?), 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, 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 !
|