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 >> |