[goffice] Support SI units in scientific format selector.



commit de72126beb1741ed49a9947d9a827be00bf01e76
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date:   Sat Sep 3 02:33:22 2011 -0600

    Support SI units  in scientific format selector.
    
    2011-09-03  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* goffice/gtk/go-format-sel.ui: new widgets
    	* goffice/gtk/go-format-sel.c (_GOFormatSel): new fields
    	(load_si_combo): new
    	(cb_si_toggle): enable/disable new widgets
    	(cb_si_unit_toggle): new
    	(cb_si_combo_changed): new
    	(fmt_dialog_enable_widgets): handle new widgets
    	(nfs_init): ditto
    	(go_format_sel_finalize): finalize details
    	* goffice/utils/go-format.h (go_format_details_finalize): new
    	and add new fields
    	* goffice/utils/go-format.c (go_format_generate_scientific_str):
    	use new fields
    	(go_format_details_finalize): new
    	(go_format_details_free): use go_format_details_finalize
    	(go_format_get_details): consider new fields

 ChangeLog                    |   19 ++++
 NEWS                         |    2 +-
 goffice/gtk/go-format-sel.c  |  199 ++++++++++++++++++++++++++++++++++++++++-
 goffice/gtk/go-format-sel.ui |   84 +++++++++++++++++-
 goffice/utils/go-format.c    |   35 +++++++-
 goffice/utils/go-format.h    |    3 +
 6 files changed, 329 insertions(+), 13 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 075a109..aec29b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2011-09-03  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* goffice/gtk/go-format-sel.ui: new widgets
