~gabriel1984sibiu/gtk+1.2/gtk+1.2

« back to all changes in this revision

Viewing changes to docs/html/gtk_tut_it-10.html

  • Committer: Bazaar Package Importer
  • Author(s): Akira TAGOH
  • Date: 2002-04-15 02:19:49 UTC
  • Revision ID: james.westby@ubuntu.com-20020415021949-eh01yrgh4b85p9z7
Tags: upstream-1.2.10
ImportĀ upstreamĀ versionĀ 1.2.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 
2
<HTML>
 
3
<HEAD>
 
4
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
 
5
 <TITLE>GTK Tutorial: Il Widget Men&ugrave; (Menu Widgets)</TITLE>
 
6
 <LINK HREF="gtk_tut_it-11.html" REL=next>
 
7
 <LINK HREF="gtk_tut_it-9.html" REL=previous>
 
8
 <LINK HREF="gtk_tut_it.html#toc10" REL=contents>
 
9
</HEAD>
 
10
<BODY BGCOLOR="#FFFFFF">
 
11
<A HREF="gtk_tut_it-11.html">Avanti</A>
 
12
<A HREF="gtk_tut_it-9.html">Indietro</A>
 
13
<A HREF="gtk_tut_it.html#toc10">Indice</A>
 
14
<HR NOSHADE>
 
15
<H2><A NAME="s10">10. Il Widget Men&ugrave; (Menu Widgets)</A></H2>
 
16
 
 
17
<P>Ci sono due modi per creare dei men&ugrave;, quello facile e quello difficile.
 
18
Ognuno &egrave; pi&ugrave; adatto per certe circostanze, ma di solito si pu&ograve; usare il
 
19
modo semplice, cio&eacute; menu_factory (la ``fabbrica dei men&ugrave;''). Il modo 
 
20
``difficile'' &egrave; di crearsi tutti i men&ugrave; usando direttamente le chiamate.
 
21
Quello semplice &egrave; di usare le chiamate di tipo gtk_menu_factory. Anche se
 
22
&egrave; un modo molto pi&ugrave; semplice, ci sono svantaggi e vantaggi per ciascuno
 
23
dei due approcci.
 
24
<P>La menu_factory &egrave; molto pi&ugrave; semplice da usare e per aggiungere dei nuovi
 
25
men&ugrave;, anche se scriversi un po' di funzioni per creare dei men&ugrave; con il
 
26
metodo manuale pu&ograve; dare risultati molto migliori dal punto di vista 
 
27
dell'usabilit&agrave;. Con la menufactory, non &egrave; possibile mettere immagini o
 
28
caratteri '/' nei men&ugrave;.
 
29
<P>
 
30
<H2><A NAME="ss10.1">10.1 Creazione Manuale di Men&ugrave;</A>
 
31
</H2>
 
32
 
 
33
<P>Seguendo la tradizionale arte dell'insegnamento, partiamo dal modo
 
34
difficile. <CODE>:)</CODE>
 
35
<P>I widget che hanno a che fare con la creazione di una barra di men&ugrave; e di sottomen&ugrave; sono tre:
 
36
<UL>
 
37
<LI>un elemento di men&ugrave;, che \ quello che l'utente poi selezioner&agrave;, per esempio 'Salva'</LI>
 
38
<LI>un men&ugrave;, che fa la parte di contenitore per gli elementi di men&ugrave;, e</LI>
 
39
<LI>una barra dei men&ugrave;, che &egrave; un contenitore per ciascuno dei men&ugrave;</LI>
 
40
</UL>
 
41
<P>
 
42
<P>La cosa viene un po' complicata dal fatto che i widget elemento di men&ugrave; vngono usati per
 
43
<P>due scopi diversi. Essi sono sia i widget che vengono impacchettati nei men&ugrave;, che 
 
44
<P>quelli che vengono impacchettati nella barra dei men&ugrave; che, quando selezonati, attivano i men&ugrave;.
 
45
<P>Diamo un'occhiata alle funzioni usate per creare i men&ugrave; e le barre di men&ugrave;.
 
46
Con questa prima funzione si crea un nuova barra di men&ugrave;:
 
47
<P>
 
48
<P>
 
49
<BLOCKQUOTE><CODE>
 
50
<PRE>
 
51
GtkWidget *gtk_menu_bar_new(void);
 
52
</PRE>
 
53
</CODE></BLOCKQUOTE>
 
