Programmation GTK2 en Pascal/GtkNotebook

Programmation GTK2 en Pascal

Présentation modifier

Nous allons étudier dans ce chapitre les pages à onglets qui sont souvent utilisés dans les fenêtres de configuration. Pour cela nous allons utiliser le contrôle GtkNotebook qui dérive du contrôle GtkContainer.

Hiérarchie modifier

Hiérarchie
GObject
  └─GtkObject
      └─GtkWidget
          └─GtkContainer
              └─GtkNotebook

Utilisation de base modifier

Création modifier

Pour ne pas changer la création du contrôle en lui-même est très simple :

function gtk_notebook_new : PGtkWidget;

Maintenant que notre contrôle est créé, nous allons lui ajouter des pages.

Insertion de pages modifier

Nous avons là aussi trois fonctions qui restent très classiques :

procedure gtk_notebook_append_page(notebook : PGtkNotebook; child : PGtkWidget; tab_label : PGtkWidget);
procedure gtk_notebook_prepend_page(notebook : PGtkNotebook; child : PGtkWidget; tab_label : PGtkWidget);
procedure gtk_notebook_insert_page(notebook : PGtkNotebook; child : PGtkWidget; tab_label : PGtkWidget;
  position : gint);

La première fonction ajoute une nouvelle page à onglet à la suite des autres, la deuxième fonction l'ajoute au début, et la dernière l'ajoute à une position particulière.

Le premier paramètre, notebook, est bien sûr le GtkNotebook dans lequel nous voulons ajouter la page. Il faudra utiliser la fonction de conversion GTK_NOTEBOOK().

Le second, child, est le contrôle qui sera inséré dans la nouvelle page, et le troisième, tab_label, le contrôle qui sera affiché dans l'onglet.

La troisième fonction demande un paramètre supplémentaire, position, qui est la position à laquelle il faut ajouter la page. Si la valeur n'est pas correcte (négative ou trop grande) la page sera ajoutée à la suite des autres.

Gestion des pages modifier

Nous allons maintenant voir les fonctions qui permettent de connaître le nombre de page, la page en cours ainsi que d'autres fonctions.

Tout d'abord, la fonction suivante permet de connaître le nombre total de pages contenus dans le GtkNotebook. Bizarrement cette fonction n'existe pas dans les déclarations de gtk2forpascal ! Pour l'utiliser, il faudra donc la déclarer manuellement :

function gtk_notebook_get_n_pages(notebook : PGtkNotebook) : gint; cdecl; external gtklib;

Ensuite, pour connaître le numéro de la page courante, nous avons cette fonction :

function gtk_notebook_get_current_page(notebook : PGtkNotebook) : gint;

Par contre pour connaître le numéro d'une autre page que la courante, il faudra utiliser cette fonction :

function gtk_notebook_page_num(notebook : PGtkNotebook; child : PGtkWidget) : gint;

Cette fonction permet d'obtenir le numéro de la page contenant le contrôle child, ce qui impose donc d'avoir garder une trace de ce contrôle pour pouvoir utiliser cette fonction.

Avec un numéro de page, nous allons pouvoir récupérer un pointeur sur le contrôle qui est contenu dans la page avec cette fonction :

function gtk_notebook_get_nth_page(notebook : PGtkNotebook; page_num : gint) : PGtkWidget;

Ou bien nous allons pouvoir tout simplement supprimer la page :

procedure gtk_notebook_remove_page(notebook : PGtkNotebook; page_num : gint);

Et pour terminer, voici trois fonctions de navigation :

procedure gtk_notebook_next_page(notebook : PGtkNotebook);
procedure gtk_notebook_prev_page(notebook : PGtkNotebook);
procedure gtk_notebook_set_current_page(notebook : PGtkNotebook; page_num : gint);

La première fonction passe de la page courante à la page suivante. Si la dernière page est déjà affichée, il ne se passera rien. La deuxième fonction, elle, passe de la page courante à la page précédente. Bien entendu, si la page courante est déjà la première cette fonction n'aura aucun effet. La dernière fonction quant à elle passe directement à une page précise. Si la valeur de page_num est négative, nous passerons à la dernière page, par contre si cette valeur est trop grande, aucune action ne sera faite.

Gestion des labels modifier

Nous allons maintenant voir comment modifier ou récupérer le label d'une page. Attention pour chacune de ces fonctions, il faut connaître le contrôle contenu dans la page.

Tout d'abord, pour récupérer le label de la page, il existe deux fonctions différentes :

