GTK+ par l'exempleDate de publication : 28 juin 2006
XIV. Les racourcis clavier
XIV-A. Aperçu
XIV-B. Mise en place des raccourcis clavier
XIV-C. Code source
XIV. Les racourcis clavier
XIV-A. Aperçu
 Cliquez pour agrandir
XIV-B. Mise en place des raccourcis clavier
Il ne faut pas confondre les raccourcis clavier et les mnémoniques, ces derniers permettent d'accéder à un élément séquentiellement alors que les raccourcis appellent une fonction si l'utilisateur appuie simultanément sur une ou plusieurs touches (généralement de la forme <Modificateur>Touche, où Modificateur représente les touches Shift, Alt et Control). Ce raccourci peut être attaché à un élément du menu mais ceci n'est pas obligatoire.
Les raccourcis sont regroupés en groupe dans un GtkAccelGroup qu'il faut commencer par créer :
raccourcis.c | #include <gtk/gtk.h>
#include "callback.h"
#include "raccourcis.h"
GtkAccelGroup *accel_group_new (gpointer user_data)
{
GtkAccelGroup *p_accel_group = NULL;
p_accel_group = gtk_accel_group_new ();
return p_accel_group;
} |
Vous commencez à avoir l'habitude de cette organisation, nous allons donc créer une fonction qui va se charger d'ajouter un raccourci au groupe :
raccourcis.c | static void accelerator_new (GtkAccelGroup *p_accel_group, const gchar *accelerator, const gchar *accel_path,
GCallback callback, gpointer user_data)
{
guint key;
GdkModifierType mods;
GClosure *closure = NULL;
gtk_accelerator_parse (accelerator, &key, &mods);
closure = g_cclosure_new (callback, user_data, NULL);
gtk_accel_group_connect (p_accel_group, key, mods, GTK_ACCEL_VISIBLE, closure);
gtk_accel_map_add_entry (accel_path, key, mods);
} |
La fonction gtk_accelerator_parse permet de décomposer une chaîne de caractères de la forme "<Control>F1" ou encore "<Alt>A" en numéro de touche et modificateur.
En plus des touches, pour créer un raccourci clavier, nous avons besoin d'une fonction à appeler lorsque l'utilisateur appuie sur les touches spécifiées. gtk_accel_group_connect attend une fonction du type GClosure, regardons la documentation de gobject pour savoir à quoi cela correspond :
typedef struct {
} GClosure; |
Bon pas très instructif :( Heureusement en regardant le constructeur de la classe GClosure on retombe sur des choses connues :
GClosure *g_cclosure_new (GCallback callback_func, gpointer user_data, GClosureNotify destroy_data); |
Le dernier paramètre est une fonction qui sera appelée pour détruire l'objet user_data lorsqu'il ne sera plus utilisé.
Voilà nous pouvons déjà connecter le raccourci clavier à notre fonction callback.
Pour finir, pour associer un élément du menu à un raccourci clavier, nous avons besoin de l'ajouter à la carte des raccourcis, cette carte est unique et spécifique à chaque application :
void gtk_accel_map_add_entry (const gchar *accel_path, guint accel_key, GdkModifierType accel_mods); |
Il nous manque juste le paramètre accel_path. Il s'agit, comme son nom le laisse penser, d'un chemin pour notre raccourci. Ce chemin est semblable à un chemin de fichier : "<WINDOWTYPE>/Category1/Category2/.../Action" où WINDOWTYPE est un identifiant spécifique à chaque application, pour notre application, nous utiliserons EditeurGTK, ensuite la documentation de GTK+ conseille, pour les éléments du menu, d'utiliser son chemin, par exemple pour l'élément Nouveau : "Fichier/Nouveau" ce qui nous donne : "<EditeurGTK>/Fichier/Nouveau". Comme il va être nécessaire de reprendre ces chemins lors de la création des éléments du menu, il est préférable d'en faire des constantes :
raccourcis.h | #define ACCEL_PATH_NEW "<EditeurGTK>/Fichier/Nouveau"
#define ACCEL_PATH_OPEN "<EditeurGTK>/Fichier/Ouvrir"
#define ACCEL_PATH_SAVE "<EditeurGTK>/Fichier/Enregistrer"
#define ACCEL_PATH_SAVEAS "<EditeurGTK>/Fichier/Enregistrer sous"
#define ACCEL_PATH_CLOSE "<EditeurGTK>/Fichier/Fermer"
#define ACCEL_PATH_QUIT "<EditeurGTK>/Fichier/Quitter" |
Avant de créer nos raccourcis, il faut régler un problème (sur ce point je trouve que GTK+ est mal fait), en effet il est précisé que la fonction callback pour les raccourcis doit avoir la signature suivante :
gboolean (*GtkAccelGroupActivate) (GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier); |
Alors que nous avons des fonctions de la forme :
void callback (GtkWidget *p_widget, gpointer user_data); |
On est donc obligé de créer des fonctions de type GtkAccelGroupActivate qui vont se charger d'appeler nos fonctions callback :
raccourcis.c | static gboolean accel_new (GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer user_data)
{
cb_new (NULL, user_data);
return TRUE;
} |
 |
Notre fonction n'a pas la même signature que les GtkAccelGroupActivate puisque g_cclosure_new précise qu'il appelle la fonction callback ainsi créée avec user_data comme dernier paramètre.
|
Maintenant que le problème est résolu, créons nos raccourcis :
raccourcis.c | accelerator_new (p_accel_group, "<Control>N", ACCEL_PATH_NEW, G_CALLBACK (accel_new), user_data);
accelerator_new (p_accel_group, "<Control>O", ACCEL_PATH_OPEN, G_CALLBACK (accel_open), user_data);
accelerator_new (p_accel_group, "<Control>S", ACCEL_PATH_SAVE, G_CALLBACK (accel_save), user_data);
accelerator_new (p_accel_group, "<Control><Shift>S", ACCEL_PATH_SAVEAS, G_CALLBACK (accel_saveas), user_data);
accelerator_new (p_accel_group, "<Control>W", ACCEL_PATH_CLOSE, G_CALLBACK (accel_close), user_data);
accelerator_new (p_accel_group, "<Control>Q", ACCEL_PATH_QUIT, G_CALLBACK (accel_quit), user_data); |
Pour finir, il faut ajouter le GtkAccelGroup à notre fenêtre principale :
raccourcis.c | gtk_window_add_accel_group (docs.p_main_window, p_accel_group); |
Voilà, nous en avons fini avec ce fichier, maintenant il faut revenir à menu.c pour associer les raccouris aux éléments du menu. Il nous suffit de modifier notre constructeur de GtkMenuItem pour qu'il prenne en argument le accel_path :
menu.c | static void menu_item_new (GtkMenu *p_menu, const gchar *title, const gchar *accel_path, GCallback callback, gpointer user_data)
{
gtk_menu_item_set_accel_path (GTK_MENU_ITEM (p_menu_item), accel_path);
} |
Et d'utiliser nos constantes lors de l'appel à la fonction meni_item_new :
menu.c | menu_item_new (GTK_MENU (p_menu), "_Nouveau", ACCEL_PATH_NEW, G_CALLBACK (cb_new), user_data); |
XIV-C. Code source
Les sources présentés sur cette pages sont libre de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright ©2006 Nicolas Joseph.
Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu :
textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérets.
Cette page est déposée à la SACD.
|