[gnumeric] Implement sheet object button



commit 01229eb99039130a3cf03fb26ce25a8dca88ab0e
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date:   Wed Sep 23 17:31:46 2009 -0600

    Implement sheet object button
    
    2009-09-23  Andreas J. Guelzow <aguelzow pyrshep ca>
    	slightly modified patches from Albert Gräf <Dr Graef t-online de>
    
    	* src/commands.c (cmd_so_set_button): new
    	(CmdSOSetButton): new
    	(cmd_so_set_button_redo): new
    	(cmd_so_set_button_undo): new
    	(cmd_so_set_button_finalize): new
    	* src/commands.h (cmd_so_set_button): new
    	* src/sheet-object-widget.c (sheet_widget_button_set_link): new
    	(sheet_widget_button_get_link): new
    	(button_eval): new
    	(button_debug_name): new
    	(sheet_widget_button_init_full): handle new fields
    	(sheet_widget_button_init_full): add argument and change all callers
    	(cb_button_pressed): new
    	(cb_button_released): new
    	(sheet_widget_button_create_widget): handle signals
    	(cb_button_set_focus): new
    	(sheet_widget_button_copy): handle new fields
    	(cb_button_config_destroy): new
    	(cb_button_config_ok_clicked): new
    	(sheet_widget_button_user_config): new
    	(sheet_widget_button_set_sheet): new
    	(sheet_widget_button_foreach_dep): new
    	(sheet_widget_button_write_xml_sax): handle new fields
    	(sheet_widget_button_prep_sax_parser): ditto
    	* src/sheet-object-widget.h (sheet_widget_button_set_link): new
    	(sheet_widget_button_get_link): new
    
    2009-09-23  Andreas J. Guelzow <aguelzow pyrshep ca>
    	slightly modified patches from Albert Gräf <Dr Graef t-online de>
    
    	* so-button.glade: new
    	* Makefile.am: add so-button.glade
    	* help.h: add GNUMERIC_HELP_LINK_SO_BUTTON

 ChangeLog                   |   30 ++++
 NEWS                        |    3 +
 src/commands.c              |   74 ++++++++
 src/commands.h              |    4 +
 src/dialogs/ChangeLog       |    7 +
 src/dialogs/Makefile.am     |    5 +-
 src/dialogs/help.h          |    1 +
 src/dialogs/so-button.glade |  167 ++++++++++++++++++
 src/sheet-object-widget.c   |  399 +++++++++++++++++++++++++++++++++++++------
 src/sheet-object-widget.h   |    3 +
 10 files changed, 636 insertions(+), 57 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b9bee21..06e1157 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2009-09-23  Andreas J. Guelzow <aguelzow pyrshep ca>
+	slightly modified patches from Albert Gräf <Dr Graef t-online de>
+
+	* src/commands.c (cmd_so_set_button): new
+	(CmdSOSetButton): new
+	(cmd_so_set_button_redo): new
+	(cmd_so_set_button_undo): new
+	(cmd_so_set_button_finalize): new
+	* src/commands.h (cmd_so_set_button): new
+	* src/sheet-object-widget.c (sheet_widget_button_set_link): new
+	(sheet_widget_button_get_link): new
+	(button_eval): new
+	(button_debug_name): new
+	(sheet_widget_button_init_full): handle new fields
+	(sheet_widget_button_init_full): add argument and change all callers
+	(cb_button_pressed): new
+	(cb_button_released): new
+	(sheet_widget_button_create_widget): handle signals
+	(cb_button_set_focus): new
+	(sheet_widget_button_copy): handle new fields
+	(cb_button_config_destroy): new
+	(cb_button_config_ok_clicked): new
+	(sheet_widget_button_user_config): new
+	(sheet_widget_button_set_sheet): new
+	(sheet_widget_button_foreach_dep): new
+	(sheet_widget_button_write_xml_sax): handle new fields
+	(sheet_widget_button_prep_sax_parser): ditto
+	* src/sheet-object-widget.h (sheet_widget_button_set_link): new
+	(sheet_widget_button_get_link): new
+
 2009-09-23  Jean Brefort  <jean brefort normalesup org>
 
 	* component/gnumeric.c (cb_gognm_save), (go_gnm_component_edit): allow