function gtk_notebook_get_tab_label_text(notebook : PGtkNotebook; child : PGtkWidget) : Pgchar;
function gtk_notebook_get_tab_label(notebook : PGtkNotebook; child : PGtkWidget) : PGtkWidget;

La première fonction renvoie directement le label de la page sous la forme d'un Pgchar. Cette fonction fonctionnera correctement uniquement si le label de la page est un GtkLabel, car comme nous l'avons vu lors de l'étude des fonctions d'insertion des pages, il est possible de définir le label comme autre chose qu'un GtkLabel. Dans ce cas, il faut utiliser la deuxième fonction qui elle renvoie le contrôle qui a été utilisé lors de la création.

Pour définir un nouveau label pour une page, il existe là aussi deux fonctions :

procedure gtk_notebook_set_tab_label_text(notebook : PGtkNotebook; child : PGtkWidget; tab_text : Pgchar);
procedure gtk_notebook_set_tab_label(notebook : PGtkNotebook; child : PGtkWidget; tab_label : PGtkWidget);

La première fonction permet de définir un label de type GtkLabel. Cette fonction s'occupe de la création du GtkLabel et de son insertion dans l'onglet de la page. La deuxième fonction permet d'insérer n'importe quel contrôle dans l'onglet, comme pour les fonctions de création. Dans les deux cas, si les paramètres tab_text ou tab_label sont définis comme NULL, le label de la page sera « Page y », y étant le numéro de la page.

Modification des propriétés des onglets modifier

Nous allons maintenant voir comment modifier trois des propriétés d'un GtkNotebook.

Tout d'abord voyons comment gérer la position des onglets :

procedure gtk_notebook_set_tab_pos(notebook : PGtkNotebook; pos : TGtkPositionType);
function gtk_notebook_get_tab_pos(notebook : PGtkNotebook) : TGtkPositionType;

La première fonction permet de modifier la position des onglets. C'est le paramètre pos qui définit sa position, et il doit prendre une des valeurs suivantes :

  • GTK_POS_LEFT pour les mettre à gauche ;
  • GTK_POS_RIGHT pour les mettre à droite ;
  • GTK_POS_TOP pour les mettre en haut ;
  • GTK_POS_BOTTOM pour les mettre en bas.

La deuxième fonction permet au contraire de connaître la position des onglets. La valeur de retour est obligatoirement une des quatre valeurs précédentes.

Ensuite nous allons pouvoir définir si les onglets doivent s'afficher ou pas avec ces fonctions :

procedure gtk_notebook_set_show_tabs(notebook : PGtkNotebook; show_tabs : gboolean);
function gtk_notebook_get_show_tabs(notebook : PGtkNotebook) : gboolean;

Si nous voulons modifier ce paramètre, il faut utiliser la première fonction en mettant le paramètre show_tabs à TRUE pour les afficher et à FALSE dans le cas contraire. La deuxième fonction permet quant à elle de connaître l'état de cette propriété.

Et enfin, pour terminer nous allons voir comment ajouter deux boutons de navigation à la fin des onglets, pour le cas où il y aurait trop d'onglets à afficher :

procedure gtk_notebook_set_scrollable(notebook : PGtkNotebook; scrollable : gboolean);
function gtk_notebook_get_scrollable(notebook : PGtkNotebook) : gboolean;

Si nous mettons le paramètre scrollable de la première fonction à TRUE, deux boutons de navigation apparaîtront et une partie seulement des onglets sera affichée. Pour accéder aux autres onglets il faudra utiliser ces nouveaux boutons.

Bien entendu, la deuxième fonction permet de savoir si les boutons de navigation sont présents ou pas.

Programme exemple modifier

Nous allons créer un programme qui insèrera un GtkNotebook de 8 pages dans une fenêtre. Chaque page contiendra uniquement un label « Je suis le GtkLabel numero x ». Il y a aussi un bouton qui permettra d'afficher les informations de la page sélectionnée dans une boîte de dialogue.

Voilà le fichier gtk009.pas :

program gtk009;

uses glib2, gtk2, SysUtils;

procedure OnBoutonClick(ABouton : PGtkwidget; AData : pgpointer); cdecl;
var
  pDialogue : PGtkWidget;
  pContEnfant : PGtkWidget;
  NoPage : GInt;
  TexteLabel : PGChar;
  TexteOnglet : PGChar;
  TexteDialogue : PGChar;