+	* goffice/gtk/go-format-sel.c (_GOFormatSel): new fields
+	(load_si_combo): new
+	(cb_si_toggle): enable/disable new widgets
+	(cb_si_unit_toggle): new
+	(cb_si_combo_changed): new
+	(fmt_dialog_enable_widgets): handle new widgets
+	(nfs_init): ditto
+	(go_format_sel_finalize): finalize details
+	* goffice/utils/go-format.h (go_format_details_finalize): new
+	and add new fields
+	* goffice/utils/go-format.c (go_format_generate_scientific_str):
+	use new fields
+	(go_format_details_finalize): new
+	(go_format_details_free): use go_format_details_finalize
+	(go_format_get_details): consider new fields
+
 2011-09-02  Jean Brefort  <jean brefort normalesup org>
 
 	* goffice/graph/gog-axis.c: use data format for discrete axis. [#641901]
diff --git a/NEWS b/NEWS
index 81d3454..897710f 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Andreas:
 	* Extend encoding specification from file-openers to plugin services.
 	* Improve the scientific number formats selector. [#657187][#623847]
 	* Improve fraction format selector. [#117215]
-	* Support SI prefixes in scientific format selector. [#588516]
+	* Support SI prefixes and units  in scientific format selector. [#588516]
 
 Jean:
 	* Port to gtk+-3.0.
diff --git a/goffice/gtk/go-format-sel.c b/goffice/gtk/go-format-sel.c
index 7945848..a18712e 100644
--- a/goffice/gtk/go-format-sel.c
+++ b/goffice/gtk/go-format-sel.c
@@ -93,7 +93,8 @@ typedef enum {
 	F_LIST_LABEL,		F_LIST_SCROLL,		F_LIST,
 	F_DECIMAL_SPIN,		F_ENGINEERING_BUTTON,
 	F_SUPERSCRIPT_BUTTON,	F_SUPERSCRIPT_HIDE_1_BUTTON,
-	F_SI_BUTTON,
+	F_SI_BUTTON,            F_SI_CUSTOM_UNIT_BUTTON,
+	F_SI_SI_UNIT_BUTTON,	F_SI_UNIT_COMBO,
 	F_EXP_DIGITS,           F_EXP_DIGITS_LABEL,
 	F_NEGATIVE_LABEL,	F_NEGATIVE_SCROLL,	F_NEGATIVE,
 	F_DECIMAL_LABEL,	F_CODE_LABEL,
@@ -152,6 +153,8 @@ struct  _GOFormatSel {
 		GOFormat const	*spec;
 		gint		current_type;
 
+		char *default_si_unit;
+
 		GOFormatDetails details;
 	} format;
 };
@@ -293,6 +296,65 @@ fillin_negative_samples (GOFormatSel *gfs)
 	END_LOCALE_SWITCH;
 }
 
+static struct {
+	char const *name;
+	char const * unit;
+	int scale;
+} si_units[] = {
+	{N_("A (ampere)"), "A", 0},
+	{N_("Bq (becquerel)"), "Bq", 0},
+	{N_("cd (candela)"), "cd", 0},
+	{N_("C (coulomb)"), "C", 0},
+	{N_("\302\260C (degree Celsius)"), "\302\260C", 0},
+	{N_("F (farad)"), "F", 0},
+	{N_("Gy (gray)"), "Gy", 0},
+	{N_("H (henry)"), "H", 0},
+	{N_("Hz (hertz)"), "Hz", 0},
+	{N_("J (joule)"), "J", 0},
+	{N_("K (kelvin)"), "K", 0},
+	{N_("kg (kilogram)"), "kg", 3},
+	{N_("lm (lumen)"), "lm", 0},
+	{N_("lx (lux)"), "lx", 0},
+	{N_("m (meter)"), "m", 0},
+	{N_("mol (mole)"), "mol", 0},
+	{N_("N (newton)"), "N", 0},
+	{N_("\316\251 (ohm)"), "\316\251", 0},
+	{N_("Pa (pascal)"), "Pa", 0},
+	{N_("rad (radian)"), "rad", 0},
+	{N_("s (second)"), "s", 0},
+	{N_("S (siemens)"), "S", 0},
+	{N_("sr (steradian)"), "sr", 0},
+	{N_("Sv (sievert)"), "Sv", 0},
+	{N_("T (tesla)"), "T", 0},
+	{N_("kat (katal)"), "kat", 0},
+	{N_("V (volt)"), "V", 0},
+	{N_("W (watt)"), "W", 0},
+	{N_("Wb (weber)"), "Wb", 0}
+};
+
+static void
+load_si_combo (GtkWidget *w, GOFormatSel *gfs)
+{
+	GtkComboBox *c = GTK_COMBO_BOX (w);
+	GtkListStore *store = GTK_LIST_STORE (gtk_combo_box_get_model (c));
+	guint i;
+	GtkCellRenderer  *cell;
+
+	for (i = 0; i < G_N_ELEMENTS (si_units); i++)
+		gtk_list_store_insert_with_values 
+			(store, NULL, i,
+			 0, _(si_units[i].name),
+			 1, si_units[i].unit,
+			 2, si_units[i].scale,
+			 -1);
+	cell = gtk_cell_renderer_text_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(c), cell, TRUE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(c), cell, "text", 
+				       0, NULL);
+	gtk_combo_box_set_id_column (c, 1);
+}
+
+
 static void
 cb_decimals_changed (GtkSpinButton *spin, GOFormatSel *gfs)
 {
@@ -387,13 +449,51 @@ cb_engineering_toggle (GtkWidget *w, GOFormatSel *gfs)
 static void
 cb_si_toggle (GtkWidget *w, GOFormatSel *gfs)
 {
-	gfs->format.details.append_SI =
-		gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+	gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+
+	gfs->format.details.append_SI = active;
+
+	gtk_widget_set_sensitive (gfs->format.widget[F_SI_CUSTOM_UNIT_BUTTON],
+				  active);
+	gtk_widget_set_sensitive (gfs->format.widget[F_SI_SI_UNIT_BUTTON],
+				  active);
+	gtk_widget_set_sensitive (gfs->format.widget[F_SI_UNIT_COMBO],
+				  active);
 
 	draw_format_preview (gfs, TRUE);
 }
 
 static void
+cb_si_unit_toggle (GtkWidget *w, GOFormatSel *gfs)
+{
+	g_free (gfs->format.details.appended_SI_unit);
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) {
+		GtkComboBox *c = GTK_COMBO_BOX (gfs->format.widget[F_SI_UNIT_COMBO]);
+		GtkTreeIter iter;
+		GtkTreeModel *store = gtk_combo_box_get_model (c);
+		if (gtk_combo_box_get_active_iter (c, &iter)) {
+			gtk_tree_model_get (store, &iter, 1, &gfs->format.details.appended_SI_unit,
+					    2, &gfs->format.details.scale, -1);
+			if (gfs->format.details.scale == 3) {
+				char *text = gfs->format.details.appended_SI_unit;
+				gfs->format.details.appended_SI_unit = g_strdup (text + 1);
+				g_free (text);
+			}
+		} else
+			gfs->format.details.appended_SI_unit = NULL;
+	} else
+		gfs->format.details.appended_SI_unit = g_strdup (gfs->format.default_si_unit);
+
+	draw_format_preview (gfs, TRUE);
+}
+
+static void
+cb_si_combo_changed (GtkWidget *w, GOFormatSel *gfs)
+{
+	cb_si_unit_toggle (gfs->format.widget[F_SI_SI_UNIT_BUTTON], gfs);
+}
+
+static void
 cb_superscript_toggle (GtkWidget *w, GOFormatSel *gfs)
 {
 	gfs->format.details.use_markup =
@@ -617,6 +717,9 @@ fmt_dialog_enable_widgets (GOFormatSel *gfs, int page)
 			F_EXP_DIGITS_LABEL,
 #ifdef ALLOW_SI_APPEND
 			F_SI_BUTTON,
+			F_SI_CUSTOM_UNIT_BUTTON,
+			F_SI_SI_UNIT_BUTTON,
+			F_SI_UNIT_COMBO,
 #endif
 			F_MAX_WIDGET
 		},
@@ -787,15 +890,86 @@ stays:
 			break;
 
 		case F_SI_BUTTON:
-			gtk_toggle_button_set_active 
 #ifdef ALLOW_SI_APPEND
+			gtk_toggle_button_set_active 
 				(GTK_TOGGLE_BUTTON (w),
 				 gfs->format.details.append_SI);
 #else
+			gtk_toggle_button_set_active 
 				(GTK_TOGGLE_BUTTON (w), FALSE);
+			show_widget = FALSE;
 #endif
 			break;
 
+		case F_SI_CUSTOM_UNIT_BUTTON:
+#ifdef ALLOW_SI_APPEND
+			/* This is set through F_SI_UNIT_COMBO */
+#else
+				show_widget = FALSE;
+#endif
+			break;
+
+		case F_SI_SI_UNIT_BUTTON:
+#ifdef ALLOW_SI_APPEND
+			/* This is set through F_SI_UNIT_COMBO */
+#else
+				show_widget = FALSE;
+#endif
+			break;
+
+		case F_SI_UNIT_COMBO: {
+#ifdef ALLOW_SI_APPEND
+			gint row = -1;
+			guint ii;
+
+			if (gfs->format.details.appended_SI_unit != NULL) {
+				char const *unit = gfs->format.details.appended_SI_unit;
+				if (unit[0] == 'g' && unit[1] == 0)
+					unit = "kg";
+				for (ii = 0; ii < G_N_ELEMENTS (si_units); ii++) 
+					if (0 == strcmp (si_units[ii].unit, unit)) {
+						row = (gint)ii;
+						break;
+					}
+			}
+					
+			if (row == -1) {
+				if (gfs->format.details.appended_SI_unit == NULL) {
+					gtk_button_set_label 
+						(GTK_BUTTON (gfs->format.widget[F_SI_CUSTOM_UNIT_BUTTON]),
+						 _("Append no further unit."));
+					g_free (gfs->format.default_si_unit);
+					gfs->format.default_si_unit = NULL;
+				} else {
+					gchar *label;
+					gfs->format.default_si_unit 
+						= g_strdup (gfs->format.details.appended_SI_unit);
+					label = g_strdup_printf (_("Append \'%s\'."), 
+								 gfs->format.default_si_unit);
+					gtk_button_set_label 
+						(GTK_BUTTON (gfs->format.widget[F_SI_CUSTOM_UNIT_BUTTON]),
+						 label);
+					g_free (label);
+				}
+			} else
+				gtk_combo_box_set_active_id (GTK_COMBO_BOX (w), si_units[row].unit);
+			
+			if (row >= 0)
+				gtk_toggle_button_set_active 
+					(GTK_TOGGLE_BUTTON (gfs->format.widget[F_SI_SI_UNIT_BUTTON]),
+					 TRUE);
+			else
+				gtk_toggle_button_set_active 
+					(GTK_TOGGLE_BUTTON (gfs->format.widget[F_SI_CUSTOM_UNIT_BUTTON]),
+					 TRUE);
+				
+
+#else
+				show_widget = FALSE;
+#endif
+			break;
+		}
+
 		case F_ENGINEERING_BUTTON:
 			gtk_toggle_button_set_active
 				(GTK_TOGGLE_BUTTON (w),
@@ -1175,7 +1349,10 @@ nfs_init (GOFormatSel *gfs)
 		"format_engineering_button",
 		"format_superscript_button",
 		"format_superscript_hide_1_button",
-		"format_si_button",
+		"format_SI_button",
+		"format_SI_custom_unit_button",
+		"format_SI_SI_unit_button",
+		"format_SI_unit_combo",
 		"format_exp_digits",
 		"format_exp_digits_label",
 		"format_negatives_label",
@@ -1225,6 +1402,7 @@ nfs_init (GOFormatSel *gfs)
 	go_format_ref (gfs->format.spec);
 
 	gfs->format.preview = NULL;
+	gfs->format.default_si_unit = NULL;
 
 	/* The handlers will set the format family later.  -1 flags that
 	 * all widgets are already hidden. */
@@ -1325,6 +1503,12 @@ nfs_init (GOFormatSel *gfs)
 		G_CALLBACK (cb_superscript_toggle), gfs);
 	g_signal_connect (G_OBJECT (gfs->format.widget[F_SI_BUTTON]), "toggled",
 		G_CALLBACK (cb_si_toggle), gfs);
+	g_signal_connect (G_OBJECT (gfs->format.widget[F_SI_SI_UNIT_BUTTON]), 
+			  "toggled", G_CALLBACK (cb_si_unit_toggle), gfs);
+	load_si_combo (gfs->format.widget[F_SI_UNIT_COMBO], gfs);
+	g_signal_connect (G_OBJECT (gfs->format.widget[F_SI_UNIT_COMBO]), 
+			  "changed", G_CALLBACK (cb_si_combo_changed), gfs);
+	
 	g_signal_connect (G_OBJECT (gfs->format.widget[F_SUPERSCRIPT_HIDE_1_BUTTON]), 
 			  "toggled", G_CALLBACK (cb_superscript_hide_1_toggle), gfs);
 	g_signal_connect (G_OBJECT (gfs->format.widget[F_FRACTION_AUTOMATIC]), 
@@ -1423,6 +1607,9 @@ go_format_sel_finalize (GObject *obj)
 	go_format_unref (gfs->format.spec);
 	gfs->format.spec = NULL;
 
+	g_free (gfs->format.default_si_unit);
+	gfs->format.default_si_unit = NULL;
+
 	if (gfs->format.size_group) {
 		g_object_unref (gfs->format.size_group);
 		gfs->format.size_group = NULL;
@@ -1433,6 +1620,8 @@ go_format_sel_finalize (GObject *obj)
 		gfs->gui = NULL;
 	}
 
+	go_format_details_finalize (&gfs->format.details);
+
 	G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_BOX))->finalize (obj);
 }
 
diff --git a/goffice/gtk/go-format-sel.ui b/goffice/gtk/go-format-sel.ui
index bbefa65..912cf9e 100644
--- a/goffice/gtk/go-format-sel.ui
+++ b/goffice/gtk/go-format-sel.ui
@@ -35,6 +35,16 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkListStore" id="liststore1">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name unit -->
+      <column type="gchararray"/>
+      <!-- column-name scale -->
+      <column type="gint"/>
+    </columns>
+  </object>
   <object class="GtkBox" id="number_box">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -905,11 +915,12 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkBox" id="box1">
+                  <object class="GtkBox" id="vbox3">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkCheckButton" id="format_si_button">
+                      <object class="GtkCheckButton" id="format_SI_button">
                         <property name="label" translatable="yes">Append SI prefix</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
@@ -923,12 +934,77 @@
                       </object>
                       <packing>
                         <property name="expand">False</property>
-                        <property name="fill">False</property>
+                        <property name="fill">True</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
-                      <placeholder/>
+                      <object class="GtkAlignment" id="alignment6">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="left_padding">24</property>
+                        <child>
+                          <object class="GtkBox" id="box3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkRadioButton" id="format_SI_custom_unit_button">
+                                <property name="label" translatable="yes">Append no further unit.</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="xalign">0</property>
+                                <property name="image_position">top</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">format_SI_SI_unit_button</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="format_SI_SI_unit_button">
+                                <property name="label" translatable="yes">Append the SI unit:</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="xalign">0</property>
+                                <property name="yalign">0.52999997138977051</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBox" id="format_SI_unit_combo">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="model">liststore1</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
                     </child>
                   </object>
                   <packing>
diff --git a/goffice/utils/go-format.c b/goffice/utils/go-format.c
index b10bd30..0618afe 100644
--- a/goffice/utils/go-format.c
+++ b/goffice/utils/go-format.c
@@ -5650,7 +5650,8 @@ go_format_generate_scientific_str (GString *dst, GOFormatDetails const *details)
 		g_string_append_c (dst, '.');
 		go_string_append_c_n (dst, '0', num_decimals);
 	}
