goffice r2098 - in trunk: . goffice/graph pixmaps plugins/plot_boxes plugins/plot_xy



Author: jbrefort
Date: Fri May 30 14:40:51 2008
New Revision: 2098
URL: http://svn.gnome.org/viewvc/goffice?rev=2098&view=rev

Log:
2008-05-30  Jean Brefort  <jean brefort normalesup org>

	* goffice/graph/gog-renderer.c: (_draw_circle),
	(gog_renderer_draw_circle), (gog_renderer_stroke_circle),
	(gog_renderer_fill_circle): new utilities.
	* goffice/graph/gog-renderer.h: ditto.
	* pixmaps/Makefile.am: add new pixmaps for box-plots
	excluding outliers.
	* plugins/plot_boxes/gog-boxplot-prefs.glade: add new 
properties.
	* plugins/plot_boxes/gog-boxplot.c: (cb_outliers_changed),
	(cb_ratio_changed), (gog_box_plot_pref),
	(gog_box_plot_set_property), (gog_box_plot_get_property),
	(gog_box_plot_class_init), (gog_box_plot_init),
	(gog_box_plot_view_render), (gog_box_plot_series_update),
	(gog_box_plot_series_finalize), (gog_box_plot_series_class_init):
	ditto, fixes #534642.
	* plugins/plot_boxes/plot-types.xml.in: new boxplots sub-types.
	* plugins/plot_xy/gog-xy.c: (gog_xy_view_render): use
	gog_renderer_draw_circle for bubbles.



Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/goffice/graph/gog-renderer.c
   trunk/goffice/graph/gog-renderer.h
   trunk/pixmaps/Makefile.am
   trunk/plugins/plot_boxes/gog-boxplot-prefs.glade
   trunk/plugins/plot_boxes/gog-boxplot.c
   trunk/plugins/plot_boxes/plot-types.xml.in
   trunk/plugins/plot_xy/gog-xy.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Fri May 30 14:40:51 2008
@@ -1,3 +1,11 @@
+goffice-0.7.0:
+
+Jean:
+	* New boxplot feature requested: exclude outliers. [#534642]
+	* Moved GOConf code from gnumeric to goffice.
+	* Fixed plot types activation/deactivation issues.
+
+--------------------------------------------------------------------------
 goffice 0.6.3:
 
 Hiroyuki Ikezoe:

Modified: trunk/goffice/graph/gog-renderer.c
==============================================================================
--- trunk/goffice/graph/gog-renderer.c	(original)
+++ trunk/goffice/graph/gog-renderer.c	Fri May 30 14:40:51 2008
@@ -829,6 +829,54 @@
 	grc_draw_path (rend, NULL, path, FALSE);
 }
 
