Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : MUI - plus loin dans les classes
(Article écrit par Mathias Parnaudeau - juillet 2004)
|
|
Chapitre 3
Allez, il est temps que notre application ressemble un peu à un lecteur de CD ! Après avoir passé en revue
les éléments nécessaires à l'élaboration basique de l'interface, nous passerons à leur mise en place dans le source,
en nous basant sur celui du chapitre 2. Ceci fera intervenir les groupes de manière un peu plus poussée.
Cahier des charges
En regardant sur une platine CD de salon classique, on remarque les éléments suivants :
- Les boutons Précédent, Suivant, Jouer, Pause, Arrêter.
- Le bouton de volume qui peut être représenté par une réglette.
- L'affichage du numéro de la piste courante (et éventuellement de la position en minutes et secondes).
- Un voyant lumineux indiquant que la lecture est en cours (admettons que ça soit le cas, histoire de
réutiliser notre objet de classe Busy :)).
Après avoir décidé de ce qui serait présent, il faut agencer tout cela puisque cette décision déterminera
l'arborescence des objets : souvenez-vous des couples Child/End.
On fixera la liste des pistes en premier, c'est-à-dire en haut et occupant presque toute la largeur. En
effet, sur la droite, nous mettrons une glissière verticale, surmontée de l'annotation "Volume". En dessous,
on placera les boutons alignés horizontalement avec au bout un champ de texte (en lecture seule) indiquant
la piste courante. Puis tout en bas un objet Busy de faible épaisseur.
Concrètement
On remarque donc que nous avons à faire à trois groupes horizontaux superposés :
- Affichage de la liste des pistes et volume.
- Boutons et indicateur de la piste courante.
- Voyant lumineux Busy comme témoin de lecture.
Voici comme on dit le pseudo-code équivalent :
Window
VGroup
HGroup
Liste
VGroup
Label Volume
Glissière (Slider)
HGroup
Bouton Précédent
Bouton Suivant
Bouton Jouer
Bouton Pause
Bouton Stop
Texte avec numéro de piste
Busy
J'espère que tout cela est clair et que vous visualisez l'aspect que le lecteur va revêtir. Cette imbrication
de groupes horizontaux et verticaux représente une première difficulté. L'autre réside dans les trois nouvelles
classes utilisées pour les composants suivants :
- Le label qui contient le mot "Volume", son usage est on ne peut plus simple !
- Le volume.
- La liste des chansons.
Le volume utilise la classe interne Slider (glisseur) dont l'autodoc est très accessible. Ses attributs sont : sa représentation
verticale ou horizontale, sa valeur minimum et maximum, sa valeur de départ, etc. Pour notre exemple, on a choisi
arbitrairement les limites 0 et 100, avec 38 comme valeur initiale. On fixe l'attribut MUIA_Lister_Reverse à TRUE
pour obtenir le 0 en bas.
Lorsqu'on regarde dans la documentation (ce qu'il faut toujours faire :)) on s'aperçoit que la plupart des attributs
sont indiqués comme obsolètes. En fait, puisque l'on utilise des valeurs numériques, les attributs recommandés
sont les équivalents de la classe builtin Numeric : MUIA_Numeric_Max au lieu de MUIA_Slider_Max, etc. Cela ne
change rien dans le fonctionnement mais c'est plus correct au niveau de la conception. Et logique, tout simplement !
Pour visualiser toutes ces nouvelles notions, voici le source :
/*
* DisKo3.c (08/06/04)
*
*/
#include <stdio.h>
#include <libraries/mui.h>
#include <proto/intuition.h>
#include <proto/muimaster.h>
#include <proto/exec.h>
#include <clib/alib_protos.h>
#include <mui/Busy_mcc.h>
#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))
struct Library *MUIMasterBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
#ifdef __amigaos4__
struct IntuitionIFace *IIntuition;
struct MUIMasterIFace *IMUIMaster;
#endif
#define MUIA_Application_UsedClasses 0x8042e9a7 /* V20 STRPTR * i.. */
static STRPTR ClassList[] =
{
"Busy.mcc",
NULL
};
void CreateGui(void)
{
Object *app = NULL;
Object *window = NULL;
Object *bt_play, *bt_stop, *bt_previous, *bt_next, *bt_pause, *bt_eject;
Object *busy;
Object *sl_volume;
Object *lv_pistes;
Object *list;
/* Description de l'interface et de ses propriétés */
app = (Object *)ApplicationObject,
MUIA_Application_Author, "corto@guru-meditation.net",
MUIA_Application_Base, "DISKO",
MUIA_Application_Title, "DisKo - Exemple 3",
MUIA_Application_Version, "$VER: DisKo 1.03 (08/06/04)",
MUIA_Application_Copyright, "Mathias PARNAUDEAU",
MUIA_Application_Description, "Player de CD audio minimaliste",
MUIA_Application_HelpFile, NULL,
MUIA_Application_UsedClasses, ClassList,
SubWindow, window = WindowObject,
MUIA_Window_Title, "DisKo - release 3",
MUIA_Window_ID, MAKE_ID('W', 'I', 'N', '1'),
WindowContents, VGroup,
Child, HGroup,
Child, lv_pistes = ListviewObject,
MUIA_Listview_Input, FALSE,
MUIA_Listview_List, list = ListObject,
ReadListFrame,
MUIA_List_Format, "P=\33r",
End,
End,
Child, VGroup,
Child, Label("Volume"),
Child, sl_volume = SliderObject,
MUIA_Group_Horiz, FALSE,
MUIA_Numeric_Min, 0,
MUIA_Numeric_Max, 100,
MUIA_Numeric_Value, 38,
MUIA_Numeric_Reverse, TRUE,
End,
End,
End,
/* Utilisation d'un groupe horizontal pourvu de boutons */
Child, HGroup,
Child, bt_previous = KeyButton("Précédent", 'p'),
Child, bt_next = KeyButton("Suivant", 'v'),
Child, bt_play = KeyButton("Jouer", 'j'),
Child, bt_pause = KeyButton("Pause", 'a'),
Child, bt_stop = KeyButton("Arrêter", 's'),
Child, bt_eject = KeyButton("Ejecter", 'e'),
End,
Child, busy = BusyObject,
MUIA_Busy_Speed, MUIV_Busy_Speed_Off,
End,
End,
End,
End;
/* On fixe quelques valeurs et notifications */
DoMethod(window,
MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
app, 2,
MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
set(bt_stop, MUIA_Disabled, TRUE);
DoMethod(busy, MUIM_Busy_Move, FALSE);
DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
bt_stop, 3, MUIM_Set, MUIA_Disabled, FALSE);
DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
bt_play, 3, MUIM_Set, MUIA_Disabled, TRUE);
DoMethod(bt_stop, MUIM_Notify, MUIA_Pressed, FALSE,
bt_play, 3, MUIM_Set, MUIA_Disabled, FALSE);
DoMethod(bt_stop, MUIM_Notify, MUIA_Pressed, FALSE,
bt_stop, 3, MUIM_Set, MUIA_Disabled, TRUE);
DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
busy, 3, MUIM_Set, MUIA_Busy_Speed, 20);
DoMethod(bt_stop, MUIM_Notify, MUIA_Pressed, FALSE,
busy, 3, MUIM_Set, MUIA_Busy_Speed, MUIV_Busy_Speed_Off);
DoMethod(list, MUIM_List_InsertSingle, "1 - Première piste", MUIV_List_Insert_Bottom);
DoMethod(list, MUIM_List_InsertSingle, "2 - Deuxième piste", MUIV_List_Insert_Bottom);
SetAttrs(window, MUIA_Window_Open, TRUE, TAG_END);
/* Boucle de gestion des événements, toujours la même */
{
ULONG sigs = 0;
while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
{
if (sigs)
{
sigs = Wait(sigs | SIGBREAKF_CTRL_C);
if (sigs & SIGBREAKF_CTRL_C) break;
}
}
}
set(window, MUIA_Window_Open, FALSE);
/* Libération des ressources et fermeture */
MUI_DisposeObject(app);
}
/*
* Initialisation et vérification de tout ce qui est nécessaire à la bonne exécution
* de l'application : ouverture des bibliothèques, test de présence des classes MCC, ...
*/
int Initialize(void)
{
int res = 1;
Object *busy = NULL;
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39L);
MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN);
if (IntuitionBase == NULL){
printf("Impossible d'ouvrir 'intuition.library' V39\n");
res = 0;
}
if (MUIMasterBase == NULL){
printf("Impossible d'ouvrir '%s' V%d\n", MUIMASTER_NAME, MUIMASTER_VMIN);
res = 0;
}
#ifdef __amigaos4__
IIntuition = (struct IntuitionIFace *)GetInterface((struct Library *)IntuitionBase, "main", 1, NULL);
if (!IIntuition){
printf("Impossible d'obtenir l'interface IIntuition\n");
res = 0;
}
IMUIMaster = (struct MUIMasterIFace *)GetInterface(MUIMasterBase, "main", 1, NULL);
if (!IMUIMaster){
printf("Impossible d'obtenir l'interface IMUIMaster\n");
res = 0;
}
#endif
busy = BusyObject, End;
if (busy == NULL){
printf("Classe Busy manquante\n");
res = 0;
}
MUI_DisposeObject(busy);
return res;
}
/*
* Fermeture et libération de tout ce qui a été initialisé au démarrage.
*/
void DeInitialize(void)
{
#ifdef __amigaos4__
if (IMUIMaster) {
DropInterface((struct Interface *)IMUIMaster);
}
if (IIntuition) {
DropInterface((struct Interface *)IIntuition);
}
#endif
CloseLibrary(MUIMasterBase);
CloseLibrary((struct Library *)IntuitionBase);
}
int main(int argc, char **argv)
{
if(Initialize()){
CreateGui();
}
DeInitialize();
return 0;
}
|
Sur la liste
En prévision de l'affichage des titres des chansons, un composant de type liste a été ajouté. La
construction d'une liste repose en réalité sur deux classes, List et Listview, qui gèrent respectivement
la gestion de la liste (manipulation de ses éléments) et sa représentation. La listview ne propose que
peu d'options, les efforts devront être portés sur la richesse de la classe List, qui se trouve alors "embarquée"
dans la listview.
Il a été choisi d'employer les classes List et Listview d'origine même si de nombreuses applications utilisent
les classes NList et NListView, plus complètes et compatibles. Nos besoins n'étant pas très étendus, nous
privilégions la simplicité. Nous ne perdrons rien dans les fonctionnalités liées aux listes que nous aborderons.
Par contre, attention à ne pas mélanger ces deux groupes ! Leur compatibilité autoriserait une compilation
sans soucis mais des surprises (mauvaises !) sont à prévoir dans le comportement de la liste produite.
Le contenu de la liste est géré par un objet List que l'on doit affecté à la Listview via l'attribut MUIA_Listview_List.
La List interne contient ses propres attributs comme MUIA_List_Format pour déterminer comment cela sera affiché par
la listview : définition de plusieurs colonnes, justification du texte (ici à droite pour que ça soit marquant,
avec \33r), etc. L'incontournable DoMethod() est utilisée par deux fois avant l'ouverture de la fenêtre pour ajouter
une ligne de texte avec MUIM_List_InsertSingle, soit deux lignes au total. On simule ainsi la lecture des
titres des pistes d'un hypothétique CD. A noter qu'il est possible d'ajouter plusieurs lignes en même temps avec
MUIM_List_Insert.
Notions acquises dans ce chapitre
- Conception d'une interface, agencement des groupes.
- Introduction aux importantes classes List et Listview.
|