Questa sezione descrive i metodi rimanenti per GnomeCanvasItem, inclusi event, point, bounds, realize, unrealize, map e unmap.
La classe GnomeCanvasItem fornisce uno spazio
nella sua vtable chiamato event. Questa
è l'unica funzione della classe di GnomeCanvasItem associata a un segnale. Nessuno
degli oggetti canvas predefiniti implementa un gestore di default per event ma, ovviamente, il vostro oggetto canvas personalizzato può farlo.
Il valore restituito da event è pressoché identico al segnale "event" del GtkWidget. Se l'ultimo gestore del segnale restituisce un valore uguale a FALSE, l'evento viene allora propagato agli oggetti genitori (emettendo il segnale event sul padre), se invece è uguale a TRUE la propagazione termina.
Il metodo point viene utilizzato per determinare quale oggetto canvas è posizionato in un determinato punto. Il canvas utilizza queste informazioni per decidere quale oggetto deve/può ricevere eventi. Il metodo point calcola la distanza da un punto all'oggetto sul canvas. Gli oggetti devono riportare correttamente un distanza uguale a zero se il punto si trova sull'oggetto, oppure non riceveranno eventi. Devono inoltre riportare un valore diverso da zero se il punto non si trova sull'oggetto stesso, oppure riceveranno troppi eventi. Il valore esatto restituito non è importante quando la distizione zero/diverso da zero.
Per pura convenienza, il metodo point riceve uno stesso punto con coordinate pre-convertite in entrambi i sistemi canvas e ad oggetto.
Il metodo point inoltre riceve un puntatore a GnomeCanvasItem. Oggetti del canvas che non sono raggruppati devono conservare il puntatore a loro stessi in questo spazio. I gruppi gestiscono il *actual_item ricevuto dal figlio che restituisce un valore uguale a zero per il suo metodo point.
Ecco l'implementazione del metodo point per GnomeCanvasRect:
|
static double
gnome_canvas_rect_point (GnomeCanvasItem *item,
double x, double y, int cx, int cy,
GnomeCanvasItem **actual_item)
{
GnomeCanvasRE *re;
double x1, y1, x2, y2;
double hwidth;
double dx, dy;
double tmp;
re = GNOME_CANVAS_RE (item);
*actual_item = item;
/* Trova gli estremi del rettangolo piú lo spessore del bordo */
x1 = re->x1;
y1 = re->y1;
x2 = re->x2;
y2 = re->y2;
if (re->outline_set) {
if (re->width_pixels)
hwidth = (re->width / item->canvas->pixels_per_unit) / 2.0;
else
hwidth = re->width / 2.0;
x1 -= hwidth;
y1 -= hwidth;
x2 += hwidth;
y2 += hwidth;
} else
hwidth = 0.0;
/* Il punto si trova all'interno del rettangolo ? */
if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
if (re->fill_set || !re->outline_set)
return 0.0;
dx = x - x1;
tmp = x2 - x;
if (tmp < dx)
dx = tmp;
dy = y - y1;
tmp = y2 - y;
if (tmp < dy)
dy = tmp;
if (dy < dx)
dx = dy;
dx -= 2.0 * hwidth;
if (dx < 0.0)
return 0.0;
else
return dx;
}
/* Il punto si trova all'esterno del rettangolo */
if (x < x1)
dx = x1 - x;
else if (x > x2)
dx = x - x2;
else
dx = 0.0;
if (y < y1)
dy = y1 - y;
else if (y > y2)
dy = y - y2;
else
dy = 0.0;
return sqrt (dx * dx + dy * dy);
}
|
Dovrebbe essere ovvio il funzionamento di questa funzione. È pura, semplice geometria. Notare la linea:
Se il vostro oggetto non riceve eventi, assicuratevi di aver incluso una istruzione simile.
Il metodo bounds calcola approsimando gli estremi del contenitore di un oggetto canvas. In Gnome 1.0, questo metodo viene utilizzando esclusivamente all'interno della funzione gnome_canvas_item_get_bounds(), una funzione pubblica per restituire i valori degli estrami dell'oggetto canvas. Il canvas non utilizza internamente questa funzione, ed è possibile lavorare senza implementarla, come fanno attualmente tutti gli oggetti predefiniti.
La funzione deve restituire le coordinate degli estremi del contenitore dell'oggetto. Ecco la versione per GnomeCanvasRE:
|
static void
gnome_canvas_re_bounds (GnomeCanvasItem *item,
double *x1, double *y1,
double *x2, double *y2)
{
GnomeCanvasRE *re;
double hwidth;
re = GNOME_CANVAS_RE (item);
if (re->width_pixels)
hwidth = (re->width / item->canvas->pixels_per_unit) / 2.0;
else
hwidth = re->width / 2.0;
*x1 = re->x1 - hwidth;
*y1 = re->y1 - hwidth;
*x2 = re->x2 + hwidth;
*y2 = re->y2 + hwidth;
}
|
Gli oggetti del canvas vengono realizzati e mappati esattamente come i widget. Questi metodi giocano lo stesso ruolo delle funzioni equivalenti per i widget. Realizzare un oggetto del canvas comporta l'allocamento delle risorse del GDK richieste dall'oggetto. Mappare un oggetto del canvas significa mostrarne la propria GdkWindow. Pochissimi oggetti del canvas hanno una propria GdkWindow (GnomeCanvasWidget è appunto l'eccezione più grande), di conseguenza la maggior parte degli oggetti non implementano metodi di mapping. GnomeCanvasRect non le implementa, ad ogni modo fornisce i metodi di realizzazione.
Ecco il codice:
|
static void
gnome_canvas_re_realize (GnomeCanvasItem *item)
{
GnomeCanvasRE *re;
re = GNOME_CANVAS_RE (item);
if (re_parent_class->realize)
(* re_parent_class->realize) (item);
if (!item->canvas->aa) {
re->fill_gc = gdk_gc_new (item->canvas->layout.bin_window);
re->outline_gc = gdk_gc_new (item->canvas->layout.bin_window);
}
}
|
L'inverso:
|
static void
gnome_canvas_re_unrealize (GnomeCanvasItem *item)
{
GnomeCanvasRE *re;
re = GNOME_CANVAS_RE (item);
if (!item->canvas->aa) {
gdk_gc_unref (re->fill_gc);
gdk_gc_unref (re->outline_gc);
}
if (re_parent_class->unrealize)
(* re_parent_class->unrealize) (item);
}
|
Notare che questi due metodi non hanno niente a che fare con la modalità antialiased, dato che in quest'ultima non esistono risorse GDK di cui preoccuparsi.
Ovviamente, qualunque sottoclasse dell'oggetto del canvas deve implementare il tipico metodo per GtkObject, incluso destroy se l'oggetto alloca risorse che dovranno essere liberate, e una coppia get_arg/set_arg se l'oggetto denifisce degli argomenti.