[evolution/gtk3] Bug #637081 - Port EMap widget to GTK+ 3



commit 69f3641b22fd7f4e796c602e2199a4431e61424b
Author: Milan Bouchet-Valat <nalimilan club fr>
Date:   Fri Jan 21 19:39:29 2011 +0100

    Bug #637081 - Port EMap widget to GTK+ 3

 widgets/misc/e-map.c |  321 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 219 insertions(+), 102 deletions(-)
---
diff --git a/widgets/misc/e-map.c b/widgets/misc/e-map.c
index 23a7bd4..c72b15e 100644
--- a/widgets/misc/e-map.c
+++ b/widgets/misc/e-map.c
@@ -42,8 +42,8 @@
 
 /* */
 
-#define E_MAP_GET_WIDTH(map) gtk_adjustment_get_upper((map)->priv->hadj)
-#define E_MAP_GET_HEIGHT(map) gtk_adjustment_get_upper((map)->priv->vadj)
+#define E_MAP_GET_WIDTH(map) gtk_adjustment_get_upper((map)->priv->hadjustment)
+#define E_MAP_GET_HEIGHT(map) gtk_adjustment_get_upper((map)->priv->vadjustment)
 
 /* Zoom state - keeps track of animation hacks */
 
@@ -79,8 +79,13 @@ struct _EMapPrivate {
 	gboolean frozen, smooth_zoom;
 
 	/* Adjustments for scrolling */
-	GtkAdjustment *hadj;
-	GtkAdjustment *vadj;
+	GtkAdjustment *hadjustment;
+	GtkAdjustment *vadjustment;
+
+	/* GtkScrollablePolicy needs to be checked when
+	 * driving the scrollable adjustment values */
+	guint hscroll_policy : 1;
+	guint vscroll_policy : 1;
 
 	/* Current scrolling offsets */
 	gint xofs, yofs;
@@ -99,6 +104,18 @@ struct _EMapPrivate {
 	guint tween_id;
 };
 
+/* Properties */
+
+enum {
+	PROP_0,
+
+	/* For scrollable interface */
+	PROP_HADJUSTMENT,
+	PROP_VADJUSTMENT,
+	PROP_HSCROLL_POLICY,
+	PROP_VSCROLL_POLICY
+};
+
 /* Internal prototypes */
 
 static void e_map_get_current_location (EMap *map, gdouble *longitude, gdouble *latitude);
@@ -109,7 +126,6 @@ static void set_scroll_area (EMap *map, gint width, gint height);
 static void center_at (EMap *map, gdouble longitude, gdouble latitude);
 static void scroll_to (EMap *map, gint x, gint y);
 static gint load_map_background (EMap *map, gchar *name);
-static void adjustment_changed_cb (EMap *map);
 static void update_and_paint (EMap *map);
 static void update_render_point (EMap *map, EMapPoint *point);
 static void repaint_point (EMap *map, EMapPoint *point);
@@ -211,10 +227,11 @@ e_map_tween_new (EMap *map, guint msecs, gdouble longitude_offset, gdouble latit
 	gtk_widget_queue_draw (GTK_WIDGET (map));
 }
 
-G_DEFINE_TYPE (
+G_DEFINE_TYPE_WITH_CODE (
 	EMap,
 	e_map,
-	GTK_TYPE_WIDGET)
+	GTK_TYPE_WIDGET,
+	G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
 
 static void
 e_map_tween_new_from (EMap *map,
@@ -293,65 +310,183 @@ e_map_tweens_compute_matrix (EMap *map, cairo_matrix_t *matrix)
 	cairo_matrix_translate (matrix, -x, -y);
 }
 
-/* ----------------- *
- * Widget management *
- * ----------------- */
+/* GtkScrollable implementation */
 
 static void
-e_map_notify_hadjustment_cb (EMap *map)
+e_map_adjustment_changed (GtkAdjustment *adjustment, EMap *map)
 {
-	GtkScrollable *scrollable;
-	GtkAdjustment *hadjustment;
+	EMapPrivate *priv = map->priv;
 
-	scrollable = GTK_SCROLLABLE (map);
-	hadjustment = gtk_scrollable_get_hadjustment (scrollable);
+	if (gtk_widget_get_realized (GTK_WIDGET (map))) {
+		gint hadj_value;
+		gint vadj_value;
 
-	if (hadjustment != NULL)
-		g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment));
-	else
-		hadjustment = gtk_adjustment_new (.0, .0, .0, .0, .0, .0);
+		hadj_value = gtk_adjustment_get_value (priv->hadjustment);
+		vadj_value = gtk_adjustment_get_value (priv->vadjustment);
 
-	if (map->priv->hadj != NULL && map->priv->hadj != hadjustment) {
-		g_signal_handlers_disconnect_by_func (
-			map->priv->hadj, adjustment_changed_cb, map);
-		g_object_unref (map->priv->hadj);
+		scroll_to (map, hadj_value, vadj_value);
 	}
+}
+
+static void
+e_map_set_hadjustment_values (EMap *map)
+{
+	GtkAllocation  allocation;
+	EMapPrivate *priv = map->priv;
+	GtkAdjustment *adj = priv->hadjustment;
+	gdouble old_value;
+	gdouble new_value;
+	gdouble new_upper;
+
+	gtk_widget_get_allocation (GTK_WIDGET (map), &allocation);
+
+	old_value = gtk_adjustment_get_value (adj);
+	new_upper = MAX (allocation.width, gdk_pixbuf_get_width (priv->map_pixbuf));
+
+	g_object_set (adj,
+		"lower", 0.0,
+		"upper", new_upper,
+		"page-size", (gdouble)allocation.height,
+		"step-increment", allocation.height * 0.1,
+		"page-increment", allocation.height * 0.9,
+		NULL);
+
+	new_value = CLAMP (old_value, 0, new_upper - allocation.width);
+	if (new_value != old_value)
+		gtk_adjustment_set_value (adj, new_value);
+}
+
+static void
+e_map_set_vadjustment_values (EMap *map)
+{
+	GtkAllocation  allocation;
+	EMapPrivate *priv = map->priv;
+	GtkAdjustment *adj = priv->vadjustment;
+	gdouble old_value;
+	gdouble new_value;
+	gdouble new_upper;
+
+	gtk_widget_get_allocation (GTK_WIDGET (map), &allocation);
 
-	if (map->priv->hadj != hadjustment) {
-		map->priv->hadj = g_object_ref_sink (hadjustment);
-		g_signal_connect_swapped (
-			hadjustment, "value-changed",
-			G_CALLBACK (adjustment_changed_cb), map);
-		adjustment_changed_cb (map);
+	old_value = gtk_adjustment_get_value (adj);
+	new_upper = MAX (allocation.height, gdk_pixbuf_get_height (priv->map_pixbuf));
+
+	g_object_set (adj,
+		"lower", 0.0,
+		"upper", new_upper,
+		"page-size", (gdouble)allocation.height,
+		"step-increment", allocation.height * 0.1,
+		"page-increment", allocation.height * 0.9,
+		NULL);
+
+	new_value = CLAMP (old_value, 0, new_upper - allocation.height);
+	if (new_value != old_value)
+		gtk_adjustment_set_value (adj, new_value);
+}
+
+static void
+e_map_set_hadjustment (EMap *map, GtkAdjustment *adjustment)
+{
+	EMapPrivate *priv = map->priv;
+
+	if (adjustment && priv->hadjustment == adjustment)
+		return;
+
+	if (priv->hadjustment != NULL) {
+		g_signal_handlers_disconnect_matched (priv->hadjustment, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, map);
+		g_object_unref (priv->hadjustment);
 	}
+
+	if (!adjustment)
+		adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+	g_signal_connect (adjustment, "value-changed", G_CALLBACK (e_map_adjustment_changed), map);
+	priv->hadjustment = g_object_ref_sink (adjustment);
+	e_map_set_hadjustment_values (map);
+
+	g_object_notify (G_OBJECT (map), "hadjustment");
 }
 
 static void
-e_map_notify_vadjustment_cb (EMap *map)
+e_map_set_vadjustment (EMap *map, GtkAdjustment *adjustment)
 {
-	GtkScrollable *scrollable;
-	GtkAdjustment *vadjustment;
+	EMapPrivate *priv = map->priv;
 
-	scrollable = GTK_SCROLLABLE (map);
-	vadjustment = gtk_scrollable_get_vadjustment (scrollable);
+	if (adjustment && priv->vadjustment == adjustment)
+		return;
 
-	if (vadjustment != NULL)
-		g_return_if_fail (GTK_IS_ADJUSTMENT (vadjustment));
-	else
-		vadjustment = gtk_adjustment_new (.0, .0, .0, .0, .0, .0);
+	if (priv->vadjustment != NULL) {
+		g_signal_handlers_disconnect_matched (priv->vadjustment, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, map);
+		g_object_unref (priv->vadjustment);
+	}
+
+	if (!adjustment)
+		adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+	g_signal_connect (adjustment, "value-changed", G_CALLBACK (e_map_adjustment_changed), map);
+	priv->vadjustment = g_object_ref_sink (adjustment);
+	e_map_set_vadjustment_values (map);
 
-	if (map->priv->vadj != NULL && map->priv->vadj != vadjustment) {
-		g_signal_handlers_disconnect_by_func (
-			map->priv->vadj, adjustment_changed_cb, map);
-		g_object_unref (map->priv->vadj);
+	g_object_notify (G_OBJECT (map), "vadjustment");
+}
+
+/* ----------------- *
+ * Widget management *
+ * ----------------- */
+
+static void
+e_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	EMap *map;
+
+	map = E_MAP (object);
+
+	switch (prop_id) {
+	case PROP_HADJUSTMENT:
+		e_map_set_hadjustment (map, g_value_get_object (value));
+		break;
+	case PROP_VADJUSTMENT:
+		e_map_set_vadjustment (map, g_value_get_object (value));
+		break;
+	case PROP_HSCROLL_POLICY:
+		map->priv->hscroll_policy = g_value_get_enum (value);
+		gtk_widget_queue_resize (GTK_WIDGET (map));
+		break;
+	case PROP_VSCROLL_POLICY:
+		map->priv->vscroll_policy = g_value_get_enum (value);
+		gtk_widget_queue_resize (GTK_WIDGET (map));
+		break;
+
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
 	}
+}
 
-	if (map->priv->vadj != vadjustment) {
-		map->priv->vadj = g_object_ref_sink (vadjustment);
-		g_signal_connect_swapped (
-			vadjustment, "value-changed",
-			G_CALLBACK (adjustment_changed_cb), map);
-		adjustment_changed_cb (map);
+static void
+e_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	EMap *map;
+
+	map = E_MAP (object);
+
+	switch (prop_id) {
+	case PROP_HADJUSTMENT:
+		g_value_set_object (value, map->priv->hadjustment);
+		break;
+	case PROP_VADJUSTMENT:
+		g_value_set_object (value, map->priv->vadjustment);
+		break;
+	case PROP_HSCROLL_POLICY:
+		g_value_set_enum (value, map->priv->hscroll_policy);
+		break;
+	case PROP_VSCROLL_POLICY:
+		g_value_set_enum (value, map->priv->vscroll_policy);
+		break;
+
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
 	}
 }
 
@@ -366,17 +501,7 @@ e_map_finalize (GObject *object)
 		e_map_tween_destroy (map, map->priv->tweens->data);
 	e_map_stop_tweening (map);
 
-	g_signal_handlers_disconnect_by_func (map->priv->hadj, adjustment_changed_cb, map);
-	g_signal_handlers_disconnect_by_func (map->priv->vadj, adjustment_changed_cb, map);
-
-	g_object_unref ((map->priv->hadj));
-	map->priv->hadj = NULL;
-
-	g_object_unref ((map->priv->vadj));
-	map->priv->vadj = NULL;
-
-	if (map->priv->map_pixbuf)
-	{
+	if (map->priv->map_pixbuf) {
 		g_object_unref (map->priv->map_pixbuf);
 		map->priv->map_pixbuf = NULL;
 	}
@@ -596,18 +721,18 @@ e_map_key_press (GtkWidget *widget,
 		gint upper;
 		gint x, y;
 
-		page_size = gtk_adjustment_get_page_size (map->priv->hadj);
-		upper = gtk_adjustment_get_upper (map->priv->hadj);
+		page_size = gtk_adjustment_get_page_size (map->priv->hadjustment);
+		upper = gtk_adjustment_get_upper (map->priv->hadjustment);
 		x = CLAMP (map->priv->xofs + xofs, 0, upper - page_size);
 
-		page_size = gtk_adjustment_get_page_size (map->priv->vadj);
-		upper = gtk_adjustment_get_upper (map->priv->vadj);
+		page_size = gtk_adjustment_get_page_size (map->priv->vadjustment);
+		upper = gtk_adjustment_get_upper (map->priv->vadjustment);
 		y = CLAMP (map->priv->yofs + yofs, 0, upper - page_size);
 
 		scroll_to (map, x, y);
 
-		gtk_adjustment_set_value (map->priv->hadj, x);
-		gtk_adjustment_set_value (map->priv->vadj, y);
+		gtk_adjustment_set_value (map->priv->hadjustment, x);
+		gtk_adjustment_set_value (map->priv->vadjustment, y);
 	}
 
 	return TRUE;
@@ -621,6 +746,14 @@ e_map_class_init (EMapClass *class)
 
 	object_class = G_OBJECT_CLASS (class);
 	object_class->finalize = e_map_finalize;
+	object_class->set_property = e_map_set_property;
+	object_class->get_property = e_map_get_property;
+
+	/* Scrollable interface properties */
+	g_object_class_override_property (object_class, PROP_HADJUSTMENT,    "hadjustment");
+	g_object_class_override_property (object_class, PROP_VADJUSTMENT,    "vadjustment");
+	g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+	g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
 
 	widget_class = GTK_WIDGET_CLASS (class);
 	widget_class->realize = e_map_realize;
@@ -654,14 +787,6 @@ e_map_init (EMap *map)
 
 	gtk_widget_set_can_focus (widget, TRUE);
 	gtk_widget_set_has_window (widget, TRUE);
-
-	g_signal_connect (
-		map, "notify::hadjustment",
-		G_CALLBACK (e_map_notify_hadjustment_cb), NULL);
-
-	g_signal_connect (
-		map, "notify::vadjustment",
-		G_CALLBACK (e_map_notify_vadjustment_cb), NULL);
 }
 
 /* ---------------- *
@@ -1131,8 +1256,8 @@ center_at (EMap *map, gdouble longitude, gdouble latitude)
 	x = CLAMP (x - (allocation.width / 2), 0, pb_width - allocation.width);
 	y = CLAMP (y - (allocation.height / 2), 0, pb_height - allocation.height);
 
-	gtk_adjustment_set_value (map->priv->hadj, x);
-	gtk_adjustment_set_value (map->priv->vadj, y);
+	gtk_adjustment_set_value (map->priv->hadjustment, x);
+	gtk_adjustment_set_value (map->priv->vadjustment, y);
 
 	gtk_widget_queue_draw (GTK_WIDGET (map));
 }
@@ -1170,49 +1295,41 @@ e_map_get_current_location (EMap *map, gdouble *longitude, gdouble *latitude)
 			       longitude, latitude);
 }
 
-/* Callback used when an adjustment is changed */
-
 static void
-adjustment_changed_cb (EMap *map)
+set_scroll_area (EMap *view, int width, int height)
 {
-	gint hadj_value;
-	gint vadj_value;
-
-	hadj_value = gtk_adjustment_get_value (map->priv->hadj);
-	vadj_value = gtk_adjustment_get_value (map->priv->vadj);
+	EMapPrivate *priv;
+	GtkAllocation allocation;
 
-	scroll_to (map, hadj_value, vadj_value);
-}
+	priv = view->priv;
 
-static void
-set_scroll_area (EMap *map, gint width, gint height)
-{
-	GtkAllocation allocation;
+	if (!gtk_widget_get_realized (GTK_WIDGET (view)))
+		return;
 
-	if (!gtk_widget_get_realized (GTK_WIDGET (map))) return;
-	if (!map->priv->hadj || !map->priv->vadj) return;
+	if (!priv->hadjustment || !priv->vadjustment)
+		return;
 
-	g_object_freeze_notify (G_OBJECT (map->priv->hadj));
-	g_object_freeze_notify (G_OBJECT (map->priv->vadj));
+	g_object_freeze_notify (G_OBJECT (priv->hadjustment));
+	g_object_freeze_notify (G_OBJECT (priv->vadjustment));
 
-	gtk_widget_get_allocation (GTK_WIDGET (map), &allocation);
+	gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
 
-	map->priv->xofs = CLAMP (map->priv->xofs, 0, width - allocation.width);
-	map->priv->yofs = CLAMP (map->priv->yofs, 0, height - allocation.height);
+	priv->xofs = CLAMP (priv->xofs, 0, width - allocation.width);
+	priv->yofs = CLAMP (priv->yofs, 0, height - allocation.height);
 
-	gtk_adjustment_configure (map->priv->hadj,
-				  map->priv->xofs,
+	gtk_adjustment_configure (priv->hadjustment,
+				  priv->xofs,
 				  0, width,
 				  SCROLL_STEP_SIZE,
 				  allocation.width / 2,
 				  allocation.width);
-	gtk_adjustment_configure (map->priv->vadj,
-				  map->priv->yofs,
+	gtk_adjustment_configure (priv->vadjustment,
+				  priv->yofs,
 				  0, height,
 				  SCROLL_STEP_SIZE,
 				  allocation.height / 2,
 				  allocation.height);
 
-	g_object_thaw_notify (G_OBJECT (map->priv->hadj));
-	g_object_thaw_notify (G_OBJECT (map->priv->vadj));
+	g_object_thaw_notify (G_OBJECT (priv->hadjustment));
+	g_object_thaw_notify (G_OBJECT (priv->vadjustment));
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]