[gnumeric] Add radiobutton sheet object.



commit 5373d4882e185d070e0de64a47c8e6ce5c855c14
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date:   Sat Sep 26 11:10:31 2009 -0600

    Add radiobutton sheet object.
    
    2009-09-26  Andreas J. Guelzow <aguelzow pyrshep ca>
    	for Albert Gräf <Dr Graef t-online de>
    
    	* so-radiobutton.glade: new
    	* Makefile.am: add so-radiobutton.glade
    	* help.h: add GNUMERIC_HELP_LINK_SO_RADIO_BUTTON
    
    2009-09-26  Andreas J. Guelzow <aguelzow pyrshep ca>
    	for Albert Graef  <Dr Graef t-online de>
    
    	* src/commands.c (cmd_so_set_radio_button, CmdSOSetRadioButton)
    	(cmd_so_set_radio_button_redo, cmd_so_set_radio_button_undo)
    	(cmd_so_set_radio_button_finalize): new set radio button command
    	* src/commands.h: added cmd_so_set_radio_button
    	* src/sheet-object-widget.c (dep_hash, dep_equal, dep_destroy)
    	(get_group, set_group): new functions to manage radio button
    	  groups
    	(parse_value, match_value): new functions to parse and match radio
    	  button values
    	(SheetWidgetRadioButton): added value and active fields
    	(sheet_widget_radio_button_set_value)
    	(sheet_widget_radio_button_set_active)
    	(sheet_widget_radio_button_set_group): new callbacks
    	(radio_button_eval): modified to set radio button activation state
    	  according to linked cell value
    	(sheet_widget_radio_button_init, sheet_widget_radio_button_init_full):
    	  split to support initialization from existing data, added initialization
    	  of new fields in SheetWidgetRadioButton struct
    	(sheet_widget_radio_button_finalize): added finalization of new
    	  fields in SheetWidgetRadioButton struct
    	(sheet_widget_radio_button_toggled): modified to handle clicks on
    	  radio buttons
    	(sheet_widget_radio_button_changed): new callback to handle moving
    	  a radio button to a new group
    	(sheet_widget_radio_button_create_widget): modified to initialize
    	  button group and connect signal to change group callback
    	(sheet_widget_radio_button_copy): new callback to allow radio
    	  buttons to be copied
    	(sheet_widget_radio_button_write_xml_sax)
    	(sheet_widget_radio_button_prep_sax_parser): new callback for reading
    	  and writing radio buttons
    	(sheet_widget_radio_button_set_link)
    	(sheet_widget_radio_button_get_link): new callbacks to set and get
    	  the linked cell
    	(RadioButtonConfigState, cb_radio_button_set_focus)
    	(cb_radio_button_config_destroy)
    	(cb_radio_button_config_ok_clicked)
    	(cb_radio_button_config_cancel_clicked)
    	(cb_radio_button_label_changed, cb_radio_button_value_changed)
    	(sheet_widget_radio_button_user_config): added config dialog
    	(SOW_MAKE_TYPE(radio_button)): added new callbacks
    	* src/sheet-object-widget.h: added
    	  sheet_widget_radio_button_get_link,
    	  sheet_widget_radio_button_set_link,
    	  sheet_widget_radio_button_set_label,
    	  sheet_widget_radio_button_set_value

 ChangeLog                        |   55 ++++
 NEWS                             |    1 +
 src/commands.c                   |   83 +++++
 src/commands.h                   |    5 +
 src/dialogs/ChangeLog            |    7 +
 src/dialogs/Makefile.am          |    1 +
 src/dialogs/help.h               |    1 +
 src/dialogs/so-radiobutton.glade |  233 ++++++++++++++
 src/gnm-pane.c                   |    1 -
 src/sheet-object-widget.c        |  637 ++++++++++++++++++++++++++++++++++----
 src/sheet-object-widget.h        |    9 +-
 11 files changed, 964 insertions(+), 69 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9f0697d..50eef6e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2009-09-26  Andreas J. Guelzow <aguelzow pyrshep ca>
+	for Albert Graef  <Dr Graef t-online de>
+
+	* src/commands.c (cmd_so_set_radio_button, CmdSOSetRadioButton)
+	(cmd_so_set_radio_button_redo, cmd_so_set_radio_button_undo)
+	(cmd_so_set_radio_button_finalize): new set radio button command
+	* src/commands.h: added cmd_so_set_radio_button
+	* src/sheet-object-widget.c (dep_hash, dep_equal, dep_destroy)
+	(get_group, set_group): new functions to manage radio button
+	  groups
+	(parse_value, match_value): new functions to parse and match radio
+	  button values
+	(SheetWidgetRadioButton): added value and active fields
+	(sheet_widget_radio_button_set_value)
+	(sheet_widget_radio_button_set_active)
+	(sheet_widget_radio_button_set_group): new callbacks
+	(radio_button_eval): modified to set radio button activation state
+	  according to linked cell value
+	(sheet_widget_radio_button_init, sheet_widget_radio_button_init_full): 
+	  split to support initialization from existing data, added initialization 
+	  of new fields in SheetWidgetRadioButton struct
+	(sheet_widget_radio_button_finalize): added finalization of new
+	  fields in SheetWidgetRadioButton struct
+	(sheet_widget_radio_button_toggled): modified to handle clicks on
+	  radio buttons
+	(sheet_widget_radio_button_changed): new callback to handle moving
+	  a radio button to a new group
+	(sheet_widget_radio_button_create_widget): modified to initialize
+	  button group and connect signal to change group callback
+	(sheet_widget_radio_button_copy): new callback to allow radio
+	  buttons to be copied
+	(sheet_widget_radio_button_write_xml_sax)
+	(sheet_widget_radio_button_prep_sax_parser): new callback for reading
+	  and writing radio buttons
+	(sheet_widget_radio_button_set_link)
+	(sheet_widget_radio_button_get_link): new callbacks to set and get
+	  the linked cell
+	(RadioButtonConfigState, cb_radio_button_set_focus)
+	(cb_radio_button_config_destroy)
+	(cb_radio_button_config_ok_clicked)
+	(cb_radio_button_config_cancel_clicked)
+	(cb_radio_button_label_changed, cb_radio_button_value_changed)
+	(sheet_widget_radio_button_user_config): added config dialog
+	(SOW_MAKE_TYPE(radio_button)): added new callbacks
+	* src/sheet-object-widget.h: added
+	  sheet_widget_radio_button_get_link,
+	  sheet_widget_radio_button_set_link,
+	  sheet_widget_radio_button_set_label,
+	  sheet_widget_radio_button_set_value
+
+2009-09-26  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* src/gnm-pane.c (set_acetate_coords): revert my previous change (with the newer
+	  version of goffice this is not needed.)
+	
 2009-09-25  Jean Brefort  <jean brefort normalesup org>
 
 	* src/gnm-so-filled.c (gnm_so_filled_draw_cairo): fixed line setting.