54
<P>Questa funzione crea una nuova barra di men&ugrave;. Per impacchettarla in una
 
55
finestra o si usa la funzione gtk_container_add, oppure, per impacchettarla
 
56
in una scatola, le funzioni box_pack - come con i bottoni.
 
57
<P>
 
58
<BLOCKQUOTE><CODE>
 
59
<PRE>
 
60
GtkWidget *gtk_menu_new();
 
61
</PRE>
 
62
</CODE></BLOCKQUOTE>
 
63
<P>Questa funzione restituisce un puntatore ad un nuovo men&ugrave;, non viene mai
 
64
realmente mostrato (con gtk_widget_show), serve solo per contenere gli
 
65
elementi del men&ugrave;. Spero che il tutto risulti pi&ugrave; chiaro quando daremo
 
66
un'occhiata all'esempio pi&ugrave; sotto.
 
67
<P>Le prossime due chiamate sono usate per creare degli elementi che poi
 
68
vengono impacchettati nei men&ugrave; e nelle barre dei men&ugrave;..
 
69
<P>
 
70
<BLOCKQUOTE><CODE>
 
71
<PRE>
 
72
GtkWidget *gtk_menu_item_new();
 
73
</PRE>
 
74
</CODE></BLOCKQUOTE>
 
75
<P>e
 
76
<P>
 
77
<BLOCKQUOTE><CODE>
 
78
<PRE>
 
79
GtkWidget *gtk_menu_item_new_with_label(const char *label);
 
80
</PRE>
 
81
</CODE></BLOCKQUOTE>
 
82
<P>Queste chiamate sono usate per creare gli elementi di men&ugrave; che devono poi essere mostrati.
 
83
Ricordate la differenza che esiste fra un ``men&ugrave;'' come quelli creati con
 
84
gtk_menu_new e un ``elemento di men&ugrave;'' (menu item) come quelli creati con
 
85
la funzione gtk_menu_item_new. L'elemento di men&ugrave; sar&agrave; un bottone
 
86
vero e proprio con una azione associata, mentre un men&ugrave; &egrave; solo un contenitore che li raccoglie.
 
87
Le funzioni gtk_menu_new_with_label e gtk_menu_new sono esattamente come vi aspettereste che siano dopo
 
88
<P>aver conosciuto i bottoni. Una crea un nuovo elemento di men&ugrave; con un'etichetta gi&agrave; impacchettata,
 
89
<P>mentre l'altra crea un elemento di men&ugrave; vuoto.
 
90
<P>
 
91
<P>Una volta che si \ creato un elemento di men&ugrave;, &egrave; necessario piazzarlo su di un men&ugrave;.
 
92
<P>Per fare ci&ograve; si usa la funzione gtk_menu_append. Per determinare quando l'utente ha selezionato un elemento, abbiamo bisogno di connettere il segnale <CODE>activate</CODE> nel solito modo.
 
93
<P>Quindi, se volessimo creare un normale men&ugrave; <CODE>File</CODE>, con le opzioni <CODE>Open</CODE>, <CODE>Save</CODE> e <CODE>Quit</CODE>, il codice avrebbe pi&ugrave; o meno il seguente aspetto:
 
94
<P>
 
95
<BLOCKQUOTE><CODE>
 
96
<PRE>
 
97
file_menu = gtk_menu_new();    /* Non e' necessario mostrare i menu' */
 
98
 
 
99
/* Creiamo gli elementi del menu' */
 
100
open_item = gtk_menu_item_new_with_label("Open");
 
101
save_item = gtk_menu_item_new_with_label("Save");
 
102
quit_item = gtk_menu_item_new_with_label("Quit");
 
103
 
 
104
/* Aggiungiamoli al menu' */
 
105
gtk_menu_append( GTK_MENU(file_menu), open_item);
 
106
gtk_menu_append( GTK_MENU(file_menu), save_item);
 
107
gtk_menu_append( GTK_MENU(file_menu), quit_item);
 
108
 
 
109
 
 
110
/* Colleghiamo le funzioni di callback al segnale activate */
 
111
gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
 
112
                           GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.open");
 
113
gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
 
114
                           GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.save");
 
115
 
 
116
/* Possiamo collegare l'elemento Quit alla nostra funzione di uscita */
 
117
gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
 
118
                           GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit");
 
119
 
 
120
/* Abbiamo bisogno di mostrare gli elementi di menu' */
 