+static void
+_draw_circle (GogRenderer *rend, double x, double y, double r, gboolean fill, gboolean stroke)
+{
+	GogStyle const *style;
+	GOPath *path;
+	gboolean narrow = r < 1.5;
+	double o, o_2;
+
+	g_return_if_fail (IS_GOG_RENDERER (rend));
+	g_return_if_fail (IS_GOG_STYLE (rend->cur_style));
+
+	style = rend->cur_style;
+	narrow |= !gog_style_is_outline_visible (style);
+
+	path = go_path_new ();
+	go_path_set_options (path, GO_PATH_OPTIONS_SHARP);
+
+	if (!narrow) {
+		o = gog_renderer_line_size (rend, style->outline.width);
+		o_2 = o / 2.;
+	} else
+		o = o_2 = 0.;
+
+	go_path_arc (path, x, y, r, r, 0, 2 * M_PI);
+
+	_draw_shape (rend, path, fill, stroke && !narrow);
+
+	go_path_free (path);
+}
+
+void
+gog_renderer_draw_circle (GogRenderer *rend, double x, double y, double r)
+{
+	_draw_circle (rend, x, y, r, TRUE, TRUE);
+}
+
+void
+gog_renderer_stroke_circle (GogRenderer *rend, double x, double y, double r)
+{
+	_draw_circle (rend, x, y, r, FALSE, TRUE);
+}
+
+void
+gog_renderer_fill_circle (GogRenderer *rend, double x, double y, double r)
+{
+	_draw_circle (rend, x, y, r, TRUE, FALSE);
+}
+
 /**
  * gog_renderer_draw_rectangle:
  * @rend: a #GogRenderer

Modified: trunk/goffice/graph/gog-renderer.h
==============================================================================
--- trunk/goffice/graph/gog-renderer.h	(original)
+++ trunk/goffice/graph/gog-renderer.h	Fri May 30 14:40:51 2008
@@ -101,6 +101,10 @@
 void  gog_renderer_stroke_shape		(GogRenderer *renderer, GOPath const *path);
 void  gog_renderer_fill_shape 		(GogRenderer *renderer, GOPath const *path);
 
+void  gog_renderer_draw_circle		(GogRenderer *rend, double x, double y, double r);
+void  gog_renderer_stroke_circle 	(GogRenderer *rend, double x, double y, double r);
+void  gog_renderer_fill_circle	 	(GogRenderer *rend, double x, double y, double r);
+
 void  gog_renderer_draw_rectangle	(GogRenderer *rend, GogViewAllocation const *rect);
 void  gog_renderer_stroke_rectangle 	(GogRenderer *rend, GogViewAllocation const *rect);
 void  gog_renderer_fill_rectangle 	(GogRenderer *rend, GogViewAllocation const *rect);

Modified: trunk/pixmaps/Makefile.am
==============================================================================
--- trunk/pixmaps/Makefile.am	(original)
+++ trunk/pixmaps/Makefile.am	Fri May 30 14:40:51 2008
@@ -35,6 +35,7 @@
 	chart_colored_1_1.png \
 	chart_contour_1_1.png \
 	chart_boxplot_1_1.png	chart_boxplot_1_2.png \
+	chart_boxplot_2_1.png	chart_boxplot_2_2.png \
 	chart_dropbar_1_1.png	chart_dropbar_1_2.png \
 	chart_minmax_1_1.png	chart_minmax_1_2.png \
 	chart_minmax_2_1.png	chart_minmax_2_2.png \

Modified: trunk/plugins/plot_boxes/gog-boxplot-prefs.glade
==============================================================================
--- trunk/plugins/plot_boxes/gog-boxplot-prefs.glade	(original)
+++ trunk/plugins/plot_boxes/gog-boxplot-prefs.glade	Fri May 30 14:40:51 2008
@@ -1,160 +1,156 @@
-<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd";>
-
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
 <glade-interface>
-
-<widget class="GtkWindow" id="window1">
-  <property name="title" translatable="yes">window1</property>
-  <property name="type">GTK_WINDOW_TOPLEVEL</property>
-  <property name="window_position">GTK_WIN_POS_NONE</property>
-  <property name="modal">False</property>
-  <property name="resizable">True</property>
-  <property name="destroy_with_parent">False</property>
-  <property name="decorated">True</property>
-  <property name="skip_taskbar_hint">False</property>
-  <property name="skip_pager_hint">False</property>
-  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
-  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
-  <property name="focus_on_map">True</property>
-  <property name="urgency_hint">False</property>
-
-  <child>
-    <widget class="GtkTable" id="gog_box_plot_prefs">
-      <property name="border_width">12</property>
-      <property name="visible">True</property>
-      <property name="n_rows">2</property>
-      <property name="n_columns">3</property>
-      <property name="homogeneous">False</property>
-      <property name="row_spacing">6</property>
-      <property name="column_spacing">12</property>
-
-      <child>
-	<widget class="GtkLabel" id="label1">
-	  <property name="visible">True</property>
-	  <property name="label" translatable="yes">_Gap:</property>
-	  <property name="use_underline">True</property>
-	  <property name="use_markup">False</property>
-	  <property name="justify">GTK_JUSTIFY_LEFT</property>
-	  <property name="wrap">False</property>
-	  <property name="selectable">False</property>
-	  <property name="xalign">0</property>
-	  <property name="yalign">0</property>
-	  <property name="xpad">0</property>
-	  <property name="ypad">0</property>
-	  <property name="mnemonic_widget">gap_spinner</property>
-	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-	  <property name="width_chars">-1</property>
-	  <property name="single_line_mode">False</property>
-	  <property name="angle">0</property>
-	</widget>
-	<packing>
-	  <property name="left_attach">0</property>
-	  <property name="right_attach">1</property>
-	  <property name="top_attach">0</property>
-	  <property name="bottom_attach">1</property>
-	  <property name="x_options">fill</property>
-	  <property name="y_options"></property>
-	</packing>
-      </child>
-
-      <child>
-	<widget class="GtkLabel" id="label2">
-	  <property name="visible">True</property>
-	  <property name="label" translatable="yes">%</property>
-	  <property name="use_underline">False</property>
-	  <property name="use_markup">False</property>
-	  <property name="justify">GTK_JUSTIFY_LEFT</property>
-	  <property name="wrap">False</property>
-	  <property name="selectable">False</property>
-	  <property name="xalign">0</property>
-	  <property name="yalign">0.5</property>
-	  <property name="xpad">0</property>
-	  <property name="ypad">0</property>
-	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-	  <property name="width_chars">-1</property>
-	  <property name="single_line_mode">False</property>
-	  <property name="angle">0</property>
-	</widget>
-	<packing>
-	  <property name="left_attach">2</property>
-	  <property name="right_attach">3</property>
-	  <property name="top_attach">0</property>
-	  <property name="bottom_attach">1</property>
-	  <property name="x_options">fill</property>
-	  <property name="y_options"></property>
-	</packing>
-      </child>
-
-      <child>
-	<widget class="GtkSpinButton" id="gap_spinner">
-	  <property name="visible">True</property>
-	  <property name="tooltip" translatable="yes">Separation between groups as a percentage of bar/col width</property>
-	  <property name="can_focus">True</property>
-	  <property name="climb_rate">10</property>
-	  <property name="digits">0</property>
-	  <property name="numeric">True</property>
-	  <property name="update_policy">GTK_UPDATE_ALWAYS</property>
-	  <property name="snap_to_ticks">True</property>
-	  <property name="wrap">False</property>
-	  <property name="adjustment">0 0 500 10 10 10</property>
-	</widget>
-	<packing>
-	  <property name="left_attach">1</property>
-	  <property name="right_attach">2</property>
-	  <property name="top_attach">0</property>
-	  <property name="bottom_attach">1</property>
-	  <property name="x_options">fill</property>
-	  <property name="y_options"></property>
-	</packing>
-      </child>
-
-      <child>
-	<widget class="GtkLabel" id="layout-lbl">
-	  <property name="visible">True</property>
-	  <property name="label" translatable="yes">_Layout</property>
-	  <property name="use_underline">True</property>
-	  <property name="use_markup">False</property>
-	  <property name="justify">GTK_JUSTIFY_LEFT</property>
-	  <property name="wrap">False</property>
-	  <property name="selectable">False</property>
-	  <property name="xalign">0</property>
-	  <property name="yalign">0.5</property>
-	  <property name="xpad">0</property>
-	  <property name="ypad">0</property>
-	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-	  <property name="width_chars">-1</property>
-	  <property name="single_line_mode">False</property>
-	  <property name="angle">0</property>
-	</widget>
-	<packing>
-	  <property name="left_attach">0</property>
-	  <property name="right_attach">1</property>
-	  <property name="top_attach">1</property>
-	  <property name="bottom_attach">2</property>
-	  <property name="x_options">fill</property>
-	  <property name="y_options"></property>
-	</packing>
-      </child>
-
-      <child>
-	<widget class="GtkComboBox" id="layout">
-	  <property name="visible">True</property>
-	  <property name="items" translatable="yes">Horizontal
+  <widget class="GtkWindow" id="window1">
+    <property name="title" translatable="yes">window1</property>
+    <child>
+      <widget class="GtkTable" id="gog_box_plot_prefs">
+        <property name="visible">True</property>
+        <property name="border_width">12</property>
+        <property name="n_rows">4</property>
+        <property name="n_columns">3</property>
+        <property name="column_spacing">12</property>
+        <property name="row_spacing">6</property>
+        <child>
+          <widget class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="yalign">0</property>
+            <property name="label" translatable="yes">_Gap:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">gap_spinner</property>
+          </widget>
+          <packing>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="label2">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">%</property>
+          </widget>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="right_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkSpinButton" id="gap_spinner">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="tooltip" translatable="yes">Separation between groups as a percentage of bar/col width</property>
+            <property name="adjustment">0 0 500 10 10 10</property>
+            <property name="climb_rate">10</property>
+            <property name="snap_to_ticks">True</property>
+            <property name="numeric">True</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="layout-lbl">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Layout</property>
+            <property name="use_underline">True</property>
+          </widget>
+          <packing>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkComboBox" id="layout">
+            <property name="visible">True</property>
+            <property name="items" translatable="yes">Horizontal
 Vertical</property>
-	  <property name="add_tearoffs">False</property>
-	  <property name="focus_on_click">True</property>
-	</widget>
-	<packing>
-	  <property name="left_attach">1</property>
-	  <property name="right_attach">3</property>
-	  <property name="top_attach">1</property>
-	  <property name="bottom_attach">2</property>
-	  <property name="x_options">fill</property>
-	  <property name="y_options">fill</property>
-	</packing>
-      </child>
-    </widget>
-  </child>
-</widget>
-
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">3</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options">GTK_FILL</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkCheckButton" id="show-outliers">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="label" translatable="yes">_Exclude and show outliers</property>
+            <property name="use_underline">True</property>
+            <property name="response_id">0</property>
+            <property name="draw_indicator">True</property>
+          </widget>
+          <packing>
+            <property name="right_attach">3</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="diameter-label">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Diameter/width:</property>
+            <property name="use_underline">True</property>
+            <property name="justify">GTK_JUSTIFY_RIGHT</property>
+            <property name="wrap_mode">PANGO_WRAP_WORD_CHAR</property>
+          </widget>
+          <packing>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkSpinButton" id="diameter">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="has_tooltip">True</property>
+            <property name="tooltip_text">Ratio of the diameter of the circles representing outliers versus the rectangle width.</property>
+            <property name="adjustment">25 0 50 1 10 10</property>
+          </widget>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkLabel" id="diam-pc-label">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">%</property>
+          </widget>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="right_attach">3</property>
+            <property name="top_attach">3</property>
+            <property name="bottom_attach">4</property>
+            <property name="x_options">GTK_FILL</property>
+            <property name="y_options"></property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>

Modified: trunk/plugins/plot_boxes/gog-boxplot.c
==============================================================================
--- trunk/plugins/plot_boxes/gog-boxplot.c	(original)
+++ trunk/plugins/plot_boxes/gog-boxplot.c	Fri May 30 14:40:51 2008
@@ -31,6 +31,7 @@
 #include <goffice/data/go-data-simple.h>
 #include <goffice/math/go-rangefunc.h>
 #include <goffice/math/go-math.h>
+#include <goffice/utils/go-marker.h>
 #include <goffice/app/module-plugin-defs.h>
 
 #include <glib/gi18n-lib.h>
@@ -45,8 +46,9 @@
 	unsigned  num_series;
 	double min, max;
 	int gap_percentage;
-	gboolean vertical;
+	gboolean vertical, outliers;
 	char const **names;
+	double radius_ratio;
 };
 
 static GogObjectClass *gog_box_plot_parent_klass;
@@ -58,6 +60,7 @@
 #include <glade/glade-xml.h>
 #include <gtk/gtkcombobox.h>
 #include <gtk/gtkspinbutton.h>
+#include <gtk/gtktogglebutton.h>
 #include <gtk/gtkenums.h>
 
 static void
@@ -72,6 +75,36 @@
 	g_object_set (boxplot, "vertical", gtk_combo_box_get_active (box), NULL);
 }
 
+static void
+cb_outliers_changed (GtkToggleButton *btn, GObject *boxplot)
+{
+	GladeXML *gui = GLADE_XML (g_object_get_data (G_OBJECT (btn), "state"));
+	GtkWidget *w;
+	gboolean outliers = gtk_toggle_button_get_active (btn);
+	if (outliers) {
+		w = glade_xml_get_widget (gui, "diameter-label");
+		gtk_widget_show (w);
+		w = glade_xml_get_widget (gui, "diameter");
+		gtk_widget_show (w);
+		w = glade_xml_get_widget (gui, "diam-pc-label");
+		gtk_widget_show (w);
+	} else {
+		w = glade_xml_get_widget (gui, "diameter-label");
+		gtk_widget_hide (w);
+		w = glade_xml_get_widget (gui, "diameter");
+		gtk_widget_hide (w);
+		w = glade_xml_get_widget (gui, "diam-pc-label");
+		gtk_widget_hide (w);
+	}
+	g_object_set (boxplot, "outliers", outliers, NULL);
+}
+
+static void
+cb_ratio_changed (GtkAdjustment *adj, GObject *boxplot)
+{
+	g_object_set (boxplot, "radius-ratio", adj->value / 200., NULL);
+}
+
 static gpointer
 gog_box_plot_pref (GogObject *obj,
 		   GogDataAllocator *dalloc, GOCmdContext *cc)
@@ -97,6 +130,25 @@
 	gtk_combo_box_set_active (GTK_COMBO_BOX (w), boxplot->vertical);
 	g_signal_connect (w, "changed", G_CALLBACK (cb_layout_changed), boxplot);
 
+	w = glade_xml_get_widget (gui, "show-outliers");
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), boxplot->outliers);
+	g_object_set_data (G_OBJECT (w), "state", gui);
+	g_signal_connect (w, "toggled", G_CALLBACK (cb_outliers_changed), boxplot);
+
+	w = glade_xml_get_widget (gui, "diameter");
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (w), boxplot->radius_ratio * 200.);
+	g_signal_connect (G_OBJECT (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (w))),
+		"value_changed",
+		G_CALLBACK (cb_ratio_changed), boxplot);
+
+	if (!boxplot->outliers) {
+		gtk_widget_hide (w);
+		w = glade_xml_get_widget (gui, "diameter-label");
+		gtk_widget_hide (w);
+		w = glade_xml_get_widget (gui, "diam-pc-label");
+		gtk_widget_hide (w);
+	}
+
 	w = glade_xml_get_widget (gui, "gog_box_plot_prefs");
 	g_object_set_data_full (G_OBJECT (w),
 		"state", gui, (GDestroyNotify)g_object_unref);
@@ -120,12 +172,16 @@
 	BOX_PLOT_PROP_0,
 	BOX_PLOT_PROP_GAP_PERCENTAGE,
 	BOX_PLOT_PROP_VERTICAL,
+	BOX_PLOT_PROP_OUTLIERS,
+	BOX_PLOT_PROP_RADIUS_RATIO,
 };
 
 typedef struct {
 	GogSeries base;
 	int	 gap_percentage;
 	double vals[5];
+	double *svals; //sorted data
+	int nb_valid;
 } GogBoxPlotSeries;
 typedef GogSeriesClass GogBoxPlotSeriesClass;
 
@@ -161,8 +217,14 @@
 		if (boxplot->base.axis[1])
 			gog_axis_bound_changed (boxplot->base.axis[1], GOG_OBJECT (boxplot));
 		break;
+	case BOX_PLOT_PROP_OUTLIERS:
+		boxplot->outliers = g_value_get_boolean (value);
+		break;
+	case BOX_PLOT_PROP_RADIUS_RATIO:
+		boxplot->radius_ratio = g_value_get_double (value);
+		break;
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
-		 return; /* NOTE : RETURN */
+		return; /* NOTE : RETURN */
 	}
 	gog_object_emit_changed (GOG_OBJECT (obj), TRUE);
 }