diff --git a/NEWS b/NEWS
index 0c43472..b51af95 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Gnumeric 1.9.14
 
 Albert Gräf:
         * Add button sheet object.
+        * Add radiobutton sheet object.
 
 Andreas:
 	* Add more ODF elements on ODF read. [#595750]
diff --git a/src/commands.c b/src/commands.c
index 48f2c5f..48d7cc5 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -7289,6 +7289,89 @@ cmd_so_set_button (WorkbookControl *wbc,
 }
 
 /******************************************************************/
+#define CMD_SO_SET_RADIO_BUTTON_TYPE (cmd_so_set_radio_button_get_type ())
+#define CMD_SO_SET_RADIO_BUTTON(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_RADIO_BUTTON_TYPE, CmdSOSetRadioButton))
+
+typedef struct {
+	GnmCommand cmd;
+	SheetObject *so;
+	GnmExprTop const *new_link;
+	GnmExprTop const *old_link;
+	char *old_label;
+	char *new_label;
+	char *old_value;
+	char *new_value;
+} CmdSOSetRadioButton;
+
+MAKE_GNM_COMMAND (CmdSOSetRadioButton, cmd_so_set_radio_button, NULL)
+
+static gboolean
+cmd_so_set_radio_button_redo (GnmCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc)
+{
+	CmdSOSetRadioButton *me = CMD_SO_SET_RADIO_BUTTON (cmd);
+
+	sheet_widget_radio_button_set_link (me->so, me->new_link);
+	sheet_widget_radio_button_set_label (me->so, me->new_label);
+	sheet_widget_radio_button_set_value (me->so, me->new_value);
+
+	return FALSE;
+}
+
+static gboolean
+cmd_so_set_radio_button_undo (GnmCommand *cmd, G_GNUC_UNUSED  WorkbookControl *wbc)
+{
+	CmdSOSetRadioButton *me = CMD_SO_SET_RADIO_BUTTON (cmd);
+
+	sheet_widget_radio_button_set_link (me->so, me->old_link);
+	sheet_widget_radio_button_set_label (me->so, me->old_label);
+	sheet_widget_radio_button_set_value (me->so, me->old_value);
+
+	return FALSE;
+}
+
+static void
+cmd_so_set_radio_button_finalize (GObject *cmd)
+{
+	CmdSOSetRadioButton *me = CMD_SO_SET_RADIO_BUTTON (cmd);
+
+	if (me->new_link)
+		gnm_expr_top_unref (me->new_link);
+	if (me->old_link)
+		gnm_expr_top_unref (me->old_link);
+	g_free (me->old_label);
+	g_free (me->new_label);
+	g_free (me->old_value);
+	g_free (me->new_value);
+	gnm_command_finalize (cmd);
+}
+
+gboolean
+cmd_so_set_radio_button (WorkbookControl *wbc,
+		   SheetObject *so, GnmExprTop const *link,
+		   char *old_label, char *new_label,
+		   char *old_value, char *new_value)
+{
+	CmdSOSetRadioButton *me;
+
+	g_return_val_if_fail (IS_WORKBOOK_CONTROL (wbc), TRUE);
+
+	me = g_object_new (CMD_SO_SET_RADIO_BUTTON_TYPE, NULL);
+	me->cmd.sheet = sheet_object_get_sheet (so);
+	me->cmd.size = 1;
+	me->cmd.cmd_descriptor = g_strdup (_("Configure Radio Button"));
+	me->so = so;
+	me->new_link = link;
+	me->old_label = old_label;
+	me->new_label = new_label;
+	me->old_value = old_value;
+	me->new_value = new_value;
+
+	me->old_link = sheet_widget_radio_button_get_link (so);
+
+	return gnm_command_push_undo (wbc, G_OBJECT (me));
+}
+
+/******************************************************************/
 #define CMD_SO_SET_CHECKBOX_TYPE (cmd_so_set_checkbox_get_type ())
 #define CMD_SO_SET_CHECKBOX(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_CHECKBOX_TYPE, CmdSOSetCheckbox))
 
diff --git a/src/commands.h b/src/commands.h
index c23d143..a5dd05b 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -184,6 +184,11 @@ gboolean cmd_so_set_button (WorkbookControl *wbc, SheetObject *so,
 			    GnmExprTop const *link,
 			    char *old_label, char *new_label);
 
+gboolean cmd_so_set_radio_button (WorkbookControl *wbc, SheetObject *so,
+				  GnmExprTop const *link,
+				  char *old_label, char *new_label,
+				  char *old_value, char *new_value);
+
 gboolean cmd_so_set_checkbox (WorkbookControl *wbc, SheetObject *so,
 			      GnmExprTop const *link,
 			      char *old_label, char *new_label);
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index e441309..b03cfc1 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,10 @@
+2009-09-26  Andreas J. Guelzow <aguelzow pyrshep ca>
+	for Albert Gräf <Dr Graef t-online de>
+
+	* so-radiobutton.glade: new
+	* Makefile.am: add so-radiobutton.glade
+	* help.h: add GNUMERIC_HELP_LINK_SO_RADIO_BUTTON
+
 2009-09-23  Andreas J. Guelzow <aguelzow pyrshep ca>
 	slightly modified patches from Albert Gräf <Dr Graef t-online de>
 
diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am
index debd628..1d18353 100644
--- a/src/dialogs/Makefile.am
+++ b/src/dialogs/Makefile.am
@@ -152,6 +152,7 @@ glade_DATA = 				\
 	sheet-resize.glade              \
 	shuffle.glade			\
 	so-button.glade			\
+ 	so-radiobutton.glade		\
 	so-checkbox.glade		\
 	so-frame.glade			\
 	so-list.glade			\
diff --git a/src/dialogs/help.h b/src/dialogs/help.h
index ef8874a..2828a26 100644
--- a/src/dialogs/help.h
+++ b/src/dialogs/help.h
@@ -21,6 +21,7 @@
 #define GNUMERIC_HELP_LINK_SO_FRAME	 "sect-graphics-drawings"
 #define GNUMERIC_HELP_LINK_SO_ADJUSTMENT "sect-graphics-drawings"
 #define GNUMERIC_HELP_LINK_SO_BUTTON	 "sect-graphics-drawings"
+#define GNUMERIC_HELP_LINK_SO_RADIO_BUTTON "sect-graphics-drawings"
 #define GNUMERIC_HELP_LINK_SO_CHECKBOX	 "sect-graphics-drawings"
 #define GNUMERIC_HELP_LINK_SO_LIST	 "sect-graphics-drawings"
 
diff --git a/src/dialogs/so-radiobutton.glade b/src/dialogs/so-radiobutton.glade
new file mode 100644
index 0000000..690130c
--- /dev/null
+++ b/src/dialogs/so-radiobutton.glade
@@ -0,0 +1,233 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd";>
+
+<glade-interface>
+
+<widget class="GtkDialog" id="SO-Radiobutton">
+  <property name="border_width">6</property>
+  <property name="title" translatable="yes">Radiobutton Properties</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_MOUSE</property>
+  <property name="modal">False</property>
+  <property name="resizable">False</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>
+  <property name="has_separator">False</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">6</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="dialog-action_area1">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="help_button">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-help</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">0</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="cancel_button">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">0</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="ok_button">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="has_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-ok</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">0</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkTable" id="table">
+	  <property name="border_width">5</property>
+	  <property name="visible">True</property>
+	  <property name="n_rows">3</property>
+	  <property name="n_columns">2</property>
+	  <property name="homogeneous">False</property>
+	  <property name="row_spacing">6</property>
+	  <property name="column_spacing">12</property>
+
+	  <child>
+	    <widget class="GtkEntry" id="value_entry">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="editable">True</property>
+	      <property name="visibility">True</property>
+	      <property name="max_length">0</property>
+	      <property name="text"></property>
+	      <property name="has_frame">True</property>
+	      <property name="invisible_char">â??</property>
+	      <property name="activates_default">False</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">1</property>
+	      <property name="right_attach">2</property>
+	      <property name="top_attach">2</property>
+	      <property name="bottom_attach">3</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Value:</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.5</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">2</property>
+	      <property name="bottom_attach">3</property>
+	      <property name="x_options"></property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkEntry" id="label_entry">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="editable">True</property>
+	      <property name="visibility">True</property>
+	      <property name="max_length">0</property>
+	      <property name="text"></property>
+	      <property name="has_frame">True</property>
+	      <property name="invisible_char">*</property>
+	      <property name="activates_default">False</property>
+	      <accessibility>
+		<atkrelation target="label2" type="labelled-by"/>
+	      </accessibility>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">1</property>
+	      <property name="right_attach">2</property>
+	      <property name="top_attach">1</property>
+	      <property name="bottom_attach">2</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label2">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Label:</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">True</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>
+	      <accessibility>
+		<atkrelation target="label_entry" type="label-for"/>
+	      </accessibility>
+	    </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"></property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label_linkto">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Link to:</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">True</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">0</property>
+	      <property name="bottom_attach">1</property>
+	      <property name="x_options"></property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/src/gnm-pane.c b/src/gnm-pane.c
index 3f597f0..085ba50 100644
--- a/src/gnm-pane.c
+++ b/src/gnm-pane.c
@@ -2895,7 +2895,6 @@ set_acetate_coords (GnmPane *pane, SheetObject *so, GocItem **ctrl_pts,
 
 		style->fill.auto_type = FALSE;
 		style->fill.type  = GO_STYLE_FILL_PATTERN;
-		style->fill.auto_fore = FALSE;
 		style->fill.auto_back = FALSE;
 		go_pattern_set_solid (&style->fill.pattern, 0);
 		style->line.auto_dash = FALSE;
diff --git a/src/sheet-object-widget.c b/src/sheet-object-widget.c
index e28086f..2723478 100644
--- a/src/sheet-object-widget.c
+++ b/src/sheet-object-widget.c
@@ -2204,32 +2204,275 @@ GSF_CLASS (SheetWidgetToggleButton, sheet_widget_toggle_button,
 #define SHEET_WIDGET_RADIO_BUTTON(obj)	(G_TYPE_CHECK_INSTANCE_CAST((obj), SHEET_WIDGET_RADIO_BUTTON_TYPE, SheetWidgetRadioButton))
 #define DEP_TO_RADIO_BUTTON(d_ptr)	(SheetWidgetRadioButton *)(((char *)d_ptr) - G_STRUCT_OFFSET(SheetWidgetRadioButton, dep))
 
+#include "expr-impl.h"
+
+/* Keep track of GnmDepenmdent -> radio button group mapping. We have to go to
+   some lengths here because the cell reference expressions in the dependents
+   are not forced to have explicit sheet references. Thus, when hashing or
+   comparing the dependents, we check for cell references with a NULL sheet in
+   which case we assume the sheet of the dependent instead. */
+
+static GHashTable *groups = NULL;
+
+static guint
+dep_cellref_hash(GnmDependent const *k)
+{
+	const GnmCellRef *ref = &k->texpr->expr->cellref.ref;
+	GnmCellRef r;
+	if (!ref->sheet) {
+		r = *ref;
+		r.sheet = k->sheet;
+		ref = &r;
+	}
+	return gnm_cellref_hash(ref);
+}
+
+static guint
+dep_hash(GnmDependent const *k)
+{
+	if (!k || !k->texpr)
+		return 0;
+	else if (GNM_EXPR_GET_OPER (k->texpr->expr) == GNM_EXPR_OP_CELLREF)
+		return dep_cellref_hash(k);
+	else
+		/* shouldn't happen */
+		return gnm_expr_top_hash(k->texpr);
+}
+
+static gint
+dep_cellref_equal(GnmDependent const *k1, GnmDependent const *k2)
+{
+	const GnmCellRef *ref1 = &k1->texpr->expr->cellref.ref;
+	const GnmCellRef *ref2 = &k2->texpr->expr->cellref.ref;
+	GnmCellRef r1, r2;
+	if (!ref1->sheet) {
+		r1 = *ref1;
+		r1.sheet = k1->sheet;
+		ref1 = &r1;
+	}
+	if (!ref2->sheet) {
+		r2 = *ref2;
+		r2.sheet = k2->sheet;
+		ref2 = &r2;
+	}
+	return gnm_cellref_equal(ref1, ref2);
+}
+
+static gint
+dep_equal(GnmDependent const *k1, GnmDependent const *k2)
+{
+	if (k1 && k2)
+		if (k1->texpr == k2->texpr)
+			return 1;
+		else if (!k1->texpr || !k2->texpr)
+			return 0;
+		else if (GNM_EXPR_GET_OPER (k1->texpr->expr) == GNM_EXPR_OP_CELLREF &&
+			 GNM_EXPR_GET_OPER (k2->texpr->expr) == GNM_EXPR_OP_CELLREF)
+			return dep_cellref_equal(k1, k2);
+		else
+			/* shouldn't happen */
+			return gnm_expr_top_equal(k1->texpr, k2->texpr);
+	else
+		return k1==k2;
+}
+
+static void
+dep_destroy(GnmDependent *k)
+{
+	if (k) {
+		if (k->texpr) gnm_expr_top_unref(k->texpr);
+		g_free(k);
+	}
+}
+
+static GSList *get_group(const GnmDependent *dep)
+{
+	if (!groups)
+		groups = g_hash_table_new_full ((GHashFunc)dep_hash,
+						(GEqualFunc)dep_equal,
+						(GDestroyNotify)dep_destroy,
+						NULL);
+	return g_hash_table_lookup (groups, dep);
+}
+
+static void set_group(const GnmDependent *d, GSList *g)
+{
+	if (g) {
+		GnmDependent *dep;
+		g_return_if_fail (groups != NULL);
+		if (d) {
+			dep = g_new(GnmDependent, 1);
+			*dep = *d;
+			if (dep->texpr) gnm_expr_top_ref(dep->texpr);
+		} else
+			dep = NULL;
+		g_hash_table_insert (groups, dep, g);
+	} else
+		g_hash_table_remove (groups, d);
+}
+
+/* Radiobutton values are stored internally as simple strings and are parsed
+   on the fly when needed. At present we recognize booleans, numbers and
+   strings. A string value looking like a boolean or a number may be escaped
+   with a leading single quote. */
+
+static GnmValue *parse_value(const char *val)
+{
+	g_return_val_if_fail (val != NULL, NULL);
+	if (*val == '\'')
+		val++;
+	else {
+		GnmValue *res = value_new_from_string (VALUE_BOOLEAN, val, NULL, FALSE);
+		if (res) return res;
+		res = value_new_from_string (VALUE_FLOAT, val, NULL, FALSE);
+		if (res) return res;
+	}
+	return value_new_string (val);
+}
+
+static gboolean match_value(const char *val, const GnmValue *res)
+{
+	GnmValue *v = parse_value(val);
+	gboolean ret = value_equal(v, res);
+	value_release(v);
+	return ret;
+}
+
 typedef struct {
 	SheetObjectWidget	sow;
 
 	gboolean	 being_updated;
-	char		*label;
+	char		*label, *value;
+	gboolean	 active;
 	GnmDependent	 dep;
 } SheetWidgetRadioButton;
 typedef SheetObjectWidgetClass SheetWidgetRadioButtonClass;
 
+enum {
+	SOR_PROP_0 = 0,
+	SOR_PROP_TEXT,
+	SOR_PROP_MARKUP
+};
+
+static void
+sheet_widget_radio_button_get_property (GObject *obj, guint param_id,
+				    GValue  *value, GParamSpec *pspec)
+{
+	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (obj);
+
+	switch (param_id) {
+	case SOR_PROP_TEXT:
+		g_value_set_string (value, swrb->label);
+		break;
+	case SOR_PROP_MARKUP:
+		g_value_set_boxed (value, NULL); /* swrb->markup */
+		break;
+	default :
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+sheet_widget_radio_button_set_property (GObject *obj, guint param_id,
+					GValue const *value, GParamSpec *pspec)
+{
+	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (obj);
+
+	switch (param_id) {
+	case SOR_PROP_TEXT:
+		sheet_widget_radio_button_set_label (SHEET_OBJECT (swrb),
+						     g_value_get_string (value));
+		break;
+	case SOR_PROP_MARKUP:
+#if 0
+		sheet_widget_radio_button_set_markup (SHEET_OBJECT (swrb),
+						      g_value_peek_pointer (value));
+#endif
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		return;
+	}
+}
+
+void
+sheet_widget_radio_button_set_value (SheetObject *so, char const *str)
+{
+	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
+	char *new_value;
+
+	if (go_str_compare (str, swrb->value) == 0)
+		return;
+
+	new_value = g_strdup (str);
+	g_free (swrb->value);
+	swrb->value = new_value;
+}
+
+static void
+sheet_widget_radio_button_set_active (SheetWidgetRadioButton *swrb)
+{
+	GList *ptr;
+
+	if (!swrb->active) return;
+
+	swrb->being_updated = TRUE;
+
+	for (ptr = swrb->sow.realized_list; ptr != NULL ; ptr = ptr->next) {
+		SheetObjectView *view = ptr->data;
+		GocWidget *item = get_goc_widget (view);
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->widget),
+					      TRUE);
+	}
+
+	swrb->being_updated = FALSE;
+}
+
+static void
+sheet_widget_radio_button_set_group (SheetWidgetRadioButton *swrb, GSList *grp)
+{
+	GList *ptr;
+
+	swrb->being_updated = TRUE;
+	swrb->active = FALSE;
+
+	for (ptr = swrb->sow.realized_list; ptr != NULL ; ptr = ptr->next) {
+		SheetObjectView *view = ptr->data;
+		GocWidget *item = get_goc_widget (view);
+		GtkRadioButton *w = GTK_RADIO_BUTTON(item->widget);
+		GSList *old_grp = gtk_radio_button_get_group (w);
+		/* Move widget from old_grp to new_grp. */
+		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) {
+			/* Activate some other widget in the same group. */
+			for (; old_grp; old_grp = old_grp->next) {
+				GtkRadioButton *v = GTK_RADIO_BUTTON(old_grp->data);
+				if (v != w) {
+					gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (v), TRUE);
+					break;
+				}
+			}
+		}
+		gtk_radio_button_set_group (w, grp);
+	}
+
+	swrb->being_updated = FALSE;
+}
+
 static void
 radio_button_eval (GnmDependent *dep)
 {
 	GnmValue *v;
 	GnmEvalPos pos;
-	gnm_float result;
 
 	v = gnm_expr_top_eval (dep->texpr, eval_pos_init_dep (&pos, dep),
 			       GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
-	result = value_get_as_float (v);
-	value_release (v);
-#if 0
-	if (!err) {
-		/* FIXME : finish this when I have a better idea of a group */
-		/* SheetWidgetRadioButton *swrb = DEP_TO_RADIO_BUTTON (dep); */
+	if (v) {
+		SheetWidgetRadioButton *swrb = DEP_TO_RADIO_BUTTON(dep);
+		swrb->active = match_value (swrb->value, v);
+		sheet_widget_radio_button_set_active (swrb);
 	}
-#endif
+	value_release (v);
 }
 
 static void
@@ -2240,62 +2483,133 @@ radio_button_debug_name (GnmDependent const *dep, GString *target)
 
 static DEPENDENT_MAKE_TYPE (radio_button, NULL)
 
+static guint rb_counter = 0;
+
 static void
-sheet_widget_radio_button_init (SheetObjectWidget *sow)
+sheet_widget_radio_button_init_full (SheetObjectWidget *sow,
+				     GnmCellRef const *ref,
+				     char const *label,
+				     char const *value)
 {
 	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (sow);
 
+	g_return_if_fail (swrb != NULL);
+
 	swrb->being_updated = FALSE;
-	swrb->label = g_strdup (_("RadioButton"));
+	swrb->label = g_strdup (label?label:_("RadioButton"));
+	swrb->value = g_strdup (value?value:"");
+	swrb->active = FALSE;
 
+	swrb->being_updated = FALSE;
 	swrb->dep.sheet = NULL;
 	swrb->dep.flags = radio_button_get_dep_type ();
-	swrb->dep.texpr = NULL;
+	swrb->dep.texpr = (ref != NULL)
+		? gnm_expr_top_new (gnm_expr_new_cellref (ref))
+		: NULL;
+	rb_counter++;
+}
+
+static void
+sheet_widget_radio_button_init (SheetWidgetRadioButton *swrb)
+{
+	sheet_widget_radio_button_init_full (SHEET_OBJECT (swrb), NULL, NULL, NULL);
 }
 
 static void
 sheet_widget_radio_button_finalize (GObject *obj)
 {
 	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (obj);
+	GSList *grp;
+
+	g_return_if_fail (swrb != NULL);
 
 	g_free (swrb->label);
 	swrb->label = NULL;
+	g_free (swrb->value);
+	swrb->value = NULL;
 
+	if ((grp = get_group(&swrb->dep)) && grp->next == NULL)
+		/* Removing the last button from the group. */
+		set_group(&swrb->dep, NULL);
 	dependent_set_expr (&swrb->dep, NULL);
 	(*sheet_object_widget_class->finalize) (obj);
+
+	if (--rb_counter == 0) {
+		g_hash_table_destroy(groups);
+		groups = NULL;
+	}
 }
 
 static void
 sheet_widget_radio_button_toggled (GtkToggleButton *button,
 				   SheetWidgetRadioButton *swrb)
 {
+	GnmCellRef ref;
 	if (swrb->being_updated || !gtk_toggle_button_get_active (button))
 		return;
-#if 0
-	swrb->value = gtk_toggle_button_get_active (button);
-	sheet_widget_checkbox_set_active (swrb);
-#endif
+	swrb->active = TRUE;
+	sheet_widget_radio_button_set_active (swrb);
+
+	if (so_get_ref (SHEET_OBJECT (swrb), &ref, TRUE) != NULL) {
+		cmd_so_set_value (widget_wbc (GTK_WIDGET (button)),
+				  /* FIXME: This text sucks:  */
+				  _("Clicking radiobutton"),
+				  &ref, parse_value (swrb->value),
+				  sheet_object_get_sheet (SHEET_OBJECT (swrb)));
+	}
+}
+
+static void
+sheet_widget_radio_button_changed (GtkRadioButton *button,
+				   SheetWidgetRadioButton *swrb)
+{
+	GSList *old_grp = get_group (&swrb->dep),
+	       *new_grp = gtk_radio_button_get_group (button);
+	if (old_grp != new_grp)
+		set_group(&swrb->dep, new_grp);
 }
 
 static GtkWidget *
 sheet_widget_radio_button_create_widget (SheetObjectWidget *sow)
 {
 	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (sow);
-	/* FIXME: NULL group?  */
-	GtkWidget *w = gtk_radio_button_new_with_label (NULL,
-							swrb->label);
+	GSList* grp =  get_group(&swrb->dep);
+	GtkWidget *w = gtk_radio_button_new_with_label (grp, swrb->label);
+	if (!grp) {
+		grp = gtk_radio_button_get_group (GTK_RADIO_BUTTON(w));
+		set_group (&swrb->dep, grp);
+	}
+	GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_FOCUS);
+	if (swrb->active)
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);
 	g_signal_connect (G_OBJECT (w),
 			  "toggled",
 			  G_CALLBACK (sheet_widget_radio_button_toggled), sow);
+	g_signal_connect (G_OBJECT (w),
+			  "group-changed",
+			  G_CALLBACK (sheet_widget_radio_button_changed), sow);
 	return w;
 }
 
+static void
+sheet_widget_radio_button_copy (SheetObject *dst, SheetObject const *src)
+{
+	SheetWidgetRadioButton const *src_swrb = SHEET_WIDGET_RADIO_BUTTON (src);
+	SheetWidgetRadioButton       *dst_swrb = SHEET_WIDGET_RADIO_BUTTON (dst);
+	GnmCellRef ref;
+	sheet_widget_radio_button_init_full (SHEET_OBJECT (dst_swrb),
+					     so_get_ref (src, &ref, FALSE),
+					     src_swrb->label,
+					     src_swrb->value);
+}
+
 static gboolean
 sheet_widget_radio_button_set_sheet (SheetObject *so, Sheet *sheet)
 {
 	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
 
 	dependent_set_sheet (&swrb->dep, sheet);
+	sheet_widget_radio_button_set_active (swrb);
 
 	return FALSE;
 }
@@ -2309,6 +2623,66 @@ sheet_widget_radio_button_foreach_dep (SheetObject *so,
 	func (&swrb->dep, so, user);
 }
 
+static void
+sheet_widget_radio_button_write_xml_sax (SheetObject const *so, GsfXMLOut *output,
+				     GnmConventions const *convs)
+{
+	SheetWidgetRadioButton const *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
+
+	gsf_xml_out_add_cstr (output, "Label", swrb->label);
+	gsf_xml_out_add_cstr (output, "Value", swrb->value);
+	gsf_xml_out_add_int (output, "Active", swrb->active);
+	sax_write_dep (output, &swrb->dep, "Input", convs);
+}
+
+static void
+sheet_widget_radio_button_prep_sax_parser (SheetObject *so, GsfXMLIn *xin,
+				       xmlChar const **attrs,
+				       GnmConventions const *convs)
+{
+	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
+
+	for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+		if (attr_eq (attrs[0], "Label")) {
+			g_free (swrb->label);
+			swrb->label = g_strdup (CXML2C (attrs[1]));
+		} else if (attr_eq (attrs[0], "Value")) {
+			g_free (swrb->value);
+			swrb->value = g_strdup (CXML2C (attrs[1]));
+		} else if (gnm_xml_attr_int (attrs, "Active", &swrb->active))
+			; /* ??? */
+		else if (sax_read_dep (attrs, "Input", &swrb->dep, xin, convs))
+			; /* ??? */
+}
+
+void
+sheet_widget_radio_button_set_link (SheetObject *so, GnmExprTop const *texpr)
+{
+	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
+	GSList *old_grp =  get_group(&swrb->dep), *new_grp;
+	if (old_grp && old_grp->next == NULL)
+		/* Removing the last button from the group. */
+		set_group(&swrb->dep, NULL);
+	dependent_set_expr (&swrb->dep, texpr);
+	if (NULL != texpr)
+		dependent_link (&swrb->dep);
+	new_grp = get_group(&swrb->dep);
+	if (old_grp != new_grp)
+		sheet_widget_radio_button_set_group(swrb, new_grp);
+}
+
+GnmExprTop const *
+sheet_widget_radio_button_get_link	 (SheetObject *so)
+{
+	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
+	GnmExprTop const *texpr = swrb->dep.texpr;
+
+	if (texpr)
+		gnm_expr_top_ref (texpr);
+
+	return texpr;
+}
+
 void
 sheet_widget_radio_button_set_label (SheetObject *so, char const *str)
 {
@@ -2330,64 +2704,197 @@ sheet_widget_radio_button_set_label (SheetObject *so, char const *str)
 	}
 }
 