121
gtk_widget_show( open_item );
 
122
gtk_widget_show( save_item );
 
123
gtk_widget_show( quit_item );
 
124
 
 
125
</PRE>
 
126
</CODE></BLOCKQUOTE>
 
127
<P>
 
128
<P>A questo punto abbiamo il nostro men&ugrave; Adesso abbiamo bisogno di creare una barra dei men&ugrave;
 
129
<P>e un elemento di men&ugrave; per <CODE>File</CODE>, a cui aggiungeremo il nostro men&ugrave;. Il codice &egrave; questo:
 
130
<P>
 
131
<P>
 
132
<BLOCKQUOTE><CODE>
 
133
<PRE>
 
134
menu_bar = gtk_menu_bar_new();
 
135
gtk_container_add( GTK_CONTAINER(window), menu_bar);
 
136
gtk_widget_show( menu_bar );
 
137
 
 
138
file_item = gtk_menu_item_new_with_label("File");
 
139
gtk_widget_show(file_item);
 
140
</PRE>
 
141
</CODE></BLOCKQUOTE>
 
142
<P>
 
143
<P>Ora dobbiamo associare il men&ugrave; con <CODE>file_item</CODE>. Lo si pu&ograve; fare con la funzione
 
144
<P>
 
145
<BLOCKQUOTE><CODE>
 
146
void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
 
147
GtkWidget *submenu);
 
148
</CODE></BLOCKQUOTE>
 
149
<P>
 
150
<P>Quindi, il nostro esempio continuerebbe con
 
151
<P>
 
152
<BLOCKQUOTE><CODE>
 
153
<PRE>
 
154
gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu);
 
155
</PRE>
 
156
</CODE></BLOCKQUOTE>
 
157
<P>
 
158
<P>Ci&ograve; che manca a questo punto &egrave; di collegare il men&ugrave; alla barra, cosa che si pu&ograve; ottenere tramite la funzione
 
159
<P>
 
160
<BLOCKQUOTE><CODE>
 
161
void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
 
162
</CODE></BLOCKQUOTE>
 
163
<P>che nel nostro caso &egrave;:
 
164
<P>
 
165
<BLOCKQUOTE><CODE>
 
166
<PRE>
 
167
gtk_menu_bar_append( GTK_MENU_BAR(menu_bar), file_item );
 
168
</PRE>
 
169
</CODE></BLOCKQUOTE>
 
170
<P>
 
171
<P>Se volessimo il men&ugrave; giustificato a dstra, come sono spesso i men&ugrave; di aiuto, potremm
 
172
<P>usare la seguente funzioe (di nuovo su <CODE>file_item</CODE>  in questo esempio) prima di fare il collegamento alla barra.
 
173
<P>
 
174
<P>
 
175
<BLOCKQUOTE><CODE>
 
176
<PRE>
 
177
void gtk_menu_item_right_justify (GtkMenuItem *menu_item);
 
178
</PRE>
 
179
</CODE></BLOCKQUOTE>
 
180
 
 
181
Ecco un riassunto dei passi necessari per creare una barra con i relativi men&ugrave; collegati:
 
182
<P>
 
183
<UL>
 
184
<LI>    Create un nuovo men&ugrave; con gtk_menu_new()</LI>
 
185
<LI>    Usate delle chiamate multiple a gtk_menu_item_new() per ognuno degli
 
186
elementi che volete mettere nel vostro men&ugrave;. Usate inoltre gtk_menu_item_append()
 
187
per mettere ciascuno di questi nuovi elementi sul men&ugrave;..</LI>
 
188
<LI> Create un elemento di men&ugrave; usando gtk_menu_item_new(). Questo rappresenta l'elemento di base 
 
189
 
 
190
delmen&ugrave;, e il testo relativo sar&agrave; il testo mostrato sulla barra dei men&ugrave; stessa.
 
191
</LI>
 
192
<LI> Usate gtk_menu_item_set_submenu() per collegare i men&ugrave; all'elemento base del men&ugrave; (cio&egrave; quello creato al passaggio precedente).
 
193
</LI>
 
194
<LI>    Create una nuova barra di men&ugrave; usando gtk_menu_bar_new. Questo passo
 
195
necessita di essere effettuato una sola volta quando si crea una serie di
 
196
men&ugrave; su una sola barra.</LI>
 
