[goffice] Axes can use only a part of available space. [#654392]



commit 2d27e8ef37d7a6063b4a80270cc784ad95627d81
Author: Jean Brefort <jean brefort normalesup org>
Date:   Sun Aug 7 17:12:23 2011 +0200

    Axes can use only a part of available space. [#654392]

 ChangeLog                       |   14 +++++
 NEWS                            |    1 +
 goffice/canvas/goc-graph.c      |   89 ++++++++++++++++++++------------
 goffice/graph/gog-axis-prefs.ui |  111 ++++++++++++++++++++++++++++++++------
 goffice/graph/gog-axis.c        |  107 ++++++++++++++++++++++++++++++++++++-
 goffice/graph/gog-axis.h        |    2 +
 6 files changed, 270 insertions(+), 54 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0acd7fb..1efacc9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-08-07  Jean Brefort  <jean brefort normalesup org>
+
+	* goffice/canvas/goc-graph.c (goc_graph_do_tooltip): fix when an axis
+	does not use all the available space.
+	* goffice/graph/gog-axis-prefs.ui: allows an axis to use only part of
+	available space. [#654392]
+	* goffice/graph/gog-axis.c (gog_axis_map_new),
+	(gog_axis_map_get_extents), (gog_axis_map_get_bounds),
+	(gog_axis_set_property), (gog_axis_get_property),
+	(cb_start_changed), (cb_end_changed), (gog_axis_populate_editor),
+	(gog_axis_class_init), (gog_axis_init), (gog_axis_set_bounds),
+	(gog_axis_get_effective_span): ditto.
+	* goffice/graph/gog-axis.h: ditto.
+
 2011-08-06  Jean Brefort  <jean brefort normalesup org>
 
 	* goffice/graph/gog-label.c (gog_text_set_property),
diff --git a/NEWS b/NEWS
index 9cdd5e9..17f846a 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Jean:
 	* Add a plugin directory for extern plugins, independent from micro version.
 	* Allow the frame around a chart label to rotate with the text. [647147]
 	* Chart labels accept rich text. [#417631]
+	* Axes can use only a part of available space. [#654392]
 
 Morten:
 	* Recognize scientific formats with longer exponents.
diff --git a/goffice/canvas/goc-graph.c b/goffice/canvas/goc-graph.c
index 16a71cd..41776d8 100644
--- a/goffice/canvas/goc-graph.c
+++ b/goffice/canvas/goc-graph.c
@@ -248,16 +248,17 @@ format_coordinate (GogAxis *axis, GOFormat *fmt, double x)
 static void
 goc_graph_do_tooltip (GocGraph *graph)
 {
-	GogView *view;
+	GogView *view, *base_view;
 	char *buf = NULL, *s1 = NULL, *s2 = NULL;
 	GogObject *obj;
 	GogChart *chart;
 	GogViewAllocation alloc;
 	double xpos, ypos;
-	GogChartMap *map;
-	GogAxis *x_axis, *y_axis;
+	GogChartMap *map = NULL;
+	GogAxis *x_axis, *y_axis = NULL;
 	GogAxisSet set;
-	GSList *l;
+	GogPlot *plot;
+	GSList *l, *ptr;
 	GOFormat *format;
 	GocItem *item = (GocItem *)graph;
 	double x = graph->coords.x;
@@ -271,9 +272,9 @@ goc_graph_do_tooltip (GocGraph *graph)
 	y -= ypos;
 
 	/* get the GogView at the cursor position */
-	g_object_get (G_OBJECT (graph->renderer), "view", &view, NULL);
-	g_object_unref (view); /* we don't need a reference */
-	gog_view_get_view_at_point (view, x, y, &obj, NULL);
+	g_object_get (G_OBJECT (graph->renderer), "view", &base_view, NULL);
+	g_object_unref (base_view); /* we don't need a reference */
+	gog_view_get_view_at_point (base_view, x, y, &obj, NULL);
 	if (!obj)
 		goto tooltip;
 	chart = GOG_CHART (gog_object_get_parent_typed (obj, GOG_TYPE_CHART));
@@ -284,35 +285,57 @@ goc_graph_do_tooltip (GocGraph *graph)
 	l = gog_object_get_children (GOG_OBJECT (chart), gog_object_find_role_by_name (GOG_OBJECT (chart), "Plot"));
 	if (l == NULL)
 		return;
-	view = gog_view_find_child_view (view, GOG_OBJECT (l->data));
+	ptr = l;
+	while (ptr) {
+		view = gog_view_find_child_view (base_view, GOG_OBJECT (ptr->data));
+		if (view) {
+			double start, end;
+			alloc = view->allocation;
+			plot = GOG_PLOT (ptr->data);
+			switch (set) {
+			case GOG_AXIS_SET_XY:
+				/* get the axis */
+				x_axis = gog_plot_get_axis (plot, GOG_AXIS_X);
+				gog_axis_get_effective_span (x_axis, &start, &end);
+				if (x < alloc.x + alloc.w * start || x > alloc.x + alloc.w * end) 
+					break;
+				y_axis = gog_plot_get_axis (plot, GOG_AXIS_Y);
+				gog_axis_get_effective_span (y_axis, &start, &end);
+				if (y < alloc.y + alloc.h * (1. - start) && y > alloc.y + alloc.h * (1. - end))
+					map = gog_chart_map_new (chart, &alloc, x_axis, y_axis, NULL, FALSE);
+				break;
+			case GOG_AXIS_SET_RADAR: {
+				double a, r, min, max;
+				/* get the axis */
+				x_axis = gog_plot_get_axis (plot, GOG_AXIS_CIRCULAR);
+				y_axis = gog_plot_get_axis (plot, GOG_AXIS_RADIAL);
+				map = gog_chart_map_new (chart, &alloc, x_axis, y_axis, NULL, FALSE);
+				gog_axis_get_bounds (y_axis, &min, &max);
+				r = min - 1;
+				if (gog_chart_map_is_valid (map))
+					gog_chart_map_view_to_2D (map, x, y, &a, &r);
+				if (r < min || r > max) {
+					gog_chart_map_free (map);
+					map = NULL;
+				}
+				break;
+			}
+			default:
+				buf = gog_view_get_tip_at_point (view, x, y);
+				g_slist_free (l);
+				goto tooltip;
+			}
+			if (map != NULL)
+				break;
+			view = NULL;
+		}
+		ptr = ptr->next;
+	}
 	g_slist_free (l);
-	if (!view)
+	if (view == NULL) {
+		gtk_widget_set_tooltip_markup (GTK_WIDGET (item->canvas), NULL);
 		return;
-	alloc = view->allocation;
-	switch (set) {
-	case GOG_AXIS_SET_XY:
-		/* get the axis */
-		l = gog_chart_get_axes (chart, GOG_AXIS_X);
-		x_axis = GOG_AXIS (l->data);
-		g_slist_free (l);
-		l = gog_chart_get_axes (chart, GOG_AXIS_Y);
-		y_axis = GOG_AXIS (l->data);
-		g_slist_free (l);
-		break;
-	case GOG_AXIS_SET_RADAR:
-		/* get the axis */
-		l = gog_chart_get_axes (chart, GOG_AXIS_CIRCULAR);
-		x_axis = GOG_AXIS (l->data);
-		g_slist_free (l);
-		l = gog_chart_get_axes (chart, GOG_AXIS_RADIAL);
-		y_axis = GOG_AXIS (l->data);
-		g_slist_free (l);
-		break;
-	default:
-		buf = gog_view_get_tip_at_point (view, x, y);
-		goto tooltip;
 	}
-	map = gog_chart_map_new (chart, &alloc, x_axis, y_axis, NULL, FALSE);
 	if (gog_chart_map_is_valid (map) &&
 				x >= alloc.x && x < alloc.x + alloc.w &&
 				y >= alloc.y && y < alloc.y + alloc.h) {
diff --git a/goffice/graph/gog-axis-prefs.ui b/goffice/graph/gog-axis-prefs.ui
index ff49ff3..3667984 100644
--- a/goffice/graph/gog-axis-prefs.ui
+++ b/goffice/graph/gog-axis-prefs.ui
@@ -13,6 +13,99 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkAdjustment" id="start-adj">
+    <property name="upper">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="end-adj">
+    <property name="upper">100</property>
+    <property name="value">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkGrid" id="area-grid">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="row_spacing">12</property>
+    <property name="column_spacing">6</property>
+    <child>
+      <object class="GtkLabel" id="label13">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">&lt;b&gt;Effective area&lt;/b&gt; (as % of available room)</property>
+        <property name="use_markup">True</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+        <property name="width">3</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label14">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">12</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Start:</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">1</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkSpinButton" id="start-btn">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="invisible_char">â</property>
+        <property name="invisible_char_set">True</property>
+        <property name="adjustment">start-adj</property>
+        <property name="digits">1</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">1</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkSpinButton" id="end-btn">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="invisible_char">â</property>
+        <property name="invisible_char_set">True</property>
+        <property name="adjustment">end-adj</property>
+        <property name="digits">1</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">2</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label15">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">End:</property>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">2</property>
+        <property name="width">1</property>
+        <property name="height">1</property>
+      </packing>
+    </child>
+  </object>
   <object class="GtkGrid" id="axis-base-pref-grid">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -205,9 +298,6 @@
                 <property name="height">1</property>
               </packing>
             </child>
-            <child>
-              <placeholder/>
-            </child>
           </object>
           <packing>
             <property name="left_attach">0</property>
@@ -282,15 +372,6 @@
       </packing>
     </child>
     <child>
-      <placeholder/>
-    </child>
-    <child>
-      <placeholder/>
-    </child>
-    <child>
-      <placeholder/>
-    </child>
-    <child>
       <object class="GtkGrid" id="minor-tick-grid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
@@ -536,9 +617,6 @@
                 <property name="height">1</property>
               </packing>
             </child>
-            <child>
-              <placeholder/>
-            </child>
           </object>
           <packing>
             <property name="left_attach">0</property>
@@ -547,9 +625,6 @@
             <property name="height">1</property>
           </packing>
         </child>
-        <child>
-          <placeholder/>
-        </child>
       </object>
       <packing>
         <property name="left_attach">0</property>
diff --git a/goffice/graph/gog-axis.c b/goffice/graph/gog-axis.c
index be61241..293dc9f 100644
--- a/goffice/graph/gog-axis.c
+++ b/goffice/graph/gog-axis.c
@@ -92,6 +92,7 @@ struct _GogAxis {
 
 	GogAxisTick	*ticks;
 	unsigned	 tick_nbr;
+	double span_start, span_end;    /* percent of used area */
 };
 
 /*****************************************************************************/
@@ -1578,6 +1579,11 @@ gog_axis_map_new (GogAxis *axis, double offset, double length)
 	map->data = NULL;
 	map->is_valid = FALSE;
 
+	if (axis->type != GOG_AXIS_CIRCULAR) {
+		offset += axis->span_start * length;
+		length *= axis->span_end - axis->span_start;
+	}
+
 	if (map->desc->init != NULL)
 		map->is_valid = map->desc->init (map, offset, length);
 
@@ -1708,11 +1714,16 @@ void
 gog_axis_map_get_extents (GogAxisMap *map, double *start, double *stop)
 {
 	g_return_if_fail (map != NULL);
-
+	
 	if (map->axis->inverted)
 		map->desc->map_bounds (map, stop, start);
 	else
 		map->desc->map_bounds (map, start, stop);
+	if (map->axis->type != GOG_AXIS_CIRCULAR) {
+		double buf = (*stop - *start) / (map->axis->span_end - map->axis->span_start);
+		*start -= map->axis->span_start * buf;
+		*stop = *start + buf;
+	}
 }
 
 /**
@@ -1731,8 +1742,13 @@ void
 gog_axis_map_get_bounds (GogAxisMap *map, double *minimum, double *maximum)
 {
 	g_return_if_fail (map != NULL);
-
+	
 	map->desc->map_bounds (map, minimum, maximum);
+	if (map->axis->type != GOG_AXIS_CIRCULAR) {
+		double buf = (*minimum - *maximum) / (map->axis->span_end - map->axis->span_start);
+		*maximum -= map->axis->span_start * buf;
+		*minimum = *maximum + buf;
+	}
 }
 
 /**
@@ -1873,7 +1889,9 @@ enum {
 	AXIS_PROP_MAP,
 	AXIS_PROP_ASSIGNED_FORMAT_STR_XL,
 	AXIS_PROP_CIRCULAR_ROTATION,
-	AXIS_PROP_POLAR_UNIT
+	AXIS_PROP_POLAR_UNIT,
+	AXIS_PROP_SPAN_START,
+	AXIS_PROP_SPAN_END
 };
 
 /*****************************************************************************/
@@ -2066,6 +2084,20 @@ gog_axis_set_property (GObject *obj, guint param_id,
 		}
 		break;
 	}
+	case AXIS_PROP_SPAN_START:
+		if (axis->type != GOG_AXIS_CIRCULAR) {
+			double new_value = g_value_get_double (value);
+			g_return_if_fail (new_value < axis->span_end); 
+			axis->span_start = new_value;
+		}
+		break;
+	case AXIS_PROP_SPAN_END:
+		if (axis->type != GOG_AXIS_CIRCULAR) {
+			double new_value = g_value_get_double (value);
+			g_return_if_fail (new_value > axis->span_start); 
+			axis->span_end = new_value;
+		}
+		break;
 
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
 		 return; /* NOTE : RETURN */
@@ -2109,6 +2141,12 @@ gog_axis_get_property (GObject *obj, guint param_id,
 	case AXIS_PROP_POLAR_UNIT:
 		g_value_set_string (value, polar_units[axis->polar_unit].name);
 		break;
+	case AXIS_PROP_SPAN_START:
+		g_value_set_double (value, axis->span_start);
+		break;
+	case AXIS_PROP_SPAN_END:
+		g_value_set_double (value, axis->span_end);
+		break;
 
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
 		 break;
@@ -2447,6 +2485,24 @@ cb_rotation_changed (GtkSpinButton *spin, GogAxis *axis)
 }
 
 static void
+cb_start_changed (GtkSpinButton *spin, GogAxis *axis)
+{
+	double val = gtk_spin_button_get_value (spin);
+	GtkAdjustment *adj = GTK_ADJUSTMENT (g_object_get_data (G_OBJECT (spin), "other-adj"));
+	gtk_adjustment_set_lower (adj, fmin (val + 1, axis->span_end * 100.));
+	g_object_set (axis, "span-start", val /100., NULL);
+}
+
+static void
+cb_end_changed (GtkSpinButton *spin, GogAxis *axis)
+{
+	double val = gtk_spin_button_get_value (spin);
+	GtkAdjustment *adj = GTK_ADJUSTMENT (g_object_get_data (G_OBJECT (spin), "other-adj"));
+	gtk_adjustment_set_upper (adj, fmax (val - 1, axis->span_start * 100.));
+	g_object_set (axis, "span-end", val /100., NULL);
+}
+
+static void
 gog_axis_populate_editor (GogObject *gobj,
 			  GOEditor *editor,
 			  GogDataAllocator *dalloc,
@@ -2547,6 +2603,28 @@ gog_axis_populate_editor (GogObject *gobj,
 			     go_gtk_builder_get_widget (gui, "axis-pref-grid"),
 			     _("Scale"));
 
+	/* effective area */
+	if (axis->type != GOG_AXIS_CIRCULAR) {
+		GtkAdjustment *adj;
+		double start = axis->span_start * 100., end = axis->span_end * 100.;
+		w = go_gtk_builder_get_widget (gui, "start-btn");
+		adj = GTK_ADJUSTMENT (gtk_builder_get_object (gui, "end-adj"));
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), start);
+		gtk_adjustment_set_lower (adj, fmin (start + 1., end));
+		g_signal_connect (w, "value_changed", G_CALLBACK (cb_start_changed), axis);
+		g_object_set_data (G_OBJECT (w), "other-adj", adj);
+		w = go_gtk_builder_get_widget (gui, "end-btn");
+		adj = GTK_ADJUSTMENT (gtk_builder_get_object (gui, "start-adj"));
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), end);
+		gtk_adjustment_set_upper (adj, fmax (end - 1., start));
+		g_signal_connect (w, "value_changed", G_CALLBACK (cb_end_changed), axis);
+		g_object_set_data (G_OBJECT (w), "other-adj", adj);
+		go_editor_add_page (editor,
+		                    go_gtk_builder_get_widget (gui, "area-grid"),
+		                    _("Span"));
+	}
+
+
 	if (gog_object_is_visible (axis) && gog_axis_get_atype (axis) < GOG_AXIS_VIRTUAL) {
 	    /* Style page */
 	    (GOG_OBJECT_CLASS(parent_klass)->populate_editor) (gobj, editor, dalloc, cc);
@@ -2651,6 +2729,18 @@ gog_axis_class_init (GObjectClass *gobject_klass)
 			_("Polar axis set unit"),
 			polar_units[GOG_AXIS_POLAR_UNIT_DEGREES].name,
 			GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
+	g_object_class_install_property (gobject_klass, AXIS_PROP_SPAN_START,
+		g_param_spec_double ("span-start",
+			_("Axis start position"),
+			_("Position of the plot area at which the axis effective area starts, expressed as a percentage of the available position. Defaults to 0.0"),
+			0., 1., 0.,
+			GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
+	g_object_class_install_property (gobject_klass, AXIS_PROP_SPAN_END,
+		g_param_spec_double ("span-end",
+			_("Axis end position"),
+			_("Position of the plot area at which the axis effective area ends, expressed as a percentage of the available position. Defaults to 1.0"),
+			0., 1., 1.,
+			GSF_PARAM_STATIC | G_PARAM_READWRITE | GO_PARAM_PERSISTENT));
 
 	gog_object_register_roles (gog_klass, roles, G_N_ELEMENTS (roles));
 
@@ -2686,6 +2776,8 @@ gog_axis_init (GogAxis *axis)
 
 	axis->ticks = NULL;
 	axis->tick_nbr = 0;
+	axis->span_start = 0.;
+	axis->span_end = 1.;
 }
 
 static void
@@ -2822,6 +2914,15 @@ gog_axis_set_bounds (GogAxis *axis, double minimum, double maximum)
 	}
 }
 
+void
+gog_axis_get_effective_span (GogAxis const *axis, double *start, double *end)
+{
+	g_return_if_fail (GOG_IS_AXIS (axis));
+
+	*start = axis->span_start;
+	*end = axis->span_end;
+}
+
 /**
  * gog_axis_set_extents :
  * @axis : #GogAxis
diff --git a/goffice/graph/gog-axis.h b/goffice/graph/gog-axis.h
index 8e531ee..f7b001d 100644
--- a/goffice/graph/gog-axis.h
+++ b/goffice/graph/gog-axis.h
@@ -81,6 +81,8 @@ gboolean      gog_axis_get_bounds 	  (GogAxis const *axis,
 void	      gog_axis_set_bounds 	  (GogAxis *axis,
 					   double minimum, double maximum);
 void 	      gog_axis_set_extents 	  (GogAxis *axis, double start, double stop);
+void          gog_axis_get_effective_span (GogAxis const *axis,
+					   double *start, double *end);
 GOFormat     *gog_axis_get_format	  (GogAxis const *axis);
 GOFormat     *gog_axis_get_effective_format (GogAxis const *axis);
 gboolean      gog_axis_set_format	  (GogAxis *axis, GOFormat *fmt);



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