@@ -180,8 +242,14 @@
 	case BOX_PLOT_PROP_VERTICAL:
 		g_value_set_boolean (value, boxplot->vertical);
 		break;
+	case BOX_PLOT_PROP_OUTLIERS:
+		g_value_set_boolean (value, boxplot->outliers);
+		break;
+	case BOX_PLOT_PROP_RADIUS_RATIO:
+		g_value_set_double (value, boxplot->radius_ratio);
+		break;
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
-		 break;
+		break;
 	}
 }
 
@@ -302,6 +370,18 @@
 			_("Whether the box-plot should be vertical instead of horizontal"),
 			FALSE, 
 			GSF_PARAM_STATIC | G_PARAM_READWRITE | GOG_PARAM_PERSISTENT));
+	g_object_class_install_property (gobject_klass, BOX_PLOT_PROP_OUTLIERS,
+		g_param_spec_boolean ("outliers", 
+			_("Outliers"),
+			_("Whether outliers should be taken into account and displayed"),
+			FALSE, 
+			GSF_PARAM_STATIC | G_PARAM_READWRITE | GOG_PARAM_PERSISTENT));
+	g_object_class_install_property (gobject_klass, BOX_PLOT_PROP_RADIUS_RATIO,
+		g_param_spec_double ("radius-ratio", 
+			_("Radius ratio"),
+			_("The ratio between the radius of the circles representing outliers and the rectangls widths"),
+			0., 0.5, 0.125, 
+			GSF_PARAM_STATIC | G_PARAM_READWRITE | GOG_PARAM_PERSISTENT));
 
 	gog_object_klass->type_name	= gog_box_plot_type_name;
 	gog_object_klass->view_type	= gog_box_plot_view_get_type ();
