Reprenons notre chemin dans la forêt des widgets. Nous ne pourrons pas tous les voir mais je sais que vous attendez avec impatience de pouvoir ajouter des menus ou des barres d'icônes à vos programmes. Ce sera donc le cœur de ce troisième et dernier chapitre sur les widgets. Cela ne signifie pas que nous aurons tout vu, loin de là, mais nous aurons alors effectué un large tour des possibilités offertes par GTK.
La barre de menu
Créer une barre de menu
Fiche d'identité
- Widget : GTK_Menu_Bar
- Package : Gtk.Menu_Bar et Gtk.Menu_Shell
- Descendance : GTK_Widget >> GTK_Container >> GTK_Menu_Shell
- Description : La GTK_Menu_Bar est simplement la barre dans laquelle nous placerons nos divers menus. Sur la figure suivante, vous pouvez observer une barre de menu un peu vide et… sans menus.
Le package GTK.Menu_Bar ne contient que très peu de méthodes ; je vous invite donc à jeter un œil au package GTK.Menu_Shell dont hérite GTK.Menu_Bar.
Quelques méthodes et un exemple
Le constructeur des GTK_Menu_Bar
est simplissime et ne demande aucun paramètre. La seule méthode définie spécifiquement pour les GTK_Menu_Bar
est la suivante :
1 2 3 4 | procedure Set_Pack_Direction(Menubar : access Gtk_Menu_Bar_Record; Pack_Dir : Gtk.Enums.Gtk_Pack_Direction); function Get_Pack_Direction (Menubar : access Gtk_Menu_Bar_Record) return Gtk.Enums.Gtk_Pack_Direction; |
C'est elle qui indiquera comment seront classés vos menus : de gauche à droite, de haut en bas… Les valeurs possibles pour le paramètre Pack_Dir
sont :
Pack_Direction_LTR
: classement de gauche à droite (Left To Right)Pack_Direction_RTL
: classement de droite à gauche(Right To Left)Pack_Direction_TTB
: classement de haut en bas (Top To Bottom)Pack_Direction_BTT
: classement de bas en haut (Bottom To Top)
Avec ceci nous pouvons dors et déjà créer une fenêtre contenant une barre de menu :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Menu_Bar ; USE Gtk.Menu_Bar ; WITH Gtk.Enums ; USE Gtk.Enums ; PROCEDURE MesMenus IS Win : GTK_Window ; Barre : GTK_Menu_Bar ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --Création de la barre de menu Gtk_New(Barre) ; Barre.set_pack_direction(Pack_Direction_LTR) ; --cette ligne est superflue car par défaut, --GTK oriente le menu de gauche à droite Win.Add(Barre) ; --Finalisation Win.Show_All ; Main ; END MesMenus ; |
Nous obtenons ainsi la barre de menu vide présentée en introduction. Pour plus de méthodes, il faudra fouiller le package Gtk.Menu_Shell
. Voici quelques-unes qui nous serviront :
1 2 3 4 5 6 7 | procedure Append (Menu_Shell : access Gtk_Menu_Shell_Record; Child : access Gtk_Menu_Item_Record'Class); procedure Prepend(Menu_Shell : access Gtk_Menu_Shell_Record; Child : access Gtk_Menu_Item_Record'Class); procedure Insert (Menu_Shell : access Gtk_Menu_Shell_Record; Child : access Gtk_Menu_Item_Record'Class; Position : Gint); |
Voila des noms qui devraient vous parler désormais : Append()
ajoute à la fin, Prepend()
ajoute au début et Insert()
ajoute à la position indiquée. Oui mais qu'ajoutent-elles ces méthodes ? Si vous avez observé leurs spécifications, vous avez du remarquer qu'elles permettent d'ajouter des GTK_Menu_Item
.
Qu'est-ce que c'est que ça encore ? Et puis j'aimerais que ma barre ne soit plus vide svp.
Ça tombe bien, car les GTK_Menu_Item
sont justement les widgets qui vont remplir notre barre.
Créer et ajouter des items
Fiche d'identité
- Widget : GTK_Menu_Item
- Package : Gtk.Menu_Item
- Descendance : GTK_Widget >> GTK_Container >> GTK_Bin >> GTK_Item
- Description : Ce sont des sortes de cases cliquables contenant du texte et que nous allons insérer dans notre
GTK_Menu_Bar
(voir la figure suivante).
Retour sur notre exemple
Pour obtenir la barre ci-dessus, vous allez devoir créer un GTK_Menu_Item
et l'ajouter à votre barre à l'aide de l'une des trois méthodes Append()
, Prepend()
et Insert()
. Voici la spécification du constructeur :
1 | procedure Gtk_New(Menu_Item : out Gtk_Menu_Item; Label : UTF8_String := ""); |
Et voici ce que donnerait notre code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Menu_Bar ; USE Gtk.Menu_Bar ; WITH Gtk.Menu_Item ; USE Gtk.Menu_Item ; WITH Gtk.Enums ; USE Gtk.Enums ; PROCEDURE MesMenus IS Win : GTK_Window ; Barre : GTK_Menu_Bar ; Item_Fichier : Gtk_Menu_Item ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --Création de la barre de menu Gtk_New(Barre) ; Win.Add(Barre) ; --Création de l'item Fichier Gtk_New(Item_Fichier,"Fichier") ; Barre.Append(Item_Fichier) ; --Finalisation Win.Show_All ; Main ; END MesMenus ; |
Ça y est. Ma barre n'est plus vide ! Mais… mais cette fois c'est le menu fichier qui est vide !
Erreur ! Le menu Fichier n'est pas vide : il n'existe pas ! Tout ce que vous avez fait pour l'instant, c'est ajouter du texte à votre barre. Il vous reste une dernière étape : créer un menu déroulant. Mais avant cela, jetons tout de même un rapide coup d’œil aux méthodes disponibles :
1 2 3 4 5 6 7 8 9 10 11 12 | procedure Gtk_New_With_Mnemonic(Menu_Item : out Gtk_Menu_Item; Label : UTF8_String); procedure Set_Label(Menu_Item : access Gtk_Menu_Item_Record; Label : String); function Get_Label (Menu_Item : access Gtk_Menu_Item_Record) return String; procedure Set_Use_Underline(Menu_Item : access Gtk_Menu_Item_Record; Setting : Boolean); function Get_Use_Underline (Menu_Item : access Gtk_Menu_Item_Record) return Boolean; |
Ces méthodes devraient vous dire quelque chose désormais puisque nous les avons déjà vues lors des chapitres sur les étiquettes, les boutons ou les extenseurs. Elles vous permettront de redéfinir le texte de votre GTK_Item
ou d'utiliser des caractères soulignés (pratique si vous voulez créer des raccourcis claviers). Mais comme votre priorité est d'ajouter un menu à votre item, voici les méthodes qu'il vous faut :
1 2 3 4 | procedure Set_Submenu(Menu_Item : access Gtk_Menu_Item_Record; Submenu : access Gtk_Widget_Record'Class); function Get_Submenu (Menu_Item : access Gtk_Menu_Item_Record) return Gtk_Widget; |
Créer et ajouter un menu déroulant
Pour finaliser notre barre de menu, nous avons besoin d'un ultime widget : GTK_Menu
.
Fiche d'identité
- Widget : GTK_Menu
- Package : Gtk.Menu
- Descendance : GTK_Widget >> GTK_Container >> GTK_Menu_Shell
- Description : Ce widget est un menu déroulant pouvant contenir plusieurs items (voir la figure suivante).
Terminons notre exemple
Nous allons achever notre barre de menu. Pour cela nous allons :
- créer un
GTK_Menu
; - l'attacher au
GTK_Menu_Item
que nous avons appeléItem_Fichier
à l'aide de la méthodeSet_Submenu()
vue précédemment ; - lui ajouter deux items : Ouvrir et Fermer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Menu_Bar ; USE Gtk.Menu_Bar ; WITH Gtk.Menu ; USE Gtk.Menu ; WITH Gtk.Menu_Item ; USE Gtk.Menu_Item ; PROCEDURE MesMenus IS Win : GTK_Window ; Barre : GTK_Menu_Bar ; Menu_Fichier : Gtk_Menu ; Item_Fichier : Gtk_Menu_Item ; Item_Ouvrir : Gtk_Menu_Item ; Item_Fermer : Gtk_Menu_Item ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --Création de la barre de menu Gtk_New(Barre) ; Win.Add(Barre) ; --Création de l'item Fichier Gtk_New(Item_Fichier,"Fichier") ; Barre.Append(Item_Fichier) ; --Création du menu Fichier Gtk_New(Menu_Fichier) ; Item_Fichier.Set_Submenu(Menu_Fichier) ; --Création de l'item Ouvrir Gtk_New(Item_Ouvrir,"Ouvrir") ; Menu_Fichier.append(Item_Ouvrir) ; --Création de l'item Fermer Gtk_New(Item_Fermer,"Fermer") ; Menu_Fichier.Append(Item_Fermer) ; --Finalisation Win.Show_All ; Main ; END MesMenus ; |
Désormais, vous n'avez plus qu'à connecter les GTK_Item à vos callbacks. Pour cela, vous aurez besoin du signal suivant : Signal_Activate
ou "activate"
. Celui-ci est émis dès lors que vous cliquez sur un item.
Améliorer la barre de menu
Vous connaissez désormais les rudiments nécessaires pour créer une barre de menu. Comme je ne cesse de le répéter depuis le début de la partie V, n'hésitez pas à ouvrir et lire les fichiers ads. Vous y trouverez toutes les méthodes disponibles ainsi que des commentaires généralement exhaustifs. Dans cette partie, nous allons voir comment améliorer nos menus à partir de ce que nous savons déjà ou à l'aide de nouveaux widgets.
Créer un menu en image
GTK est livré avec toute une batterie d'images permettant d'égayer vos menus et boutons. Vous pouvez par exemple obtenir un menu comme celui-ci :
Si vous êtes tentés, rien de plus simple. Abandonnez les GTK_Menu_Item
au profit du widget fils : Gtk_Image_Menu_Item
. Vous aurez deux possibilités pour créer vos items en image :
- Le créer comme précédemment puis lui ajouter une image.
- Utiliser une image prédéfinie de GTK.
Méthode artisanale
Dans le premier cas, utilisez GTK_New()
comme vous saviez le faire puis créez une image avec un GTK_Image
. Il vous suffit ensuite d'attribuer l'image à votre item à l'aide de la méthode Set_Image()
:
1 2 3 4 | procedure Set_Image(Menu_Item : access Gtk_Image_Menu_Item_Record; Image : access Gtk_Widget_Record'Class); function Get_Image (Menu_Item : access Gtk_Image_Menu_Item_Record) return Gtk_Widget; |
Méthode pour ne pas réinventer la roue
Mais la solution de facilité est de faire appel au stock d'images intégrées dans le thème visuel de GTK. C'est très simple, il suffit d'utiliser la méthode Gtk_New_From_Stock()
à la place de GTK_New()
:
1 2 | procedure Gtk_New_From_Stock(Widget : out Gtk_Image_Menu_Item; Stock_Id : String); |
Stock_Id indique le nom de l'image et du texte à afficher. Ces noms sont normés et commencent généralement par "gtk-"
. Vous trouverez la liste des valeurs possibles pour Stock_Id dans le package Gtk.Stock. Pour notre menu Ouvrir, nous utiliserons "gtk-open"
et pour Fermer, ce sera "gtk-close"
.
C'est bien sympa tout ça mais je me retrouve avec des menus en Anglais?!
Souvenez-vous que les GTK_Image_Menu_Item
dérivent des GTK_Menu_Item
et qu'ils héritent donc de leurs méthodes. Vous pourrez donc les renommer avec :
1 2 | procedure Set_Label(Menu_Item : access Gtk_Menu_Item_Record; Label : String); |
Créer un sous-menu
Je voulais créer un sous-menu pour la sauvegarde car je prévois deux formats différents pour enregistrer mes documents. Comment faire ?
Vous n'avez besoin de rien de plus que ce que vous connaissez déjà. Tout d'abord, ajoutons un nouvel Item pour la sauvegarde :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ... WITH Gtk.Image_Menu_Item ; USE Gtk.Image_Menu_Item ; PROCEDURE MesMenus IS ... Item_Sauver : Gtk_Image_Menu_Item ; BEGIN ... --Création de l'item Sauver Gtk_New_From_Stock(Item_Sauver,"gtk-save-as") ; Item_Sauver.set_label("Enregistrer au format") ; Menu_Fichier.Append(Item_Sauver) ; ... END MesMenus ; |
Puis, nous allons créer un second Gtk_Menu
que nous ajouterons à l'item que nous venons de faire. Il ne restera plus qu'à y ajouter deux nouveaux items :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Menu_Bar ; USE Gtk.Menu_Bar ; WITH Gtk.Menu ; USE Gtk.Menu ; WITH Gtk.Menu_Item ; USE Gtk.Menu_Item ; WITH Gtk.Image_Menu_Item ; USE Gtk.Image_Menu_Item ; PROCEDURE MesMenus IS Win : GTK_Window ; Barre : GTK_Menu_Bar ; Menu_Fichier : Gtk_Menu ; Menu_Sauver : Gtk_Menu ; Item_Fichier : Gtk_Menu_Item ; Item_Ouvrir : Gtk_Image_Menu_Item ; Item_Fermer : Gtk_Image_Menu_Item ; Item_Sauver : Gtk_Image_Menu_Item ; Item_Format1 : Gtk_Menu_Item ; Item_Format2 : Gtk_Menu_Item ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --Création de la barre de menu Gtk_New(Barre) ; Win.Add(Barre) ; --Création de l'item Fichier Gtk_New(Item_Fichier,"Fichier") ; Barre.Append(Item_Fichier) ; --Création du menu Fichier Gtk_New(Menu_Fichier) ; Item_Fichier.Set_Submenu(Menu_Fichier) ; --Création de l'item Ouvrir Gtk_New_From_Stock(Item_Ouvrir,"gtk-open") ; Item_Ouvrir.set_label("Ouvrir") ; Menu_Fichier.append(Item_Ouvrir) ; --Création de l'item Fermer Gtk_New_From_Stock(Item_Fermer,"gtk-close") ; Item_Fermer.set_label("Fermer") ; Menu_Fichier.Append(Item_Fermer) ; --Création de l'item Sauver Gtk_New_From_Stock(Item_Sauver,"gtk-save-as") ; Item_Sauver.set_label("Enregistrer au format") ; Menu_Fichier.Append(Item_Sauver) ; --Création du sous-menu Gtk_New(Menu_Sauver) ; Item_Sauver.Set_Submenu(Menu_Sauver) ; --Création de l'item de format n°1 Gtk_New(Item_Format1,"*.truc") ; Menu_Sauver.append(Item_Format1) ; --Création de l'item de format n°2 Gtk_New(Item_Format2,"*.bidule") ; Menu_Sauver.append(Item_Format2) ; --Finalisation Win.Show_All ; Main ; END MesMenus ; |
Proposer un item à cocher dans le menu
Je souhaite proposer une option "Afficher le score"
dans mon menu que le joueur pourrait cocher ou décocher. Comment faire ?
Encore une fois, rien de plus simple. Nous allons faire appel au widget Gtk_Check_Menu_Item
au lieu de Gtk_Menu_Item
. Il s'agit d'un type dérivé bien entendu ce qui nous permettra de réutiliser les méthodes du père. Voici ce que cela pourrait donner :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ... WITH Gtk.Check_Menu_Item ; USE Gtk.Check_Menu_Item ; PROCEDURE MesMenus IS ... Item_Afficher : Gtk_Check_Menu_Item ; BEGIN ... --Création de l'item Afficher score Gtk_New(Item_Afficher,"Afficher le score") ; Menu_Fichier.append(Item_Afficher) ; ... END MesMenus ; |
Admirez le dernier item du menu : une case à cocher ! (Voir la figure suivante.)
Dans le package Gtk.Check_Menu_Item
, vous trouverez la plupart des méthodes additionnelles, mais voici celles qui vous seront essentielles :
1 2 3 | procedure Set_Active(Check_Menu_Item : access Gtk_Check_Menu_Item_Record; Is_Active : Boolean); function Get_Active (Check_Menu_Item : access Gtk_Check_Menu_Item_Record) return Boolean; |
Avec Set_Active()
, vous pourrez cocher ou décocher votre item, tandis qu'avec Get_Active()
, vous pourrez connaître son état. Enfin, chaque fois que l'utilisateur coche ou décoche votre item, le signal Signal_Toggled
ou "toggled"
est émis.
Vous aurez compris que les items à cocher (Gtk_Check_Menu_Item
) sont très similaires aux boutons à cocher (Gtk_Check_Button
) vus au chapitre 5. De la même manière, il existe des items radio, semblables aux boutons radio (Gtk_Radio_Button
). Ils s'appellent tout simplement Gtk_Radio_Menu_Item
.
Organiser vos menus
Lorsque vos menus commenceront à devenir volumineux, il sera judicieux d'utiliser des séparateurs pour que l'utilisateur visualise rapidement les groupes logiques d'item. Aussi aurez-vous besoin du widget Gtk_Separator_Menu_Item
. Vous constaterez, sur la figure ci-dessous, la présence d'un petit trait séparant l'item "Afficher le score"
des trois autres items.
La barre d'icônes
Fiches d'identité
Pour réaliser une barre d'icônes, nous aurons besoin des deux widgets GTK_Toolbar
et GTK_Tool_Button
. On retrouve ainsi une architecture semblable aux barres de menu : une barre servant de conteneur et des objets à y insérer.
Fiche d'identité des GTK_Toolbar
- Widget : GTK_Toolbar
- Package : GTK.Toolbar
- Descendance : GTK_Widget >> GTK_Container
- Description : La GTK_Toolbar est la barre dans laquelle nous placerons nos icônes.
Fiche d'identité des GTK_Tool_Button
- Widget : GTK_Tool_Button
- Package : GTK.Tool_Button
- Descendance : GTK_Widget >> GTK_Container >> GTK_bin >> GTK_Tool_Item
- Description : Les GTK_Tool_Button sont les boutons des icônes à insérer.
Créer notre barre d'icônes
Les méthodes élémentaires
Comme toujours, vous devez commencer par construire la barre à l'aide de la méthode :
1 | procedure Gtk_New (Widget : out Gtk_Toolbar); |
Puis vous devrez construire votre icône avec les méthodes GTK_New()
ou GTK_New_From_Stock()
:
1 2 3 4 5 | procedure Gtk_New(Button : out Gtk_Tool_Button; Icon_Widget : Gtk.Widget.Gtk_Widget := null; Label : String := ""); procedure Gtk_New_From_Stock(Button : out Gtk_Tool_Button; Stock_Id : String); |
En revanche, pour ajouter un icône à la barre, vous ne disposerez plus de méthode Append()
ou Prepend()
(celles-ci étant obsolètes). Vous devrez donc utiliser la méthode :
1 2 3 | procedure Insert(Toolbar : access Gtk_Toolbar_Record; Item : access Gtk_Tool_Item_Record'Class; Pos : Gint := -1); |
Si le paramètre Pos
vaut 0, votre icône sera placé en première position, s'il vaut 1 en deuxième position… Et si vous n'avez aucune idée de l'endroit où cet icône doit être situé, donnez -1 comme position : GTK le placera en bout de liste.
Exemple
Pour mieux comprendre, rien de tel qu'un exemple. Nous allons construire un programme comportant une barre d'icône et deux icônes. Le code ci-dessous devrait être suffisamment simple et commenté pour que vous le déchiffriez seuls :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Toolbar ; USE Gtk.Toolbar ; WITH Gtk.Tool_button ; USE Gtk.Tool_button ; PROCEDURE MesMenus IS Win : GTK_Window ; Barre : Gtk_Toolbar ; Icon_Ouvrir : Gtk_Tool_Button ; Icon_Fermer : Gtk_Tool_Button ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --création barre d'outils Gtk_New(Barre) ; Win.add(barre) ; --Création de l'icône ouvrir Gtk_New_From_Stock(Icon_Ouvrir,"gtk-open") ; icon_ouvrir.set_label("Ouvrir") ; Barre.Insert(Icon_Ouvrir) ; --Création de l'icône fermer Gtk_New_From_Stock(Icon_Fermer,"gtk-close") ; icon_fermer.set_label("Fermer") ; Barre.Insert(Icon_fermer) ; --Finalisation Win.Show_All ; Main ; END MesMenus ; |
Voici, sur la figure suivante, le résultat en image.
Pour plus de clarté, les icônes ne sont reliés à aucun callback, mais il est évident que vous devrez connecté chacun d'entre eux à sa méthode. Le signal émis par les GTK_Tool_Button
lorsque l'utilisateur clique dessus se nomme Signal_Clicked
ou "clicked"
.
Améliorer les barres d'icônes
D'autres icônes
Existe-t-il d'autres types d'icônes, à la manière des items de menu ?
Bien sûr. Il n'existe pas que les Gtk_Tool_Button
, sinon les créateurs de Gtk n'auraient pas créé de classe mère Gtk_Tool_Item
. Il existe :
- des icônes séparateurs pour séparer des groupes d'icônes : les
Gtk_Separator_Tool_Item
; - des icônes à bascule pour activer ou désactiver un option : les
Gtk_Toggle_Tool_Button
; - des icônes radio pour choisir entre un groupe d'options : les
Gtk_Radio_Tool_Button
.
Enfin, il existe un dernier type d'icône. Il s'agit d'icônes ouvrant des menus : les Gtk_Menu_Tool_Button
. Pour leur adjoindre un menu, il faudra utiliser la méthode suivante :
1 2 | procedure Set_Menu(Button : access Gtk_Menu_Tool_Button_Record; Menu : access Gtk_Menu_Record'Class); |
Ce genre d'icône vous sera très utile si vous comptez créer de nombreux outils pour votre logiciel. Ainsi, pour les logiciels de dessin, les outils de sélection par zone, à main levée et par couleur sont généralement rassemblés sous un même icône de sélection.
Sur la figure suivante, un exemple d'utilisation d'un icône-menu avec le logiciel Paint Shop Pro
Ajouter une info-bulle
Si vous explorez le package Gtk.Tool_Button
, vous serez déçus de ne trouver que très peu de méthodes, hormis les éternels (Get/Set)_Label()
, (Get/Set)_Icon_Widget()
, (Get/Set)_Stock_Id()
… permettant d'obtenir ou d'éditer les paramètres essentiels du bouton. Mais en fouillant dans le package père Gtk.Tool_Item
, vous trouverez les méthodes suivantes :
1 2 3 4 | procedure Set_Tooltip_Text (Tool_Item : access Gtk_Tool_Item_Record; Text : UTF8_String); procedure Set_Tooltip_Markup(Tool_Item : access Gtk_Tool_Item_Record; Markup : UTF8_String); |
Celles-ci permettent de créer des info-bulles pour vos icônes expliquant leur action. La seconde méthode permet même d'utiliser des balises de mise en forme (voir le chapitre sur les étiquettes pour rappel). Et vous n'avez pas besoin de faire appel à ce package puisque par dérivation, les Gtk_Tool_Button
héritent de ces méthodes. Exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Toolbar ; USE Gtk.Toolbar ; WITH Gtk.Tool_Button ; USE Gtk.Tool_Button ; PROCEDURE MesIcones IS Win : GTK_Window ; Barre : Gtk_Toolbar ; Icon_Ouvrir : Gtk_Tool_Button ; Icon_Fermer : Gtk_Tool_Button ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --Création barre d'outils Gtk_New(Barre) ; Win.add(barre) ; --Création de l'icône Ouvrir Gtk_New_From_Stock(Icon_Ouvrir,"gtk-open") ; Icon_Ouvrir.Set_Label("Ouvrir") ; Icon_Ouvrir.Set_Tooltip_Text("Permet d'ouvrir un document") ; Barre.Insert(Icon_Ouvrir) ; --Création de l'icône Fermer Gtk_New_From_Stock(Icon_Fermer,"gtk-close") ; Icon_Fermer.Set_Label("Fermer") ; Icon_Fermer.Set_Tooltip_Markup("<span foreground='red'><b>Ferme</b></span> le document en cours") ; Barre.Insert(Icon_fermer) ; --Finalisation Win.Show_All ; Main ; END MesIcones ; |
Sur la figure suivante, on constate que lorsque l'icône est survolé par la souris, une info-bulle apparaît.
Améliorez la barre
De nombreuses méthodes liées aux Gtk_Toolbar sont désormais obsolètes, si bien qu'il n'en reste que peu. Mais voici quelques méthodes qui pourraient vous intéresser :
1 2 3 4 5 6 7 8 9 10 11 12 | procedure Set_Orientation(Toolbar : access Gtk_Toolbar_Record; Orientation : Gtk_Orientation); function Get_Orientation(Toolbar : access Gtk_Toolbar_Record) return Gtk_Orientation; procedure Set_Tooltips(Toolbar : access Gtk_Toolbar_Record; Enable : Boolean); function Get_Tooltips(Toolbar : access Gtk_Toolbar_Record) return Boolean; procedure Set_Show_Arrow(Toolbar : access Gtk_Toolbar_Record; Show_Arrow : Boolean := True); function Get_Show_Arrow(Toolbar : access Gtk_Toolbar_Record) return Boolean; |
Avec Set_Orientation()
vous pourrez indiquer si vos icônes sont alignés horizontalement (Orientation
vaut alors Orientation_Horizontal
) ou verticalement (Orientation_Vertical
). Avec Set_Tooltips()
vous pourrez autoriser ou non l'affichage des info-bulles ; enfin avec Set_Show_Arrow(), vous pourrez afficher ou non une flèche en bout de barre. Si votre barre contient trop d'icônes, cette flèche vous permettra d'ouvrir un petit menu pour avoir accès aux icône cachés. Cette flèche n'apparaît qu'en cas de besoin et est activée par défaut.
Les barres d'icônes sont aussi appelées barres d'outils. Beaucoup de logiciels permettent de déplacer ces barres d'outil pour les placer en haut, à gauche ou en bas de la fenêtre ou de les en détacher. Pour obtenir cet effet, vous pouvez combinez votre Gtk_Toolbar
avec une Gtk_Handle_Box
(voir chapitre sur les boîtes détachables).
Combiner menus et icônes
Dans certains logiciels, comme ceux de dessin, les icônes sont essentiels et donnent accès à des outils inatteignables autrement, comme le pinceau ou les outils de sélection. Mais la plupart du temps, ces icônes sont des raccourcis de menus déjà existants. Si nous essayons de combiner la barre de menus et la barre d'icônes que nous venons de créer, nous allons voir apparaître de sacrés doublons ! Il faudra créer un Gtk_Menu_Item
et un Gtk_Tool_Button
pour ouvrir un document, pour le fermer, pour en créer un nouveau, pour le sauvegarder … sans parler des callbacks qu'il faudra connecter deux fois. Une solution à ce problème est de faire appel aux actions, aussi appelées Gtk_Action
.
Fiche d'identité
- Widget : GTK_Action
- Package : GTK.Action
- Descendance : il ne s'agit pas d'un widget. Toutefois il dérive des Gtk_Object, tout comme les Gtk_Widget.
- Description : définit un objet de type action qui pourra être réutiliser par la suite pour créer un item de menu ou un icône.
Mode d'emploi
L'emploi des actions pourrait être déconcertant, mais vous avez désormais l'expérience suffisante pour les aborder en toute sérénité. La partie la plus complexe est, une fois n'est pas coutume, le constructeur. Celui-ci va cumuler tous les paramètres nécessaires aux icônes et items de menu :
1 2 3 4 5 | procedure Gtk_New(Action : out Gtk_Action; Name : String; Label : String; Tooltip : String := ""; Stock_Id : String := ""); |
Le paramètre Label
est le texte qui sera affiché dans le menu ou sous l'icône ; Tooltip
correspond au texte qui sera affiché dans l'info-bulle ; Stock_Id
est bien entendu le nom de l'image ("gtk-open"
, "gtk-close"
…). Le paramètre Name
correspond à un nom que vous devez donner à cette action. Ce nom doit être unique, de même que chaque signal à un nom unique.
La connexion aux callbacks se fait de la même façon que pour les widgets, toutefois faites attention à l'instanciation de vos packages : les actions ne sont pas des widgets ! Il s'agit un type d'objet frère mais distinct ; widgets et actions sont tous deux des Gtk_Object.
Une fois vos actions créées et connectées, leur transformation en menus, en items de menu ou en icônes pourra se faire avec l'une des méthodes suivantes :
1 2 3 4 5 | function Create_Menu (Action : access Gtk_Action_Record) return Gtk_Widget; function Create_Menu_Item(Action : access Gtk_Action_Record) return Gtk_Widget; function Create_Tool_Item(Action : access Gtk_Action_Record) return Gtk_Widget; |
Toutefois, ces fonctions de conversion transformeront votre action en widget, mais pas spécifiquement en item, menu ou icône. Pour mieux comprendre, reprenons nos codes précédents et réalisons une fenêtre contenant une barre de menu et une barre d'icônes. Nous nous limiterons aux deux actions Ouvrir et Nouveau :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Box ; USE Gtk.Box ; WITH Gtk.Menu_Bar ; USE Gtk.Menu_Bar ; WITH Gtk.Menu ; USE Gtk.Menu ; WITH Gtk.Menu_Item ; USE Gtk.Menu_Item ; WITH Gtk.Toolbar ; USE Gtk.Toolbar ; WITH Gtk.Tool_button ; USE Gtk.Tool_button ; WITH Glib.Convert ; USE Glib.Convert ; WITH Gtk.Action ; USE Gtk.Action ; PROCEDURE DoubleMenu IS Win : GTK_Window ; Vbox : Gtk_Vbox ; Barre1 : GTK_Menu_Bar ; Barre2 : Gtk_Toolbar ; Menu_Fichier : Gtk_Menu ; Item_Fichier : Gtk_Menu_Item ; Action_Nouveau : Gtk_Action ; Action_Ouvrir : Gtk_Action ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,25) ; Win.Set_Title("Mes menus") ; --Création boîte Gtk_New_Vbox(Vbox) ; Win.Add(Vbox) ; --Création de la barre de menu Gtk_New(Barre1) ; Vbox.pack_start(Barre1) ; --Création barre d'icones Gtk_New(Barre2) ; Vbox.Pack_Start(Barre2) ; --Création de l'item Fichier Gtk_New(Item_Fichier,"Fichier") ; Barre1.Append(Item_Fichier) ; --Création du menu Fichier Gtk_New(Menu_Fichier) ; Item_Fichier.Set_Submenu(Menu_Fichier) ; --Création de l'action ouvrir Gtk_new(Action_Ouvrir,"action-open","Ouvrir","Ouvre un document existant","gtk-open") ; Menu_Fichier.Append(GTK_Menu_item(Action_Ouvrir.Create_Menu_Item)) ; Barre2.insert(gtk_tool_button(Action_Ouvrir.Create_Tool_Item)) ; --Création de l'action nouveau Gtk_new(Action_nouveau,"action-new","Nouveau",locale_to_utf8("Crée un nouveau document"),"gtk-new") ; Menu_Fichier.Append(GTK_Menu_item(Action_Nouveau.Create_Menu_Item)) ; Barre2.insert(gtk_tool_button(Action_nouveau.Create_Tool_Item)) ; --Finalisation Win.Show_All ; Main ; END DoubleMenu ; |
Comme vous pouvez le constater, pour créer deux items de menu et deux icônes (soit quatre widgets), je n'ai eu besoin que de deux actions (et il n'aurait fallu que deux connexions de callback au lieu de quatre, non écrits par soucis de clarté). J'attire toutefois votre attention sur les lignes 52,53,57 et 58 :
1 2 | Menu_Fichier.Append(GTK_Menu_item(Action_Ouvrir.Create_Menu_Item)) ; Barre2.insert(gtk_tool_button(Action_Ouvrir.Create_Tool_Item)) ; |
1 2 | Menu_Fichier.Append(GTK_Menu_item(Action_Nouveau.Create_Menu_Item)) ; Barre2.insert(gtk_tool_button(Action_nouveau.Create_Tool_Item)) ; |
Aux lignes 52 et 57, j'ajoute au menu Fichier mes deux actions que je convertis en widget grâce à Create_Menu_Item()
. Toutefois, la méthode Append()
n'attend pas un Gtk_Widget
mais un Gtk_Menu_Item
! C'est pourquoi il faut effectuer une conversion supplémentaire. Le phénomène est le même aux lignes 53 et 58 où j'ai convertis les actions en widget grâce à Create_Tool_Item()
puis en icône avec gtk_tool_button()
.
La barre de statut
Fiche d'identité
- Widget : GTK_Status_Bar
- Package : GTK.Status_Bar
- Descendance : GTK_Widget >> GTK_Container >> GTK_Box >> GTK_Hbox
- Description : La barre de statut (ou barre d'état) affiche des informations en continu pour l'utilisateur. Elle est généralement située au bas de la fenêtre.
Sur la figure suivante, au survol du second bouton, la barre de statut affiche «C'est le bouton 2»
Méthodes et fonctionnement
Méthodes pour l'apparence
Les barres de statut disposent de très peu de méthodes propres. Voici celles concernant l'apparence :
1 2 3 4 5 6 7 | function Get_Has_Resize_Grip(Statusbar : access Gtk_Status_Bar_Record) return Boolean; procedure Set_Has_Resize_Grip(Statusbar : access Gtk_Status_Bar_Record; Setting : Boolean); function Get_Orientation (Self : access Gtk_Status_Bar_Record) return Gtk.Enums.Gtk_Orientation; procedure Set_Orientation(Self : access Gtk_Status_Bar_Record; Orientation : Gtk.Enums.Gtk_Orientation); |
La méthode Set_Resize_Grip()
vous permet d'indiquer si la barre contient ou non un petit carré à droite pour redimensionner la fenêtre. Par défaut, ce carré est affiché. Je ne m'attarde plus sur les méthodes Get_Orientation()
et Set_Orientation()
que nous avons vues et revues (retournez à la partie précédente sur la barre d'icônes si vous avez déjà oublié).
Fonctionnement
Mais le but d'une barre d'état est avant tout d'afficher des messages. Alors vous devez d'abord comprendre comment sont gérés ces messages. À chaque fois que vous souhaitez afficher un message, vous devrez l'ajouter à la liste de messages de la GTK_Status_Bar
. Celle-ci lui attribuera un numéro d'identification de message, qui n'est autre qu'un entier de type Message_Id
. Mais ce n'est pas tout ! Vous devrez également fournir, en plus de la chaîne de caractères, un numéro d'identification de contexte qui est également un entier, mais de type Context_Id
. Ce nouveau numéro d'identification permet de classer les messages selon leur «contexte» : les messages d'erreurs porteront par exemple le numéro 0 et les messages d'aide le numéro 1.
Cet identifiant nous sera inutile car nous ne pousserons pas la difficulté si loin mais nous devons tout de même le fournir et nous en souvenir car il nous sera demandé lorsque nous souhaiterons retirer notre dernier message. En effet, la liste de messages fonctionne à la manière d'une liste de piles (voire chapitre sur les TAD) : pour retirer un message, vous fournissez le Context_Id
et GTK retire de la pile correspondante le dernier message posté.
Sur la figure suivante, la représentation de la liste des messages dans une GTK_Status_Bar
.
Sur le schéma précédent, on peut deviner l'ordre d'arrivée des messages et leur classement :
- Ajout du message n°0 dans le Context_Id n°0
- Ajout du message n°1 dans le Context_Id n°1
- Ajout du message n°2 dans le Context_Id n°2
- Ajout du message n°3 dans le Context_Id n°2
- Ajout du message n°4 dans le Context_Id n°1
- Ajout du message n°5 dans un Context_Id inconnu
- Suppression du message n°5
- Ajout du message n°6 dans le Context_Id n°1
Le message affiché en ce moment est donc le n°6, c'est le plus vieux. S'il était supprimé, ce serait le 4, toujours dans le Context_Id n°1, puis le 3 et ainsi de suite.
Méthodes essentielles
Venons-en maintenant aux méthodes :
1 2 3 4 5 6 7 8 9 10 | function Push(Statusbar : access Gtk_Status_Bar_Record; Context : Context_Id; Text : UTF8_String) return Message_Id; procedure Pop(Statusbar : access Gtk_Status_Bar_Record; Context : Context_Id); procedure Remove(Statusbar : access Gtk_Status_Bar_Record; Context : Context_Id; Message : Message_Id); procedure Remove_All(Statusbar : access Gtk_Status_Bar_Record; Context : Context_Id); |
Si vous vous souvenez du chapitre sur les piles, les noms de ces procédures devraient vous sembler familiers : Push()
ajoute un message à une pile ; Pop()
retire l'élément au sommet d'une pile ; Remove()
permet de supprimer un message précis d'une pile précise ; Remove_all()
vide toute une pile. Vous remarquerez que toutes ces méthodes exigent un Context_Id, c'est-à-dire le numéro de la pile désirée. De plus, faites attention car Push()
n'est pas une procédure mais une fonction qui renvoie le numéro du message créé (nécessaire si vous souhaitez utiliser Remove()
).
Exemples d'utilisation
Exemple basique
Contrairement aux autres widgets, je vais devoir vous présenter les barres de statut avec quelques callbacks, sans quoi cela n'aurait aucun intérêt. Voici donc le code écrit pour réaliser la fenêtre d'exemple contenant deux boutons et une barre d'état :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Box ; USE Gtk.Box ; WITH Gtk.Button ; USE Gtk.button ; WITH Glib.Convert ; USE Glib.Convert ; WITH Gtk.Status_Bar ; USE Gtk.Status_Bar ; WITH Gtk.Handlers ; PROCEDURE MaBarreDeStatut IS --Objets Win : GTK_Window ; Vbox : Gtk_Vbox ; Barre : GTK_Status_Bar ; Btn1, Btn2 : Gtk_Button ; Msg0 : Message_Id ; --Type nécessaire aux callbacks TYPE T_Data IS RECORD Barre : GTK_Status_Bar ; Id : Integer ; END RECORD ; --Packages PACKAGE P_Callback IS NEW Gtk.Handlers.User_Callback(Gtk_Button_Record,T_Data) ; USE P_Callback ; --Callbacks PROCEDURE Active_Barre(Emetteur : ACCESS Gtk_Button_Record'Class ; Data : T_Data) IS PRAGMA Unreferenced(Emetteur) ; Msg1 : Message_Id ; BEGIN CASE Data.Id IS WHEN 1 => Msg1 := Data.Barre.Push(1,"C'est le bouton 1") ; WHEN 2 => Msg1 := Data.Barre.Push(1,"C'est le bouton 2") ; WHEN OTHERS => NULL ; END CASE ; END Active_Barre ; PROCEDURE Desactive_Barre(Emetteur : ACCESS Gtk_Button_Record'Class ; Data : T_Data) IS PRAGMA Unreferenced(Emetteur) ; BEGIN Data.Barre.Pop(1) ; END Desactive_Barre ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(250,300) ; Win.Set_Title("Ma barre de statut") ; --Création de la boîte Gtk_New_Vbox(Vbox) ; Win.Add(Vbox) ; --Création de la barre de statut Gtk_New(Barre) ; Msg0 := Barre.Push(0,"Passez le curseur sur un bouton") ; Vbox.pack_end(Barre, expand => false) ; --Création des boutons Gtk_New(Btn1,"Premier bouton") ; Connect(Btn1,"enter", Active_Barre'ACCESS, (Barre,1)) ; Connect(Btn1,"leave", Desactive_Barre'ACCESS, (Barre,1)) ; Vbox.Pack_Start(Btn1) ; Gtk_New(Btn2,Locale_To_Utf8("Deuxième bouton")) ; Connect(Btn2,"enter", Active_Barre'ACCESS, (Barre,2)) ; Connect(Btn2,"leave", Desactive_Barre'ACCESS, (Barre,2)) ; Vbox.Pack_Start(Btn2) ; --Finalisation Win.Show_All ; Main ; END MaBarreDeStatut ; |
Pour chaque bouton, j'effectue deux connexions. Pour le signal "enter"
(émis lorsque la souris entre dans le bouton) je déclenche le callback Active_Barre()
qui affiche un message particulier ; pour le signal "leave"
(émis lorsque la souris quitte le bouton) je déclenche le callback Desactive_Barre()
qui efface le message écrit. Le premier callback utilise la méthode push()
, le second utilise pop()
. Ainsi, les messages concernant les boutons n'apparaissent que si la souris est au-dessus et disparaissent sinon.
Une petite amélioration
Une barre de statut, c'est bien gentil mais ça n'est pas fondamental : tant de travail pour un tout petit message en bas ! Est-ce si utile ?
J'admets que c'est du fignolage. Mais une barre d'état peut être plus utile que vous ne le pensez. Si vous avez été attentifs à la fiche d'identité, vous avez du (ou vous auriez du) remarquer une bizarrerie : les GTK_Status_Bar
dérivent des GTK_HBox
! Étonnant, non ? Oui mais voilà qui va nous être utile. Notre barre de statut peut donc contenir d'autres widgets ! Alors pourquoi ne pas y ajouter une barre de progression pour un éventuel téléchargement ainsi qu'une case à cocher pour une option ? (Voir la figure suivante.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | WITH Gtk.Main ; USE Gtk.Main ; WITH Gtk.Window ; USE Gtk.Window ; WITH Gtk.Box ; USE Gtk.Box ; WITH Gtk.Button ; USE Gtk.button ; WITH Glib.Convert ; USE Glib.Convert ; WITH Gtk.Status_Bar ; USE Gtk.Status_Bar ; WITH Gtk.Progress_Bar ; USE Gtk.Progress_Bar ; WITH Gtk.Check_Button ; USE Gtk.Check_Button ; WITH Gtk.Handlers ; PROCEDURE MaBarreDeStatus IS --Objets Win : GTK_Window ; Vbox : Gtk_Vbox ; Barre : GTK_Status_Bar ; Btn1, Btn2 : Gtk_Button ; Msg0 : Message_Id ; Progress : Gtk_Progress_Bar ; Option : Gtk_Check_Button ; --Type nécessaire aux callbacks TYPE T_Data IS RECORD Barre : GTK_Status_Bar ; Id : Integer ; END RECORD ; --Packages PACKAGE P_Callback IS NEW Gtk.Handlers.User_Callback(Gtk_Button_Record,T_Data) ; USE P_Callback ; --Callbacks PROCEDURE Active_Barre(Emetteur : ACCESS Gtk_Button_Record'Class ; Data : T_Data) IS PRAGMA Unreferenced(Emetteur) ; Msg1 : Message_Id ; BEGIN CASE Data.Id IS WHEN 1 => Msg1 := Data.Barre.Push(1,"C'est le bouton 1") ; WHEN 2 => Msg1 := Data.Barre.Push(1,"C'est le bouton 2") ; WHEN OTHERS => NULL ; END CASE ; END Active_Barre ; PROCEDURE Desactive_Barre(Emetteur : ACCESS Gtk_Button_Record'Class ; Data : T_Data) IS PRAGMA Unreferenced(Emetteur) ; BEGIN Data.Barre.Pop(1) ; END Desactive_Barre ; BEGIN Init ; --Création de la fenêtre Gtk_New(Win) ; Win.Set_Default_Size(400,300) ; Win.Set_Title("Ma barre de statut") ; --Création de la boîte Gtk_New_Vbox(Vbox) ; Win.Add(Vbox) ; --Création de la barre de statut Gtk_New(Barre) ; Msg0 := Barre.Push(0,"Passez le curseur sur un bouton") ; Vbox.pack_end(Barre, expand => false) ; --Création des boutons Gtk_New(Btn1,"Premier bouton") ; Connect(Btn1,"enter", Active_Barre'ACCESS, (Barre,1)) ; Connect(Btn1,"leave", Desactive_Barre'ACCESS, (Barre,1)) ; Vbox.Pack_Start(Btn1) ; Gtk_New(Btn2,Locale_To_Utf8("Deuxième bouton")) ; Connect(Btn2,"enter", Active_Barre'ACCESS, (Barre,2)) ; Connect(Btn2,"leave", Desactive_Barre'ACCESS, (Barre,2)) ; Vbox.Pack_Start(Btn2) ; --Création d'une case à cocher Gtk_New(Option,Locale_To_Utf8("Connecté")) ; Barre.Pack_End(Option, Expand => False, Fill => False) ; --Création d'une barre de progression Gtk_New(Progress) ; Progress.set_fraction(0.5) ; Barre.Pack_End(Progress,Expand=> False, Fill => False) ; --Finalisation Win.Show_All ; Main ; END MaBarreDeStatus ; |
Maintenant, libre à vous de proposer des barres d'état avec davantage d'options. Pourquoi ne pas y intégrer l'heure, des statistiques concernant votre document, un outil de zoom ou des boutons pour remplacer les boîtes de dialogue !
Le menu déroulant
Fiche d'identité
- Widget : GTK_Combo_Box
- Package : GTK.Combo_Box
- Descendance : GTK_Widget >> GTK_Container >> GTK_Bin
- Description : Le
GTK_Combo_Box
se présente sous la forme d'un menu déroulant permettant un choix entre différents textes.
Sur la figure suivante, le menu déroulant permet de choisir entre différentes monnaies.
Méthodes
De nombreuses méthodes existent pour les GTK_Combo_Box
, mais nous allons nous concentrer sur le cas courant : un menu déroulant ne proposant que des lignes de texte. Auquel cas, nous devrons utiliser le constructeur suivant :
1 | procedure Gtk_New_Text(Combo : out Gtk_Combo_Box); |
L'ajout de texte se fait à l'aide de méthodes de type Append-Prepend-Insert comme vous devez vous en douter :
1 2 3 4 5 6 7 | procedure Append_Text (Combo_Box : access Gtk_Combo_Box_Record; Text : String); procedure Prepend_Text(Combo_Box : access Gtk_Combo_Box_Record; Text : String); procedure Insert_Text (Combo_Box : access Gtk_Combo_Box_Record; Position : Gint; Text : String); |
Pour la suppression d'une ligne de texte, vous devrez faire appel à la méthode Remove_Text()
et renseigner la position de la ligne souhaitée :
1 2 | procedure Remove_Text(Combo_Box : access Gtk_Combo_Box_Record; Position : Gint); |
Enfin, vous aurez besoin pour vos callbacks de connaître la valeur sélectionnée par l'utilisateur. Deux méthodes existent : Get_Active()
renverra le numéro de la valeur choisie (0 pour la première valeur, 1 pour la seconde… -1 si aucune n'est sélectionnée) ; Get_Active_Text()
renverra quant à elle le texte sélectionné (si aucune valeur n'a été sélectionnée, elle renverra un string
vide). Inversement, vous pourrez définir le texte activé avec Set_Active()
, par exemple pour définir une valeur par défaut. Attention toutefois, cette méthode émet automatiquement le signal Signal_Changed / "changed"
indiquant que la valeur à été modifiée.
1 2 3 4 | procedure Set_Active (Combo_Box : access Gtk_Combo_Box_Record; Index : Gint); function Get_Active (Combo_Box : access Gtk_Combo_Box_Record) return Gint; function Get_Active_Text(Combo_Box : access Gtk_Combo_Box_Record) return String; |
Menu déroulant avec saisie
Il est également possible d'autoriser l'utilisateur à saisir une valeur non prédéfinie. Reprenons l'exemple du programme présenté dans la Fiche d'identité. L'utilisateur ne peut utiliser le rouble, la livre sterling ou la roupie ; il est limité aux quatre choix proposés : Euro, Dollar, Yen et Yuan. Si vous souhaitez laisser davantage de liberté, il faudra utiliser un widget fils : les GTK_Combo_Box_Entry
. Ceux-ci n'apportent aucune méthode supplémentaire et utilisent le même signal.
Sur la figure suivante, la GTK_Combo_Box_Entry
permet d'entrer une valeur supplémentaire.
En résumé :
- Pour créer une barre d'icônes ou de menu, vous devez tout d'abord utiliser un premier widget comme conteneur :
GTK_Toolbar
ouGTK_Menu_Bar
. - Une fois la barre créée, ajoutez-y des items :
GTK_Menu_Item
pour la barre de menus etGTK_Tool_Button
pour la barre d'icônes. - Les
GTK_Menu_Item
ne sont en définitive que du texte. Pour qu'ils déroulent un menu, vous devrez utiliser lesGTK_Menu
. La même chose est réalisable avec la barre d'icônes en utilisant lesGtk_Menu_Tool_Button
au lieu desGtk_Tool_Button
. - Les widgets présentés dans ce chapitre sont des conteneurs. Il est donc possible de les imbriquer avec d'autres conteneurs afin de combiner divers widgets et d'obtenir des barres moins classiques.