]> Pileus Git - ~andy/gtk/blob - docs/gtk_tut_it.sgml
update of Italian tutorial translation from Daniele Canazza
[~andy/gtk] / docs / gtk_tut_it.sgml
1 <!doctype linuxdoc system>
2 <article>
3 <title>GTK Tutorial
4 <author>Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
5                               name="&lt;imain@gtk.org&gt;"></tt>,
6 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
7                               name="&lt;gale@gtk.org&gt;"></tt>
8 <date>April 6th, 1998  - Traduzione aggiornata al 1 Maggio 1998
9
10 <abstract>Tradotto da Michel Morelli, <tt><htmlurl url="mailto:ziobudda@chiara.dei.unipd.it" name="ziobudda@chiara.dei.unipd.it"></tt>, Daniele Canazza, <tt><htmlurl url="mailto:dcanazz@tin.it" name="dcanazz@tin.it"></tt> e Antonio Schifano, <tt><htmlurl url="mailto:schifano@cli.di.unipi.it" name="schifano@cli.di.unipi.it"></tt>
11 </abstract>
12 <!-- ***************************************************************** -->
13 <sect>Introduzione
14 <!-- ***************************************************************** -->
15 <p>
16 GTK (GIMP Toolkit) &egrave; stato orginariamente sviluppato come toolkit per
17 il programma GIMP (General Image Manipulation Program). GTK &egrave; costruito
18 sulla base del kit di disegno di GIMP, il GDK (GIMP Drawing Kit) il quale
19 &egrave; costruito a sua volta attorno alle funzioni della Xlib. E' chiamato
20 ``toolkit di GIMP'' perch&eacute; era inizialmente scritto per sviluppare GIMP,
21 ma ora viene utilizzato nello sviluppo di molti progetti software ``free''. 
22 Gli autori sono
23 <itemize>
24 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
25                            name="petm@xcf.berkeley.edu"></tt>     
26 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
27                            name="spencer@xcf.berkeley.edu"></tt>
28 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
29                            name="jmacd@xcf.berkeley.edu"></tt>
30 </itemize>
31
32 <p>
33 GTK &egrave; essenzialmente una API (application programmers interface)
34 orientata agli oggetti.
35 Anche se scritto completamente in C, &egrave; implementato usando l'idea delle
36 classi e delle funzioni di callback (puntatori a funzioni).
37
38 <p>
39 C'&egrave; anche una terza componente chiamata glib che contiene una serie di
40 implementazioni differenti di alcune chiamate di funzioni standard e anche
41 alcune funzioni aggiuntive, per esempio per la manipolazione delle liste 
42 collegate. Le funzioni sostitutive sono usate per migliorare la 
43 portabilit&agrave; di GTK. Alcune delle funzioni implementate qui non sono
44 disponibili o non sono standard,  altre sono uniche come g_strerror().
45 Altre contengono miglioramenti alle stesse della libc come g_malloc che ha 
46 delle utility di debugging migliorate.
47
48 <p>
49 Questo tutorial &egrave; un tentativo di documentare il meglio possibile la
50 libreria gtk e non pretende di essere completo. Questo tutorial suppone una
51 buona conoscenza del linugaggio C e di come creare programmi in C. Saranno
52 facilitati i lettori che hanno una precedente esperienza nella programmazione
53 in X. Se il GTK &egrave; il primo insieme di widget che studiate, vi prego di
54 dirmi come avete trovato questo tutorial e che tipo di problemi avete avuto.
55 Notate che c'&egrave; anche una versione per il C++ della libreria GTK (chiamata
56 GTK--), quindi se preferite utilizzare questo linguaggio al posto del C potreste
57 cercare questa versione al posto della GTK normale.
58 Ci sono poi un ``wrapper'' Objective C e un collegamento a Guile, ma non ne
59 seguo l'evoluzione.
60
61 <p>
62 Mi farebbe molto piacere conoscere qualsiasi problema che abbiate avuto
63 nell'imparare il GTK da questo documento e apprezzerei anche critiche sul come
64 migliorarlo.
65
66 <!-- ***************************************************************** -->
67 <sect>Iniziamo
68 <!-- ***************************************************************** -->
69 <p>
70 La prima cosa da fare &egrave; certamente quella di scaricare il GTK e installarlo.
71 Potete prendere l'ultima versione dal sito ftp.gtk.org in /pub/gtk. Un'altra
72 possibile sorgente di informazioni &egrave; il sito
73 <htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">. 
74
75 GTK usa il comando GNU autoconf per autoconfigurarsi. 
76 Una volta estratti i file dall'archivio tar, eseguite configure --help per
77 vedere una lista delle opzioni del comando configure.
78
79 <p>
80 Per iniziare la nostra introduzione a GTK, cominceremo con il pi&ugrave; semplice
81 programma possibile. Questo programma crea una finestra con dimensioni (in pixel)
82 di 200x200 e l'unica possibilit&agrave; di uscita &egrave; di ucciderlo usando la
83 shell o il Window Manager.
84
85 <tscreen><verb>
86 #include <gtk/gtk.h>
87
88 int main (int argc, char *argv[])
89 {
90     GtkWidget *window;
91     
92     gtk_init (&amp;argc, &amp;argv);
93     
94     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
95     gtk_widget_show (window);
96     
97     gtk_main ();
98     
99     return 0;
100 }
101 </verb></tscreen>
102
103 Tutti i programmi GTK includeranno sicuramente &lt;gtk/gtk.h&gt; in cui vengono
104 dichiarate le variabili, le funzioni, le strutture, etc. che saranno usate nella
105 tua applicazione GTK.
106
107 <p>
108 La linea seguente: 
109
110 <tscreen><verb>
111 gtk_init (&amp;argc, &amp;argv);
112 </verb></tscreen>
113
114 invoca la funzione gtk_init(gint *argc, gchar ***argv) che sar&agrave; usata in
115 tutte le applicazioni GTK. Questa funzione sistema alcune cose al posto nostro,
116 come la visuale predefinita e la mappa dei colori, e  procede poi chiamando
117 gdk_init(gint *argc, gchar ***argv).
118 Questa funzione inizializza la libreria per l'uso, setta il gestore predefinito
119 dei segnali e guarda negli argomenti, passati via linea di comando alla vostra
120 applicazione, alla ricerca di uno di questi argomenti:
121 <itemize>
122 <item> <tt/--display/
123 <item> <tt/--debug-level/
124 <item> <tt/--no-xshm/
125 <item> <tt/--sync/
126 <item> <tt/--show-events/
127 <item> <tt/--no-show-events/
128 </itemize>
129 <p>
130 Rimuove poi questi argomenti dalla lista degli argomenti passati, lasciando
131 quelli non riconosciuti a disposizione della vostra applicazione che potr&agrave;
132 tenerne conto o ignorarli.
133 In questo modo si crea un set di argomenti standard accettato da tutte le
134 applicazioni GTK.
135
136 <p>
137 Le seguenti 2 linee di codice creano e mostrano la finestra.
138
139 <tscreen><verb>
140   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
141   gtk_widget_show (window);
142 </verb></tscreen>
143
144 L'argomento GTK_WINDOW_TOPLEVEL specifica che noi vogliamo che la nostra finestra
145 si sottometta alle decorazioni del windows manager e alla posizione che quest'ultimo
146 indicher&agrave;. Invece di creare una finestra avente dimensioni 0x0, la dimensione
147 di una finestra senza figli (altri widget, come i bottoni, etc) &egrave; predefinita
148 a 200x200 cos&igrave; che si possa manipolarla.
149 La funzione gtk_widget_show()  fa s&igrave; che GTK sappia che abbiamo finito di
150 settare gli attributi di questo widget e che quindi quest'ultimo pu&ograve; essere
151 visualizzato.
152
153 <p>
154 L'ultima linea ci fa entrare nel ciclo principale del GTK.
155
156 <tscreen><verb>
157 gtk_main ();
158 </verb></tscreen>
159
160 gtk_main() &egrave; un'altra chiamata che vedrete in tutte le applicazioni GTK.
161 Quando il controllo raggiunge questo punto, l'applicazione si metter&agrave; a
162 dormire aspettando che si verifichino eventi di X (come la pressione di un bottone
163 o di un tasto), timeout o notifiche di Input/Output dai file
164 Nel nostro esempio, comunque, tutti gli eventi vengono ignorati.
165
166 <!-- ----------------------------------------------------------------- -->
167 <sect1>Hello World in GTK
168 <!-- ----------------------------------------------------------------- -->
169 <p>
170 Ok, ora un programma con un widget (un bottone). E' il classico ``Hello World''
171 alla GTK. 
172
173 <tscreen><verb>
174 /* helloworld.c */
175 #include <gtk/gtk.h>
176
177
178 /* E' una funzione di ritorno (callback). Gli argomenti passati sono ignorati in questo 
179 * esempio.
180 * Piu' informazioni sulle callback in seguito. */
181
182 void hello (GtkWidget *widget, gpointer data)
183 {
184     g_print ("Hello World\n");
185 }
186
187 gint delete_event(GtkWidget *widget, gpointer data)
188   {
189       g_print ("delete event occured\n");
190       /* Se si d&agrave; FALSE al gestore del segnale ``delete_event'', GTK emettera' il segnale
191        * ``destroy''. Fornire TRUE significa non volere che la finestra sia distrutta. 
192       * Questo e' utile per far uscire delle finestre di dialogo del tipo:
193       * 'sei sicuro di voler uscire ?'
194       * Cambia TRUE in FALSE e la finestra principale sara' distrutta con un "delete_event"
195       */
196     return (TRUE);
197
198 }
199
200
201 /* Un'altra callback */
202 void destroy (GtkWidget *widget, gpointer data)
203 {
204     gtk_main_quit ();
205 }
206
207 int main (int argc, char *argv[])
208 {
209     /* GtkWidget e' il tipo di dato per i Widget */
210     GtkWidget *window;
211     GtkWidget *button;
212     
213     /* Questa e' una chiamata presente in tutte le applicazioni GTK. Gli argomenti della
214         linea di comando vengono scorsi e restituiti alla applicazione  */
215     gtk_init (&amp;argc, &amp;argv);
216     
217     /* Crea una nuova finestra */
218     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
219     
220     /* Quando alla finestra viene passato il segnale ``delete_event'' (questo 
221      * segnale viene passato Windows Manager di solito con l'opzione 'close' 
222      * o con la barra del titolo (title bar)) noi chiediamo che la funzione 
223      * delete_event() (definita sopra) venga invocata.
224      * Il dato passato come argomento alla funzione di ritorno &eacute; NULL
225      * ed &eacute; ignorato dalla funzione stessa. */
226     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
227                         GTK_SIGNAL_FUNC (delete_event), NULL);
228     
229     /* Qui connettiamo l'evento ``destroy'' al gestore del segnale.
230      * Questo evento accade quando noi chiamimo la funzione gtk_widget_destroy() 
231      * sulla finestra o se ritorniamo FALSE dalla callback ``delete_event''. */
232     gtk_signal_connect (GTK_OBJECT (window), "destroy",
233                         GTK_SIGNAL_FUNC (destroy), NULL);
234
235     /* Setta il bordo interno della finestra */
236     gtk_container_border_width (GTK_CONTAINER (window), 10);
237     
238     /* Crea un nuovo bottone avente etichetta (label)  uguale a ``Hello World'' */
239     button = gtk_button_new_with_label ("Hello World");
240     
241     /* Quando il bottone riceve il segnale ``clicked'', invochera' la funzione 
242      * hello() passando NULL come argomento della funzione. La funzione
243      * hello() &eacute; definita sopra. */
244     gtk_signal_connect (GTK_OBJECT (button), "clicked",
245                         GTK_SIGNAL_FUNC (hello), NULL);
246     
247     /* Questo far&agrave; s&igrave; che la finestra venga distrutta dalla chiamata
248      * gtk_widget_destroy(window) quando il bottone verr&agrave; premuto. Ancora,
249      * questo segnale (``destroy'') puo' arrivare da qui o dal windows 
250      * manager */
251     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
252                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
253                                GTK_OBJECT (window));
254     
255     /* Questo inserisce il bottone nella finestra 
256      * (un contenitore GTK) */
257     gtk_container_add (GTK_CONTAINER (window), button);
258     
259     /* Il passo finale &eacute; il mostrare questo nuovo widget appena creato */
260     gtk_widget_show (button);
261     
262     /* e la finestra */
263     gtk_widget_show (window);
264     
265     /* Tutte le applicazioni GTK devono avere la funzione gtk_main(). 
266      * Il controllo finisce qui e attende un evento (come la pressione
267      * di un tasto o l'evento di un mouse). */
268     gtk_main ();
269     
270     return 0;
271 }
272 </verb></tscreen>
273
274 <!-- ----------------------------------------------------------------- -->
275 <sect1>Compilare hello World
276 <!-- ----------------------------------------------------------------- -->
277 <p>
278 Per compilare si utilizza :
279
280 <tscreen><verb>
281
282 gcc -Wall -g helloworld.c -o hello_world `gtk-config --cflags` \
283     `gtk-config --libs`
284 </verb></tscreen>
285 (N.d.T.: se lanciato da linea di comando, il precedente comando di
286 compilazione va messo su di una unica linea eliminando il backslash) 
287 <p>
288 In questo modo, si usa il progamma <tt>gtk-config</>, che viene
289 distribuito con gtk. Questo programma 'sa' che opzioni di compilatore
290 sono necessarie per compilare i programmi che usano gtk.
291 <tt>gtk-config --cflags</> d&agrave; come risultato una lista di directory
292 in cui i file di include devono essere cercati, e <tt>gtk-config --libs</>
293 fornisce invece la lista delle librerie che devono essere linkate con le
294 directory in cui devono essere cercate.
295
296 <p>
297 Le librerie che normalmente vengono linkate sono:
298 <itemize>
299 <item> la libreria glib (-lglib), contiene varie funzioni, ma solo 
300 g_print() &eacute; usato in questo esempio. GTK si appoggia a questa
301 libreria, quindi essa viene sempre, comunque, linkata. Vedi comunque
302 la  sezione sulla <ref id="sec_glib" name="glib"> per altri dettagli.
303 <item>La libreria GDK (-lgdk), la copertura della X11.
304 <item>La libreria GTK (-lgtk), la libreria dei widget, basata sulla GDK.
305 <item>La libreria Xlib(-lX11) la quale &egrave; usata dalla GDK.
306 <item>La libreria Xext(-lXext). Questa contiene il codice per le pixmap a
307 memoria condivisa e altre estensioni di X.
308 <item>La libreria matematica (-lm). Questa &eacute; usata dalla GTK per
309 vari scopi.
310 </itemize>
311
312 <!-- ----------------------------------------------------------------- -->
313 <sect1>Teoria dei segnali e delle funzioni di ritorno (callback)
314 <p>
315 Prima di guardare in dettaglio ``Hello World'', parleremo un po' degli eventi
316 e delle funzioni di ritorno. GTK  &egrave; un toolkit guidato dagli eventi,
317 il che significa che se ne star&agrave; a dorimire in gtk_main finch&eacute;
318 non succede un evento ed il controllo viene passato alla funzione appropriata.
319
320 <p>
321 Questo passaggio di controllo &egrave; basato sull'idea dei segnali.
322 Quando si ha un evento, come la pressione di un bottone del mouse, verr&agrave;
323 emesso il segnale appropriato, per esempio dal widget che &eacute; stato premuto.
324 Questo &egrave; il modo in cui GTK fa molto del suo utile lavoro. Per far
325 s&igrave; che un bottone esegua una azione, prepareremo un gestore del segnale
326 che catturi questi segnali e chiami la funzione corretta. Questo viene fatto
327 usando una funzione del tipo:
328
329 <tscreen><verb>
330 gint gtk_signal_connect (GtkObject *object,
331                          gchar *name,
332                          GtkSignalFunc func,
333                          gpointer func_data);
334 </verb></tscreen>
335 <p>
336 in cui il primo argomento &egrave; il widget che emetter&agrave; il segnale,
337 il secondo &egrave; il nome del segnale che si vuole catturare, il terzo &egrave;
338 la funzione che verr&agrave; invocata quando il segnale sar&agrave; catturato e
339 il quarto &egrave; il dato che potr&agrave; essere passato a questa funzione.
340 <p>
341 La funzione specificata come terzo argomento &egrave; chiamata ``funzione di
342 ritorno (callback)'', e dovrebbe essere della forma:
343
344 <tscreen><verb>
345 void callback_func(GtkWidget *widget, gpointer *callback_data);
346 </verb></tscreen>
347 <p>
348 Dove il primo argomento sar&agrave; un puntatore al widget che emette il segnale
349 e il secondo un puntatore al dato passato come ultimo argomento della funzione 
350 gtk_signal_connect() come descritto sopra.
351 <p>
352 Un'altra chiamata usata nell'esempio Hello World &egrave;:
353
354 <tscreen><verb>
355 gint gtk_signal_connect_object (GtkObject *object,
356                                 gchar  *name,
357                                 GtkSignalFunc func,
358                                 GtkObject *slot_object);
359 </verb></tscreen>
360 <p>
361 gtk_signal_connect_object() &egrave; uguale a gtk_signal_connect() eccetto che
362 la funzione di callback usa solo un argomento, un puntatore ad un'oggetto GTK.
363 Cos&igrave; quando si usa questa funzione per connettere i segnali, la callback 
364 dovrebbe essere della forma :
365
366 <tscreen><verb>
367 void callback_func (GtkObject *object);
368 </verb></tscreen>
369 <p>
370 dove object &egrave; normalmente un widget. Generalmente, non si assegna
371 una callback per gtk_signal_connect_object.  Queste sono invocate, usualmente,
372 per chiamare una funzione GTK che accetta un widget singolo o un oggetto come
373 argomento, come nel caso dell'esempio Hello World.
374
375 Lo scopo di avere due funzioni per connettere i segnali &egrave; semplicemente
376 quello di permettere alla funzione di callback di avere un numero di argomenti
377 diverso. Molte funzioni della libreria GTK accettano solo un singolo puntatore
378 ad un widget GTK come argomento, cos&igrave; per queste si pu&ograve; usare la
379 funzione gtk_signal_connect_object(), mentre per le vostre funzioni potreste
380 aver bisogno di passare dati supplementari alle funzioni di ritorno.
381
382 <sect1>Attraverso Hello World passo per passo
383 <p>
384 Ora che conosciamo la teoria che vi &egrave; dietro, iniziamo ad essere pi&ugrave;
385 chiari camminando attraverso il programma di Hello World.
386 <p>
387 Questa &egrave; la funzione di callback che sar&agrave; invocata quando il bottone
388 viene cliccato.
389 Noi, in questo esempio, ignoriamo sia il widget che i dati passati, ma non &egrave; 
390 difficile farci invece qualcosa. Il prossimo esempio user&agrave; l'argomento passato
391 per dire quale bottone &egrave; stato premuto.
392
393 <tscreen><verb>
394 void hello (GtkWidget *widget, gpointer *data)
395 {
396     g_print ("Hello World\n");
397 }
398 </verb></tscreen>
399
400 <p>
401 Questa callback &egrave; un po' speciale. L'evento ``delete'' avviene quanto
402 il Window Manager manda questo evento all'applicazione. Qui abbiamo una scelta
403 da fare: cosa fare di questo evento. Possiamo ignorarlo, creare qualche tipo di
404 risposta, o semplicemente terminare l'applicazione.
405
406 Il valore che si restituisce in questa callback fa s&igrave; che la GTK sappia
407 cosa fare. Restituire TRUE significa che non vogliamo che il segnale ``destroy''
408 sia emesso, quindi far s&igrave; che la nostra applicazione proceda normalmente.
409 Ritornare FALSE vuole dire far emettere il segnale ``destroy'' il quale
410 chiamer&agrave; la nostra funzione di callback che gestisce il segnale ``destroy''.
411
412 <tscreen><verb>
413 gint delete_event(GtkWidget *widget, gpointer data)
414 {
415    g_print ("delete event occured\n");
416
417    return (TRUE);
418 }
419 </verb></tscreen>
420 <p>
421 Questa &egrave; un'altra funzione di callback la quale fa uscire dal programma
422 chiamando gtk_main_quit(). Questa funzione dice a GTK che deve uscire da gtk_main
423 quando gli viene restituito il controllo.
424
425 <tscreen><verb>
426 void destroy (GtkWidget *widget, gpointer *data)
427 {
428     gtk_main_quit ();
429 }
430 </verb></tscreen>
431 <p>
432 Ritengo che conosciate la funzione main()... si, come tutte le altre applicazioni
433 anche le applicazioni GTK hanno questa funzione.
434
435 <tscreen><verb>
436 int main (int argc, char *argv[])
437 {
438 </verb></tscreen>
439 <p>
440 Questa parte dichiara un puntatore ad una struttura di tipo GtkWidget. Queste sono
441 usate pi&ugrave; sotto per creare una finestra ed un bottone.
442
443 <tscreen><verb>
444     GtkWidget *window;
445     GtkWidget *button;
446 </verb></tscreen>
447 <p>
448 Qui vi &egrave; ancora la nostra gtk_init. Come prima questa inizializza il toolkit
449 e analizza gli argomenti trovati nella linea di comando. Tutti gli argomenti
450 riconosciuti nella linea di comando sono rimossi dalla lista degli argomenti e
451 vengono cos&igrave; modificati argc e argv per far s&igrave; che sembri che questi
452 non siano mai esisiti e permettere alla vostra applicazione di analizzare gli
453 argomenti rimasti.
454
455 <tscreen><verb>
456     gtk_init (&amp;argc, &amp;argv);
457 </verb></tscreen>
458 <p>
459 Crea una nuova finestra. Questo viene spiegato abbastanza approfonditamente
460 pi&ugrave; avanti. Viene allocata la memoria per la struttura GtkWidget *window
461 cos&igrave; che si punti ad una struttura valida. In questo modo si predispone
462 la nuova finestra, ma non la si visualizza fino a sotto dove, quasi alla fine
463 del nostro programma, invochiamo gtk_widget_show(window).
464 <tscreen><verb>
465     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
466 </verb></tscreen>
467 <p>
468 Questo &egrave; un esempio di come connettere un gestore dei segnali con un oggetto,
469 in questo caso la finestra. Qui viene catturato il segnale ``destroy''. Questo
470 viene emesso quando usiamo il Window Manager per uccidere la finestra (e noi
471 restituiamo TRUE dal gestore di ``delete_event'') o quando emettiamo la chiamata
472 gtk_widget_destroy() passando l'oggetto finestra come oggetto da distruggere.
473 Sistemando le cose cos&igrave;, trattiamo entrambi i casi con una singola 
474 chiamata. Qui &egrave; giusto invocare la funzione destroy() definita sopra con
475 NULL come argomento, la quale termina l'applicazione GTK per noi.
476 Questo ci permetter&agrave; di utilizzare il Window Manager per uccidere il programma.
477 <p>
478 GTK_OBJECT e GTK_SIGNAL_FUNC sono macro che interpretano il casting e il controllo
479 di tipo per noi, cos&igrave; da rendere piu' leggibile il codice.
480
481 <tscreen><verb>
482     gtk_signal_connect (GTK_OBJECT (window), "destroy",
483                         GTK_SIGNAL_FUNC (destroy), NULL);
484 </verb></tscreen>
485 <p>
486 La prossima funzione &egrave; usata per settare un attributo di un oggetto
487 contenitore. Questo sistema la finestra cos&igrave; da avere un'area vuota
488 all'interno della finestrra larga 10 pixel dove non potr&agrave; andare nessun
489 widget. Ci sono altre funzioni simili che vedremo nella
490 sezione <ref id="sec_setting_widget_attributes" name="Settare gli attributi del Widget.">
491 <p>
492 E ancora, GTK_CONTAINER &egrave; una macro per interpretare il casting di tipo.
493
494 <tscreen><verb>
495     gtk_container_border_width (GTK_CONTAINER (window), 10);
496 </verb></tscreen>
497 <p>
498 Questa chiamata crea un nuovo bottone. Alloca spazio in memoria per un nuovo
499 GtkWidget, inizializzandolo e facendo s&igrave; che il puntatore a bottone punti
500 ad esso.
501 Quando sar&agrave; visualizzato, avr&agrave; etichetta  ``Hello World''.
502
503 <tscreen><verb>
504     button = gtk_button_new_with_label ("Hello World");
505 </verb></tscreen>
506 <p>
507 Qui prendiamo il bottone e gli facciamo fare qualcosa di utile.
508 Gli colleghiamo un gestore di segnale  in modo che quando emetter&agrave; il 
509 segnale ``clicked'', verr&agrave; invocata la nostra funzione hello(). Il
510 dato passato alla funzione &egrave; ignorato, cosicch&eacute; alla funzione
511 di callback hello() passiamo semplicemente NULL. Evidentemente il segnale
512 ``clicked'' viene emesso quando premiamo il bottone con il mouse.
513
514 <tscreen><verb>
515     gtk_signal_connect (GTK_OBJECT (button), "clicked",
516                         GTK_SIGNAL_FUNC (hello), NULL);
517 </verb></tscreen>
518 <p>
519 Usiamo questo bottone anche per uscire dal programma. Questo illustrer&agrave; 
520 come il segnale ``destroy'' pu&ograve; arrivare sia dal Window Manager che dal
521 nostro programma. Quando il bottone viene cliccato come descritto sopra,
522 chiamer&agrave; la funzione di callback hello() e poi quest'ultima nell'ordine
523 in cui sono definite. Si possono cio&eacute; avere tante funzioni di callback
524 quante sono necessarie, e saranno eseguite nell'ordine in cui sono connesse.
525 Visto che la funzione gtk_widget_destroy() accetta come argomento solo un GtkWidget *widget, usiamo la funzione
526 gtk_signal_connect_object() al posto della normale gtk_signal_connect().
527
528 <tscreen><verb>
529     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
530                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
531                                GTK_OBJECT (window));
532 </verb></tscreen>
533 <p>
534 Questa &eacute; una chiamata di ``impacchettamento'' che sar&agrave; spiegata
535 pi&ugrave; avanti. Ma &egrave; molto facile da capire. Semplicemente dice alla
536 libreria GTK che il bottone &egrave; da mettere nella finestra dove sar&agrave;
537 visualizzato.
538
539 <tscreen><verb>
540     gtk_container_add (GTK_CONTAINER (window), button);
541 </verb></tscreen>
542 <p>
543 A questo punto abbiamo predisposto tutto quello che ci eravamo prefissati.
544 Con tutti i gestori di segnale a posto e il bottone messo nella finestra in cui
545 dovrebbe essere, possiamo dire a GTK di mostrare gli oggetti sullo schermo. 
546 L'oggetto finestra viene mostrato per ultimo cos&igrave; che la finestra
547 completa di tutti i suoi oggetti verr&agrave; mostrata tutta in una volta,
548 invece di vedere prima la finestra spoglia e poi la comparsa del bottone
549 all'interno di essa. Per quanto, con questi semplici esempi, questo l'avrete
550 gi&agrave; notato.
551 <tscreen><verb>
552     gtk_widget_show (button);
553
554     gtk_widget_show (window);
555 </verb></tscreen>
556 <p>
557 E naturalmente chiamiamo gtk_main(), la quale aspetta l'arrivo degli eventi 
558 dal server X e chiama l'oggetto interessato per fargli emettere il segnale
559 corrispondente.
560 <tscreen><verb>
561     gtk_main ();
562 </verb></tscreen>
563 E il return finale. Il controllo ritorna qui dopo che viene invocata gtk_quit().
564
565 <tscreen><verb>
566     return 0;
567 </verb></tscreen>
568 <p>
569 Ora, quando premiamo il bottone del mouse su un bottone GTK, questo oggetto
570 emette il segnale ``clicked''. Per poter utilizzare queste informazioni, il
571 nostro programma predispone un gestore di segnale per catturare quel segnale,
572 il quale avvia la funzione da noi scelta. Nel nostro esempio, quando il
573 bottone creato viene cliccato, la funzione hello() viene invocata con argomento
574 NULL, dopoodich&eacute; viene invocato il successivo gestore di questo segnale.
575 Questo chiama la funziona gtk_widget_destroy(), passandole l'oggetto-finestra
576 (window) come argomento, che distrugger&agrave; la finestra. Questo fa s&igrave;
577 che la finestra emetta il segnale ``destroy'' che viene catturato e che fa
578 invocare la funzione di ritorno destroy(), che semplicemente esce dal programma GTK.
579 <p>
580 Un'altro modo in cui possono andare le cose &egrave; l'uso del window manager per
581 uccidere la finestra. Questo causera' l'emissione del segnale ``delete_event'' che
582 automaticamente chiamer&agrave; il gestore del segnale ``delete_event''. Se qui noi
583 restituiamo il valore TRUE, la finestra non verr&agrave; toccata e tutto
584 proceder&agrave; come se nulla fosse successo. Dare invece il valore FALSE
585 causer&agrave; l'emissione da parte di GTK del segnale ``destroy'' il quale, a sua
586 volta, invocher&agrave; la callback ``destroy'', uscendo dall'applicazione.
587 <p>
588 Nota che questi segnali non sono gli stessi del sistema Unix e che non sono
589 implementati usando quei segnali, anche se la terminologia &egrave; praticamente
590 identica.
591
592 <!-- ***************************************************************** -->
593 <sect>Proseguiamo
594 <!-- ***************************************************************** -->
595 <p>
596
597 <!-- ----------------------------------------------------------------- -->
598 <sect1>Tipi di Dato
599 <p>
600 Ci sono alcune cose che avrete probabilmente notato nei precedenti esempi che
601 hanno bisogno di una spiegazione. I gint, gchar ecc. che vedete sono tipi di dato
602 (typedef) riferiti rispettivamente a int e char. Questo viene fatto per rimediare
603 alle scomode dipendenze dalle dimensioni di semplici tipi di dato quando si fanno
604 dei calcoli. Un buon esempio &egrave; ``gint32'' il quale sar&agrave; un tipo di
605 dato riferito ad un intero a 32 bit per tutte le piattaforme, sia per gli x86 che
606 per gli per gli alpha a 64 bit.
607 I tipi di dato sono ben spiegati pi&ugrave; avanti e molto intuitivi. Sono definiti
608 in glib/glib.h (il quale viene incluso da gtk.h).
609 <p>
610 Noterete anche la possibilit&agrave; di utilizzare un GtkWidget quando la funzione
611 richiede un GtkObject. GTK &egrave; una libreria orienta agli oggetti ed un widget
612 &egrave; un oggetto.
613
614 <!-- ----------------------------------------------------------------- -->
615 <sect1>Altri Dettagli sui Segnali
616 <p>
617 Diamo un'altra occhiata alla dichiarazione della funzione gtk_signal_connect.
618
619 <tscreen><verb>
620 gint gtk_signal_connect (GtkObject *object, gchar *name,
621                          GtkSignalFunc func, gpointer func_data);
622 </verb></tscreen>
623 Notate il valore di ritorno definito come gint? Questo &egrave; un identificatore
624 per la vostra funzione di callback. Come detto sopra, si possono avere pi&ugrave;
625 funzioni di ritorno per ogni segnale e per ogni ogetto a seconda delle
626 necessit&agrave;, ed ognuna sar&agrave; eseguita in sequenza, nell'ordine in cui
627 &egrave; stata collegata. 
628
629 Questo identificatore vi permette di rimuovere una funzione dalla lista delle 
630 funzioni di ritorno tramite la seguente chiamata
631
632 <tscreen><verb>
633 void gtk_signal_disconnect (GtkObject *object,
634                             gint id);
635 </verb></tscreen>
636 Cos&igrave;, passando il widget da cui si vuole rimuovere il gestore di segnale e
637 l'identificativo restituito da una delle funzioni signal_connect, si pu&ograve;
638 rimuovere il gestore di segnale che si desidera dal widget.
639
640 Un'altra funzione, usata per rimuovere tutti i segnali di un widget in una volta
641 sola &egrave;:
642
643 <tscreen><verb>
644 gtk_signal_handlers_destroy (GtkObject *object);
645 </verb></tscreen>
646 <p>
647 Questa chiamata &egrave; abbastanza auto esplicativa. Semplicemente rimuove tutti
648 i segnali collegati al widget che si passa alla funzione come argomento.
649
650 <!-- ----------------------------------------------------------------- -->
651 <sect1>Miglioriamo Hello World
652
653 <p>
654 Diamo un'occhiata ad una versione migliorata di Hello World con altri esempi
655 sulle callback. Questo ci introdurr&agrave; anche al nostro prossimo argomento,
656 l'impacchettamento dei widget.
657
658 <tscreen><verb>
659 /* helloworld2.c */
660 #include <gtk/gtk.h>
661
662 /* La nostra funzione di callback migliorata. I dati passati a questa
663  * vengono stampati su stdout. */
664 void callback (GtkWidget *widget, gpointer *data)
665 {
666     g_print ("Hello again - %s was pressed\n", (char *) data);
667 }
668
669 /* Un'altra callback */
670 void delete_event (GtkWidget *widget, gpointer *data)
671 {
672     gtk_main_quit ();
673 }
674
675 int main (int argc, char *argv[])
676 {
677     /* GtkWidget e' il tipo di dato per i widget */
678     GtkWidget *window;
679     GtkWidget *button;
680     GtkWidget *box1;
681
682     /* Questa funzione e' invocata in tutte le applicazioni GTK, gli 
683        argomenti sono analizzati e restituiti all'applicazione. */
684     gtk_init (&amp;argc, &amp;argv);
685
686     /* Crea una nuova finestra */
687     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
688
689     /* Questa e' una nuova chiamata. Assegna "Hello Buttons" come titolo 
690        della nostra finestra */
691     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
692
693     /* Qui settiamo il gestore per il segnale "delete_event" che
694        immediatamente esce dalla applicazione.
695     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
696                         GTK_SIGNAL_FUNC (delete_event), NULL);
697
698
699     /* predispone il bordo della finestra */
700     gtk_container_border_width (GTK_CONTAINER (window), 10);
701
702     /* creiamo una scatola dove mettere tutti i widget. Questa &egrave; descritta
703        dettagliatamente nella sezione "packing". La scatola non &egrave; realmente
704        visibile, &egrave; solamente usata per sistemare i widget. */
705     box1 = gtk_hbox_new(FALSE, 0);
706
707     /* Inseriamo la scatola nella finestra */
708     gtk_container_add (GTK_CONTAINER (window), box1);
709
710     /* Creiamo un nuovo bottone con etichetta "Button 1" */
711     button = gtk_button_new_with_label ("Button 1");
712
713     /* Quando il bottone e' premuto, noi invocheremo la funzione di callback,
714        con un puntatore alla stringa "button 1" come proprio argomento) */
715     gtk_signal_connect (GTK_OBJECT (button), "clicked",
716                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
717
718     /* invece di aggiungerlo alla finestra, lo inseriamo nella scatola invisibile,
719        la quale e' stata inserita nella finstra. */
720     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
721
722     /* Ricordati sempre questo passo. Dice a GTK che la preparazione di questo 
723        bottone e' finita e che quindi puo' essere mostrato. */
724     gtk_widget_show(button);
725
726     /* Facciamo la stessa cosa per il secondo bottone. */
727     button = gtk_button_new_with_label ("Button 2");
728
729     /* Chiamiamo la stessa funzione ma passandogli un argomento differente,
730        gli passiamo un puntatore alla stringa "button 2" */
731     gtk_signal_connect (GTK_OBJECT (button), "clicked",
732                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
733
734     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
735
736     /* L'ordine nel quale i bottoni sono visualizzati non e' realmente importante,
737        ma io ti raccomando di mostrare per ultima la finestra cosi' che tutto 
738        sia visualizzato in una volta sola */
739     gtk_widget_show(button);
740
741     gtk_widget_show(box1);
742
743     gtk_widget_show (window);
744
745     /* e ora ci mettiamo in gtk_main e aspettiamo che il diverimento inizi.
746     gtk_main ();
747
748     return 0;
749 }
750 </verb></tscreen>
751
752 Compilate questo programma usando gli stessi argomenti di link del nostro primo
753 esempio. Noterete che questa volta non c'&egrave; un modo semplice per uscire
754 dal programma, si deve usare il nostro window manager o la linea di comando per
755 uccidere l'applicazione.
756 Un buon esercizio per il lettore &egrave; quello di inserire un tezo bottone
757 ``quit'' che faccia uscire dal programma. Potete anche divertirvi  con le opzioni
758 di gtk_box_pack_start() mentre leggete il prossimo capitolo. Provate a
759 ridimensionare la finestra ed a osservare cosa succede.
760
761 Solo una piccola nota: c'&egrave; un'altra definizione di gtk_window_new() - 
762 GTK_WINDOW_DIALOG. Questa interagisce con il window manager in un modo un po' 
763 diverso, e dovrebbe essere usata per finestre temporanee.
764
765 <!-- ***************************************************************** -->
766 <sect>Come ``Impacchettare'' i Widget 
767 <!-- ***************************************************************** -->
768 <p>
769 Nel momento in cui si crea un'applicazione, normalmente si avr&agrave; la
770 necessit&agrave; di mettere pi&ugrave; di un unico bottone all'interno di
771 una finestra. Il nostro primo esempio ``Hello World'' usava un solo oggetto,
772 cosicch&eacute; abbiamo potuto usare semplicemente una chiamata a
773 gtk_container_add per impacchettare il widget nella finestra. Quando invece
774 si vuole inserire pi&ugrave; di un unico widget in una finestra, come si fa
775 a controllare dove vengono posizionati i propri oggetti? E' qui che entra in
776 gioco il meccanismo dell'``impacchettamento''.
777 <!-- ----------------------------------------------------------------- -->
778 <sect1>Teoria delle Scatole per Impacchettamento
779 <p>
780 La maggior parte dell'impacchettamento viene effettuata creando delle scatole
781 come nell'esempio pi&ugrave; sopra. Le scatole sono dei contenitori invisibili
782 di widget che possiamo usare per imballarci i nostri oggetti e che esistono in
783 due variet&agrave;: in particolare si possono avere scatole orizzontali (hbox)
784 e verticali (vbox).
785 Quando si impacchentano degli oggetti in una scatola orizzontale, gli oggetti
786 vengono inseriti orizzontalmente da sinistra a destra oppure da destra a sinistra
787 a seconda della chiamata di funzione che si usa. In una scatola verticale, gli
788 oggetti vengono inseriti dall'alto in basso o viceversa. Si pu&ograve; usare
789 qualsiasi combinazione di scatole all'interno o a fianco di altre scatole, fino
790 ad ottenere l'effetto desiderato.
791 <p>
792 Per creare una nuova scatola orizzontale, si usa una chiamata a gtk_hbox_new(),
793 mentre per le scatole verticali si usa gtk_vbox_new(). Per inserire i widget
794 all'interno di questi contenitori si usano le funzioni gtk_box_pack_start() e
795 gtk_box_pack_end(). La funzione gtk_box_pack_start() comincer&agrave; dall'alto
796 verso il basso in una vbox e da sinistra a destra in una hbox. gtk_box_pack_end()
797 fa l'opposto, impacchettando dal basso verso l'alto in una vbox e da destra a
798 sinistra in una hbox. Queste funzioni ci permettono di giustificare a destra o
799 a sinistra i nostri widget, e possono essere mescolate in qualsiasi modo per
800 ottenere l'effetto desiderato. Useremo gtk_box_pack_start() nella maggior parte
801 dei nostri esempi. Un oggetto pu&ograve; essere costituito da un altro contenitore
802 o da un oggetto grafico. Infatti, molti oggetti grafici sono a loro volta dei
803 contenitori, compreso il bottone, anche se tipicamente all'interno del bottone
804 mettiamo solo una etichetta.
805 <p>
806
807 Usando queste chiamate, GTK riesce a capire dove si vogliono piazzare i propri
808 widget, in modo di essere poi in grado di effettuare il ridimensionamento
809 automatico e altre cose interessanti. Esiste poi un insieme di opzioni che riguardano
810 il modo in cui i propri oggetti grafici dovrebbero essere impacchettati. Come
811 si pu&ograve; immaginare, questo metodo d&agrave; una buona flessibilit&agrave; nella creazione e
812 nella disposizione dei propri widget.
813
814 <!-- ----------------------------------------------------------------- -->
815 <sect1>Dettagli sulle Scatole
816 <p>
817 A causa di questa flessibilit&agrave;, le scatole per impacchettamento del GTK
818 possono, di primo acchito, creare un po' di disorientamento. Sono infatti disponibili
819 molte opzioni, e non &egrave; immediato il modo in cui si combinano l'una con l'altra.
820 Alla fine per&ograve;, si possono ottenere essenzialmente cinque diversi stili.
821
822 <p>
823 <? <CENTER> >
824 <?
825 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" HEIGHT="235"
826 ALT="Box Packing Example Image">
827 >
828 <? </CENTER> >
829  
830 Ogni linea contiene una scatola orizzontale (hbox) con diversi bottoni. 
831 La chiamata a  gtk_box_pack &egrave; una scorciatoia per la chiamata di
832 impacchettamento di ognuno dei bottoni nella hbox. Ognuno dei bottoni viene
833 impacchettato nella hbox nello stesso modo (cio&egrave;, con gli stessi
834 argomenti per la funzione gtk_box_pack_start ()).
835 <p>
836 Questa &egrave; la dichiarazione della funzione gtk_box_pack_start.
837
838 <tscreen><verb>
839 void gtk_box_pack_start (GtkBox    *box,
840                          GtkWidget *child,
841                          gint       expand,
842                          gint       fill,
843                          gint       padding);
844 </verb></tscreen>
845 Il primo argomento &egrave; la scatola nella quale si stanno inscatolando i
846 widget, il secondo &egrave; il widget stesso. Gli oggetti per ora saranno 
847 bottoni, quindi quello che faremo sar&agrave; impacchettare bottoni in scatole.
848 <p>
849 L'argomento ``expand'' in  gtk_box_pack_start() o  gtk_box_pack_end() controlla
850 se gli oggetti devono essere sistemati nella scatola in modo da riempire tutto
851 lo spazio in diponibile presente nella scatola, in modo che la scatola si espanda
852 fino ad occupare tutta l'area assegnatale (valore TRUE).
853 La scatola pu&ograve; anche essere rimpiciolita in modo da contenere esattamente i
854 widget (valore FALSE). Assegnare a expand il valore FALSE permette di giustificare
855 a destra o sinistra i propri oggetti. In caso contrario, tutti gli ogetti si
856 espandono fino ad adattarsi alla scatola, e il medesimo effetto si pu&ograve;
857 ottenere usando solo una delle funzioni gtk_box_pack_start o pack_end.
858 <p>
859 L'argomento ``fill'' delle funzioni gtk_box_pack stabilisce se lo spazio disponibile
860 nella scatola deve essere allocato agli oggetti (TRUE) o se deve essere mantenuto
861 come riempimento attorno a questi oggetti (FALSE). Questo argomento ha effetto
862 solo se a expand &egrave; assegnato il valore TRUE.
863 <p>
864 Quando si crea una nuova scatola, la funzione ha questo aspetto:
865
866 <tscreen><verb>
867 GtkWidget * gtk_hbox_new (gint homogeneous,
868                           gint spacing);
869 </verb></tscreen>
870
871 L'argomento homogeneous di gtk_hbox_new (la stesso per gtk_vbox_new)
872 determina se ogni oggetto nella scatola deve avere la stessa dimensione
873 (cio&egrave; la stessa ampiezza in una hbox o la stessa altezza in una vbox).
874 Se &egrave; settato, l'argomento expand delle routine gtk_box_pack &egrave;
875 sempre attivato.
876 <p>
877 Qual &egrave; la differenza fra la spaziatura (che &egrave; stabilita quando
878 la scatola viene creata) e il riempimento (che viene stabilito quando gli
879 elementi vengono impacchettati)? La spaziatura viene inserita fra gli oggetti,
880 mentre il riempimento viene aggiuno a ciascuno dei lati dell'oggetti. La seguente
881 figura dovrebbe chiarire meglio questo punto:
882  
883 <? <CENTER> >
884  <?
885 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" HEIGHT="213"
886 VSPACE="15" HSPACE="10" ALT="Box Packing Example Image">
887 >
888 <? </CENTER> >
889
890
891 Di seguito &egrave; riportato il codice usato per creare le immagini precedenti.
892 L'ho commentato in modo piuttosto pesante, in modo che non dovreste avere
893 problemi nel seguirlo. Compilatelo voi stessi e provate a giocarci un po'.
894
895 <!-- ----------------------------------------------------------------- -->
896 <sect1>Programma Dimostrativo di Impacchettamento
897 <p>
898
899 <tscreen><verb>
900 /* packbox.c */
901 #include "gtk/gtk.h"
902
903 void
904 delete_event (GtkWidget *widget, gpointer *data)
905 {
906     gtk_main_quit ();
907 }
908
909 /* Costruisco una nuova hbox riempita con bottoni-etichette. Gli
910  * argomenti per le varabili che ci interessano sono passati
911  * in questa funzione. Non mostriamo la scatola, ma mostriamo
912  * tutto quello che c'e' dentro. */
913 GtkWidget *make_box (gint homogeneous, gint spacing,
914                      gint expand, gint fill, gint padding) 
915 {
916     GtkWidget *box;
917     GtkWidget *button;
918     char padstr[80];
919     
920     /* costruisco una nuova hbox con i valori appropriati di
921      * homogeneous e spacing */
922     box = gtk_hbox_new (homogeneous, spacing);
923     
924     /* costruisco una serie di bottoni con i valori appropriati */
925     button = gtk_button_new_with_label ("gtk_box_pack");
926     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
927     gtk_widget_show (button);
928     
929     button = gtk_button_new_with_label ("(box,");
930     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
931     gtk_widget_show (button);
932     
933     button = gtk_button_new_with_label ("button,");
934     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
935     gtk_widget_show (button);
936     
937     /* costruisco un bottone con l'etichetta che dipende dal valore di 
938      * expand. */
939     if (expand == TRUE)
940             button = gtk_button_new_with_label ("TRUE,");
941     else
942             button = gtk_button_new_with_label ("FALSE,");
943     
944     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
945     gtk_widget_show (button);
946     
947     /* Questo e' la stessa cosa della creazione del bottone per "expand"
948      * piu' sopra, ma usa la forma breve. */
949     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
950     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
951     gtk_widget_show (button);
952     
953     sprintf (padstr, "%d);", padding);
954     
955     button = gtk_button_new_with_label (padstr);
956     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
957     gtk_widget_show (button);
958     
959     return box;
960 }
961
962 int
963 main (int argc, char *argv[])
964 {
965     GtkWidget *window;
966     GtkWidget *button;
967     GtkWidget *box1;
968     GtkWidget *box2;
969     GtkWidget *separator;
970     GtkWidget *label;
971     GtkWidget *quitbox;
972     int which;
973     
974     /* La nostra inizializzazione, non dimenticatela! :) */
975     gtk_init (&amp;argc, &amp;argv);
976     
977     if (argc != 2) {
978         fprintf (stderr, "uso: packbox num, dove num &egrave; 1, 2, o 3.\n");
979         /* questo fa solo un po' di pulizia in GTK, ed esce con un valore 1. */
980         gtk_exit (1);
981     }
982     
983     which = atoi (argv[1]);
984
985     /* Creiamo la nostra finestra */
986     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
987
988     /* Ci si dovrebbe sempre ricordare di connettere il segnale di destroy
989      * alla finestra principale. Cio' e' molto importante per avere un funzionamento
990      * corretto dal punto di vista intuitivo */
991     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
992                         GTK_SIGNAL_FUNC (delete_event), NULL);
993     gtk_container_border_width (GTK_CONTAINER (window), 10);
994     
995     /* Creiamo una scatola verticale (vbox) in cui impacchettare quelle
996      * orizzontali. Questo ci permette di impilare le scatole orizzontali
997      * piene di bottoni una sull'altra in questa vbox. */
998   
999     box1 = gtk_vbox_new (FALSE, 0);
1000     
1001     /* Decide quale esempio si deve mostrare. Corrispondono alle figure precedenti */
1002     switch (which) {
1003     case 1:
1004         /* creare una nuova etichetta. */
1005         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1006         
1007         /* allineare l'etichetta al lato sinistro. Discuteremo questa e altre
1008          * funzioni nella sezione dedicata agli attributi degli oggetti grafici. */
1009         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1010
1011         /* Impacchettare l'etichetta nella scatola verticale (vbox box1).
1012          * Ricordare che gli oggetti che vengono aggiunti in una vbox vengono
1013          * impacchettati uno sopra all'altro in ordine. */
1014         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1015         
1016         /* mostrare l'etichetta */
1017         gtk_widget_show (label);
1018         
1019         /* chiamare la nostra funzione make_box - homogeneous = FALSE,
1020          * spacing = 0, expand = FALSE, fill = FALSE, padding = 0 */
1021         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1022         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1023         gtk_widget_show (box2);
1024
1025         /* chiamare la nostra funzione make_box - homogeneous = FALSE, spacing = 0,
1026          * expand = FALSE, fill = FALSE, padding = 0 */
1027         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1028         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1029         gtk_widget_show (box2);
1030         
1031         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1032         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1033         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1034         gtk_widget_show (box2);
1035         
1036         /* Questo crea un separatore. Li conosceremo meglio in seguito, 
1037          * comunque sono piuttosto semplici. */
1038         separator = gtk_hseparator_new ();
1039         
1040         /* Impacchetta il separatore nella vbox. Ricordare che stiamo impacchettando
1041          * ognuno di questi oggetti in una vbox, cosicch&eacute; essi verranno
1042          * impacchettati verticalmente. */
1043         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1044         gtk_widget_show (separator);
1045         
1046         /* crea un'altra nuova etichetta e mostrala. */
1047         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1048         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1049         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1050         gtk_widget_show (label);
1051         
1052         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1053         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1054         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1055         gtk_widget_show (box2);
1056         
1057         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1058         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1059         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1060         gtk_widget_show (box2);
1061         
1062         /* ancora un nuovo separatore. */
1063         separator = gtk_hseparator_new ();
1064         /* Gli ultimi 3 argumenti per gtk_box_pack_start sono: expand, fill, padding. */
1065         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1066         gtk_widget_show (separator);
1067         
1068         break;
1069
1070     case 2:
1071
1072         /* creare una nuova etichetta, ricordare che box1 e' la vbox creata 
1073          * vicino all'inizio di main() */
1074         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1075         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1076         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1077         gtk_widget_show (label);
1078         
1079         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1080         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1081         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1082         gtk_widget_show (box2);
1083         
1084         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1085         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1086         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1087         gtk_widget_show (box2);
1088         
1089         separator = gtk_hseparator_new ();
1090         /* Gli ultimi tre arcomenti di gtk_box_pack_start sono: expand, fill, padding. */
1091         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1092         gtk_widget_show (separator);
1093         
1094         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1095         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1096         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1097         gtk_widget_show (label);
1098         
1099         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1100         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1101         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1102         gtk_widget_show (box2);
1103         
1104         /* Gli argomenti sono: homogeneous, spacing, expand, fill, padding */
1105         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1106         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1107         gtk_widget_show (box2);
1108         
1109         separator = gtk_hseparator_new ();
1110         /* Gli ultimi tre argomenti di gtk_box_pack_start sono: expand, fill, padding. */
1111         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1112         gtk_widget_show (separator);
1113         break;
1114     
1115     case 3:
1116
1117         /* Questo dimostra la possibilita' di usare use gtk_box_pack_end() per
1118          * giustificare gli oggetti a destra. Per prima cosa creiamo una
1119          * nuova scatola come prima. */
1120         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1121         /* creiamo l'etichetta che sara' aggiunta alla fine. */
1122         label = gtk_label_new ("end");
1123         /* impacchettiamola usando gtk_box_pack_end(), cosa' che viene inserita
1124          * sul lato destro della hbox creata nella chiamata a the make_box(). */
1125         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1126         /* mostriamo l'etichetta. */
1127         gtk_widget_show (label);
1128         
1129         /* impacchettiamo box2 in box1 (the vbox, ricordate? :) */
1130         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1131         gtk_widget_show (box2);
1132         
1133         /* un separatore per il fondo */
1134         separator = gtk_hseparator_new ();
1135         /* Questo assegna esplicitamente al separatore l'ampiezza di 400 pixel
1136          * e l'altezza di 5 pixel. Cio' fa si' che la hbox che abbiamo creato sia
1137          * anche essa larga 400 pixel, e che l'etichetta finale sia separata dalle
1138          * altre etichette nella hbox. In caso contrario, tutti gli oggetti nella
1139          * hbox sarebbero impacchettati il piu' vicino possibile. */
1140         gtk_widget_set_usize (separator, 400, 5);
1141         /* impacchetta il separatore nella vbox (box1) creata vicino all'inizio 
1142          * di main() */
1143         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1144         gtk_widget_show (separator);    
1145     }
1146     
1147     /* Creare un'altra nuova hbox.. ricordate che ne possiamo usare quante ne vogliamo! */
1148     quitbox = gtk_hbox_new (FALSE, 0);
1149     
1150     /* Il nostro bottone di uscita. */
1151     button = gtk_button_new_with_label ("Quit");
1152     
1153
1154     /* Configuriamo il segnale per distruggere la finestra.  Ricordate che
1155      * ci&ograve; mander&agrave; alla finestra il segnale "destroy", che verr&agrave; catturato 
1156      * dal nostro gestore di segnali che abbiamo definito in precedenza. */
1157     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1158                                GTK_SIGNAL_FUNC (gtk_main_quit),
1159                                GTK_OBJECT (window));
1160     /* impacchetta il bottone in quitbox.
1161      * Gli ultimi tre argomenti di gtk_box_pack_start sono: expand, fill, padding. */
1162     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1163     /* impacchetta quitbox nella vbox (box1) */
1164     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1165     
1166     /* impacchetta la vbox (box1), che ora contiene tutti i nostri oggetti,
1167      * nella finestra principale. */
1168     gtk_container_add (GTK_CONTAINER (window), box1);
1169     
1170     /* e mostra tutto quel che rimane */
1171     gtk_widget_show (button);
1172     gtk_widget_show (quitbox);
1173     
1174     gtk_widget_show (box1);
1175     /* Mostriamo la finestra alla fine in modo che tutto spunti fuori assieme. */
1176     gtk_widget_show (window);
1177     
1178     /* E, naturalmente, la nostra funzione main. */
1179     gtk_main ();
1180
1181     /* Il controllo ritorna a questo punto quando viene chiamata gtk_main_quit(), 
1182      * ma non quando si usa gtk_exit. */
1183     
1184     return 0;
1185 }
1186 </verb></tscreen>
1187
1188 <!-- ----------------------------------------------------------------- -->
1189 <sect1>Impacchettamento con uso di Tabelle
1190 <p>
1191 Diamo ora un'occhiata ad un altro modo di impacchettare - le Tabelle.
1192 In certe situazioni, possono risultare estremamente utili.
1193
1194 Usando le tabelle, creiamo una griglia in cui possiamo piazzare gli oggetti.
1195 Gli oggetti possono occupare tanti spazi quanti ne specifichiamo.
1196
1197 Naturalmente, la prima cosa da vedere &egrave; la funzione gtk_table_new:
1198
1199 <tscreen><verb>
1200 GtkWidget* gtk_table_new (gint rows,
1201                           gint columns,
1202                           gint homogeneous);
1203 </verb></tscreen>
1204 <p>
1205 Il primo argomento rappresenta il numero di righe da mettere nella tabella,
1206 mentre il secondo &egrave; ovviamente il numero di colonne.
1207
1208 L'argomento homogeneous ha a che fare con il modo in cui le caselle della tabella
1209 sono dimensionate. Se homogeneous ha il valore TRUE, le caselle sono ridimensionate
1210 fino alla dimensione del pi&ugrave; grande oggetto contenuto nella tabelle. Se &egrave; FALSE, la
1211 dimensione delle caselle&egrave; decisa dal pi&ugrave; alto oggetto in una certa riga e dal pi&ugrave;
1212 largo oggetto in una stessa colonna.
1213
1214 Le righe e le colonne sono disposte a partire da 0 fino a n, dove n &egrave; il numero
1215 che era stato specificato nella chiamata a gtk_table_new. Cos&igrave;, se specificate 
1216 rows = 2 e columns = 2, lo schema avr&agrave; questo aspetto:
1217
1218 <tscreen><verb>
1219  0          1          2
1220 0+----------+----------+
1221  |          |          |
1222 1+----------+----------+
1223  |          |          |
1224 2+----------+----------+
1225 </verb></tscreen>
1226 <p>
1227 Notate che il sistema di coordinate ha origine nel vertice in alto a sinistra. Per
1228 mettere un oggetto in una tabella, usate la seguente funzione:
1229
1230 <tscreen><verb>
1231 void gtk_table_attach (GtkTable      *table,
1232                        GtkWidget     *child,
1233                        gint           left_attach,
1234                        gint           right_attach,
1235                        gint           top_attach,
1236                        gint           bottom_attach,
1237                        gint           xoptions,
1238                        gint           yoptions,
1239                        gint           xpadding,
1240                        gint           ypadding);
1241 </verb></tscreen>                                      
1242 <p>
1243 In cui il primo argomento (``table'') &egrave; la tabella che avete creato e il secondo
1244 (``child'') &egrave; l'oggetto che volete piazzare nella tabella.
1245
1246 Gli argomenti ``attach''  (right, left, top, bottom)  specificano dove mettere l'oggetto
1247 e quante caselle adoperare. Se volete mettere un bottone nella casella in basso a destra
1248 nella nostra tabella 2x2, e volete che esso riempia SOLO quella casella, dovete porre
1249 left_attach = 1, right_attach = 2, top_attach = 1, bottom_attach = 2.
1250
1251 Se invece volete che un oggetto si prenda tutta la riga pi&ugrave; in alto nella nostra tabella
1252 2x2, dovreste usare left_attach = 0, right_attach =2, top_attach = 0, 
1253 bottom_attach = 1.
1254
1255 Gli argomenti  ``xoptions'' e ``yoptions'' sono usati per specificare le opzioni di impacchettamento;
1256 di essi si pu&ograve; fare l'OR in modo di ottenere opzioni multiple.
1257
1258 Le opzioni sono:
1259 <itemize>
1260 <item>GTK_FILL - Se la parte di tabella in cui si vuole inserire il widget &egrave; pi&ugrave; 
1261 grande dell'oggetto, e se si specifica GTK_FILL, l'oggetto viene espanso fino ad
1262 occupare tutto lo spazio disponibile.
1263
1264 <item>GTK_SHRINK - Se si alloca all'oggetto nella tabella meno spazio del necessario
1265 (di solito succede quando l'utente ridimensiona la finestra), allora normalmente
1266 l'oggetto verrebbe spinto fuori dal fondo della finestra fino a sparire.
1267 Se invece si specifica GTK_SHRINK is specified, gli oggetti si rimpiccioliscono
1268 assieme alla tabella.
1269
1270 <item>GTK_EXPAND - Questo fa s&igrave; che la tabella si espanda fino ad occupare tutto lo 
1271 spazio che rimane nella finestra.
1272 </itemize>
1273
1274 Il riempimento funziona come nelle scatole, con la creazione di un'area vuota
1275 attorno all'oggetto la cui dimensione viene specificata in pixel.
1276
1277 La funzione gtk_table_attach() ha UN MUCCHIO di opzioni. Quindi, ecco una scorciatoia:
1278
1279 <tscreen><verb>
1280 void gtk_table_attach_defaults (GtkTable   *table,
1281                                 GtkWidget  *widget,
1282                                 gint        left_attach,
1283                                 gint        right_attach,
1284                                 gint        top_attach,
1285                                 gint        bottom_attach);
1286 </verb></tscreen>
1287
1288 Le xoptions e yoptions vengono posti per difetto a GTK_FILL | GTK_EXPAND, e sia xpadding
1289 che ypadding vengono posti a 0. Il resto degli argomenti sono identici a quelli della funzione
1290 precedente.
1291
1292 Ci sono poi le funzioni gtk_table_set_row_spacing() and gtk_table_set_col_spacing().
1293 Queste mettono dello spazio fra le righe (o colonne)in corrispondenza di una specifica
1294 riga (o colonna).
1295
1296 <tscreen><verb>
1297 void gtk_table_set_row_spacing (GtkTable      *table,
1298                                 gint           row,
1299                                 gint           spacing);
1300 </verb></tscreen>
1301 e
1302 <tscreen><verb>
1303 void       gtk_table_set_col_spacing  (GtkTable      *table,
1304                                        gint           column,
1305                                        gint           spacing);
1306 </verb></tscreen>
1307
1308 Notate che per le colonne lo spazio viene posto alla destra della colonna, mentre
1309 per le righe lo spazio viene posto al di sotto della riga.
1310
1311 Si pu&ograve; poi inserire una spaziatura identica fra tutte le righe e/o colonne usando:
1312
1313 <tscreen><verb>
1314 void gtk_table_set_row_spacings (GtkTable *table,
1315                                  gint      spacing);
1316 </verb></tscreen>
1317 <p>
1318 e
1319 <tscreen><verb>
1320 void gtk_table_set_col_spacings (GtkTable  *table,
1321                                  gint       spacing);
1322 </verb></tscreen>
1323 <p>
1324 Notate che con queste chiamate,  all'ultima riga e all'ultima colonna
1325 non viene assegnata alcuna spaziatura.
1326
1327 <!-- ----------------------------------------------------------------- -->
1328 <sect1>Esempio di Impacchettamento con Tabelle
1329  <p>
1330 In questo esempio creiamo una finestra avente tre bottoni disposti
1331 in una tabella 2x2. I primi due bottoni li mettiamo nella riga superiore.
1332 Un terzo bottone, quit, lo mettiamo nella riga inferioe, in modo da
1333 comprendere entrambe le colonne. Ci&ograve; significa che dovremmo
1334 avere qualcosa di questo tipo:
1335 <p>
1336 <? <CENTER> >
1337 <?
1338 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1339 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1340 >
1341 <? </CENTER> >
1342
1343 Ecco il codice sorgente:
1344  
1345 <tscreen><verb>
1346 /* table.c */
1347 #include <gtk/gtk.h>
1348
1349 /* la nostra funzione di ritorno.
1350  * i dati passati a questa funzione vengono stampati su stdout */
1351 void callback (GtkWidget *widget, gpointer *data)
1352 {
1353     g_print ("Hello again - %s was pressed\n", (char *) data);
1354 }
1355
1356 /* questa funzione fa uscire dal programma */
1357 void delete_event (GtkWidget *widget, gpointer *data)
1358 {
1359     gtk_main_quit ();
1360 }
1361
1362 int main (int argc, char *argv[])
1363 {
1364     GtkWidget *window;
1365     GtkWidget *button;
1366     GtkWidget *table;
1367
1368     gtk_init (&amp;argc, &amp;argv);
1369
1370     /* creiamo una nova finestra */
1371     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1372
1373     /* predisponiamo il titolo per la finestra */
1374     gtk_window_set_title (GTK_WINDOW (window), "Table");
1375
1376     /* creiamo un gestore per delete_event che esca immediatamente
1377      * da GTK. */
1378     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1379                         GTK_SIGNAL_FUNC (delete_event), NULL);
1380
1381     /* regoliamo la larghezza del bordo della finestra. */
1382     gtk_container_border_width (GTK_CONTAINER (window), 20);
1383
1384     /* creiamo una tabella 2x2 */
1385     table = gtk_table_new (2, 2, TRUE);
1386
1387     /* mettiamo la tabella nella finesta principale */
1388     gtk_container_add (GTK_CONTAINER (window), table);
1389
1390     /*creiamo il primo bottone */
1391     button = gtk_button_new_with_label ("button 1");
1392     /* quando viene premuto il bottone, chiamiamo la funzione di ritorno
1393      * con un puntatore a "button 1"come argomento */
1394     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1395               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1396
1397
1398     /* inseriamo il bottone 1 nel quadrante in alto a sinistra della tabella */
1399     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1400
1401     gtk_widget_show (button);
1402
1403     /* creiamo il secondo bottone */
1404
1405     button = gtk_button_new_with_label ("button 2");
1406
1407     /* quando si preme il bottone, chiamamo la funzione di ritorno
1408      * con un puntatore a "button 2"come argomento */
1409     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1410               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1411     /* inseriamo il secondo bottone nel quadrate in alto a destra della tbella */
1412     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1413
1414     gtk_widget_show (button);
1415
1416     /* creiamo il botone "Quit" */
1417     button = gtk_button_new_with_label ("Quit");
1418
1419     /* quando viene premuto questo bottone, chiamiamo la funzione "delete_event"
1420      * e si esce dal programma */
1421     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1422                         GTK_SIGNAL_FUNC (delete_event), NULL);
1423
1424     /* inseriamo il pulsante quit nelle due casele in basso della tabella */
1425     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1426
1427     gtk_widget_show (button);
1428
1429     gtk_widget_show (table);
1430     gtk_widget_show (window);
1431
1432     gtk_main ();
1433
1434     return 0;
1435 }
1436 </verb></tscreen>
1437
1438 <!-- ***************************************************************** -->
1439 <sect>Panoramica sui Widget
1440 <!-- ***************************************************************** -->
1441
1442 <p>
1443 La procedura generale di creazione di un widget in GTK prevede i seguenti passi:
1444 <enum>
1445 <item> gtk_*_new - una delle varie funzioni che servono per greare un nuovo widget.
1446 In questa sezione le vedremo tutte in dettaglio.
1447
1448 <item> Connettere tutti i segnali che si vogliono usare alle funzione gestione appfropriate.
1449
1450 <item> Assegnare gli attributi all'oggetto.
1451
1452 <item> Impacchettare l'oggetto in un contenitore usando la chiamate appropriata, 
1453 per esempio gtk_container_add() o gtk_box_pack_start().
1454
1455 <item> Mostrare l'oggetto con gtk_widget_show().
1456 </enum>
1457 <p>
1458 gtk_widget_show() fa s&igrave; che GTK sappia che abbiamo terminato di assegnare gli
1459 attributi dell'oggetto grafico, e che &egrave; pronto per essere visualizzato.
1460 Si pu&ograve; anche usare la funzione gtk_widget_hide per farlo sparire di nuovo.
1461 L'ordine in cui mostrate gli oggetti grafici non &egrave; importante, ma io suggerisco
1462 di mostrare per ultima la finestra, in modo che questa spunti fuori gi&agrave; completa,
1463 invece di vedere i singoli oggetti che arrivano sullo schermo a mano a mano che si
1464 formano. I figli di un oggetto grafico (anche una finestra &egrave; un oggetto grafico) non
1465 vengono infatti mostrati finch&eacute; la finestra stessa non viene mostrata usando la
1466 funzione gtk_widget_show().
1467
1468 <!-- ----------------------------------------------------------------- -->
1469 <sect1> Casting
1470 <p>
1471 Noterete andando avanti che GTK usa un sistema di casting di tipo. Questa operazione
1472 viene sempre effettuata usando delle macro che allo stesso tempo controllano la
1473 possibilit&agrave; di effettuare il cast sull'elemento dato e lo effettuano realmente.
1474 Alcune macro che avrete modo di incontrare sono:
1475
1476 <itemize>
1477 <item> GTK_WIDGET(widget)
1478 <item> GTK_OBJECT(object)
1479 <item> GTK_SIGNAL_FUNC(function)
1480 <item> GTK_CONTAINER(container)
1481 <item> GTK_WINDOW(window)
1482 <item> GTK_BOX(box)
1483 </itemize>
1484
1485 Tutte queste funzioni  sono usate per fare il cast di argomenti di funzione. Le vedrete
1486 negli esempi, e capirete se &egrave; il caso di usarle semplicemente guardando alle
1487 dichiarazioni delle funzioni.
1488
1489 Come potrete vedere pi&ugrave; sotto nella gerarchia delle classi, tutti i GtkWidgets
1490 sono derivati dalla classe base GtkObject. Ci&ograve; significa che potete usare un
1491 widget in ogni posto in cui una funzione richiede un oggetto - semplicemente
1492 usate la macro GTK_OBJECT().
1493
1494 Per esempio:
1495
1496 <tscreen><verb>
1497 gtk_signal_connect(GTK_OBJECT(button), "clicked",
1498                    GTK_SIGNAL_FUNC(callback_function), callback_data);
1499 </verb></tscreen> 
1500
1501 Questo fa il cast del bottone in un oggetto e fornisce alla chiamata di ritorno
1502 un cast al puntatore a funzione.
1503
1504 Molti oggetti grafici sono anche contenitori. Se guardate alla gerarchia delle
1505 classi pi&ugrave; sotto, vedrete che molti oggetti grafici sono derivati dalla classe
1506 GtkContainer. Ognuna di queste classi pu&ograve; essere usata, con la macro GTK_CONTAINER,
1507 come argomento per funzioni che richiedono un contenitore.
1508
1509 Sfortunatamente, in questo tutorial non si parler&agrave; in modo estensivo di queste macro,
1510 ma raccomando di dare un'occhiata ai file header di GTK. Pu&ograve; essere una cosa molto
1511 educativa. Infatti, non &egrave; difficile imparare come funziona un oggetto solo guardando
1512 le dichiarazioni delle funzioni.
1513
1514 <!-- ----------------------------------------------------------------- -->
1515 <sect1>Gerarchia degli Oggetti Grafici
1516 <p>
1517 Ecco, per vostro riferimento, la gerarchia delle classi usata per implementare gli
1518 oggetti grafici.
1519
1520  <tscreen><verb>
1521   GtkObject
1522    +GtkData
1523    | +GtkAdjustment
1524    | `GtkTooltips
1525    `GtkWidget
1526      +GtkContainer
1527      | +GtkBin
1528      | | +GtkAlignment
1529      | | +GtkEventBox
1530      | | +GtkFrame
1531      | | | `GtkAspectFrame
1532      | | +GtkHandleBox
1533      | | +GtkItem
1534      | | | +GtkListItem
1535      | | | +GtkMenuItem
1536      | | | | `GtkCheckMenuItem
1537      | | | |   `GtkRadioMenuItem
1538      | | | `GtkTreeItem
1539      | | +GtkViewport
1540      | | `GtkWindow
1541      | |   +GtkColorSelectionDialog
1542      | |   +GtkDialog
1543      | |   | `GtkInputDialog
1544      | |   `GtkFileSelection
1545      | +GtkBox
1546      | | +GtkButtonBox
1547      | | | +GtkHButtonBox
1548      | | | `GtkVButtonBox
1549      | | +GtkHBox
1550      | | | +GtkCombo
1551      | | | `GtkStatusbar
1552      | | `GtkVBox
1553      | |   +GtkColorSelection
1554      | |   `GtkGammaCurve
1555      | +GtkButton
1556      | | +GtkOptionMenu
1557      | | `GtkToggleButton
1558      | |   `GtkCheckButton
1559      | |     `GtkRadioButton
1560      | +GtkCList
1561      | +GtkFixed
1562      | +GtkList
1563      | +GtkMenuShell
1564      | | +GtkMenuBar
1565      | | `GtkMenu
1566      | +GtkNotebook
1567      | +GtkPaned
1568      | | +GtkHPaned
1569      | | `GtkVPaned
1570      | +GtkScrolledWindow
1571      | +GtkTable
1572      | +GtkToolbar
1573      | `GtkTree
1574      +GtkDrawingArea
1575      | `GtkCurve
1576      +GtkEditable
1577      | +GtkEntry
1578      | | `GtkSpinButton
1579      | `GtkText
1580      +GtkMisc
1581      | +GtkArrow
1582      | +GtkImage
1583      | +GtkLabel
1584      | | `GtkTipsQuery
1585      | `GtkPixmap
1586      +GtkPreview
1587      +GtkProgressBar
1588      +GtkRange
1589      | +GtkScale
1590      | | +GtkHScale
1591      | | `GtkVScale
1592      | `GtkScrollbar
1593      |   +GtkHScrollbar
1594      |   `GtkVScrollbar
1595      +GtkRuler
1596      | +GtkHRuler
1597      | `GtkVRuler
1598      `GtkSeparator
1599        +GtkHSeparator
1600        `GtkVSeparator
1601 </verb></tscreen>
1602
1603 <!-- ----------------------------------------------------------------- -->
1604 <sect1>Oggetti senza Finestre
1605 <p>
1606 Gli oggetti seguenti non hanno una finestra associata. Se volete catturare 
1607 degli eventi, dovrete usare l'oggetto GtkEventBox. Vedete anche la sezione su
1608 <ref id="sec_The_EventBox_Widget" name="Il Widget EventBox">
1609
1610 <tscreen><verb>
1611 GtkAlignment
1612 GtkArrow
1613 GtkBin
1614 GtkBox
1615 GtkImage
1616 GtkItem
1617 GtkLabel
1618 GtkPixmap
1619 GtkScrolledWindow
1620 GtkSeparator
1621 GtkTable
1622 GtkAspectFrame
1623 GtkFrame
1624 GtkVBox
1625 GtkHBox
1626 GtkVSeparator
1627 GtkHSeparator
1628 </verb></tscreen>
1629 <p>
1630 Proseguiremo la nostra esplorazione di GTK esaminando uno alla volta tutti
1631 gli oggetti, creando qualche semplice funzione per mostrarli. Un'altra
1632 buona sorgente &egrave; il programma testgtk.c che viene fornito con GTK. Potete
1633 trovarlo in gtk/testgtk.c.
1634
1635 <!-- ***************************************************************** -->
1636 <sect>Il Widget Bottone (Button)
1637 <!-- ***************************************************************** -->
1638
1639 <!-- ----------------------------------------------------------------- -->
1640 <sect1>Bottoni Normali
1641 <p>
1642 Ormai abbiamo visto tutto quello che c'&egrave; da vedere riguardo all'oggetto
1643 ``bottone''. E' piuttosto semplice, ma ci sono due modi per crare un bottone.
1644 Potete usare gtk_button_new_with_label() per creare un bottone con una
1645 etichetta, o usare gtk_button_new() per creare un bottone vuoto. In tal caso &egrave; poi
1646 vostro compito impacchettare un'etichetta o una pixmap sul bottone creato.
1647 Per fare ci&ograve;, create una nuova scatola, e poi impacchettateci i vostri
1648 oggetti usando la solita  gtk_box_pack_start, e infine usate la funzione
1649 gtk_container_add per impacchettare la scatola nel bottone.
1650 <p>
1651 Ecco un esempio di utilizzo di  gtk_button_new per creare un bottone con
1652 un'immagine ed un'etichetta su di s&egrave;. Ho separato il codice usato per
1653 creare la scatola in modo che lo possiate usare nei vostri programmi.
1654
1655 <tscreen><verb>
1656 /* buttons.c */
1657 #include <gtk/gtk.h>
1658
1659
1660 /* crea una nuova hbox contenente un'immagine ed un'etichetta
1661  * e ritorna la scatola creata. */
1662
1663 GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, gchar *label_text)
1664 {
1665     GtkWidget *box1;
1666     GtkWidget *label;
1667     GtkWidget *pixmapwid;
1668     GdkPixmap *pixmap;
1669     GdkBitmap *mask;
1670     GtkStyle *style;
1671
1672     /* creare una scatola per una xpm ed una etichetta */
1673     box1 = gtk_hbox_new (FALSE, 0);
1674     gtk_container_border_width (GTK_CONTAINER (box1), 2);
1675
1676     /* ottengo lo stile del bottone. Penso che sia per avere il colore
1677      * dello sfondo. Se qualcuno sa il vero motivo, &egrave; pregato di dirmelo. */
1678     style = gtk_widget_get_style(parent);
1679
1680     /* e ora via con le faccende dell'xpm stuff. Carichiamo l'xpm*/
1681     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1682                                          &amp;style->bg[GTK_STATE_NORMAL],
1683                                          xpm_filename);
1684     pixmapwid = gtk_pixmap_new (pixmap, mask);
1685
1686     /* creiamo l'etichetta per il bottone */
1687     label = gtk_label_new (label_text);
1688
1689     /* impacchettiamo la pixmap e l'etichetta nella scatola */
1690     gtk_box_pack_start (GTK_BOX (box1),
1691                         pixmapwid, FALSE, FALSE, 3);
1692
1693     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1694
1695     gtk_widget_show(pixmapwid);
1696     gtk_widget_show(label);
1697
1698     return (box1);
1699 }
1700
1701 /* la nostra solita funzione di callback */
1702 void callback (GtkWidget *widget, gpointer *data)
1703 {
1704     g_print ("Hello again - %s was pressed\n", (char *) data);
1705 }
1706
1707
1708 int main (int argc, char *argv[])
1709 {
1710     /* GtkWidget &egrave; il tipo per contenere gli oggetti */
1711     GtkWidget *window;
1712     GtkWidget *button;
1713     GtkWidget *box1;
1714
1715     gtk_init (&amp;argc, &amp;argv);
1716
1717     /* creiamo una nuova finestra */
1718     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1719
1720     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1721
1722     /* E' una buona idea fare questo per tutte le finestre. */
1723     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1724                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1725
1726     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1727                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1728
1729     /* assegnamo lo spessore del bordo della finestra */
1730     gtk_container_border_width (GTK_CONTAINER (window), 10);
1731     gtk_widget_realize(window);
1732
1733     /* creiamo un nuovo bottone */
1734     button = gtk_button_new ();
1735
1736     /* Ormai dovreste esservi abituati a vedere la maggior parte di
1737      * queste funzioni  */
1738     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1739                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1740
1741     /* questa chiama la nostra funzione di creazione di scatole */
1742     box1 = xpm_label_box(window, "info.xpm", "cool button");
1743
1744     /* impacchetta e mostra tutti i nostri oggetti */
1745     gtk_widget_show(box1);
1746
1747     gtk_container_add (GTK_CONTAINER (button), box1);
1748
1749     gtk_widget_show(button);
1750
1751     gtk_container_add (GTK_CONTAINER (window), button);
1752
1753     gtk_widget_show (window);
1754
1755     /* mettiti in gtk_main e aspetta che cominci il divertimento! */
1756     gtk_main ();
1757
1758     return 0;
1759 }
1760 </verb></tscreen>
1761 La funzione xpm_label_box pu&ograve; essere usata per impacchettare delle xpm
1762 e delle etichette su qualsiasi oggetto che pu&ograve; essere un contenitore.
1763
1764 <!-- ----------------------------------------------------------------- -->
1765 <sect1> Bottoni a Commutazione (Toggle Buttons)
1766 <p>
1767 I bottoni a commutazione sono molto simili ai bottoni normali, tranne che per il
1768 fatto che essi si trovano sempre in uno di due stati, che si alternano ad ogni
1769 click. Possono trovarsi nello stato ``premuto'', e quando li si ripreme, tornano
1770 ad essere sollevati. Ri-clickandoli, torneranno gi&ugrave;.
1771
1772 I bottoni a commutazione sono la base per i bottoni di controllo (check button) e
1773 per i radio-bottoni, e quindi molte delle chiamate disponibili per i bottoni
1774 a commutazione vengono ereditati dai radio-bottoni e dai bottoni di controllo.
1775 Ma vedremo questi aspetti nel momento in cui li incontreremo.
1776
1777 Creare un nuovo bottone a commutazione:
1778
1779 <tscreen><verb>
1780 GtkWidget* gtk_toggle_button_new (void);
1781
1782 GtkWidget* gtk_toggle_button_new_with_label (gchar *label);
1783 </verb></tscreen>
1784 <p>
1785 Come potete immaginare, queste funzioni lavorano in modo identico che per
1786 i bottoni normali. La prima crea un bottone a commutazione vuoto e la seconda un
1787 bottone con un'etichetta.
1788 <p>
1789 Per ottenere lo stato dei widget a commutazione, compresi i radio-bottoni e i
1790 bottoni di controllo, si pu&ograve; usare una macro come mostrato nell'esempio 
1791 pi&ugrave; sotto. In questo modo lo stato dell'oggetto commutabile viene valutato in
1792 una funzione di ritorno. Il segnale emesso dai bottoni a commutazione 
1793 (toggle button, il radio button o il check button) che ci interessa &egrave; il segnale
1794 ``toggled''. Per controllare lo stato di questi bottoni, create un gestore di
1795 segnali che catturi il ``toggled'', e usate la macro per determinare
1796 il suo stato. La funzione di callback avr&agrave; un aspetto pi&ugrave; o meno cos&igrave;:
1797
1798 <tscreen><verb>
1799 void toggle_button_callback (GtkWidget *widget, gpointer   data)
1800  {
1801      if (GTK_TOGGLE_BUTTON (widget)->active) 
1802      {
1803         /* Se il programma si &egrave; arrivato a questo punto, il bottone
1804          * a commutazione &egrave; premuto */
1805     
1806     } else {
1807     
1808         /* il bottone &egrave; sollevato */
1809      }
1810  }
1811  </verb></tscreen>
1812
1813 <!--
1814
1815 COMMENTED!
1816
1817 <tscreen><verb>
1818 guint gtk_toggle_button_get_type (void);
1819 </verb></tscreen>
1820 <p>
1821 No idea... they all have this, but I dunno what it is :)
1822
1823
1824 <tscreen><verb>
1825 void gtk_toggle_button_set_mode (GtkToggleButton *toggle_button,
1826                                  gint draw_indicator);
1827 </verb></tscreen>
1828 <p>
1829 No idea.
1830 -->
1831
1832 <tscreen><verb>
1833 void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
1834                                   gint state);
1835 </verb></tscreen>
1836 <p>
1837 La chiamata qui sopra pu&ograve; essere usata per fare l'assegnazione dello stato
1838 del bottone a commutazione e dei suoi figli, il radio-bottone e il bottone di
1839 controllo. Passando come primo argomento a questa funzione il vostro bottone e
1840 come secondo argomento il valore TRUE o FALSE, si pu&ograve; specificare se il
1841 bottone deve essere sollevato (rilasciato) o abbassato (premuto). Il valore
1842 di difetto &egrave; sollevato, cio&egrave; FALSE.
1843
1844 Notate che quando usate la funzione  gtk_toggle_button_set_state(), e lo
1845 stato viene cambiato, si ha il risultato che il bottone emette il segnale
1846 ``clicked''.
1847
1848 <tscreen><verb>
1849 void       gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
1850 </verb></tscreen>
1851 <p>
1852 Questa funzione semplicemente commuta il bottone, ed emette il segnale ``toggled''.
1853
1854 <!-- ----------------------------------------------------------------- -->
1855 <sect1> Bottoni di Controllo (Check Buttons)
1856 <p>
1857 I bottoni di controllo ereditano molte propriet&agrave; e funzioni dal bottone a commutazione,
1858 ma hanno un aspetto un po' diverso. Invece di essere bottoni contenenti del testo,
1859 si tratta di quadratini con del testo alla propria destra. Questi bottoni sono
1860 spesso usati nelle applicazioni per commutare fra lo stato attivato e disattivato delle
1861 opzioni.
1862
1863 Le due funzioni di creazione sono analoghe a quelle del bottone normale..
1864
1865 <tscreen><verb>
1866 GtkWidget* gtk_check_button_new (void);
1867
1868 GtkWidget* gtk_check_button_new_with_label (gchar *label);
1869 </verb></tscreen>
1870
1871 La funzione new_with_label crea un bottone di controllo con una etichetta
1872 a fianco di esso.
1873
1874 Per controllare lo stato del check button si opera in modo identico al bottone
1875 a commutazione.
1876
1877 <!-- ----------------------------------------------------------------- -->
1878 <sect1> Radio-Bottoni (Radio Buttons)
1879 <p>
1880 I radio-bottoni sono simili ai bottoni di controllo, tranne che per il
1881 fatto che sono sempre raggruppati in modo che solo uno alla volta di essi
1882 pu&ograve; essere selezionato (premuto). Tornano utili quando nella propria applicazione
1883 si ha bisogno di selezionare una opzione da una breve lista.
1884
1885 La creazione di un nuovo radio-bottone si fa con una di queste chiamate:
1886
1887 <tscreen><verb>
1888 GtkWidget* gtk_radio_button_new (GSList *group);
1889
1890 GtkWidget* gtk_radio_button_new_with_label (GSList *group,
1891                                             gchar *label);
1892 </verb></tscreen>
1893 <p>
1894 Avrete notato l'argomento in pi&ugrave; che c'&egrave; in queste chiamate. Queste hanno
1895 infatti bisogno dela specificazione di un ``gruppo'' per svolgere il loro compito.
1896 Per il primo bottone di un gruppo si deve passare come primo argomento il valore
1897 NULL. Dopodich&eacute; potete creare un gruppo usando la funzione:
1898
1899 <tscreen><verb>
1900 GSList* gtk_radio_button_group (GtkRadioButton *radio_button);
1901 </verb></tscreen>
1902
1903 <p>
1904 La cosa importante da ricordare &egrave; che gtk_radio_button_group va chiamata ogni volta che si aggiunge un nuovo bottone al gruppo, con il preceente bottone passato come argomento. Il risultato viene poi passato nella chiamata a gtk_radio_button_new o a gtk_radio_button_new_with_label. Ci&ograve; permette di creare una catena di bottoni. L'esempio pi&ugrave; sotto dovrebbe chiarire questo punto.
1905
1906 E' poi una buona idea stabiire quale dev'essere il bottone premuto per difetto, usando:
1907
1908 <tscreen><verb>
1909 void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
1910                                   gint state);
1911 </verb></tscreen>
1912 <p>
1913 Questa funzione &egrave; descritta nella sezione sui bottoni a commutazione, e funziona
1914 nello stesso identico modo.
1915
1916 <p>
1917 Nel seguente esempio creiamo un gruppo di tre radio-bottoni.
1918  
1919 <tscreen><verb>
1920 /* radiobuttons.c */
1921
1922 #include <gtk/gtk.h>
1923 #include <glib.h>
1924  
1925 void close_application( GtkWidget *widget, gpointer *data ) {
1926   gtk_main_quit();
1927 }
1928
1929 main(int argc,char *argv[])
1930 {
1931   static GtkWidget *window = NULL;
1932   GtkWidget *box1;
1933   GtkWidget *box2;
1934   GtkWidget *button;
1935   GtkWidget *separator;
1936   GSList *group;
1937   
1938   gtk_init(&amp;argc,&amp;argv);          
1939   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1940   
1941   gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1942                       GTK_SIGNAL_FUNC(close_application),
1943                       NULL);
1944
1945   gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
1946   gtk_container_border_width (GTK_CONTAINER (window), 0);
1947
1948   box1 = gtk_vbox_new (FALSE, 0);
1949   gtk_container_add (GTK_CONTAINER (window), box1);
1950   gtk_widget_show (box1);
1951
1952   box2 = gtk_vbox_new (FALSE, 10);
1953   gtk_container_border_width (GTK_CONTAINER (box2), 10);
1954   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1955   gtk_widget_show (box2);
1956
1957   button = gtk_radio_button_new_with_label (NULL, "button1");
1958   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1959   gtk_widget_show (button);
1960
1961   group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1962   button = gtk_radio_button_new_with_label(group, "button2");
1963   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
1964   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1965   gtk_widget_show (button);
1966
1967   group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1968   button = gtk_radio_button_new_with_label(group, "button3");
1969   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1970   gtk_widget_show (button);
1971
1972   separator = gtk_hseparator_new ();
1973   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1974   gtk_widget_show (separator);
1975
1976   box2 = gtk_vbox_new (FALSE, 10);
1977   gtk_container_border_width (GTK_CONTAINER (box2), 10);
1978   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1979   gtk_widget_show (box2);
1980
1981   button = gtk_button_new_with_label ("close");
1982   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1983                              GTK_SIGNAL_FUNC(close_application),
1984                              GTK_OBJECT (window));
1985   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1986   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1987   gtk_widget_grab_default (button);
1988   gtk_widget_show (button);
1989   gtk_widget_show (window);
1990      
1991   gtk_main();
1992   return(0);
1993 }
1994 </verb></tscreen>
1995
1996 La cosa pu&ograve; essere accorciata un po' usando la seguente sintassi,
1997 che elimina la necessit&agrave; di una variabile per contenere la lista di bottoni:
1998
1999 <tscreen><verb>
2000      button2 = gtk_radio_button_new_with_label(
2001                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2002                  "button2");
2003 </verb></tscreen>
2004
2005
2006 <!-- ***************************************************************** -->
2007 <sect> Alcuni Widget
2008 <!-- ***************************************************************** -->
2009
2010 <!-- ----------------------------------------------------------------- -->
2011 <sect1> L'Etichetta (Label)
2012 <p>
2013 Le etichette sono molto usate in GTK, e sono relativamente semplici. Le
2014 etichette non emettono segnali, dal momento che non hanno una finestra
2015 X a loro assegnata. Se avete la necessit&agrave; di avere dei segnali o di fare
2016 delle operazioni di clipping, potete usare il widget EventBox.
2017
2018 Per creare una nuova etichetta, si usa:
2019
2020 <tscreen><verb>
2021 GtkWidget* gtk_label_new (char *str);
2022 </verb></tscreen>
2023
2024 In cui l'unico argomento &egrave; la stringa che si vuole sia mostrata.
2025
2026 Per cambiare il testo dell'etichetta dopo che &egrave; stata creata, si usa
2027 la funzione:
2028
2029 <tscreen><verb>
2030 void gtk_label_set (GtkLabel  *label,
2031                     char      *str);
2032 </verb></tscreen>
2033 <p>
2034 in cui il primo argomento &egrave; l'etichetta creata in precedenza (di cui si
2035 fa il cast usando la macro GTK_LABEL()), mentre il secondo &egrave; la nuova
2036 stringa.
2037
2038 Nel caso, lo spazio necessario per la nuova stringa verr&agrave; regolato automaticamente.
2039
2040 Per ottenere la stringa corrente si usa:
2041
2042 <tscreen><verb>
2043 void gtk_label_get (GtkLabel  *label,
2044                     char     **str);
2045 </verb></tscreen>
2046
2047 in cui il primo argomento &egrave; l'etichetta che avete creato, e il secondo
2048 &egrave; il valore di ritorno per la stringa.
2049
2050 <!-- ----------------------------------------------------------------- -->
2051 <sect1>Il Widget Suggerimenti (Tooltips)
2052 <p>
2053 I suggerimenti sono piccole stringhe di testo che spuntano quando lasciate il
2054 puntatore su un bottone o un altro widget per qualche secondo. Sono piuttosto
2055 semplici da usare, per cui ne dar&ograve; la spiegazione senza corredarla di esempi.
2056 Se volede vedere un po' di codice, date un'occhiata al programma testgtk.c
2057 distribuito con GTK.
2058 <p>
2059 Con alcuni widget (per esempio con l'etichetta) i suggerimenti non funzionano.
2060 <p>
2061 La prima chiamata che si usa per creare un nuovo tooltip &egrave; la seguente.
2062 In una data funzione, &egrave; necessario chiamarla una sola volta: il GtkTooltip
2063 che viene ritornato da questa funzione pu&ograve; essere usato per creare suggerimenti
2064 multipli.
2065
2066 <tscreen><verb>
2067 GtkTooltips *gtk_tooltips_new (void);
2068 </verb></tscreen>
2069
2070 Una volta creato un nuovo suggerimento e il widget su cui lo volete usare,
2071 basta usare la seguente chiamata per fare l'assegnazione:
2072
2073 <tscreen><verb>
2074 void gtk_tooltips_set_tips   (GtkTooltips *tooltips,
2075                               GtkWidget   *widget,
2076                               gchar       *tips_text);
2077 </verb></tscreen>
2078
2079 Il primo argomento &egrave; il suggerimento che era gi&agrave; stato creato, che &egrave; seguito
2080 dal widget da cui volete che spunti il suggerimento e dal testo che volete
2081 venga mostrato.
2082 <p>
2083 Ecco un piccolo esempio:
2084
2085 <tscreen><verb>
2086 GtkTooltips *tooltips;
2087 GtkWidget *button;
2088 ...
2089 tooltips = gtk_tooltips_new ();
2090 button = gtk_button_new_with_label ("button 1");
2091 ...
2092 gtk_tooltips_set_tips (tooltips, button, "This is button 1");
2093 </verb></tscreen>
2094
2095 Ci sono anche altre funzioni che si usano con i suggerimenti. Eccone una lista
2096 con una breve descrizione di quello che fanno.
2097
2098 <tscreen><verb>
2099 void gtk_tooltips_destroy    (GtkTooltips *tooltips);
2100 </verb></tscreen>
2101
2102 Distrugge un suggerimento esistente.
2103
2104 <tscreen><verb>
2105 void gtk_tooltips_enable     (GtkTooltips *tooltips);
2106 </verb></tscreen>
2107
2108 Abilita  un gruppo di suggerimenti disbilitato.
2109
2110 <tscreen><verb>
2111 void gtk_tooltips_disable    (GtkTooltips *tooltips);
2112 </verb></tscreen>
2113
2114 Disabilita un gruppo di suggerimenti abilitato.
2115
2116 <tscreen><verb>
2117 void gtk_tooltips_set_delay  (GtkTooltips *tooltips,
2118                               gint         delay);
2119
2120 </verb></tscreen>
2121 Stabilisce quanti millisecondi si deve mantenere il puntatore sopra al
2122 widget prima che venga mostrato il suggerimento. Il valore di difetto
2123 &egrave; di 1000 millisecondi.
2124
2125 <tscreen><verb>
2126 void      gtk_tooltips_set_tips (GtkTooltips *tooltips,
2127                                  GtkWidget   *widget,
2128                                  gchar    *tips_text);
2129 </verb></tscreen>
2130
2131 Cambia il testo di un suggerimento gi&agrave; esistente.
2132
2133 <tscreen><verb>
2134 void gtk_tooltips_set_colors (GtkTooltips *tooltips,
2135                               GdkColor    *background,
2136                               GdkColor    *foreground);
2137 </verb></tscreen>
2138
2139 Assegna i colori di primo piano e di sfondo dei suggerimenti. (Non ho idea
2140 di come si specifichino i colori).
2141 <p>
2142 E questo &egrave; tutto riguardo alle funzioni relative ai suggerimenti. Pi&ugrave;
2143 di quanto avreste mai voluto sapere :)
2144  
2145  
2146 <!-- ----------------------------------------------------------------- -->
2147 <sect1> La Barra di Avanzamento (Progress Bar)
2148 <p>
2149 Le barre di avanzamento sono usate per mostrare lo stato di una operazione. Come potete
2150 vedere nel frammento di codice qui sotto, sono piuttosto semplici da usare.
2151 Ma prima vediamo come cominciare con la chiamata per creare una nuova progress
2152 bar.
2153
2154 <tscreen><verb>
2155 GtkWidget *gtk_progress_bar_new (void);
2156 </verb></tscreen>
2157
2158 Ora che la barra di avanzamento &egrave; stata creata, possiamo usarla..
2159
2160 <tscreen><verb>
2161 void gtk_progress_bar_update (GtkProgressBar *pbar, gfloat percentage);
2162 </verb></tscreen>
2163
2164 Il primo argomento &egrave; la barra di avanzamento su cui volete lavorare, e il secondo
2165 &egrave; la quantit&agrave; 'completato', cio&egrave; la quantit&agrave; di riempimento della progress
2166 bar fra 0 e 100% (un numero reale fra 0 e 1).
2167
2168 Le barre di avanzamento sono usate di solito con funzioni di timeout o altre di
2169 questo tipo (vedi alla sezione <ref id="sec_timeouts" name="Timeouts,
2170 I/O and Idle Functions">) per dare l'illusione del multitasking. Tutte
2171 usano la funzione gtk_progress_bar_update nello stesso modo.
2172
2173 Ecco un esempio di barra di avanzamento, in cui l'aggiornamento avviene usando
2174 dei timeout. Questo codice vi mostra anche come riinizializzare le
2175 barre di avanzamento.
2176
2177 <tscreen><verb>
2178 /* progressbar.c */
2179
2180 #include <gtk/gtk.h>
2181
2182 static int ptimer = 0;
2183 int pstat = TRUE;
2184
2185 /* Questa funzione incrementa e aggiorna la barra di avanzamento, e la rimette
2186    a zero se pstat &egrave; FALSE */
2187 gint progress (gpointer data)
2188 {
2189     gfloat pvalue;
2190     
2191     /* ottiene il valore corrente della status bar */
2192     pvalue = GTK_PROGRESS_BAR (data)->percentage;
2193     
2194     if ((pvalue >= 1.0) || (pstat == FALSE)) {
2195         pvalue = 0.0;
2196         pstat = TRUE;
2197     }
2198     pvalue += 0.01;
2199     
2200     gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);
2201     
2202     return TRUE;
2203 }
2204
2205 /* Questa funzione segnala la riinizializzazione della 
2206    barra di avanzamento */
2207 void progress_r (void)
2208 {  
2209     pstat = FALSE;  
2210 }
2211
2212 void destroy (GtkWidget *widget, gpointer *data)
2213 {
2214     gtk_main_quit ();
2215 }
2216
2217 int main (int argc, char *argv[])
2218 {
2219     GtkWidget *window;
2220     GtkWidget *button;
2221     GtkWidget *label;
2222     GtkWidget *table;
2223     GtkWidget *pbar;
2224     
2225     gtk_init (&amp;argc, &amp;argv);
2226     
2227     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2228     
2229     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2230                         GTK_SIGNAL_FUNC (destroy), NULL);
2231     
2232     gtk_container_border_width (GTK_CONTAINER (window), 10);
2233     
2234     table = gtk_table_new(3,2,TRUE);
2235     gtk_container_add (GTK_CONTAINER (window), table);
2236     
2237     label = gtk_label_new ("Progress Bar Example");
2238     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,2,0,1);
2239     gtk_widget_show(label);
2240     /* Crea una nuova barra di avanzamento, impacchettala nella tabella
2241        e mostrala */
2242     pbar = gtk_progress_bar_new ();
2243     gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2);
2244     gtk_widget_show (pbar);
2245     
2246     /* Attiva un timeout che gestisca l'aggiornamento automatico della barra */
2247     ptimer = gtk_timeout_add (100, progress, pbar);
2248     
2249     /* Questo bottone segnala alla barra che deve essere resettata */
2250     button = gtk_button_new_with_label ("Reset");
2251     gtk_signal_connect (GTK_OBJECT (button), "clicked",
2252                         GTK_SIGNAL_FUNC (progress_r), NULL);
2253     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,2,3);
2254     gtk_widget_show(button);
2255     
2256     button = gtk_button_new_with_label ("Cancel");
2257     gtk_signal_connect (GTK_OBJECT (button), "clicked",
2258                         GTK_SIGNAL_FUNC (destroy), NULL);
2259     
2260     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,2,3);
2261     gtk_widget_show (button);
2262     
2263     gtk_widget_show(table);
2264     gtk_widget_show(window);
2265     
2266     gtk_main ();
2267     
2268     return 0;
2269 }
2270 </verb></tscreen>
2271
2272 In questo programmino ci sono quattro aree che riguardano il modo di
2273 uso generale delle Barre di Avanzamento; le vediamo ora nell'ordine.
2274
2275 <tscreen><verb>
2276 pbar = gtk_progress_bar_new ();
2277 </verb></tscreen>
2278
2279 Questo codice crea una nuova barra ciamata pbar.
2280
2281 <tscreen><verb>
2282 ptimer = gtk_timeout_add (100, progress, pbar);
2283 </verb></tscreen>
2284
2285 Questo codice usa dei timeout per abilitare degli intervalli di tempo uguali.
2286 Per usare le barre di avanzamento non &egrave; per&ograve; necessario servirsi di timeout.
2287
2288 <tscreen><verb>
2289 pvalue = GTK_PROGRESS_BAR (data)->percentage;
2290 </verb></tscreen>
2291
2292 Qui si assegna a pvalue il valore corrente della percentuale di avanzamento.
2293
2294 <tscreen><verb>
2295 gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);
2296 </verb></tscreen>
2297
2298 Infine, questo codice aggiorna la barra di avanzamento con il valore di pvalue.
2299
2300 Questo &egrave; tutto quanto c'&egrave; da sapere sulle barre di avanzamento, divertitevi.
2301
2302 <!-- ----------------------------------------------------------------- -->
2303 <sect1> Dialoghi
2304 <p>
2305
2306 Il widget ``Dialogo'' &egrave; molto semplice: si tratta in realt&agrave; di una finestra
2307 con alcuni elementi pre-impacchettati. La struttura di un dialogo &egrave; la
2308 seguente:
2309
2310 <tscreen><verb>
2311 struct GtkDialog
2312 {
2313       GtkWindow window;
2314     
2315       GtkWidget *vbox;
2316       GtkWidget *action_area;
2317 };
2318 </verb></tscreen>
2319
2320 Come potete vedere, crea semplicemente una finestra vi inserisce una vbox
2321 in cima, poi un separatore e infine una hbox come ``area di azione''.
2322
2323 Un Dialogo pu&ograve; essere utilizzato per messaggi per l'utente e
2324 altri scopi simili. E' un widget molto essenziale, che ha una sola funzione,
2325 e precisamente:
2326
2327 <tscreen><verb>
2328 GtkWidget* gtk_dialog_new (void);
2329 </verb></tscreen>
2330
2331 Per cui, per creare una nuova finestra di dialogo, uate:
2332
2333 <tscreen><verb>
2334 GtkWidget window;
2335 window = gtk_dialog_new ();
2336 </verb></tscreen>
2337
2338 Questa funzione crea una finestra di dialogo, dopodich&eacute; sta a voi 
2339 utilizzarla. Potete mettere un bottone nella action_area facendo
2340 qualcosa del tipo:
2341
2342 <tscreen><verb>
2343 button = ...
2344 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
2345                     TRUE, TRUE, 0);
2346 gtk_widget_show (button);
2347 </verb></tscreen>
2348
2349 Potreste anche aggiungere, ad esempio, un'etichetta all'area della vbox,
2350 con qualcosa di questo genere:
2351
2352 <tscreen><verb>
2353 label = gtk_label_new ("Dialogs are groovy");
2354 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE,
2355                     TRUE, 0);
2356 gtk_widget_show (label);
2357 </verb></tscreen>
2358
2359 Per provare a usare una finestra di dialogo, potreste provare a mettere
2360 due bottoni nella action_area, per esempio un bottone ``Cancella'' ed un
2361 bottone ``OK'' e un'etichetta nella vbox che chieda qualcosa all'utente o
2362 segnali un errore. Poi potreste collegare un diverso segnale a ciascun
2363 bottone ed eseguire l'operazione che l'utente che viene scelta dall'utente.
2364
2365 <!-- ----------------------------------------------------------------- -->
2366 <sect1> Le Pixmap
2367 <p>
2368
2369 Le Pixmap sono strutture dati che contengono immagini. Queste immagini
2370 possono poi essere utilizzate in varie occasioni, per esempio come 
2371 icone sul desktop X-Window o come cusori. Una bitmap &egrave; una pixmap a due
2372 colori.
2373
2374 Per usare una pixmap in GTK, dobbiamo in primo luogo creare una struttura
2375 GdkPixmap utilizzando le routine disponibili nello strato GDK. Una Pixmap
2376 pu&ograve; essere creata a partire da dati presenti in memoria o letti da un file.
2377 Vedremo ora una ad una le chiamate utilizzate per creare una pixmap.
2378
2379 <tscreen><verb>
2380 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
2381                                         gchar     *data,
2382                                         gint      width,
2383                                         gint      height );
2384 </verb></tscreen>
2385 <p>
2386 Si usa questa routine per creare una pixmap ad un solo piano (2 colori) da
2387 dati disponibili in memoria. Ogni bit nei dati indica lo stato acceso o
2388 spento di un pixel. L'altezza (height) e la larghezza (width) sono espresse
2389  in pixel. GdkWindow &egrave; un puntatore alla finestra corrente, dal momento che
2390 le risorse di una pixmap hanno significato solo nel contesto dello schermo 
2391 in cui deve essere mostrata.
2392
2393 <tscreen><verb>
2394 GdkPixmap* gdk_pixmap_create_from_data( GdkWindow  *window,
2395                                         gchar      *data,
2396                                         gint        width,
2397                                         gint        height,
2398                                         gint        depth,
2399                                         GdkColor   *fg,
2400                                         GdkColor   *bg );
2401 </verb></tscreen>
2402
2403 Questa &egrave; usata per creare una pixmap con la profondit&agrave; data (depth, ossia 
2404 numero di colori) usando i dati specificati. fg e bg indicano i colori da
2405 usare per il primo piano e per lo sfondo.
2406
2407 <tscreen><verb>
2408 GdkPixmap* gdk_pixmap_create_from_xpm( GdkWindow  *window,
2409                                        GdkBitmap **mask,
2410                                        GdkColor   *transparent_color,
2411                                        const gchar *filename );
2412 </verb></tscreen>
2413
2414 Il formato XPM &egrave; una rappresentazione di pixmap leggibile per X Window. E' una
2415 rappresentazione molto diffusa, e sono disponibili parecchi programmi per creare
2416 immagini in questo formato. Il file specificato da ``filename'' deve contenere
2417 un'immagine in questo formato, che viene caricato nella struttura pixmap.
2418 La maschera (mask) specifica quali pixel della pixmap devono essere opachi.
2419 Tutti gli altri pixel sono colorati usando il colore specificato da
2420 transparent_color. Pi&ugrave; sotto mostreremo un esempio di uso di questa funzione.
2421
2422 <tscreen><verb>
2423 GdkPixmap* gdk_pixmap_create_from_xpm_d (GdkWindow  *window,
2424                                          GdkBitmap **mask,
2425                                          GdkColor   *transparent_color,
2426                                          gchar     **data);
2427 </verb></tscreen>
2428
2429 Si possono incorporare piccole immagini all'interno di un programma sotto
2430 forma di dati in formato XPM. In questo modo, invece di leggerli da un file,
2431 si possono usare questi dati per creare una pixmap. Un esempio di questo tipo
2432 di dati &egrave;
2433
2434 <tscreen><verb>
2435 /* XPM */
2436 static const char * xpm_data[] = {
2437 "16 16 3 1",
2438 "       c None",
2439 ".      c #000000000000",
2440 "X      c #FFFFFFFFFFFF",
2441 "                ",
2442 "   ......       ",
2443 "   .XXX.X.      ",
2444 "   .XXX.XX.     ",
2445 "   .XXX.XXX.    ",
2446 "   .XXX.....    ",
2447 "   .XXXXXXX.    ",
2448 "   .XXXXXXX.    ",
2449 "   .XXXXXXX.    ",
2450 "   .XXXXXXX.    ",
2451 "   .XXXXXXX.    ",
2452 "   .XXXXXXX.    ",
2453 "   .XXXXXXX.    ",
2454 "   .........    ",
2455 "                ",
2456 "                "};
2457 </verb></tscreen>
2458
2459 <tscreen><verb>
2460 void gdk_pixmap_destroy( GdkPixmap  *pixmap );
2461 </verb></tscreen>
2462 <p>
2463 Quando abbiamo finito di usare una pixmap e pensiamo di non doverla riutilizzare
2464 presto, &egrave; una buona idea liberare queste risorse usando la funzione 
2465 dk_pixmap_destroy. Le pixmap devono essere considerate una risorsa preziosa.
2466
2467 Quando abbiamo creato una pixmap, possiamo mostrarla come un widget GTK.
2468 E' necessario creare un widget pixmap che contenga una pixmap GDK. Questa
2469 operazione viene compiuta usando
2470
2471 <tscreen><verb>
2472 GtkWidget* gtk_pixmap_new( GdkPixmap  *pixmap,
2473                            GdkBitmap  *mask );
2474 </verb></tscreen>
2475 <p>
2476 Le altre chiamate per i widget pixmap sono
2477
2478 <tscreen><verb>
2479 guint gtk_pixmap_get_type( void );
2480 void  gtk_pixmap_set( GtkPixmap  *pixmap,
2481                       GdkPixmap  *val,
2482                       GdkBitmap  *mask);
2483 void  gtk_pixmap_get( GtkPixmap  *pixmap,
2484                       GdkPixmap **val,
2485                       GdkBitmap **mask);
2486 </verb></tscreen>
2487 <p>
2488 La funzione gtk_pixmap_set viene usata per cambiare la pixmap che viene
2489 gestita correntemente dal widget.
2490 gtk_pixmap_set is used to change the pixmap that the widget is currently
2491 managing.  ``val'' &egrave; la pixmap che &egrave; stata creata usando il GDK.
2492 Segue un esempio di uso di una pixmap in un bottone.
2493
2494 <tscreen><verb>
2495 /* pixmap.c */
2496 #include <gtk/gtk.h>
2497
2498
2499 /* dat XPM dell'icona Apri File */
2500 static const char * xpm_data[] = {
2501 "16 16 3 1",
2502 "       c None",
2503 ".      c #000000000000",
2504 "X      c #FFFFFFFFFFFF",
2505 "                ",
2506 "   ......       ",
2507 "   .XXX.X.      ",
2508 "   .XXX.XX.     ",
2509 "   .XXX.XXX.    ",
2510 "   .XXX.....    ",
2511 "   .XXXXXXX.    ",
2512 "   .XXXXXXX.    ",
2513 "   .XXXXXXX.    ",
2514 "   .XXXXXXX.    ",
2515 "   .XXXXXXX.    ",
2516 "   .XXXXXXX.    ",
2517 "   .XXXXXXX.    ",
2518 "   .........    ",
2519 "                ",
2520 "                "};
2521
2522
2523 /* quando invocata (con il segnale delete_event), termina l'applicazione. */
2524 void close_application( GtkWidget *widget, gpointer *data ) {
2525     gtk_main_quit();
2526 }
2527
2528 /* invocata se il bottone &egrave; clickato. Stampa semplicemente un messaggio */
2529 void button_clicked( GtkWidget *widget, gpointer *data ) {
2530     printf( "button clicked\n" );
2531 }
2532
2533 int main( int argc, char *argv[] )
2534 {
2535     /* i widget sono memorizzati nel tipo GtkWidget */
2536     GtkWidget *window, *pixmapwid, *button;
2537     GdkPixmap *pixmap;
2538     GdkBitmap *mask;
2539     GtkStyle *style;
2540     
2541     /* crea la finestra principale, e collega il segnale delete_event
2542        alla terminazione dell'applicazione */
2543     gtk_init( &amp;argc, &amp;argv );
2544     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2545     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
2546                         GTK_SIGNAL_FUNC (close_application), NULL );
2547     gtk_container_border_width( GTK_CONTAINER (window), 10 );
2548     gtk_widget_show( window );
2549
2550     /* la pixmap proviene da gdk */
2551     style = gtk_widget_get_style( window );
2552     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
2553                                            &amp;style->bg[GTK_STATE_NORMAL],
2554                                            (gchar **)xpm_data );
2555
2556     /* un widget pixmap per contenere la pixmap */
2557     pixmapwid = gtk_pixmap_new( pixmap, mask );
2558     gtk_widget_show( pixmapwid );
2559
2560     /* un bottone per contenere il widget pixmap */
2561     button = gtk_button_new();
2562     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
2563     gtk_container_add( GTK_CONTAINER(window), button );
2564     gtk_widget_show( button );
2565
2566     gtk_signal_connect( GTK_OBJECT(button), "clicked",
2567                         GTK_SIGNAL_FUNC(button_clicked), NULL );
2568
2569     /* mostra la finestra */
2570     gtk_main ();
2571           
2572     return 0;
2573 }
2574 </verb></tscreen>
2575
2576
2577 Per caricare una pixmap da un file XPM chiamato icon0.xpm che si trova
2578 nella direttorio corrente, avremmo creato la pixmap in questo modo:
2579
2580 <tscreen><verb>
2581     /* carica una pixmap da un file */
2582     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
2583                                          &amp;style->bg[GTK_STATE_NORMAL],
2584                                          "./icon0.xpm" );
2585     pixmapwid = gtk_pixmap_new( pixmap, mask );
2586     gtk_widget_show( pixmapwid );
2587     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
2588 </verb></tscreen>
2589
2590
2591 Usare le Sagome
2592 <p>
2593 Uno degli svantaggi di usare le pixmap &egrave; costituito dal fatto che l'oggetto
2594 mostrato &egrave; sempre rettangolare, a prescindere dall'immagine. Ci piacerebbe
2595 invece poter crare dei desktop e delle immagini con forme pi&ugrave; naturali. Per
2596 esempio, per l'interfaccia di un gioco, potremmo volere avere dei pulsanti
2597 circolari. Il modo per ottenere questo effetto &egrave; di usare delle finestre
2598 sagomate.
2599
2600 Una finestra sagomata &egrave; semplicemente una pixmap in cui i pixel dello
2601 sfondo sono trasparenti. In questo modo, se l'immagine di sfondo &egrave; 
2602 multicolore, possiamo evitare di sovrascriverla con un bordo rettangolare
2603 attorno all'icona. Il prossimo esempio mostra una carriola sul desktop.
2604
2605 <tscreen><verb>
2606 /* wheelbarrow.c */
2607 #include <gtk/gtk.h>
2608
2609 /* XPM */
2610 static char * WheelbarrowFull_xpm[] = {
2611 "48 48 64 1",
2612 "       c None",
2613 ".      c #DF7DCF3CC71B",
2614 "X      c #965875D669A6",
2615 "o      c #71C671C671C6",
2616 "O      c #A699A289A699",
2617 "+      c #965892489658",
2618 "@      c #8E38410330C2",
2619 "#      c #D75C7DF769A6",
2620 "$      c #F7DECF3CC71B",
2621 "%      c #96588A288E38",
2622 "&amp;      c #A69992489E79",
2623 "*      c #8E3886178E38",
2624 "=      c #104008200820",
2625 "-      c #596510401040",
2626 ";      c #C71B30C230C2",
2627 ":      c #C71B9A699658",
2628 ">      c #618561856185",
2629 ",      c #20811C712081",
2630 "<      c #104000000000",
2631 "1      c #861720812081",
2632 "2      c #DF7D4D344103",
2633 "3      c #79E769A671C6",
2634 "4      c #861782078617",
2635 "5      c #41033CF34103",
2636 "6      c #000000000000",
2637 "7      c #49241C711040",
2638 "8      c #492445144924",
2639 "9      c #082008200820",
2640 "0      c #69A618611861",
2641 "q      c #B6DA71C65144",
2642 "w      c #410330C238E3",
2643 "e      c #CF3CBAEAB6DA",
2644 "r      c #71C6451430C2",
2645 "t      c #EFBEDB6CD75C",
2646 "y      c #28A208200820",
2647 "u      c #186110401040",
2648 "i      c #596528A21861",
2649 "p      c #71C661855965",
2650 "a      c #A69996589658",
2651 "s      c #30C228A230C2",
2652 "d      c #BEFBA289AEBA",
2653 "f      c #596545145144",
2654 "g      c #30C230C230C2",
2655 "h      c #8E3882078617",
2656 "j      c #208118612081",
2657 "k      c #38E30C300820",
2658 "l      c #30C2208128A2",
2659 "z      c #38E328A238E3",
2660 "x      c #514438E34924",
2661 "c      c #618555555965",
2662 "v      c #30C2208130C2",
2663 "b      c #38E328A230C2",
2664 "n      c #28A228A228A2",
2665 "m      c #41032CB228A2",
2666 "M      c #104010401040",
2667 "N      c #492438E34103",
2668 "B      c #28A2208128A2",
2669 "V      c #A699596538E3",
2670 "C      c #30C21C711040",
2671 "Z      c #30C218611040",
2672 "A      c #965865955965",
2673 "S      c #618534D32081",
2674 "D      c #38E31C711040",
2675 "F      c #082000000820",
2676 "                                                ",
2677 "          .XoO                                  ",
2678 "         +@#$%o&amp;                                ",
2679 "         *=-;#::o+                              ",
2680 "           >,<12#:34                            ",
2681 "             45671#:X3                          ",
2682 "               +89<02qwo                        ",
2683 "e*                >,67;ro                       ",
2684 "ty>                 459@>+&amp;&amp;                    ",
2685 "$2u+                  ><ipas8*                  ",
2686 "%$;=*                *3:.Xa.dfg>                ",
2687 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
2688 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
2689 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
2690 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
2691 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
2692 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
2693 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
2694 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
2695 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
2696 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
2697 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
2698 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
2699 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
2700 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
2701 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
2702 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
2703 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
2704 "              p;<69BvwwsszslllbBlllllllu<5+     ",
2705 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
2706 "               c1-699Blvlllllu7k96MMMg4         ",
2707 "               *10y8n6FjvllllB<166668           ",
2708 "                S-kg+>666<M<996-y6n<8*          ",
2709 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
2710 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
2711 "                 N-k-<>     >=01-kuu666>        ",
2712 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
2713 "                 Ou0<>       o66y<ulw<66&amp;       ",
2714 "                  *kk5       >66By7=xu664       ",
2715 "                   <<M4      466lj<Mxu66o       ",
2716 "                   *>>       +66uv,zN666*       ",
2717 "                              566,xxj669        ",
2718 "                              4666FF666>        ",
2719 "                               >966666M         ",
2720 "                                oM6668+         ",
2721 "                                  *4            ",
2722 "                                                ",
2723 "                                                "};
2724
2725
2726 /* quando invocata (con il segnale delete_event), termina l'applicazione. */
2727 void close_application( GtkWidget *widget, gpointer *data ) {
2728     gtk_main_quit();
2729 }
2730
2731 int main (int argc, char *argv[])
2732 {
2733     /* il tipo di dato per i widget &egrave; GtkWidget */
2734     GtkWidget *window, *pixmap, *fixed;
2735     GdkPixmap *gdk_pixmap;
2736     GdkBitmap *mask;
2737     GtkStyle *style;
2738     GdkGC *gc;
2739     
2740     /* crea la finestra principale e collega il segnale delete_event per
2741        terminare l'applicazione. Notare che non mettiamo un titolo 
2742        alla finestra. */
2743     gtk_init (&amp;argc, &amp;argv);
2744     window = gtk_window_new( GTK_WINDOW_POPUP );
2745     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2746                         GTK_SIGNAL_FUNC (close_application), NULL);
2747     gtk_widget_show (window);
2748
2749     /* ora occupiamoci della pixmap e del widget pixmap */
2750     style = gtk_widget_get_default_style();
2751     gc = style->black_gc;
2752     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
2753                                              &amp;style->bg[GTK_STATE_NORMAL],
2754                                              WheelbarrowFull_xpm );
2755     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
2756     gtk_widget_show( pixmap );
2757
2758     /* Per mostrare la pixmap, usiamo un widget "fixed" in cui metterla */
2759     fixed = gtk_fixed_new();
2760     gtk_widget_set_usize( fixed, 200, 200 );
2761     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
2762     gtk_container_add( GTK_CONTAINER(window), fixed );
2763     gtk_widget_show( fixed );
2764
2765     /* Questa maschera tutto tranne l'immagine stessa */
2766     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
2767     
2768     /* mostra la finestra */
2769     gtk_widget_set_uposition( window, 20, 400 );
2770     gtk_widget_show( window );
2771     gtk_main ();
2772           
2773     return 0;
2774 }
2775 </verb></tscreen>
2776 <p>
2777 Per rendere sensibile l'immagine della carriola, potremmo collegare
2778 il segnale di pressione del bottone in modo che venga compiuta una certa
2779 azione. Le prossime linee renderebbero l'immagine sensibile alla pressione
2780 di un bottone del mouse che fa s&igrave; che l'applicazione termini.
2781
2782 <tscreen><verb>
2783 gtk_widget_set_events( window,
2784                        gtk_widget_get_events( window ) |
2785                        GDK_BUTTON_PRESS_MASK );
2786
2787 gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
2788                     GTK_SIGNAL_FUNC(close_application), NULL );
2789 </verb></tscreen>
2790
2791 <!-- ----------------------------------------------------------------- -->
2792 <sect1>Righelli
2793 <p>
2794 I widget righello vengono usati per indicare la posizione del pontatore del
2795 mouse in una certa finestra. Una finestra pu&ograve; cio&eacute; avere un
2796 righello orizzontale che si estende per tutta la sua ampiezza e un righello verticale
2797 che ne comprende l'altezza. Un piccolo triangolo sui rghelli indica la posizione
2798 esatta del puntatore relativamente ai righelli.
2799
2800 I righelli devono essere in primo luogo creati. I righlli orizzontali e verticali vengono
2801 creati usando
2802
2803 <tscreen><verb>
2804 GtkWidget *gtk_hruler_new(void);    /* horizontal ruler */
2805 GtkWidget *gtk_vruler_new(void);    /* vertical ruler   */
2806 </verb></tscreen>
2807
2808 Una volta che che si &egrave; creato il righello, si pu&ograve; l'unit&agrave; di
2809 misura. Le unit&agrave; di misura possono essere GTK_PIXELS,
2810 GTK_INCHES oppure GTK_CENTIMETERS. Ci&ograve; viene stabilito usando
2811
2812 <tscreen><verb>
2813 void gtk_ruler_set_metric( GtkRuler        *ruler,
2814                            GtkMetricType   metric );
2815 </verb></tscreen>
2816
2817 La misura predefinita &egrave;  GTK_PIXELS.
2818
2819 <tscreen><verb>
2820 gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
2821 </verb></tscreen>
2822
2823 Altre caratteritiche importanti di un righello sono il modo in cui vengono segnate
2824 le tacche delle unit&agrave; di misura e dove viene posto inizialmente l'indicatore
2825 di posizione. Questi vengono stabiliti usando
2826
2827 <tscreen><verb>
2828 void  gtk_ruler_set_range  (GtkRuler       *ruler,
2829                             gfloat          lower,
2830                             gfloat          upper,
2831                             gfloat          position,
2832                             gfloat          max_size);
2833 </verb></tscreen>
2834
2835 Gli argomenti lower e upper definiscono l'estensione del righello, e
2836 max_size rappresenta il numero massimo che verr&agrave; mostrato.
2837 Position definisce l posizione iniziale dell'indicatore del puntatore 
2838 all'interno del righello.
2839
2840 Quindi, un righello che pu&ograve; stare su una finestra di 800 pixel sar&agrave;:
2841
2842 <tscreen><verb>
2843 gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
2844 </verb></tscreen>
2845
2846 Sul righello saranno presenti dei segni da 0 a 800, con un numero ogni 100 pixel.
2847 Se avessimo invece voluto che il righello fosse andato da 7 a 16, avremmo scritto:
2848
2849 <tscreen><verb>
2850 gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
2851 </verb></tscreen>
2852
2853 L'indicatore sul righello &egrave; un piccolo segno triangolare che indica
2854 la posizione del puntatore rispetto al righello. Se il righello viene usato
2855 per seguire il movimento del mouse, il segnale di motion_notify_event
2856 dovrebbe venir connesso al metodo motion_notify_event del righello.
2857 Per seguire tutti i movimenti del mouse all'interno dell'area di una finestra,
2858 useremmo:
2859
2860 <tscreen><verb>
2861 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
2862
2863 gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
2864          (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
2865          GTK_OBJECT(ruler) );
2866 </verb></tscreen>
2867
2868 L'esempio seguente crea un'area di disegno con un reghello orizzontale nella
2869 parte superiore e un righello verticale nella parte sinistra. Le dimensioni
2870 di questa area di disegno sono di 600 e 400 pixel risettivamente per la larghezza
2871 e per l'altezza. Il righello orizzontale va da 7 a 13 con una tacca ogni 100 pixel,
2872 mentre quello verticale va da 0 a 400, ancora con una tacca ogni 100 pixel.
2873 La sistemazione dell'area di disegno e dei righelli viene fatta usando una tabella.
2874
2875 <tscreen><verb>
2876 /* rulers.c */
2877
2878 #include <gtk/gtk.h>
2879
2880 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
2881
2882 #define XSIZE  600
2883 #define YSIZE  400
2884
2885 /* il controllo raggiunge questa routine quando si preme il bottone close 
2886  */
2887 void close_application( GtkWidget *widget, gpointer *data ) {
2888     gtk_main_quit();
2889 }
2890
2891 /* la routine principale
2892  */
2893 int main( int argc, char *argv[] ) {
2894     GtkWidget *window, *table, *area, *hrule, *vrule;
2895
2896     /* inizializziamo gtk e creiamo la finestra principale */
2897     gtk_init( &amp;argc, &amp;argv );
2898
2899     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2900     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2901             GTK_SIGNAL_FUNC( close_application ), NULL);
2902     gtk_container_border_width (GTK_CONTAINER (window), 10);
2903
2904     /* creiamo una tabella in cui mettere righelli e area di disegno */
2905     table = gtk_table_new( 3, 2, FALSE );
2906     gtk_container_add( GTK_CONTAINER(window), table );
2907
2908     area = gtk_drawing_area_new();
2909     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
2910     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
2911                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
2912     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
2913
2914     /* Il righello orizzontale va nella parte superiore. Quando il mouse si muove
2915      * nell'area di disegno, si passa un motion_notify_event al gestore appropriato
2916      * per il righello. */
2917
2918     hrule = gtk_hruler_new();
2919     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
2920     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
2921     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
2922                                (GtkSignalFunc)EVENT_METHOD(hrule, motion_notify_event),
2923                                GTK_OBJECT(hrule) );
2924     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
2925     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
2926                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
2927     
2928     /* Il righello verticale va nella parte sinistra.  Quando il mouse si muove
2929      * nell'area di disegno, si passa un motion_notify_event al gestore appropriato
2930      * per il righello. */
2931
2932     vrule = gtk_vruler_new();
2933     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
2934     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
2935     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
2936                                (GtkSignalFunc)
2937                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)-motion_notify_event,
2938                                GTK_OBJECT(vrule) );
2939     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
2940                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
2941
2942     /* ora mostriamo tutto quanto */
2943     gtk_widget_show( area );
2944     gtk_widget_show( hrule );
2945     gtk_widget_show( vrule );
2946     gtk_widget_show( table );
2947     gtk_widget_show( window );
2948     gtk_main();
2949
2950     return 0;
2951 }
2952 </verb></tscreen>
2953
2954 <!-- ----------------------------------------------------------------- -->
2955 <sect1>Barre di Stato (Statusbar)
2956 <p>
2957 Le barre di stato sono dei semplici widget usati per mostrare messaggi di test.
2958 Hanno la caratteristica di mantenere uno stack dei messggi che vi vengono
2959 mostrati, cosicche&eacute; rimuovendo il messaggio corrente fa s&igrave; che
2960 torni ad essere mostrato il messaggio precedente..
2961
2962 Per permettere a parti diverse di una stessa applicazione di usare la stessa barra di
2963 stato per mostrare messaggi, questo widget emette degli 'Identificatori di Contesto'
2964 che vengono usati per identificare i diversi 'utenti'. Quello che viene mostrato
2965  &egrave; sempre il messaggio che si trova in cima allo stack, a prescindere in
2966 quale contesto si trovi. I messaggi vengono immagazzinati secondo l'ordine
2967 LIFO, e non secondo l'ordine stabilito dal contesto.
2968
2969 Una barra di stato viene creata con una chiamata a:
2970 <tscreen><verb>
2971 GtkWidget* gtk_statusbar_new (void);
2972 </verb></tscreen>
2973
2974 Per richiedere un nuovo identificatore di contesto, si usa una chiamata alla seguente
2975 funzione con una breve descrizione testuale:
2976 <tscreen><verb>
2977 guint gtk_statusbar_get_context_id (GtkStatusbar *statusbar,
2978                                     const gchar  *context_description);
2979 </verb></tscreen>
2980
2981 Le seguenti sono tre funzioni che possono operare sulle barre di stato:
2982 <tscreen><verb>
2983 guint       gtk_statusbar_push           (GtkStatusbar *statusbar,
2984                                          guint          context_id,
2985                                          gchar         *text);
2986
2987 void       gtk_statusbar_pop            (GtkStatusbar *statusbar)
2988                                          guint         context_id);
2989 void       gtk_statusbar_remove         (GtkStatusbar *statusbar,
2990                                          guint         context_id,
2991                                          guint         message_id); 
2992 </verb></tscreen>
2993
2994 La prima, gtk_statusbar_push, viene usata per aggiungere un nuovo messaggio
2995 alla barra di stato. Questa restituisce un identificatore di messaggio, che pu&ograve;
2996 essere passato successivamente alla funzione gtk_statusbar_remove per rimuovere
2997 dallo stack il messggio con identificatore di messaggio e di contesto dati.
2998
2999 La funzione gtk_statusbar_pop rimuove il messaggio che si trova in cima allo stack
3000 avente un dato identificatore di contesto.
3001
3002 Nel seguente esempio si crea una barra di stato e due bottoni, uno per mettere
3003 elementi sulla barra di stato e l'altro per riuovere l'ultimo elemento..
3004
3005 <tscreen><verb>
3006 /* statusbar.c */
3007
3008 #include <gtk/gtk.h>
3009 #include <glib.h>
3010
3011 GtkWidget *status_bar;
3012  
3013 void push_item (GtkWidget *widget, gpointer *data)
3014 {
3015   static int count = 1;
3016   char buff[20];
3017
3018   g_snprintf(buff, 20, "Item %d", count++);
3019   gtk_statusbar_push( GTK_STATUSBAR(status_bar), (guint) &amp;data, buff);
3020
3021   return;
3022 }
3023
3024 void pop_item (GtkWidget *widget, gpointer *data)
3025 {
3026   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), (guint) &amp;data );
3027   return;
3028 }
3029
3030 int main (int argc, char *argv[])
3031 {
3032
3033     GtkWidget *window;
3034     GtkWidget *vbox;
3035     GtkWidget *button;
3036
3037     int context_id;
3038
3039     gtk_init (&amp;argc, &amp;argv);
3040
3041     /* creazione di una nuova finestra */
3042     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
3043     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
3044     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
3045     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
3046                        (GtkSignalFunc) gtk_exit, NULL);
3047  
3048     vbox = gtk_vbox_new(FALSE, 1);
3049     gtk_container_add(GTK_CONTAINER(window), vbox);
3050     gtk_widget_show(vbox);
3051           
3052     status_bar = gtk_statusbar_new();      
3053     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
3054     gtk_widget_show (status_bar);
3055
3056     context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");
3057
3058     button = gtk_button_new_with_label("push item");
3059     gtk_signal_connect(GTK_OBJECT(button), "clicked",
3060         GTK_SIGNAL_FUNC (push_item), &amp;context_id);
3061     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
3062     gtk_widget_show(button);              
3063
3064     button = gtk_button_new_with_label("pop last item");
3065     gtk_signal_connect(GTK_OBJECT(button), "clicked",
3066         GTK_SIGNAL_FUNC (pop_item), &amp;context_id);
3067     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
3068     gtk_widget_show(button);              
3069
3070     /* la finestra va sempre mostrata come ultimo passo, in modo che venga
3071      * sullo schermo tutta in una volta. */
3072     gtk_widget_show(window);
3073
3074     gtk_main ();
3075
3076     return 0;
3077 }
3078 </verb></tscreen>
3079
3080 <!-- ----------------------------------------------------------------- -->
3081 <sect1>Inserimento di testo
3082 <p>
3083 Questo widget permette diinserire e mostrare del testo in una casella contenente una
3084 sola linea. Il testo pu&ograve; essere assegnato con chiamate di funzione che
3085 permettono a nuovo testo di sostituire, seguire o precedere il contenuto corrente
3086 del widget di inserimento testo.
3087
3088 Per la creazione di un inserimento di testo, sono disponibili due funzioni:
3089 <tscreen><verb>
3090 GtkWidget* gtk_entry_new (void);
3091
3092 GtkWidget* gtk_entry_new_with_max_length (guint16 max);
3093 </verb></tscreen>
3094
3095 La prima crea solamente un inserimento di testo, mentre la seconda lo crea
3096 imponendo un limite alla lunghezza del testo inseribile..
3097
3098 Per cambiaere il testo che si trova correntemente nel widget, sono disponibili diverse
3099 funzioni.
3100 <tscreen><verb>
3101 void gtk_entry_set_text       (GtkEntry    *entry,
3102                                const gchar *text);
3103 void gtk_entry_append_text    (GtkEntry    *entry,
3104                                const gchar *text);
3105 void gtk_entry_prepend_text   (GtkEntry    *entry,
3106                                const gchar *text);
3107 </verb></tscreen>
3108
3109 La funzione gtk_entry_set_text assegna il contenuto del widget di inserimento,
3110 sostituendo il contenuto corrente. Le funzioni gtk_entry_append_text e gtk_entry_prepend_text
3111 permettono di antemporre o posporre un testo al testo corrente..
3112
3113 La prossima funzione permette di stabilire il punto di inserimento.
3114 <tscreen><verb>
3115 void gtk_entry_set_position   (GtkEntry *entry,
3116                                gint     position);
3117 </verb></tscreen>
3118
3119 Usando la seguente funzione, &egrave; possibile estrarre il contenuto di un widget di inserimento.
3120 Ci&ograve; pu&ograve; essere utile nelle funzioni di ritorno come descritto pi&ugrave; sotto.
3121 <tscreen><verb>
3122 gchar* gtk_entry_get_text (GtkEntry *entry);
3123 </verb></tscreen>
3124
3125 Se non si vuole che qualcuno possa cambiare il contenuto di una entry sovrascrivendola,
3126 ne possiamo cambiare lo stato di "editabilit&agrave;"..
3127 <tscreen><verb>
3128 void gtk_entry_set_editable (GtkEntry *entry,
3129                              gboolean editable);
3130 </verb></tscreen>
3131
3132 Questa funzine ci permette di far passare un widget di inserimento dallo sato di editabile a
3133 quello di non editabile passando con l'argomento editable i valori TRUE o FALSE.
3134
3135 Se stiamo usando l'entry in un punto in cui non vogliamo che il testo sia visibile, per
3136 esempio quando si digita una password, possiamo usare la seguente funzione, che
3137 accetta un parametro booleano..
3138 <tscreen><verb>
3139 void gtk_entry_set_visibility (GtkEntry *entry,
3140                                gboolean visible);
3141 </verb></tscreen>
3142
3143 Si pu&ograve; stabilire che una parte del testo  risulti selezionata usado la seguente funzione.
3144 Si user&agrave; di solito questa possibilit&agrave; dopo aver inserito nel widget un
3145 qualche valore predefinito, in modo che per l'utente sia semplice sostituirlo. 
3146
3147 <tscreen><verb>
3148 void gtk_entry_select_region (GtkEntry *entry,
3149                               gint     start,
3150                               gint     end);
3151 </verb></tscreen>
3152
3153 Se vogliamo accorgerci del momento in cui l'utente ha inserito del testo, possiamo connettere
3154 il segnale <tt/activate/ o <tt/changed/. <tt/activate/ viene reso attivo quando
3155 l'utente preme il tasto Enter mentre si trova nel widget. <tt/changed/ viene invece emesso ogni volta che
3156 il testo cambia, per esempio ogni volta che viene inserito o rimosso un carattere.
3157
3158 Il seguente codice mostra un esempio di utilizzo del widget di inserimento.
3159 .
3160 <tscreen><verb>
3161 /* entry.c */
3162
3163 #include <gtk/gtk.h>
3164
3165 void enter_callback(GtkWidget *widget, GtkWidget *entry)
3166 {
3167   gchar *entry_text;
3168   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
3169   printf("Entry contents: %s\n", entry_text);
3170 }
3171
3172 void entry_toggle_editable (GtkWidget *checkbutton,
3173                                    GtkWidget *entry)
3174 {
3175   gtk_entry_set_editable(GTK_ENTRY(entry),
3176                          GTK_TOGGLE_BUTTON(checkbutton)->active);
3177 }
3178
3179 void entry_toggle_visibility (GtkWidget *checkbutton,
3180                                    GtkWidget *entry)
3181 {
3182   gtk_entry_set_visibility(GTK_ENTRY(entry),
3183                          GTK_TOGGLE_BUTTON(checkbutton)->active);
3184 }
3185
3186 int main (int argc, char *argv[])
3187 {
3188
3189     GtkWidget *window;
3190     GtkWidget *vbox, *hbox;
3191     GtkWidget *entry;
3192     GtkWidget *button;
3193     GtkWidget *check;
3194
3195     gtk_init (&amp;argc, &amp;argv);
3196
3197     /* creiamo una nuova finestra */
3198     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
3199     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
3200     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
3201     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
3202                        (GtkSignalFunc) gtk_exit, NULL);
3203
3204     vbox = gtk_vbox_new (FALSE, 0);
3205     gtk_container_add (GTK_CONTAINER (window), vbox);
3206     gtk_widget_show (vbox);
3207
3208     entry = gtk_entry_new_with_max_length (50);
3209     gtk_signal_connect(GTK_OBJECT(entry), "activate",
3210                        GTK_SIGNAL_FUNC(enter_callback),
3211                        entry);
3212     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
3213     gtk_entry_append_text (GTK_ENTRY (entry), " world");
3214     gtk_entry_select_region (GTK_ENTRY (entry),
3215                              0, GTK_ENTRY(entry)->text_length);
3216     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
3217     gtk_widget_show (entry);
3218
3219     hbox = gtk_hbox_new (FALSE, 0);
3220     gtk_container_add (GTK_CONTAINER (vbox), hbox);
3221     gtk_widget_show (hbox);
3222                                   
3223     check = gtk_check_button_new_with_label("Editable");
3224     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
3225     gtk_signal_connect (GTK_OBJECT(check), "toggled",
3226                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
3227     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
3228     gtk_widget_show (check);
3229     
3230     check = gtk_check_button_new_with_label("Visible");
3231     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
3232     gtk_signal_connect (GTK_OBJECT(check), "toggled",
3233                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
3234     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
3235     gtk_widget_show (check);
3236                                    
3237     button = gtk_button_new_with_label ("Close");
3238     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3239                                GTK_SIGNAL_FUNC(gtk_exit),
3240                                GTK_OBJECT (window));
3241     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
3242     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3243     gtk_widget_grab_default (button);
3244     gtk_widget_show (button);
3245     
3246     gtk_widget_show(window);
3247
3248     gtk_main();
3249     return(0);
3250 }
3251 </verb></tscreen>
3252
3253 <!-- ----------------------------------------------------------------- -->
3254 <sect1> Selettori di Colore
3255 <P>
3256 Il widget selettore di colore &egrave; chiaramente un widget che permtte di
3257 scegliere interattivamente dei colori. Questo widget composto permette all'utente
3258 di selezionare un colore agendo su terne RGB (Red, Green, Blue) e HSV
3259 (Hue, Saturation, Value). Questo lo si pu&ograve; fare o agendo sui singoli valori
3260 tramite degli slider o inserendoli da tastiera, oppure selezionando direttamente il
3261 colore da un cerchio (valori H e S) e da una barra (valore V). 
3262 Opzionalmente, &egrave; possibile anche stabilire il grado di trasparenza del
3263 colore.
3264 Il widget di selezione di colore emette per ora un solo segnale, "color_changed", che
3265 viene generato ogni volta che il colore corrente nel widget cambia, sia quando
3266 &egrave; l'utente a cambiarlo, sia quando viene modificato esplicitamente tramite
3267 una chiamata a gtk_color_selection_set_color().
3268
3269 Diamo ora un'occhiata a cosa ha da offrirci il widget di selezione di colore. 
3270 Il widget &egrave; disponibile in due versioni, gtk_color_selection e
3271 gtk_color_selection_dialog:
3272
3273 <tscreen><verb>
3274 GtkWidget *gtk_color_selection_new(void);
3275 </verb></tscreen>
3276         
3277 E' probabile che non userete questo costruttore direttamente. Infatti esso crea un
3278 widget GtkColorSelection orfano a cui dovrete assegnare un genitore voi stessi.
3279 Il widget GtkColorSelection  eredita dal widget GtkVBox. 
3280
3281 <tscreen><verb> 
3282 GtkWidget *gtk_color_selection_dialog_new(const gchar *title);
3283 </verb></tscreen>
3284
3285 Questo &egrave; il pi&ugrave; comune fra i costruttori di selettori di colore. Esso
3286 crea un GtkColorSelectionDialog, che eredita da GtkDialog. Esso consiste di un
3287 GtkFrame che contiene un widget GtkColorSelection, un GtkHSeparator e un
3288 GtkHBox con tre bottoni, "Ok", "Cancel" e "Help". Si arriva a questi bottoni
3289 accedendo ai widget "ok_button", "cancel_button" e "help_button" nella 
3290 struttura GtkColorSelectionDialog (cio&egrave;  (GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
3291
3292 <tscreen><verb>
3293 void gtk_color_selection_set_update_policy(GtkColorSelection *colorsel, 
3294                                            GtkUpdateType policy);
3295 </verb></tscreen>
3296
3297 Questa funzione stabilisce la politica di aggiornamento. Quella predefinita &egrave;
3298 GTK_UPDATE_CONTINOUS, che significa che il colore viene aggiornato
3299 continuamente mano a mano che l'utente trascina gli slider o preme e trascina il
3300 mouse nel cerchio della hue-saturation o nella relativa barra. Se si hanno problemi
3301 di prestazioni, si pu&ograve; decidere di usare la politica
3302 GTK_UPDATE_DISCONTINOUS
3303 o GTK_UPDATE_DELAYED.
3304
3305 <tscreen><verb>
3306 void gtk_color_selection_set_opacity(GtkColorSelection *colorsel,
3307                                      gint use_opacity);
3308 </verb></tscreen>
3309
3310 Il widget di selezione di colore permette anche di variare l'opacit&agrave; di un
3311 colore (conosciuta anche come canale alfa). Questa caratteristica &egrave; 
3312 normalmente disabilitata. Chiamare la precedente funzione, con use_opacity uguale
3313 a TRUE abilita la manipolazione dell'opacit&agrave;. Analogamente, mettendo
3314 use_opacity uguale a FALSE la disabiliter&agrave;.
3315
3316 <tscreen><verb>
3317 void gtk_color_selection_set_color(GtkColorSelection *colorsel,
3318                                    gdouble *color);
3319 </verb></tscreen>
3320
3321 Si pu&ograve; assegnare esplicitamente un colore chiamando questa funzione
3322 con un puntatore ad un vettore di colori (gdouble). La lunghezza del vettore
3323 dipende dall'attivazione o meno del controllo dell'opacit&agrave;. La posizione 0
3324 contiene la componente rossa, la 1 &grave; il verde, la 2 il blu e la 3 contiene
3325 l'opacit&agrave; (se questa &grave; attivata, come si &egrave; detto per
3326 gtk_color_selection_set_opacity()). Tutti i valori sono compresi fra 0.0 e 1.0.
3327
3328 <tscreen><verb>
3329 void gtk_color_selection_get_color(GtkColorSelection *colorsel,
3330                                    gdouble *color);
3331 </verb></tscreen>
3332
3333 Questa funzione viene usata per ottenere il colore corrente, tipicamente quando
3334 si &egrave; ricevuto il segnale "color_changed". Color &egrave; un puntatore al
3335 vettore di colori da riempire. Vedi la descrizione di questo vettore nella funzione
3336 gtk_color_selection_set_color().
3337
3338 <!-- C'e' bisogno di una sezione sul DnD - TRG
3339
3340 Il Drag and Drop
3341 ----------------
3342
3343 Le aree con l'esempio del colore (sotto il cerchio H-S) supportano il drag and drop.
3344 Il tipo del drag and drop &egrave; "application/x-color". I dati del messaggio sono
3345 costituiti da un vettore di 4 valori gdouble (o 5 nel caso di attivazione
3346 dell'opacit&agrave;), in cui il valore alla posizione 0 &grave; pu&ograve;
3347 essere 0.0 (opacit&agrave; attivata) o 1.0 (disattivata) seguito dal rosso,
3348 dal verde e dal blu alle posizioni 1,2 e 3. Nel caso di opacit&agrave; attiva,
3349 il suo valore &egrave; passato alla posizione 4.
3350 -->
3351
3352 Ecco un semplice esempio che mostra l'uso di  GtkColorSelectionDialog.
3353 Il programma mostra una finestra che contiene un'area di disegno. Cliccandoci
3354 sopra, si apre un dialogo di selezione di colore, e se si modifica il colore
3355 nella finestra di dialogo verr&agrave; cambiato anche il colore dello sfondo.
3356
3357 <tscreen><verb>
3358 #include <glib.h>
3359 #include <gdk/gdk.h>
3360 #include <gtk/gtk.h>
3361
3362 GtkWidget *colorseldlg = NULL;
3363 GtkWidget *drawingarea = NULL;
3364
3365 /* gestore del cambiamento del colore */
3366
3367 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
3368 {
3369   gdouble color[3];
3370   GdkColor gdk_color;
3371   GdkColormap *colormap;
3372
3373   /* recupera la colormap dell'area di disegno */
3374
3375   colormap = gdk_window_get_colormap (drawingarea->window);
3376
3377   /* recupera il colore corrente */
3378
3379   gtk_color_selection_get_color (colorsel,color);
3380
3381   /* adattamento ad un intero unsigned di 16 bit (0..65535)
3382    * e inseriscili nella struttura GdkColor */
3383
3384   gdk_color.red = (guint16)(color[0]*65535.0);
3385   gdk_color.green = (guint16)(color[1]*65535.0);
3386   gdk_color.blue = (guint16)(color[2]*65535.0);
3387
3388   /* Alloca il colore */
3389
3390   gdk_color_alloc (colormap, &amp;gdk_color);
3391
3392   /* assegna il colore di sfondo della finestra */
3393
3394   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
3395
3396   /* pulisce la finestra */
3397
3398   gdk_window_clear (drawingarea->window);
3399 }
3400
3401 /* gestore per l'area di disegno */
3402
3403 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
3404 {
3405   gint handled = FALSE;
3406   GtkWidget *colorsel;
3407
3408   /* controlliamo se abbiamo ricevuto un evento di pressione di pulsante */
3409
3410   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
3411     {
3412       /* Si , c'e' l'evento e ancora non c'e' alcun colorseldlg! */
3413
3414       handled = TRUE;
3415
3416       /* Creiamo una finestra di dialogo per la selezione del colore */
3417
3418       colorseldlg = gtk_color_selection_dialog_new("Select background color");
3419
3420       /* Otteniamo il widget GtkColorSelection */
3421
3422       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
3423
3424       /* Facciamo la connessione al segnale "color_changed",
3425        * ed assegnamo i dati-utente al widget di selezione di colore */
3426
3427       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
3428         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
3429
3430       /* Mostriamo il dialogo */
3431
3432       gtk_widget_show(colorseldlg);
3433     }
3434
3435   return handled;
3436 }
3437
3438 /* Chiusura ed uscita dal getore */
3439
3440 void destroy_window (GtkWidget *widget, gpointer client_data)
3441 {
3442   gtk_main_quit ();
3443 }
3444
3445 /* Main */
3446
3447 gint main (gint argc, gchar *argv[])
3448 {
3449   GtkWidget *window;
3450
3451   /* Inizialliziamo il toolkit, remuoviamo gli argomenti sulla linea di
3452    * comando legati a gtk */
3453
3454   gtk_init (&amp;argc,&amp;argv);
3455
3456   /* creiamo la finestra base, con titolo e politiche */
3457
3458   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3459   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
3460   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
3461
3462   /* colleghiamo gli eventi "delete" e "destroy" per poter uscire */
3463
3464   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
3465     (GtkSignalFunc)destroy_window, (gpointer)window);
3466
3467   gtk_signal_connect (GTK_OBJECT(window), "destroy",
3468     (GtkSignalFunc)destroy_window, (gpointer)window);
3469   
3470   /* crea un'area di disegna, stabilisce le dimensioni e raccogli 
3471    * gli eventi */
3472
3473   drawingarea = gtk_drawing_area_new ();
3474
3475   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
3476
3477   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
3478
3479   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
3480     (GtkSignalFunc)area_event, (gpointer)drawingarea);
3481   
3482   /* aggiungi l'area di disegno alla finestra e mostrale entrambe */
3483
3484   gtk_container_add (GTK_CONTAINER(window), drawingarea);
3485
3486   gtk_widget_show (drawingarea);
3487   gtk_widget_show (window);
3488   
3489   /* entra nel ciclo principale di gtk (che non cede mai il controllo */
3490
3491   gtk_main ();
3492
3493   /* soddisfa i compilatori brontoloni */
3494
3495   return 0;
3496 }
3497 </verb></tscreen>
3498
3499 <!-- ----------------------------------------------------------------- -->
3500 <sect1> Selezione di File (File Selections)
3501
3502 <p>
3503 Il widget Selezione di File &egrave; un modo rapido e semplice per mostrare una
3504 finestra di dialogo `File'. Questa si presenta completa di bottoni Ok,
3505 Cancel e Help, un buon modo per tagliare i tempi di programmazione.
3506
3507 Per creare una nuova finestra di selezione file usate:
3508
3509 <tscreen><verb>
3510 GtkWidget* gtk_file_selection_new (gchar *title);
3511 </verb></tscreen>
3512
3513 Per assegnare il nome del file, ad esempio per predisporre una certa
3514 directory o per dare un certo nome di file per difetto, usate la seguente
3515 funzione:
3516
3517 <tscreen><verb>
3518 void gtk_file_selection_set_filename (GtkFileSelection *filesel, gchar *filename);
3519 </verb></tscreen>
3520
3521 Per recuperare il testo che l'utente ha inserito o che ha selezionato con
3522 il mouse, si usa la funzione:
3523
3524 <tscreen><verb>
3525 gchar* gtk_file_selection_get_filename (GtkFileSelection *filesel);
3526 </verb></tscreen>
3527
3528 Ci sono anche dei puntatori ai widget che sono contenuti all'interno
3529 del widget di selezione file. Si tratta di:
3530
3531 <itemize>
3532 <item>dir_list
3533 <item>file_list
3534 <item>selection_entry
3535 <item>selection_text
3536 <item>main_vbox
3537 <item>ok_button
3538 <item>cancel_button
3539 <item>help_button
3540 </itemize>
3541
3542 Molto probabilmente potreste voler usare i puntatori a ok_button,
3543 cancel_button e help_button per segnalarne l'uso.
3544
3545 Ecco un esempio rubato da testgtk.c, nodificato per essere eseguito da
3546 solo. Come potrete vedere, non c'&egrave; molto pi&ugrave; che la creazione di un
3547 widget di selezione file. In questo esempio, il bottone Help non fa nulla
3548 mentre &egrave; mostrato allo schermo, dal momento che non c'&egrave; alcun segnale
3549 collegato con esso. 
3550
3551 <tscreen><verb>
3552 /* filesel.c */
3553
3554 #include <gtk/gtk.h>
3555
3556 /* Recupera il nome di file selezionato e stampalo a console */
3557 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
3558 {
3559     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
3560 }
3561
3562 void destroy (GtkWidget *widget, gpointer *data)
3563 {
3564     gtk_main_quit ();
3565 }
3566
3567 int main (int argc, char *argv[])
3568 {
3569     GtkWidget *filew;
3570     
3571     gtk_init (&amp;argc, &amp;argv);
3572     
3573     /* Crea un nuovo widget di selezione file */
3574     filew = gtk_file_selection_new ("File selection");
3575     
3576     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
3577                         (GtkSignalFunc) destroy, &amp;filew);
3578     /* Connette ok_button alla funzione file_ok_sel */
3579     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
3580                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
3581     
3582     /* Connette cancel_button alla funzione di distruzione del widget */
3583     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
3584                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
3585                                GTK_OBJECT (filew));
3586     
3587     /* Preassegnamo un nome di file, come se stessimo dando un valore per difetto in 
3588     dialogo di tipo `` salva con nome '' */
3589     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
3590                                      "penguin.png");
3591     
3592     gtk_widget_show(filew);
3593     gtk_main ();
3594     return 0;
3595 }
3596 </verb></tscreen>
3597
3598 <!-- ***************************************************************** -->
3599 <sect> Widget Contenitore
3600 <!-- ***************************************************************** -->
3601
3602 <!-- ----------------------------------------------------------------- -->
3603 <sect1> Il widget Blocco Note (Notebook)
3604 <p>
3605 Il widget Blocco note &egrave; un insieme di pagine sovrapposte l'una con l'altra, 
3606 ognuna contente cose diverse. Questo widget &egrave; diventato molto comune nella
3607 programmazione delle interfacce utente ed &egrave; un buon metodo per mostrare informazioni
3608 tra loro correlate ma che debbano essere mostrate separatamente.
3609
3610 <p>
3611 La prima funzione da invocare che si deve conoscere, come si pu&ograve; intuire, &egrave; usata
3612 per creare un nuovo Blocco Note.
3613
3614 <tscreen><verb>
3615 GtkWidget* gtk_notebook_new (void);
3616 </verb></tscreen>
3617
3618 Una volta che il notebook &egrave; sato creato, ci sono 12 funzioni che possono
3619 operare sul widget notebook. Guardiamole individualmente.
3620
3621 La prima che vediamo riguarda come posizionare l'indicatore di pagina.
3622 Questi inidicatori di pagina o ``linguette'' (come possono anche essere chiamati)
3623 possono essere posizionati in quattro posti: alto, basso, sinistra.destra.
3624
3625 <tscreen><verb>
3626 void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos);
3627 </verb></tscreen>
3628
3629 GtkPositionType sar&agrave; uno dei seguenti valori (molto autoesplicativi)
3630 <itemize>
3631 <item> GTK_POS_LEFT
3632 <item> GTK_POS_RIGHT
3633 <item> GTK_POS_TOP
3634 <item> GTK_POS_BOTTOM
3635 </itemize>
3636
3637 GTK_POS_TOP e' il valore predefinito.
3638
3639 Ora vediamo come aggiugere le pagine al Blocco Note. Ci sono 3 modi per farlo. Diamo
3640 un'occhiata ai primi due insieme, viste che sono molto simili.
3641
3642 <tscreen><verb>
3643 void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label);
3644
3645 void gtk_notebook_prepend_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label);
3646 </verb></tscreen>
3647
3648 Queste funzioni aggiungono pagine al notebook inserendole rispettivamente alla fine
3649 (append) o all'inizio (prepend). *child &egrave; il widget che &egrave; posto nella pagina del
3650 notebook e *tab_label e la intestazione della pagina stessa.
3651
3652 L'ultima funzione per aggiungere una pagina al notebook contiene tutte le propriet&agrave;
3653 delle precedenti due, ma permette di specificare dove posizionare la pagina che
3654 si vuole inserire.
3655
3656 <tscreen><verb>
3657 void gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label, gint position);
3658 </verb></tscreen>
3659
3660 I parametri sono gli stessi di _append_ e _prepend_ tranne che per il parametro in
3661 pi&ugrave;: ``position''. 
3662 Questo parametro viene usato per specificare in che posizione ineserire la pagina.
3663
3664 Ora che conosciamo come aggiungere le pagine, vediamo come poter toglierne una.
3665
3666 <tscreen><verb>
3667 void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num);
3668 </verb></tscreen>
3669
3670 Questa funzione prende il numero della pagina specificata dal campo page_num e
3671 rimuove la pagina corrispondente dal Blocco Note.
3672
3673 Per trovare qual'&egrave; la pagina corrente nel notebook bisogna usare la funzione:
3674
3675 <tscreen><verb>
3676 gint gtk_notebook_current_page (GtkNotebook *notebook);
3677 </verb></tscreen>
3678
3679 Le prossime due funzioni sono semplicemente delle chiamate che muovono la pagina del 
3680 notebook avanti o indietro. Semplicemente forniscono le chiamate alle rispettive
3681 funzioni del widget notebook su si pu&ograve; operare. NB: quando un notebook &egrave;
3682 correntemente sull'ultima pagina e viene invocata la funzione gtk_notebook_next_page,
3683 il notebook ritorner&agrave; automaticamente alla prima pagina. Logicamente succede anche
3684 il contrario quando invochi gtk_notebook_prev_page e ti trovi sulla prima pagina.
3685
3686 <tscreen><verb>
3687 void gtk_notebook_next_page (GtkNoteBook *notebook);
3688 void gtk_notebook_prev_page (GtkNoteBook *notebook);
3689 </verb></tscreen>
3690
3691 La prossima funzione stabilisce la pagina ``attiva''. Se si vuole che la pagina
3692 principale del notebook sia per esempio la 5 (ad esempio) si pu&ograve; usare questa
3693 funzione.
3694 Se non si usa questa funzione la pagina principale sar&agrave; la 1.
3695
3696 <tscreen><verb>
3697 void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num);
3698 </verb></tscreen>
3699
3700 Le prossime due funzioni aggiungono o rimuovono, rispettivamente, le intestazioni e
3701 i bordi delle pagine.
3702
3703 <tscreen><verb>
3704 void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs);
3705 void gtk_notebook_set_show_border (GtkNotebook *notebook, gint show_border);
3706 </verb></tscreen>
3707
3708 show_tabs e show_border posso avere come valore TRUE o FALSE (0 or 1).
3709
3710 Diamo ora una occhiata ad un esempio. Si tratta di una espansione del codice preso
3711 dal file testgtk.c che &egrave; compreso in tutte le distribuzioni, e mostra 
3712 tutte le 13 funzioni. Questo piccolo programma crea una finestra con un notebook
3713 e 6 bottoni. Il notebook contiene 11 pagine, aggiunte nei 3 modi differenti (alla
3714 fine, all'inizio o in qualsiasi posizione). I bottoni permettono di girare le 
3715 intestazioni, aggiungere/rimuovere le intestazioni e i bordi, rimuovere una 
3716 pagina, cambiare la pagina avanti e indietro e uscire dal programma.
3717
3718 <tscreen><verb>
3719 /* notebook.c */
3720
3721 #include <gtk/gtk.h>
3722
3723 /* Queta funzione ruota le posizione delle linguette delle pagine */
3724 void rotate_book (GtkButton *button, GtkNotebook *notebook)
3725 {
3726     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
3727 }
3728
3729 /* Aggiunge e rimuove le linguette e i bordi */
3730 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
3731 {
3732     gint tval = FALSE;
3733     gint bval = FALSE;
3734     if (notebook->show_tabs == 0)
3735             tval = TRUE; 
3736     if (notebook->show_border == 0)
3737             bval = TRUE;
3738     
3739     gtk_notebook_set_show_tabs (notebook, tval);
3740     gtk_notebook_set_show_border (notebook, bval);
3741 }
3742
3743 /* Rimuove una pagina */
3744 void remove_book (GtkButton *button, GtkNotebook *notebook)
3745 {
3746     gint page;
3747     
3748     page = gtk_notebook_current_page(notebook);
3749     gtk_notebook_remove_page (notebook, page);
3750     /* E' necessario fare un refresh del widget --
3751        Questo forza il widget a ridisegnarsi. */
3752     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
3753 }
3754
3755 void delete (GtkWidget *widget, gpointer *data)
3756 {
3757     gtk_main_quit ();
3758 }
3759
3760 int main (int argc, char *argv[])
3761 {
3762     GtkWidget *window;
3763     GtkWidget *button;
3764     GtkWidget *table;
3765     GtkWidget *notebook;
3766     GtkWidget *frame;
3767     GtkWidget *label;
3768     GtkWidget *checkbutton;
3769     int i;
3770     char bufferf[32];
3771     char bufferl[32];
3772     
3773     gtk_init (&amp;argc, &amp;argv);
3774     
3775     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3776     
3777     gtk_signal_connect (GTK_OBJECT (window), "destroy",
3778                         GTK_SIGNAL_FUNC (destroy), NULL);
3779     
3780     gtk_container_border_width (GTK_CONTAINER (window), 10);
3781     
3782     table = gtk_table_new(2,6,TRUE);
3783     gtk_container_add (GTK_CONTAINER (window), table);
3784     
3785     /* Crea un nuovo notebook, e tabilisce la posizione delle linguette */
3786     notebook = gtk_notebook_new ();
3787     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
3788     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
3789     gtk_widget_show(notebook);
3790     
3791     /* appende una parte delle pagine */
3792     for (i=0; i < 5; i++) {
3793         sprintf(bufferf, "Append Frame %d", i+1);
3794         sprintf(bufferl, "Page %d", i+1);
3795         
3796         frame = gtk_frame_new (bufferf);
3797         gtk_container_border_width (GTK_CONTAINER (frame), 10);
3798         gtk_widget_set_usize (frame, 100, 75);
3799         gtk_widget_show (frame);
3800         
3801         label = gtk_label_new (bufferf);
3802         gtk_container_add (GTK_CONTAINER (frame), label);
3803         gtk_widget_show (label);
3804         
3805         label = gtk_label_new (bufferl);
3806         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
3807     }
3808     
3809     
3810     /* Ora aggiungiamo una pagina in una certa posizione */
3811     checkbutton = gtk_check_button_new_with_label ("Check me please!");
3812     gtk_widget_set_usize(checkbutton, 100, 75);
3813     gtk_widget_show (checkbutton);
3814     
3815     label = gtk_label_new ("Add spot");
3816     gtk_container_add (GTK_CONTAINER (checkbutton), label);
3817     gtk_widget_show (label);
3818     label = gtk_label_new ("Add page");
3819     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
3820     
3821     /* Ora finalmente aggiungiamo le pagine all'inizio */
3822     for (i=0; i < 5; i++) {
3823         sprintf(bufferf, "Prepend Frame %d", i+1);
3824         sprintf(bufferl, "PPage %d", i+1);
3825         
3826         frame = gtk_frame_new (bufferf);
3827         gtk_container_border_width (GTK_CONTAINER (frame), 10);
3828         gtk_widget_set_usize (frame, 100, 75);
3829         gtk_widget_show (frame);
3830         
3831         label = gtk_label_new (bufferf);
3832         gtk_container_add (GTK_CONTAINER (frame), label);
3833         gtk_widget_show (label);
3834         
3835         label = gtk_label_new (bufferl);
3836         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
3837     }
3838     
3839     /* Stabilisce quale sar&agrave; la prima pagina che sar&agrave; visualizzata. */
3840     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
3841     
3842     
3843     /* Crea un set di bottoni */
3844     button = gtk_button_new_with_label ("close");
3845     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3846                                GTK_SIGNAL_FUNC (delete), NULL);
3847     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
3848     gtk_widget_show(button);
3849     
3850     button = gtk_button_new_with_label ("next page");
3851     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3852                                (GtkSignalFunc) gtk_notebook_next_page,
3853                                GTK_OBJECT (notebook));
3854     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
3855     gtk_widget_show(button);
3856     
3857     button = gtk_button_new_with_label ("prev page");
3858     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3859                                (GtkSignalFunc) gtk_notebook_prev_page,
3860                                GTK_OBJECT (notebook));
3861     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
3862     gtk_widget_show(button);
3863     
3864     button = gtk_button_new_with_label ("tab position");
3865     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3866                                (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
3867     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
3868     gtk_widget_show(button);
3869     
3870     button = gtk_button_new_with_label ("tabs/border on/off");
3871     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3872                                (GtkSignalFunc) tabsborder_book,
3873                                GTK_OBJECT (notebook));
3874     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
3875     gtk_widget_show(button);
3876     
3877     button = gtk_button_new_with_label ("remove page");
3878     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3879                                (GtkSignalFunc) remove_book,
3880                                GTK_OBJECT(notebook));
3881     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
3882     gtk_widget_show(button);
3883     
3884     gtk_widget_show(table);
3885     gtk_widget_show(window);
3886     
3887     gtk_main ();
3888     
3889     return 0;
3890 }
3891 </verb></tscreen>
3892 <p>
3893 E speriamo che questo vi aiuti a creare i Blocco Note per le vostre applicazioni GTK!
3894
3895 <!-- ----------------------------------------------------------------- -->
3896 <sect1> Finestre Scorribili (Scrolled Windows)
3897 <p>
3898 Le Finestre Scorribili sono usate per creare areee scorribili in una vera finestra.
3899 Si pu&ograve; inserire qualsiasi tipo di widget in questo tipo di finestra, e possono poi 
3900 essere accessibili a prescindere dalle dimensioni usando le barre di scorrimento.
3901
3902 La funzione seguente &egrave; usata per creare una nuova scrolled window.
3903
3904 <tscreen><verb>
3905 GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment,
3906                                     GtkAdjustment *vadjustment);
3907 </verb></tscreen>
3908 <p>
3909 Il primo argomento &egrave; l'aggiustamento (di quanto scendere ogni
3910 volta) orizzontale e il secondo &egrave; quello verticale.  A questi si assegna
3911 quasi sempre il valore NULL.
3912
3913
3914 <tscreen><verb>
3915 void gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window,
3916                                      GtkPolicyType      hscrollbar_policy,
3917                      GtkPolicyType      vscrollbar_policy);
3918 </verb></tscreen>
3919
3920 Questa funzione stabilisce la politica da usare nella barra di scorrimento. Il primo
3921 argomento &egrave; la finestra scorribile interessata. Il secondo stabilisce la politica
3922 per la barra di scorrimento orizzontale e il terzo &egrave; quello per la politca verticale.
3923
3924 La politica pu&ograve; essere GTK_POLICY AUTOMATIC o GTK_POLICY_ALWAYS.
3925 GTK_POLICY_AUTOMATIC decide automaticamente se la barra di scorrimento deve essere
3926 visualizzata, mentre con GTK_POLICY_ALWAYS la barra verr&agrave; sempre mostrata.
3927
3928 <tscreen><verb>
3929 /* scrolledwin.c */
3930
3931 #include <gtk/gtk.h>
3932
3933 void destroy(GtkWidget *widget, gpointer *data)
3934 {
3935     gtk_main_quit();
3936 }
3937
3938 int main (int argc, char *argv[])
3939 {
3940     static GtkWidget *window;
3941     GtkWidget *scrolled_window;
3942     GtkWidget *table;
3943     GtkWidget *button;
3944     char buffer[32];
3945     int i, j;
3946     
3947     gtk_init (&amp;argc, &amp;argv);
3948     
3949     /* Crea una nuove finestra di dialogo in cui la scrolled window sar&agrave; 
3950         inserita. Una finestra di dialogo &egrave; semplicemente come una 
3951         finestra normale, ma ha anche un vbox e un separatore orizzontale 
3952         gi&agrave; inseriti per difetto. E'un modo semplice per
3953         creare finestre di dialogo. */
3954     window = gtk_dialog_new ();
3955     gtk_signal_connect (GTK_OBJECT (window), "destroy",
3956                         (GtkSignalFunc) destroy, NULL);
3957     gtk_window_set_title (GTK_WINDOW (window), "dialog");
3958     gtk_container_border_width (GTK_CONTAINER (window), 0);
3959     gtk_widget_set_usize(window, 300, 300);    
3960
3961     /* crea una nuova finestra scorribile. */
3962     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
3963     
3964     gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
3965     
3966     /* la politica &egrave; GTK_POLICY AUTOMATIC per lo scorrimento orizzontale e 
3967         GTK_POLICY_ALWAYS per quello verticale.  */
3968     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
3969                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3970     
3971     /* La finestra di dialogo &egrave; creata con un vbox gi&agrave; inserito.*/
3972     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
3973                         TRUE, TRUE, 0);
3974     gtk_widget_show (scrolled_window);
3975     
3976     /* crea una tablella di10 x 10. */
3977     table = gtk_table_new (10, 10, FALSE);
3978     
3979     /* setta lo spazio tra ogni cella di 10 pixel sia verticale sia orizzontale*/
3980     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
3981     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
3982     
3983     /* inserisce la tabella nella finestra scorribile*/
3984     gtk_container_add (GTK_CONTAINER (scrolled_window), table);
3985     gtk_widget_show (table);
3986     
3987     /* questo semplicemente crea una griglia di bottoni nella tabelle per
3988        dimostrare il comportamento della finestra scorribile */
3989     for (i = 0; i < 10; i++)
3990        for (j = 0; j < 10; j++) {
3991           sprintf (buffer, "button (%d,%d)\n", i, j);
3992           button = gtk_toggle_button_new_with_label (buffer);
3993           gtk_table_attach_defaults (GTK_TABLE (table), button,
3994                                      i, i+1, j, j+1);
3995           gtk_widget_show (button);
3996        }
3997     
3998     /* Aggiunge un bottone "close" alla fine della finestra */
3999     button = gtk_button_new_with_label ("close");
4000     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4001                                (GtkSignalFunc) gtk_widget_destroy,
4002                                GTK_OBJECT (window));
4003     
4004     /* questo fa s&igrave; che questo bottone sia quello predefinito */
4005     
4006     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4007     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
4008     
4009     /* Questo ottiene il bottone predefinito. Premendo semplicemente l'"enter" il
4010         bottone si avvier&agrave; */
4011     gtk_widget_grab_default (button);
4012     gtk_widget_show (button);
4013     
4014     gtk_widget_show (window);
4015     
4016     gtk_main();
4017     
4018     return(0);
4019 }
4020 </verb></tscreen>
4021 <p>
4022 Prova a giocare con il ridemensionamento della finestra. Noterete la reazione della
4023 barra di scorrimento. Potete anche usare la funzione gtk_widget_set_usize() per
4024 assegnare la dimensione predefinita della finestra o di un widget.
4025 <!-- (ndMichel: questa chiamata non funziona per i bottoni!) -->
4026
4027 <!-- ----------------------------------------------------------------- -->   
4028 <sect1> Il widget "Finestra Frazionata" (Paned Window)
4029 <p>
4030 Le finestre frazionate tornano utili quando si vuole dividere un'area in due parti,
4031
4032 le cui dimensioni relative siano sotto il controllo dell'utente. Fra le due zone
4033
4034 viene disgnato un separatore dotato di una maniglia che l'utente pu&ograve;
4035
4036 trascinare per cambiare la proporzione fra le aree. La divisione pu&ograve;
4037
4038 essere sia di tipo orizzontale (HPaned) che verticale (VPaned).
4039
4040    
4041 Per creare una finestra frazionata, si chiama una delle seguenti:
4042    
4043 <tscreen><verb>
4044 GtkWidget* gtk_hpaned_new (void)
4045 GtkWidget* gtk_vpaned_new (void)
4046 </verb></tscreen>
4047
4048
4049 Dopo aver creato il widget della finestra frazionata, si devono aggiungere dei
4050
4051 widget figli alle due parti. Per farlo, si usano le funzioni:
4052
4053 <tscreen><verb>
4054 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child)
4055 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child)
4056 </verb></tscreen>
4057
4058 <tt/gtk_paned_add1()/ inserisce il widget figlo alla parte di sinistra o superiore
4059
4060 della finestra. <tt/gtk_paned_add2()/ lo inserisce invece nella parte destra o
4061
4062 inferore.
4063
4064    
4065 Per fare un esempio, creeremo una parte dell'interfaccia utente di un immaginario
4066
4067 programma di email. Si divide una finestra in due verticalmente, <!-- sicuro ? -->
4068
4069 con la parte superiore in cui si mette la lista dei messaggi, e quella inferiore con
4070
4071 il testo. La maggior parte del programma &egrave; piuttosto banale. Un paio
4072
4073 di punti da notare sono: Non si pu&ograve; scrivere su un widget di testo prima
4074
4075 che esso venga "realizato". Questa operazione pu&ograve; essere fatta con una
4076
4077 chiamata alla funzione <tt/gtk_widget_realize()/, ma per far vedere un metodo
4078
4079 alternativo, connetteremo una funzione al segnale "realize" per aggiungere il testo.
4080
4081 Inoltre, dobbiamo aggiungere l'opzione <tt/GTK_SHRINK/ ad alcuni degli
4082
4083 elementi della tabella che contiene la finestra del testo e le barre di scorrimento, in
4084
4085 modo che quando si riducono le dimensioni della parte inferiore, le parti coinvolte
4086
4087 risultino proporzionalmente rimpicciolite invece di venir spinte fuori dal fondo
4088
4089 della finestra.
4090
4091
4092 <tscreen><verb>
4093 /* paned.c */
4094
4095 #include <gtk/gtk.h>
4096    
4097 /*Creiamo la lista dei "messaggi" */
4098 GtkWidget *
4099 create_list (void)
4100 {
4101
4102     GtkWidget *scrolled_window;
4103     GtkWidget *list;
4104     GtkWidget *list_item;
4105    
4106     int i;
4107     char buffer[16];
4108    
4109     /* Creiamo una nuova finestra scorribile con barre di scorrimento solo
4110
4111      * se necessarie */
4112     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
4113     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
4114                                     GTK_POLICY_AUTOMATIC, 
4115                                     GTK_POLICY_AUTOMATIC);
4116    
4117     /* Creiamo una nuova lista e la mettiamo nella finestra scorribile */
4118     list = gtk_list_new ();
4119     gtk_container_add (GTK_CONTAINER(scrolled_window), list);
4120     gtk_widget_show (list);
4121    
4122     /* Aggiungiamo un po' di messaggi alla fiestra */
4123     for (i=0; i<10; i++) {
4124
4125         sprintf(buffer,"Message #%d",i);
4126         list_item = gtk_list_item_new_with_label (buffer);
4127         gtk_container_add (GTK_CONTAINER(list), list_item);
4128         gtk_widget_show (list_item);
4129
4130     }
4131    
4132     return scrolled_window;
4133 }
4134    
4135 /* Aggiungiamo un po' di testo al nostro widget di testo - questa e' una
4136
4137 funzione di callback che viene invocata quando la finestra viene "realizzata".
4138
4139 Potremmo anche forzare la finestra ad essere realizzata con la funzione
4140
4141  gtk_widget_realize, ma dovrebbe prima essere parte di una certa cerarchia */
4142
4143
4144 void
4145 realize_text (GtkWidget *text, gpointer data)
4146 {
4147     gtk_text_freeze (GTK_TEXT (text));
4148     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
4149     "From: pathfinder@nasa.gov\n"
4150     "To: mom@nasa.gov\n"
4151     "Subject: Made it!\n"
4152     "\n"
4153     "We just got in this morning. The weather has been\n"
4154     "great - clear but cold, and there are lots of fun sights.\n"
4155     "Sojourner says hi. See you soon.\n"
4156     " -Path\n", -1);
4157    
4158     gtk_text_thaw (GTK_TEXT (text));
4159 }
4160    
4161 /* Creiamo un'area di testo scorribile che mostra un "messaggio" */
4162 GtkWidget *
4163 create_text (void)
4164 {
4165     GtkWidget *table;
4166     GtkWidget *text;
4167     GtkWidget *hscrollbar;
4168     GtkWidget *vscrollbar;
4169    
4170     /*Creiamo una tabella in cui mettere il widget di testo e le barre di scorrimento */
4171     table = gtk_table_new (2, 2, FALSE);
4172    
4173     /* Mettiamo un widget di testo nella parte superiore destra. Notate l'uso di
4174      * GTK_SHRINK nella direzione y */
4175     text = gtk_text_new (NULL, NULL);
4176     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
4177                       GTK_FILL | GTK_EXPAND,
4178                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
4179     gtk_widget_show (text);
4180    
4181     /* Mettiamo una HScrollbar nella parte in basso a sinistra */
4182     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
4183     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
4184                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
4185     gtk_widget_show (hscrollbar);
4186    
4187     /* Aggiungiamo una VScrollbar in alto a sinistra */
4188     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
4189     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
4190                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
4191     gtk_widget_show (vscrollbar);
4192    
4193     /* Aggiungiamo un gestore per mettere un messaggio nel wiget di testo
4194
4195      * viene reaizzato */
4196     gtk_signal_connect (GTK_OBJECT (text), "realize",
4197                         GTK_SIGNAL_FUNC (realize_text), NULL);
4198    
4199     return table;
4200 }
4201    
4202 int
4203 main (int argc, char *argv[])
4204 {
4205     GtkWidget *window;
4206     GtkWidget *vpaned;
4207     GtkWidget *list;
4208     GtkWidget *text;
4209
4210     gtk_init (&amp;argc, &amp;argv);
4211    
4212     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4213     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
4214     gtk_signal_connect (GTK_OBJECT (window), "destroy",
4215                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
4216     gtk_container_border_width (GTK_CONTAINER (window), 10);
4217    
4218     /* Creiamo un widget frazionato verticalmente e aggiungiamolo alla
4219
4220      * finestra di piu' alto livello */
4221    
4222     vpaned = gtk_vpaned_new ();
4223     gtk_container_add (GTK_CONTAINER(window), vpaned);
4224     gtk_widget_show (vpaned);
4225    
4226     /* Creiamo il contenuto delle de parti della finestra */
4227    
4228     list = create_list ();
4229     gtk_paned_add1 (GTK_PANED(vpaned), list);
4230     gtk_widget_show (list);
4231    
4232     text = create_text ();
4233     gtk_paned_add2 (GTK_PANED(vpaned), text);
4234     gtk_widget_show (text);
4235     gtk_widget_show (window);
4236     gtk_main ();
4237     return 0;
4238 }
4239
4240 </verb></tscreen>
4241
4242 <!-- ----------------------------------------------------------------- -->   
4243 <sect1> Cornici ad aspetto fisso (Aspect Frames)
4244 <p>
4245 Il widget aspect frame &grave; analogo al widget "cornice", tranne che per il
4246
4247 fatto che &egrave; in grado di forzare le finestre figlie ad avere un certo aspetto,
4248
4249 cio&egrave; un certo rapporto fra altezza e larghezza, aggiungendo se necessario
4250
4251 dello spazio in pi&ugrave;. Ci&ograve; pu&ograve; tornare utile se per esempio
4252
4253 si vuole fare l'anteprima di un'immagine: le dimensioni dell'anteprima devono
4254
4255 variare se l'utente ridimensiona la finestra, ma le proporzioni devono essere
4256
4257 sempre quelle dell'immagine originale.
4258    
4259 Per creare una nuova cornice ad aspetto fisso, si usa:
4260    
4261 <tscreen><verb>
4262 GtkWidget* gtk_aspect_frame_new  (const gchar *label,
4263                                         gfloat xalign,
4264                                         gfloat yalign,
4265                                         gfloat ratio,
4266                                         gint obey_child)
4267 </verb></tscreen>
4268    
4269 <tt/xalign/ e <tt/yalign/ specificano l'allineamento come si fa con il widget di
4270
4271 allineamento. Se <tt/obey_child/ &egrave; TRUE, le proporzioni di una finestra
4272
4273 figlia saranno le stesse delle misure ideali richieste. In caso contrario, vengono
4274
4275 stabilite da <tt/ratio/.
4276
4277
4278 Per cambiare le opzioni di una finestra esistente, si pu&ograve; usare:   
4279 To change the options of an existing aspect frame, you can use:
4280    
4281 <tscreen><verb>
4282 void gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
4283                            gfloat xalign,
4284                            gfloat yalign,
4285                            gfloat ratio,
4286                            gint obey_child)
4287 </verb></tscreen>
4288    
4289 <p>
4290 Per fare un esempio, il seguente programma usa un Aspect Frame per rendere
4291
4292 disponibile un'area disegnabile che sia sempre di proporzioni 2:1, in quasiasi
4293
4294 modo l'utente ridimensioni la finestra di base.
4295
4296    
4297 <tscreen><verb>
4298 /* aspectframe.c */
4299
4300 #include <gtk/gtk.h>
4301    
4302 int
4303 main (int argc, char *argv[])
4304 {
4305     GtkWidget *window;
4306     GtkWidget *aspect_frame;
4307     GtkWidget *drawing_area;
4308     gtk_init (&amp;argc, &amp;argv);
4309    
4310     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4311     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
4312     gtk_signal_connect (GTK_OBJECT (window), "destroy",
4313     GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
4314     gtk_container_border_width (GTK_CONTAINER (window), 10);
4315    
4316     /* Creiamo aspect_frame e lo mettiamo nella finestra di base */
4317    
4318     aspect_frame = gtk_aspect_frame_new ("2x1", /* etichetta */
4319                                          0.5, /* x del centro */
4320                                          0.5, /* y del centro */
4321                                          2, /* xsize/ysize = 2 */
4322                                          FALSE /* ignora le proporzioni del figlio */);
4323    
4324     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
4325     gtk_widget_show (aspect_frame);
4326    
4327     /* Aggiungamo un widget figlio alla nostra cornice */
4328    
4329     drawing_area = gtk_drawing_area_new ();
4330    
4331     /* Chiediamo una finestra 200x200, anche se l'AspectFrame ce ne dara' una 
4332      * di 200x100 perche' forziamo l'aspetto 2:1 */
4333     gtk_widget_set_usize (drawing_area, 200, 200);
4334     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
4335     gtk_widget_show (drawing_area);
4336    
4337     gtk_widget_show (window);
4338     gtk_main ();
4339     return 0;
4340 }  
4341 </verb></tscreen>
4342                               
4343 <!-- fin qui -->
4344
4345
4346 <!-- ***************************************************************** -->
4347 <sect> Il Widgets Lista
4348 <!-- ***************************************************************** -->
4349 <p>
4350 Il widget GtkList serve come contenitore verticale per altri widget che
4351 devono essere di tipo GtkListItem.
4352
4353 Un widget GtkList possiede una sua propria finestra per ricevere eventi
4354 e un suo proprio colore di sfondo che di solito &egrave; bianco. Dal momento
4355 che &egrave; direttamente derivato dal widget GtkContainer, pu&ograve; essere trattato
4356 come tale usando la macro GTK_CONTAINER(List); si veda il widget GtkContainer
4357 per ulteriori dettagli.
4358 Per usare il widget GtkList in tutte le sue potenzialit&agrave;, si dovrebbe essere
4359 gi&agrave; familiari con l'uso della GList e delle relative funzioni g_list_*().
4360
4361 All'interno della definizione della struttura del widget GtkList c'&egrave; un
4362 campo che sar&agrave; per noi di grande interesse, cio&egrave;:
4363
4364 <tscreen><verb>
4365 struct _GtkList
4366 {
4367   ...
4368   GList *selection;
4369   guint selection_mode;
4370   ...
4371 }; 
4372 </verb></tscreen>
4373
4374 Il campo ``selection'' in un GtkList punta a una lista collegata di tutti
4375 gli elementi che sono selezionati correntemente, oppure a NULL se la 
4376 selezione &egrave; vuota. Quindi, per avere informazioni sulla selezione corrente,
4377 leggiamo il campo GTK_LIST()->selection, senza per&ograve; modificarlo dal momento
4378 che i campi interni debbono essere gestiti dalle funzioni gtk_list_*(). 
4379
4380 Le modalit&agrave; di selezione in una GtkList, e quindi il contenuto di
4381 GTK_LIST()->selection, sono determinate dal campo selection_mode:
4382
4383 selection_mode pu&ograve; assumere uno dei seguenti valori:
4384 <itemize>
4385 <item> GTK_SELECTION_SINGLE - La selezione pu&ograve; essere o NULL oppure
4386                         un puntatore GList* per un singolo elemento
4387                         selezionato.
4388
4389 <item> GTK_SELECTION_BROWSE - La selezione &egrave; null se la lista non contiene
4390                         alcun widget o se ha solo widget non sensibili,
4391                         oppure pu&ograve; contenere un puntatore a una struttura
4392                         GList, e quindi esattamente un elemento di lista.
4393
4394 <item> GTK_SELECTION_MULTIPLE - La selezione &egrave; ``NULL'' se non &egrave; selezionato
4395                         alcun elemento di lista, oppure un puntatore GList al
4396                         primo elemento selezionato. Quello, a sua volta, punta
4397                         a una struttura GList per il secondo elemento selezionato
4398                         e cos&igrave; via.
4399
4400 <item> GTK_SELECTION_EXTENDED - La selezione &egrave; sempre NULL.
4401 </itemize>
4402 <p>
4403 Il valore per difetto &egrave;  GTK_SELECTION_MULTIPLE.
4404
4405 <!-- ----------------------------------------------------------------- -->
4406 <sect1> Segnali
4407 <p>
4408 <tscreen><verb>
4409 void selection_changed (GtkList *LIST)
4410 </verb></tscreen>
4411
4412 Questo segnale verr&agrave; invocato ogni volta che il campo di
4413 selezione di una GtkList &egrave; cambiato. Questo accade quando
4414 un figlio della GtkList viene selezionato o deselezionato.
4415
4416 <tscreen><verb>
4417 void select_child (GtkList *LIST, GtkWidget *CHILD)
4418 </verb></tscreen>
4419
4420 Questo segnale viene invocato quando un fuglio di una GtkList
4421 sta per essere selezionato. Questo accade principalmente in
4422 occasione di chiamate a gtk_list_select_item() e gtk_list_select_child(),
4423 di pressioni di bottoni e a volte pu&ograve; venir fatto scattare indirettamente
4424 in altre occasioni, in cui vengono aggiunti o rimossi dei figli
4425 dalla GtkList.
4426
4427 <tscreen><verb>
4428 void unselect_child (GtkList *LIST, GtkWidget *CHILD)
4429 </verb></tscreen>
4430
4431 Questo segnale viene invocato quando un figlio della GtkList sta
4432 per essere deselezionato. Ci&ograve; accade principalmente in occasione
4433 di chiamate a gtk_list_unselect_item() e gtk_list_unselect_child(),
4434 di pressioni di bottoni, e a volte pu&ograve; venir fatto scattare indirettamente
4435 in altre occasioni, in cui vengono aggiunti o rimossi dei figli
4436 dalla GtkList.
4437
4438 <!-- ----------------------------------------------------------------- -->
4439 <sect1> Funzioni
4440 <p>
4441 <tscreen><verb>
4442 guint gtk_list_get_type (void)
4443 </verb></tscreen>
4444
4445 Restituisce l'identificatore di tipo `GtkList'.
4446
4447 <tscreen><verb>
4448 GtkWidget* gtk_list_new (void)
4449 </verb></tscreen>
4450
4451 Crea un nuovo oggetto `GtkList'. Il nuovo widget viene
4452 restituito sotto forma di un puntoatore ad un oggetto
4453 `GtkWidget&igrave;'. In caso di fallimento, viene ritornato NULL.
4454
4455 <tscreen><verb>
4456 void gtk_list_insert_items (GtkList *LIST, GList *ITEMS, gint POSITION)
4457 </verb></tscreen>
4458
4459 Inserisce degli elementi di lista nella LIST, a partire da
4460 POSITION. ITEMS ITEMS &egrave; una lista doppiamente collegata, in
4461 cui ci si aspetta che i puntatori di ogni nodo puntino a
4462 un GtkListItem appena creato. I nodi GList di ITEMS vengono
4463 assunti dalla LIST.
4464
4465 <tscreen><verb>
4466 void gtk_list_append_items (GtkList *LIST, GList *ITEMS)
4467 </verb></tscreen>
4468
4469 Inserisce elementi di lista proprio come gtk_list_insert_items(),
4470 ma alla fine della LIST. I nodi GList di ITEMS vengono
4471 assunti dalla LIST.
4472
4473 <tscreen><verb>
4474 void gtk_list_prepend_items (GtkList *LIST, GList *ITEMS)
4475 </verb></tscreen>
4476
4477 Inserisce elementi di lista proprio come gtk_list_insert_items(),
4478 ma al principio della LIST. I nodi GList di ITEMS vengono
4479 assunti dalla LIST.
4480
4481 <tscreen><verb>
4482 void gtk_list_remove_items (GtkList *LIST, GList *ITEMS)
4483 </verb></tscreen>
4484
4485 Rimuove degli elementi di lista dalla LIST. ITEMS &egrave; una lista
4486 doppiamente collegata in cui ci si aspetta che i puntatori di
4487 ogni nodo puntino a un figlio diretto di LIST. E' poi responsabilit&agrave;
4488 del chiamante di fare una chiamata a g_list_free(ITEMS). E' anche
4489 necessario che il chiamante distrugga lui stesso gli elementi della
4490 lista.
4491
4492 <tscreen><verb>
4493 void gtk_list_clear_items (GtkList *LIST, gint START, gint END)
4494 </verb></tscreen>
4495
4496 Rimuove e distrugge elementi di lista da LIST. Un widget ne &egrave;
4497 interessato se la sua posizione corrente all'interno di LIST &egrave; compreso
4498 fra START ed END.
4499
4500 <tscreen><verb>
4501 void gtk_list_select_item (GtkList *LIST, gint ITEM)
4502 </verb></tscreen>
4503
4504 Invoca il segnale select_child per un elemento di lista
4505 specificato dalla sua posizione corrente all'interno di LIST.
4506
4507 <tscreen><verb>
4508 void gtk_list_unselect_item (GtkList *LIST, gint ITEM)
4509 </verb></tscreen>
4510
4511 Invoca il segnale unselect_child per un elemento di lista
4512 specificato dalla sua posizione corrente all'interno di LIST.
4513
4514 <tscreen><verb>
4515 void gtk_list_select_child (GtkList *LIST, GtkWidget *CHILD)
4516 </verb></tscreen>
4517
4518 Invoca il segnale select_child per uno specifico CHILD.
4519
4520 <tscreen><verb>
4521 void gtk_list_unselect_child (GtkList *LIST, GtkWidget *CHILD)
4522 </verb></tscreen>
4523
4524 Invoca il segnale unselect_child per uno specifico CHILD.
4525
4526 <tscreen><verb>
4527 gint gtk_list_child_position (GtkList *LIST, GtkWidget *CHILD)
4528 </verb></tscreen>
4529
4530 Restituisce la posizione di CHILD all'interno di LIST. In caso di fallimento,
4531 viene restituito `-1'.
4532
4533 <tscreen><verb>
4534 void gtk_list_set_selection_mode (GtkList *LIST, GtkSelectionMode MODE)
4535 </verb></tscreen>
4536
4537 Assegna a LIST il modo di selezione MODE, che pu&ograve; essere uno fra 
4538 GTK_SELECTION_SINGLE, GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE o
4539 GTK_SELECTION_EXTENDED.
4540
4541 <tscreen><verb>
4542 GtkList* GTK_LIST (gpointer OBJ)
4543 </verb></tscreen>
4544
4545 Fa il cast di un generico puntatore a `GtkList*'. Per maggiori
4546 informazioni vedere Standard Macros::.
4547
4548 <tscreen><verb>
4549 GtkListClass* GTK_LIST_CLASS (gpointer CLASS)
4550 </verb></tscreen>
4551
4552 Fa il cast di un generico puntatore a `GtkListClass*'. Per maggiori
4553 informazioni vedere Standard Macros::.
4554
4555 <tscreen><verb>
4556 gint GTK_IS_LIST (gpointer OBJ)
4557 </verb></tscreen>
4558
4559 Determina se un generico puntatore si riferisce ad un oggetto `GtkList'.
4560 Per maggiori informazioni vedere Standard Macros::.
4561
4562 <!-- ----------------------------------------------------------------- -->
4563 <sect1> Esempio
4564 <p>
4565 Diamo di seguito un programma di esempio che stamper&agrave; i campbiamenti
4566 della selezione di una GtkList, e vi lascia ``imprigionare'' gli elementi
4567 di una lista selezionandoli con il pulsante destro del mouse:
4568
4569 <tscreen><verb>
4570 /* list.c */
4571
4572 /* includiamo i file header di gtk+
4573  * includiamo stdio.h, ne abbiamo bisogno per printf()
4574  */
4575 #include        <gtk/gtk.h>
4576 #include        <stdio.h>
4577
4578 /* Questa e' la nostra stringa di identificazione dei dati per assegnarli
4579  * ad elementi di lista
4580  */
4581 const   gchar   *list_item_data_key="list_item_data";
4582
4583
4584 /* prototipi per i gestori di segnale che connetteremo
4585  * al widget GtkList
4586  */
4587 static  void    sigh_print_selection    (GtkWidget      *gtklist,
4588                                          gpointer       func_data);
4589 static  void    sigh_button_event       (GtkWidget      *gtklist,
4590                                          GdkEventButton *event,
4591                                          GtkWidget      *frame);
4592
4593
4594 /* funzione main per predisporre l'interfaccia utente */
4595
4596 gint main (int argc, gchar *argv[])
4597 {                                  
4598     GtkWidget       *separator;
4599     GtkWidget       *window;
4600     GtkWidget       *vbox;
4601     GtkWidget       *scrolled_window;
4602     GtkWidget       *frame;
4603     GtkWidget       *gtklist;
4604     GtkWidget       *button;
4605     GtkWidget       *list_item;
4606     GList           *dlist;
4607     guint           i;
4608     gchar           buffer[64];
4609     
4610     
4611     /* inizializza gtk+ (e di conseguenza gdk) */
4612
4613     gtk_init(&amp;argc, &amp;argv);
4614     
4615     
4616     /* crea una finestra in cui mettere tutti i widget
4617      * connette gtk_main_quit() al segnale "destroy" della finestra
4618      * per gestire le richieste di chiusura finestra del window manager
4619      */
4620     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
4621     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
4622     gtk_signal_connect(GTK_OBJECT(window),
4623                        "destroy",
4624                        GTK_SIGNAL_FUNC(gtk_main_quit),
4625                        NULL);
4626     
4627     
4628     /* all'interno della finestra abbiamo bisogno di una scatola
4629      * in cui mettere i widget verticalmente */
4630     vbox=gtk_vbox_new(FALSE, 5);
4631     gtk_container_border_width(GTK_CONTAINER(vbox), 5);
4632     gtk_container_add(GTK_CONTAINER(window), vbox);
4633     gtk_widget_show(vbox);
4634     
4635     /* questa &egrave; la finestra scorribile in cui mettere il widget GtkList */
4636     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
4637     gtk_widget_set_usize(scrolled_window, 250, 150);
4638     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
4639     gtk_widget_show(scrolled_window);
4640     
4641     /* crea il widget GtkList
4642      * connette il gestore di segnale sigh_print_selection()
4643      * al segnale "selection_changed" della GtkList, per stampare
4644      * gli elementi selezionati ogni volta che la selezione cambia
4645      */
4646     gtklist=gtk_list_new();
4647     gtk_container_add(GTK_CONTAINER(scrolled_window), gtklist);
4648     gtk_widget_show(gtklist);
4649     gtk_signal_connect(GTK_OBJECT(gtklist),
4650                        "selection_changed",
4651                        GTK_SIGNAL_FUNC(sigh_print_selection),
4652                        NULL);
4653     
4654     /* creiamo una "Prigione" (Prison) in cui mettere gli elementi di lista ;)
4655      */
4656     frame=gtk_frame_new("Prison");
4657     gtk_widget_set_usize(frame, 200, 50);
4658     gtk_container_border_width(GTK_CONTAINER(frame), 5);
4659     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
4660     gtk_container_add(GTK_CONTAINER(vbox), frame);
4661     gtk_widget_show(frame);
4662     
4663     /* connette il gestore di segnale sigh_button_event() alla GtkList
4664      * il quale gestira' l'"imprigionamento" degli elementi di lista
4665      */
4666     gtk_signal_connect(GTK_OBJECT(gtklist),
4667                        "button_release_event",
4668                        GTK_SIGNAL_FUNC(sigh_button_event),
4669                        frame);
4670     
4671     /* crea un separatore
4672      */
4673     separator=gtk_hseparator_new();
4674     gtk_container_add(GTK_CONTAINER(vbox), separator);
4675     gtk_widget_show(separator);
4676     
4677     /* infine creiamo un bottone e connettiamone il segnale "clicked"
4678      * alla distruzione della finestra
4679      */
4680     button=gtk_button_new_with_label("Close");
4681     gtk_container_add(GTK_CONTAINER(vbox), button);
4682     gtk_widget_show(button);
4683     gtk_signal_connect_object(GTK_OBJECT(button),
4684                               "clicked",
4685                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
4686                               GTK_OBJECT(window));
4687     
4688     
4689     /* a questo punto creiamo 5 elementi di lista, ognuno con la
4690      * propria etichetta, e li aggiungiamo alla GtkList usando
4691      * gtk_container_add(). Inoltre, recuperiamo la stringa di testo
4692      * dall'etichetta e la associamo, per ogni elemento, a
4693      * list_item_data_key
4694      */
4695     for (i=0; i<5; i++) {
4696         GtkWidget       *label;
4697         gchar           *string;
4698         
4699         sprintf(buffer, "ListItemContainer with Label #%d", i);
4700         label=gtk_label_new(buffer);
4701         list_item=gtk_list_item_new();
4702         gtk_container_add(GTK_CONTAINER(list_item), label);
4703         gtk_widget_show(label);
4704         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
4705         gtk_widget_show(list_item);
4706         gtk_label_get(GTK_LABEL(label), &amp;string);
4707         gtk_object_set_data(GTK_OBJECT(list_item),
4708                             list_item_data_key,
4709                             string);
4710     }
4711
4712     /* qui creiamo altre 5 etichette, questa volta usando
4713      * per la creazione gtk_list_item_new_with_label().
4714      * Non possiamo recuperare la stringa di testo dall'etichetta
4715      * dal momento che non disponiamo di puntatori alle etichette,
4716      * quindi associamo semplicemente il list_item_data_key di ogni
4717      * elemento di lista con la medesima stringa di testo.
4718      * Per aggiungere elementi di lista, li mettiamo tutti in una lista
4719      * doppiamente collegata (GList), e quindi li aggiungiamo con una
4720      * unica chiamata a gtk_list_append_items().
4721      * Dal momento che usiamo g_list_prepend() per mettere gli elementi
4722      * nella lista doppiamente collegata, il loro ordine sara' discendente
4723      * (invece che ascendente come sarebbe se usassimo g_list_append())
4724      */
4725     dlist=NULL;
4726     for (; i<10; i++) {
4727         sprintf(buffer, "List Item with Label %d", i);
4728         list_item=gtk_list_item_new_with_label(buffer);
4729         dlist=g_list_prepend(dlist, list_item);
4730         gtk_widget_show(list_item);
4731         gtk_object_set_data(GTK_OBJECT(list_item),
4732                             list_item_data_key,
4733                             "ListItem with integrated Label");
4734     }
4735     gtk_list_append_items(GTK_LIST(gtklist), dlist);
4736     
4737     /* e finalmente vogliamo vedere la finestra, non e' vero? ;)
4738      */
4739     gtk_widget_show(window);
4740     
4741     /* lancia il ciclo principale di gtk
4742      */
4743     gtk_main();
4744     
4745     /* si arriva a questo punto dopo la chiamata di gtk_main_quit(),
4746      * il che accade quando viene distrutta la finestra principale
4747      */
4748     return 0;
4749 }
4750
4751 /* questo e' il gestore di segnale che e' stato connesso all'evento di
4752  * pressione/rilascio del bottone della GtkList
4753  */
4754 void
4755 sigh_button_event       (GtkWidget      *gtklist,
4756                          GdkEventButton *event,
4757                          GtkWidget      *frame)
4758 {
4759     /* facciamo qualcosa solo nel caso di rilascio del terzo bottone
4760      * (quello piu' a destra)
4761      */
4762     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
4763         event->button==3) {
4764         GList           *dlist, *free_list;
4765         GtkWidget       *new_prisoner;
4766         
4767         /* recuperiamo l'elemento di lista selezionato correntemente,
4768          * che sara' il nostro prossimo prigioniero ;)
4769          */
4770         dlist=GTK_LIST(gtklist)->selection;
4771         if (dlist)
4772                 new_prisoner=GTK_WIDGET(dlist->data);
4773         else
4774                 new_prisoner=NULL;
4775         
4776         /* cerchiamo elementi di lista gia' imprigionati,
4777          * li rimetteremo nella lista.
4778          * Ricordare di liberare la lista doppiamente collegata
4779          * che viene restituita da gtk_container_children()
4780          */
4781         dlist=gtk_container_children(GTK_CONTAINER(frame));
4782         free_list=dlist;
4783         while (dlist) {
4784             GtkWidget       *list_item;
4785             
4786             list_item=dlist->data;
4787             
4788             gtk_widget_reparent(list_item, gtklist);
4789             
4790             dlist=dlist->next;
4791         }
4792         g_list_free(free_list);
4793         
4794         /* se abbiamo un nuovo prigioniero, lo rimuoviamo
4795          * dalla GtkList e lo mettiamo nella cornice della
4796          * "Prigione". Dobbiamo prima deselezionare l'elemento
4797          */
4798         if (new_prisoner) {
4799             GList   static_dlist;
4800             
4801             static_dlist.data=new_prisoner;
4802             static_dlist.next=NULL;
4803             static_dlist.prev=NULL;
4804             
4805             gtk_list_unselect_child(GTK_LIST(gtklist),
4806                                     new_prisoner);
4807             gtk_widget_reparent(new_prisoner, frame);
4808         }
4809     }
4810 }
4811
4812 /* questo e' il gestore di segnaleche viene chiamato de la
4813  * GtkList emette il segnale "selection_changed"
4814  */
4815 void
4816 sigh_print_selection    (GtkWidget      *gtklist,
4817                          gpointer       func_data)
4818 {
4819     GList   *dlist;
4820     
4821     /* recuperiamo la lista doppiamente collegata degli
4822      * elementi selezionati della GtkList, ricordate di
4823      * trattarla come sola lettura
4824      */
4825     dlist=GTK_LIST(gtklist)->selection;
4826     
4827     /* se non ci sono elementi selezionati non c'e' altro da
4828      * fare che dirlo all'utente
4829      */
4830     if (!dlist) {
4831         g_print("Selection cleared\n");
4832         return;
4833     }
4834     /* ok, abbiamo una selezione e quindi lo scriviamo
4835      */
4836     g_print("The selection is a ");
4837     
4838     /* ottieniamo l'elemento di lista dalla lista doppiamente
4839      * collegata e poi richiediamo i dati associati con
4840      *  list_item_data_key. Poi semplicemente li stampiamo
4841      */
4842     while (dlist) {
4843         GtkObject       *list_item;
4844         gchar           *item_data_string;
4845         
4846         list_item=GTK_OBJECT(dlist->data);
4847         item_data_string=gtk_object_get_data(list_item,
4848                                              list_item_data_key);
4849         g_print("%s ", item_data_string);
4850         
4851         dlist=dlist->next;
4852     }
4853     g_print("\n");
4854 }
4855 </verb></tscreen>
4856
4857 <!-- ----------------------------------------------------------------- -->
4858 <sect1> Il Widget Elemento di Lista (List Item)
4859 <p>
4860 Il widget GtkListItem &egrave; progettato allo scopo di essere un contenitore
4861 collegato ad un figlio, per fornire le funzioni per la selezione e deselezione
4862 allo stesso modo in cui il widget GtkList ne ha bisogno per i propri figli.
4863
4864 Un GtkListItem ha la sua propria finestra per ricevere eventi, e ha il suo
4865 proprio colore di sfondo, che di solito &egrave; bianco.
4866
4867 Dal momento che questo widget deriva direttamente da GtkItem, pu&ograve; essere
4868 trattato come tale usando la macro GTK_ITEM(ListItem), vedere il widget
4869 GtkItem per ulteriori informazioni.
4870 Di solito un GtkListItem ha solo un'etichetta per identificare per esempio
4871 un nome di file all'interno di una GtkList -- per cui viene fornita la
4872 funzione appropriata gtk_list_item_new_with_label(). Si pu&ograve; ottenere lo
4873 stesso effetto creando una GtkLabel da sola, assegnando al suo allineamento
4874 i valori xalign=0 e yalign=0.5, aggiungendo successivamente un contenitore
4875 alla GtkListItem.
4876
4877 Dal momento che non si &egrave; obbligati a mettere una GtkLabel, si pu&ograve; anche
4878 aggiungere una GtkVBox  una GtkArrow ecc. alla GtkListItem.
4879
4880
4881 <!-- ----------------------------------------------------------------- -->
4882 <sect1> Segnali
4883 <p>
4884 Un GtkListItem non crea alcun nuovo segnale di per se, ma eredita
4885 i segnali di GtkItem. Per ulteriori informazioni, vedere GtkItem::.
4886
4887 <!-- ----------------------------------------------------------------- -->
4888 <sect1> Funzioni
4889 <p>
4890
4891 <tscreen><verb>
4892 guint gtk_list_item_get_type (void)
4893 </verb></tscreen>
4894
4895 Restituisce l'identificatore di tipo `GtkListItem'.
4896
4897 <tscreen><verb>
4898 GtkWidget* gtk_list_item_new (void)
4899 </verb></tscreen>
4900
4901 Crea un nuovo oggetto `GtkListItem'. Il nuovo widget viene restituito
4902 sottoforma di un puntatore ad un oggetto `GtkWidget'. In caso di 
4903 fallimento, viene restituito `NULL'.
4904
4905 <tscreen><verb>
4906 GtkWidget* gtk_list_item_new_with_label (gchar *LABEL)
4907 </verb></tscreen>
4908
4909 Cre un nuovo oggetto `GtkListItem', avente come unico figlio
4910 un GtkLabel.  Il nuovo widget viene restituito
4911 sottoforma di un puntatore ad un oggetto `GtkWidget'. In caso di 
4912 fallimento, viene restituito `NULL'.
4913
4914 <tscreen><verb>
4915 void gtk_list_item_select (GtkListItem *LIST_ITEM)
4916 </verb></tscreen>
4917
4918 Questa funzione &egrave; essenzialmente un wrapper per una chiamata a
4919 gtk_item_select (GTK_ITEM (list_item)) che emetter&agrave; il segnale
4920 select.
4921 Vedere GtkItem:: per maggiori informazioni.
4922
4923 <tscreen><verb>
4924 void gtk_list_item_deselect (GtkListItem *LIST_ITEM)
4925 </verb></tscreen>
4926
4927 Questa funzione &egrave; essenzialmente un wrapper per una chiamata a
4928 gtk_item_deselect (GTK_ITEM (list_item)) che emetter&agrave; il segnale
4929 deselect.
4930 Vedere GtkItem:: per maggiori informazioni.
4931
4932 <tscreen><verb>
4933 GtkListItem* GTK_LIST_ITEM (gpointer OBJ)
4934 </verb></tscreen>
4935
4936 Effettua il cast di un puntatore generico a `GtkListItem*'. Vedere
4937 Standard Macros:: per maggiorni informazioni.
4938
4939 <tscreen><verb>
4940 GtkListItemClass* GTK_LIST_ITEM_CLASS (gpointer CLASS)
4941 </verb></tscreen>
4942
4943 Effettua il cast di un puntatore generico a `GtkListItemClass*'. Vedere
4944 Standard Macros:: per maggiorni informazioni.
4945
4946 <tscreen><verb>
4947 gint GTK_IS_LIST_ITEM (gpointer OBJ)
4948 </verb></tscreen>
4949
4950 Determina se un puntatore generico si riferisce ad un oggetto
4951 `GtkListItem'. Vedere Standard Macros:: per maggiorni informazioni.
4952
4953 <!-- ----------------------------------------------------------------- --> 
4954 <sect1> Esempio
4955 <p>
4956 Come esempio su questo argomento, si veda quello relativo alla GtkList,
4957 che riguarda anche l'uso del GtkListItem.
4958
4959 <!-- ***************************************************************** -->
4960 <sect>Il Widget Men&ugrave; (Menu Widgets)
4961 <!-- ***************************************************************** -->
4962 <p>
4963 Ci sono due modi per creare dei men&ugrave;, quello facile e quello difficile.
4964 Ognuno &egrave; pi&ugrave; adatto per certe circostanze, ma di solito si pu&ograve; usare il
4965 modo semplice, cio&eacute; menu_factory (la ``fabbrica dei men&ugrave;''). Il modo 
4966 ``difficile'' &egrave; di crearsi tutti i men&ugrave; usando direttamente le chiamate.
4967 Quello semplice &egrave; di usare le chiamate di tipo gtk_menu_factory. Anche se
4968 &egrave; un modo molto pi&ugrave; semplice, ci sono svantaggi e vantaggi per ciascuno
4969 dei due approcci.
4970
4971 La menu_factory &egrave; molto pi&ugrave; semplice da usare e per aggiungere dei nuovi
4972 men&ugrave;, anche se scriversi un po' di funzioni per creare dei men&ugrave; con il
4973 metodo manuale pu&ograve; dare risultati molto migliori dal punto di vista 
4974 dell'usabilit&agrave;. Con la menufactory, non &egrave; possibile mettere immagini o
4975 caratteri '/' nei men&ugrave;.
4976 <p>
4977 <!-- ----------------------------------------------------------------- -->
4978 <sect1>Creazione Manuale di Men&ugrave;
4979 <p>
4980 Seguendo la tradizionale arte dell'insegnamento, partiamo dal modo
4981 difficile. <tt>:)</>
4982 <p>
4983 I widget che hanno a che fare con la creazione di una barra di men&ugrave; e di sottomen&ugrave; sono tre:
4984 <itemize>
4985 <item>un elemento di men&ugrave;, che &grave; quello che l'utente poi selezioner&agrave;, per esempio 'Salva'
4986 <item>un men&ugrave;, che fa la parte di contenitore per gli elementi di men&ugrave;, e
4987 <item>una barra dei men&ugrave;, che &egrave; un contenitore per ciascuno dei men&ugrave;
4988 </itemize>
4989
4990
4991 La cosa viene un po' complicata dal fatto che i widget elemento di men&ugrave; vngono usati per
4992
4993 due scopi diversi. Essi sono sia i widget che vengono impacchettati nei men&ugrave;, che 
4994
4995 quelli che vengono impacchettati nella barra dei men&ugrave; che, quando selezonati, attivano i men&ugrave;.
4996
4997 Diamo un'occhiata alle funzioni usate per creare i men&ugrave; e le barre di men&ugrave;.
4998 Con questa prima funzione si crea un nuova barra di men&ugrave;:
4999
5000
5001 <tscreen><verb>
5002 GtkWidget *gtk_menu_bar_new(void);
5003 </verb></tscreen>
5004
5005 Questa funzione crea una nuova barra di men&ugrave;. Per impacchettarla in una
5006 finestra o si usa la funzione gtk_container_add, oppure, per impacchettarla
5007 in una scatola, le funzioni box_pack - come con i bottoni.
5008
5009 <tscreen><verb>
5010 GtkWidget *gtk_menu_new();
5011 </verb></tscreen>
5012
5013 Questa funzione restituisce un puntatore ad un nuovo men&ugrave;, non viene mai
5014 realmente mostrato (con gtk_widget_show), serve solo per contenere gli
5015 elementi del men&ugrave;. Spero che il tutto risulti pi&ugrave; chiaro quando daremo
5016 un'occhiata all'esempio pi&ugrave; sotto.
5017 <p>
5018 Le prossime due chiamate sono usate per creare degli elementi che poi
5019 vengono impacchettati nei men&ugrave; e nelle barre dei men&ugrave;..
5020
5021 <tscreen><verb>
5022 GtkWidget *gtk_menu_item_new();
5023 </verb></tscreen>
5024
5025 e
5026
5027 <tscreen><verb>
5028 GtkWidget *gtk_menu_item_new_with_label(const char *label);
5029 </verb></tscreen>
5030
5031 Queste chiamate sono usate per creare gli elementi di men&ugrave; che devono poi essere mostrati.
5032 Ricordate la differenza che esiste fra un ``men&ugrave;'' come quelli creati con
5033 gtk_menu_new e un ``elemento di men&ugrave;'' (menu item) come quelli creati con
5034 la funzione gtk_menu_item_new. L'elemento di men&ugrave; sar&agrave; un bottone
5035 vero e proprio con una azione associata, mentre un men&ugrave; &egrave; solo un contenitore che li raccoglie.
5036 Le funzioni gtk_menu_new_with_label e gtk_menu_new sono esattamente come vi aspettereste che siano dopo
5037
5038 aver conosciuto i bottoni. Una crea un nuovo elemento di men&ugrave; con un'etichetta gi&agrave; impacchettata,
5039
5040 mentre l'altra crea un elemento di men&ugrave; vuoto.
5041
5042
5043 Una volta che si &grave; creato un elemento di men&ugrave;, &egrave; necessario piazzarlo su di un men&ugrave;.
5044
5045 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 <tt/activate/ nel solito modo.
5046
5047 Quindi, se volessimo creare un normale men&ugrave; <tt/File/, con le opzioni <tt/Open/, <tt/Save/ e <tt/Quit/, il codice avrebbe pi&ugrave; o meno il seguente aspetto:
5048
5049 <tscreen><verb>
5050 file_menu = gtk_menu_new();    /* Non e' necessario mostrare i menu' */
5051
5052 /* Creiamo gli elementi del menu' */
5053 open_item = gtk_menu_item_new_with_label("Open");
5054 save_item = gtk_menu_item_new_with_label("Save");
5055 quit_item = gtk_menu_item_new_with_label("Quit");
5056
5057 /* Aggiungiamoli al menu' */
5058 gtk_menu_append( GTK_MENU(file_menu), open_item);
5059 gtk_menu_append( GTK_MENU(file_menu), save_item);
5060 gtk_menu_append( GTK_MENU(file_menu), quit_item);
5061
5062
5063 /* Colleghiamo le funzioni di callback al segnale activate */
5064 gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
5065                            GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.open");
5066 gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
5067                            GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.save");
5068
5069 /* Possiamo collegare l'elemento Quit alla nostra funzione di uscita */
5070 gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
5071                            GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit");
5072
5073 /* Abbiamo bisogno di mostrare gli elementi di menu' */
5074 gtk_widget_show( open_item );
5075 gtk_widget_show( save_item );
5076 gtk_widget_show( quit_item );
5077  </verb></tscreen>
5078
5079
5080 A questo punto abbiamo il nostro men&ugrave; Adesso abbiamo bisogno di creare una barra dei men&ugrave;
5081
5082 e un elemento di men&ugrave; per <tt/File/, a cui aggiungeremo il nostro men&ugrave;. Il codice &egrave; questo:
5083
5084
5085 <tscreen><verb>
5086 menu_bar = gtk_menu_bar_new();
5087 gtk_container_add( GTK_CONTAINER(window), menu_bar);
5088 gtk_widget_show( menu_bar );
5089
5090 file_item = gtk_menu_item_new_with_label("File");
5091 gtk_widget_show(file_item);
5092 </verb></tscreen>
5093
5094
5095 Ora dobbiamo associare il men&ugrave; con <tt/file_item/. Lo si pu&ograve; fare con la funzione
5096
5097 <tscreen>
5098 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
5099                                 GtkWidget *submenu);
5100 </tscreen>
5101
5102
5103 Quindi, il nostro esempio continuerebbe con
5104
5105 <tscreen><verb>
5106 gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu);
5107 </verb></tscreen>
5108
5109
5110 Ci&ograve; che manca a questo punto &egrave; di collegare il men&ugrave; alla barra, cosa che si pu&ograve; ottenere tramite la funzione
5111
5112 <tscreen>
5113 void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
5114 </tscreen>
5115
5116 che nel nostro caso &egrave;:
5117
5118 <tscreen><verb>
5119 gtk_menu_bar_append( menu_bar, file_item );
5120 </verb></tscreen>
5121
5122
5123 Se volessimo il men&ugrave; giustificato a dstra, come sono spesso i men&ugrave; di aiuto, potremm
5124
5125 usare la seguente funzioe (di nuovo su <tt/file_item/  in questo esempio) prima di fare il collegamento alla barra.
5126
5127
5128 <tscreen><verb>
5129 void gtk_menu_item_right_justify (GtkMenuItem *menu_item);
5130 </verb></tscreen>
5131 Ecco un riassunto dei passi necessari per creare una barra con i relativi men&ugrave; collegati:
5132
5133 <itemize>
5134 <item>  Create un nuovo men&ugrave; con gtk_menu_new()
5135 <item>  Usate delle chiamate multiple a gtk_menu_item_new() per ognuno degli
5136   elementi che volete mettere nel vostro men&ugrave;. Usate inoltre gtk_menu_item_append()
5137   per mettere ciascuno di questi nuovi elementi sul men&ugrave;..
5138 <item> Create un elemento di men&ugrave; usando gtk_menu_item_new(). Questo rappresenta l'elemento di base 
5139
5140 delmen&ugrave;, e il testo relativo sar&agrave; il testo mostrato sulla barra dei men&ugrave; stessa.
5141
5142 <item> Usate gtk_menu_item_set_submenu() per collegare i men&ugrave; all'elemento base del men&ugrave; (cio&egrave; quello creato al passaggio precedente).
5143
5144 <item>  Create una nuova barra di men&ugrave; usando gtk_menu_bar_new. Questo passo
5145   necessita di essere effettuato una sola volta quando si crea una serie di
5146   men&ugrave; su una sola barra.
5147 <item> Usate gtk_menu_bar_append per mettere il men&ugrave; base sulla barra dei men&ugrave;.
5148 </itemize>
5149 <p>
5150 Creare un men&ugrave; a comparsa &egrave; pi&ugrave; o meno la stessa cosa. La differenza &egrave; che il
5151 il men&ugrave; non viene attivato ``automaticamente'' da una barra, bens&igrave; per esempio
5152 con la chiamata espicita alla funzione gtk_menu_popup() da parte di un evento di pressione di un pulsante.
5153 Seguite questi passaggi:
5154 <itemize>
5155 <item>Create una funzione di gestione di un evento. Essa deve seguire il prototipo
5156 <tscreen>
5157 static gint handler(GtkWidget *widget, GdkEvent *event);
5158 </tscreen>
5159 e usare l'evento per scoprire dove il menu deve essere fatto comparire.
5160 <item>Nel gestore di evento, se questo &egrave; la pressione di un bottone, trattate
5161 <tt>event</tt> come l'evento relativo ad un bottone (cosa che in effetti &egrave;)
5162 e usatelo come mostrato nel codice di esempio per passare informazioni a
5163 gtk_menu_popup().
5164 <item>Collegate il gestore di evento a un widget con
5165 <tscreen>
5166 gtk_signal_connect_object(GTK_OBJECT(widget), "event",
5167                           GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu));
5168 </tscreen>
5169 in cui <tt>widget</tt> &egrave; il widget a cui state effettuando il collegamento, e
5170 <tt>handler</tt> &egrave; la funzione di gestione, mentre <tt>menu</tt> &egrave; un men&ugrave;
5171 creato con gtk_menu_new(). Quest'ultimo pu&ograve; essere un men&ugrave; che viene anche
5172 attivato da una barra di men&ugrave;, come mostrato nel codice di esempio.
5173 </itemize>
5174
5175
5176 <!-- ----------------------------------------------------------------- -->
5177 <sect1>Esempio di Men&ugrave; Manuale
5178 <p>
5179 Per la teoria dovrebbe essere abbastanza. Diamo un'occhiata ad un esempio che
5180 ci aiuti a chiarire le cose.
5181
5182 <tscreen><verb>
5183 /* menu.c */
5184 #include <gtk/gtk.h>
5185
5186 static gint button_press (GtkWidget *, GdkEvent *);
5187 static void menuitem_response (gchar *);
5188
5189 int main (int argc, char *argv[])
5190 {
5191
5192     GtkWidget *window;
5193     GtkWidget *menu;
5194     GtkWidget *menu_bar;
5195     GtkWidget *root_menu;
5196     GtkWidget *menu_items;
5197     GtkWidget *vbox;
5198     GtkWidget *button;
5199     char buf[128];
5200     int i;
5201
5202     gtk_init (&amp;argc, &amp;argv);
5203
5204     /* crea una nuova finestra */
5205     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
5206     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
5207
5208     gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
5209     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
5210                        (GtkSignalFunc) gtk_main_quit, NULL);
5211
5212     /* Inizializziamo il men&ugrave;, e ricordate: mai applicare
5213      * gtk_show_widget() al widget men&ugrave;!!
5214      * Questo &egrave; il men&ugrave; che contiene gli elementi, quello che
5215      * spunta quando si fa click sul "Men&ugrave; radice" nell'applicazione */
5216     menu = gtk_menu_new();
5217
5218     /* Ora creiamo un ciclo che crea tre elementi di menu per "test-menu".
5219      * Notete la chiamata a gtk_menu_append. In questo punto aggiungiamo una
5220      * lista di elementi al nostro men&ugrave;. Normalmente, dovremmo poi catturare
5221      * il segnale di attivazione per ognuno degli elementi del menu, e creare
5222      * una funzione di ritorno per ciascuno di essi, ma qui non li mettiamo per
5223      * brevit&agrave;. */
5224
5225     for(i = 0; i < 3; i++)
5226         {
5227             /* Copia i nomi in buf. */
5228             sprintf(buf, "Test-undermenu - %d", i);
5229
5230             /* Crea un nuovo elemento di men&ugrave; con un nome... */
5231             menu_items = gtk_menu_item_new_with_label(buf);
5232
5233             /* ...e aggiungilo al men&ugrave;. */
5234             gtk_menu_append(GTK_MENU (menu), menu_items);
5235
5236             /* Fa qualcosa di interessante quando si seleziona l'elemento */
5237             gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
5238                 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
5239
5240             /* Mostra il widget */
5241             gtk_widget_show(menu_items);
5242         }
5243
5244     /* Questo &egrave; il men&ugrave; radice, e l'etichetta sar&agrave; il nome del men&ugrave; che
5245      * verr&agrave; mostrato sulla barra dei men&ugrave;. Non ci sar&agrave; alcun gestore di
5246      * segnale collegato, dal momento che non fa altro che mostrare il resto
5247      * del men&ugrave; quando viene premuto. */
5248     root_menu = gtk_menu_item_new_with_label("Root Menu");
5249
5250     gtk_widget_show(root_menu);
5251
5252
5253
5254
5255     /* Ora specifichiamo che vogliamo che il men&ugrave; che abbiamo appena creato
5256      * sia il men&ugrave; radice *//
5257     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
5258
5259     /* Una vbox in cui mettere un men&ugrave; ed un bottone: */
5260     vbox = gtk_vbox_new(FALSE, 0);
5261     gtk_container_add(GTK_CONTAINER(window), vbox);
5262     gtk_widget_show(vbox);
5263
5264     /* Crea una barra dei men&ugrave; per metterci i men&ugrave; e l'aggiunge alla finestra principale */
5265     menu_bar = gtk_menu_bar_new();
5266     gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
5267     gtk_widget_show(menu_bar);
5268
5269     /* Crea un bottone a cui collegare un men&ugrave; */
5270     button = gtk_button_new_with_label("press me");
5271     gtk_signal_connect_object(GTK_OBJECT(button), "event",
5272         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
5273     gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
5274     gtk_widget_show(button);
5275
5276     /* E finalmente attacchiamo l'elemento di men&ugrave; alla barra dei men&ugrave; -- questo
5277      * &egrave; l'elemento di men&ugrave; "radice" di cui parlavo */
5278     gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
5279
5280     /* La finestra va mostrata sempre come ultimo passo in modo che sia gi&agrave;
5281      * completa di tutti i suoi elementi. */
5282     gtk_widget_show(window);
5283
5284     gtk_main ();
5285
5286     return 0;
5287 }
5288
5289
5290
5291 /* Risponde alla pressione di un bottone impostando un men&ugrave; che
5292  * viene passato come widget.
5293  * Notate che l'argomento "widget" si riferisce al men&ugrave; impostato
5294  * e NON al bottone premuto.
5295  */
5296
5297 static gint button_press (GtkWidget *widget, GdkEvent *event)
5298 {
5299
5300     if (event->type == GDK_BUTTON_PRESS) {
5301         GdkEventButton *bevent = (GdkEventButton *) event; 
5302         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
5303                         bevent->button, bevent->time);
5304         /* Riferisce al codice chiamante che abbiamo trattato l'evento;
5305          * la faccenda finisce qui. */
5306         return TRUE;
5307     }
5308
5309     /* Riferisce al codice chiamante che abbiamo trattato l'evento; passa avanti. */
5310     return FALSE;
5311 }
5312
5313
5314 /* Stampa una stringa quando viene selezionato un elemento di men&ugrave; */
5315
5316 static void menuitem_response (gchar *string)
5317 {
5318     printf("%s\n", string);
5319 }
5320 </verb></tscreen>
5321
5322 Si pu&ograve; anche fare in modo che un elemento di men&ugrave; sia insensibile e, usando
5323 una tabella di acelleratori, collegare dei tasti a delle funzioni di men&ugrave;.
5324
5325
5326 <!-- ----------------------------------------------------------------- -->
5327 <sect1>Usare GtkMenuFactory
5328 <p>
5329 Ora che vi abbiamo mostrato il modo difficile, ecco invece come si fa usando
5330 le chiamate di gtk_menu_factory.
5331
5332
5333 <!-- ----------------------------------------------------------------- -->
5334 <sect1>Esempio di Menu Factory
5335 <p>
5336 Ecco un esempio di utilizzo della ``Fabbrica'' di Men&ugrave; di GTK (Menu Factory). 
5337 Questo &egrave; il primo file, menufactoy.h. Teniemo dei file menufactory.c e main.c separati
5338 a causa delle variabili globali usate nel file menufactory.c.
5339
5340 <tscreen><verb>
5341
5342 /* menufactory.h */
5343
5344 #ifndef __MENUFACTORY_H__
5345 #define __MENUFACTORY_H__
5346  
5347 #ifdef __cplusplus
5348 extern "C" {
5349 #endif /* __cplusplus */
5350
5351 void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);
5352 void menus_create(GtkMenuEntry *entries, int nmenu_entries);
5353
5354 #ifdef __cplusplus
5355 }
5356 #endif /* __cplusplus */
5357
5358 #endif /* __MENUFACTORY_H__ */
5359
5360 </verb></tscreen>
5361 <p>
5362 Ed ecco il file menufactory.c.
5363
5364 <tscreen><verb>
5365 /* menufactory.c */
5366 #include <gtk/gtk.h>
5367 #include <strings.h>
5368
5369 #include "mfmain.h"
5370
5371 static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path);
5372 static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path);
5373 void menus_init(void);
5374 void menus_create(GtkMenuEntry * entries, int nmenu_entries);
5375
5376 /* Questa &egrave; la struttuta GtkMenuEntry, che viene usata per creare dei nuovi
5377  * men&ugrave;. Il primo membro &agrave; la stringa di definizione del men&ugrave;. Il secondo
5378  * &egrave; il tasto acceleratore predefinito, usato per accedere a questa funzione
5379  * con la tastiera. Il terzo &egrave; la funzione di ritorno che viene chiamata
5380  * quando si seleziona con la tastiera o il mouse questo elemento di men&ugrave;.
5381  * L'ultimo membro costituisce il dato che viene passato alla funzione di
5382  * ritorno. */
5383
5384 static GtkMenuEntry menu_items[] =
5385 {
5386         {"<Main>/File/New", "<control>N", NULL, NULL},
5387         {"<Main>/File/Open", "<control>O", NULL, NULL},
5388         {"<Main>/File/Save", "<control>S", NULL, NULL},
5389         {"<Main>/File/Save as", NULL, NULL, NULL},
5390         {"<Main>/File/<separator>", NULL, NULL, NULL},
5391         {"<Main>/File/Quit", "<control>Q", file_quit_cmd_callback, "OK, I'll quit"},
5392         {"<Main>/Options/Test", NULL, NULL, NULL}
5393 };
5394
5395 /* calcola il numero di menu_item */
5396 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
5397
5398 static int initialize = TRUE;
5399 static GtkMenuFactory *factory = NULL;
5400 static GtkMenuFactory *subfactory[1];
5401 static GHashTable *entry_ht = NULL;
5402
5403 void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table)
5404 {
5405     if (initialize)
5406             menus_init();
5407     
5408     if (menubar)
5409             *menubar = subfactory[0]->widget;
5410     if (table)
5411             *table = subfactory[0]->table;
5412 }
5413
5414 void menus_init(void)
5415 {
5416     if (initialize) {
5417         initialize = FALSE;
5418         
5419         factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
5420         subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
5421         
5422         gtk_menu_factory_add_subfactory(factory, subfactory[0], "<Main>");
5423         menus_create(menu_items, nmenu_items);
5424     }
5425 }
5426
5427 void menus_create(GtkMenuEntry * entries, int nmenu_entries)
5428 {
5429     char *accelerator;
5430     int i;
5431     
5432     if (initialize)
5433             menus_init();
5434     
5435     if (entry_ht)
5436             for (i = 0; i < nmenu_entries; i++) {
5437                 accelerator = g_hash_table_lookup(entry_ht, entries[i].path);
5438                 if (accelerator) {
5439                     if (accelerator[0] == '\0')
5440                             entries[i].accelerator = NULL;
5441                     else
5442                             entries[i].accelerator = accelerator;
5443                 }
5444             }
5445     gtk_menu_factory_add_entries(factory, entries, nmenu_entries);
5446     
5447     for (i = 0; i < nmenu_entries; i++)
5448             if (entries[i].widget) {
5449                 gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator",
5450                                    (GtkSignalFunc) menus_install_accel,
5451                                    entries[i].path);
5452                 gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator",
5453                                    (GtkSignalFunc) menus_remove_accel,
5454                                    entries[i].path);
5455             }
5456 }
5457
5458 static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path)
5459 {
5460     char accel[64];
5461     char *t1, t2[2];
5462     
5463     accel[0] = '\0';
5464     if (modifiers & GDK_CONTROL_MASK)
5465             strcat(accel, "<control>");
5466     if (modifiers & GDK_SHIFT_MASK)
5467             strcat(accel, "<shift>");
5468     if (modifiers & GDK_MOD1_MASK)
5469             strcat(accel, "<alt>");
5470     
5471     t2[0] = key;
5472     t2[1] = '\0';
5473     strcat(accel, t2);
5474     
5475     if (entry_ht) {
5476         t1 = g_hash_table_lookup(entry_ht, path);
5477         g_free(t1);
5478     } else
5479             entry_ht = g_hash_table_new(g_str_hash, g_str_equal);
5480     
5481     g_hash_table_insert(entry_ht, path, g_strdup(accel));
5482     
5483     return TRUE;
5484 }
5485
5486 static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path)
5487 {
5488     char *t;
5489     
5490     if (entry_ht) {
5491         t = g_hash_table_lookup(entry_ht, path);
5492         g_free(t);
5493         
5494         g_hash_table_insert(entry_ht, path, g_strdup(""));
5495     }
5496 }
5497
5498 void menus_set_sensitive(char *path, int sensitive)
5499 {
5500     GtkMenuPath *menu_path;
5501     
5502     if (initialize)
5503             menus_init();
5504     
5505     menu_path = gtk_menu_factory_find(factory, path);
5506     if (menu_path)
5507             gtk_widget_set_sensitive(menu_path->widget, sensitive);
5508     else
5509             g_warning("Impossibile assegnare sensibilit&agrave; a men&ugrave; inesistente: %s", path);
5510 }
5511
5512 </verb></tscreen>
5513 <p>
5514 Ed ecco mfmain.h
5515
5516 <tscreen><verb>
5517 /* mfmain.h */
5518
5519
5520
5521 #ifndef __MFMAIN_H__
5522 #define __MFMAIN_H__
5523
5524 #ifdef __cplusplus
5525 extern "C" {
5526 #endif /* __cplusplus */
5527
5528 void file_quit_cmd_callback(GtkWidget *widget, gpointer data);
5529
5530 #ifdef __cplusplus
5531 }
5532 #endif /* __cplusplus */
5533
5534 #endif /* __MFMAIN_H__ */
5535
5536 </verb></tscreen>
5537 <p>
5538 E mfmain.c
5539
5540 <tscreen><verb>
5541 /* mfmain.c */
5542
5543
5544
5545 #include <gtk/gtk.h>
5546
5547 #include "mfmain.h"
5548 #include "menufactory.h"
5549
5550
5551 int main(int argc, char *argv[])
5552 {
5553     GtkWidget *window;
5554     GtkWidget *main_vbox;
5555     GtkWidget *menubar;
5556     
5557     GtkAcceleratorTable *accel;
5558     
5559     gtk_init(&amp;argc, &amp;argv);
5560     
5561     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
5562     gtk_signal_connect(GTK_OBJECT(window), "destroy", 
5563                        GTK_SIGNAL_FUNC(file_quit_cmd_callback), 
5564                        "WM destroy");
5565     gtk_window_set_title(GTK_WINDOW(window), "Menu Factory");
5566     gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
5567     
5568     main_vbox = gtk_vbox_new(FALSE, 1);
5569     gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
5570     gtk_container_add(GTK_CONTAINER(window), main_vbox);
5571     gtk_widget_show(main_vbox);
5572     
5573     get_main_menu(&amp;menubar, &amp;accel);
5574     gtk_window_add_accelerator_table(GTK_WINDOW(window), accel);
5575     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
5576     gtk_widget_show(menubar);
5577     
5578     gtk_widget_show(window);
5579     gtk_main();
5580     
5581     return(0);
5582 }
5583
5584 /* Questo &egrave; per mostrare come si usano le funzioni di ritorno quando 
5585  * si utilizza la MenuFactory. Spesso, si mettono tutte le funzioni di
5586  * callback in un file separato, e le si fanno chiamare le funzioni
5587  * appropriate da l&igrave;. Cos&igrave; le cose sono pi&ugrave; organizzate. */
5588 void file_quit_cmd_callback (GtkWidget *widget, gpointer data)
5589 {
5590     g_print ("%s\n", (char *) data);
5591     gtk_exit(0);
5592 }
5593 </verb></tscreen>
5594 <p>
5595 Ed infine un bel makefile per semplificare la compilazione.
5596
5597 <tscreen><verb>
5598
5599 # Makefile.mf
5600
5601
5602 CC      = gcc
5603 PROF    = -g
5604 C_FLAGS =  -Wall $(PROF) -L/usr/local/include -DDEBUG
5605 L_FLAGS =  $(PROF) -L/usr/X11R6/lib -L/usr/local/lib 
5606 L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lm
5607 PROGNAME = menufactory
5608
5609 O_FILES = menufactory.o mfmain.o
5610
5611 $(PROGNAME): $(O_FILES)
5612         rm -f $(PROGNAME)
5613         $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS)
5614
5615 .c.o: 
5616         $(CC) -c $(C_FLAGS) $<
5617
5618 clean: 
5619         rm -f core *.o $(PROGNAME) nohup.out
5620 distclean: clean 
5621         rm -f *~
5622 </verb></tscreen>
5623 <p>
5624 Per il momento, accontentatevi di questo esempio. Pi&ugrave; avanti aggiungeremo
5625 una spiegazione ed un bel po' di commenti.
5626
5627  
5628 <!-- ***************************************************************** -->
5629 <sect> Widget "Testo" (Text Widget)
5630 <!-- ***************************************************************** -->
5631 <p>
5632 Il widget di testo permette di mostrare e modificare del testo disposto su pi&ugrave;
5633 linee. Questo widget supporta sia la presenza di diversi colori che di diversi font
5634 contemporaneamente, permettendo di mischiarli nel modo in cui si desidera. Mette poi a
5635 disposizione un ampio gruppo di comandi basati sulla tastiera, che sono compatibili con
5636 Emacs.
5637
5638 Il widget di testo d&agrave; la possibilit&agrave; di fare taglia e incolla in modo
5639 completo, compreso l'uso del doppio e triplo click per selezionare un'intera parola o
5640 un'intera linea.
5641
5642 <!-- ----------------------------------------------------------------- -->
5643 <sect1>Creazione e configurazione di una casella di testo
5644 <p>
5645 Esiste un'unica funzione per la creazione di un nuovo widget di testo:
5646 <tscreen><verb>
5647 GtkWidget* gtk_text_new (GtkAdjustment *hadj,
5648                          GtkAdjustment *vadj);
5649 </verb></tscreen>
5650
5651 Gli argomenti di questa chiamata ci permettono di assegnare dei puntatori a dei
5652 valori che stabiliscono il punto di vista del widget. Passare dei valori NULL all'uno
5653 o all'altro o ad entrambi questi argomenti, f&agrave; s&igrave; che gtk_text_new li
5654 crei automaticamente.
5655
5656 <tscreen><verb>
5657 void gtk_text_set_adjustments (GtkText       *text,
5658                                GtkAdjustment *hadj,
5659                                GtkAdjustment *vadj);
5660 </verb></tscreen>
5661
5662 La funzione precedente permette di cambiare gli aggiustamenti orizzontale e verticale
5663 di un widget di testo i ogni momento.
5664
5665 Il widget di testo non &grave; di creare delle barre di scorrimento quando la
5666 quantit&agrave; &egrave; troppo grande per la finestra. Dobbiamo quindi crearle e
5667 aggiungerle alla finestra noi stessi.
5668
5669 <tscreen><verb>
5670   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
5671   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
5672   gtk_widget_show (vscrollbar);
5673 </verb></tscreen>
5674
5675 Il pezzetto di codice precedente crea una nuova barra di scorrimento verticale e la
5676 collega all'aggiustamento verticale del widget di testo, <tt/text/, dopodich&eacute; la
5677 impacchetta nella hbox al solito modo.
5678
5679 Ci sono due modi principali di utilizzo di un widget di testo: per permettere all'utente
5680 di editare del testo, oppure per permettere a noi di mostrare all'utente del testo
5681 disposto su pi&ugrave; righe. Per passare dall'una all'altra di queste modalit&agrave;,
5682 il widget di testo ci mette a disposizione la seguente funzione:
5683
5684 <tscreen><verb>
5685 void gtk_text_set_editable    (GtkText *text,
5686                                gint    editable);
5687 </verb></tscreen>
5688
5689 L'argomento <tt/editable/ &egrave; un valore TRUE o FALSE che specifica se l'utente
5690 pu&ograve; modificare o meno il contenuto del widgte. Quando il widget &egrave;
5691 modificabile, mostrer&agrave; un cursore nel punto di inserimento corrente.
5692
5693 Niente per&ograve; vi obbliga ad usare il widget di testo in questi due soli modi. Si
5694 pu&ograve; passare dall'una all'altra delle due modalit&agrave; in qualsiasi momento,
5695 e si pu&ograve; inserire del testo in ogni momento.
5696
5697 Il widget di testo &egrave; in grado di andare a capo automaticamente quando delle linee
5698 di testo sono troppo lunghe per stare su una sola linea della finestra. Il comportamento
5699 predefinito &egrave; di andare a capo automaticamente al termine della linea. Questo
5700 pu&ograve; essere cambiato con la seguente funzione:
5701
5702 <tscreen><verb>
5703 void gtk_text_set_word_wrap (GtkText *text,
5704                              gint    word_wrap);
5705 </verb></tscreen>
5706
5707 L'uso di questa funzione ci permette di specificare se il widget di testo deve spezzare
5708 o no le linee lunghe ai bordi della finestra. L'argomento <tt/word_wrap/ &egrave; un
5709 valore di tipo TRUE o FALSE.
5710
5711 <!-- ----------------------------------------------------------------- -->
5712 <sect1>Manipolazione del testo
5713 <P>
5714 Il punto di inserimento corrente del widget pu&ograve; essere stabilito usando
5715 <tscreen><verb>
5716 void gtk_text_set_point (GtkText *text,
5717                          guint   index);
5718 </verb></tscreen>
5719 in cui <tt/index/ &egrave; la posizione in cui mettere il punto di inserimento.
5720
5721 La funzione per ottenere la posizione di inserimento corrente &egrave; analoga:
5722 <tscreen><verb>
5723 guint gtk_text_get_point (GtkText *text);
5724 </verb></tscreen>
5725
5726 Una funzione che &egrave; utile in combinazione con le precedenti due &egrave;
5727 <tscreen><verb>
5728 guint gtk_text_get_length (GtkText *text);
5729 </verb></tscreen>
5730 la quale restituisce la lunghezza corrente del widget di testo. La lunghezza &egrave;
5731 definita come il numero di caratteri che si trovano nel blocco di testo della finestra,
5732 compresi i caratteri tipo CR, che marcano la fine delle linee.
5733
5734 Per inserire del testo alla posizione corrente del widget di testo, si usa la funzione
5735 gtk_text_insert, che permette anche di specificare i colori di primo piano e di sfondo
5736 per il testo, oltre al font da usare.
5737
5738 <tscreen><verb>
5739 void gtk_text_insert (GtkText    *text,
5740                       GdkFont    *font,
5741                       GdkColor   *fore,
5742                       GdkColor   *back,
5743                       const char *chars,
5744                       gint       length);
5745 </verb></tscreen>
5746
5747 Passare un valore di NULL come valore per il colore di primo piano (fore), di sfondo (back)
5748 o per il font, far&agrave; s&igrave; che vengano usati i valori che sono specifici dello
5749 stile del widget. Usare un valore di <tt/-1/ per il parametro lunghezza (length) avr&agrave;
5750 come risultato l'inserzione dell'intera stringa di testo.
5751
5752 Il widget di testo &egrave; uno dei pochi in GTK che vengono disegnati dinamicamente, fuori
5753 dalla funzione gtk_main. Ci&ograve; significa che tutti i cambiamenti al suo contenuto
5754 avranno effetto immediato. Questo pu&ograve; essere un comportamento indesiderabile quando
5755 si stanno facendo delle modifiche multiple al contenuto del widget. Per permettere di 
5756 operare cambiamenti multipli sul widget senza che esso si ridisegni continuamente,
5757 si pu&ograve; congelare il contenuto della finestra, in modo che esso interrompa
5758 temporaneamente di ridisegnarsi. Potremo poi sbloccare il widget una volta che tutte
5759 le modifiche sono state completate.
5760
5761 Le due seguenti funzioni fanno il congelamento e lo sbloccaggio (thaw) del widget:
5762
5763 <tscreen><verb>
5764 void gtk_text_freeze (GtkText *text);
5765 void gtk_text_thaw   (GtkText *text);         
5766 </verb></tscreen>
5767
5768 Il testo pu&ograve; essere cancellato nel widget di testo a partire dal punto di
5769 inserimento corrente usando le seguenti due funzioni, andando all'indietro (backward)
5770 o all'avanti (forward):
5771
5772 <tscreen><verb>
5773 gint gtk_text_backward_delete (GtkText *text,
5774                                guint   nchars);
5775 gint gtk_text_forward_delete  (GtkText *text,
5776                                guint   nchars);
5777 </verb></tscreen>
5778
5779 Quando si vuole recuperare il contenuto del widget di testo, &egrave;
5780 disponibile la macro <tt/GTK_TEXT_INDEX(t, index)/, che permette di
5781 ottenere il crattere alla posizione <tt/index/ all'interno del widget
5782 <tt/t/.
5783
5784 Per ecuperare un blocco di testo pi&ugrave; ampio, si usa la funzione:
5785
5786 <tscreen><verb>
5787 gchar *gtk_editable_get_chars (GtkEditable *editable,
5788                                gint        start_pos,
5789                                gint        end_pos);   
5790 </verb></tscreen>
5791
5792 Questa &egrave; una funzione della classe madre del widget di testo. Un valore
5793 di -1 per <tt/end_pos/, sta ad indicare la fine del testo. L'indice per il
5794 testo parte da 0.
5795
5796 Questa funzione alloca una nuova porzione di memoria per il blocco di testo,
5797 per cui non dimenticate di liberarla con una chiamata a g_free quando non
5798 ne avete pi&ugrave; bisogno.
5799  
5800 <!-- ----------------------------------------------------------------- -->
5801 <sect1>Keyboard Shortcuts
5802 <p>
5803 Il widget di testo mette a disposizione un certo numero di scorciatoie da tastiera
5804 per le pi&ugrave; comuni operazioni di modifica, movimento e selezione. Si possono
5805 utilizzare con delle combinazioni che comprendono i tasti Control e Alt.
5806
5807 Oltre a queste, mantenendo premuto il pulsante Control mentre si usano i tasti di
5808 movimento del cursore, causer&agrave; lo spostamento parola per parola invece che
5809 carattere per carattere. Mantenere invece premuto il tasto Shift mentre si sposta il
5810 cursore, causer&agrave; l'estensione della selezione.
5811
5812 <sect2>Scorciatoie per il movimento
5813 <p>
5814 <itemize>
5815 <item> Ctrl-A   Inizio della linea
5816 <item> Ctrl-E   Fine della linea
5817 <item> Ctrl-N   Prossima linea
5818 <item> Ctrl-P   Linea precedente
5819 <item> Ctrl-B   Indietro di un carattere
5820 <item> Ctrl-F   Avanti di un carattere
5821 <item> Alt-B    Indietro di una parola
5822 <item> Alt-F    Avanti di una parola
5823 </itemize>
5824
5825 <sect2>Scorciatoie per la modifica
5826 <p>
5827 <itemize>
5828 <item> Ctrl-H   Cancella il carattere precedente (Backspace)
5829 <item> Ctrl-D   Cancella il carattere successivo (Delete)
5830 <item> Ctrl-W   Cancella la parola precedente
5831 <item> Alt-D    Cancella la parola successiva
5832 <item> Ctrl-K   Cancella fino alla fine della linea
5833 <item> Ctrl-U   Cancella la linea
5834 </itemize>
5835
5836 <sect2>Scorciatoie per la selezione
5837 <p>
5838 <itemize>
5839 <item> Ctrl-X   Taglia
5840 <item> Ctrl-C   Copia
5841 <item> Ctrl-V   Incolla
5842 </itemize>
5843
5844
5845 <!-- ***************************************************************** -->
5846 <sect> Widget non documentati
5847 <!-- ***************************************************************** -->
5848
5849 <p>
5850 Per questi sarebbe utile il contributo degli autori! :) Prendete in
5851 considerazione la possibilit&agrave; di contribuire al nostro tutorial.
5852
5853 Se dovete usare uno di questi widget non documentati, vi suggeriamo
5854 caldamente di dare un'occhiata ai loro rispettivi file header nella 
5855 distribuzione di GTK. I nomi delle funzioni di GTK sono molto descrittivi.
5856 Non appena si capisce come funzionano le cose, non &egrave; 
5857 difficile dedurre il modo d'uso di un widget semplicemente guardando la
5858 dichiarazione di funzione ad esso associata. Aggiungendo a questo qualche
5859 spunto tratto dal codice di altri non dovrebbero esserci problemi.
5860
5861 Quando avrete raggiunto una comprensione globale di tutte le funzioni
5862 di un widget non documentato, considerate la possibilit&agrave; di scrivere
5863 un tutorial su di esso, in modo che altri possano beneficiare del
5864 vostro lavoro.
5865
5866 <!-- ----------------------------------------------------------------- -->
5867 <sect1> Controlli di intervallo (Range Controls)
5868
5869 <!-- ----------------------------------------------------------------- -->
5870 <sect1> Anteprime
5871 <!--
5872 (Potrebbe essere necessario riscrivere questa parte per conformarsi allo stile
5873 del resto del tutorial)
5874 -->
5875 <p>
5876 Le anteprime servono a un certo numero di cose in GIMP/GTK. La pi&ugrave;
5877 importante &egrave; questa: a risoluzioni molto alte le immagini possono
5878 facilmente occupare diverse decine di megabyte di memoria; ogni operazione
5879 su immagini cos&igrave; grosse pu&ograve richiedere molto tempo. Se per la
5880 scelta di una data modifica vi occorrono 5-10 tentativi (cio&egrave; 10-20
5881 passi, poich&eacute; &egrave; necessario ripristinare l'originale se si 
5882 &egrave; commesso un errore), possono volerci letteralmente delle ore per
5883 fare quella giusta - se non si rimane a corto di memoria prima! Coloro che
5884 hanno passato ore in camera oscura conoscono la sensazione. In questi casi
5885 le anteprime sono utilissime!
5886
5887 Ma la seccatura dell'attesa non &egrave; l'unico caso. Spesso &egrave; utile
5888 confrontare la versione precedente con la successiva affiancandole, o almeno
5889 alternandole. Se si sta lavorando con grandi immagini e ritardi di una decina
5890 di secondi un confronto efficace &egrave; quantomeno difficile da fare.
5891 Per immagini di 30 mega (4 pollici per 6 pollici, 600 punti per pollice, 24 bit)
5892 tale confronto risulta impraticabile per la maggior parte degli utenti. In
5893 questo caso le anteprime sono di grande aiuto!  
5894
5895 Ma c'&egrave; di pi&ugrave;. Con le anteprime &egrave; possibile scrivere
5896 plug-in per ottenere addirittura anteprime di anteprime (per esempio, la
5897 simulazione del pacchetto di filtri). Questi plug-in possono cos&igrave;
5898 fornire un certo numero di anticipazioni di quel che si otterrebbe applicando
5899 certe opzioni. Un simile approccio funziona come una tavolozza di anteprime,
5900 ed &egrave; molto efficace per piccoli cambiamenti!  
5901
5902 Non &egrave; finita. Per alcuni plug-in pu&ograve; essere necessario un
5903 intervento umano in tempo reale specifico per ogni immagine. Nel plug-in 
5904 SuperNova, ad esempio, vengono chieste le coordinate del centro della
5905 futura supernova. Il modo pi&ugrave; semplice per fare questo &egrave;
5906 senza dubbio quello di mostrare un'anteprima all'utente chiedendogli di
5907 selezionare interattivamente il centro.
5908
5909 Infine, un paio di applicazioni tipiche. Le anteprime possono essere usate
5910 anche quando non si sta lavorando con grandi immagini. Per esempio, sono 
5911 utili quando si stanno calcolando dei pattern complicati (date un'occhiata
5912 al venerabile plug in ``Diffraction'' e a molti altri!). Altro esempio:
5913 date un'occhiata al plug-in di rotazione della mappa dei colori (in allestimento).
5914 Le anteprime possono anche essere usate per visualizzare in un plug-in
5915 piccoli logo o, addirittura, l'immagine dell'Autore!
5916
5917 Quando non usare le anteprime
5918
5919 Le anteprime non vanno usate per grafici, disegni ecc., poich&eacute; per 
5920 queste cose GDK &egrave; molto pi&ugrave; veloce. Le anteprime vanno usate
5921 solo per immagini derivate da un'elaborazione!
5922  
5923 Le anteprime possono essere inserite dappertutto. In un vbox, in un hbox,
5924 in una tabella, in un bottone, ecc. Sicuramente per&ograve; hanno il loro
5925 look migliore se bordate con delle cornici (frame). Le anteprime non hanno
5926 bordi propri e appaiono piatte senza (naturalmente, se quel che si vuole
5927 &egrave; proprio un aspetto piatto...). I bordi possono essere creati con
5928 delle cornici.
5929
5930                                [Image][Image]
5931
5932 Le anteprime sono per molti aspetti simili agli altri widget in GTK (con
5933 tutto ci&ograve; che questo implica), con l'eccezione di avere una
5934 caratteristica in pi&ugrave;: &egrave; necessario che siano riempite con
5935 qualche tipo di immagine! Inizialmente parleremo solo dell'aspetto GTK 
5936 delle anteprime e successivamente discuteremo di come riempirle.
5937
5938 Semplicemente:
5939
5940 <tscreen><verb>
5941                               /* Crea un widget di anteprima,
5942                                  inizializzane le dimensioni
5943                                  e visualizzalo */
5944 GtkWidget *preview;
5945 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
5946                               /* Alternativamente:
5947                               GTK_PREVIEW_GRAYSCALE);*/
5948 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
5949 gtk_widget_show(preview);
5950 my_preview_rendering_function(preview);
5951 </verb></tscreen>
5952
5953 Come gi&agrave; detto, le anteprime hanno un buon aspetto dentro le cornici,
5954 quindi:
5955
5956 <tscreen><verb>
5957 GtkWidget *create_a_preview(int        Width,
5958                             int        Height,
5959                             int        Colorfulness)
5960 {
5961   GtkWidget *preview;
5962   GtkWidget *frame;
5963   
5964   frame = gtk_frame_new(NULL);
5965   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
5966   gtk_container_border_width (GTK_CONTAINER(frame),0);
5967   gtk_widget_show(frame);
5968
5969   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
5970                                        :GTK_PREVIEW_GRAYSCALE);
5971   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
5972   gtk_container_add(GTK_CONTAINER(frame),preview);
5973   gtk_widget_show(preview);
5974
5975   my_preview_rendering_function(preview);
5976   return frame;
5977 }
5978
5979 </verb></tscreen>
5980
5981 Questa &egrave; una semplice anteprima. Questa funzione restituisce la cornice
5982 ``madre'', in modo che sia possibile metterla in qualche altro posto nella vostra
5983 interfaccia. Naturalmente &egrave; possibile passare alla routine la cornice
5984 madre come parametro. In molte situazioni, comunque, il contenuto di un'anteprima
5985 viene aggiornato continuamente dall'applicazione; in questi casi potreste 
5986 preferire passare alla funzione ``create_a_preview()'' un puntatore 
5987 all'anteprima, ottenendone cos&igrave; il controllo dopo.
5988
5989 Un'avvertimento pi&ugrave; importante che potrebbe un giorno risparmiarvi 
5990 tanto tempo perso: a volte &egrave; preferibile etichettare le anteprime;
5991 ad esempio, &egrave; possibile etichettare l'anteprima contenente l'immagine 
5992 originale come ``Originale'' e quella contenente l'immagine modificata come 
5993 ``Modificata''. Potrebbe capitarvi di impacchettare in un vbox l'anteprima
5994 insieme con l'etichetta associata. L'insidia inattesa sta nel fatto che se
5995 l'etichetta &egrave; pi&ugrave; ampia dell'anteprima (cosa che pu&ograve;
5996 accadere per una variet&agrave; di motivi da voi non prevedibili, come il
5997 fatto che la dimensione dell'anteprima viene decisa dinamicamente, o la
5998 dimensione del font), la cornice si espande e non risulta pi&ugrave;
5999 perfettamente aderente all'anteprima. Questo stesso problema probabilmente
6000 pu&ograve; verificarsi anche in altre situazioni.
6001
6002                                    [Image]
6003
6004 La soluzione &egrave; quella di mettere l'anteprima e l'etichetta in una
6005 tabella 2x1 e di legarle insieme chiamando la funzione gtk_table_attach con
6006 i seguenti parametri (questa &egrave; una delle varianti possibili,
6007 naturalmente; l'importante &egrave; che non ci sia GTK_FILL nella seconda
6008 gtk_table_attach):
6009
6010 <tscreen><verb>
6011 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
6012                  0,
6013                  GTK_EXPAND|GTK_FILL,
6014                  0,0);
6015 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
6016                  GTK_EXPAND,
6017                  GTK_EXPAND,
6018                  0,0);
6019 </verb></tscreen>
6020
6021 Ed ecco il risultato:
6022
6023                                    [Image]
6024
6025 Altri suggerimenti
6026
6027 La maniera pi&ugrave; semplice per rendere cliccabile un'anteprima &egrave; 
6028 quella di metterla dentro un bottone. Questo ha anche l'effetto di aggiungere 
6029 un bel bordo attorno all'anteprima, il che rende superfluo metterla in una 
6030 cornice.
6031
6032 Questo &egrave; tutto per quel che riguarda GTK.
6033
6034
6035 Completare un'anteprima
6036
6037 Per impratichirci con le basi del completamento delle anteprime, creiamo
6038 il seguente disegno (trovato per tentativi):
6039
6040                                    [Image]
6041
6042 <tscreen><verb>
6043 void
6044 my_preview_rendering_function(GtkWidget     *preview)
6045 {
6046 #define SIZE 100
6047 #define HALF (SIZE/2)
6048
6049   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
6050   gint i, j;                             /* Coordinates    */
6051   double r, alpha, x, y;
6052
6053   if (preview==NULL) return; /* Di solito aggiungo questo per  */  
6054                              /* evitare piantamenti stupidi.   */
6055                              /* Probabilmente bisognerebbe     */
6056                              /* assicurarsi che tutto sia stato*/
6057                              /* inizializzato con successo     */
6058   for (j=0; j < ABS(cos(2*alpha)) ) {    /* Siamo dentro la sagoma?   */
6059                                          /* glib.h contiene ABS(x).   */
6060         row[i*3+0] = sqrt(1-r)*255;      /* Definisce il Rosso        */
6061         row[i*3+1] = 128;                /* Definisce il Verde        */
6062         row[i*3+2] = 224;                /* Definisce il Blu          */
6063       }                                  /* "+0" &egrave; per allineamento   */
6064       else {
6065         row[i*3+0] = r*255;
6066         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
6067         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
6068       }
6069     }
6070     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
6071     /* Inserisce "row" in "preview" a partire del punto avente */
6072     /* coordinate (0,j) prima colonna, j-esima riga, per SIZE  */
6073     /* pixel verso destra */
6074   }
6075
6076   free(row); /* libera un po' di memoria */
6077   gtk_widget_draw(preview,NULL); /* indovina cosa fa questo? */
6078   gdk_flush(); /* e questo? */
6079 }
6080 </verb></tscreen>
6081 Coloro che non usano GIMP probabilmente hanno gi&agrave; visto abbastanza
6082 per fare molte cose. Per gli utenti GIMP c'&egrave; ancora qualcosa da
6083 aggiungere.
6084  
6085 Anteprima dell'immagine
6086
6087 Probabilmente &egrave; opportuno tenere pronta una versione ridotta dell'immagine,
6088 grande quanto basta per riempire l'anteprima. Questo pu&ograve; essere fatto
6089 selezionando un pixel ogni n, dove n &egrave; il rapporto tra la dimensione
6090 dell'immagine e la dimensione dell'anteprima. Tutte le operazioni successive
6091 (compreso il riempimento dell'anteprima) sono fatte solo sul ridotto numero
6092 di pixel selezionati. Di seguito &egrave; riportata un'implementazione della
6093 riduzione dell'immagine (si tenga presente che ho preso solo lezioni basilari 
6094 di C!).
6095
6096
6097 (ATTENZIONE: CODICE NON VERIFICATO!!!)
6098
6099 <tscreen><verb>
6100
6101 typedef struct {
6102   gint      width;
6103   gint      height;
6104   gint      bbp;
6105   guchar    *rgb;
6106   guchar    *mask;
6107 } ReducedImage;
6108
6109 enum {
6110   SELECTION_ONLY,
6111   SELCTION_IN_CONTEXT,
6112   ENTIRE_IMAGE
6113 };
6114
6115 ReducedImage *Reduce_The_Image(GDrawable *drawable,
6116                                GDrawable *mask,
6117                                gint LongerSize,
6118                                gint Selection)
6119 {
6120   /* Questa funzione riduce l'immagine alla dimens. scelta per l'anteprima */
6121   /* La dimensione dell'anteprima &egrave; determinata da LongerSize, cio&egrave; la pi&ugrave; */
6122   /* grande delle dimensioni. Funziona solo per immagini RGB!              */
6123   gint RH, RW;          /* Altezza ridotta e larghezza ridotta             */
6124   gint width, height;   /* Larghezza e altezza dell'area da ridurre        */
6125   gint bytes=drawable->bpp;
6126   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
6127
6128   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
6129   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
6130   GPixelRgn srcPR, srcMask;
6131   gint NoSelectionMade=TRUE; /* Assumiamo di trattare l'intera immagine    */                                         
6132
6133   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
6134   width  = x2-x1;
6135   height = y2-y1;
6136   /* Se c'&egrave; una SELEZIONE, ne abbiamo avuto gli estremi! */
6137
6138   if (width != drawable->width &amp;&amp; height != drawable->height)
6139     NoSelectionMade=FALSE;
6140   /* Controlliamo se l'utente ha una selezione attiva. Questo         */
6141   /* diventer&agrave; importante dopo, alla creazione di una maschera ridotta */
6142
6143   /* Se si vuole l'anteprima dell'immagine intera, annulla quanto sopra */
6144   /* Naturalmente, in assenza di una selezione, questo non cambia nulla */
6145   if (Selection==ENTIRE_IMAGE) {
6146     x1=0;
6147     x2=drawable->width;
6148     y1=0;
6149     y2=drawable->height;
6150   }
6151
6152   /* Se si vuole l'anteprima di una selezione con parte dell'area   */
6153   /* circostante bisogna espanderla un po'.                         */
6154   if (Selection==SELECTION_IN_CONTEXT) {
6155     x1=MAX(0,                x1-width/2.0);
6156     x2=MIN(drawable->width,  x2+width/2.0);
6157     y1=MAX(0,                y1-height/2.0);
6158     y2=MIN(drawable->height, y2+height/2.0);
6159   }
6160
6161   /* Cos&igrave; si determinano larghezza e altezza dell'area da ridurre.   */
6162   width  = x2-x1;
6163   height = y2-y1;
6164
6165   /* Le linee seguenti determinano quale dimensione deve essere  il  */
6166   /* lato pi&ugrave; lungo. L'idea &egrave; presa dal plug-in supernova. Ritengo   */
6167   /* che avrei potuto pensarci da solo, ma la verit&agrave; va detta.       */
6168   /* Brutta cosa il plagio!                                          */
6169   if (width>height) {
6170     RW=LongerSize;
6171     RH=(float) height * (float) LongerSize/ (float) width;
6172   }
6173   else {
6174     RH=LongerSize;
6175     RW=(float)width * (float) LongerSize/ (float) height;
6176   }
6177
6178   /* L'intera immagine viene "stirata" in una stringa! */
6179   tempRGB   = (guchar *) malloc(RW*RH*bytes);
6180   tempmask  = (guchar *) malloc(RW*RH);
6181
6182   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
6183   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height, FALSE, FALSE);
6184
6185   /* Prendine abbastanza da contenere una riga di immagine e una di maschera */
6186   src_row       = (guchar *) malloc (width*bytes);
6187   src_mask_row  = (guchar *) malloc (width);
6188
6189   for (i=0; i < RH; i++) {
6190     whichrow=(float)i*(float)height/(float)RH;
6191     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
6192     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
6193
6194     for (j=0; j < RW; j++) {
6195       whichcol=(float)j*(float)width/(float)RW;
6196
6197       /* Nessuna selezione = tutti i punti sono completamente selezionati */
6198       if (NoSelectionMade)
6199         tempmask[i*RW+j]=255;
6200       else
6201         tempmask[i*RW+j]=src_mask_row[whichcol];
6202
6203       /* Aggiungi la riga alla lunga stringa che ora contiene l'immagine */
6204       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
6205       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
6206       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
6207
6208       /* Mantieni anche la trasparenza (alpha) */
6209       if (bytes==4)
6210         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
6211     }
6212   }
6213   temp->bpp=bytes;
6214   temp->width=RW;
6215   temp->height=RH;
6216   temp->rgb=tempRGB;
6217   temp->mask=tempmask;
6218   return temp;
6219 }
6220 </verb></tscreen>
6221
6222
6223 La seguente &egrave; una funzione di anteprima che usa lo stesso tipo
6224 ReducedImage! Si noti che usa una finta trasparenza - se ne &egrave; presente 
6225 una, tramite fake_transparency che &egrave; definita come segue:
6226
6227 <tscreen><verb>
6228 gint fake_transparency(gint i, gint j)
6229 {
6230   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
6231     return 64;
6232   else
6233     return 196;
6234 }
6235
6236 </verb></tscreen>
6237 E adesso la funzione per l'anteprima:
6238 <tscreen><verb>
6239 void
6240 my_preview_render_function(GtkWidget     *preview,
6241                            gint          changewhat,
6242                            gint          changewhich)
6243 {
6244   gint Inten, bytes=drawable->bpp;
6245   gint i, j, k;
6246   float partial;
6247   gint RW=reduced->width;
6248   gint RH=reduced->height;
6249   guchar *row=malloc(bytes*RW);;
6250
6251
6252   for (i=0; i < RH; i++) {
6253     for (j=0; j < RW; j++) {
6254
6255       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
6256       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
6257       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
6258
6259       if (bytes==4)
6260         for (k=0; k<3; k++) {
6261           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
6262           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
6263         }
6264     }
6265     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
6266   }
6267
6268   free(a);
6269   gtk_widget_draw(preview,NULL);
6270   gdk_flush();
6271 }
6272
6273 Funzioni Applicabili
6274
6275 guint           gtk_preview_get_type           (void);
6276 /* No idea */
6277 void            gtk_preview_uninit             (void);
6278 /* No idea */
6279 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
6280 /* Descritta precedentemente */
6281 void            gtk_preview_size               (GtkPreview      *preview,
6282                                                 gint             width,
6283                                                 gint             height);
6284 /* Permette di ridimensionare un'anteprima esistente */
6285 /* Pare che un bug in GTK renda disordinato questo   */
6286 /* processo. Un modo di rimettere le cose a posto    */
6287 /* &egrave; quello di ridimensionare manualmente            */
6288 /* la finestra contenente l'anteprima dopo aver      */
6289 /* ridimensionato l'anteprima.                       */
6290
6291 void            gtk_preview_put                (GtkPreview      *preview,
6292                                                 GdkWindow       *window,
6293                                                 GdkGC           *gc,
6294                                                 gint             srcx,
6295                                                 gint             srcy,
6296                                                 gint             destx,
6297                                                 gint             desty,
6298                                                 gint             width,
6299                                                 gint             height);
6300 /* No idea */
6301
6302 void            gtk_preview_put_row            (GtkPreview      *preview,
6303                                                 guchar          *src,
6304                                                 guchar          *dest,
6305                                                 gint             x,
6306                                                 gint             y,
6307                                                 gint             w);
6308 /* No idea */
6309
6310 void            gtk_preview_draw_row           (GtkPreview      *preview,
6311                                                 guchar          *data,
6312                                                 gint             x,
6313                                                 gint             y,
6314                                                 gint             w);
6315 /* Descritta nel testo */
6316
6317 void            gtk_preview_set_expand         (GtkPreview      *preview,
6318                                                 gint             expand);
6319 /* No idea */
6320
6321 /* Nessun indizio per le seguenti, ma  dovrebbero  */
6322 /* essere standard per la maggior parte dei widget */
6323 void            gtk_preview_set_gamma          (double           gamma);
6324 void            gtk_preview_set_color_cube     (guint            nred_shades,
6325                                                 guint            ngreen_shades,
6326                                                 guint            nblue_shades,
6327                                                 guint            ngray_shades);
6328 void            gtk_preview_set_install_cmap   (gint             install_cmap);
6329 void            gtk_preview_set_reserved       (gint             nreserved);
6330 GdkVisual*      gtk_preview_get_visual         (void);
6331 GdkColormap*    gtk_preview_get_cmap           (void);
6332 GtkPreviewInfo* gtk_preview_get_info           (void);
6333
6334 E' tutto!
6335
6336 </verb></tscreen>
6337
6338 <!-- ----------------------------------------------------------------- -->
6339 <sect1> Curve
6340 <p>
6341
6342 <!-- ***************************************************************** -->
6343 <sect>Il Widget EventBox<label id="sec_The_EventBox_Widget">
6344 <!-- ***************************************************************** -->
6345 <p> 
6346 Alcuni widget gtk non sono associati a finestre X, sicch&eacute;
6347 semplicemente disegnano sui loro genitori. Per questo motivo essi non possono 
6348 ricevere eventi e se sono sovradimensionati non vengono troncati, ma rischiano
6349 di sovrapporsi, generando confusione. Se si vuole di pi&ugrave; da questi 
6350 widget si pu&ograve; ricorrere agli EventBox.
6351
6352 A prima vista il widget EventBox potrebbe sembrare completamente inutile. Non 
6353 disegna nulla sullo schermo e non risponde a nessun evento. Tuttavia ha 
6354 una funzione: fornire una finestra X al suo widget figlio. Ci&ograve;
6355 &egrave; importante in quanto molti widget GTK non hanno una finestra X
6356 associata. Se questo da una parte risparmia memoria e migliora le prestazioni,
6357 dall'altra introduce degli svantaggi: un widget senza una finestra X non 
6358 pu&ograve; ricevere eventi, e non taglia in alcun modo il suo contenuto.
6359 Sebbene il nome ``EventBox'' (casella di eventi) enfasizzi la funzione di 
6360 gestione degli eventi, il widget pu&ograve; essere usato anche per 
6361 limitare la dimensione dei widget figli (ma anche per altro: si veda 
6362 l'esempio seguente).
6363
6364 <p>
6365 Per creare un widget di tipo EventBox:
6366
6367 <tscreen><verb>
6368 GtkWidget* gtk_event_box_new (void);
6369 </verb></tscreen>
6370
6371 <p>
6372 All'EventBox si pu&ograve aggiungere un widget figlio:
6373
6374 <tscreen><verb>
6375 gtk_container_add (GTK_CONTAINER(event_box), widget);
6376 </verb></tscreen>
6377
6378 <p>
6379 The following example demonstrates both uses of an EventBox - a label
6380 is created that clipped to a small box, and set up so that a
6381 mouse-click on the label causes the program to exit.
6382 Il seguente esempio mostra entrambi gli usi di un EventBox - si crea 
6383 un'etichetta limitata da un rettangolo piccolo, fatta in modo che
6384 cliccando con il mouse su di essa il programma termina.
6385
6386 <tscreen><verb>
6387 /* eventbox.c */
6388
6389 #include <gtk/gtk.h>
6390
6391 int 
6392 main (int argc, char *argv[])
6393 {
6394     GtkWidget *window;
6395     GtkWidget *event_box;
6396     GtkWidget *label;
6397     
6398     gtk_init (&amp;argc, &amp;argv);
6399     
6400     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6401     
6402     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6403     
6404     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6405                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6406     
6407     gtk_container_border_width (GTK_CONTAINER (window), 10);
6408     
6409     /* Crea un EventBox e lo aggiunge alla finestra principale */
6410
6411     event_box = gtk_event_box_new ();
6412     gtk_container_add (GTK_CONTAINER(window), event_box);
6413     gtk_widget_show (event_box);
6414     
6415     /* Crea una etichetta lunga */
6416     
6417     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
6418     gtk_container_add (GTK_CONTAINER (event_box), label);
6419     gtk_widget_show (label);
6420     
6421     /* Limitane le dimensioni */
6422     gtk_widget_set_usize (label, 110, 20);
6423     
6424     /* E collega ad essa una azione */
6425     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6426     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
6427                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6428     
6429     /* Un'altra cosa per cui si ha bisogno di una finestra X ... */
6430     
6431     gtk_widget_realize (event_box);
6432     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
6433     
6434     gtk_widget_show (window);
6435     
6436     gtk_main ();
6437     
6438     return 0;
6439 }
6440 </verb></tscreen>
6441
6442 <!-- ***************************************************************** -->
6443 <sect>Selezionare gli Attributi dei Widget<label id="sec_setting_widget_attributes">
6444 <!-- ***************************************************************** -->
6445 <p>
6446 Qui si descrivono le funzioni per la gestione dei widget. Esse possono essere 
6447 usate per impostarne lo stile, il padding, le dimensioni, ...
6448
6449 (Forse andrebbe fatta un'intera sezione sugli acceleratori).
6450
6451 <tscreen><verb>
6452 void       gtk_widget_install_accelerator (GtkWidget           *widget,
6453                                            GtkAcceleratorTable *table,
6454                                            gchar               *signal_name,
6455                                            gchar                key,
6456                                            guint8               modifiers);
6457
6458 void       gtk_widget_remove_accelerator  (GtkWidget           *widget,
6459                                            GtkAcceleratorTable *table,
6460                                            gchar               *signal_name);
6461
6462 void       gtk_widget_activate            (GtkWidget           *widget);
6463
6464 void       gtk_widget_set_name            (GtkWidget           *widget,
6465                                            gchar               *name);
6466 gchar*     gtk_widget_get_name            (GtkWidget           *widget);
6467
6468 void       gtk_widget_set_sensitive       (GtkWidget           *widget,
6469                                            gint                 sensitive);
6470
6471 void       gtk_widget_set_style           (GtkWidget           *widget,
6472                                            GtkStyle            *style);
6473                                            
6474 GtkStyle*    gtk_widget_get_style     (GtkWidget *widget);
6475
6476 GtkStyle*    gtk_widget_get_default_style    (void);
6477
6478 void       gtk_widget_set_uposition       (GtkWidget           *widget,
6479                                            gint                 x,
6480                                            gint                 y);
6481 void       gtk_widget_set_usize           (GtkWidget           *widget,
6482                                            gint                 width,
6483                                            gint                 height);
6484
6485 void       gtk_widget_grab_focus          (GtkWidget           *widget);
6486
6487 void       gtk_widget_show                (GtkWidget           *widget);
6488
6489 void       gtk_widget_hide                (GtkWidget           *widget);
6490 </verb></tscreen>
6491
6492
6493 <!-- ***************************************************************** -->
6494 <sect>Funzioni periodiche, di I/O e di attesa<label id="sec_timeouts">
6495 <!-- ***************************************************************** -->
6496 <p>
6497 <!-- ----------------------------------------------------------------- -->
6498 <sect1>Funzioni periodiche
6499 <p>
6500 Probabilmente vi sarete chiesti come far fare qualcosa di utile a GTK
6501 durante la chiamata alla gtk_main(). Ci sono diverse possibilit&agrave;.
6502 Usando le seguenti funzioni si possono creare funzioni che vengono chiamate
6503 periodicamente.
6504
6505 <tscreen><verb>
6506 gint gtk_timeout_add (guint32 interval,
6507                       GtkFunction function,
6508                       gpointer data);
6509 </verb></tscreen>
6510
6511 Il primo argomento &egrave; il numero di millisecondi tra le chiamate alla 
6512 funzione. Il secondo &egrave; la funzione periodica, mentre il terzo
6513 rappresenta i dati che vengono passati alla funzione. Il valore restituito
6514 &egrave; un'etichetta che pu&ograve; essere utilizzata per fermare la chiamata
6515 periodica, passandolo alla funzione:
6516
6517 <tscreen><verb>
6518 void gtk_timeout_remove (gint tag);
6519 </verb></tscreen>
6520
6521 La chiamata periodica si ferma anche se la funzione periodica ritorna zero
6522 o FALSE. Naturalmente questo vuol dire che se si vuole che la funzione periodica
6523 continui ad essere richiamata, essa deve restituire un valore non nullo,
6524 cio&egrave; TRUE.
6525
6526 La dichiarazione della funzione periodica dovrebbe essere come questa:
6527
6528 <tscreen><verb>
6529 gint timeout_callback (gpointer data);
6530 </verb></tscreen>
6531
6532 <!-- ----------------------------------------------------------------- -->
6533 <sect1>Controllo dell'I/O
6534 <p>
6535 Un'altra utile caratteristica di GTK &egrave; la possibilit&agrave; di fargli
6536 controllare che siano verificate certe condizioni su un descrittore di file 
6537 (come quelli restituiti da open(2) o socket(2)). Questo &egrave; utile in
6538 particolar modo per le applicazioni di rete. La funzione &egrave; la seguente:
6539
6540 <tscreen><verb>
6541 gint gdk_input_add (gint source,
6542                     GdkInputCondition condition,
6543                     GdkInputFunction  function,
6544                     gpointer data);
6545 </verb></tscreen>
6546
6547 Il primo argomento &egrave; il descrittore che si desidera venga controllato,
6548 mentre il secondo specifica quale condizione si vuole che GDK controlli.
6549 Questa pu&ograve; essere una tra:
6550 <p>
6551 GDK_INPUT_READ - Chiama la funzione quando ci sono dati pronti per la lettura
6552 nel descrittore di file.
6553 <p>
6554 GDK_INPUT_WRITE - Chiama la funzione quando il descrittore di file &egrave; 
6555 pronto per la scrittura.
6556 <p>
6557 Come sicuramente avrete gi&agrave; intuito, il terzo parametro &egrave; la
6558 funzione da chiamare quando la condizione specificata &egrave; soddisfatta,
6559 mentre il quarto rappresenta i dati da passare a questa funzione.
6560 <p>
6561 Il valore di ritorno  &egrave; un etichetta che pu&ograve; essere usata per
6562 fermare il controllo di GDK sul descrittore di file, usando la seguente
6563 funzione:
6564 <p>
6565 <tscreen><verb>
6566 void gdk_input_remove (gint tag);
6567 </verb></tscreen>
6568 <p>
6569 La funzione da richiamare va dichiarata cos&igrave;:
6570 <p>
6571 <tscreen><verb>
6572 void input_callback (gpointer data, gint source, 
6573                      GdkInputCondition condition);
6574 </verb></tscreen>
6575 <p>
6576
6577 <!-- ----------------------------------------------------------------- -->
6578 <sect1>Funzioni di attesa (``Idle'')
6579 <p>
6580 Cosa fare se si ha una funzione che si vuole venga chiamata quando non
6581 sta accadendo nient'altro?
6582
6583 <tscreen><verb>
6584 gint gtk_idle_add (GtkFunction function,
6585                    gpointer data);
6586 </verb></tscreen>
6587
6588 Questa fa si che GDK chiami la funzione specificata quando non c'&egrave;
6589 nessuna altra operazione in corso.
6590
6591 <tscreen><verb>
6592 void gtk_idle_remove (gint tag);
6593 </verb></tscreen>
6594 <p>
6595 Non ci soffermeremo sul significato dei parametri in quanto del tutto analoghi
6596 ai precedenti. La funzione puntata dal primo argomento della gtk_idle_add 
6597 viene chiamata non appena se ne presenta l'opportunit&agrave;; come 
6598 negli altri casi, se essa restituisce FALSE non viene pi&ugrave; chiamata.
6599
6600 <!-- ***************************************************************** -->
6601 <sect>La gestione delle selezioni
6602 <!-- ***************************************************************** -->
6603
6604 <!-- ----------------------------------------------------------------- -->
6605 <sect1> Overview
6606
6607 <p>
6608
6609 Le <em>selezioni</em> sono un tipo di comunicazione tra processi
6610 supportato da GTK. Una selezione identifica un frammento di dati; per 
6611 esempio, una porzione di testo selezionata dall'utente in qualche modo,
6612 magari con il mouse. Su un display solo un'applicazione alla volta
6613 (il <em>proprietario</em>) pu&oacute; essere proprietaria di una
6614 particolare selezione, sicch&eacute; quando un'applicazione richiede
6615 una selezione il precedente proprietario deve comunicare all'utente che
6616 la selezione &egrave; stata ceduta. Altre applicazioni possono richiedere
6617 il contenuto di una selezione in diverse forme, chiamate <em>obiettivi</em>.
6618 Ci pu&ograve; essere un numero qualsiasi di selezioni, ma la maggior parte
6619 delle applicazioni X pu&ograve; gestirne solo una, la <em>selezione
6620 primaria</em>.
6621
6622 <p>
6623 Nella maggior parte dei casi per una applicazione GTK non &egrave; 
6624 necessario gestire esplicitamente le selezioni. I widget standard,
6625 come quello di Ingresso, hanno gi&agrave; la capacit&agrave; di
6626 chiedere la selezione se necessario (p. e., quando l'utente
6627 seleziona sul testo), e di recuperare il contenuto di una selezione
6628 di un altro widget o di un'altra applicazione (p. e., quando l'utente
6629 clicca il tasto centrale del mouse). Ci possono comunque essere dei
6630 casi nei quali si vuole dare ad altri widget la capacit&agrave; di
6631 fornire la selezione, o si vogliono recuperare degli obiettivi non
6632 supportati direttamente.
6633
6634 <p>
6635 Un concetto fondamentale necessario per comprendere la gestione delle
6636 selezioni &egrave; quello di <em>atomo</em>. Un atomo &egrave; un intero
6637 che identifica univocamente una stringa (su un certo display).
6638 Certi atomi sono predefiniti dal server X, e in alcuni casi in <tt>gtk.h</tt>
6639 ci sono costanti corrispondenti a questi atomi. Per esempio, la costante
6640 <tt>GDK_PRIMARY_SELECTION</tt> corrisponde alla stringa ``PRIMARY''.
6641 Negli altri casi bisogna usare le funzioni <tt>gdk_atom_intern()</tt>
6642 per ottenere l'atomo corrispondente ad una stringa, e <tt>gdk_atom_name()</tt>
6643 per ottenere il nome di un atomo. Sia le selezioni sia gli obiettivi sono
6644 identificati da atomi.
6645 <!-- ----------------------------------------------------------------- -->
6646 <sect1> Recuperare le selezioni
6647
6648 <p>
6649
6650 Il recupero di una selezione &egrave;  un processo asincrono. Per iniziare 
6651 il processo, si chiama:
6652 <tscreen><verb>
6653 gint gtk_selection_convert   (GtkWidget           *widget, 
6654                               GdkAtom              selection, 
6655                               GdkAtom              target,
6656                               guint32              time)
6657 </verb</tscreen>
6658
6659 Questo <em>converte</em> la selezione nella forma specificata 
6660 dall'obiettivo <tt/target/. Se possibile, il campo <tt/time/ 
6661 dovrebbe essere il tempo dell'evento che ha attivato la selezione.
6662 Questo aiuta a far si che gli eventi avvengano nell'ordine in cui
6663 l'utente li ha richiesti. Se comunque non fosse disponibile (per
6664 esempio, se la conversione &egrave; stata attivata da un segnale di
6665 ``cliccato''), allora si pu&ograve; usare la costante 
6666 <tt>GDK_CURRENT_TIME</tt>.
6667
6668 <p>
6669 Quando il proprietario di una selezione risponde ad una richiesta,
6670 un segnale ``selection_received'' (selezione ricevuta) viene inviato
6671 alla vostra applicazione. Il gestore di questo segnale riceve un 
6672 puntatore ad una struttura <tt>GtkSelectionData</tt>, che &egrave;
6673 definita nel modo seguente:
6674 <tscreen><verb>
6675 struct _GtkSelectionData
6676 {
6677   GdkAtom selection;
6678   GdkAtom target;
6679   GdkAtom type;
6680   gint    format;
6681   guchar *data;
6682   gint    length;
6683 };
6684 </verb></tscreen>
6685 <tt>selection</tt> e <tt>target</tt> sono i valori da voi specificati
6686 nella chiamata <tt>gtk_selection_convert()</tt>. <tt>type</tt> &egrave;
6687 un atomo che identifica il tipo di dati restituiti dal proprietario della
6688 selezione. Alcuni valori possibili sono ``STRING'', una stringa di 
6689 caratteri latin-1, ``ATOM'', una serie di atomi, ``INTEGER'', un intero, ecc. 
6690 La maggior parte degli obiettivi pu&ograve; restituire solo un tipo.
6691 <tt/format/ ci d&agrave; la lunghezza delle unit&agrave; (per esempio caratteri)
6692 in bit. Di solito, quando si ricevono i dati non ci si cura di questo.
6693 <tt>data</tt> &egrave; un puntatore ai dati restituiti, e <tt>length</tt>
6694 &egrave; la lunghezza dei dati restituiti, in byte. Se <tt>length</tt>
6695 &egrave; negativo allora si &egrave; verificato un errore e non &egrave;
6696 stato possibile recuperare la selezione. Questo pu&ograve; avvenire se
6697 nessuna applicazione era proprietaria della selezione, o se si &egrave;
6698 richiesto un obiettivo non supportato dall'applicazione. Viene garantito
6699 che il buffer sia un byte pi&ugrave; lungo di <tt>length</tt>; il byte
6700 in pi&ugrave; sar&agrave; sempre zero, in modo che non sia necessario
6701 ricopiare le stringhe solo per farle terminare con zero.
6702
6703 <p>
6704 Nell'esempio che segue viene recuperato l'obiettivo speciale ``TARGETS'',
6705 che &egrave; una lista di tutti gli obiettivi in cui pu&ograve; essere
6706 convertita la selezione.
6707 <tscreen><verb>
6708 /* gettargets.c */
6709
6710 #include <gtk/gtk.h>
6711
6712 void selection_received (GtkWidget *widget, 
6713                          GtkSelectionData *selection_data, 
6714                          gpointer data);
6715
6716 /* Gestore di segnale chiamato quando l'utente clicca nel bottone */
6717 /* "Get Targets"                                                   */
6718 void
6719 get_targets (GtkWidget *widget, gpointer data)
6720 {
6721   static GdkAtom targets_atom = GDK_NONE;
6722
6723   /* Prende l'atomo corrispondente alla stringa "TARGETS" */
6724   if (targets_atom == GDK_NONE)
6725     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
6726
6727   /* E richiede l'obiettivo "TARGETS" per la selezione primaria */
6728   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
6729                          GDK_CURRENT_TIME);
6730 }
6731
6732 /* Gestore di segnale chiamato quando il proprietario della selezione */
6733 /* restituisce i dati                                                 */
6734 void
6735 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
6736                     gpointer data)
6737 {
6738   GdkAtom *atoms;
6739   GList *item_list;
6740   int i;
6741
6742   /* **** IMPORTANTE **** Controlla che il recupero sia riuscito */
6743   if (selection_data->length < 0)
6744     {
6745       g_print ("Selection retrieval failed\n");
6746       return;
6747     }
6748   /* Make sure we got the data in the expected form */
6749   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
6750     {
6751       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
6752       return;
6753     }
6754   
6755   /* Stampa gli atomi ricevuti */
6756   atoms = (GdkAtom *)selection_data->data;
6757
6758   item_list = NULL;
6759   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
6760     {
6761       char *name;
6762       name = gdk_atom_name (atoms[i]);
6763       if (name != NULL)
6764         g_print ("%s\n",name);
6765       else
6766         g_print ("(bad atom)\n");
6767     }
6768
6769   return;
6770 }
6771
6772 int 
6773 main (int argc, char *argv[])
6774 {
6775   GtkWidget *window;
6776   GtkWidget *button;
6777   
6778   gtk_init (&amp;argc, &amp;argv);
6779
6780   /* Create the toplevel window */
6781
6782   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6783   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6784   gtk_container_border_width (GTK_CONTAINER (window), 10);
6785
6786   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6787                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
6788
6789   /* Crea un bottone che l'utente pu&ograve; cliccare per ottenere gli obiettivi */
6790
6791   button = gtk_button_new_with_label ("Get Targets");
6792   gtk_container_add (GTK_CONTAINER (window), button);
6793
6794   gtk_signal_connect (GTK_OBJECT(button), "clicked",
6795                       GTK_SIGNAL_FUNC (get_targets), NULL);
6796   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
6797                       GTK_SIGNAL_FUNC (selection_received), NULL);
6798
6799   gtk_widget_show (button);
6800   gtk_widget_show (window);
6801   
6802   gtk_main ();
6803   
6804   return 0;
6805 }
6806 </verb></tscreen>
6807
6808 <!-- ----------------------------------------------------------------- -->
6809 <sect1> Fornire una selezione 
6810
6811 <p>
6812 Fornire la selezione &egrave; un po' pi&ugrave; complicato. Bisogna
6813 registrare i gestori che verranno chiamati quando viene richiesta la
6814 propria selezione. Per ogni coppia selezione/obiettivo che si gestir&agrave;
6815 occorre una chiamata a:
6816
6817 <tscreen><verb>
6818 void gtk_selection_add_handler (GtkWidget           *widget, 
6819                                 GdkAtom              selection,
6820                                 GdkAtom              target,
6821                                 GtkSelectionFunction function,
6822                                 GtkRemoveFunction    remove_func,
6823                                 gpointer             data);
6824 </verb></tscreen>
6825
6826 <tt/widget/, <tt/selection/, e <tt/target/ identificano le richieste
6827 che questo gestore soddisfer&agrave;.  <tt/remove_func/, se non &egrave;
6828 NULL, verr&agrave; chiamato quando il gestore di segnale viene rimosso.
6829 Questo &egrave; utile, per esempio, per linguaggi interpretati ai quali
6830 serve di tener traccia di un conteggio di riferimento per <tt/data/.
6831
6832 <p>
6833 La funzione di richiamo ha la forma:
6834
6835 <tscreen><verb>
6836 typedef void (*GtkSelectionFunction) (GtkWidget *widget, 
6837                                       GtkSelectionData *selection_data,
6838                                       gpointer data);
6839
6840 </verb></tscreen>
6841
6842 La GtkSelectionData &egrave; la stessa di prima, ma stavolta siamo
6843 responsabili di riempire i campi <tt/type/, <tt/format/, <tt/data/,
6844 e <tt/length/. (Il campo <tt/format/ qui &egrave; effettivamente 
6845 importante - il server  X lo usa per capire se occorre che i byte
6846 dei dati vengano scambiati o no. Di solito sar&agrave; 8 - cio&egrave;
6847 un carattere - o 32 - cio&egrave; un intero.) Questo viene fatto
6848 chiamando la funzione:
6849
6850 <tscreen><verb>
6851 void gtk_selection_data_set (GtkSelectionData *selection_data,
6852                              GdkAtom           type,
6853                              gint              format,
6854                              guchar           *data,
6855                              gint              length);
6856 </verb></tscreen>
6857 Questa funzione si prende cura di fare propriamente una copia dei dati
6858 in modo che non ci si debba preoccupare di conservarli (&egrave; opportuno
6859 evitare di riempire a mano i campi della struttura GtkSelectionData).
6860
6861 <p>
6862 Quando richiesto dall'utente, richiederete la propriet&agrave; della selezione
6863 chiamando:
6864
6865 <tscreen><verb>
6866 gint gtk_selection_owner_set (GtkWidget           *widget,
6867                               GdkAtom              selection,
6868                               guint32              time);
6869 </verb></tscreen>
6870
6871 Se un'altra applicazione richiede la propriet&agrave; della selezione,
6872 riceverete un evento di azzeramento della selezione (``selection_clear_event'').
6873
6874 Come esempio di fornitura della selezione, il programma seguente aggiunge
6875 la funzionalit&agrave; di selezione a un bottone di attivazione. Quando il
6876 bottone viene premuto, il programma richiede la selezione primaria.
6877 L'unico obiettivo supportato (oltre a certi obiettivi come ``TARGETS''
6878 fornito dalla stessa GTK) &egrave; l'obiettivo ``STRING''. Quando viene
6879 richiesto questo obiettivo, viene restituita una rappresentazione stringa
6880 del tempo.
6881
6882 <tscreen><verb>
6883 /* setselection.c */
6884
6885 #include <gtk/gtk.h>
6886 #include <time.h>
6887
6888 /* Richiamata quando l'utente attiva la selezione */ 
6889 void
6890 selection_toggled (GtkWidget *widget, gint *have_selection)
6891 {
6892   if (GTK_TOGGLE_BUTTON(widget)->active)
6893     {
6894       *have_selection = gtk_selection_owner_set (widget,
6895                                                  GDK_SELECTION_PRIMARY,
6896                                                  GDK_CURRENT_TIME);
6897       /* se il richiamo della selezione &egrave; fallito, si riporta il
6898          bottone nello stato non premuto */
6899       if (!*have_selection)
6900         gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
6901     }
6902   else
6903     {
6904       if (*have_selection)
6905         {
6906           /* Prima di annullare la selezione mettendone a NULL il proprietario,
6907              controlliamo se siamo i veri proprietari */
6908           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
6909             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
6910                                      GDK_CURRENT_TIME);
6911           *have_selection = FALSE;
6912         }
6913     }
6914 }
6915
6916 /* Chiamata quando un'altra applicazione richiede la selezione */
6917 gint
6918 selection_clear (GtkWidget *widget, GdkEventSelection *event,
6919                  gint *have_selection)
6920 {
6921   *have_selection = FALSE;
6922   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
6923
6924   return TRUE;
6925 }
6926
6927 /* Fornisce come selezione il tempo attuale */
6928 void
6929 selection_handle (GtkWidget *widget, 
6930                   GtkSelectionData *selection_data,
6931                   gpointer data)
6932 {
6933   gchar *timestr;
6934   time_t current_time;
6935
6936   current_time = time (NULL);
6937   timestr = asctime (localtime(&amp;current_time)); 
6938   /* Quando si restituisce una singola stringa, non occorre che finisca
6939      con NULL. Questo verr&agrave; fatto automaticamente */
6940      
6941   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
6942                           8, timestr, strlen(timestr));
6943 }
6944
6945 int
6946 main (int argc, char *argv[])
6947 {
6948   GtkWidget *window;
6949
6950   GtkWidget *selection_button;
6951
6952   static int have_selection = FALSE;
6953   
6954   gtk_init (&amp;argc, &amp;argv);
6955
6956   /* Crea la finestra di livello superiore */
6957
6958   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6959   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6960   gtk_container_border_width (GTK_CONTAINER (window), 10);
6961
6962   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6963                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
6964
6965   /* Crea un bottone a commutazione che agisce come la selezione */
6966
6967   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
6968   gtk_container_add (GTK_CONTAINER (window), selection_button);
6969   gtk_widget_show (selection_button);
6970
6971   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
6972                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
6973   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
6974                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
6975
6976   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
6977                              GDK_SELECTION_TYPE_STRING,
6978                              selection_handle, NULL);
6979
6980   gtk_widget_show (selection_button);
6981   gtk_widget_show (window);
6982   
6983   gtk_main ();
6984   
6985   return 0;
6986 }
6987 </verb></tscreen>
6988
6989 <!-- ***************************************************************** -->
6990 <sect>La glib<label id="sec_glib">
6991 <!-- ***************************************************************** -->
6992 <p>
6993 La glib fornisce molte funzioni e definizioni utili pronte all'uso quando si
6994 creano applicazioni GDK e GTK. Qui verranno elencate tutte, con una
6995 breve spiegazione. Molte sono duplicati delle funzioni standard della libc,
6996 e quindi per queste non si scender&agrave; nei dettagli. Questa vuole essere una
6997 lista di riferimento, in modo che si sappia cosa &egrave; possibile usare.
6998
6999 <!-- ----------------------------------------------------------------- -->
7000 <sect1>Definizioni
7001 <p>
7002 Le definizioni per gli estremi di molti dei tipi standard sono:
7003
7004 <tscreen><verb>
7005 G_MINFLOAT
7006 G_MAXFLOAT
7007 G_MINDOUBLE
7008 G_MAXDOUBLE
7009 G_MINSHORT
7010 G_MAXSHORT
7011 G_MININT
7012 G_MAXINT
7013 G_MINLONG
7014 G_MAXLONG
7015 </verb></tscreen>
7016
7017 Ci sono anche le seguenti definizioni di tipo. Quelle rimaste non specificate
7018 sono dipendenti dall'architettura. Si ricordi di evitare di fare affidamento
7019 sulla dimensione di un puntatore se si vuole la portabilit&agrave;! P.e., un puntatore
7020 su un Alpha &egrave; lungo 8 byte, ma 4 su un Intel. 
7021
7022 <tscreen><verb>
7023 char   gchar;
7024 short  gshort;
7025 long   glong;
7026 int    gint;
7027 char   gboolean;
7028
7029 unsigned char   guchar;
7030 unsigned short  gushort;
7031 unsigned long   gulong;
7032 unsigned int    guint;
7033
7034 float   gfloat;
7035 double  gdouble;
7036 long double gldouble;
7037
7038 void* gpointer;
7039
7040 gint8
7041 guint8
7042 gint16
7043 guint16
7044 gint32
7045 guint32
7046 </verb></tscreen>
7047
7048 <!-- ----------------------------------------------------------------- -->
7049 <sect1>Liste a doppio collegamento
7050 <p>
7051 le seguenti funzioni sono usate per creare, gestire e distruggere liste a
7052 doppio collegamento. Si assume che il lettore sappia gi&agrave; cosa sono le liste
7053 collegate (linked list), poich&eacute; descriverle &egrave; fuori dagli scopi di
7054 questo documento. Naturalmente non &egrave; necessario conoscerle per l'uso
7055 generale di GTK, per quanto conoscerle sia comunque interessante.
7056
7057 <tscreen><verb>
7058 GList* g_list_alloc       (void);
7059
7060 void   g_list_free        (GList     *list);
7061
7062 void   g_list_free_1      (GList     *list);
7063
7064 GList* g_list_append      (GList     *list,
7065                            gpointer   data);
7066                            
7067 GList* g_list_prepend     (GList     *list,
7068                            gpointer   data);
7069                         
7070 GList* g_list_insert      (GList     *list,
7071                            gpointer   data,
7072                            gint       position);
7073
7074 GList* g_list_remove      (GList     *list,
7075                            gpointer   data);
7076                            
7077 GList* g_list_remove_link (GList     *list,
7078                            GList     *link);
7079
7080 GList* g_list_reverse     (GList     *list);
7081
7082 GList* g_list_nth         (GList     *list,
7083                            gint       n);
7084                            
7085 GList* g_list_find        (GList     *list,
7086                            gpointer   data);
7087
7088 GList* g_list_last        (GList     *list);
7089
7090 GList* g_list_first       (GList     *list);
7091
7092 gint   g_list_length      (GList     *list);
7093
7094 void   g_list_foreach     (GList     *list,
7095                            GFunc      func,
7096                            gpointer   user_data);
7097 </verb></tscreen>                                             
7098
7099 <!-- ----------------------------------------------------------------- -->
7100 <sect1>Liste a collegamento singolo
7101 <p>
7102 Molte delle funzioni per le liste a collegamento singolo sono identiche alle
7103 precedenti. Eccone una lista completa:
7104 <tscreen><verb>
7105 GSList* g_slist_alloc       (void);
7106
7107 void    g_slist_free        (GSList   *list);
7108
7109 void    g_slist_free_1      (GSList   *list);
7110
7111 GSList* g_slist_append      (GSList   *list,
7112                              gpointer  data);
7113                 
7114 GSList* g_slist_prepend     (GSList   *list,
7115                              gpointer  data);
7116                              
7117 GSList* g_slist_insert      (GSList   *list,
7118                              gpointer  data,
7119                              gint      position);
7120                              
7121 GSList* g_slist_remove      (GSList   *list,
7122                              gpointer  data);
7123                              
7124 GSList* g_slist_remove_link (GSList   *list,
7125                              GSList   *link);
7126                              
7127 GSList* g_slist_reverse     (GSList   *list);
7128
7129 GSList* g_slist_nth         (GSList   *list,
7130                              gint      n);
7131                              
7132 GSList* g_slist_find        (GSList   *list,
7133                              gpointer  data);
7134                              
7135 GSList* g_slist_last        (GSList   *list);
7136
7137 gint    g_slist_length      (GSList   *list);
7138
7139 void    g_slist_foreach     (GSList   *list,
7140                              GFunc     func,
7141                              gpointer  user_data);
7142         
7143 </verb></tscreen>
7144
7145 <!-- ----------------------------------------------------------------- -->
7146 <sect1>Gestione della memoria
7147 <p>
7148 <tscreen><verb>
7149 gpointer g_malloc      (gulong    size);
7150 </verb></tscreen>
7151
7152 Questa &egrave; una sostituta di malloc(). Non occorre controllare il valore 
7153 restituito, in quanto lo fa gi&agrave; questa funzione.
7154
7155 <tscreen><verb>
7156 gpointer g_malloc0     (gulong    size);
7157 </verb></tscreen>
7158
7159 Come la precedente, ma la memoria viene azzerata prima di restituire un
7160 puntatore ad essa.
7161
7162 <tscreen><verb>
7163 gpointer g_realloc     (gpointer  mem,
7164                         gulong    size);
7165 </verb></tscreen>
7166
7167 Riloca ``size'' byte di memoria che inizia a ``mem''. Ovviamente, la memoria
7168 dovrebbe essere stata allocata precedentemente.
7169
7170 <tscreen><verb>
7171 void     g_free        (gpointer  mem);
7172 </verb></tscreen>
7173
7174 Libera la memoria. Facile!
7175
7176 <tscreen><verb>
7177 void     g_mem_profile (void);
7178 </verb></tscreen>
7179
7180 Emette un profilo della memoria usata, ma occorre ricompilare e reinstallare
7181 la libreria aggiungendo #define MEM_PROFILE all'inizio del file glib/gmem.c.
7182
7183 <tscreen><verb>
7184 void     g_mem_check   (gpointer  mem);
7185 </verb></tscreen>
7186
7187 Controlla che una locazione di memoria sia valida. Occorre ricompilare e
7188 reinstallare la libreria aggiungendo #define MEM_CHECK all'inizio del file
7189 gmem.c.
7190
7191 <!-- ----------------------------------------------------------------- -->
7192 <sect1>Timer
7193 <p>
7194 Funzioni legate ai timer...
7195
7196 <tscreen><verb>
7197 GTimer* g_timer_new     (void);
7198
7199 void    g_timer_destroy (GTimer  *timer);
7200
7201 void    g_timer_start   (GTimer  *timer);
7202
7203 void    g_timer_stop    (GTimer  *timer);
7204
7205 void    g_timer_reset   (GTimer  *timer);
7206
7207 gdouble g_timer_elapsed (GTimer  *timer,
7208                          gulong  *microseconds);
7209 </verb></tscreen>                        
7210
7211 <!-- ----------------------------------------------------------------- -->
7212 <sect1>Gestione delle stringhe
7213 <p>
7214 Un'accozzaglia di funzioni per la gestione delle stringhe. Sembrano tutte molto
7215 interessanti, e probabilmente migliori per molte caratteristiche delle funzioni
7216 standard del C per le stringhe, ma necessitano di documentazione.
7217
7218 <tscreen><verb>
7219 GString* g_string_new       (gchar   *init);
7220 void     g_string_free      (GString *string,
7221                              gint     free_segment);
7222                              
7223 GString* g_string_assign    (GString *lval,
7224                              gchar   *rval);
7225                              
7226 GString* g_string_truncate  (GString *string,
7227                              gint     len);
7228                              
7229 GString* g_string_append    (GString *string,
7230                              gchar   *val);
7231                             
7232 GString* g_string_append_c  (GString *string,
7233                              gchar    c);
7234         
7235 GString* g_string_prepend   (GString *string,
7236                              gchar   *val);
7237                              
7238 GString* g_string_prepend_c (GString *string,
7239                              gchar    c);
7240         
7241 void     g_string_sprintf   (GString *string,
7242                              gchar   *fmt,
7243                              ...);
7244         
7245 void     g_string_sprintfa  (GString *string,
7246                              gchar   *fmt,
7247                              ...);
7248 </verb></tscreen>                                                         
7249
7250 <!-- ----------------------------------------------------------------- -->
7251 <sect1>Funzioni d'utilit&agrave; e di errore
7252 <p>
7253 <tscreen><verb>
7254 gchar* g_strdup    (const gchar *str);
7255 </verb></tscreen>
7256
7257 Funzione sostitutiva della strdup. Copia i contenuti originari delle stringhe 
7258 in memoria appena allocata, restituendo un puntatore ad essa.
7259
7260 <tscreen><verb>
7261 gchar* g_strerror  (gint errnum);
7262 </verb></tscreen>
7263 Si raccomanda di usare questa gunzione per tutti i messaggi di errore. E' molto
7264 pi&ugrave; graziosa, e pi&ugrave; portabile di perror() o di altre. L'output di solito ha la
7265 forma:
7266
7267 <tscreen><verb>
7268 nome programma:funzione fallita:file o altre descrizioni:strerror
7269 </verb></tscreen>
7270
7271 Di seguito un esempio di una chiamata di questo tipo usata nel nostro
7272 programma Hello World:
7273
7274 <tscreen><verb>
7275 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
7276 </verb></tscreen>
7277
7278 <tscreen><verb>
7279 void g_error   (gchar *format, ...);
7280 </verb></tscreen>
7281
7282 Visualizza un messaggio di errore. Il formato &egrave; come quello di printf,
7283 ma prepone ``** ERROR **: '' al messaggio e termina il programma. Da usare solo
7284 per errori gravi.
7285
7286 <tscreen><verb>
7287 void g_warning (gchar *format, ...);
7288 </verb></tscreen>
7289
7290 Come la precedente, ma prepone ``** WARNING **: '' e non termina il programma.
7291
7292 <tscreen><verb>
7293 void g_message (gchar *format, ...);
7294 </verb></tscreen>
7295
7296 Visualizza ``message: '' e poi il messaggio.
7297
7298 <tscreen><verb>
7299 void g_print   (gchar *format, ...);
7300 </verb></tscreen>
7301
7302 Sostituta di printf().
7303
7304 L'ultima funzione:
7305
7306 <tscreen><verb>
7307 gchar* g_strsignal (gint signum);
7308 </verb></tscreen>
7309
7310 Visualizza il nome del messaggio del sistema Unix associato al numero di
7311 segnale. Utile nelle funzioni generiche di gestione dei segnali.
7312
7313 Tutte le funzioni elencate sono pi&ugrave; o meno prese da glib.h. Se qualcuno volesse
7314 documentare qualche funzione, mandi una email all'autore!
7315
7316 <!-- ***************************************************************** -->
7317 <sect>I file rc di GTK
7318 <!-- ***************************************************************** -->
7319
7320 <p>
7321 GTK ha un suo modo di trattare le preferenze delle applicazioni, usando
7322 i file rc. Questi possono essere usati per scegliere i colori di quasi tutti
7323 i widget, e possono anche essere usati per inserire delle pixmap nello sfondo
7324 di alcuni widget.
7325
7326 <!-- ----------------------------------------------------------------- -->
7327 <sect1>Funzioni per i file rc
7328 <p>
7329 All'inizio della vostra applicazione dovrebbe esserci una chiamata a
7330 <tscreen><verb>
7331 void gtk_rc_parse (char *filename);
7332 </verb></tscreen>
7333 <p>
7334 passando come parametro il nome del vostro file rc. Questo far&agrave; si che GTK
7335 analizzi tale file e usi le impostazioni di stile per i tipi di widget ivi
7336 definite.
7337 <p>
7338 Se si desidera avere un insieme speciale di widget che abbia uno stile diverso
7339 dagli altri, o qualsiasi altra divisione logica dei widget, si chiami
7340 <tscreen><verb>
7341 void gtk_widget_set_name (GtkWidget *widget,
7342                           gchar *name);
7343 </verb></tscreen>
7344 <p>
7345 passando un widget appena creato come primo argomento, e il nome che gli si
7346 vuole dare come secondo. Questo consentir&agrave; di cambiare gli attributi di
7347 questo widget per nome tramite il file rc.
7348 <p>
7349 Effettuando una chiamata come questa:
7350
7351 <tscreen><verb>
7352 button = gtk_button_new_with_label ("Special Button");
7353 gtk_widget_set_name (button, "special button");
7354 </verb></tscreen>
7355 <p>
7356 allora a questo bottone viene dato il nome ``special button'' ed esso pu&ograve; essere
7357 riferito per nome nel file rc come ``special button.GtkButton''. [<--- Verificatemi!]
7358 <p>
7359 Il seguente esempio di file rc imposta le propriet&agrave; della finestra principale,
7360 e fa si che tutti i figli di questa finestra ereditino lo stile descritto
7361 dallo stile ``main button''. Il codice usato nell'applicazione &egrave;:
7362
7363 <tscreen><verb>
7364 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7365 gtk_widget_set_name (window, "main window");
7366 </verb></tscreen>
7367 <p>
7368 Lo stile viene definito nel file rc usando:
7369
7370 <tscreen><verb>
7371 widget "main window.*GtkButton*" style "main_button"
7372 </verb></tscreen>
7373 <p>
7374 che assegna a tutti i widget GtkButton nella finestra principale lo stile
7375 ``main_buttons'' secondo la definizione data nel file rc.
7376 <p>
7377 Come si pu&ograve; vedere, questo sistema &egrave; molto potente e flessibile. Usate la
7378 vostra immaginazione per trarre il massimo vantaggio da esso.
7379
7380 <!-- ----------------------------------------------------------------- -->
7381 <sect1>Il formato dei file rc di GTK
7382 <p>
7383 Nell'esempio che segue viene illustrato il formato del file GTK. Si tratta
7384 del file testgkrc dalla distribuzione del GTK, a cui sono stati aggiunti
7385 vari commenti e varie cose. Potete includere questa spiegazione nella
7386 vostra applicazione per consentire all'utente di personalizzarla finemente.
7387 <p>
7388 There are several directives to change the attributes of a widget.
7389 Ci sono diverse direttive per cambiare gli attributi di un widget.
7390 <itemize>
7391 <item>fg - Assegna il colore di primo piano di un widget.
7392 <item>bg - Assegna il colore di sfondo di un widget.
7393 <item>bg_pixmap - Inserisce nello sfondo di un widget una pixmap.
7394 <item>font - Sceglie il font da usarsi con il dato widget.
7395 </itemize>
7396 <p>
7397 Inoltre ci sono diversi stati in cui pu&ograve; trovarsi un widget, e si possono
7398 assegnare diversi colori, pixmap e font per ogni stato. Essi sono:
7399 <itemize>
7400 <item>NORMAL - Lo stato normale di un widget, quando il mouse non si trova su
7401 di esso, quando non &egrave; premuto, ecc.
7402 <item>PRELIGHT (evidenziato)- Quando il mouse si trova sopra al widget
7403 verranno usati i colori assegnati per questo stato.
7404 <item>ACTIVE (attivo) - Quando il widget &egrave; premuto o cliccato esso sar&agrave; attivo,
7405 e verranno usati gli attributi assegnati da questa etichetta.
7406 <item>INSENSITIVE (insensibile)- Quando un widget viene reso insensibile,
7407 e non pu&ograve; essere attivato, prender&agrave; questi attributi.
7408 <item>SELECTED (selezionato) - Quando un oggetto viene selezionato, prende
7409 questi attributi.
7410 </itemize>
7411 <p>
7412 Quando si usano le parole chiave ``fg'' e ``bg'' per assegnare i colori dei 
7413 widget il formato &egrave;:
7414 <tscreen><verb>
7415 fg[<STATE>] = { Rosso, Verde, Blu }
7416 </verb></tscreen>
7417 <p>
7418 Dove STATE &egrave; uno degli stati visti prima (PRELIGHT, ACTIVE ecc.), e Rosso,
7419 Verde e Blu sono valori nell'intervallo 0 - 1.0;  { 1.0, 1.0, 1.0 } rappresenta
7420 il bianco.
7421 Devono essere in formato float, o verranno visti come 0, sicch&eacute; un ``1'' diretto
7422 non funziona, deve essere ``1.0''. Uno ``0'' diretto va invece bene, poich&eacute; poco
7423 importa se non viene riconosciuto: valori non riconosciuti vengono considerati
7424 0.
7425 <p>
7426 bg_pixmap &egrave; molto simile al precedente, tranne per i colori che vengono
7427 sostituiti dal nome di un file.
7428
7429 pixmap_path &egrave; una lista di percorsi separati da ``:''. In questi percorsi vengono
7430 cercate le pixmap specificate.
7431 <p>
7432 La direttiva font &egrave; semplicemente:
7433 <tscreen><verb>
7434 font = "<font name>"
7435 </verb></tscreen>
7436 <p>
7437 dove l'unica parte complicata &egrave; immaginare la stringa del font. Allo scopo
7438 pu&ograve; servire usare xfontsel o una utilit&agrave; analoga.
7439 <p>
7440 ``widget_class'' assegna lo stile di una classe di widget. Queste classi sono
7441 elencate nell'introduzione ai widget sulla gerarchia delle classi.
7442 <p>
7443 La direttiva ``widget'' assegna un insieme di widget dal nome specificato ad
7444 un dato stile, annullando qualsiasi stile assegnato per la data classe di widget.
7445 Questi widget vengono registrati nell'applicazione usando la chiamata
7446 gtk_widget_set_name(). Questo consente di specificare gli attributi di un
7447 widget singlarmente, piuttosto che assegnando gli attributi di un'intera classe
7448 di widget. E' opportuno documentare tutti questi widget speciali in modo che
7449 gli utenti possano personalizzarli.
7450 <p>
7451 Quando la parola chiave ``<tt>parent</>'' viene usata come un attributo, il
7452 widget erediter&agrave; gli attributi del suo genitore nell'applicazione.
7453 <p>
7454 Quando si definisce uno stile si possono assegnare gli attributi di uno
7455 stile definito precedentemente a quello nuovo.
7456 <tscreen><verb>
7457 style "main_button" = "button"
7458 {
7459   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
7460   bg[PRELIGHT] = { 0.75, 0, 0 }
7461 }
7462 </verb></tscreen>
7463 <p>
7464 Questo esempio prende lo stile ``button'' e crea un nuovo stile 
7465 semplicemente cambiando il font e il colore di sfondo dello stato ``prelight''
7466 nello stile ``button''.
7467 <p>
7468 Naturalmente, molti di questi attributi non sono applicabili a tutti i widget.
7469 E' veramente un semplice problema di buon senso. Tutto quello che potrebbe
7470 applicarsi, dovrebbe.
7471
7472 <!-- ----------------------------------------------------------------- -->
7473 <sect1>Esempio di file rc 
7474 <p>
7475
7476 <tscreen><verb>
7477 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
7478 #
7479 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
7480 #
7481 # style <name> [= <name>]
7482 # {
7483 #   <option>
7484 # }
7485 #
7486 # widget <widget_set> style <style_name>
7487 # widget_class <widget_class_set> style <style_name>
7488
7489
7490 # Ecco una lista di tutti gli stati possibili. Si noti che alcuni non sono
7491 # applicabili a certi widget.
7492 #
7493 # NORMAL - Lo stato normale di un widget, quando il mouse non si trova su
7494 # di esso, quando non &egrave; premuto, ecc.
7495 #
7496 # PRELIGHT (evidenziato)- Quando il mouse si trova sopra al widget
7497 # verranno usati i colori assegnati per questo stato.
7498 #
7499 # ACTIVE (attivo) - Quando il widget &egrave; premuto o cliccato esso sar&agrave; attivo,
7500 # e verranno usati gli attributi assegnati da questa etichetta.
7501 #
7502 # INSENSITIVE (insensibile)- Quando un widget viene reso insensibile,
7503 # e non pu&ograve; essere attivato, prender&agrave; questi attributi.
7504 #
7505 # SELECTED (selezionato) - Quando un oggetto viene selezionato, prende
7506 # questi attributi.
7507 #
7508 # Dati questi stati, &egrave; possibile assegnare gli attributi dei widget in
7509 # ognuno di questi stati usando le seguenti direttive.
7510 #
7511 # fg - Assegna il colore di primo piano di un widget.
7512 # bg - Assegna il colore di sfondo di un widget.
7513 # bg_pixmap - Inserisce nello sfondo di un widget una pixmap.
7514 # font - Sceglie il font da usarsi con il dato widget.
7515 #
7516
7517 # Questo &egrave; uno stile chiamato "button". Il nome non &egrave; veramente importante,
7518 # in quanto viene assegnato ai veri widget alla fine del file. 
7519
7520 style "window"
7521 {
7522   # Questo inserisce nella spaziatura attorno alla finestra la pixmap
7523   # specificata.
7524   #bg_pixmap[<STATE>] = "<pixmap filename>"
7525   bg_pixmap[NORMAL] = "warning.xpm"
7526 }
7527
7528 style "scale"
7529 {
7530   # Mette il colore di primo piano (il colore del font) a rosso nello
7531   # stato "NORMAL".
7532   
7533   fg[NORMAL] = { 1.0, 0, 0 }
7534   
7535   # Inserisce nello sfondo del gadget la stessa pixmap usata dal suo genitore.
7536   bg_pixmap[NORMAL] = "<parent>"
7537 }
7538
7539 style "button"
7540 {
7541   # Questo mostra tutti i possibili stati per un bottone. L'unico che
7542   # non &egrave; applicabile &egrave; lo stato "SELECTED".
7543   
7544   fg[PRELIGHT] = { 0, 1.0, 1.0 }
7545   bg[PRELIGHT] = { 0, 0, 1.0 }
7546   bg[ACTIVE] = { 1.0, 0, 0 }
7547   fg[ACTIVE] = { 0, 1.0, 0 }
7548   bg[NORMAL] = { 1.0, 1.0, 0 }
7549   fg[NORMAL] = { .99, 0, .99 }
7550   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
7551   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
7552 }
7553
7554 # In questi esempio ereditiamo gli attributi dello stile "button" e poi
7555 # alteriamo il font e il colore di sfondo quando evidenziato per creare
7556 # un nuovo stile "main_button".
7557
7558 style "main_button" = "button"
7559 {
7560   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
7561   bg[PRELIGHT] = { 0.75, 0, 0 }
7562 }
7563
7564 style "toggle_button" = "button"
7565 {
7566   fg[NORMAL] = { 1.0, 0, 0 }
7567   fg[ACTIVE] = { 1.0, 0, 0 }
7568   
7569   # Questo seleziona come pixmap di sfondo per il toggle_button quella del
7570   # suo widget genitore (definita nell'applicazione).
7571   bg_pixmap[NORMAL] = "<parent>"
7572 }
7573
7574 style "text"
7575 {
7576   bg_pixmap[NORMAL] = "marble.xpm"
7577   fg[NORMAL] = { 1.0, 1.0, 1.0 }
7578 }
7579
7580 style "ruler"
7581 {
7582   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
7583 }
7584
7585 # pixmap_path "~/.pixmaps"
7586
7587 # Queste assegnano ai tipi di widget gli stili definiti prima.
7588 # I tipi di widget sono elencati nella gerarchia delle classi, ma probabilmente
7589 # dovrebbero essere elencati in questo documento come riferimento per l'utente.
7590
7591 widget_class "GtkWindow" style "window"
7592 widget_class "GtkDialog" style "window"
7593 widget_class "GtkFileSelection" style "window"
7594 widget_class "*Gtk*Scale" style "scale"
7595 widget_class "*GtkCheckButton*" style "toggle_button"
7596 widget_class "*GtkRadioButton*" style "toggle_button"
7597 widget_class "*GtkButton*" style "button"
7598 widget_class "*Ruler" style "ruler"
7599 widget_class "*GtkText" style "text"
7600
7601 # Questo assegna lo stile main_button a tutti i bottoni che sono figli della
7602 # "main window" (finestra principale). Questi devono essere documenati per
7603 # potersene avvantaggiare.
7604 widget "main window.*GtkButton*" style "main_button"
7605 </verb></tscreen>
7606
7607
7608 <!-- ***************************************************************** -->
7609 <sect>Scrivere un proprio Widget
7610 <!-- ***************************************************************** -->
7611
7612 <!-- ----------------------------------------------------------------- -->
7613 <sect1> Panoramica
7614 <p>
7615 Anche se la distribuzione GTK contiene molto tipi di widget che possono
7616 coprire molte necessit&agrave; basilari, pu&ograve; essere necessario costruirsi
7617 un proprio widget. GTK usa molto l'ereditariet&agrave; tra i vari
7618 widget e, di solito, vi &egrave; un widget che si avvicina a quello che ti
7619 servirebbe, ed &egrave; spesso possibile creare un nuovo widget con poche linee
7620 di codice. Ma prima di iniziare il lavoro su un nuovo widget, vediamo 
7621 se qualcuno non lo ha gi&agrave; creato. Questo eviter&agrave; un duplicazione
7622 di lavoro e far&agrave; s&igrave; che i widget non-GTK puri siano minimi, cos&igrave; da
7623 aiutare sia chi crea il codice che chi l'interfaccia per applicazioni GTK 
7624 molto grosse. D'altra parte, quando hai finito di scrivere un widget, 
7625 annuncialo a tutto il mondo cos&igrave; che le altre persone ne possano
7626 beneficiare. Il miglioro modo dove farlo &egrave; la  <tt>gtk-list</tt>.
7627  
7628 I sorgenti completi per i widget di esempio possono essere presi dallo stesso
7629 sito da cui avete scaricato questo tutorial, oppure da:
7630
7631 <htmlurl url="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial"
7632 name="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial">
7633
7634
7635 <!-- ----------------------------------------------------------------- -->
7636 <sect1> L'anatomia di un widget
7637
7638 <p>
7639 Per creare un nuovo widget &egrave; importante aver capito come gli ogetti 
7640 di GTK lavorano. Questa sezione &egrave; solo una breve spiegazione. Guarda la
7641 documentazione di riferimento per maggiori dettagli.
7642
7643 <p>
7644 I widget GTK sono implementati in un modo orientato agli oggetti,
7645 anche se usando il C standard. Questo aumenta notevolmente la portabilit&agrave;
7646 e la stabilit&agrave;, specialmente per le correnti generazioni di compilatori C++;
7647 comunque questo significa che chi scrive un widget deve fare attenzione
7648 ad alcuni dettagli di implementazione. L'informazione comune a tutte le
7649 istanze di una classe di widget (ad esempio: a tutti i bottoni) &egrave; memorizzata 
7650 <em>class structure</em>. C'e' solamente una copia di questo in cui 
7651 sono memorizzate le informazioni riguardanti i segnali della classe 
7652 (assomiglia ad una funzione virtuale in C). Per supportare l'ereditariet&agrave;
7653 il primo campo della struttura di una classe deve essere una copia della
7654 struttura della classe genitore. La dichiarazione della struttura della 
7655 classe GtkButton &egrave;:
7656
7657 <tscreen><verb>
7658 struct _GtkButtonClass
7659 {
7660   GtkContainerClass parent_class;
7661
7662   void (* pressed)  (GtkButton *button);
7663   void (* released) (GtkButton *button);
7664   void (* clicked)  (GtkButton *button);
7665   void (* enter)    (GtkButton *button);
7666   void (* leave)    (GtkButton *button);
7667 };
7668 </verb></tscreen>
7669
7670 <p>
7671 Quando un bottone viene trattato come un contenitore (ad esempio quando viene 
7672 ridimensionato) si pu&ograve; fare il cast della struttura della sua classe con la 
7673 GtkContainerClass, e usare i campi rilevanti per gestire i segnali.
7674
7675 <p>
7676 C'&egrave; anche una struttura per ogni widget che viene creata 
7677 ad ogni istanza. Questa struttura ha campi per 
7678 memorizzare le informazioni che sono differenti per ogni volta che il widget
7679 viene istanziato. Chiameremo questa struttura la <em> struttura
7680 oggetto</em>. Per la classe Bottone, questa ha l'aspetto:
7681
7682 <tscreen><verb>
7683 struct _GtkButton
7684 {
7685   GtkContainer container;
7686
7687   GtkWidget *child;
7688
7689   guint in_button : 1;
7690   guint button_down : 1;
7691 };
7692 </verb></tscreen>
7693
7694 <p>
7695 Si noti che, similmente alla struttura della classe, il primo campo
7696 &egrave; la struttura dell'oggetto della classe madre, cos&igrave; che, se necessario, si pu&ograve; fare il
7697 cast di questa struttura con quella dell'oggetto della classe madre.
7698
7699 <!-- ----------------------------------------------------------------- -->
7700 <sect1> Creare un Widget composto
7701
7702 <!-- ----------------------------------------------------------------- -->
7703 <sect2> Introduzione
7704
7705 <p>
7706 Un tipo di widget a cui potreste essere interessati &egrave; un widget che
7707 &egrave; semplicemnte un aggregato di altri widget GTK. Questo tipo di 
7708 widget non fa nulla che non possa essere fatto creando un nuovo
7709 widget, ma fornisce un modo conveniente per inscatolare elementi 
7710 dell'interfaccia utente per poi riutilizzarli. 
7711 I widget FileSelection e ColorSelection della ditribuzione standard
7712 sono esempi di questo tipo di widget.
7713
7714 <p>
7715 Il widget di esempio che creeremo in questo capitolo &egrave; il 
7716 Tictactoe, un vettore 3x3 di bottoni a commutazione il quale emette
7717 un segnale quando tutti e 3 i bottoni di una riga, colonna o di una
7718 diagonale sono premuti.
7719
7720 <!-- ----------------------------------------------------------------- -->
7721 <sect2> Scegliere la classe madre
7722
7723 <p>
7724 La classe madre per un widget composto e' tipicamente la classe 
7725 contenitrice che racchiude tutti gli elementi del widget composto.
7726 Per esempio, la classe madre del widget FileSelection &egrave; la classe
7727 Dialog. Visto che i nostri bottoni sono inseriti in una tabella, &egrave; 
7728 naturale pensare che la nostra classe madre possa essere la GtkTable.
7729 Sfortunatamente, cos&igrave; non &egrave;. La creazione di un widget &egrave; diviso
7730 tra 2 funzioni : la funzione <tt/WIDGETNAME_new()/ che viene invocata
7731 dall'utente, e la funzione  <tt/WIDGETNAME_init()/ che ha il compito
7732 principale di inizializzare il widget che &egrave; indipendente dai valori
7733 passati alla funzione <tt/_new()/. Widget figli o discendenti  possono 
7734 chiamare, solamente, la funzione del loro widget genitore. 
7735 Ma questa divisione del lavoro non funziona bene per la tabella, la
7736 quale, quando creata, necessita di conoscere il numero di righe e
7737 colonne che la comporr&agrave;. A meno che non vogliamo duplicare molte delle 
7738 fuinzionalit&agrave; della <tt/gtk_table_new()/ nel nostro widget
7739 Tictactoe, faremmo meglio a evitare di derivarlo dalla GtkTable. Per questa
7740 ragione lo deriviamo invece da GtkVBox, e uniamo la nostra tabella
7741 dentro il VBox.
7742
7743 <!-- ----------------------------------------------------------------- -->
7744 <sect2> Il File Header
7745
7746 <p>
7747 Ogni classe di widget ha un file header il quale dichiara l'oggetto e la
7748 struttura della classe del widget, comprese le funzioni pubbliche.
7749 Per prevenire duplicati di definizioni, noi includiamo l'intero file header fra:
7750
7751 <tscreen><verb>
7752 #ifndef __TICTACTOE_H__
7753 #define __TICTACTOE_H__
7754 .
7755 .
7756 .
7757 #endif /* __TICTACTOE_H__ */
7758 </verb></tscreen>
7759
7760 E per far felici i programmi in C++ che includono il nostro file header, in:
7761
7762 <tscreen><verb>
7763 #ifdef __cplusplus
7764 extern "C" {
7765 #endif /* __cplusplus */
7766 .
7767 .
7768 .
7769 #ifdef __cplusplus
7770 }
7771 #endif /* __cplusplus */
7772 </verb></tscreen>
7773
7774 Insieme alle funzioni e alle strutture, dichiariamo tre macro 
7775 standard nel nostro file header, <tt/TICTACTOE(obj)/,
7776 <tt/TICTACTOE_CLASS(klass)/, e <tt/IS_TICTACTOE(obj)/, i quali rispettivamente 
7777 fanno il cast di un puntatore ad un puntatore ad un ogetto od ad una struttura
7778 di classe, e guarda se un oggetto &egrave; un widget Tictactoe.
7779
7780
7781 Qui vi &egrave; il file header completo:
7782
7783 <tscreen><verb>
7784 /* tictactoe.h */
7785
7786 #ifndef __TICTACTOE_H__
7787 #define __TICTACTOE_H__
7788
7789 #include <gdk/gdk.h>
7790 #include <gtk/gtkvbox.h>
7791
7792 #ifdef __cplusplus
7793 extern "C" {
7794 #endif /* __cplusplus */
7795
7796 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
7797 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
7798 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
7799
7800
7801 typedef struct _Tictactoe       Tictactoe;
7802 typedef struct _TictactoeClass  TictactoeClass;
7803
7804 struct _Tictactoe
7805 {
7806   GtkVBox vbox;
7807   
7808   GtkWidget *buttons[3][3];
7809 };
7810
7811 struct _TictactoeClass
7812 {
7813   GtkVBoxClass parent_class;
7814
7815   void (* tictactoe) (Tictactoe *ttt);
7816 };
7817
7818 guint          tictactoe_get_type        (void);
7819 GtkWidget*     tictactoe_new             (void);
7820 void           tictactoe_clear           (Tictactoe *ttt);
7821
7822 #ifdef __cplusplus
7823 }
7824 #endif /* __cplusplus */
7825
7826 #endif /* __TICTACTOE_H__ */
7827
7828 </verb></tscreen>
7829
7830 <!-- ----------------------------------------------------------------- -->
7831 <sect2> La funzione <tt/_get_type()/
7832
7833 <p>
7834 Continuiamo ora con l'implementazione del nostro widget. Una funzione
7835 basilare di ogni widget &egrave; la funzione <tt/WIDGETNAME_get_type()/.
7836 Questa funzione, quando chiamata la prima volta, comunica a GTK la classe 
7837 del widget, e ottiene un identificativo univoco per la classe del
7838 widget. Chiamate successive restituiscono semplicemente l'identificativo.
7839
7840 <tscreen><verb>
7841 guint
7842 tictactoe_get_type ()
7843 {
7844   static guint ttt_type = 0;
7845
7846   if (!ttt_type)
7847     {
7848       GtkTypeInfo ttt_info =
7849       {
7850         "Tictactoe",
7851         sizeof (Tictactoe),
7852         sizeof (TictactoeClass),
7853         (GtkClassInitFunc) tictactoe_class_init,
7854         (GtkObjectInitFunc) tictactoe_init,
7855         (GtkArgSetFunc) NULL,
7856         (GtkArgGetFunc) NULL
7857       };
7858
7859       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
7860     }
7861
7862   return ttt_type;
7863 }
7864 </verb></tscreen>
7865
7866 <p>
7867 La struttura GtkTypeInfo ha la seguente definizione:
7868
7869 <tscreen><verb>
7870 struct _GtkTypeInfo
7871 {
7872   gchar *type_name;
7873   guint object_size;
7874   guint class_size;
7875   GtkClassInitFunc class_init_func;
7876   GtkObjectInitFunc object_init_func;
7877   GtkArgSetFunc arg_set_func;
7878   GtkArgGetFunc arg_get_func;
7879 };
7880 </verb></tscreen>
7881
7882 <p>
7883 I campi di questa struttura sono abbastanza auto-esplicativi.
7884 Ignoreremo, per ora, i campi  <tt/arg_set_func/ e <tt/arg_get_func/:
7885 hanno un ruolo importante, ma ancora largamente non
7886 implementato, nel permettere ai linguaggi interpretati
7887 di settare convenientemente le opzioni del widget.
7888 Una volta che il GTK ha completato correttamente una copia di questa
7889 struttura, sa come creare un oggetto di un particolare widget.
7890
7891 <!-- ----------------------------------------------------------------- -->
7892 <sect2> La funzione <tt/_class_init()/ 
7893 <p>
7894 La funzione <tt/WIDGETNAME_class_init()/ inizialiazza i campi della
7895 struttura della classe del widget, e setta ogni segnale della classe.
7896 Per il nostro widget Tictactoe ha il seguente aspetto:
7897
7898 <tscreen><verb>
7899
7900 enum {
7901   TICTACTOE_SIGNAL,
7902   LAST_SIGNAL
7903 };
7904
7905 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
7906
7907 static void
7908 tictactoe_class_init (TictactoeClass *class)
7909 {
7910   GtkObjectClass *object_class;
7911
7912   object_class = (GtkObjectClass*) class;
7913   
7914   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
7915                                          GTK_RUN_FIRST,
7916                                          object_class->type,
7917                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
7918                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
7919
7920
7921   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
7922
7923   class->tictactoe = NULL;
7924 }
7925 </verb></tscreen>
7926
7927 <p>
7928 Il nostro  widget ha semplicemente il segnale ``tictactoe'' che &egrave;
7929 invocato quando una riga, colonna o diagonale &egrave; completamente premuta.
7930 Non tutti i widget composti necessitano di segnali, quindi se stai
7931 leggendo questo per la prima volta, puoi anche saltare alla prossima sezione,
7932 dal momento che a questo punto le cose diventano un po' complicate.
7933
7934 La funzione:
7935 <tscreen><verb>
7936 gint   gtk_signal_new (const gchar         *name,
7937                        GtkSignalRunType    run_type,
7938                        GtkType             object_type,
7939                        gint                function_offset,
7940                        GtkSignalMarshaller marshaller,
7941                        GtkType             return_val,
7942                        guint               nparams,
7943                        ...);
7944
7945 </verb></tscreen>
7946
7947 crea un nuovo segnale. I parametri sono:
7948
7949 <itemize>
7950 <item> <tt/name/: Il nome del segnale.
7951 <item> <tt/run_type/: Se il segstore predefinito viene eseguito prima o dopo
7952 di quello dell'utente. Di norma questo sar&agrave; <tt/GTK_RUN_FIRST/, o <tt/GTK_RUN_LAST/,
7953 anche se ci sono altre possibilit&agrave;.
7954 <item> <tt/object_type/: l'identificativo dell'oggetto a cui questo segnale si 
7955 riferisce. Esso sar&agrave; anche applicato agli oggetti discendenti.
7956 <item> <tt/function_offset/: L'offset nella struttura della classe di un
7957 puntatore al gestore predefinito.
7958 <item> <tt/marshaller/: una funzione che &egrave; usata per invocare il gestore
7959 del segnale. Per gestori di segnali che non hanno argomenti oltre 
7960 all'oggetto che emette il segnale e i dati dell'utente, possiamo usare
7961 la funzione predefinita <tt/gtk_signal_default_marshaller/
7962 <item> <tt/return_val/: Il tipo del valore di ritorno.
7963 <item> <tt/nparams/: Il numero di parametri del gestore di segnali (oltre
7964 ai due predefiniti menzionati sopra)
7965 <item> <tt/.../: i tipi dei parametri
7966 </itemize>
7967
7968 Quando si specificano i tipi, si usa l'enumerazione <tt/GtkType/:
7969
7970 <tscreen><verb>
7971 typedef enum
7972 {
7973   GTK_TYPE_INVALID,
7974   GTK_TYPE_NONE,
7975   GTK_TYPE_CHAR,
7976   GTK_TYPE_BOOL,
7977   GTK_TYPE_INT,
7978   GTK_TYPE_UINT,
7979   GTK_TYPE_LONG,
7980   GTK_TYPE_ULONG,
7981   GTK_TYPE_FLOAT,
7982   GTK_TYPE_DOUBLE,
7983   GTK_TYPE_STRING,
7984   GTK_TYPE_ENUM,
7985   GTK_TYPE_FLAGS,
7986   GTK_TYPE_BOXED,
7987   GTK_TYPE_FOREIGN,
7988   GTK_TYPE_CALLBACK,
7989   GTK_TYPE_ARGS,
7990
7991   GTK_TYPE_POINTER,
7992
7993   /* sarebbe bello poter togliere alla fine i prossimi due */
7994   GTK_TYPE_SIGNAL,
7995   GTK_TYPE_C_CALLBACK,
7996
7997   GTK_TYPE_OBJECT
7998
7999 } GtkFundamentalType;
8000 </verb></tscreen>
8001
8002 <p>
8003 <tt/gtk_signal_new()/ restituisce un identificatore unico intero per il segnale, 
8004 che memorizziamo nel vettore  <tt/tictactoe_signals/, che
8005 indicizzeremo usando una enumerazione. (Convenzionalmente, gli elementi dell'enumerazione
8006 sono i nomi dei segnali, in maiuscolo, 
8007 ma qui ci potrebbe essere un conflitto con la macro <tt/TICTACTOE()/, 
8008 quindi l'abbiamo chiamato  <tt/TICTACTOE_SIGNAL/
8009
8010 Dopo aver creato un nostro segnale, abbiamo bisogno di dire a GTK
8011 di associare il nostro segnale alla classe Tictactoe. Lo facciamo
8012 invocando <tt/gtk_object_class_add_signals()/. Settiamo quindi a NULL
8013 il puntatore che punta al gestore predefinito per il segnale 
8014 ``tictactoe'' a NULL, indicando che non ci sono azioni predefinite.
8015
8016 <!-- ----------------------------------------------------------------- -->
8017 <sect2> La funzione <tt/_init()/
8018
8019 <p>
8020
8021 Ogni classe di Widget necessita anche di una funzione per inizializzare 
8022 la struttura dell'oggetto. Usualmente questa funzione ha il ruolo abbastanza
8023 limitato di assegnare ai campi della struttura i valori predefiniti.
8024 Per widget composti, comunque, questa funzione crea, anche,
8025 i widget componenti del widget composto.
8026
8027 <tscreen><verb>
8028
8029 static void
8030 tictactoe_init (Tictactoe *ttt)
8031 {
8032   GtkWidget *table;
8033   gint i,j;
8034   
8035   table = gtk_table_new (3, 3, TRUE);
8036   gtk_container_add (GTK_CONTAINER(ttt), table);
8037   gtk_widget_show (table);
8038
8039   for (i=0;i<3; i++)
8040     for (j=0;j<3; j++)
8041       {
8042         ttt->buttons[i][j] = gtk_toggle_button_new ();
8043         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
8044                                    i, i+1, j, j+1);
8045         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
8046                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
8047         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
8048         gtk_widget_show (ttt->buttons[i][j]);
8049       }
8050 }
8051 </verb></tscreen>
8052
8053 <!-- ----------------------------------------------------------------- -->
8054 <sect2> E il resto...
8055
8056 <p>
8057
8058 C'&egrave; un'altra funzione che ogni widget (eccetto i Widget di base come 
8059 GtkBin che non possono essere instanziati) deve avere : la funzione
8060 che l'utente invoca per creare un oggetto di quel tipo. Questa &egrave; 
8061 convenzionalmente chiamata <tt/WIDGETNAME_new()/. In alcuni widget,
8062 non nel caso del nostro Tictactoe, questa funzione richiede degli 
8063 argomenti, e fa alcune operazioni basandosi su di essi. Le altre
8064 due funzioni sono specifiche del widget Tictactoe.
8065
8066 <p>
8067 <tt/tictactoe_clear()/ &egrave; una funzione pubblica che resetta tutti i 
8068 bottoni, nel widget, allo stato iniziale (non premuto). Notate l'uso 
8069 di <tt/gtk_signal_handler_block_by_data()/ per impedire che il nostro
8070 gestore dei segnali venga attivato quando non ce n'&egrave; bisogno.
8071
8072 <p>
8073 <tt/tictactoe_toggle()/ &egrave; il gestore del segnale che viene invocato 
8074 quando l'utente preme il bottone. Esso guarda se vi &egrave;
8075 qualche combinazione vincente che coinvolge i bottoni premuti, e nel
8076 caso ci fosse, emette il segnale ``tictactoe''.
8077
8078 <tscreen><verb>  
8079 GtkWidget*
8080 tictactoe_new ()
8081 {
8082   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
8083 }
8084
8085 void           
8086 tictactoe_clear (Tictactoe *ttt)
8087 {
8088   int i,j;
8089
8090   for (i=0;i<3;i++)
8091     for (j=0;j<3;j++)
8092       {
8093         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
8094         gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
8095                                      FALSE);
8096         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
8097       }
8098 }
8099
8100 static void
8101 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
8102 {
8103   int i,k;
8104
8105   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
8106                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
8107                              { 0, 1, 2 }, { 0, 1, 2 } };
8108   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
8109                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
8110                              { 0, 1, 2 }, { 2, 1, 0 } };
8111
8112   int success, found;
8113
8114   for (k=0; k<8; k++)
8115     {
8116       success = TRUE;
8117       found = FALSE;
8118
8119       for (i=0;i<3;i++)
8120         {
8121           success = success &amp;&amp; 
8122             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
8123           found = found ||
8124             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
8125         }
8126       
8127       if (success &amp;&amp; found)
8128         {
8129           gtk_signal_emit (GTK_OBJECT (ttt), 
8130                            tictactoe_signals[TICTACTOE_SIGNAL]);
8131           break;
8132         }
8133     }
8134 }
8135 </verb></tscreen>
8136
8137 <p>
8138
8139 E finalmente un programma di esempio che usa il nostro widget
8140 Tictactoe:
8141
8142 <tscreen><verb>
8143 #include <gtk/gtk.h>
8144 #include "tictactoe.h"
8145
8146 /* Invocato quando una riga, colonna o diagonale e' completata. */
8147 void
8148 win (GtkWidget *widget, gpointer data)
8149 {
8150   g_print ("Yay!\n");
8151   tictactoe_clear (TICTACTOE (widget));
8152 }
8153
8154 int 
8155 main (int argc, char *argv[])
8156 {
8157   GtkWidget *window;
8158   GtkWidget *ttt;
8159   
8160   gtk_init (&amp;argc, &amp;argv);
8161
8162   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8163   
8164   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
8165   
8166   gtk_signal_connect (GTK_OBJECT (window), "destroy",
8167                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
8168   
8169   gtk_container_border_width (GTK_CONTAINER (window), 10);
8170
8171   /* Crea un nuovo widget Tictactoe. */
8172   ttt = tictactoe_new ();
8173   gtk_container_add (GTK_CONTAINER (window), ttt);
8174   gtk_widget_show (ttt);
8175
8176   /* E gli aggancia il segnale "tictactoe" */
8177   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
8178                       GTK_SIGNAL_FUNC (win), NULL);
8179
8180   gtk_widget_show (window);
8181   
8182   gtk_main ();
8183   
8184   return 0;
8185 }
8186
8187 </verb></tscreen>
8188
8189 <!-- ----------------------------------------------------------------- -->
8190 <sect1> Creare un widget a partire da zero
8191
8192 <!-- ----------------------------------------------------------------- -->
8193 <sect2> Introduzione
8194
8195 <p>
8196
8197 In questa sezione impareremo meglio come i widget si mostrano sullo schermo
8198 e interagiscono con gli eventi. Come esempio, creeremo
8199 un widget di quadrante analogico con un puntatore che l'utente 
8200 pu&ograve; trascinare per assegnare il valore.
8201
8202 <!-- ----------------------------------------------------------------- -->
8203 <sect2> Mostrare un widget sullo schermo
8204
8205 <p>
8206 Ci sono alcuni passi che sono necessari nella visualizzazione sullo
8207 schermo. Dopo che il widget &egrave; stato creato con una chiamata a 
8208 <tt/WIDGETNAME_new()/, sono necessarie alcune altre funzioni:
8209
8210 <itemize>
8211 <item> <tt/WIDGETNAME_realize()/ &egrave; responsabile della creazione di 
8212 una finestra X per il widget se ne ha una.
8213 <item> <tt/WIDGETNAME_map()/ &egrave; invocata dopo che l'utente ha 
8214 chiamato <tt/gtk_widget_show()/. E' responsabile di vedere se il
8215 widget &egrave; attualmente disegnato sullo schermo (<em/mappato/). Per 
8216 una classe contenitore, essa deve anche creare chiamate alle 
8217 funzioni  <tt/map()/> per ogni widget figlio.
8218 <item> <tt/WIDGETNAME_draw()/ &egrave; invocata quando 
8219 <tt/gtk_widget_draw()/ viene chiamata per il widget o per uno dei suoi
8220 predecessori. Esso fa s&igrave; che l'attuale chiamata alla
8221 funzione di disegno del widget disegni il widget sullo schermo.
8222 Per la classe contenitore, questa funzione deve eseguire le
8223 chiamate alla funzioni <tt/gtk_widget_draw()/ di ogni suo widget
8224 figlio.
8225 <item> <tt/WIDGETNAME_expose()/ &egrave; un gestore per l'evento di esposizione
8226 per il widget. Esso crea le chiamate necessarie alle funzioni di disegno
8227 per disegnare la porzione che si &egrave; resa visibile. Per le classi 
8228 contenitore, questa funzione deve generare gli eventi di ``expose'' per 
8229 tutti i widget figli che non hanno una propria finestra (se essi hanno
8230 una loro finestra, sar&agrave; X che generer&agrave; i necessari eventi di expose).
8231 </itemize>
8232
8233 <p>
8234 Potete notare che le ultime due funzioni sono molto simili, ognuna &egrave;
8235 responsabile per il disegno del widget sullo schermo. Infatti molti
8236 tipi di widget non sanno relamente la differenza tra le due.
8237 La funzione di predefinita <tt/draw()/ nella classe widget, semplicemente
8238 genera un sintetico evento di ``expose'' per l'area da ridisegnare.
8239 Comunque, alcuni tipi di widget possono risparmiare tempo distinguendo
8240 le due funzioni. Per esempio, se un widget ha piu' finestre X, allora 
8241 visto che l'evento ``expose'' identifica solo la finestra esposta, 
8242 esso pu&ograve; ridisegnare solo la finestra interessata, cosa che non &egrave; 
8243 possibile per chiamate a <tt/draw()/.
8244
8245 <p>
8246 I widget contenitori, anche se essi non farebbero differenze,
8247 non possono semplicemente usare la funzione <tt/draw()/ perch&egrave; per i 
8248 loro widget figli la differenza potrebbere essere importante. Comunque, 
8249 sarebbe uno spreco duplicare il codice di disegno nelle due
8250 funzioni. La convenzione &egrave; che questi widget abbiano una funzione
8251 chiamata <tt/WIDGETNAME_paint()/ che disegna il widget, che &egrave; poi
8252 chiamata dalle funzioni <tt/draw()/ e <tt/expose()/
8253
8254 <p>
8255 Nell'approccio del nostro esempio, visto che il widget, ha 
8256 una sola finestra, possiamo utilizzare il modo piu' semplice
8257 ed usare la funzione predefinita <tt/draw()/ e implementare
8258 solamente la funzione <tt/expose()/.
8259
8260 <!-- ----------------------------------------------------------------- -->
8261 <sect2> Le origini del widget Dial
8262
8263 <p>
8264 Come tutti gli animali terresti sono semplicemente varianti del primo
8265 amfibio, i widget Gtk tendono ad essere varianti di altri widget, precedentemente
8266 scritti. Cos&igrave;, anche se questa sezione &egrave; intitolata ``Creare
8267 un widget a partire da zero", il nostro widget inizia in realt&agrave; con il codice 
8268 sorgente del widget Range. Questo &egrave; stato preso come punto d'inizio
8269 perche' sarebbe carino se il nostro widget avesse la
8270 stessa interfaccia del widget Scale il quale &egrave; semplicemente una
8271 specializzazione del widget Range. Cos&igrave;, sebbene  il codice sorgente e' 
8272 presentato sotto in forma definitiva, non si deve pensare che sia stato
8273 scritto <em>deus ex machina</em> in questo modo. Se poi non avete familiarit&agrave;
8274 con il funzionamento del widget Scale dal punto di vista di chi scrive
8275 un'applicazione, potrebbe essere una buona idea guardare indietro prima 
8276 di continuare.
8277
8278 <!-- ----------------------------------------------------------------- -->
8279 <sect2> Le basi
8280
8281 <p>
8282 Una parte del nostro widget potrebbe essere simile
8283 al widget Tictactoe. In primo luogo, abbiamo il file header:
8284
8285 <tscreen><verb>
8286 /* GTK - The GIMP Toolkit
8287  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
8288  *
8289  * This library is free software; you can redistribute it and/or
8290  * modify it under the terms of the GNU Library General Public
8291  * License as published by the Free Software Foundation; either
8292  * version 2 of the License, or (at your option) any later version.
8293  *
8294  * This library is distributed in the hope that it will be useful,
8295  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8296  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
8297  * Library General Public License for more details.
8298  *
8299  * You should have received a copy of the GNU Library General Public
8300  * License along with this library; if not, write to the Free
8301  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8302  */
8303
8304 #ifndef __GTK_DIAL_H__
8305 #define __GTK_DIAL_H__
8306
8307 #include <gdk/gdk.h>
8308 #include <gtk/gtkadjustment.h>
8309 #include <gtk/gtkwidget.h>
8310
8311
8312 #ifdef __cplusplus
8313 extern "C" {
8314 #endif /* __cplusplus */
8315
8316
8317 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
8318 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
8319 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
8320
8321
8322 typedef struct _GtkDial        GtkDial;
8323 typedef struct _GtkDialClass   GtkDialClass;
8324
8325 struct _GtkDial
8326 {
8327   GtkWidget widget;
8328
8329   /* Politica di update (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
8330   guint policy : 2;
8331
8332   /* Bottone correntemente premuto o 0 altrimenti */
8333   guint8 button;
8334
8335   /* Dimensione della componente Dial. */
8336   gint radius;
8337   gint pointer_width;
8338
8339   /* ID del timer di update, o 0 altrimenti */
8340   guint32 timer;
8341
8342   /* Angolo corrente. */
8343   gfloat angle;
8344
8345   /* Vecchi valori dell'aggiustamento cos&igrave; sappiamo quando 
8346    * qualcosa cambia */
8347   gfloat old_value;
8348   gfloat old_lower;
8349   gfloat old_upper;
8350
8351   /* L'oggetto adjustament che memorizza i dati per questo dial */
8352   GtkAdjustment *adjustment;
8353 };
8354
8355 struct _GtkDialClass
8356 {
8357   GtkWidgetClass parent_class;
8358 };
8359
8360
8361 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
8362 guint          gtk_dial_get_type               (void);
8363 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
8364 void           gtk_dial_set_update_policy      (GtkDial      *dial,
8365                                                 GtkUpdateType  policy);
8366
8367 void           gtk_dial_set_adjustment         (GtkDial      *dial,
8368                                                 GtkAdjustment *adjustment);
8369 #ifdef __cplusplus
8370 }
8371 #endif /* __cplusplus */
8372
8373
8374 #endif /* __GTK_DIAL_H__ */
8375 </verb></tscreen>
8376
8377 Essendoci pi&ugrave; cose da fare con questo widget, rispetto al precedente,
8378 abbiamo pi&ugrave; cambi nella struttura dati, ma le altre cose sono 
8379 abbastamza simili.
8380
8381 Dopo aver incluso i file di header e aver dichiarato alcune costanti,
8382 dobbiamo fornire alcune funzioni circa il widget e la sua
8383 inizializzazione.
8384
8385 <tscreen><verb>
8386 #include <math.h>
8387 #include <stdio.h>
8388 #include <gtk/gtkmain.h>
8389 #include <gtk/gtksignal.h>
8390
8391 #include "gtkdial.h"
8392
8393 #define SCROLL_DELAY_LENGTH  300
8394 #define DIAL_DEFAULT_SIZE 100
8395
8396 /* Dichiarazioni di funzioni successive */
8397
8398 [ omesse per salvare spazio ]
8399
8400 /* variabili locali. */
8401
8402 static GtkWidgetClass *parent_class = NULL;
8403
8404 guint
8405 gtk_dial_get_type ()
8406 {
8407   static guint dial_type = 0;
8408
8409   if (!dial_type)
8410     {
8411       GtkTypeInfo dial_info =
8412       {
8413         "GtkDial",
8414         sizeof (GtkDial),
8415         sizeof (GtkDialClass),
8416         (GtkClassInitFunc) gtk_dial_class_init,
8417         (GtkObjectInitFunc) gtk_dial_init,
8418         (GtkArgSetFunc) NULL,
8419         (GtkArgGetFunc) NULL,
8420       };
8421
8422       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
8423     }
8424
8425   return dial_type;
8426 }
8427
8428 static void
8429 gtk_dial_class_init (GtkDialClass *class)
8430 {
8431   GtkObjectClass *object_class;
8432   GtkWidgetClass *widget_class;
8433
8434   object_class = (GtkObjectClass*) class;
8435   widget_class = (GtkWidgetClass*) class;
8436
8437   parent_class = gtk_type_class (gtk_widget_get_type ());
8438
8439   object_class->destroy = gtk_dial_destroy;
8440
8441   widget_class->realize = gtk_dial_realize;
8442   widget_class->expose_event = gtk_dial_expose;
8443   widget_class->size_request = gtk_dial_size_request;
8444   widget_class->size_allocate = gtk_dial_size_allocate;
8445   widget_class->button_press_event = gtk_dial_button_press;
8446   widget_class->button_release_event = gtk_dial_button_release;
8447   widget_class->motion_notify_event = gtk_dial_motion_notify;
8448 }
8449
8450 static void
8451 gtk_dial_init (GtkDial *dial)
8452 {
8453   dial->button = 0;
8454   dial->policy = GTK_UPDATE_CONTINUOUS;
8455   dial->timer = 0;
8456   dial->radius = 0;
8457   dial->pointer_width = 0;
8458   dial->angle = 0.0;
8459   dial->old_value = 0.0;
8460   dial->old_lower = 0.0;
8461   dial->old_upper = 0.0;
8462   dial->adjustment = NULL;
8463 }
8464
8465 GtkWidget*
8466 gtk_dial_new (GtkAdjustment *adjustment)
8467 {
8468   GtkDial *dial;
8469
8470   dial = gtk_type_new (gtk_dial_get_type ());
8471
8472   if (!adjustment)
8473     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
8474
8475   gtk_dial_set_adjustment (dial, adjustment);
8476
8477   return GTK_WIDGET (dial);
8478 }
8479
8480 static void
8481 gtk_dial_destroy (GtkObject *object)
8482 {
8483   GtkDial *dial;
8484
8485   g_return_if_fail (object != NULL);
8486   g_return_if_fail (GTK_IS_DIAL (object));
8487
8488   dial = GTK_DIAL (object);
8489
8490   if (dial->adjustment)
8491     gtk_object_unref (GTK_OBJECT (dial->adjustment));
8492
8493   if (GTK_OBJECT_CLASS (parent_class)->destroy)
8494     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
8495 }
8496 </verb></tscreen>
8497
8498 Notate che questa funzione <tt/init()/ fa meno rispetto all'analoga del
8499 widget Tictactoe, essendo questo un widget non composto, e la 
8500 funzione <tt/new()/ fa di pi&ugrave;, essendoci un argomento. Inoltre, 
8501 notate che quando memorizziamo un puntatore all'oggetto Adjustment,
8502 incrementiamo il conteggio dei suoi riferimenti(e corrispondentemente 
8503 lo decrementato quando non lo usiamo pi&ugrave;) cos&igrave; che GTK pu&ograve; tener traccia di 
8504 quando &egrave; possibile distruggerlo senza causare guai.
8505
8506 <p>
8507 Inoltre, ci sono alcune funzioni per manipolare le opzioni del widget:
8508
8509 <tscreen><verb>
8510 GtkAdjustment*
8511 gtk_dial_get_adjustment (GtkDial *dial)
8512 {
8513   g_return_val_if_fail (dial != NULL, NULL);
8514   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
8515
8516   return dial->adjustment;
8517 }
8518
8519 void
8520 gtk_dial_set_update_policy (GtkDial      *dial,
8521                              GtkUpdateType  policy)
8522 {
8523   g_return_if_fail (dial != NULL);
8524   g_return_if_fail (GTK_IS_DIAL (dial));
8525
8526   dial->policy = policy;
8527 }
8528
8529 void
8530 gtk_dial_set_adjustment (GtkDial      *dial,
8531                           GtkAdjustment *adjustment)
8532 {
8533   g_return_if_fail (dial != NULL);
8534   g_return_if_fail (GTK_IS_DIAL (dial));
8535
8536   if (dial->adjustment)
8537     {
8538       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
8539       gtk_object_unref (GTK_OBJECT (dial->adjustment));
8540     }
8541
8542   dial->adjustment = adjustment;
8543   gtk_object_ref (GTK_OBJECT (dial->adjustment));
8544
8545   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
8546                       (GtkSignalFunc) gtk_dial_adjustment_changed,
8547                       (gpointer) dial);
8548   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
8549                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
8550                       (gpointer) dial);
8551
8552   dial->old_value = adjustment->value;
8553   dial->old_lower = adjustment->lower;
8554   dial->old_upper = adjustment->upper;
8555
8556   gtk_dial_update (dial);
8557 }
8558 </verb></tscreen>
8559
8560 <!-- ----------------------------------------------------------------- -->
8561 <sect2> <tt/gtk_dial_realize()/
8562
8563 <p>
8564 Abbiamo ora raggiunto alcuni nuovi tipi di funzione. In primo luogo,
8565 abbiamo una funzione che crea la finestra di X. Noterete che viene
8566 passata alla funzione <tt/gdk_window_new()/ una maschera che 
8567 specifica quali campi della struttura GdkWindowAttr non sono vuoti 
8568 (ai rimanenti campi pu&ograve; essere dato il valore predefinito). Anche 
8569 il modo con cui la maschera degli eventi del widget  creata non &egrave;
8570 complicato. Chiameremo <tt/gtk_widget_get_events()/ per sapere la 
8571 maschera degli eventi che l'utente ha specificato per questo widget
8572 (con <tt/gtk_widget_set_events()/) e aggiungeremo gli eventi che ci possono 
8573 interessare.
8574
8575 <p>
8576 Dopo aver creato la finestra, settiamo lo stile e lo sfondo,
8577 e creiamo un puntatore al widget nel campo dei dati utente (user data)
8578 del GdkWindow. Quest'ultimo passo permette a GTK di mandare gli 
8579 eventi della finestra al widget corretto.
8580
8581 <tscreen><verb>
8582 static void
8583 gtk_dial_realize (GtkWidget *widget)
8584 {
8585   GtkDial *dial;
8586   GdkWindowAttr attributes;
8587   gint attributes_mask;
8588
8589   g_return_if_fail (widget != NULL);
8590   g_return_if_fail (GTK_IS_DIAL (widget));
8591
8592   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
8593   dial = GTK_DIAL (widget);
8594
8595   attributes.x = widget->allocation.x;
8596   attributes.y = widget->allocation.y;
8597   attributes.width = widget->allocation.width;
8598   attributes.height = widget->allocation.height;
8599   attributes.wclass = GDK_INPUT_OUTPUT;
8600   attributes.window_type = GDK_WINDOW_CHILD;
8601   attributes.event_mask = gtk_widget_get_events (widget) | 
8602     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
8603     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
8604     GDK_POINTER_MOTION_HINT_MASK;
8605   attributes.visual = gtk_widget_get_visual (widget);
8606   attributes.colormap = gtk_widget_get_colormap (widget);
8607
8608   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
8609   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
8610
8611   widget->style = gtk_style_attach (widget->style, widget->window);
8612
8613   gdk_window_set_user_data (widget->window, widget);
8614
8615   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
8616 }
8617 </verb></tscreen>
8618
8619 <!-- ----------------------------------------------------------------- -->
8620 <sect2> Negoziazione della dimensione
8621
8622 <p>
8623 Prima di visualizzare per la prima volta la finestra, e  se il 
8624 layout della finestra cambia, GTK chiede ad ogni widget, incluso nella
8625 finestra, la propria dimensione. Questa richiesta &egrave; fatta dalla
8626 funzione  <tt/gtk_dial_size_request()/. Non essendo il nostro widget 
8627 un contenitore, e non avendo dei veri limiti per la propria
8628 dimensione, restituiamo semplicemnte un valore ragionevole.
8629
8630 <tscreen><verb>
8631 static void 
8632 gtk_dial_size_request (GtkWidget      *widget,
8633                        GtkRequisition *requisition)
8634 {
8635   requisition->width = DIAL_DEFAULT_SIZE;
8636   requisition->height = DIAL_DEFAULT_SIZE;
8637 }
8638 </verb></tscreen>
8639
8640 <p>
8641 Dopo che tutti i widget hanno restituito una dimensione ideale, viene 
8642 calcolata la disposizione della finestra  e ad ogni widget figlio &egrave;
8643 notificata la propria dimensione attuale <!--ndMichel : che pu&ograve; essere diversa
8644 da quella restitutita con la funzione sopra -->. Usualmente, questo sar&agrave; 
8645 almeno quanto richiesto, ma occasionalmente pu&ograve; essere pi&ugrave; piccolo. 
8646 La notifica della dimensione  viene fatta dalla funzione
8647  <tt/gtk_dial_size_allocate()/. Notate che questa funzione &egrave; utilizzata
8648 anche quando la finestra X del widget &egrave; spostata o modificata come 
8649 dimensione.
8650
8651 <tscreen><verb>
8652 static void
8653 gtk_dial_size_allocate (GtkWidget     *widget,
8654                         GtkAllocation *allocation)
8655 {
8656   GtkDial *dial;
8657
8658   g_return_if_fail (widget != NULL);
8659   g_return_if_fail (GTK_IS_DIAL (widget));
8660   g_return_if_fail (allocation != NULL);
8661
8662   widget->allocation = *allocation;
8663   if (GTK_WIDGET_REALIZED (widget))
8664     {
8665       dial = GTK_DIAL (widget);
8666
8667       gdk_window_move_resize (widget->window,
8668                               allocation->x, allocation->y,
8669                               allocation->width, allocation->height);
8670
8671       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
8672       dial->pointer_width = dial->radius / 5;
8673     }
8674 }
8675 </verb></tscreen>.
8676
8677 <!-- ----------------------------------------------------------------- -->
8678 <sect2> <tt/gtk_dial_expose()/
8679
8680 <p>
8681 Come menzionato sopra, tutto il lavoro di questo widget viene fatto nella
8682 gestione dell'evento ``expose''. Non c'&egrave; molto da notare su questo eccetto
8683 l'uso della funzione <tt/gtk_draw_polygon/ per disegnare il 
8684 puntatore con un'ombreggiatura a tre dimensioni in accordo con il colore
8685 memorizzato nello stile del wiget.
8686
8687 <tscreen><verb>
8688 static gint
8689 gtk_dial_expose (GtkWidget      *widget,
8690                  GdkEventExpose *event)
8691 {
8692   GtkDial *dial;
8693   GdkPoint points[3];
8694   gdouble s,c;
8695   gdouble theta;
8696   gint xc, yc;
8697   gint tick_length;
8698   gint i;
8699
8700   g_return_val_if_fail (widget != NULL, FALSE);
8701   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
8702   g_return_val_if_fail (event != NULL, FALSE);
8703
8704   if (event->count > 0)
8705     return FALSE;
8706   
8707   dial = GTK_DIAL (widget);
8708
8709   gdk_window_clear_area (widget->window,
8710                          0, 0,
8711                          widget->allocation.width,
8712                          widget->allocation.height);
8713
8714   xc = widget->allocation.width/2;
8715   yc = widget->allocation.height/2;
8716
8717   /* Draw ticks */
8718
8719   for (i=0; i<25; i++)
8720     {
8721       theta = (i*M_PI/18. - M_PI/6.);
8722       s = sin(theta);
8723       c = cos(theta);
8724
8725       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
8726       
8727       gdk_draw_line (widget->window,
8728                      widget->style->fg_gc[widget->state],
8729                      xc + c*(dial->radius - tick_length),
8730                      yc - s*(dial->radius - tick_length),
8731                      xc + c*dial->radius,
8732                      yc - s*dial->radius);
8733     }
8734
8735   /* Draw pointer */
8736
8737   s = sin(dial->angle);
8738   c = cos(dial->angle);
8739
8740
8741   points[0].x = xc + s*dial->pointer_width/2;
8742   points[0].y = yc + c*dial->pointer_width/2;
8743   points[1].x = xc + c*dial->radius;
8744   points[1].y = yc - s*dial->radius;
8745   points[2].x = xc - s*dial->pointer_width/2;
8746   points[2].y = yc - c*dial->pointer_width/2;
8747
8748   gtk_draw_polygon (widget->style,
8749                     widget->window,
8750                     GTK_STATE_NORMAL,
8751                     GTK_SHADOW_OUT,
8752                     points, 3,
8753                     TRUE);
8754   
8755   return FALSE;
8756 }
8757 </verb></tscreen>
8758
8759 <!-- ----------------------------------------------------------------- -->
8760 <sect2> Gestione degli eventi
8761
8762 <p>
8763
8764 Il resto del codice del widget manipola vari tipi di eventi, e non
8765 &egrave; differente da quello che pu&ograve; essere trovato in molte applicazione
8766 GTK. Due tipi di eventi possono verificarsi: l'utente pu&ograve; 
8767 clickare sul widget con il mouse e trascinare per muovere il puntatore, 
8768 o il valore dell'oggetto Adjustmente pu&ograve; cambiare a causa di alcune
8769 circostanze esterne.
8770
8771 <p>
8772 Quando l'utente clicka sul widget, noi vediamo se la pressione
8773 era veramente vicina al puntatore, e se cos&igrave;, memorizziamo il bottone
8774 premuto dall'utente con il campo <tt/button/ della struttura del
8775 widget, e prendiamo tutti gli eventi del mouse con una chiamata alla
8776 funzione <tt/gtk_grab_add()/. Successivi movimenti del mouse causano il 
8777 ricalcolo dei valori di controllo (fatto dalla funzione 
8778 <tt/gtk_dial_update_mouse/). Dipendentemente dalla politica che abbiamo
8779 stabilito, gli eventi ``value_changed'' possono essere  generati
8780 istantaneamente (<tt/GTK_UPDATE_CONTINUOUS/), dopo un certo tempo aggiunto
8781 con la funzione <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), o
8782 solamente quando il bottone del mouse e' rilasciato 
8783 (<tt/GTK_UPDATE_DISCONTINUOUS/).
8784
8785 <tscreen><verb>
8786 static gint
8787 gtk_dial_button_press (GtkWidget      *widget,
8788                        GdkEventButton *event)
8789 {
8790   GtkDial *dial;
8791   gint dx, dy;
8792   double s, c;
8793   double d_parallel;
8794   double d_perpendicular;
8795
8796   g_return_val_if_fail (widget != NULL, FALSE);
8797   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
8798   g_return_val_if_fail (event != NULL, FALSE);
8799
8800   dial = GTK_DIAL (widget);
8801
8802   /* Determina se il bottone premuto era dentro la regione del puntatore:
8803      lo facciamo calcolando la distanza parallela e 
8804      perpendicolare dal punto dove il bottone del mouse e' stato premuto
8805      alla linea passante per il puntatore. */
8806   
8807   dx = event->x - widget->allocation.width / 2;
8808   dy = widget->allocation.height / 2 - event->y;
8809   
8810   s = sin(dial->angle);
8811   c = cos(dial->angle);
8812   
8813   d_parallel = s*dy + c*dx;
8814   d_perpendicular = fabs(s*dx - c*dy);
8815   
8816   if (!dial->button &&
8817       (d_perpendicular < dial->pointer_width/2) &&
8818       (d_parallel > - dial->pointer_width))
8819     {
8820       gtk_grab_add (widget);
8821
8822       dial->button = event->button;
8823
8824       gtk_dial_update_mouse (dial, event->x, event->y);
8825     }
8826
8827   return FALSE;
8828 }
8829
8830 static gint
8831 gtk_dial_button_release (GtkWidget      *widget,
8832                           GdkEventButton *event)
8833 {
8834   GtkDial *dial;
8835
8836   g_return_val_if_fail (widget != NULL, FALSE);
8837   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
8838   g_return_val_if_fail (event != NULL, FALSE);
8839
8840   dial = GTK_DIAL (widget);
8841
8842   if (dial->button == event->button)
8843     {
8844       gtk_grab_remove (widget);
8845
8846       dial->button = 0;
8847
8848       if (dial->policy == GTK_UPDATE_DELAYED)
8849         gtk_timeout_remove (dial->timer);
8850       
8851       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
8852           (dial->old_value != dial->adjustment->value))
8853         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
8854     }
8855
8856   return FALSE;
8857 }
8858
8859 static gint
8860 gtk_dial_motion_notify (GtkWidget      *widget,
8861                          GdkEventMotion *event)
8862 {
8863   GtkDial *dial;
8864   GdkModifierType mods;
8865   gint x, y, mask;
8866
8867   g_return_val_if_fail (widget != NULL, FALSE);
8868   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
8869   g_return_val_if_fail (event != NULL, FALSE);
8870
8871   dial = GTK_DIAL (widget);
8872
8873   if (dial->button != 0)
8874     {
8875       x = event->x;
8876       y = event->y;
8877
8878       if (event->is_hint || (event->window != widget->window))
8879         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
8880
8881       switch (dial->button)
8882         {
8883         case 1:
8884           mask = GDK_BUTTON1_MASK;
8885           break;
8886         case 2:
8887           mask = GDK_BUTTON2_MASK;
8888           break;
8889         case 3:
8890           mask = GDK_BUTTON3_MASK;
8891           break;
8892         default:
8893           mask = 0;
8894           break;
8895         }
8896
8897       if (mods & mask)
8898         gtk_dial_update_mouse (dial, x,y);
8899     }
8900
8901   return FALSE;
8902 }
8903
8904 static gint
8905 gtk_dial_timer (GtkDial *dial)
8906 {
8907   g_return_val_if_fail (dial != NULL, FALSE);
8908   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
8909
8910   if (dial->policy == GTK_UPDATE_DELAYED)
8911     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
8912
8913   return FALSE;
8914 }
8915
8916 static void
8917 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
8918 {
8919   gint xc, yc;
8920   gfloat old_value;
8921
8922   g_return_if_fail (dial != NULL);
8923   g_return_if_fail (GTK_IS_DIAL (dial));
8924
8925   xc = GTK_WIDGET(dial)->allocation.width / 2;
8926   yc = GTK_WIDGET(dial)->allocation.height / 2;
8927
8928   old_value = dial->adjustment->value;
8929   dial->angle = atan2(yc-y, x-xc);
8930
8931   if (dial->angle < -M_PI/2.)
8932     dial->angle += 2*M_PI;
8933
8934   if (dial->angle < -M_PI/6)
8935     dial->angle = -M_PI/6;
8936
8937   if (dial->angle > 7.*M_PI/6.)
8938     dial->angle = 7.*M_PI/6.;
8939
8940   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
8941     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
8942
8943   if (dial->adjustment->value != old_value)
8944     {
8945       if (dial->policy == GTK_UPDATE_CONTINUOUS)
8946         {
8947           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
8948         }
8949       else
8950         {
8951           gtk_widget_draw (GTK_WIDGET(dial), NULL);
8952
8953           if (dial->policy == GTK_UPDATE_DELAYED)
8954             {
8955               if (dial->timer)
8956                 gtk_timeout_remove (dial->timer);
8957
8958               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
8959                                              (GtkFunction) gtk_dial_timer,
8960                                              (gpointer) dial);
8961             }
8962         }
8963     }
8964 }
8965 </verb></tscreen>
8966
8967 <p>
8968 Cambiamenti esterni all'Adjustment sono comunicati al nostro widget
8969 dai segnali ``changed'' e ``value_changed''. Il gestore per 
8970 queste funzioni chiama  <tt/gtk_dial_update()/ per validare gli
8971 argomenti, calcolare il nuovo angolo del puntatore e ridisegnare il
8972 widget (chiamando <tt/gtk_widget_draw()/).
8973
8974 <tscreen><verb>
8975 static void
8976 gtk_dial_update (GtkDial *dial)
8977 {
8978   gfloat new_value;
8979   
8980   g_return_if_fail (dial != NULL);
8981   g_return_if_fail (GTK_IS_DIAL (dial));
8982
8983   new_value = dial->adjustment->value;
8984   
8985   if (new_value < dial->adjustment->lower)
8986     new_value = dial->adjustment->lower;
8987
8988   if (new_value > dial->adjustment->upper)
8989     new_value = dial->adjustment->upper;
8990
8991   if (new_value != dial->adjustment->value)
8992     {
8993       dial->adjustment->value = new_value;
8994       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
8995     }
8996
8997   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
8998     (dial->adjustment->upper - dial->adjustment->lower);
8999
9000   gtk_widget_draw (GTK_WIDGET(dial), NULL);
9001 }
9002
9003 static void
9004 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
9005                               gpointer       data)
9006 {
9007   GtkDial *dial;
9008
9009   g_return_if_fail (adjustment != NULL);
9010   g_return_if_fail (data != NULL);
9011
9012   dial = GTK_DIAL (data);
9013
9014   if ((dial->old_value != adjustment->value) ||
9015       (dial->old_lower != adjustment->lower) ||
9016       (dial->old_upper != adjustment->upper))
9017     {
9018       gtk_dial_update (dial);
9019
9020       dial->old_value = adjustment->value;
9021       dial->old_lower = adjustment->lower;
9022       dial->old_upper = adjustment->upper;
9023     }
9024 }
9025
9026 static void
9027 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
9028                                     gpointer       data)
9029 {
9030   GtkDial *dial;
9031
9032   g_return_if_fail (adjustment != NULL);
9033   g_return_if_fail (data != NULL);
9034
9035   dial = GTK_DIAL (data);
9036
9037   if (dial->old_value != adjustment->value)
9038     {
9039       gtk_dial_update (dial);
9040
9041       dial->old_value = adjustment->value;
9042     }
9043 }
9044 </verb></tscreen>
9045
9046 <!-- ----------------------------------------------------------------- -->
9047 <sect2> Possibili Miglioramenti
9048 <p>
9049
9050 Il widget Dial, da come l'abbiamo costruito, &egrave; lungo circa 670 linee
9051 di codice C. Anche se questo potrebbe sembrare un po' troppo, abbiamo
9052 realmente fatto un bel po' con quel tanto di codice, specialmente 
9053 considerando che molta della lunghezza &egrave; costituita da file header e
9054 commmenti. Comunque ci sono alcuni miglioramenti che potrebbero essere
9055 fatti a questo widget:
9056
9057 <itemize>
9058 <item> Se tu provate questo widget, troverete che ci sono alcuni lampeggiamenti
9059 quando il puntatore viene trascinato in giro. Questo 
9060 perch&egrave; l'intero widget &egrave; cancellato ogni volta che il 
9061 puntatore viene mosso, prima di essere ridisegnato. Spesso, il modo migliore
9062 per gestire questo tipo di problema &egrave; il disegnare il tutto su una 
9063 pixmap non visibile, poi copiare il risultato finale sullo schermo 
9064 in una passata sola (il widget ProgressBar viene disegnato in questo
9065 modo).
9066
9067 <item> L'utente potrebbe essere abilitato ad usare le frecce su e giu per
9068 incrementare e diminuire il valore.
9069
9070 <item> Potrebbe essere carino se il widget avesse i bottoni per 
9071 incrementare e decrementare il valore di step. Anche se potrebbe essere
9072 possibile usare dei widget Bottone incorporati per questo, possiamo anche
9073 far s&igrave; che il bottone sia auto-ripentente quando premuto, come le frecce
9074 in una barra di scorrimento. Molto del codice per implementare questo tipo di 
9075 comportamento pu&ograve; essere trovato nel widget GtkRange.
9076
9077 <item> il widget Dial potrebbe essere fatto/creato dentro un widget 
9078 contenitore con un singolo widget figlio posizionato all'inizio tra i 
9079 2 bottoni menzionati prima. L'utente potrebbe poi aggiungere o una etichetta
9080 o un widget ``entry'' per mostrare il valore corrente del dial.
9081
9082 </itemize>
9083
9084 <!-- ----------------------------------------------------------------- -->
9085 <sect1> Impararne di pi&ugrave;
9086
9087 <p> 
9088 Fin qui abbiamo esposto solo una piccola parte di tutto quello che serve
9089 per creare un widget. Se volete davvero  scrivere un vostro widget, la
9090 miglior risorsa di esempi &egrave; lo stesso codice sorgente GTK. Chiedete a voi
9091 stessi alcune cose su come deve essere il widget che volete scrivere: &egrave;
9092 un widget contenitore? dovr&agrave; avere una propria finestra? &egrave; una modifica di 
9093 un widget precedente? Trovate poi un widget simile e iniziate a fargli 
9094 delle modifiche.
9095 Buone Fortuna.
9096
9097 <!-- ***************************************************************** -->
9098 <sect>Scribble, Un semplice esempio di Programma di Disegno
9099 <!-- ***************************************************************** -->
9100
9101 <!-- ----------------------------------------------------------------- -->
9102 <sect1> Panoramica
9103
9104 <p>
9105 In questa sezione, creeremo un semplice programma di disegno. Durante
9106 questo processo, esamineremo come gestire gli eventi generati dal mouse,
9107 come disegnare all'interno di una finestra e come disegnare in modo migliore
9108 usando una pixmap di supporto. Dopo averlo creato, lo amplieremo aggiungendo
9109 il supporto per i dispositivi XInput, per esempio le tavolette grafiche.
9110 Il GTK fornisce delle routine di supporto grazie alle quali risulta  piuttosto
9111 semplice ottenere informazioni estese, come la pressione o l'inclinazione.
9112
9113 <!-- ----------------------------------------------------------------- -->
9114 <sect1> Gestione degli Eventi
9115
9116 <p>
9117 I segnali di GTK che abbiamo discusso finora si riferivano ad azioni di
9118 alto livello, ad esempio la selezione di un elemento di un men&ugrave;. Per&ograve;, a volte
9119 &egrave; utile sapere qualcosa su cose che si svolgono a livello pi&ugrave; basso livello,
9120 come possono essere il movimento del mouse o la pressione di un tasto.
9121 Ci sono segnali di GTK anche per questi <em>eventi</em> di basso livello.
9122 I gestori di questo tipo di segnali hanno un parametro caratteristico in pi&ugrave;,
9123 che &egrave; il puntatore ad una struttura che contiene informazioni riguardo
9124 all'evento. Per esempio, ai gestori di eventi che riguardano dei movimenti,
9125 si passa un puntatore ad una struttura GdkEventMotion, che &egrave; fatta (in parte)
9126 cos&igrave;:
9127
9128 <tscreen><verb>
9129 struct _GdkEventMotion
9130 {
9131   GdkEventType type;
9132   GdkWindow *window;
9133   guint32 time;
9134   gdouble x;
9135   gdouble y;
9136   ...
9137   guint state;
9138   ...
9139 };
9140 </verb></tscreen>
9141
9142 <tt/type/ avr&agrave; il valore del tipo di evento, in questo caso 
9143 <tt/GDK_MOTION_NOTIFY/, <tt/window/ rappresenta la finestra in cui l'evento
9144 si &egrave; verificato. <tt/x/ e <tt/y/ forniscono le coordinate dell'evento e
9145 <tt/state/ specifica lo stato dei modificatori nel momento in cui l'evento
9146 si &egrave; verificato (cio&egrave;, specifica quali tasti modificatori e tasti del mouse
9147 erano premuti in quel momento). E' un OR bit per bit dei seguenti valori:
9148
9149 <tscreen><verb>
9150 GDK_SHIFT_MASK  
9151 GDK_LOCK_MASK   
9152 GDK_CONTROL_MASK
9153 GDK_MOD1_MASK   
9154 GDK_MOD2_MASK   
9155 GDK_MOD3_MASK   
9156 GDK_MOD4_MASK   
9157 GDK_MOD5_MASK   
9158 GDK_BUTTON1_MASK
9159 GDK_BUTTON2_MASK
9160 GDK_BUTTON3_MASK
9161 GDK_BUTTON4_MASK
9162 GDK_BUTTON5_MASK
9163 </verb></tscreen>
9164
9165 <p>
9166 Come succede per gli altri segnali, per determinare cosa deve accadere in
9167 corrispondenza di un evento, si chiama <tt>gtk_signal_connect()</tt>. Ma
9168 &egrave; anche necessario far s&igrave; che GTK sappia di quali eventi vogliamo essere
9169 informati. A questo fine, chiamiamo la funzione:
9170
9171 <tscreen><verb>
9172 void  gtk_widget_set_events (GtkWidget *widget, gint events);
9173 </verb></tscreen>
9174
9175 Il secondo campo specifica gli eventi che ci interessano. Si tratta dell'OR
9176 bit per bit delle costanti che identificano i diversi tipi di eventi. La lista
9177 dei tipi di eventi &egrave; la seguente:
9178
9179 <tscreen><verb>
9180 GDK_EXPOSURE_MASK
9181 GDK_POINTER_MOTION_MASK
9182 GDK_POINTER_MOTION_HINT_MASK
9183 GDK_BUTTON_MOTION_MASK     
9184 GDK_BUTTON1_MOTION_MASK    
9185 GDK_BUTTON2_MOTION_MASK    
9186 GDK_BUTTON3_MOTION_MASK    
9187 GDK_BUTTON_PRESS_MASK      
9188 GDK_BUTTON_RELEASE_MASK    
9189 GDK_KEY_PRESS_MASK         
9190 GDK_KEY_RELEASE_MASK       
9191 GDK_ENTER_NOTIFY_MASK      
9192 GDK_LEAVE_NOTIFY_MASK      
9193 GDK_FOCUS_CHANGE_MASK      
9194 GDK_STRUCTURE_MASK         
9195 GDK_PROPERTY_CHANGE_MASK   
9196 GDK_PROXIMITY_IN_MASK      
9197 GDK_PROXIMITY_OUT_MASK     
9198 </verb></tscreen>
9199
9200 Per chiamare <tt/gtk_widget_set_events()/, si devono fare alcune osservazioni
9201 sottili. In primo luogo, la si deve chiamare prima che sia stata creata la
9202 finestra X per il widget GTK. In pratica, ci&ograve; significa che la si deve
9203 chiamare subito dopo aver creato il widget. In secondo luogo, il widget
9204 deve avere una finestra X associata. Molti widget, per ragioni di
9205 efficienza, non hanno una propria finetra, e vengono mostrati nella
9206 finestra madre. Questi widget sono:
9207
9208 <tscreen><verb>
9209 GtkAlignment
9210 GtkArrow
9211 GtkBin
9212 GtkBox
9213 GtkImage
9214 GtkItem
9215 GtkLabel
9216 GtkPixmap
9217 GtkScrolledWindow
9218 GtkSeparator
9219 GtkTable
9220 GtkAspectFrame
9221 GtkFrame
9222 GtkVBox
9223 GtkHBox
9224 GtkVSeparator
9225 GtkHSeparator
9226 </verb></tscreen>
9227
9228 Per catturare degli eventi per questo tipo di widget, si deve fare uso 
9229 del widget EventBox. Si veda a questo proposito la sezione su
9230 <ref id="sec_The_EventBox_Widget" name="The EventBox Widget">.
9231
9232 <p>
9233 Per il nostro programma di disegno, vogliamo sapere quando il pulsante del
9234 mouse &egrave; premuto e quando viene mosso, quindi specificheremo
9235 <tt/GDK_POINTER_MOTION_MASK/ e <tt/GDK_BUTTON_PRESS_MASK/. Vogliamo anche
9236 essere informati su quando &egrave; necessario ridisegnare la nostra finestra,
9237 quindi specifichiamo <tt/GDK_EXPOSURE_MASK/. Anche se vogliamo essere
9238 avvertiti con un evento ``Configure'' se la dimensione della nostra finestra
9239 cambia, non &egrave; necessario specificare il flag <tt/GDK_STRUCTURE_MASK/, dal
9240 momento che questo viene specificato automaticamente per tutte le finestre.
9241
9242 <p>
9243 Risulta, conunque, che specificando semplicemente <tt/GDK_POINTER_MOTION_MASK/
9244 si crea un problema. Ci&ograve; infatti fa s&igrave; che il server aggiunga nella coda un
9245 un nuovo evento di movimento ogni volta che l'utente muovoe il mouse. Immaginate
9246 che ci vogliano 0.1 secondi per gestire uno di questi eventi, e che il server
9247 X metta in coda un nuovo evento ogni 0.05 secondi. Rimarremo ben presto indietro
9248 rispetto al disegno dell'utente. Se l'utente disegna per 5 secondi, ci metteremmo
9249 altri 5 secondi prima di finire dopo che l'utente ha rilasciato il pulsante del
9250 mouse! Vorremmo quindi che venga notificato un solo evento di movimento per
9251 ogni evento che processiamo. Il modo per farlo &egrave; di specificare 
9252 <tt/GDK_POINTER_MOTION_HINT_MASK/. 
9253
9254 <p>
9255 Quando specifichiamo <tt/GDK_POINTER_MOTION_HINT_MASK/, il server ci notifica
9256 un evento di movimento la prima volta che il puntatore si muove dopo essere
9257 entrato nella nostra finestra, oppure dopo ogni rilascio di un pulsante del
9258 mouse. Gli altri eventi di movimento verranno soppressi finch&eacute; non richiediamo
9259 esplicitamente la posizione del puntatore con la funzione:
9260
9261 <tscreen><verb>
9262 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
9263                                           gint            *x,
9264                                           gint            *y,
9265                                           GdkModifierType *mask);
9266 </verb></tscreen>
9267
9268 (c'&egrave; anche un'altra funzione, <tt>gtk_widget_get_pointer()</tt>, che ha
9269 un'interfaccia pi&ugrave; semplice, ma che non risulta molto utile dal momento
9270 che restituisce solo la posizione del puntatore, senza dettagli sullo
9271 sato dei pulsanti.)
9272
9273 <p>
9274 Quindi, il codice per assegnare gli eventi per la nostra finestra, avr&agrave; l'aspetto:
9275
9276 <tscreen><verb>
9277   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
9278                       (GtkSignalFunc) expose_event, NULL);
9279   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
9280                       (GtkSignalFunc) configure_event, NULL);
9281   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
9282                       (GtkSignalFunc) motion_notify_event, NULL);
9283   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
9284                       (GtkSignalFunc) button_press_event, NULL);
9285
9286   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
9287                          | GDK_LEAVE_NOTIFY_MASK
9288                          | GDK_BUTTON_PRESS_MASK
9289                          | GDK_POINTER_MOTION_MASK
9290                          | GDK_POINTER_MOTION_HINT_MASK);
9291 </verb></tscreen>
9292
9293 Teniamo per dopo i gestori di  ``expose_event'' e  ``configure_event''. Quelli di
9294 ``motion_notify_event'' e ``button_press_event'' sono piuttosto semplici: 
9295
9296 <tscreen><verb>
9297 static gint
9298 button_press_event (GtkWidget *widget, GdkEventButton *event)
9299 {
9300   if (event->button == 1 &amp;&amp; pixmap != NULL)
9301       draw_brush (widget, event->x, event->y);
9302
9303   return TRUE;
9304 }
9305
9306 static gint
9307 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
9308 {
9309   int x, y;
9310   GdkModifierType state;
9311
9312   if (event->is_hint)
9313     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
9314   else
9315     {
9316       x = event->x;
9317       y = event->y;
9318       state = event->state;
9319     }
9320     
9321   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
9322     draw_brush (widget, x, y);
9323   
9324   return TRUE;
9325 }
9326 </verb></tscreen>
9327
9328 <!-- ----------------------------------------------------------------- -->
9329 <sect1> Il widget Area di Disegno (DrawingArea) e il procedimento per Disegnare
9330
9331 <p>
9332 Vediamo ora il procedimento per disegnare sullo schermo. Il
9333 widget da usare &egrave; l'Area di Disegno (DrawingArea). Essenzialmente si
9334 tratta di una finestra X e nient'altro. E' una tela bianca su cui possimo
9335 disegnare tutto quello che vogliamo. Per crearne una usiamo la chiamata:
9336
9337 <tscreen><verb>
9338 GtkWidget* gtk_drawing_area_new        (void);
9339 </verb></tscreen>
9340
9341 Per specificare una dimensione predefinita, si puo fare:
9342
9343 <tscreen><verb>
9344 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
9345                                         gint                 width,
9346                                         gint                 height);
9347 </verb></tscreen>
9348
9349 Come &egrave; vero per tutti i widget, si pu&ograve; modificare questa dimensione
9350 predefinita, tramite la chamata a <tt>gtk_widget_set_usize()</tt>, e
9351 questa a sua volta pu&ograve; essere modificata dall'utente ridimensionando
9352 manualmente la finestra che contiene l'area di disegno.
9353
9354 <p>
9355 Si deve notare che nel momento in cui creiamo un widget DrawingArea, siamo
9356 <em>completamente</em> responsabili di disegnarne il contenuto. Se ad 
9357 esempio la nostra finestra viene prima nascosta e poi dinuovo portata in
9358 primo piano, otteniamo un evento di ``esposizione'' e doppiamo ridisegnare
9359 ci&ograve; che era stato precedente nascosto.
9360
9361 <p>
9362 Dover ricordare tutto quello che era disegnato sulla finestra in modo da
9363 poterlo ridisegnare successivamente, pu&ograve; essere, come minimo, noioso.
9364 In pi&ugrave;, pu&ograve; essere spiacevole dal punto di vista visivo, se delle porzioni
9365 dello schermo vengono prima cancellate e poi ridisegnate passo per passo.
9366 La soluzione per questo problema &egrave; di usare una <em>pixmap di supporto</em>.
9367 Invece di disegnare direttamente sullo schermo, disegnamo su un'iimagine
9368 conservata nella memoria del server ma che non viene mostrata; quindi, quando
9369 l'immagine cambia o ne vengono mostrate nuove porzioni, copiamo sullo schermo
9370 le parti corrispondenti.
9371
9372 <p>
9373 Per creare una ppixmap fuori dallo schermo, usiamo la funzione:
9374
9375 <tscreen><verb>
9376 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
9377                                          gint        width,
9378                                          gint        height,
9379                                          gint        depth);
9380 </verb></tscreen>
9381
9382 Il parametro <tt>window</tt>specifica una finestra GDK dalla quale questa
9383 pixmap prende alcune delle sue propriet&agrave;. <tt>width</tt> e <tt>height</tt>
9384 specificano le dimensioni della pixmap.  <tt>depth</tt> specifica la 
9385 <em>profondit&agrave; di colore</em>, cio&egrave; il numero di bit per ogni pixel, per
9386 la nuova pixmap. Se alla profondit&agrave; &egrave; assegnato il valore <tt>-1</tt>, questa
9387 verr&agrave; posta identica a quella di <tt>window</tt>.
9388
9389 <p>
9390 Creiamo la pixmap all'interno del gestore di ``configure_event''. Questo evento
9391 &egrave; generato ogni volta che la finestra cambia di dimensione, compreso il
9392 momento in cui viene creata per la prima volta.
9393
9394 <tscreen><verb>
9395 /* Pixmap di supporto per l'area di disegno */
9396 static GdkPixmap *pixmap = NULL;
9397
9398 /* Creare una pixmap della dimensione appropriata */
9399 static gint
9400 configure_event (GtkWidget *widget, GdkEventConfigure *event)
9401 {
9402   if (pixmap)
9403     {
9404       gdk_pixmap_destroy(pixmap);
9405     }
9406   pixmap = gdk_pixmap_new(widget->window,
9407                           widget->allocation.width,
9408                           widget->allocation.height,
9409                           -1);
9410   gdk_draw_rectangle (pixmap,
9411                       widget->style->white_gc,
9412                       TRUE,
9413                       0, 0,
9414                       widget->allocation.width,
9415                       widget->allocation.height);
9416
9417   return TRUE;
9418 }
9419 </verb></tscreen>
9420
9421 La chiamata a <tt>gdk_draw_rectangle()</tt> inizialmente rende bianca l'intera
9422 pixmap. Fra un momento ne riparleremo.
9423
9424 <p>
9425 Il gestore dell'evento ``esposizione'', copia quindi la porzione appropriata
9426 della pixmap sullo schermo (determiniamo qual &egrave; l'area da ridisegnare usando
9427 il campo event->area dell'evento di esposizione):
9428
9429 <tscreen><verb>
9430 /* Ridisegna sullo schermo a partire dalla pixmap di supporto */
9431 static gint
9432 expose_event (GtkWidget *widget, GdkEventExpose *event)
9433 {
9434   gdk_draw_pixmap(widget->window,
9435                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
9436                   pixmap,
9437                   event->area.x, event->area.y,
9438                   event->area.x, event->area.y,
9439                   event->area.width, event->area.height);
9440
9441   return FALSE;
9442 }
9443 </verb></tscreen>
9444
9445 Abbiamo quindi visto come tenete aggiornato lo schermo con la nostra
9446 pixmap, ma come facciamo per disegnare delle cose interessanti sulla
9447 pixmap? Ci sono un bel po' di funzioni nella libreria GDK di GTK che
9448 servono per disegnare su superfici <em>disegnabili</em>. Una superficie
9449 disegnabile &egrave; semplicemente qualcosa su cui si pu&ograve; disegnare un'immagine.
9450 Pu&ograve; essere una finestra, una pixmap o una bitmap (un'immagine in bianco e
9451 nero). Abbiamo gi&agrave; visto sopra due di chiamate,
9452 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. La lista
9453 completa &egrave; la seguente:
9454
9455 <tscreen><verb>
9456 gdk_draw_line ()
9457 gdk_draw_rectangle ()
9458 gdk_draw_arc ()
9459 gdk_draw_polygon ()
9460 gdk_draw_string ()
9461 gdk_draw_text ()
9462 gdk_draw_pixmap ()
9463 gdk_draw_bitmap ()
9464 gdk_draw_image ()
9465 gdk_draw_points ()
9466 gdk_draw_segments ()
9467 </verb></tscreen>
9468
9469 Per ulteriori dettagli su queste funzioni, vedete la documentazione di
9470 riferimento nei file header <tt>&lt;gdk/gdk.h&gt;</tt>.
9471 Tutte queste funzioni hanno i medesimi primi due argomenti. Il primo
9472 &egrave; la superficie disegnabili su cui disegnare, il secondo &egrave; un 
9473 <em>contesto grafico</em> (GC). 
9474
9475 <p>
9476 Un contesto grafico incapsula delle informazioni riguardo a cose come
9477 il colore di sfondo e di primo piano e lo spessore della linea.
9478 GDK ha un ampio insieme di funzioni per crare e modificare contesti grafici,
9479 ma per tenere le cose semplici useremo solo dei contesti grafici predefiniti.
9480 Ogni widget ha uno stile associato (che pu&ograve; essere modificato agendo su un
9481 file gtkrc). Questo, fra le altre cose, contiene un certo numero di contesti
9482 grafici. Alcuni esempi di come accedere a questi contesti grafici sono
9483 i seguenti:
9484
9485 <tscreen><verb>
9486 widget->style->white_gc
9487 widget->style->black_gc
9488 widget->style->fg_gc[GTK_STATE_NORMAL]
9489 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
9490 </verb></tscreen>
9491
9492 I campi <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, e
9493 <tt>light_gc</tt> sono indicizzati tramite un parametri di tipo
9494 <tt>GtkStateType</tt>, che pu&ograve; assumere i valori:
9495
9496 <tscreen><verb>
9497 GTK_STATE_NORMAL,
9498 GTK_STATE_ACTIVE,
9499 GTK_STATE_PRELIGHT,
9500 GTK_STATE_SELECTED,
9501 GTK_STATE_INSENSITIVE
9502 </verb></tscreen>
9503
9504 Per esempio, per  <tt/GTK_STATE_SELECTED/ il colore di sfondo predefinito
9505 &egrave; blu scuro e quello di primo piano bianco.
9506
9507 <p>
9508 La nostra funzione <tt>draw_brush()</tt>, che efettivamente disegna sullo
9509 schermo, diventa quindi:
9510
9511 <tscreen><verb>
9512 /* Disegna un rettangolo sullo schermo */
9513 static void
9514 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
9515 {
9516   GdkRectangle update_rect;
9517
9518   update_rect.x = x - 5;
9519   update_rect.y = y - 5;
9520   update_rect.width = 10;
9521   update_rect.height = 10;
9522   gdk_draw_rectangle (pixmap,
9523                       widget->style->black_gc,
9524                       TRUE,
9525                       update_rect.x, update_rect.y,
9526                       update_rect.width, update_rect.height);
9527   gtk_widget_draw (widget, &amp;update_rect);
9528 }
9529 </verb></tscreen>
9530
9531 Dopo aver disegnato il rettangolo sulla pixmap, chiamiamo la funzione:
9532
9533 <tscreen><verb>
9534 void       gtk_widget_draw                (GtkWidget           *widget,
9535                                            GdkRectangle        *area);
9536 </verb></tscreen>
9537
9538 che notifica a X che l'area data dal parametro <tt>area</tt> deve essere
9539 aggiornata. X poi generer&agrave; un evento di esposizione (che pu&ograve; essere combinato
9540 con le aree passate da diverse chiamate a <tt>gtk_widget_draw()</tt>) che
9541 far&agrave; s&igrave; che il nostro gestore dell'evento di esposizione, copi le porzioni
9542 rilevanti sullo schermo.
9543
9544 <p>
9545 Abbiamo a questo punto creato tutto il programma di disegno, tranne che
9546 per qualche dettaglio irrilevante come la creazione della finestra principale.
9547 Il codice sorgente completo &egrave; reperibile dove avete ottenuto questo tutorial,
9548 oppure da:
9549
9550 <htmlurl url="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial"
9551 name="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial">
9552
9553 <!-- ----------------------------------------------------------------- -->
9554 <sect1> Aggiungere il supporto per XInput
9555
9556 <p>
9557 Al giorno d'oggi &egrave; possibile acquistare dei dispositivi abbastanza a buon
9558 mercato, come tavolette grafice, che permettono di disegnare con una
9559 espressivit&agrave; artistica molto semplificata rispetto ad un mouse.
9560 Il modo pi&ugrave; semplice per usare questi dispositivi &egrave; di sostituirli
9561 semplicemente al mouse, ma in questo modo si perdono molti dei loro
9562 vantaggi, come:
9563
9564 <itemize>
9565 <item> Sensibilit&agrave; alla pressione
9566 <item> Sensibilit&agrave; all'inclinazione
9567 <item> Posizionamento infra-pixel
9568 <item> Ingressi multipli (per esempio, uno stilo che contiene sia una ``matita''
9569 sia una ``gomma'')
9570 </itemize>
9571
9572 Per ulteriori informazioni sulle estensioni XInput, vedere l'<htmlurl
9573 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
9574 name="XInput-HOWTO">.
9575
9576 <p>
9577 Se esaminiamo, per esempio, la definizione completa della struttura
9578 GdkEventMotion, possiamo vedere che contiene dei campi per il supporto
9579 delle informazioni estese dai dispositivi.
9580
9581 <tscreen><verb>
9582 struct _GdkEventMotion
9583 {
9584   GdkEventType type;
9585   GdkWindow *window;
9586   guint32 time;
9587   gdouble x;
9588   gdouble y;
9589   gdouble pressure;
9590   gdouble xtilt;
9591   gdouble ytilt;
9592   guint state;
9593   gint16 is_hint;
9594   GdkInputSource source;
9595   guint32 deviceid;
9596 };
9597 </verb></tscreen>
9598
9599 <tt/pressure/ fornisce la pressione sotto forma di un numero decimale
9600 compreso fra 0 e 1. <tt/xtilt/ e <tt/ytilt/ possono assumere valori
9601 compresi fra -1 e 1, corrispondenti al grado di inclinazione in ciascuna
9602 direzione. <tt/source/ e <tt/deviceid/ specificano il dispositivo per il
9603 quale si &egrave; verificato l'evento in due modi distinti. <tt/source/  da alcune
9604 semplici informazioni sul tipo di dispositivo, e pu&ograve; assumere i valori:
9605
9606 <tscreen><verb>
9607 GDK_SOURCE_MOUSE
9608 GDK_SOURCE_PEN
9609 GDK_SOURCE_ERASER
9610 GDK_SOURCE_CURSOR
9611 </verb></tscreen>
9612
9613 <tt/deviceid/ specifica invece un identificativo numerico univoco per il
9614 dispositivo. Questo pu&ograve; essere a sua volta utilizzato per avere ulteriori
9615 informazioni sul dispositivo tramite la chiamata a <tt/gdk_input_list_devices()/
9616 (vedi sotto). Il valore speciale <tt/GDK_CORE_POINTER/ viene usato per identificare
9617 il dispositivo di puntamento principale (di solito il mouse).
9618
9619 <sect2> Abilitare le informazioni estese
9620
9621 <p>
9622 Per far s&igrave; che GTK sappia che ci interessano le informazioni estese dai
9623 dispositivi, basta aggiungere un'unica linea al nostro programma:
9624
9625 <tscreen><verb>
9626 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
9627 </verb></tscreen>
9628
9629 Dando il valore <tt/GDK_EXTENSION_EVENTS_CURSOR/, diciamo che ci interessano
9630 gli eventi relativi alle estensioni, ma solo se non dobbiamo disegnare da noi
9631 il nostro cursore. Si veda pi&ugrave; sotto alla sezione <ref
9632 id="sec_Further_Sophistications" name="Ulteriori Sofisticazioni"> per ulteriori
9633 informazioni sul modo si disegnare i cursori. Potremmo anche dare i valori
9634 <tt/GDK_EXTENSION_EVENTS_ALL/ se vogliamo disegnare il nostro cursore o
9635 <tt/GDK_EXTENSION_EVENTS_NONE/ se vogliamo tornare alle condizioni predefinite.
9636
9637 <p>
9638 Comunque, non finisce tutto qui. Non ci sono estensioni abilitate per difetto.
9639 Abbiamo bisogno di un meccanismo per permettere agli utenti l'abilitazione e
9640 la configurazione delle estensioni dei loro dispositivi, GTK fornisce il
9641 widget InputDialog per automatizzare questo processo. La seguente procedura
9642 mostra come gestire un widget InputDialog. Crea la finestra di dialogo nel
9643 caso non sia presente, mentre la porta in primo piano in caso contrario.
9644
9645 <tscreen><verb>
9646 void
9647 input_dialog_destroy (GtkWidget *w, gpointer data)
9648 {
9649   *((GtkWidget **)data) = NULL;
9650 }
9651
9652 void
9653 create_input_dialog ()
9654 {
9655   static GtkWidget *inputd = NULL;
9656
9657   if (!inputd)
9658     {
9659       inputd = gtk_input_dialog_new();
9660
9661       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
9662                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
9663       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
9664                                  "clicked",
9665                                  (GtkSignalFunc)gtk_widget_hide,
9666                                  GTK_OBJECT(inputd));
9667       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
9668
9669       gtk_widget_show (inputd);
9670     }
9671   else
9672     {
9673       if (!GTK_WIDGET_MAPPED(inputd))
9674         gtk_widget_show(inputd);
9675       else
9676         gdk_window_raise(inputd->window);
9677     }
9678 }
9679 </verb></tscreen>
9680
9681 (Notate come gestiamo questo dialogo. Con la connessione del segnale
9682 ``destroy'' ci assicuriamo di non tenerci in giro il puntatore al dialogo
9683 dopo che lo abbiamo distrutto, cosa che potrebbe portare ad un errore di
9684 segmentazione.)
9685
9686 <p>
9687 L'InputDialog ha due pulsanti, ``Close'' e ``Save'', i quali non hanno alcuna
9688 azione predefinita assegnata ad essi. Nella funzione precedente, abbiamo
9689 fatto in modo che ``Close'' nasconda la finestra di dialogo, e abbiamo nascosto
9690 il pulsante ``Save'' dal momento che in questo programma non implementiamo il
9691 salvataggio delle opzioni di XInput.
9692
9693 <sect2> Usare le informazioni estese
9694
9695 <p>
9696 Una volta abilitato il dipositivo, possiamo usare le informazioni estese
9697 che si trovano nei corrispondenti campi delle strutture che descrivono gli
9698 eventi. A dire il vero, l'utilizzo di questi campi &egrave; sempre sicuro, perch&eacute;
9699 sono tutti posti per difetto a valori ragionevoli ancje quando la gestione
9700 degli eventi estesi non &egrave; abilitata.
9701
9702 <p>
9703 Un cambiamento che dobbiamo fare &egrave; di chiamare <tt/gdk_input_window_get_pointer()/
9704 invece di <tt/gdk_window_get_pointer/. Ci&ograve; si rende necessario perch&eacute;
9705 <tt/gdk_window_get_pointer/ non restituisce le informazioni esetese.
9706
9707 <tscreen><verb>
9708 void gdk_input_window_get_pointer     (GdkWindow       *window,
9709                                        guint32         deviceid,
9710                                        gdouble         *x,
9711                                        gdouble         *y,
9712                                        gdouble         *pressure,
9713                                        gdouble         *xtilt,
9714                                        gdouble         *ytilt,
9715                                        GdkModifierType *mask);
9716 </verb></tscreen>
9717
9718 Quando chiamiamo questa funzione, dobbiamo specificare l'identificativo
9719 del dispositivo e la finestra. Normalmente questo identificativo lo si
9720 ottiene dal campo <tt/deviceid/ della struttura dell'evento.
9721 Questa funzione restituir&agrave; valori ragionevoli nel caso che la gestione
9722 degli eventi estesi non sia attivata (in questo caso, <tt/event->deviceid/
9723 avr&agrave; il valore <tt/GDK_CORE_POINTER/).
9724
9725 Quindi, la struttura di base dei gestori degli eventi relativi alla
9726 pressione di bottoni e ai movomenti non cambia molto - abbiamo solo
9727 bisogno di aggiungere il codice necessario per tenere conto delle
9728 informazioni estese.
9729
9730 <tscreen><verb>
9731 static gint
9732 button_press_event (GtkWidget *widget, GdkEventButton *event)
9733 {
9734   print_button_press (event->deviceid);
9735   
9736   if (event->button == 1 &amp;&amp; pixmap != NULL)
9737     draw_brush (widget, event->source, event->x, event->y, event->pressure);
9738
9739   return TRUE;
9740 }
9741
9742 static gint
9743 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
9744 {
9745   gdouble x, y;
9746   gdouble pressure;
9747   GdkModifierType state;
9748
9749   if (event->is_hint)
9750     gdk_input_window_get_pointer (event->window, event->deviceid,
9751                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
9752   else
9753     {
9754       x = event->x;
9755       y = event->y;
9756       pressure = event->pressure;
9757       state = event->state;
9758     }
9759     
9760   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
9761     draw_brush (widget, event->source, x, y, pressure);
9762   
9763   return TRUE;
9764 }
9765 </verb></tscreen>
9766
9767 Avremo anche bisogno di fare qualcosa con queste nuove informazioni. La
9768 nostra nuova funzione <tt/draw_brush/ disegna con un colore diverso per
9769 ogni <tt/event->source/ e cambia la dimensione della linea in funzione
9770 della pressione.
9771
9772 <tscreen><verb>
9773 /* Disegna un rettangolo sullo schermo, con la dimensione dipendente
9774    dalla pressione e il colore dipendente dal tipo di dispositivo */
9775 static void
9776 draw_brush (GtkWidget *widget, GdkInputSource source,
9777             gdouble x, gdouble y, gdouble pressure)
9778 {
9779   GdkGC *gc;
9780   GdkRectangle update_rect;
9781
9782   switch (source)
9783     {
9784     case GDK_SOURCE_MOUSE:
9785       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
9786       break;
9787     case GDK_SOURCE_PEN:
9788       gc = widget->style->black_gc;
9789       break;
9790     case GDK_SOURCE_ERASER:
9791       gc = widget->style->white_gc;
9792       break;
9793     default:
9794       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
9795     }
9796
9797   update_rect.x = x - 10 * pressure;
9798   update_rect.y = y - 10 * pressure;
9799   update_rect.width = 20 * pressure;
9800   update_rect.height = 20 * pressure;
9801   gdk_draw_rectangle (pixmap, gc, TRUE,
9802                       update_rect.x, update_rect.y,
9803                       update_rect.width, update_rect.height);
9804   gtk_widget_draw (widget, &amp;update_rect);
9805 }
9806 </verb></tscreen>
9807
9808 <sect2> Trovare ulteriori informazioni su di un dispositivo
9809
9810 <p>
9811 Come esempio del modo di trovare altre informazioni su di un dispositivo,
9812 il nostro programma stamper&agrave; il nome di ogni dispositivo che genera un
9813 evento di pressione di un pulsante. Per avere il nome di un dispositivo,
9814 chiamiamo la funzione
9815
9816 <tscreen><verb>
9817 GList *gdk_input_list_devices               (void);
9818 </verb></tscreen>
9819
9820 che restituisce una GList (un tipo di lista collegata che si trova nella
9821 libreria glib) di strutture di tipo GdkDeviceInfo. La definizione di
9822 GdkDeviceInfo &egrave; la seguente:
9823
9824 <tscreen><verb>
9825 struct _GdkDeviceInfo
9826 {
9827   guint32 deviceid;
9828   gchar *name;
9829   GdkInputSource source;
9830   GdkInputMode mode;
9831   gint has_cursor;
9832   gint num_axes;
9833   GdkAxisUse *axes;
9834   gint num_keys;
9835   GdkDeviceKey *keys;
9836 };
9837 </verb></tscreen>
9838
9839 La maggior parte di questi campi rappresentano informazioni di configurazione
9840 che potete ignorare a meno che non implementiate il salvataggio della
9841 configurazione di un XInput. Quelle che ci interessano sono <tt/name/, che
9842 &egrave; semplicemente il nome che X assegna al dispositivo, e <tt/has_cursor/. Anche
9843 <tt/has_cursor/ non &egrave; informazione di configurazione, e indica, nel caso
9844 abbia valore ``falso'', che dobbiamo disegnare da soli il nostro cursore. Ma
9845 dal momento che abbiamo specificato <tt/GDK_EXTENSION_EVENTS_CURSOR/,
9846 possiamo anche non preoccuparcene.
9847
9848 <p>
9849
9850 La nostra funzione <tt/print_button_press()/ scorre semplicemente la lista
9851 che &egrave; stata restituita finch&eacute; non trova il valore corretto, e poi stampa
9852 il nome del dispositivo.
9853
9854 <tscreen><verb>
9855 static void
9856 print_button_press (guint32 deviceid)
9857 {
9858   GList *tmp_list;
9859
9860   /* gdk_input_list_devices restituisce una lista interna, cos&igrave; poi
9861      non dobbiamo liberarla */
9862   tmp_list = gdk_input_list_devices();
9863
9864   while (tmp_list)
9865     {
9866       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
9867
9868       if (info->deviceid == deviceid)
9869         {
9870           printf("Button press on device '%s'\n", info->name);
9871           return;
9872         }
9873
9874       tmp_list = tmp_list->next;
9875     }
9876 }
9877 </verb></tscreen>
9878 Questo completa i cambiamenti necessari per usare gli XInput nel nostro
9879 programma. Come per la prima versione, i sorgenti completi sono prelevabili
9880 da dove avete prelevato questo tutorial, oppure da:
9881
9882 <htmlurl url="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial"
9883 name="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial">
9884
9885 <sect2> Ulteriori sofisticazioni <label id="sec_Further_Sophistications">
9886
9887 <p>
9888 Anche se ora il nostro programma supporta XInput pittosto bene, gli mancano
9889 alcune caratteristiche che probabilmente vorremmo mettere in una applicazione
9890 completa. In primo luogo, probabilmente all'utente non far&agrave; piacere dover
9891 configurare i propri dispositivi ogni volta che lanciano il programma, per
9892 cui dovremmo dare la possibilit&agrave; di salvare la configurazione dei dispositivi.
9893 Ci&ograve; pu&ograve; essere fatto scorrendo la lista restituita da <tt/gdk_input_list_devices()/
9894 e scrivendo la configurazione su di un file.
9895
9896 <p>
9897 Per tornare allo stato salvato la prossima volta che il programma viene
9898 eseguito, GDK mette a disposizione delle funzioni per cambiare la configurazione
9899 dei dispositivi:
9900
9901 <tscreen><verb>
9902 gdk_input_set_extension_events()
9903 gdk_input_set_source()
9904 gdk_input_set_mode()
9905 gdk_input_set_axes()
9906 gdk_input_set_key()
9907 </verb></tscreen>
9908
9909 (La lista restituita da <tt/gdk_input_list_devices()/ non dovrebbe
9910 essere modificata direttamente.) Un esempio di come fare pu&ograve; essere
9911 trovato nel programma di disegno gsumi (disponibile da <htmlurl
9912 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
9913 name="http://www.msc.cornell.edu/~otaylor/gsumi/">). Sarebbe bello
9914 avere alla fine un modo standard di recuperare le informazioni per tutte
9915 le applicazioni. Questo probabilmente appartiene ad un livello un po'
9916 pi&ugrave; elevato ripetto a GTK, forse alla libreria GNOME.
9917
9918 <p>
9919 Un'altra notevole omissione a cui abbiamo accennato precedentemente &egrave; il
9920 fatto di non disegnare il cursore direttamente. Piattaforme diverse da
9921 XFree86 non permettono in questo momento di usare contemporaneamente un
9922 dispositivo sia come puntatore principale sia direttamente da una
9923 applicazione. Vedere  <url url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
9924 name="XInput-HOWTO"> per ulteriori informazioni. Ci&ograve; significa che le
9925 applicazioni che vogliono rivolgersi al pubblico pi&ugrave; ampio dovranno prevedere
9926 di disegnare esse stesse il proprio cursore.
9927
9928 <p>
9929 Un'applicazione che voglia disegnare il proprio cursore dovr&agrave; fare due cose:
9930 determinare se il dispositivo corrente necessita che venga disegnato un
9931 cursore, e determinare se il dispositivo corrente &egrave; in prossimit&agrave;. (Se il
9932 dispositivo &egrave; una tavoletta grafica, un tocco di finezza &egrave; fare sparire
9933 il puntatore quando lo stilo viene sollevato dalla tavoletta. Quando c'&egrave;
9934 contatto fra lo stilo e la tavoletta, si dice che il dispositivo &egrave; ``in
9935 prossimit&agrave;".) La prima cosa viene fatta scorrendo la lista dei dispositivi,
9936 come abbiamo fatto per trovare il nome del dispositivo. La seconda cosa
9937 viene ottenuta selezionando gli eventi ``proximity_out''. Un esempio di
9938 disegno del proprio cursore si trova nel programma 'testinput' incluso nella
9939 distribuzione di GTK.
9940
9941 <!-- ***************************************************************** -->
9942 <sect>Consigli per scrivere Applicazioni GTK
9943 <!-- ***************************************************************** -->
9944
9945 <p>
9946
9947 Questa sezione &egrave; semplicemente una raccolta di saggezza, una
9948 guida di stile e un aiuto per creare buone applicazioni GTK. E' totalmente
9949 inutile per ora perch&eacute; &egrave; solamente un appunto.
9950
9951 Usa autoconf e automake! Sono tuoi amici :) Ho intenzione di fare una
9952 piccola introduzione su di loro qui.
9953
9954 <!-- ***************************************************************** -->
9955 <sect>Contributi
9956 <!-- ***************************************************************** -->
9957
9958 <p>
9959 Questo documento, come molti altri grandi software l&agrave; fuori, &egrave; stato 
9960 creato da volontari. Se sai tutto quello che c'&egrave; da sapere su GTK e non
9961 lo hai trovato qui allora considera la possibilit&agrave; di contribuire a questo
9962 documento.
9963
9964 <p>
9965 Se decidi di contribuire, ti prego di trasmettere il tuo lavoro a Tony Gale, 
9966 <tt><htmlurl url="mailto:gale@gtk.org"
9967 name="gale@gtk.org"></tt>. Inoltre, ricorda  che l'intero documento &egrave;
9968 ``free'', e che ogni tua aggiunta sar&agrave; considerata allo stesso modo.
9969 Per questo motivo le persone possono usare porzioni dei tuoi esempi nei loro
9970 programmi, copie di questo documento possono essere distribuite all'infinito,
9971 ecc...
9972 <p>
9973
9974 Grazie.
9975
9976 <!-- ***************************************************************** -->
9977 <sect>Credits
9978 <!-- ***************************************************************** -->
9979 <p>
9980 Voglio qui ringraziare le persone che seguono, per il loro contributo
9981 alla stesura di questo testo.
9982
9983 <itemize>
9984 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
9985 name="chamele0n@geocities.com"></tt> per il tutorial sui men&ugrave;.
9986
9987 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
9988                          name="raph@acm.org"></tt>
9989 per il "hello world" alla GTK, l'immpacchettamento del widget, e in generale
9990 per tutta la sua saggezza.
9991 Lui ha anche donato una casa per questo tutorial.
9992
9993 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
9994 name="petm@xcf.berkeley.edu"></tt> Per il pi&ugrave; semplice programma GTK e l'abilit&agrave;
9995 di farlo. :)
9996
9997 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
9998 name="werner.koch@guug.de"></tt> per la conversione da testo semplice a SGML
9999 e la gerarchia delle classi di widget.
10000
10001 <item>Mark Crichton <tt><htmlurl url="mailto:crichton@expert.cc.purdue.edu"
10002 name="crichton@expert.cc.purdue.edu"></tt> per il codice della "MenuFactory"
10003 e per la parte sull'impacchettamento nelle tabelle del tutorial.
10004
10005 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
10006 name="mailto:owt1@cornell.edu"></tt> per la sezione del  widget EventBox
10007 (e il patch alla distribuzione). Lui &egrave; anche responsabile per il codice
10008 e il tutorial delle selezioni, come per la sezione sulla scrittura di un 
10009 proprio widget, e l'applicazione d'esempio. Grazie di tutto Owen.
10010
10011 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
10012 name="mailto:mailto:mvboom42@calvin.edu"></tt> per il suo meraviglioso lavoro
10013 sul Notebook, Progres Bar, Dialogs e File selection. Grazie molto Mark. Sei
10014 stato di grande aiuto.
10015
10016 <item>Tim Janik <tt><htmlurl url="mailto:timj@psynet.net"
10017 name="mailto:timj@psynet.net"></tt> per il suo grande lavoro sul widget List.
10018 Grazie Tim :)
10019
10020 <item> Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
10021 name="johnsonm@redhat.com"> </tt> per le informazioni e il codice dei menu
10022 a comparsa.
10023
10024 </itemize>
10025 <p>
10026 E a tutti voi che avete fatto commenti e avete aiutato a raffinare questo documento.
10027 <p>
10028
10029 Thanks.
10030
10031 <!-- ***************************************************************** -->
10032 <sect> Dichiarazione di Copyright e Licenza
10033 <!-- ***************************************************************** -->
10034 <p>
10035 A questa traduzione, Copyright (c) 1997-1998 di Michel Morelli,
10036 Daniele Canazza e Antonio Schifano, si applica la medesime licenza
10037 prevista dal lavoro originale di Ian Main e Tony Gale. Segue la traduzione
10038 di quelle disposizioni e la loro versione originale. In caso di discordanze
10039 fra traduzione e versione originale, fa fede quest'ultima.
10040 <p>
10041 Il GTK Tutorial &egrave; Copyright (c) 1997 Ian Main.
10042
10043 Copyright (c) 1998 Tony Gale.
10044 <p>
10045 E' permesso fare e distribuire copie non modificate di questo manuale,
10046 sotto la condizione che  la dichiarazione di copyright e queste disposizioni
10047 siano riportate su tutte le copie.
10048 <p>E' permesso fare e distribuire copie di versioni modificate di questo
10049 documento, sotto le stesse condizioni previste per la copia non modificata,
10050 e che questa dichiarazione di copyright sia inclusa esattamente come
10051 nell'originale, e che l'intero lavoro risultante sia distribuito sotto
10052 i termini di una licenza identica a questa.
10053 <p>E' permesso fare e distribuire copie di traduzioni di questo documento in
10054 altre lingue, sotto le stesse condizioni previste per le versioni modificate.
10055 <p>Nel caso si intenda includere questo documento in un lavoro pubblicato,
10056 si prega di contattarne il curatore, che cercher&agrave; di mettere a
10057 disposizione le informazioni pi&ugrave; aggiornate.
10058 <p>Non c'&egrave; garanzia che questo documento sia rispondente ai propri
10059 propositi. Esso viene semplicemente fornito come una risorsa "free" (libera e
10060 gratuita). In quanto tale, gli autori e i curatori delle informazioni contenute
10061 in esso, non possono dare alcuna garanzia nemmeno sul fatto che tali informazioni
10062 siano accurate.
10063
10064 <p>---------------------
10065 <p>
10066 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
10067
10068 Copyright (C) 1998 Tony Gale.
10069 <p>
10070 Permission is granted to make and distribute verbatim copies of this 
10071 manual provided the copyright notice and this permission notice are 
10072 preserved on all copies.
10073 <P>Permission is granted to copy and distribute modified versions of 
10074 this document under the conditions for verbatim copying, provided that 
10075 this copyright notice is included exactly as in the original,
10076 and that the entire resulting derived work is distributed under 
10077 the terms of a permission notice identical to this one.
10078 <P>Permission is granted to copy and distribute translations of this 
10079 document into another language, under the above conditions for modified 
10080 versions.
10081 <P>If you are intending to incorporate this document into a published 
10082 work, please contact the maintainer, and we will make an effort 
10083 to ensure that you have the most up to date information available.
10084 <P>There is no guarentee that this document lives up to its intended
10085 purpose.  This is simply provided as a free resource.  As such,
10086 the authors and maintainers of the information provided within can
10087 not make any guarentee that the information is even accurate.
10088
10089 </article>
10090