MOTIF: Finger in Ze NoZe Alors que pour les mini-projets de deuxième année, beaucoup doivent ou souhaitent utiliser les librairies motif, je vais essayer de faciliter la découverte de cette librairie X en présentant brièvement Xmt: X Motif Tools, et en décrivant une application toute simple mais assez bluffante, vu la taille de son code source. Motif en est à sa version 2.0, et tous ceux qui ont fait l expérience de la toolkit Motif savent comme cette librairie est puissante, mais également frustrante. Au début, il y avait le problème des bugs, mais ceux-ci tendent à disparaître. la XToolkit de X11R4 et R5 est maintenant assez fiable et les widgets motif 1.2.2 (dernière version dispo à l EERIE) ont été nettement améliorés par rapport à ceux de la version 1.0. Motif reste cependant assez énervant. En fait, motif n a pas été conçu dans l optique de la facilité d utilisation par les programmeurs. La XToolkit a été réalisée d après le mot d ordre du X Consortium mechanism, not policy pour être une architecture standard, et motif n est censé qu apporter un niveau de base aux fonctionnalités de l interface utilisateur: des boutons, ascenseurs,... Maintenant, toute application graphique possède un menu -sauf peutêtre les "mandelbrots" des premières années- or Motif n a pas de widget menu à proprement parler. Pour l aide en ligne c est pareil: aucun widget n existe. Quant au type XmString, c est la cata complète: impossible de changer de 18 police ou de graisse, difficile d intégrer des retour chariots dans une chaîne,... et XmString n offre pourtant aucun véritable avantage sur le bête tableau de char. Il ne faut cependant pas exagérer, Motif apporte quand même un avantage certain par rapport au X pur, ne serait ce que pour le widget bouton: essayez de faire un joli bouton ombré avec du texte dedans et qui bouge quand on appuie dessus! en motif ça prend une ligne. Tout cela pris en compte, un certain David Flanagan s est dit que ce serait pas mal de partir de motif pour faire un truc vraiment sympa. D où Xmt : X motif tools (j ai pas dit que sympa se disait tools en anglais, tools ce serait plutôt outils). Xmt c est donc quelques widgets en plus pour là où ça faisait mal: XmtLayout pour le positionnement des widgets (XmForm, l équivalent motif pur, fait vraiment pitié à côté), XmtChooser: des ensembles de boutons tout prêts, des widgets pour l aide contextuelle, d autres pour faire attendre l utilisateur final, des lignes de commande etc... Xmt c est aussi plus de 260 fonctions et des convertisseurs pour faciliter le développement. Enfin Xmt permet un design rapide de l interface. le programme UIL -user interface language- existait déjà pour cela, Xmt avec son système de ressources "application default" va encore plus loin: plus clair plus puissant et plus compact (un fichier UIL pouvait faire plusieurs milliers de lignes pour
une application assez simple, avec Xmt, ça peut se réduire à quelques centaines). Xmt 2.0 est installé à l eerie dans /usr/ local/tool/xmt. On a une seule license, mais le reste est considéré comme shareware. Xmt marche avec motif et X11R5. je l ai compilé avec motif 1.2.2 sur sun, il faudra le refaire sur HP si le besoin s en ressent. Pour les chemins regarder dans le Makefile. De la doc sur xmt se trouve dans ~xmt/ 2.0.0/cat (man en format texte) et ~xmt/ 2.0.0/examples Divers programmes se trouvent dans ~xmt/2.0.0/clients notamment mockup: un interprêteur de ressources pour tester avant de compiler (essayer mockup demo), et divers scripts sed pour valider ou convertir des fichier.ad en.h ou des bitmaps.xpm ou.xbm en.ad. Voici donc le source commenté d une application bidon "exemple" montrant le principe général. Vous allez voir, c est vraiment bluffant. Un snapshot de l'écran est reproduit ci-dessous. L'application se compose d'un menu et d'une fenêtre. Le menu est "tear off",: on peut le détacher. L'option Open est une boîte motif toute prête et la fonction "callback" qui lui est associée renvoie le chemin complet du fichier choisi. Pour mettre en évidence la communication possible dans les deux sens, j'ai utilisé cette chaîne de caractères pour changer le texte dans la fenêtre principale. Le menu de boutons libellés 1, 2 et 3 active un callback très simple qui imprime par un bête printf la valeur sélectionnée dans la xterm appellante. Je pense l avoir assez commenté, mais n hésitez pas à me poser des questions. François "^J" Nguyen Biblio: Motif Tools D. I. Flanagan, ORA OSF/Motif Programmer's reference, PrenticeHall Sources: L'exemple se trouve, source et exécutable dans ~nguyen/projet/exemple. 19
exemple.ad (les ressources)!couleurs *Foreground: navy *Background: gray!polices *FontList:*-helvetica-medium-r-*-*-*-140-*=R,\ *-helvetica-bold-r-*-*-*-140-*=b!description du widget exemple exemple.title: exemple - Copyright \251 1995 exemple.mwmmenu: \ "dummy" f.separator\n\ "Pass Keys" _K Meta<Key>K f.pass_keys\n\ "Refresh" _R Meta<Key>R f.refresh_win exemple.xmtchildren: XmtLayout layout;\ XmDialogShell FileSelSh; *layout.xmtchildren: XmtMenu menubar; XmtLayout workarea; *layout.layout: Fixed 12mm High menubar 600pt % 1.5in workarea *layout.marginwidth:2 *layout.marginheight:2 *menubar.height : 30 *menubar.items: Tearoff "_File" -> file ; *menubar*file.items: \ "_Open..." [Meta+O] XtManageChild(*fileSel);\ "E_xit" [Ctrl-C] exit(0); *FileSelSh.xmtChildren : unmanaged XmFileSelectionBox filesel; *filesel.activatecallback:getfileselectionvalue();xtunmanagechild(*filesel); *filesel.dirmask : *.c *filesel.okcallback : GetFileSelectionValue();\ XtUnmanageChild(*fileSel); *filesel.cancelcallback :XtUnmanageChild(*fileSel); *workarea.xmtchildren : XmLabel Label ; XmtChooser Chooser; *workarea.layoutframetype : XmtLayoutFrameBox *workarea.layout : 28mm Wide Fixed Chooser Label *workarea.orientation : XmHORIZONTAL *Label.labelString : bonjour *Chooser.chooserType: Option *Chooser.layoutCaption: @fb exemple @fr *Chooser.strings: "zero", "un", "deux" *Chooser.layoutCaptionPosition: Top *Chooser.valueChangedCallback : SetChooserValue(); 20
#include <Xmt/Xmt.h> #include <Xmt/Layout.h> #include <Xmt/Converters.h> #include <Xmt/Procedures.h> #include <Xmt/Dialogs.h> #include <Xmt/Chooser.h> #include <Xmt/WorkingBox.h> #include <Xm/FileSB.h> exemple.c /* Motif 1.2.2 a ete compile avec R6, on n a que R5, pour eviter * des warnings de compilation on declare cette fonction */ char* _Xsetlocale (){printf("appel Xsetlocale\n"); /* les ressources (du fichier exemple.ad) */ static char *fallback[] = { #include "exemple.h" (char*) NULL ; Widget toplevel; /* -------------------------------- */ /* ---------- Les CallBacks ------------- */ /* ------------------------------- */ static void SetChooserValue ( Widget w, XtPointer client_data, XtPointer call_data ) { XmtChooserCallbackStruct *data; data = (XmtChooserCallbackStruct*) client_data; printf(«%i\n», (data->item)); return; static void GetFileSelectionValue(Widget w, XtPointer client_data, XtPointer call_data ) { Arg args; XmFileSelectionBoxCallbackStruct *data= (XmFileSelectionBoxCallbackStruct*) client_data; XtSetArg(args, XmNlabelString, data->value); XtSetValues (XmtNameToWidget(toplevel, "*Label"), &args, 1); return; /*---------------------------------main-------------------------------*/ /*----------installe les ressources et lance la main loop-------------*/ void main(int argc, char **argv) { XtAppContext app; int i; /*initialise l application ( et lecture fallbacks ) */ toplevel = XtAppInitialize (&app, "exemple", NULL, 0, &argc, argv, fallback, NULL, 0); 21
XmtRegisterAll(); /*enregistrement nom des callbacks */ XmtVaRegisterCallbackProcedures( «SetChooserValue», SetChooserValue,XmtRCallbackData, «GetFileSelectionValue», GetFileSelectionValue,XmtRCallbackData, NULL); /* enregistre les convertisseurs */ /* gere la hierarchie de widgets a parit de toplevel */ XmtCreateChildren(toplevel); XtRealizeWidget(toplevel); /*main loop */ XtAppMainLoop(app); Makefile CC= gcc AD2C= /usr/local/tool/xmt/clients/ad2c LIBS = -L/usr/local/tool/X11R5/lib -L/usr/local/prod/motif/1.2.2/lib -L/ usr/local/lib/xmt -lxmt -lxm -lxt -lx11 -lxext -lm INCLUDES=-I/usr/local/tool/X11R5/include -I/usr/local/prod/motif/1.2.2/ include -I/usr/local/include all : exemple exemple.h : exemple.ad ${AD2C exemple.ad > exemple.h exemple : exemple.o ${CC -o exemple exemple.o ${LIBS exemple.o : exemple.c exemple.h ${CC -c exemple.c ${INCLUDES clean : rm -f *.o exemple 22