diff --git a/NEWS b/NEWS
index bbb3b03..5621afe 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Gnumeric 1.9.14
 
+Albert Gräf:
+        * Add button sheet object.
+
 Andreas:
 	* Add more ODF elements on ODF read. [#595750]
 	* Fix 2-factor ANOVA with replication
diff --git a/src/commands.c b/src/commands.c
index 0c292f9..48f2c5f 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -7215,6 +7215,80 @@ cmd_so_set_frame_label (WorkbookControl *wbc,
 }
 
 /******************************************************************/
+#define CMD_SO_SET_BUTTON_TYPE (cmd_so_set_button_get_type ())
+#define CMD_SO_SET_BUTTON(o)   (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_BUTTON_TYPE, CmdSOSetButton))
+
+typedef struct {
+	GnmCommand cmd;
+	SheetObject *so;
+	GnmExprTop const *new_link;
+	GnmExprTop const *old_link;
+	char *old_label;
+	char *new_label;
+} CmdSOSetButton;
+
+MAKE_GNM_COMMAND (CmdSOSetButton, cmd_so_set_button, NULL)
+
+static gboolean
+cmd_so_set_button_redo (GnmCommand *cmd, G_GNUC_UNUSED WorkbookControl *wbc)
+{
+	CmdSOSetButton *me = CMD_SO_SET_BUTTON (cmd);
+
+	sheet_widget_button_set_link (me->so, me->new_link);
+	sheet_widget_button_set_label (me->so, me->new_label);
+
+	return FALSE;
+}
+
+static gboolean
+cmd_so_set_button_undo (GnmCommand *cmd, G_GNUC_UNUSED  WorkbookControl *wbc)
+{
+	CmdSOSetButton *me = CMD_SO_SET_BUTTON (cmd);
+
+	sheet_widget_button_set_link (me->so, me->old_link);
+	sheet_widget_button_set_label (me->so, me->old_label);
+
+	return FALSE;
+}
+
+static void
+cmd_so_set_button_finalize (GObject *cmd)
+{
+	CmdSOSetButton *me = CMD_SO_SET_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);
+	gnm_command_finalize (cmd);
+}
+
+gboolean
+cmd_so_set_button (WorkbookControl *wbc,
+		   SheetObject *so, GnmExprTop const *link,
+		   char *old_label, char *new_label)
+{
+	CmdSOSetButton *me;
+
+	g_return_val_if_fail (IS_WORKBOOK_CONTROL (wbc), TRUE);
+
+	me = g_object_new (CMD_SO_SET_BUTTON_TYPE, NULL);
+	me->cmd.sheet = sheet_object_get_sheet (so);
+	me->cmd.size = 1;
+	me->cmd.cmd_descriptor = g_strdup (_("Configure Button"));
+	me->so = so;
+	me->new_link = link;
+	me->old_label = old_label;
+	me->new_label = new_label;
+
+	me->old_link = sheet_widget_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 01efd7b..c23d143 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -180,6 +180,10 @@ gboolean cmd_so_set_links (WorkbookControl *wbc, SheetObject *so,
 gboolean cmd_so_set_frame_label (WorkbookControl *wbc, SheetObject *so,
 				 char *old_label, char *new_label);
 
+gboolean cmd_so_set_button (WorkbookControl *wbc, SheetObject *so,
+			    GnmExprTop const *link,
+			    char *old_label, char *new_label);
+
 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 9737977..e441309 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,10 @@
+2009-09-23  Andreas J. Guelzow <aguelzow pyrshep ca>
+	slightly modified patches from Albert Gräf <Dr Graef t-online de>
+
+	* so-button.glade: new
+	* Makefile.am: add so-button.glade
+	* help.h: add GNUMERIC_HELP_LINK_SO_BUTTON
+	
 2009-09-20  Morten Welinder <terra gnome org>
 
 	* Release 1.9.13
diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am
index ec44c36..debd628 100644
--- a/src/dialogs/Makefile.am
+++ b/src/dialogs/Makefile.am
@@ -102,7 +102,7 @@ glade_DATA = 				\
 	cell-comment.glade		\
 	cell-format.glade		\
 	cell-sort.glade			\
-	chi-squared.glade			\
+	chi-squared.glade		\
 	col-width.glade			\
 	colrow.glade			\
 	consolidate.glade		\
@@ -149,8 +149,9 @@ glade_DATA = 				\
 	scenario-manager.glade		\
 	search-replace.glade		\
 	sheet-order.glade		\
-	sheet-resize.glade                \
+	sheet-resize.glade              \
 	shuffle.glade			\
+	so-button.glade			\
 	so-checkbox.glade		\
 	so-frame.glade			\
 	so-list.glade			\
diff --git a/src/dialogs/help.h b/src/dialogs/help.h
index 8f26fc5..ef8874a 100644
--- a/src/dialogs/help.h
+++ b/src/dialogs/help.h
@@ -20,6 +20,7 @@
 /* ../sheet-object-widget.c    */
 #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_CHECKBOX	 "sect-graphics-drawings"
 #define GNUMERIC_HELP_LINK_SO_LIST	 "sect-graphics-drawings"
 
diff --git a/src/dialogs/so-button.glade b/src/dialogs/so-button.glade
new file mode 100644
index 0000000..9acbabc
--- /dev/null
+++ b/src/dialogs/so-button.glade
@@ -0,0 +1,167 @@
+<?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-Button">
+  <property name="border_width">6</property>
+  <property name="title" translatable="yes">Button 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="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="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="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="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">2</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="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>
+	    </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">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>
+	      <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">fill</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>
+	</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/sheet-object-widget.c b/src/sheet-object-widget.c
index 6cd9302..e28086f 100644
--- a/src/sheet-object-widget.c
+++ b/src/sheet-object-widget.c
@@ -525,27 +525,112 @@ SOW_MAKE_TYPE (frame, Frame,
 /****************************************************************************/
 #define SHEET_WIDGET_BUTTON_TYPE     (sheet_widget_button_get_type ())
 #define SHEET_WIDGET_BUTTON(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj), SHEET_WIDGET_BUTTON_TYPE, SheetWidgetButton))
+#define DEP_TO_BUTTON(d_ptr)		(SheetWidgetButton *)(((char *)d_ptr) - G_STRUCT_OFFSET(SheetWidgetButton, dep))
 typedef struct {
 	SheetObjectWidget	sow;
+
+	GnmDependent	 dep;
 	char *label;
 	PangoAttrList *markup;
+	gboolean	 value;
 } SheetWidgetButton;
 typedef SheetObjectWidgetClass SheetWidgetButtonClass;
 
+enum {
+	SOB_PROP_0 = 0,
+	SOB_PROP_TEXT,
+	SOB_PROP_MARKUP
+};
+
+static void
+sheet_widget_button_get_property (GObject *obj, guint param_id,
+				    GValue  *value, GParamSpec *pspec)
+{
+	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (obj);
+
+	switch (param_id) {
+	case SOB_PROP_TEXT:
+		g_value_set_string (value, swb->label);
+		break;
+	case SOB_PROP_MARKUP:
+		g_value_set_boxed (value, NULL); /* swb->markup */
+		break;
+	default :
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		break;
+	}
+}
+
+static void
+sheet_widget_button_set_property (GObject *obj, guint param_id,
+				    GValue const *value, GParamSpec *pspec)
+{
+	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (obj);
+
+	switch (param_id) {
+	case SOB_PROP_TEXT:
+		sheet_widget_button_set_label (SHEET_OBJECT (swb),
+						 g_value_get_string (value));
+		break;
+	case SOB_PROP_MARKUP:
+#if 0
+		sheet_widget_button_set_markup (SHEET_OBJECT (swb),
+						g_value_peek_pointer (value));
+#endif
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+		return;
+	}
+}
+
+static void
+button_eval (GnmDependent *dep)
+{
+	GnmValue *v;
+	GnmEvalPos pos;
+	gboolean err, result;
+
+	v = gnm_expr_top_eval (dep->texpr, eval_pos_init_dep (&pos, dep),
+			       GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
+	result = value_get_as_bool (v, &err);
+	value_release (v);
+	if (!err) {
+		SheetWidgetButton *swb = DEP_TO_BUTTON(dep);
+
+		swb->value = result;
+	}
+}
+
+static void
+button_debug_name (GnmDependent const *dep, GString *target)
+{
+	g_string_append_printf (target, "Button%p", (void *)dep);
+}
+
+static DEPENDENT_MAKE_TYPE (button, NULL)
+
 static void
 sheet_widget_button_init_full (SheetWidgetButton *swb,
+			       GnmCellRef const *ref,
 			       char const *text,
 			       PangoAttrList *markup)
 {
 	swb->label = g_strdup (text);
 	swb->markup = markup;
+	swb->value = FALSE;
+	swb->dep.sheet = NULL;
+	swb->dep.flags = button_get_dep_type ();
+	swb->dep.texpr = (ref != NULL)
+		? gnm_expr_top_new (gnm_expr_new_cellref (ref))
+		: NULL;
 	if (markup) pango_attr_list_ref (markup);
 }
 
 static void
 sheet_widget_button_init (SheetWidgetButton *swb)
 {
-	sheet_widget_button_init_full (swb, _("Button"), NULL);
+	sheet_widget_button_init_full (swb, NULL, _("Button"), NULL);
 }
 
 static void
@@ -561,25 +646,247 @@ sheet_widget_button_finalize (GObject *obj)
 		swb->markup = NULL;
 	}
 
+	dependent_set_expr (&swb->dep, NULL);
+
 	(*sheet_object_widget_class->finalize)(obj);
 }
 
+static void
+cb_button_pressed (GtkToggleButton *button, SheetWidgetButton *swb)
+{
+	GnmCellRef ref;
+
+	swb->value = TRUE;
+
+	if (so_get_ref (SHEET_OBJECT (swb), &ref, TRUE) != NULL) {
+		cmd_so_set_value (widget_wbc (GTK_WIDGET (button)),
+				  _("Pressed Button"),
+				  &ref, value_new_bool (TRUE),
+				  sheet_object_get_sheet (SHEET_OBJECT (swb)));
+	}
+}
+
+static void
+cb_button_released (GtkToggleButton *button, SheetWidgetButton *swb)
+{
+	GnmCellRef ref;
+
+	swb->value = TRUE;
+
+	if (so_get_ref (SHEET_OBJECT (swb), &ref, TRUE) != NULL) {
+		cmd_so_set_value (widget_wbc (GTK_WIDGET (button)),
+				  _("Released Button"),
+				  &ref, value_new_bool (FALSE),
+				  sheet_object_get_sheet (SHEET_OBJECT (swb)));
+	}
+}
+
 static GtkWidget *
 sheet_widget_button_create_widget (SheetObjectWidget *sow)
 {
 	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (sow);
 	GtkWidget *w = gtk_button_new_with_label (swb->label);
+	GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_FOCUS);
 	gtk_label_set_attributes (GTK_LABEL (GTK_BIN (w)->child),
 				  swb->markup);
+	g_signal_connect (G_OBJECT (w),
+			  "pressed",
+			  G_CALLBACK (cb_button_pressed), swb);
+	g_signal_connect (G_OBJECT (w),
+			  "released",
+			  G_CALLBACK (cb_button_released), swb);
 	return w;
 }
 
 static void
-sheet_widget_button_copy (SheetObject *dst, SheetObject const *src_swb)
+sheet_widget_button_copy (SheetObject *dst, SheetObject const *src)
+{
+	SheetWidgetButton const *src_swb = SHEET_WIDGET_BUTTON (src);
+	SheetWidgetButton       *dst_swb = SHEET_WIDGET_BUTTON (dst);
+	GnmCellRef ref;
+	sheet_widget_button_init_full (dst_swb,
+				       so_get_ref (src, &ref, FALSE),
+				       src_swb->label,
+				       src_swb->markup);
+	dst_swb->value = src_swb->value;
+}
+
+typedef struct {
+	GladeXML           *gui;
+	GtkWidget *dialog;
+	GnmExprEntry *expression;
+	GtkWidget *label;
+
+	char *old_label;
+	GtkWidget *old_focus;
+
+	WBCGtk  *wbcg;
+	SheetWidgetButton *swb;
+	Sheet		    *sheet;
+} ButtonConfigState;
+
+static void
+cb_button_set_focus (GtkWidget *window, GtkWidget *focus_widget,
+		       ButtonConfigState *state)
+{
+	/* 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;
+}
+
+static void
+cb_button_config_destroy (ButtonConfigState *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);
+	state->old_label = NULL;
+	state->dialog = NULL;
+	g_free (state);
+}
+
+static void
+cb_button_config_ok_clicked (GtkWidget *button, ButtonConfigState *state)
+{
+	SheetObject *so = SHEET_OBJECT (state->swb);
+	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));
+
+	cmd_so_set_button (WORKBOOK_CONTROL (state->wbcg), so,
+			     texpr, g_strdup (state->old_label), g_strdup (text));
+
+	gtk_widget_destroy (state->dialog);
+}
+
+static void
+cb_button_config_cancel_clicked (GtkWidget *button, ButtonConfigState *state)
 {
-	sheet_widget_button_init_full (SHEET_WIDGET_BUTTON (dst),
-				       SHEET_WIDGET_BUTTON (src_swb)->label,
-				       SHEET_WIDGET_BUTTON (src_swb)->markup);
+	sheet_widget_button_set_label	(SHEET_OBJECT (state->swb),
+					 state->old_label);
+	gtk_widget_destroy (state->dialog);
+}
+
+static void
+cb_button_label_changed (GtkEntry *entry, ButtonConfigState *state)
+{
+	sheet_widget_button_set_label	(SHEET_OBJECT (state->swb),
+					 gtk_entry_get_text (entry));
+}
+
+static void
+sheet_widget_button_user_config (SheetObject *so, SheetControl *sc)
+{
+	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (so);
+	WBCGtk  *wbcg = scg_wbcg (SHEET_CONTROL_GUI (sc));
+	ButtonConfigState *state;
+	GtkWidget *table;
+
+	g_return_if_fail (swb != NULL);
+
+	/* Only pop up one copy per workbook */
+	if (gnumeric_dialog_raise_if_exists (wbcg, SHEET_OBJECT_CONFIG_KEY))
+		return;
+
+	state = g_new (ButtonConfigState, 1);
+	state->swb = swb;
+	state->wbcg = wbcg;
+	state->sheet = sc_sheet	(sc);
+	state->old_focus = NULL;
+	state->old_label = g_strdup (swb->label);
+	state->gui = gnm_glade_xml_new (GO_CMD_CONTEXT (wbcg),
+		"so-button.glade", NULL, NULL);
+	state->dialog = glade_xml_get_widget (state->gui, "SO-Button");
+
+	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, &swb->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), swb->label);
+	gtk_editable_select_region (GTK_EDITABLE(state->label), 0, -1);
+	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
+				  GTK_WIDGET (state->expression));
+	gnumeric_editable_enters (GTK_WINDOW (state->dialog),
+				  GTK_WIDGET (state->label));
+
+	g_signal_connect (G_OBJECT (state->label),
+		"changed",
+		G_CALLBACK (cb_button_label_changed), state);
+	g_signal_connect (G_OBJECT (glade_xml_get_widget (state->gui, "ok_button")),
+		"clicked",
+		G_CALLBACK (cb_button_config_ok_clicked), state);
+	g_signal_connect (G_OBJECT (glade_xml_get_widget (state->gui, "cancel_button")),
+		"clicked",
+		G_CALLBACK (cb_button_config_cancel_clicked), state);
+
+	gnumeric_init_help_button (
+		glade_xml_get_widget (state->gui, "help_button"),
+		GNUMERIC_HELP_LINK_SO_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_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_button_set_focus), state);
+
+	gtk_widget_show (state->dialog);
+}
+
+static gboolean
+sheet_widget_button_set_sheet (SheetObject *so, Sheet *sheet)
+{
+	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (so);
+
+	dependent_set_sheet (&swb->dep, sheet);
+
+	return FALSE;
+}
+
+static void
+sheet_widget_button_foreach_dep (SheetObject *so,
+				   SheetObjectForeachDepFunc func,
+				   gpointer user)
+{
+	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (so);
+	func (&swb->dep, so, user);
 }
 
 static void