197
<LI> Usate gtk_menu_bar_append per mettere il men&ugrave; base sulla barra dei men&ugrave;.</LI>
 
198
</UL>
 
199
<P>Creare un men&ugrave; a comparsa &egrave; pi&ugrave; o meno la stessa cosa. La differenza &egrave; che il
 
200
il men&ugrave; non viene attivato ``automaticamente'' da una barra, bens&igrave; per esempio
 
201
con la chiamata espicita alla funzione gtk_menu_popup() da parte di un evento di pressione di un pulsante.
 
202
Seguite questi passaggi:
 
203
<UL>
 
204
<LI>Create una funzione di gestione di un evento. Essa deve seguire il prototipo
 
205
<BLOCKQUOTE><CODE>
 
206
static gint handler(GtkWidget *widget, GdkEvent *event);
 
207
</CODE></BLOCKQUOTE>
 
208
 
 
209
e usare l'evento per scoprire dove il menu deve essere fatto comparire.</LI>
 
210
<LI>Nel gestore di evento, se questo &egrave; la pressione di un bottone, trattate
 
211
<CODE>event</CODE> come l'evento relativo ad un bottone (cosa che in effetti &egrave;)
 
212
e usatelo come mostrato nel codice di esempio per passare informazioni a
 
213
gtk_menu_popup().</LI>
 
214
<LI>Collegate il gestore di evento a un widget con
 
215
<BLOCKQUOTE><CODE>
 
216
gtk_signal_connect_object(GTK_OBJECT(widget), "event",
 
217
GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu));
 
218
</CODE></BLOCKQUOTE>
 
219
 
 
220
in cui <CODE>widget</CODE> &egrave; il widget a cui state effettuando il collegamento, e
 
221
<CODE>handler</CODE> &egrave; la funzione di gestione, mentre <CODE>menu</CODE> &egrave; un men&ugrave;
 
222
creato con gtk_menu_new(). Quest'ultimo pu&ograve; essere un men&ugrave; che viene anche
 
223
attivato da una barra di men&ugrave;, come mostrato nel codice di esempio.</LI>
 
224
</UL>
 
225
<P>
 
226
<P>
 
227
<H2><A NAME="ss10.2">10.2 Esempio di Men&ugrave; Manuale</A>
 
228
</H2>
 
229
 
 
230
<P>Per la teoria dovrebbe essere abbastanza. Diamo un'occhiata ad un esempio che
 
231
ci aiuti a chiarire le cose.
 
232
<P>
 
233
<BLOCKQUOTE><CODE>
 
234
<PRE>
 
235
/* menu.c */
 
236
#include &lt;gtk/gtk.h>
 
237
 
 
238
static gint button_press (GtkWidget *, GdkEvent *);
 
239
static void menuitem_response (gchar *);
 
240
 
 
241
int main (int argc, char *argv[])
 