@@ -330,6 +410,7 @@
 gog_box_plot_init (GogBoxPlot *model)
 {
 	model->gap_percentage = 150;
+	model->radius_ratio = 0.125;
 }
 
 GSF_DYNAMIC_CLASS (GogBoxPlot, gog_box_plot,
@@ -394,14 +475,62 @@
 		if (!gog_series_is_valid (GOG_SERIES (series)) ||
 			!go_data_vector_get_len (GO_DATA_VECTOR (series->base.values[0].data)))
 			continue;
-		style = GOG_STYLED_OBJECT (series)->style;
+		style = gog_style_dup (GOG_STYLED_OBJECT (series)->style);
+		y = gog_axis_map_to_view (ser_map, num_ser);
 		gog_renderer_push_style (view->renderer, style);
-		min = gog_axis_map_to_view (map, series->vals[0]);
+		if (model->outliers) {
+			double l1, l2, m1, m2, d, r = 2. * hrect * model->radius_ratio;
+			int i = 0;
+		    	style->outline = style->line;
+			d = series->vals[3] - series->vals[1];
+			l1 = series->vals[1] - d * 1.5;
+			l2 = series->vals[1] - d * 3.;
+			m1 = series->vals[3] + d * 1.5;
+			m2 = series->vals[3] + d * 3.;
+			while (series->svals[i] < l1) {
+				/* display the outlier as a mark */
+				d = gog_axis_map_to_view (map, series->svals[i]);
+				if (model->vertical) {
+					if (series->svals[i] < l2)
+						gog_renderer_stroke_circle (view->renderer, y, d, r);
+					else
+						gog_renderer_draw_circle (view->renderer, y, d, r);
+				} else {
+					if (series->svals[i] < l2)
+						gog_renderer_stroke_circle (view->renderer, d, y, r);
+					else
+						gog_renderer_draw_circle (view->renderer, d, y, r);
+				}
+				i++;
+			}
+			min = series->svals[i];
+			i = series->nb_valid - 1;
+			while (series->svals[i] > m1) {
+				/* display the outlier as a mark */
+				d = gog_axis_map_to_view (map, series->svals[i]);
+				if (model->vertical) {
+					if (series->svals[i] > m2)
+						gog_renderer_stroke_circle (view->renderer, y, d, r);
+					else
+						gog_renderer_draw_circle (view->renderer, y, d, r);
+				} else {
+					if (series->svals[i] > m2)
+						gog_renderer_stroke_circle (view->renderer, d, y, r);
+					else
+						gog_renderer_draw_circle (view->renderer, d, y, r);
+				}
+				i--;
+			}
+			max = series->svals[i];
+		} else {
+			min = series->vals[0];
+			max = series->vals[4];
+		}
+		min = gog_axis_map_to_view (map, min);
 		qu1 = gog_axis_map_to_view (map, series->vals[1]);
 		med = gog_axis_map_to_view (map, series->vals[2]);
 		qu3 = gog_axis_map_to_view (map, series->vals[3]);
-		max = gog_axis_map_to_view (map, series->vals[4]);
-		y = gog_axis_map_to_view (ser_map, num_ser);
+		max = gog_axis_map_to_view (map, max);
 		if (model->vertical) {
 			path[2].code = ART_LINETO;
 			path[0].y = path[3].y = path[4].y = qu1;
@@ -463,6 +592,7 @@
 		}
 		gog_renderer_draw_sharp_path (view->renderer, path);
 		gog_renderer_pop_style (view->renderer);
+		g_object_unref (style);
 		num_ser++;
 	}
 	gog_chart_map_free (chart_map);