@@ -589,6 +896,8 @@ sheet_widget_button_write_xml_sax (SheetObject const *so, GsfXMLOut *output,
 	/* FIXME: markup */
 	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (so);
 	gsf_xml_out_add_cstr (output, "Label", swb->label);
+	gsf_xml_out_add_int (output, "Value", swb->value);
+	sax_write_dep (output, &swb->dep, "Input", convs);
 }
 
 static void
@@ -600,9 +909,35 @@ sheet_widget_button_prep_sax_parser (SheetObject *so, GsfXMLIn *xin,
 	for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
 		if (attr_eq (attrs[0], "Label"))
 			g_object_set (G_OBJECT (swb), "text", attrs[1], NULL);
+		else if (gnm_xml_attr_int (attrs, "Value", &swb->value))
+			;
+		else if (sax_read_dep (attrs, "Input", &swb->dep, xin, convs))
+			;
 }
 
 void
+sheet_widget_button_set_link (SheetObject *so, GnmExprTop const *texpr)
+{
+ 	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (so);
+ 	dependent_set_expr (&swb->dep, texpr);
+ 	if (NULL != texpr)
+ 		dependent_link (&swb->dep);
+}
+
+GnmExprTop const *
+sheet_widget_button_get_link	 (SheetObject *so)
+{
+ 	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (so);
+ 	GnmExprTop const *texpr = swb->dep.texpr;
+	
+ 	if (texpr)
+ 		gnm_expr_top_ref (texpr);
+	
+ 	return texpr;
+}
+
+
+void
 sheet_widget_button_set_label (SheetObject *so, char const *str)
 {
 	GList *ptr;
@@ -644,57 +979,11 @@ sheet_widget_button_set_markup (SheetObject *so, PangoAttrList *markup)
 	}
 }
 