242
{
 
243
 
 
244
    GtkWidget *window;
 
245
    GtkWidget *menu;
 
246
    GtkWidget *menu_bar;
 
247
    GtkWidget *root_menu;
 
248
    GtkWidget *menu_items;
 
249
    GtkWidget *vbox;
 
250
    GtkWidget *button;
 
251
    char buf[128];
 
252
    int i;
 
253
 
 
254
    gtk_init (&amp;argc, &amp;argv);
 
255
 
 
256
    /* crea una nuova finestra */
 
257
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
258
    gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
 
259
 
 
260
    gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
 
261
    gtk_signal_connect(GTK_OBJECT (window), "delete_event",
 
262
                       (GtkSignalFunc) gtk_main_quit, NULL);
 
263
 
 
264
    /* Inizializziamo il men&ugrave;, e ricordate: mai applicare
 
265
     * gtk_show_widget() al widget men&ugrave;!!
 
266
     * Questo &egrave; il men&ugrave; che contiene gli elementi, quello che
 
267
     * spunta quando si fa click sul "Men&ugrave; radice" nell'applicazione */
 
268
    menu = gtk_menu_new();
 
269
 
 
270
    /* Ora creiamo un ciclo che crea tre elementi di menu per "test-menu".
 
271
     * Notete la chiamata a gtk_menu_append. In questo punto aggiungiamo una
 
272
     * lista di elementi al nostro men&ugrave;. Normalmente, dovremmo poi catturare
 
273
     * il segnale di attivazione per ognuno degli elementi del menu, e creare
 
274
     * una funzione di ritorno per ciascuno di essi, ma qui non li mettiamo per
 
275
     * brevit&agrave;. */
 
276
 
 
277
    for(i = 0; i &lt; 3; i++)
 
278
        {
 
279
            /* Copia i nomi in buf. */
 
280
            sprintf(buf, "Test-undermenu - %d", i);
 
281
 
 
282
            /* Crea un nuovo elemento di men&ugrave; con un nome... */
 
283
            menu_items = gtk_menu_item_new_with_label(buf);
 
284
 
 
285
            /* ...e aggiungilo al men&ugrave;. */
 
286
            gtk_menu_append(GTK_MENU (menu), menu_items);
 
287
 
 
288
            /* Fa qualcosa di interessante quando si seleziona l'elemento */
 
289
            gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
 
290
                GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
 
291
 
 
292
            /* Mostra il widget */
 
293
            gtk_widget_show(menu_items);
 
294
        }
 
295
 
 
296
    /* Questo &egrave; il men&ugrave; radice, e l'etichetta sar&agrave; il nome del men&ugrave; che
 
297
     * verr&agrave; mostrato sulla barra dei men&ugrave;. Non ci sar&agrave; alcun gestore di
 
298
     * segnale collegato, dal momento che non fa altro che mostrare il resto
 
299
     * del men&ugrave; quando viene premuto. */
 
300
    root_menu = gtk_menu_item_new_with_label("Root Menu");
 
301
 
 
302
    gtk_widget_show(root_menu);
 
303
 
 
304
 
 
305
 
 
306
 
 
307
    /* Ora specifichiamo che vogliamo che il men&ugrave; che abbiamo appena creato
 
308
     * sia il men&ugrave; radice *//
 
309
    gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
 
310
 
 
311
    /* Una vbox in cui mettere un men&ugrave; ed un bottone: */
 
312
    vbox = gtk_vbox_new(FALSE, 0);
 
313
    gtk_container_add(GTK_CONTAINER(window), vbox);
 
314
    gtk_widget_show(vbox);
 
315
 
 
316
    /* Crea una barra dei men&ugrave; per metterci i men&ugrave; e l'aggiunge alla finestra principale */
 
317
    menu_bar = gtk_menu_bar_new();
 
318
    gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
 
319
    gtk_widget_show(menu_bar);
 
320
 
 
321
    /* Crea un bottone a cui collegare un men&ugrave; */
 
322
    button = gtk_button_new_with_label("press me");
 
323
    gtk_signal_connect_object(GTK_OBJECT(button), "event",
 
324
        GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
 
325
    gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
 
326
    gtk_widget_show(button);
 
327
 
 
328
    /* E finalmente attacchiamo l'elemento di men&ugrave; alla barra dei men&ugrave; -- questo
 
329
     * &egrave; l'elemento di men&ugrave; "radice" di cui parlavo */
 
330
    gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
 
331
 
 
332
    /* La finestra va mostrata sempre come ultimo passo in modo che sia gi&agrave;
 
333
     * completa di tutti i suoi elementi. */
 
334
    gtk_widget_show(window);
 
335
 
 
336
    gtk_main ();
 
337
 
 
338
    return 0;
 
339
}
 
340
 
 
341
 
 
342
 
 
343
/* Risponde alla pressione di un bottone impostando un men&ugrave; che
 
344
 * viene passato come widget.
 
345
 * Notate che l'argomento "widget" si riferisce al men&ugrave; impostato
 
346
 * e NON al bottone premuto.
 
347
 */
 
348
 
 
349
static gint button_press (GtkWidget *widget, GdkEvent *event)
 
350
{
 
351
 
 
352
    if (event->type == GDK_BUTTON_PRESS) {
 
353
        GdkEventButton *bevent = (GdkEventButton *) event; 
 
354
        gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
 
355
                        bevent->button, bevent->time);
 
356
        /* Riferisce al codice chiamante che abbiamo trattato l'evento;
 
357
         * la faccenda finisce qui. */
 
358
        return TRUE;
 
359
    }
 
360
 
 
361
    /* Riferisce al codice chiamante che abbiamo trattato l'evento; passa avanti. */
 
362
    return FALSE;
 
363
}
 
364
 
 
365
 
 
366
/* Stampa una stringa quando viene selezionato un elemento di men&ugrave; */
 
367
 
 
368
static void menuitem_response (gchar *string)
 
369
{
 
370
    printf("%s\n", string);
 
371
}
 
