À la création, la plupart des widgets sont placés en 0,0 par défaut.
On récupère les coordonnées d'un widget hn par
int x1 = HeGetX(hn), y1 = HegetY(hn);
et on modifie ces coordonnées par
HeSetX(hn, x2); HeSetY(hn, y2);
Chaque widget possède également une largeur width et une hauteur height
int w1 = HeGetWidth(hn), h1 = HeGetHeight(hn);
que l'on modifie par
HeSetWidth(hn, w2); HeSetHeight(hn, h2);
Les changements au niveau de l'affichage sont automatiques. On peut
déplacer un widget de dx,dy par
HeSetX (hn, HeGetX(hn) + dx); HeSetY (hn, HeGetY(hn) + dy);
ou par le raccourci
HeMoveX (hn, dx); HeMoveY (hn, dy);
On peut de même changer la taille d'un widget avec HeMoveWidth et
HeMoveHeight.HeSetX
, HeSetY
.Par défaut, les widgets sont placés à la suite les uns des autres, sur une même ligne horizontale. On peut changer cela avec la fonction
HeSetPanelLayout (panel, layout);
où layout vaut HE_HORIZONTAL
, HE_VERTICAL
ou HE_LINE_FEED
.
Avec HE_VERTICAL
les widgets seront alignés les uns en dessous des
autres ; avec HE_LINE_FEED
les widgets sont placés horizontalement,
mais on change de ligne au moment où on fait cet appel. Ainsi
HeCreateButtonP (panel, "La", NULL, NULL);
HeCreateButtonP (panel, "première", NULL, NULL);
HeCreateButtonP (panel, "ligne", NULL, NULL);
HeSetPanelLayout(panel, HE_LINE_FEED);
HeCreateButtonP (panel, "puis", NULL, NULL);
HeCreateButtonP (panel, "la", NULL, NULL);
HeCreateButtonP (panel, "seconde", NULL, NULL);
crée deux lignes horizontales de boutons. On peut modifier
l'espacement entre les widgets avec
HeSetPanelXGap (panel, xgap);
HeSetPanelYGap (panel, ygap);
qu'il faut appeler AVANT de créer les widgets. On peut de même
modifier l'espacement entre les widgets et le bord du Panel avec
HeSetPanelXAlign (panel, xalign);
HeSetPanelYAlign (panel, yalign);
On peut récupérer les valeurs par défaut avec la fonction
HeGetPanel...(panel)
correspondante. HeFit (hn);
Pour certains widgets l'ajustement est automatique. Par exemple, les
widgets Button et Message recalculent leur taille chaque fois que
l'on change leur Label (on peut désactiver le mécanisme en faisant
HeSetAutoFit(hn,FALSE);
).Pour d'autres widgets l'opération est manuelle. C'est le cas pour les widgets Frame et Panel : une fois que tous les boutons sont créés dans un Panel, on ajuste le Panel par rapport aux boutons, et ensuite on ajuste le Frame par rapport au Panel. On fait donc dans l'ordre :
HeFit (panel);
HeFit (frame);
Pour certains widgets enfin, l'ajustement n'a pas de sens. C'est le
cas pour les widgets de dessin Canvas et GLArea. La fonction HeFit
ne
fait tout simplement rien. Dans l'exemple suivant on crée deux lignes de boutons et on ajuste la taille du Panel et de la fenêtre :
/* examples/button/layout.c */
#include <helium.h>
He_node *princ, *panel;
void butt_proc (He_node *hn)
{
char *nom = HeGetButtonLabel (hn);
printf ("butt_proc: %s\n", nom);
}
void quit_proc (He_node *hn)
{
HeQuit (0);
}
int main (int argc, char *argv[])
{
HeInit (&argc, &argv);
princ = HeCreateFrame ();
HeSetFrameLabel (princ, "Placement et ajustement");
panel = HeCreatePanel (princ);
HeCreateButtonP (panel, "Trouvez", butt_proc, NULL);
HeCreateButtonP (panel, "le", butt_proc, NULL);
HeCreateButtonP (panel, "bouton", butt_proc, NULL);
HeSetPanelLayout(panel, HE_LINE_FEED);
HeCreateButtonP (panel, "pour", butt_proc, NULL);
HeCreateButtonP (panel, "me", butt_proc, NULL);
HeCreateButtonP (panel, "quitter", quit_proc, NULL);
HeFit(panel);
HeFit(princ);
return HeMainLoop (princ);
}
HeGetWidth
et HeGetHeight
renvoient la largeur et
hauteur intérieure d'un widget. Pour certains widgets tels que les boutons, la taille intérieure correspond à la taille extérieure (c'est-à-dire totale) du widget. Ce n'est pas le cas pour le Panel ou le Canvas, qui peuvent avoir un bord (en général de 1 pixel, d'où largeur extérieure = largeur intérieure + 2). Ce n'est pas non plus le cas pour le Frame : il faut compter la taille de la barre de titre et de la décoration, qui sont rajoutés par le Window Manager.
On a donc introduit les fonctions suivantes, qui traitent tous les cas de figure : la largeur et la hauteur extérieure d'un widget s'obtient par
int w1 = HeGetExtWidth(hn), h1 = HeGetExtHeight(hn);
les coordonnées du point à l'extérieur en bas à droite du widget sont
obtenues par
int x1 = HeGetExtX(hn), y1 = HeGetExtY(hn);
Attention, les fonctions HeSetExt...()
n'existent pas pour le moment.
Pour placer un widget h2
à droite d'un widget h1
, on peut faire :
HeSetX (h2, HeGetExtX(h1));
Si ces widgets sont dans un Panel, il faut tenir compte de
l'espacement horizontal du Panel, et faire à la place
HeSetX (h2, HeGetExtX(h1) + HeGetPanelXGap(panel));
Pour simplifier l'alignement des widgets, on introduit la fonction
HeJustify
, qui traite tous les cas de figure.
HeJustify (hn, ref, pos);
justifie (c'est-à-dire aligne sur un bord) le widget hn
par rapport au
widget ref
.
Si ref
est NULL, le widget hn
est justifié par rapport au bord de son
père (très pratique). Si ref
est non NULL, ref
et hn
doivent avoir le
même père (pour qu'ils aient le même système de coordonnées relatives)
sinon il y a un message d'erreur. pos
peut être l'une des
constantes HE_LEFT
, HE_RIGHT
, HE_TOP
, HE_BOTTOM
ou HE_TOP_LEFT
,
HE_BOTTOM_LEFT
, HE_TOP_RIGHT
, HE_BOTTOM_RIGHT
(qui font deux
justifications à la fois).
Dans notre exemple, pour placer h2
à droite de h1
il suffit de
justifier h2
à gauche par rapport à h1
:
HeJustify (h2, h1, HE_LEFT);
Le même problème se pose lorsqu'on veut élargir un widget pour qu'il
occupe toute la place disponible jusqu'à un autre widget ou jusqu'au
bord du propriétaire. On introduit la fonction HeExpand
, qui traite
tous les cas de figure (maintien de l'espacement dans un Panel, pas
d'espacement dans un Frame, taille de la décoration des Frame, etc) :
HeExpand (hn, ref, pos);
élargit (ou rétrécit) le widget hn
jusqu'au widget ref
. Si ref
est
NULL, le widget hn
est élargi jusqu'au bord de son père. Si ref
est
non NULL, ref
et hn
doivent avoir le même père sinon il y a un
message d'erreur. pos
peut être l'une des constantes HE_LEFT
,
HE_RIGHT
, HE_TOP
, HE_BOTTOM
ou HE_TOP_LEFT
, HE_BOTTOM_LEFT
,
HE_TOP_RIGHT
, HE_BOTTOM_RIGHT
.
Par exemple, pour que h1
occupe tout l'espace à gauche de h2
,
on élargit h1
à droite vers h2
:
HeExpand (h1, h2, HE_RIGHT);
On verra plus loin l'utilité de ces fonctions pour adapter la
position et la taille des widgets lorsqu'une fenêtre est
redimensionnée. void HeSetShow (He_node *hn, int show);
int HeGetShow (He_node *hn);
pour afficher ou cacher un widget hn. Par défaut, à la création tous
les widgets sont visibles, sauf les Frame qui sont tous cachés.
(voir la section « Afficher une fenêtre »). L'exemple suivant montre comment réaliser un bouton qui fait apparaître ou disparaître un autre bouton.
/* examples/button/show.c */
#include <helium.h>
He_node *princ, *panel, *butt1;
void show_proc (He_node *hn)
{
HeSetShow (butt1, !HeGetShow(butt1));
}
int main (int argc, char *argv[])
{
HeInit (&argc, &argv);
princ = HeCreateFrame ();
HeSetFrameLabel (princ, "Afficher un bouton");
panel = HeCreatePanel (princ);
HeCreateButtonP (panel, "Afficher/cacher", show_proc, NULL);
butt1 = HeCreateButtonP (panel, "Cible", NULL, NULL);
return HeMainLoop (princ);
}
void HeSetActive (He_node *hn, int active);
int HeGetActive (He_node *hn);
Par défaut, à la création tous les widgets sont actifs. L'exemple
suivant montre comment réaliser un bouton qui active ou inactive
un autre bouton.
/* examples/button/active.c */
#include <helium.h>
He_node *princ, *panel, *butt1;
void acti_proc (He_node *hn)
{
HeSetActive (butt1, !HeGetActive(butt1));
}
int main (int argc, char *argv[])
{
HeInit (&argc, &argv);
princ = HeCreateFrame ();
HeSetFrameLabel (princ, "Activer un bouton");
panel = HeCreatePanel (princ);
HeCreateButtonP (panel, "Activer/inactiver", acti_proc, NULL);
butt1 = HeCreateButtonP (panel, "Cible", NULL, NULL);
return HeMainLoop (princ);
}