@@ -491,6 +621,9 @@
 	GogBoxPlotSeries *series = GOG_BOX_PLOT_SERIES (obj);
 	unsigned old_num = series->base.num_elements;
 
+	g_free (series->svals);
+	series->svals = NULL;
+
 	if (series->base.values[0].data != NULL) {
 		vals = go_data_vector_get_values (GO_DATA_VECTOR (series->base.values[0].data));
 		len = go_data_vector_get_len 
@@ -498,15 +631,16 @@
 	}
 	series->base.num_elements = len;
 	if (len > 0) {
-		double *svals = g_new (double, len), x;
+		double x;
 		int n, max = 0;
+		series->svals = g_new (double, len);
 		for (n = 0; n < len; n++)
 			if (go_finite (vals[n]))
-				svals[max++] = vals[n];
-		go_range_fractile_inter_nonconst (svals, max, &series->vals[0], 0);
+				series->svals[max++] = vals[n];
+		go_range_fractile_inter_nonconst (series->svals, max, &series->vals[0], 0);
 		for (x = 0.25,n = 1; n < 5; n++, x+= 0.25)
-			go_range_fractile_inter_sorted (svals, max, &series->vals[n], x);
-		g_free (svals);
+			go_range_fractile_inter_sorted (series->svals, max, &series->vals[n], x);
+		series->nb_valid = max;
 	}
 	/* queue plot for redraw */
 	gog_object_request_update (GOG_OBJECT (series->base.plot));
