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