-enum {
-	SOB_PROP_0 = 0,
-	SOB_PROP_TEXT,
-	SOB_PROP_MARKUP
-};
-
-static void
-sheet_widget_button_get_property (GObject *obj, guint param_id,
-				  GValue  *value, GParamSpec *pspec)
-{
-	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (obj);
-
-	switch (param_id) {
-	case SOB_PROP_TEXT:
-		g_value_set_string (value, swb->label);
-		break;
-	case SOB_PROP_MARKUP:
-		g_value_set_boxed (value, swb->markup);
-		break;
-	default :
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
-		break;
-	}
-}
-
-static void
-sheet_widget_button_set_property (GObject *obj, guint param_id,
-				  GValue const *value, GParamSpec *pspec)
-{
-	SheetWidgetButton *swb = SHEET_WIDGET_BUTTON (obj);
-
-	switch (param_id) {
-	case SOB_PROP_TEXT:
-		sheet_widget_button_set_label (SHEET_OBJECT (swb),
-					       g_value_get_string (value));
-		break;
-	case SOB_PROP_MARKUP:
-		sheet_widget_button_set_markup (SHEET_OBJECT (swb),
-						g_value_peek_pointer (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
-		return;
-	}
-}
-
 SOW_MAKE_TYPE (button, Button,
-	       NULL,
-	       NULL,
-	       NULL,
-	       NULL,
+	       sheet_widget_button_user_config,
+	       sheet_widget_button_set_sheet,
+	       so_clear_sheet,
+	       sheet_widget_button_foreach_dep,
 	       sheet_widget_button_copy,
 	       sheet_widget_button_write_xml_sax,
 	       sheet_widget_button_prep_sax_parser,
diff --git a/src/sheet-object-widget.h b/src/sheet-object-widget.h
index 61346fd..2bc59f7 100644
--- a/src/sheet-object-widget.h
+++ b/src/sheet-object-widget.h
@@ -41,6 +41,9 @@ 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 *result_link);
+GnmExprTop const *sheet_widget_button_get_link (SheetObject *so);
 void sheet_widget_button_set_label	 (SheetObject *so, char const *str);
 void sheet_widget_radio_button_set_label (SheetObject *so, char const *str);
 



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