From 79c6e0166164555e918e32e758aa048a078edc50 Mon Sep 17 00:00:00 2001 From: Andrea Zagli Date: Sat, 18 Jul 2009 18:56:55 +0200 Subject: [PATCH] Implementd zoom. Implementd pan. Added GtkGis::get_layer_by_name. Fixed some bugs. --- .gitignore | 1 + src/gtkgis.c | 349 ++++++++++++++++++++++++++++++++++++++++------- src/gtkgis.h | 11 +- tests/from_xml.c | 7 + 4 files changed, 311 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index b6d27c4..d5a5551 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ install-sh libgtkgis.pc libtool ltmain.sh +test_saved.gtkgis m4/ missing src/.deps/ diff --git a/src/gtkgis.c b/src/gtkgis.c index 5475307..ac2db1d 100644 --- a/src/gtkgis.c +++ b/src/gtkgis.c @@ -40,9 +40,6 @@ static void gtk_gis_destroy (GtkObject *object); static void gtk_gis_add (GtkContainer *container, GtkWidget *widget); -static gboolean gtk_gis_focus (GtkWidget*widget, - GtkDirectionType direction); - static void gtk_gis_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, @@ -57,13 +54,25 @@ static void gtk_gis_get_property (GObject *object, GValue *value, GParamSpec *pspec); -static gboolean gtk_gis_scroll_event (GtkWidget *widget, - GdkEventScroll *event); - +static void gtk_gis_realize (GtkWidget *widget); +static void gtk_gis_unrealize (GtkWidget *widget); +static void gtk_gis_map (GtkWidget *widget); static void gtk_gis_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_gis_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static gboolean gtk_gis_focus (GtkWidget*widget, + GtkDirectionType direction); +static gboolean gtk_gis_button_press_event (GtkWidget *widget, + GdkEventButton *event); +static gboolean gtk_gis_button_release_event (GtkWidget *widget, + GdkEventButton *event); +static gboolean gtk_gis_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event); +static gboolean gtk_gis_scroll_event (GtkWidget *widget, + GdkEventScroll *event); + +static void gtk_gis_canvas_resize (GtkGis *gtkgis); #define GTK_GIS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_GTK_GIS, GtkGisPrivate)) @@ -71,6 +80,8 @@ static void gtk_gis_size_allocate (GtkWidget *widget, typedef struct _GtkGisPrivate GtkGisPrivate; struct _GtkGisPrivate { + GdkWindow *event_window; + GtkWidget *scroll_win; GtkWidget *canvas; @@ -81,6 +92,8 @@ struct _GtkGisPrivate GtkGisLayerExtent *extent; GtkGisScale *scale; + + GtkGisPoint *sel_start; }; G_DEFINE_TYPE (GtkGis, gtk_gis, GTK_TYPE_BIN) @@ -100,10 +113,16 @@ gtk_gis_class_init (GtkGisClass *klass) object_class->destroy = gtk_gis_destroy; - widget_class->scroll_event = gtk_gis_scroll_event; + widget_class->realize = gtk_gis_realize; + widget_class->unrealize = gtk_gis_unrealize; + widget_class->map = gtk_gis_map; widget_class->size_request = gtk_gis_size_request; widget_class->size_allocate = gtk_gis_size_allocate; widget_class->focus = gtk_gis_focus; + widget_class->button_press_event = gtk_gis_button_press_event; + widget_class->button_release_event = gtk_gis_button_release_event; + widget_class->motion_notify_event = gtk_gis_motion_notify_event; + widget_class->scroll_event = gtk_gis_scroll_event; container_class->add = gtk_gis_add; container_class->forall = gtk_gis_forall; @@ -114,24 +133,15 @@ gtk_gis_init (GtkGis *gtk_gis) { GtkGisPrivate *priv = GTK_GIS_GET_PRIVATE (gtk_gis); - GTK_WIDGET_SET_FLAGS (gtk_gis, GTK_NO_WINDOW | GTK_CAN_FOCUS); + GTK_WIDGET_SET_FLAGS (gtk_gis, GTK_CAN_FOCUS); + GTK_WIDGET_UNSET_FLAGS (gtk_gis, GTK_NO_WINDOW); - gtk_widget_set_events (GTK_WIDGET (gtk_gis), - GDK_BUTTON_PRESS_MASK - | gtk_widget_get_events (GTK_WIDGET (gtk_gis))); - - //g_signal_connect (G_OBJECT (gtk_gis), "scroll-event", G_CALLBACK (gtk_gis_scroll_event), (gpointer)NULL); - - priv->scroll_win = gtk_scrolled_window_new (NULL, NULL); + priv->scroll_win = gtk_layout_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (gtk_gis), priv->scroll_win); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll_win), - GTK_POLICY_NEVER, - GTK_POLICY_NEVER); - priv->canvas = goo_canvas_new (); - gtk_container_add (GTK_CONTAINER (priv->scroll_win), priv->canvas); - + gtk_layout_put (GTK_LAYOUT (priv->scroll_win), priv->canvas, 0, 0); + priv->canvas_root = goo_canvas_get_root_item (GOO_CANVAS (priv->canvas)); priv->layers_groups = NULL; @@ -143,6 +153,8 @@ gtk_gis_init (GtkGis *gtk_gis) priv->scale->x = 1.0; priv->scale->y = 1.0; priv->scale->xy = 1.0; + + priv->sel_start = NULL; } /** @@ -280,16 +292,18 @@ GtkWidget /** * gtk_gis_new_from_file: - * @filename: + * @file_name: * * Returns: the newly created #GtkGis object. */ GtkWidget -*gtk_gis_new_from_file (const gchar *filename) +*gtk_gis_new_from_file (const gchar *file_name) { GtkWidget *gtkgis = NULL; - gchar *path = g_strdup (filename); + g_return_val_if_fail (file_name != NULL, NULL); + + gchar *path = g_strdup (file_name); if (!g_path_is_absolute (path)) { @@ -324,6 +338,8 @@ xmlDoc GtkGisPrivate *priv; + g_return_val_if_fail (IS_GTK_GIS (gtkgis), NULL); + priv = GTK_GIS_GET_PRIVATE (gtkgis); xdoc = xmlNewDoc ("1.0"); @@ -350,20 +366,20 @@ xmlDoc /** * gtk_gis_save_to_xml: * @gtkgis: - * @filename: + * @file_name: */ void -*gtk_gis_save_to_xml (GtkGis *gtkgis, const gchar *filename) +*gtk_gis_save_to_xml (GtkGis *gtkgis, const gchar *file_name) { xmlDoc *xdoc; - g_return_if_fail (filename != NULL); + g_return_if_fail (file_name != NULL); xdoc = gtk_gis_get_xml (gtkgis); if (xdoc != NULL) { - xmlSaveFormatFile (filename, xdoc, 2); + xmlSaveFormatFile (file_name, xdoc, 2); } } @@ -436,6 +452,38 @@ gtk_gis_remove_layer (GtkGis *gtkgis, GtkGisLayer *layer) priv->layers = g_slist_remove (priv->layers, layer); } +/** + * gtk_gis_get_layer_by_name: + * @gtkgis: + * @layer_name: + * + */ +GtkGisLayer +*gtk_gis_get_layer_by_name (GtkGis *gtkgis, + const gchar *layer_name) +{ + GtkGisLayer *layer = NULL; + GtkGisLayer *layer_tmp; + GSList *cur; + + GtkGisPrivate *priv = GTK_GIS_GET_PRIVATE (gtkgis); + + cur = priv->layers; + while (cur != NULL) + { + layer_tmp = (GtkGisLayer *)cur->data; + if (g_strcmp0 (layer_name, gtk_gis_layer_get_name (layer_tmp)) == 0) + { + layer = layer_tmp; + break; + } + + cur = g_slist_next (cur); + } + + return layer; +} + /** * gtk_gis_draw: * @gtkgis: @@ -448,6 +496,8 @@ gtk_gis_draw (GtkGis *gtkgis) GSList *cur; GtkGisLayerSource *layer_source; + g_return_if_fail (IS_GTK_GIS (gtkgis)); + priv = GTK_GIS_GET_PRIVATE (gtkgis); cur = priv->layers; @@ -460,6 +510,8 @@ gtk_gis_draw (GtkGis *gtkgis) cur = g_slist_next (cur); } + + gtk_gis_canvas_resize (gtkgis); } /** @@ -507,6 +559,8 @@ gtk_gis_set_scale (GtkGis *gtkgis, GtkGisScale *scale) "scale-x", priv->scale->x, "scale-y", priv->scale->y, NULL); + + gtk_gis_canvas_resize (gtkgis); } /** @@ -526,6 +580,8 @@ gtk_gis_zoom_to_max (GtkGis *gtkgis) gdouble widget_width; gdouble widget_height; + g_return_if_fail (IS_GTK_GIS (gtkgis)); + priv = GTK_GIS_GET_PRIVATE (gtkgis); widget_width = GTK_WIDGET (gtkgis)->allocation.width; @@ -685,39 +741,83 @@ gtk_gis_get_property (GObject *object, guint property_id, GValue *value, GParamS } } -static gboolean -gtk_gis_scroll_event (GtkWidget *widget, - GdkEventScroll *event) +static void +gtk_gis_realize (GtkWidget *widget) { + GdkWindowAttr attributes; + gint attributes_mask; + GtkGisPrivate *priv; - GtkGis *gtkgis; - GtkGisScale *scale; -g_fprintf(stderr,"dentro scroll event"); - g_return_val_if_fail (IS_GTK_GIS (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + priv = GTK_GIS_GET_PRIVATE (GTK_GIS (widget)); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK; +g_fprintf(stderr,"dentro realize %d %d %d %d\n",attributes.x,attributes.y,attributes.width,attributes.height); + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); + + attributes.wclass = GDK_INPUT_ONLY; + attributes_mask = 0; + + priv->event_window = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_user_data (priv->event_window, widget); + + widget->style = gtk_style_attach (widget->style, widget->window); + + gdk_window_set_back_pixmap (widget->window, NULL, FALSE); +} - gtkgis = GTK_GIS (widget); - priv = GTK_GIS_GET_PRIVATE (gtkgis); +static void +gtk_gis_unrealize (GtkWidget *widget) +{ + GtkGisPrivate *priv; - scale = gtk_gis_get_scale (gtkgis); + priv = GTK_GIS_GET_PRIVATE (widget); - if (event->direction == GDK_SCROLL_UP) - {g_fprintf(stderr,"dentro scroll up"); - scale->x = (scale->x * 120) / 100; - scale->y = (scale->y * 120) / 100; - scale->xy = (scale->xy * 120) / 100; - } - else if (event->direction == GDK_SCROLL_DOWN) - {g_fprintf(stderr,"dentro scroll down"); - scale->x = (scale->x * 80) / 100; - scale->y = (scale->y * 80) / 100; - scale->xy = (scale->xy * 80) / 100; + if (priv->event_window != NULL) + { + gdk_window_set_user_data (priv->event_window, NULL); + gdk_window_destroy (priv->event_window); + priv->event_window = NULL; } - gtk_gis_set_scale (gtkgis, scale); + GTK_WIDGET_CLASS (gtk_gis_parent_class)->unrealize (widget); +} - return TRUE; +static void +gtk_gis_map (GtkWidget *widget) +{ + GtkGisPrivate *priv; + + g_return_if_fail (IS_GTK_GIS (widget)); + + priv = GTK_GIS_GET_PRIVATE (GTK_GIS (widget)); + + GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); + + GTK_WIDGET_CLASS (gtk_gis_parent_class)->map (widget); + + gdk_window_show (priv->event_window); + gdk_window_show (widget->window); } static void @@ -783,3 +883,148 @@ gtk_gis_size_allocate (GtkWidget *widget, } } +static gboolean +gtk_gis_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + GtkGis *gtkgis; + GtkGisPrivate *priv; + + g_return_if_fail (IS_GTK_GIS (widget)); + + gtkgis = GTK_GIS (widget); + + priv = GTK_GIS_GET_PRIVATE (gtkgis); + + if (event->button == 1) + { + if (priv->sel_start == NULL) + { + priv->sel_start = g_malloc0 (sizeof (GtkGisPoint)); + } + + priv->sel_start->x = event->x; + priv->sel_start->y = event->y; +g_fprintf(stderr,"button press %f %f\n",priv->sel_start->x,priv->sel_start->y); + } + + return FALSE; +} + +static gboolean +gtk_gis_button_release_event (GtkWidget *widget, + GdkEventButton *event) +{ + GtkGis *gtkgis; + GtkGisPrivate *priv; + + g_return_if_fail (IS_GTK_GIS (widget)); + + gtkgis = GTK_GIS (widget); + + priv = GTK_GIS_GET_PRIVATE (gtkgis); + + if (event->button == 1) + { + g_free (priv->sel_start); + priv->sel_start = NULL; + } + + return FALSE; +} + +static gboolean +gtk_gis_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event) +{ + GtkGis *gtkgis; + GtkGisPrivate *priv; + + gint x; + gint y; + GdkModifierType state; + + g_return_if_fail (IS_GTK_GIS (widget)); + + gtkgis = GTK_GIS (widget); + + priv = GTK_GIS_GET_PRIVATE (gtkgis); +g_fprintf(stderr,"motion\n"); + if (event->is_hint) + { + gdk_window_get_pointer (event->window, &x, &y, &state); + } + else + { + x = (gint)event->x; + y = (gint)event->y; + state = event->state; + } + + if (state & GDK_BUTTON1_MASK + && priv->sel_start != NULL) + { + GtkAllocation allocation; + GtkAllocation new_allocation; + + allocation = priv->canvas->allocation; +g_fprintf(stderr,"alloc %d %d sel %f %f event %d %d\n",allocation.x,allocation.y,priv->sel_start->x,priv->sel_start->y,x,y); + new_allocation.x = allocation.x + (x - (gint)priv->sel_start->x); + new_allocation.y = allocation.y + (y - (gint)priv->sel_start->y); + + gtk_layout_move (GTK_LAYOUT (priv->scroll_win), priv->canvas, + new_allocation.x, new_allocation.y); + + priv->sel_start->x = x; + priv->sel_start->y = y; + } + + return FALSE; +} + +static gboolean +gtk_gis_scroll_event (GtkWidget *widget, + GdkEventScroll *event) +{ + GtkGisPrivate *priv; + + GtkGis *gtkgis; + GtkGisScale *scale; +g_fprintf(stderr,"dentro scroll event\n"); + g_return_val_if_fail (IS_GTK_GIS (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + gtkgis = GTK_GIS (widget); + priv = GTK_GIS_GET_PRIVATE (gtkgis); + + scale = gtk_gis_get_scale (gtkgis); + + if (event->direction == GDK_SCROLL_UP) + {g_fprintf(stderr,"dentro scroll up\n"); + scale->x = (scale->x * 120) / 100; + scale->y = (scale->y * 120) / 100; + scale->xy = (scale->xy * 120) / 100; + } + else if (event->direction == GDK_SCROLL_DOWN) + {g_fprintf(stderr,"dentro scroll down\n"); + scale->x = (scale->x * 80) / 100; + scale->y = (scale->y * 80) / 100; + scale->xy = (scale->xy * 80) / 100; + } + + gtk_gis_set_scale (gtkgis, scale); + + return TRUE; +} + +static void +gtk_gis_canvas_resize (GtkGis *gtkgis) +{ + GtkGisPrivate *priv; + + priv = GTK_GIS_GET_PRIVATE (gtkgis); + + gtk_widget_set_size_request (priv->canvas, + (priv->extent->max_x - priv->extent->min_x) * priv->scale->x, + (priv->extent->max_y - priv->extent->min_y) * priv->scale->y); +} diff --git a/src/gtkgis.h b/src/gtkgis.h index aa90770..68cbec0 100644 --- a/src/gtkgis.h +++ b/src/gtkgis.h @@ -57,17 +57,19 @@ GType gtk_gis_get_type (void) G_GNUC_CONST; GtkWidget *gtk_gis_new (void); GtkWidget *gtk_gis_new_from_xml (xmlDoc *xdoc); -GtkWidget *gtk_gis_new_from_file (const gchar *filename); +GtkWidget *gtk_gis_new_from_file (const gchar *file_name); xmlDoc *gtk_gis_get_xml (GtkGis *gtkgis); -void *gtk_gis_save_to_xml (GtkGis *gtkgis, const gchar *filename); +void *gtk_gis_save_to_xml (GtkGis *gtkgis, const gchar *file_name); -void gtk_gis_add_group (GtkGis *gtkgis, GtkGisLayersGroup *group); -void gtk_gis_remove_group (GtkGis *gtkgis, GtkGisLayersGroup *group); +void gtk_gis_add_group (GtkGis *gtkgis, GtkGisLayersGroup *layers_group); +void gtk_gis_remove_group (GtkGis *gtkgis, GtkGisLayersGroup *layers_group); void gtk_gis_add_layer (GtkGis *gtkgis, GtkGisLayer *layer); void gtk_gis_remove_layer (GtkGis *gtkgis, GtkGisLayer *layer); +GtkGisLayer *gtk_gis_get_layer_by_name (GtkGis *gtkgis, const gchar *layer_name); + void gtk_gis_draw (GtkGis *gtkgis); GtkGisScale *gtk_gis_get_scale (GtkGis *gtkgis); @@ -76,7 +78,6 @@ void gtk_gis_set_scale (GtkGis *gtkgis, GtkGisScale *scale); void gtk_gis_zoom_to_max (GtkGis *gtkgis); void gtk_gis_zoom_to_layer (GtkGis *gtkgis, GtkGisLayer *layer); -void gtk_gis_set_legend_visible (GtkGis *gtkgis, gboolean visible); GtkWidget *gtk_gis_get_legend (GtkGis *gtkgis); diff --git a/tests/from_xml.c b/tests/from_xml.c index 4272b28..1b49545 100644 --- a/tests/from_xml.c +++ b/tests/from_xml.c @@ -5,6 +5,7 @@ main (int argc, char *argv[]) { GtkWidget *window; GtkWidget *gtkgis; + GtkGisScale *scale; gtk_init (&argc, &argv); @@ -23,6 +24,12 @@ main (int argc, char *argv[]) gtk_gis_zoom_to_max (GTK_GIS (gtkgis)); gtk_gis_draw (GTK_GIS (gtkgis)); + scale = gtk_gis_get_scale (GTK_GIS (gtkgis)); + scale->x = (scale->x * 80) / 100; + scale->y = (scale->y * 80) / 100; + scale->xy = (scale->xy * 80) / 100; + gtk_gis_set_scale (GTK_GIS (gtkgis), scale); + gtk_gis_save_to_xml (GTK_GIS (gtkgis), "test_saved.gtkgis"); gtk_main (); -- 2.49.0