-
+	if (details->scale == 3)
+		g_string_append_c (dst, '\'');
 	if (details->use_markup)
 		g_string_append_c (dst, 'E');
 	g_string_append_c (dst, 'E');
@@ -5661,7 +5662,12 @@ go_format_generate_scientific_str (GString *dst, GOFormatDetails const *details)
 	digits = CLAMP (details->exponent_digits, 1, 10);
 	g_string_append_c (dst, '+');
 	go_string_append_c_n (dst, '0', digits);
-	
+
+	if (details->append_SI && details->appended_SI_unit != NULL) {
+		g_string_append_c (dst, '\"');
+		g_string_append (dst, details->appended_SI_unit);
+		g_string_append_c (dst, '\"');
+	}
 }
 #endif
 
@@ -5936,9 +5942,19 @@ go_format_details_new (GOFormatFamily family)
 
 #ifdef DEFINE_COMMON
 void
-go_format_details_free (GOFormatDetails *details)
+go_format_details_finalize (GOFormatDetails *details)
 {
+	g_free (details->appended_SI_unit);
+	details->appended_SI_unit = NULL;
 	/* We do not own ->currency.  */
+}
+#endif
+
+#ifdef DEFINE_COMMON
+void
+go_format_details_free (GOFormatDetails *details)
+{
+	go_format_details_finalize (details);
 	g_free (details);
 }
 #endif
