È molto noioso creare grandi menu, specialmente se questi hanno icone e controlli da tastiera per ogni voce al loro interno. Gnome fornisce una soluzione molto semplice. Basta creare una struttura GnomeUIInfo come modello per ciascuna voce, elencando le caratteristiche: nome, icone, controllo da tastiera e così via. Le librerie di Gnome posso creare automaticamente menu da array di modelli GnomeUIInfo. Lo stesso metodo viene applicato per le barre di pulsanti.
Ecco la dichiarazione della struttura GnomeUIInfo.
typedef struct {
GnomeUIInfoType type;
gchar* label;
gchar* hint;
gpointer moreinfo;
gpointer user_data;
gpointer unused_data;
GnomeUIPixmapType pixmap_type;
gpointer pixmap_info;
guint accelerator_key;
GdkModifierType ac_mods;
GtkWidget* widget;
} GnomeUIInfo; |
Una inizializzazione statica si rivela spesso il metodo migliore per riempire la struttura (questa operazione può, ovviamente, essere eseguita dinamicamente). Le istruzioni di Gnome accettano un array di GnomeUIInfo, e sono fornite anche macro per semplificare e standardizzare gli oggetti più comuni. Ecco un esempio tipico, il menu File:
static GnomeUIInfo file_menu[] = {
GNOMEUIINFO_MENU_NEW_ITEM(N_("_Nuova Finestra"),
N_("Crea una nuova finestre dell'editor"),
new_app_cb, NULL),
GNOMEUIINFO_MENU_OPEN_ITEM(open_cb,NULL),
GNOMEUIINFO_MENU_SAVE_AS_ITEM(save_as_cb,NULL),
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_CLOSE_ITEM(close_cb,NULL),
GNOMEUIINFO_MENU_EXIT_ITEM(exit_cb,NULL),
GNOMEUIINFO_END
}; |
Non sempre si trova la macro adatta alle proprie esigenze, quindi è necessario specificare manualmente ciascun elemento della struttura:
{
GNOME_APP_UI_ITEM, N_("_Seleziona tutto"),
N_("Seleziona tutte le celle del foglio di calcolo"),
select_all_cb, NULL,
NULL, 0, 0, 'a', GDK_CONTROL_MASK
} |
In questo momento vi starete sicuramente chiedendo che cosa significhino tutti i membri della struttura. È molto semplice:
type è il marcatore di tipo per l'enumerazione di GnomeUIInfoType. Tabella 1.
label è il testo della voce del menu o del pulsante della barra. Deve essere marcato per l'internazionalizzazione con la macro N_().
hint è la descrizione della funzionalità dell'oggetto. Per i pulsanti della barra, questo apparirà come un suggerimento, per il menu può apparire nella barra di stato.
moreinfo dipende dal type dell'oggetto. Tabella 1.
user_data verrà passato alla funzione di callback chiamata, se ne esiste una.
unused_data deve essere impostato come NULL, poiché non viene ancora utilizzato, lo sarà in future versioni di Gnome.
pixmap_type è il valore per l'enumerazione di GnomeUIPixmapType. Il suo fine è di specificare il tipo del membro successivo, pixmap_info.
pixmap_info può essere dati di una pixmap, il nome di un file oppure una pixmap del Gnome stock.
accelerator_key è il tasto associato per le scorciatoie da tastiera. È possibile utilizzare un singolo carattere, come 'a', oppure un valore di gdk/gdkkeysyms.h.
ac_mods è la maschera per il modificatore da utilizzare con la scorciatoia da tastiera.
widget deve essere NULL; Gnome riempie questo membro quando il menu o la barra vengono creati. Sarà possibile poi ottenere questo membro, per manipolarlo come desiderate.
Vi starete sicuramente chiedendo perché le voci del menu contengano underscore: questi vengono utilizzati per creare la scorciatoia da tastiera per le voci del menu. I traduttori possono spostarlo a loro piacimento per rendere l'operazione più intuitiva possibile nella propria lingua. Gnome analizza la stringa alla ricerca della scorciatoia, rimuovendo successivamente l'underscore.
Tabella 1 elenca i possibili valori del campo type di una struttura GnomeUIInfo. Per maggiori informazioni si rimanda alla consultazione del file libgnomeui/gnome-app-helper.h. Esistono attualmente alcuni valori possibili, poiché gli altri vengono utilizzati internamente alla libreria. I valori in Tabella 1 dovrebbero comunque essere sufficienti per il codice di una applicazione.
Tabella 1. I valori di GnomeUIInfoType
| GnomeUIInfoType | Descrizione | Campo moreinfo |
|---|---|---|
| GNOME_APP_UI_ENDOFINFO | Termina una tabella di GnomeUIInfo | Nessuno |
| GNOME_APP_UI_ITEM | Oggetto normale (oppure pulsante radio all'interno di un gruppo radio) | Funzione callback |
| GNOME_APP_UI_TOGGLEITEM | Oggetto Toggle/Check | Funzione Callback |
| GNOME_APP_UI_RADIOITEMS | Gruppo pulsanti Radio | Array di pulsanti radio all'interno del gruppo |
| GNOME_APP_UI_SUBTREE | Sottomenu | Array di GnomeUIInfo del sottomenu |
| GNOME_APP_UI_SEPARATOR | Separatore | Nessuno |
| GNOME_APP_UI_HELP | Oggetto di aiuto | Nodo di aiuto da visualizzare |
Per creare un intero albero di menu, dovete includere i puntatori alle tabelle dei menu utilizzando la macro GNOMEUIINFO_SUBTREE() :
static GnomeUIInfo main_menu[] = {
GNOMEUIINFO_SUBTREE(N_("_File"), file_menu),
GNOMEUIINFO_END
}; |
In questo caso particolare esiste una macro più conveniente da utilizzare:
static GnomeUIInfo main_menu[] = {
GNOMEUIINFO_MENU_FILE_TREE(file_menu),
GNOMEUIINFO_END
}; |
Il principale vantaggio derivante dall'uso di questa macro è la standardizzazione. Questa assicura che tutti i menu file di Gnome utilizzino la stessa scorciatoia da tastiera e abbiamo lo stesso nome. Esistono svariate macro analoghe offerte da Gnome, la lista completa è reperibile in libgnomeui/gnome-app-helper.h.
Una volta creta la tabella dei menu, questa verrà processata da Gnome e convertira in un widget. Le funzioni per questa operazione sono elencate in Figura 4
#include <libgnomeui/gnome-app-helper.h> |
void gnome_app_create_menus(GnomeApp* app, GnomeUIInfo* uiinfo);
void gnome_app_create_menus_with_data(GnomeApp* app, GnomeUIInfo* uiinfo, gpointer user_data);
void gnome_app_create_toolbar(GnomeApp* app, GnomeUIInfo* uiinfo);
void gnome_app_create_toolbar_with_data(GnomeApp* app, GnomeUIInfo* uiinfo, gpointer user_data);
void gnome_app_fill_toolbar(GtkToolbar* toolbar, GnomeUIInfo* uiinfo, GtkAccelGroup* accel_group);
void gnome_app_fill_toolbar_with_data(GtkToolbar* toolbar, GnomeUIInfo* uiinfo, GtkAccelGroup* accel_group, gpointer data);
void gnome_app_fill_menu(GtkMenuShell* menushell, GnomeUIInfo* uiinfo, GtkAccelGroup* accel_group, gboolean uline_accels, gint pos);
void gnome_app_fill_menu_with_data(GtkMenuShell* menushell, GnomeUIInfo* uiinfo, GtkAccelGroup* accel_group, gboolean uline_accels, gint pos, gpointer user_data);
Figura 4. Creare widget da GnomeUIInfo
Se state utilizzando il widget GnomeApp widget, gnome_app_create_menus() e gnome_app_create_toolbar() creano un menu o una barra di pulsanti dalla tabella GnomeUIInfo fornita da voi, successivamente li inseriscono all'interno di GnomeApp. Queste sono le funzioni che vengono utilizzate nella maggior parte dei casi: tutto viene eseguito automaticamente. Esiste la variante _with_data() di ciascuna funzione che sostituisce il membro user_data della struttura GnomeUIInfo.
Se le vostre esigenze sono molto particolari, potete creare manualmente la barra di menu o di pulsanti e inserirle in un contenitore di vostro piacimento. Le funzioni fill richiedono di specificare il gruppo di scorciatoie per tastiera in cui inserire le singole scorciatoie. In GnomeApp esiste un gruppo di scorciatoie nelle struttura del widget stesso (il membro accel_group). Le funzioni fill per i menu richiedono due ulteriori argomenti: potete scegliere se far analizzare la stringa della voce del menu alla ricerca di un underscore per estrarre la scorciatoia, e potete specificare la posizione in GtkMenuShell da dove la funzione inizierà a inserire voci del menu.
(GtkMenuShell è semplicemente la classe di base per GtkMenuBar e GtkMenu, ad esempio è un widget che contiene le voci del menu. Un gruppo di scorciatoie è semplicemente una raccolta di queste, associato normalmente a un GtkWindow. Utilizzate GNOME_APP(widget)->accel_group in questo caso.)
Quando viene utilizzata una tabella GnomeUIInfo per creare una barra di menu o pulsanti, i puntatori ai widget delle singole voci del menu o pulsanti della barra sono presenti nel membro widget di ciascuna struttura GnomeUIInfo. È possibile quindi utilizzare questi puntatori per accedere ai singoli widget. Ad esempio, se create un oggetto check all'interno del menu è possibile accedervi per controllarne lo stato. Il puntatore è inoltre utile per creare manualmente alcune parti del menu: potete creare un sottomenu vuoto, e quindi manualmente crearne il contenuto.
L'applicazione GnomeHello crea le barre di menu e pulsanti utilizzando il metodo GnomeUIInfo. Il codice relativo è contenuto in un file separato, menus.c. L'Appendice E mostra questo file nella sua interezza.