@@ -526,11 +660,20 @@
 }
 
 static void
+gog_box_plot_series_finalize (GObject *obj)
+{
+	g_free (GOG_BOX_PLOT_SERIES (obj)->svals);
+	((GObjectClass *) gog_box_plot_series_parent_klass)->finalize (obj);
+}
+
+static void
 gog_box_plot_series_class_init (GogObjectClass *obj_klass)
 {
+	GObjectClass *object_class = (GObjectClass *) obj_klass;
 	GogStyledObjectClass *gso_klass = (GogStyledObjectClass*) obj_klass;
 
 	gog_box_plot_series_parent_klass = g_type_class_peek_parent (obj_klass);
+	object_class->finalize = gog_box_plot_series_finalize;
 	obj_klass->update = gog_box_plot_series_update;
 	gso_klass->init_style = gog_box_plot_series_init_style;
 }

Modified: trunk/plugins/plot_boxes/plot-types.xml.in
==============================================================================
--- trunk/plugins/plot_boxes/plot-types.xml.in	(original)
+++ trunk/plugins/plot_boxes/plot-types.xml.in	Fri May 30 14:40:51 2008
@@ -15,6 +15,21 @@
 		<property name="vertical">true</property>
 		<property name="guru-hints">backplane</property>
 	</Type>