-enum {
-	SOR_PROP_0 = 0,
-	SOR_PROP_TEXT,
-	SOR_PROP_MARKUP
-};
+
+typedef struct {
+ 	GladeXML           *gui;
+ 	GtkWidget *dialog;
+ 	GnmExprEntry *expression;
+ 	GtkWidget *label, *value;
+	
+ 	char *old_label, *old_value;
+ 	GtkWidget *old_focus;
+	
+ 	WBCGtk  *wbcg;
+ 	SheetWidgetRadioButton *swrb;
+ 	Sheet		    *sheet;
+} RadioButtonConfigState;
 
 static void
-sheet_widget_radio_button_get_property (GObject *obj, guint param_id,
-				    GValue  *value, GParamSpec *pspec)
+cb_radio_button_set_focus (GtkWidget *window, GtkWidget *focus_widget,
+ 			   RadioButtonConfigState *state)
 {
-	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (obj);
+ 	/* Note:  half of the set-focus action is handle by the default
+ 	 *        callback installed by wbc_gtk_attach_guru */
+	
+ 	/* Force an update of the content in case it needs tweaking (eg make it
+ 	 * absolute) */
+ 	if (state->old_focus != NULL &&
+ 	    IS_GNM_EXPR_ENTRY (state->old_focus->parent)) {
+ 		GnmParsePos  pp;
+ 		GnmExprTop const *texpr = gnm_expr_entry_parse (
+ 			GNM_EXPR_ENTRY (state->old_focus->parent),
+ 			parse_pos_init_sheet (&pp, state->sheet),
+ 			NULL, FALSE, GNM_EXPR_PARSE_DEFAULT);
+ 		if (texpr != NULL)
+ 			gnm_expr_top_unref (texpr);
+  	}
+ 	state->old_focus = focus_widget;
+}
 