372
</PRE>
 
373
</CODE></BLOCKQUOTE>
 
374
<P>Si pu&ograve; anche fare in modo che un elemento di men&ugrave; sia insensibile e, usando
 
375
una tabella di acelleratori, collegare dei tasti a delle funzioni di men&ugrave;.
 
376
<P>
 
377
<P>
 
378
<H2><A NAME="ss10.3">10.3 Usare GtkMenuFactory</A>
 
379
</H2>
 
380
 
 
381
<P>Ora che vi abbiamo mostrato il modo difficile, ecco invece come si fa usando
 
382
le chiamate di gtk_menu_factory.
 
383
<P>
 
384
<P>
 
385
<H2><A NAME="ss10.4">10.4 Esempio di Menu Factory</A>
 
386
</H2>
 
387
 
 
388
<P>Ecco un esempio di utilizzo della ``Fabbrica'' di Men&ugrave; di GTK (Menu Factory). 
 
389
Questo &egrave; il primo file, menufactoy.h. Teniemo dei file menufactory.c e main.c separati
 
390
a causa delle variabili globali usate nel file menufactory.c.
 
391
<P>
 
392
<BLOCKQUOTE><CODE>
 
393
<PRE>
 
394
 
 
395
/* menufactory.h */
 
396
 
 
397
#ifndef __MENUFACTORY_H__
 
398
#define __MENUFACTORY_H__
 
399
 
 
400
#ifdef __cplusplus
 
401
extern "C" {
 
402
#endif /* __cplusplus */
 
403
 
 
404
void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);
 
405
void menus_create(GtkMenuEntry *entries, int nmenu_entries);
 
406
 
 
407
#ifdef __cplusplus
 
408
}
 
409
#endif /* __cplusplus */
 
410
 
 
411
#endif /* __MENUFACTORY_H__ */
 
412
</PRE>
 
413
</CODE></BLOCKQUOTE>
 
414
<P>Ed ecco il file menufactory.c.
 
415
<P>
 
416
<BLOCKQUOTE><CODE>
 
417
<PRE>
 
418
/* menufactory.c */
 
419
#include &lt;gtk/gtk.h>
 
420
#include &lt;strings.h>
 
421
 
 
422
#include "mfmain.h"
 
423
 
 
424
static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path);
 
425
static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path);
 
426
void menus_init(void);
 
427
void menus_create(GtkMenuEntry * entries, int nmenu_entries);
 
428
 
 
429
/* Questa &egrave; la struttuta GtkMenuEntry, che viene usata per creare dei nuovi
 
430
 * men&ugrave;. Il primo membro &agrave; la stringa di definizione del men&ugrave;. Il secondo
 
431
 * &egrave; il tasto acceleratore predefinito, usato per accedere a questa funzione
 
432
 * con la tastiera. Il terzo &egrave; la funzione di ritorno che viene chiamata
 
433
 * quando si seleziona con la tastiera o il mouse questo elemento di men&ugrave;.
 
434
 * L'ultimo membro costituisce il dato che viene passato alla funzione di
 
435
 * ritorno. */
 
436
 
 
437
static GtkMenuEntry menu_items[] =
 
438
{
 
439
        {"&lt;Main>/File/New", "&lt;control>N", NULL, NULL},
 
440
        {"&lt;Main>/File/Open", "&lt;control>O", NULL, NULL},
 
441
        {"&lt;Main>/File/Save", "&lt;control>S", NULL, NULL},
 
442
        {"&lt;Main>/File/Save as", NULL, NULL, NULL},
 
443
        {"&lt;Main>/File/&lt;separator>", NULL, NULL, NULL},
 
444
        {"&lt;Main>/File/Quit", "&lt;control>Q", file_quit_cmd_callback, "OK, I'll quit"},
 
445
        {"&lt;Main>/Options/Test", NULL, NULL, NULL}
 
446
};
 
447
 
 
448
/* calcola il numero di menu_item */
 
449
static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
 
450
 
 
451
static int initialize = TRUE;
 
452
static GtkMenuFactory *factory = NULL;
 
453
static GtkMenuFactory *subfactory[1];
 
454
static GHashTable *entry_ht = NULL;
 
455
 
 
456
void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table)
 
457
{
 
458
    if (initialize)
 
459
            menus_init();
 
460
    
 
461
    if (menubar)
 
462
            *menubar = subfactory[0]->widget;
 
463
    if (table)
 
464
            *table = subfactory[0]->table;
 
465
}
 
