| Programación en el entorno GNOME |
|---|
Este objeto, MyItem, deriva de GnomeCanvasShape. Sólo implementa el método update, y deja todos los demás a GnomeCanvasShape.
Además, en el ejemplo se usa un widget GtkScale para poder cambiar el zoom del canvas.
Ejemplo 13. MyItem
#include <gnome.h>
/*
* Definición de MyItem
*/
typedef struct _MyItem MyItem;
typedef struct _MyItemClass MyItemClass;
struct _MyItem {
GnomeCanvasShape shape;
gdouble x0;
gdouble y0;
gdouble x1;
gdouble y1;
};
struct _MyItemClass {
GnomeCanvasShapeClass parent_class;
};
#define MY_ITEM_TYPE (my_item_get_type())
#define MY_ITEM(obj) (GTK_CHECK_CAST ((obj), MY_ITEM_TYPE, MyItem))
/*
* "update" para calcular la ruta que se enviará a GnomeCanvasShape
*/
void my_item_update (GnomeCanvasItem *item, gdouble *affine,
ArtSVP *clip_path, gint flags);
/*
* Guardar la dirección de la clase padre de MyItem para llamar a su update
*/
static GnomeCanvasItemClass *my_item_parent_class;
/*
* Inicializar el objeto. Ésta es llamada cada vez que se crea un objeto
*/
void
my_item_init(MyItem* item)
{
item->x0 = 100.0;
item->y0 = 100.0;
item->x1 = 200.0;
item->y1 = 200.0;
}
/*
* Inicializar la clase. Ésta es llamada sólo una vez, cuando se crea el primer
* objeto y se crea la clase
*/
void
my_item_class_init(MyItemClass* class)
{
GnomeCanvasItemClass *item_class;
item_class = (GnomeCanvasItemClass *) class;
item_class->update = my_item_update;
my_item_parent_class = g_type_class_peek_parent (class);
}
/*
* Usada para crear la clase y poder enviar un GType a gnome_canvas_item_new
*/
GType
my_item_get_type ()
{
static GType item_type = 0;
if(item_type == 0)
{
static const GTypeInfo object_info = {
sizeof (MyItemClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) my_item_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof (MyItem),
0,
(GInstanceInitFunc) my_item_init,
NULL
};
item_type = g_type_register_static (GNOME_TYPE_CANVAS_SHAPE,
"MyItem", &object_info, 0);
}
return item_type;
}
void my_item_update (GnomeCanvasItem *item, gdouble *affine,
ArtSVP *clip_path, gint flags)
{
GnomeCanvasPathDef* path_def;
MyItem* my_item;
gdouble cx, cy;
/*
* crear una nueva ruta
*/
path_def = gnome_canvas_path_def_new();
my_item = MY_ITEM(item);
cx = (my_item->x1 - my_item->x0) * 0.25;
cy = (my_item->y1 - my_item->y0) * 0.25;
gnome_canvas_path_def_moveto(path_def, my_item->x0, my_item->y0);
gnome_canvas_path_def_lineto(path_def, my_item->x0 + cx, my_item->y0 - cy );
gnome_canvas_path_def_lineto(path_def, my_item->x1, my_item->y1);
gnome_canvas_path_def_lineto(path_def, my_item->x1 - cx, my_item->y1 + cy);
gnome_canvas_path_def_lineto(path_def, my_item->x0, my_item->y0);
/* mandar la ruta a GnomeCanvasShape */
gnome_canvas_path_def_closepath(path_def);
gnome_canvas_shape_set_path_def (GNOME_CANVAS_SHAPE (item), path_def);
gnome_canvas_path_def_unref(path_def);
if (my_item_parent_class->update)
(* my_item_parent_class->update)(item, affine, clip_path, flags);
}
gboolean
button_press_event(GtkWidget* canvas, GdkEventButton* event, MyItem* item)
{
gdouble x, y;
gnome_canvas_window_to_world(GNOME_CANVAS_ITEM(item)->canvas, event->x, event->y, &x, &y);
switch(event->button)
{
case 1: /* botón izquierdo */
item->x0 = x;
item->y0 = y;
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(item));
break;
case 3: /* botón derecho */
item->x1 = x;
item->y1 = y;
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(item));
break;
default:
break;
}
/*
* Devolver TRUE finaliza la propagación del evento.
* FALSE lo sigue propagando
*/
return FALSE;
}
void
on_zoom_changed(GtkAdjustment* adjs, GnomeCanvas* canvas)
{
gnome_canvas_set_pixels_per_unit(canvas, adjs->value);
}
int
main(int argc, char** argv)
{
GtkWidget *window;
GtkWidget *canvas;
GtkWidget *scroll_window;
GtkWidget *vbox;
GtkWidget *scrool_zoom;
GnomeCanvasGroup *root;
GnomeCanvasItem* item;
GtkAdjustment *adjustment;
/* inicializamos las librerías */
gnome_init("my_item", "0.1", argc, argv);
/* crear una ventana que contenga al canvas */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window), "destroy", gtk_main_quit, 0);
vbox = gtk_vbox_new(FALSE, 1);
gtk_container_add(GTK_CONTAINER(window), vbox);
/* Usar una barra de desplazamiento para el zoom */
adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(1.0, 0.25, 4.0, 0.1, 0.5, 1.0));
scrool_zoom = gtk_hscale_new(adjustment);
gtk_scale_set_draw_value(GTK_SCALE(scrool_zoom), TRUE);
gtk_box_pack_start(GTK_BOX(vbox), scrool_zoom, FALSE, TRUE, 1);
/* Usar GtkScrolledWindow para disponer de barras de desplazamiento
* en el canvas */
scroll_window = gtk_scrolled_window_new(NULL, NULL);
gtk_box_pack_end(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 1);
/* canvas en modo RGB */
canvas = gnome_canvas_new_aa();
gtk_container_add(GTK_CONTAINER(scroll_window), canvas);
gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), 0, 0, 1000, 1000);
root = gnome_canvas_root(GNOME_CANVAS(canvas));
/* poner un círculo, con fondo verde y borde azul */
item = gnome_canvas_item_new(root,
my_item_get_type(),
"fill_color", "blue",
"outline_color", "black",
"width_units", 2.0,
NULL);
/* recibir los eventos de pulsación con el ratón para cambiar el item y la señal
* de cambio de valor para el zoom*/
g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(button_press_event), item);
g_signal_connect(G_OBJECT(adjustment), "value_changed", G_CALLBACK(on_zoom_changed), canvas);
/* mostrar los widgets creados y entrar en el bucle gtk_main */
gtk_widget_show_all(window);
gtk_main();
return 0;
}
| << Crear objetos propios | CORBA >> |