begin
  // Récuperation de la page active 
  NoPage := gtk_notebook_get_current_page(GTK_NOTEBOOK(AData));
  // Récuperation du contrôle enfant 
  pContEnfant := gtk_notebook_get_nth_page(GTK_NOTEBOOK(AData), NoPage);

  // Récuperation du label 
  TexteLabel := gtk_label_get_text(GTK_LABEL(pContEnfant));
  // Récuperation du label de l'onglet
  TexteOnglet := gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(AData), pContEnfant);

  // Création du label de la boite de dialogue 
  TexteDialogue := g_strdup_printf('C' 'est la page %d'#13#10 +
    'Le label est "%s"'#13#10 +
    'Le label de l' 'onglet est "%s"',
    [NoPage, TexteLabel, TexteOnglet]);

  pDialogue := gtk_message_dialog_new(NULL,
    GTK_DIALOG_MODAL,
    GTK_MESSAGE_INFO,
    GTK_BUTTONS_OK,
    TexteDialogue);

  gtk_dialog_run(GTK_DIALOG(pDialogue));
  gtk_widget_destroy(pDialogue);
  g_free(TexteDialogue);
end;

var
  pFenetre    : PGtkWidget;
  pVBox       : PGtkWidget;
  pNotebook   : PGtkWidget;
  pBouton     : PGtkWidget;
  I           : gint;
  pLabel      : PGtkWidget;
  pTabLabel   : PGtkWidget;
  TexteLabel  : PGChar;
  TexteOnglet : PGChar;
begin
  gtk_init(@argc, @argv);
  pFenetre := gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(pFenetre), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(pFenetre), 320, 200);
  gtk_window_set_title(GTK_WINDOW(pFenetre), 'Gtk009 : GtkNoteBook');
  gtk_signal_connect(pGTKOBJECT(pFenetre), 'destroy', GTK_SIGNAL_FUNC(@gtk_main_quit), NULL);

  // Création de la GtkVBox et ajout dans la fenêtre
  pVBox := gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(pFenetre), pVBox);

  // Au tour du bouton
  pBouton := gtk_button_new_with_label('Informations');
  gtk_box_pack_start(GTK_BOX(pVBox), pBouton, FALSE, FALSE, 0);

  // Creation du GtkNotebook 
  pNotebook := gtk_notebook_new;
  gtk_box_pack_start(GTK_BOX(pVBox), pNotebook, TRUE, TRUE, 0);
  // Position des onglets : en bas 
  gtk_notebook_set_tab_pos(GTK_NOTEBOOK(pNotebook), GTK_POS_BOTTOM);
  // Ajout des boutons de navigation 
  gtk_notebook_set_scrollable(GTK_NOTEBOOK(pNotebook), TRUE);

  // Création de chacune des pages d'onglet
  for I := 1 to 8 do begin
    TexteLabel := g_strdup_printf('Je suis le GtkLabel numéro %d', [I]);
    TexteOnglet := g_strdup_printf('Page %d', [I]);

    // Création des différents GtkLabel 
    pLabel := gtk_label_new(TexteLabel);
    pTabLabel := gtk_label_new(TexteOnglet);

    // Insertion de la page 
    gtk_notebook_append_page(GTK_NOTEBOOK(pNotebook), pLabel, pTabLabel);

    g_free(TexteLabel);
    g_free(TexteOnglet);
  end;

  g_signal_connect(pGTKOBJECT(pBouton), 'clicked', GTK_SIGNAL_FUNC(@OnBoutonClick), pNotebook);

  gtk_widget_show_all(pFenetre);
  gtk_main;
end.

Note modifier

La fonction g_strdup_printf permet de faire des manipulations sur les chaines de caractères gérées par Gtk+ de type PGChar. Elle est identique au niveau manipulation à la fonction Format hormis qu'elle réserve de l'espace mémoire qu'il faut libérer après utilisation par la fonction g_free.

Les fonction préfixées par un « g_ » sont des fonctions de la GLib.

Exécution modifier

Voilà ce que donne l'exécution du programme gtk009 :

 

Si on clique sur le petit triangle noir à droite pour aller jusqu'à la page 6 :

 

Et on clique sur le bouton « Informations » :

 

Nota : En interne, les pages sont numérotées à partir de 0 (comme bien souvent en informatique). C'est pour cela que l'affichage débute par « C'est la page 5 ».

Conteneurs : GtkContainer ~ GtkBox ~ GtkBinGtkHBox ~ GtkVBox ~ GtkTable ~ GtkNotebook