466
 
 
467
void menus_init(void)
 
468
{
 
469
    if (initialize) {
 
470
        initialize = FALSE;
 
471
        
 
472
        factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
 
473
        subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
 
474
        
 
475
        gtk_menu_factory_add_subfactory(factory, subfactory[0], "&lt;Main>");
 
476
        menus_create(menu_items, nmenu_items);
 
477
    }
 
478
}
 
479
 
 
480
void menus_create(GtkMenuEntry * entries, int nmenu_entries)
 
481
{
 
482
    char *accelerator;
 
483
    int i;
 
484
    
 
485
    if (initialize)
 
486
            menus_init();
 
487
    
 
488
    if (entry_ht)
 
489
            for (i = 0; i &lt; nmenu_entries; i++) {
 
490
                accelerator = g_hash_table_lookup(entry_ht, entries[i].path);
 
491
                if (accelerator) {
 
492
                    if (accelerator[0] == '\0')
 
493
                            entries[i].accelerator = NULL;
 
494
                    else
 
495
                            entries[i].accelerator = accelerator;
 
496
                }
 
497
            }
 
498
    gtk_menu_factory_add_entries(factory, entries, nmenu_entries);
 
499
    
 
500
    for (i = 0; i &lt; nmenu_entries; i++)
 
501
            if (entries[i].widget) {
 
502
                gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator",
 
503
                                   (GtkSignalFunc) menus_install_accel,
 
504
                                   entries[i].path);
 
505
                gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator",
 
506
                                   (GtkSignalFunc) menus_remove_accel,
 
507
                                   entries[i].path);
 
508
            }
 
509
}
 
510
 
 
511
static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path)
 
512
{
 
513
    char accel[64];
 
514
    char *t1, t2[2];
 
515
    
 
516
    accel[0] = '\0';
 
517
    if (modifiers &amp; GDK_CONTROL_MASK)
 
518
            strcat(accel, "&lt;control>");
 
519
    if (modifiers &amp; GDK_SHIFT_MASK)
 
520
            strcat(accel, "&lt;shift>");
 
521
    if (modifiers &amp; GDK_MOD1_MASK)
 
522
            strcat(accel, "&lt;alt>");
 
523
    
 
524
    t2[0] = key;
 
525
    t2[1] = '\0';
 
526
    strcat(accel, t2);
 
527
    
 
528
    if (entry_ht) {
 
529
        t1 = g_hash_table_lookup(entry_ht, path);
 
530
        g_free(t1);
 
531
    } else
 
532
            entry_ht = g_hash_table_new(g_str_hash, g_str_equal);
 
533
    
 
534
    g_hash_table_insert(entry_ht, path, g_strdup(accel));
 
535
    
 
536
    return TRUE;
 
537
}
 
538
 
 
539
static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path)
 
540
{
 
541
    char *t;
 
542
    
 
543
    if (entry_ht) {
 
544
        t = g_hash_table_lookup(entry_ht, path);
 
545
        g_free(t);
 
546
        
 
547
        g_hash_table_insert(entry_ht, path, g_strdup(""));
 
548
    }
 
549
}
 
550
 
 
551
void menus_set_sensitive(char *path, int sensitive)
 
552
{
 
553
    GtkMenuPath *menu_path;
 
554
    
 
555
    if (initialize)
 
556
            menus_init();
 
557
    
 
558
    menu_path = gtk_menu_factory_find(factory, path);
 
559
    if (menu_path)
 
560
            gtk_widget_set_sensitive(menu_path->widget, sensitive);
 
561
    else
 
562
            g_warning("Impossibile assegnare sensibilit&agrave; a men&ugrave; inesistente: %s", path);
 
563
}
 
564
</PRE>
 
565
</CODE></BLOCKQUOTE>
 
566
<P>Ed ecco mfmain.h
 
567
<P>
 
568
<BLOCKQUOTE><CODE>
 
569
<PRE>
 
570
/* mfmain.h */
 
571
 
 
572
 
 
573
 
 
574
#ifndef __MFMAIN_H__
 
575
#define __MFMAIN_H__
 
576
 
 
577
#ifdef __cplusplus
 
578
extern "C" {
 
579
#endif /* __cplusplus */
 
580
 
 
581
void file_quit_cmd_callback(GtkWidget *widget, gpointer data);
 
582
 
 
583
#ifdef __cplusplus
 
584
}
 