+	<Type _name="HBoxPlotOutliers" row="2" col="1"
+		engine="GogBoxPlot" family="BoxPlot"
+		_description="Horizontal Box-Plot showing outliers."
+		sample_image_file="chart_boxplot_2_1.png">
+		<property name="outliers">true</property>
+		<property name="guru-hints">backplane</property>
+	</Type>
+	<Type _name="VBoxPlotOutliers" row="2" col="2"
+		engine="GogBoxPlot" family="BoxPlot"
+		_description="Vertical Box-Plot showing outliers."
+		sample_image_file="chart_boxplot_2_2.png">
+		<property name="outliers">true</property>
+		<property name="vertical">true</property>
+		<property name="guru-hints">backplane</property>
+	</Type>
 	<Family _name="Histogram"	sample_image_file="hist.xpm" axis_set="xy"/>
 	<Type _name="Histogram" row="1" col="1"
 		engine="GogHistogramPlot" family="Histogram"

Modified: trunk/plugins/plot_xy/gog-xy.c
==============================================================================
--- trunk/plugins/plot_xy/gog-xy.c	(original)
+++ trunk/plugins/plot_xy/gog-xy.c	Fri May 30 14:40:51 2008
@@ -831,19 +831,6 @@
 typedef GogPlotView		GogXYView;
 typedef GogPlotViewClass	GogXYViewClass;
 