-	switch (param_id) {
-	case SOR_PROP_TEXT:
-		g_value_set_string (value, swrb->label);
-		break;
-	case SOR_PROP_MARKUP:
-		g_value_set_boxed (value, NULL); /* swrb->markup */
-		break;
-	default :
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
-		break;
-	}
+static void
+cb_radio_button_config_destroy (RadioButtonConfigState *state)
+{
+ 	g_return_if_fail (state != NULL);
+	
+ 	if (state->gui != NULL) {
+ 		g_object_unref (G_OBJECT (state->gui));
+ 		state->gui = NULL;
+  	}
+	
+ 	g_free (state->old_label);
+ 	g_free (state->old_value);
+ 	state->old_label = NULL;
+ 	state->old_value = NULL;
+ 	state->dialog = NULL;
+ 	g_free (state);
 }
 
 static void
-sheet_widget_radio_button_set_property (GObject *obj, guint param_id,
-					GValue const *value, GParamSpec *pspec)
+cb_radio_button_config_ok_clicked (GtkWidget *button, RadioButtonConfigState *state)
 {
-	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (obj);
+	SheetObject *so = SHEET_OBJECT (state->swrb);
+	GnmParsePos  pp;
+ 	GnmExprTop const *texpr = gnm_expr_entry_parse (state->expression,
+							parse_pos_init_sheet (&pp, so->sheet),
+							NULL, FALSE, GNM_EXPR_PARSE_DEFAULT);
+ 	gchar const *text = gtk_entry_get_text(GTK_ENTRY(state->label));
+ 	gchar const *val = gtk_entry_get_text(GTK_ENTRY(state->value));
+	
+ 	cmd_so_set_radio_button (WORKBOOK_CONTROL (state->wbcg), so,
+ 				 texpr, g_strdup (state->old_label), 
+				 g_strdup (text), g_strdup (state->old_value), g_strdup (val));
+	
+ 	gtk_widget_destroy (state->dialog);
+}
 
