À 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);
}