Index   Table   Précédent   Suivant

3. Placement des widgets

Lorsqu'on crée un certain nombre de widgets, ils se placent toujours à un endroit par défaut, que vous pouvez ensuite modifier. Vous pouvez aussi cacher un widget (il n'est plus à l'écran et ne réagit plus) ou l'inactiver (il est visible mais ne réagit plus).

Index   Table   Précédent   Suivant

3.1. Placement manuel

Tout les widgets possèdent des coordonnées x,y par rapport au propriétaire, l'origine étant le coin intérieur en haut à gauche du propriétaire.

À 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.

Index   Table   Précédent   Suivant

3.2. Placement dans un Panel

Lorsqu'un widget est créé dans un Panel, le Panel fixe les coordonnées initiales du widget. Les coordonnées du widget peuvent ensuite être modifiée avec les fonctions 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.

Index   Table   Précédent   Suivant

3.3. Ajuster la taille

À un moment donné, on peut demander d'ajuster la taille d'un widget par rapport à son contenu ; il suffit d'appeler
    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
    /* 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);
    }

Index   Table   Précédent   Suivant

3.4. Alignement et élargissement

Les fonctions 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.

Index   Table   Précédent   Suivant

3.5. Afficher/cacher

Tout widget peut être visible ou caché. Si un widget est caché, on ne le voit pas à l'écran et il ne réagit pas. On utilise les fonctions :
    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
    /* 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);
    }

Index   Table   Précédent   Suivant

3.6. Activer/inactiver

La plupart des widget peuvent être inactivés. Un widget inactivé est un widget visible, mais qui ne réagit pas. Les widgets inactifs sont en général affichés dans une couleur plus claire. On utilise les fonctions :
    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
    /* 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);
    }


Index   Table   Début   Suivant