-	switch (param_id) {
-	case SOR_PROP_TEXT:
-		sheet_widget_radio_button_set_label (SHEET_OBJECT (swrb),
-						     g_value_get_string (value));
-		break;
-	case SOR_PROP_MARKUP:
-#if 0
-		sheet_widget_radio_button_set_markup (SHEET_OBJECT (swrb),
-						      g_value_peek_pointer (value));
-#endif
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
-		return;
-	}
+static void
+cb_radio_button_config_cancel_clicked (GtkWidget *button, RadioButtonConfigState *state)
+{
+ 	sheet_widget_radio_button_set_label (SHEET_OBJECT (state->swrb),
+ 					     state->old_label);
+ 	sheet_widget_radio_button_set_value (SHEET_OBJECT (state->swrb),
+ 					     state->old_value);
+ 	gtk_widget_destroy (state->dialog);
+}
+
+static void
+cb_radio_button_label_changed (GtkEntry *entry, RadioButtonConfigState *state)
+{
+ 	sheet_widget_radio_button_set_label (SHEET_OBJECT (state->swrb),
+ 					     gtk_entry_get_text (entry));
+}
+
+static void
+cb_radio_button_value_changed (GtkEntry *entry, RadioButtonConfigState *state)
+{
+ 	sheet_widget_radio_button_set_value (SHEET_OBJECT (state->swrb),
+ 					     gtk_entry_get_text (entry));
+}
+
+static void
+sheet_widget_radio_button_user_config (SheetObject *so, SheetControl *sc)
+{
+ 	SheetWidgetRadioButton *swrb = SHEET_WIDGET_RADIO_BUTTON (so);
+ 	WBCGtk  *wbcg = scg_wbcg (SHEET_CONTROL_GUI (sc));
+ 	RadioButtonConfigState *state;
+ 	GtkWidget *table;
+ 
+ 	g_return_if_fail (swrb != NULL);
+ 
+	/* Only pop up one copy per workbook */
+ 	if (gnumeric_dialog_raise_if_exists (wbcg, SHEET_OBJECT_CONFIG_KEY))
+ 		return;
+ 
+ 	state = g_new (RadioButtonConfigState, 1);
+ 	state->swrb = swrb;
+ 	state->wbcg = wbcg;
+ 	state->sheet = sc_sheet	(sc);
+ 	state->old_focus = NULL;
+	state->old_label = g_strdup (swrb->label);
+ 	state->old_value = g_strdup (swrb->value);
+ 	state->gui = gnm_glade_xml_new (GO_CMD_CONTEXT (wbcg),
+					"so-radiobutton.glade", NULL, NULL);
+ 	state->dialog = glade_xml_get_widget (state->gui, "SO-Radiobutton");
+ 
+ 	table = glade_xml_get_widget (state->gui, "table");
+ 
+ 	state->expression = gnm_expr_entry_new (wbcg, TRUE);
+ 	gnm_expr_entry_set_flags (state->expression,
+				  GNM_EE_FORCE_ABS_REF | GNM_EE_SHEET_OPTIONAL | GNM_EE_SINGLE_RANGE,
+				  GNM_EE_MASK);
+ 	gnm_expr_entry_load_from_dep (state->expression, &swrb->dep);
+ 	go_atk_setup_label (glade_xml_get_widget (state->gui, "label_linkto"),
+			    GTK_WIDGET (state->expression));
+ 	gtk_table_attach (GTK_TABLE (table), GTK_WIDGET (state->expression),
+ 			  1, 2, 0, 1,
+ 			  GTK_EXPAND | GTK_FILL, 0,
+ 			  0, 0);
+ 	gtk_widget_show (GTK_WIDGET (state->expression));
+ 
+ 	state->label = glade_xml_get_widget (state->gui, "label_entry");
+ 	gtk_entry_set_text (GTK_ENTRY (state->label), swrb->label);
+ 	gtk_editable_select_region (GTK_EDITABLE(state->label), 0, -1);
+ 	state->value = glade_xml_get_widget (state->gui, "value_entry");
+ 	gtk_entry_set_text (GTK_ENTRY (state->value), swrb->value);
+  	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
+ 				  GTK_WIDGET (state->expression));
+ 	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
+ 				  GTK_WIDGET (state->label));
+ 	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
+ 				  GTK_WIDGET (state->value));
+ 
+ 	g_signal_connect (G_OBJECT (state->label),
+			  "changed",
+			  G_CALLBACK (cb_radio_button_label_changed), state);
+ 	g_signal_connect (G_OBJECT (state->value),
+			  "changed",
+			  G_CALLBACK (cb_radio_button_value_changed), state);
+ 	g_signal_connect (G_OBJECT (glade_xml_get_widget (state->gui, "ok_button")),
+			  "clicked",
+			  G_CALLBACK (cb_radio_button_config_ok_clicked), state);
+ 	g_signal_connect (G_OBJECT (glade_xml_get_widget (state->gui, "cancel_button")),
+			  "clicked",
+			  G_CALLBACK (cb_radio_button_config_cancel_clicked), state);
+ 
+ 	gnumeric_init_help_button (
+ 		glade_xml_get_widget (state->gui, "help_button"),
+ 		GNUMERIC_HELP_LINK_SO_RADIO_BUTTON);
+ 
+ 	gnumeric_keyed_dialog (state->wbcg, GTK_WINDOW (state->dialog),
+ 			       SHEET_OBJECT_CONFIG_KEY);
+ 
+ 	wbc_gtk_attach_guru (state->wbcg, state->dialog);
+ 	g_object_set_data_full (G_OBJECT (state->dialog),
+				"state", state, (GDestroyNotify) cb_radio_button_config_destroy);
+ 
+	/* Note:  half of the set-focus action is handle by the default */
+ 	/*        callback installed by wbc_gtk_attach_guru */
+ 	g_signal_connect (G_OBJECT (state->dialog), "set-focus",
+			  G_CALLBACK (cb_radio_button_set_focus), state);
+ 
+ 	gtk_widget_show (state->dialog);
 }
 
 SOW_MAKE_TYPE (radio_button, RadioButton,
-	       NULL,
-	       sheet_widget_radio_button_set_sheet,
-	       so_clear_sheet,
-	       sheet_widget_radio_button_foreach_dep,
-	       NULL,
-	       NULL,
-	       NULL,
-	       sheet_widget_radio_button_get_property,
-	       sheet_widget_radio_button_set_property,
+ 	       sheet_widget_radio_button_user_config,
+  	       sheet_widget_radio_button_set_sheet,
+  	       so_clear_sheet,
+  	       sheet_widget_radio_button_foreach_dep,
+ 	       sheet_widget_radio_button_copy,
+ 	       sheet_widget_radio_button_write_xml_sax,
+ 	       sheet_widget_radio_button_prep_sax_parser,
+  	       sheet_widget_radio_button_get_property,
+  	       sheet_widget_radio_button_set_property,
 	       {
 		       g_object_class_install_property
 			       (object_class, SOR_PROP_TEXT,
diff --git a/src/sheet-object-widget.h b/src/sheet-object-widget.h
index 2bc59f7..251c1cb 100644
--- a/src/sheet-object-widget.h
+++ b/src/sheet-object-widget.h
@@ -41,12 +41,15 @@ void sheet_widget_checkbox_set_link	 (SheetObject *so,
 					  GnmExprTop const *result_link);
 GnmExprTop const *sheet_widget_checkbox_get_link (SheetObject *so);
 void sheet_widget_checkbox_set_label	 (SheetObject *so, char const *str);
-void sheet_widget_button_set_link	 (SheetObject *so,
+GnmExprTop const *sheet_widget_radio_button_get_link (SheetObject *so);
+void sheet_widget_radio_button_set_link	 (SheetObject *so,
 					  GnmExprTop const *result_link);
+void sheet_widget_radio_button_set_label (SheetObject *so, char const *str);
+void sheet_widget_radio_button_set_value (SheetObject *so, char const *str);
 GnmExprTop const *sheet_widget_button_get_link (SheetObject *so);
+void sheet_widget_button_set_link	 (SheetObject *so,
+					  GnmExprTop const *result_link);
 void sheet_widget_button_set_label	 (SheetObject *so, char const *str);
-void sheet_widget_radio_button_set_label (SheetObject *so, char const *str);
-
 void sheet_widget_button_set_markup      (SheetObject *so, PangoAttrList *markup);
 void sheet_widget_frame_set_label        (SheetObject *so, char const *str);
 



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