585
#endif /* __cplusplus */
 
586
 
 
587
#endif /* __MFMAIN_H__ */
 
588
</PRE>
 
589
</CODE></BLOCKQUOTE>
 
590
<P>E mfmain.c
 
591
<P>
 
592
<BLOCKQUOTE><CODE>
 
593
<PRE>
 
594
/* mfmain.c */
 
595
 
 
596
 
 
597
 
 
598
#include &lt;gtk/gtk.h>
 
599
 
 
600
#include "mfmain.h"
 
601
#include "menufactory.h"
 
602
 
 
603
 
 
604
int main(int argc, char *argv[])
 
605
{
 
606
    GtkWidget *window;
 
607
    GtkWidget *main_vbox;
 
608
    GtkWidget *menubar;
 
609
    
 
610
    GtkAcceleratorTable *accel;
 
611
    
 
612
    gtk_init(&amp;argc, &amp;argv);
 
613
    
 
614
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
615
    gtk_signal_connect(GTK_OBJECT(window), "destroy", 
 
616
                       GTK_SIGNAL_FUNC(file_quit_cmd_callback), 
 
617
                       "WM destroy");
 
618
    gtk_window_set_title(GTK_WINDOW(window), "Menu Factory");
 
619
    gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
 
620
    
 
621
    main_vbox = gtk_vbox_new(FALSE, 1);
 
622
    gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
 
623
    gtk_container_add(GTK_CONTAINER(window), main_vbox);
 
624
    gtk_widget_show(main_vbox);
 
625
    
 
626
    get_main_menu(&amp;menubar, &amp;accel);
 
627
    gtk_window_add_accelerator_table(GTK_WINDOW(window), accel);
 
628
    gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
 
629
    gtk_widget_show(menubar);
 
630
    
 
631
    gtk_widget_show(window);
 
632
    gtk_main();
 
633
    
 
634
    return(0);
 
635
}
 
636
 
 
637
/* Questo &egrave; per mostrare come si usano le funzioni di ritorno quando 
 
638
 * si utilizza la MenuFactory. Spesso, si mettono tutte le funzioni di
 
639
 * callback in un file separato, e le si fanno chiamare le funzioni
 
640
 * appropriate da l&igrave;. Cos&igrave; le cose sono pi&ugrave; organizzate. */
 
641
void file_quit_cmd_callback (GtkWidget *widget, gpointer data)
 
642
{
 
643
    g_print ("%s\n", (char *) data);
 
644
    gtk_exit(0);
 
645
}
 
646
</PRE>
 
647
</CODE></BLOCKQUOTE>
 
648
<P>Ed infine un bel makefile per semplificare la compilazione.
 
649
<P>
 
650
<BLOCKQUOTE><CODE>
 
651
<PRE>
 
652
 
 
653
# Makefile.mf
 
654
 
 
655
 
 
656
CC      = gcc
 
657
PROF    = -g
 
658
C_FLAGS =  -Wall $(PROF) -L/usr/local/include -DDEBUG
 
659
L_FLAGS =  $(PROF) -L/usr/X11R6/lib -L/usr/local/lib 
 
660
L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lm
 
661
PROGNAME = menufactory
 
662
 
 
663
O_FILES = menufactory.o mfmain.o
 
664
 
 
665
$(PROGNAME): $(O_FILES)
 
666
        rm -f $(PROGNAME)
 
667
        $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS)
 
668
 
 
669
.c.o: 
 
670
        $(CC) -c $(C_FLAGS) $&lt;
 
671
 
 
672
clean: 
 
673
        rm -f core *.o $(PROGNAME) nohup.out
 
674
distclean: clean 
 
675
        rm -f *~
 
676
</PRE>
 
677
</CODE></BLOCKQUOTE>
 
678
<P>Per il momento, accontentatevi di questo esempio. Pi&ugrave; avanti aggiungeremo
 
679
una spiegazione ed un bel po' di commenti.
 
680
<P>
 
681
<P>
 
682
<HR NOSHADE>
 
683
<A HREF="gtk_tut_it-11.html">Avanti</A>
 
684
<A HREF="gtk_tut_it-9.html">Indietro</A>
 
685
<A HREF="gtk_tut_it.html#toc10">Indice</A>
 
686
</BODY>
 
687
</HTML>