@@ -6083,6 +6099,7 @@ go_format_get_details (GOFormat const *fmt,
 			const char *mend = dot ? dot : epos;
 			dst->append_SI = (strstr (str, "ESI") != NULL);
 			dst->use_markup = (strstr (str, "EE") != NULL);
+			dst->scale = ((strstr (str, "'E") != NULL) ? 3 : 0);
 			dst->exponent_step = mend - str;
 			dst->simplify_mantissa = mend != str && mend[-1] == '#';
 			if (dst->simplify_mantissa)
@@ -6188,6 +6205,18 @@ go_format_get_details (GOFormat const *fmt,
 
 	if (newstr) {
 		*exact = (strcmp (str, newstr->str) == 0);
+		if (!*exact && dst->family == GO_FORMAT_SCIENTIFIC &&
+		    dst->append_SI && g_str_has_prefix (str, newstr->str) &&
+		    str [newstr->len] == '\"') {
+			int len = strlen (str);
+			if (str [len - 1] == '\"') {
+				dst->appended_SI_unit = g_strndup (str + newstr->len + 1,
+								   len - newstr->len - 2);
+				g_string_truncate (newstr, 0);
+				go_format_generate_str (newstr, dst);
+				*exact = (strcmp (str, newstr->str) == 0);
+			}
+		}
 		g_string_free (newstr, TRUE);
 	}
 }
diff --git a/goffice/utils/go-format.h b/goffice/utils/go-format.h
index ca6c9e0..da7a918 100644
--- a/goffice/utils/go-format.h
+++ b/goffice/utils/go-format.h
@@ -96,6 +96,8 @@ typedef struct {
 	gboolean use_markup;
 	gboolean simplify_mantissa;
 	gboolean append_SI;
+	gchar *appended_SI_unit;
+	int scale;
 
 	/* FRACTION: */
 	gboolean automatic_denominator;
@@ -162,6 +164,7 @@ void      go_format_generate_number_str (GString *dst,
 					 const char *prefix,
 					 const char *postfix);
 GOFormatDetails *go_format_details_new  (GOFormatFamily family);
+void  go_format_details_finalize        (GOFormatDetails *details);
 void  go_format_details_free            (GOFormatDetails *details);
 void  go_format_details_init            (GOFormatDetails *details,
 					 GOFormatFamily family);



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