-#define MAX_ARC_SEGMENTS 64
-
-static void
-bubble_draw_circle (GogView *view, double x, double y, double radius)
-{
-	GOPath *path;
-
-	path = go_path_new ();
-	go_path_pie_wedge (path, x, y, radius, radius, 0, 2 * M_PI);
-	gog_renderer_draw_shape (view->renderer, path);
-	go_path_free (path);
-}
-
 static GOColor
 get_map_color (double z, gboolean hide_outliers)
 {
@@ -1110,7 +1097,7 @@
 				if (z < 0) {
 					if (GOG_BUBBLE_PLOT(model)->show_negatives) {
 						gog_renderer_push_style (view->renderer, neg_style);
-						bubble_draw_circle (view, x_canvas, y_canvas, 
+						gog_renderer_draw_circle (view->renderer, x_canvas, y_canvas, 
 								    ((size_as_area) ? 
 								     sqrt (- z / zmax) :
 								    - z / zmax) * rmax);
@@ -1120,7 +1107,7 @@
 					if (model->base.vary_style_by_element)
 						gog_theme_fillin_style (theme, style, GOG_OBJECT (series),
 									model->base.index_num + i - 1, FALSE);
-					bubble_draw_circle (view, x_canvas, y_canvas, 
+					gog_renderer_draw_circle (view->renderer, x_canvas, y_canvas, 
 							    ((size_as_area) ?
 							    sqrt (z / zmax) :
 							    z / zmax) * rmax);



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