PATCH: generalized selection widget

Derek Atkins warlord@MIT.EDU
09 Nov 2001 17:26:38 -0500


I mentioned on this list earlier my suggestion for a more general
selection widget.  I've made the first step in that generalization,
and included herein are the patches that implement it.

This patch changes the current commodity-editor into a general
'selection' widget.  Basically, what used to be called the
gnc_commodity_edit widget is now the gnc_general_select widget.  It
looks 100% the same as before and, from a user standpoint, it acts
100% as it did before, but internally it behaves differently.  In
particular, it is passing around gpointers instead of gnc_commodity
pointers.

The biggest difference (besides the type reference) is that to create
the widget you need to pass in two call-back functions; one is used to
convert the gpointer to a string, the second is used to create the
second-stage selector that actually performs the object selection.
Those callbacks are now defined in the "new" gnc-commodity-edit.[ch]
files.

This patch adds the gnc-general-select widget, removes the
gnc-commodity-edit widget, and changes all the calls over to the new
widget.  I've compiled and tested this on my Linux box and it works
fine.  I tested the integration with both dialog-account and
dialog-price-editor (I wasn't sure how to instantiate the
druid-hierachy).

Enjoy!

-derek

New Files:
	src/gnome-utils/gnc-general-select.
	src/gnome-utils/gnc-general-select.h

Changed Files:
	src/gnome/dialog-account.c
	src/gnome/dialog-price-editor.c
	src/gnome/druid-hierarchy.c
	src/gnome-utils/Makefile.am
	src/gnome-utils/dialog-options.c
	src/gnome-utils/gnc-commodity-edit.c
	src/gnome-utils/gnc-commodity-edit.h

Index: src/gnome/dialog-account.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/dialog-account.c,v
retrieving revision 1.49
diff -u -r1.49 dialog-account.c
--- src/gnome/dialog-account.c	2001/10/06 08:12:46	1.49
+++ src/gnome/dialog-account.c	2001/11/09 22:14:24
@@ -32,8 +32,9 @@
 #include "global-options.h"
 #include "gnc-account-tree.h"
 #include "gnc-amount-edit.h"
-#include "gnc-commodity-edit.h"
+#include "gnc-general-select.h"
 #include "gnc-commodity.h"
+#include "gnc-commodity-edit.h"
 #include "gnc-component-manager.h"
 #include "gnc-date-edit.h"
 #include "gnc-engine-util.h"
@@ -155,7 +156,7 @@
   gtk_entry_set_text(GTK_ENTRY(aw->description_entry), string);
 
   commodity = xaccAccountGetCommodity (account);
-  gnc_commodity_edit_set_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit),
+  gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
                                     commodity);
 
   string = xaccAccountGetCode (account);
@@ -291,8 +292,8 @@
   if (safe_strcmp (string, old_string) != 0)
     xaccAccountSetDescription (account, string);
 
-  commodity =
-    gnc_commodity_edit_get_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit));
+  commodity = (gnc_commodity *)
+    gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
   if (commodity &&
       !gnc_commodity_equiv(commodity, xaccAccountGetCommodity (account)))
     xaccAccountSetCommodity (account, commodity);
@@ -450,7 +451,7 @@
     gnc_account_window_set_name (aw);
 
     commodity = xaccAccountGetCommodity (parent);
-    gnc_commodity_edit_set_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit),
+    gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
                                       commodity);
 
     gnc_account_tree_select_account (GNC_ACCOUNT_TREE(aw->parent_tree),
@@ -798,8 +799,8 @@
     return;
   }
 
-  commodity =
-    gnc_commodity_edit_get_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit));
+  commodity = (gnc_commodity *)
+    gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
 
   if (!commodity)
   {
@@ -949,8 +950,8 @@
   }
 
   /* check for commodity */
-  commodity =
-    gnc_commodity_edit_get_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit));
+  commodity = (gnc_commodity *)
+    gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
 
   if (!commodity)
   {
@@ -1279,12 +1280,12 @@
 }
 
 static void
-commodity_changed_cb (GNCCommodityEdit *gce, gpointer data)
+commodity_changed_cb (GNCGeneralSelect *gsl, gpointer data)
 {
   AccountWindow *aw = data;
   gnc_commodity *currency;
 
-  currency = gnc_commodity_edit_get_commodity (gce);
+  currency = (gnc_commodity *) gnc_general_select_get_selected (gsl);
   if (!currency)
     return;
 
@@ -1305,8 +1306,8 @@
   if (!account)
     return FALSE;
 
-  commodity =
-    gnc_commodity_edit_get_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit));
+  commodity = (gnc_commodity *)
+    gnc_general_select_get_selected (GNC_GENERAL_SELECT (aw->commodity_edit));
 
   return gnc_commodity_equiv (xaccAccountGetCommodity (account), commodity);
 }
@@ -1396,7 +1397,8 @@
   gnome_dialog_editable_enters(awd, GTK_EDITABLE(aw->code_entry));
 
   box = glade_xml_get_widget (xml, "commodity_hbox");
-  aw->commodity_edit = gnc_commodity_edit_new ();
+  aw->commodity_edit = gnc_general_select_new (gnc_commodity_edit_get_string,
+					       gnc_commodity_edit_new_select);
   gtk_box_pack_start(GTK_BOX(box), aw->commodity_edit, TRUE, TRUE, 0);
 
   gtk_signal_connect (GTK_OBJECT (aw->commodity_edit), "changed",
@@ -1643,7 +1645,7 @@
 
   commodity = gnc_default_currency ();
 
-  gnc_commodity_edit_set_commodity (GNC_COMMODITY_EDIT (aw->commodity_edit),
+  gnc_general_select_set_selected (GNC_GENERAL_SELECT (aw->commodity_edit),
                                     commodity);
 
   gtk_widget_show_all (aw->dialog);

Index: src/gnome/dialog-price-editor.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/dialog-price-editor.c,v
retrieving revision 1.20
diff -u -r1.20 dialog-price-editor.c
--- src/gnome/dialog-price-editor.c	2001/10/05 09:54:39	1.20
+++ src/gnome/dialog-price-editor.c	2001/11/09 22:14:24
@@ -31,6 +31,7 @@
 #include "global-options.h"
 #include "gnc-amount-edit.h"
 #include "gnc-commodity-edit.h"
+#include "gnc-general-select.h"
 #include "gnc-component-manager.h"
 #include "gnc-currency-edit.h"
 #include "gnc-date-edit.h"
@@ -312,8 +313,8 @@
   }
 
   if (commodity)
-    gnc_commodity_edit_set_commodity
-      (GNC_COMMODITY_EDIT (pdb_dialog->commodity_edit), commodity);
+    gnc_general_select_set_selected
+      (GNC_GENERAL_SELECT (pdb_dialog->commodity_edit), commodity);
 
   if (currency)
     gnc_currency_edit_set_currency
@@ -342,8 +343,8 @@
   if (!pdb_dialog->price)
     return NULL;
 
-  commodity = gnc_commodity_edit_get_commodity
-    (GNC_COMMODITY_EDIT (pdb_dialog->commodity_edit));
+  commodity = gnc_general_select_get_selected
+    (GNC_GENERAL_SELECT (pdb_dialog->commodity_edit));
   if (!commodity)
     return _("You must select a commodity.");
 
@@ -677,7 +678,7 @@
 }
 
 static void
-commodity_changed_cb (GNCCommodityEdit *gce, gpointer data)
+commodity_changed_cb (GNCGeneralSelect *gsl, gpointer data)
 {
   PricesDialog *pdb_dialog = data;
 
@@ -799,7 +800,8 @@
 
   box = glade_xml_get_widget (xml, "commodity_box");
 
-  w = gnc_commodity_edit_new ();
+  w = gnc_general_select_new (gnc_commodity_edit_get_string,
+			      gnc_commodity_edit_new_select);
   pdb_dialog->commodity_edit = w;
   gtk_box_pack_start (GTK_BOX (box), w, TRUE, TRUE, 0);
   gtk_widget_show (w);

Index: src/gnome/druid-hierarchy.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/druid-hierarchy.c,v
retrieving revision 1.10
diff -u -r1.10 druid-hierarchy.c
--- src/gnome/druid-hierarchy.c	2001/10/18 00:18:13	1.10
+++ src/gnome/druid-hierarchy.c	2001/11/09 22:14:24
@@ -34,6 +34,7 @@
 #include "druid-utils.h"
 #include "gnc-amount-edit.h"
 #include "gnc-commodity-edit.h"
+#include "gnc-general-select.h"
 #include "gnc-component-manager.h"
 #include "../gnome-utils/gnc-dir.h"
 #include "gnc-gui-query.h"
@@ -95,7 +96,7 @@
   return GTK_CLIST(hierarchy_get_widget ("account_types_clist"));
 }
 
-static GNCCommodityEdit *
+static GNCGeneralSelect *
 get_commodity_editor(void)
 {
   GtkWidget *tmp_wid = gtk_object_get_data (GTK_OBJECT (hierarchy_window),
@@ -103,11 +104,13 @@
 
   if(!tmp_wid)
   {
-    GNCCommodityEdit *cur_editor;
+    GNCGeneralSelect *cur_editor;
 
-    cur_editor = GNC_COMMODITY_EDIT(gnc_commodity_edit_new());
+    cur_editor =
+      GNC_GENERAL_SELECT (gnc_general_select_new(gnc_commodity_edit_get_string,
+						 gnc_commodity_edit_new_select));
     gtk_widget_show (GTK_WIDGET(cur_editor));
-    gnc_commodity_edit_set_commodity (cur_editor,
+    gnc_general_select_set_selected (cur_editor,
                                       gnc_locale_default_currency());
     gtk_object_set_data(GTK_OBJECT(hierarchy_window),
                         "commod_editor", cur_editor);
@@ -115,7 +118,7 @@
   }
   else
   {
-    return GNC_COMMODITY_EDIT(tmp_wid);
+    return GNC_GENERAL_SELECT(tmp_wid);
   }
 }
 
@@ -636,7 +639,7 @@
   gnc_commodity *com;
   AccountGroup *ret = xaccMallocAccountGroup (gnc_get_current_session ());
 
-  com = gnc_commodity_edit_get_commodity (get_commodity_editor ());
+  com = gnc_general_select_get_selected (get_commodity_editor ());
 
   for (mark = dalist; mark; mark = mark->next)
   {

Index: src/gnome-utils/Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Makefile.am,v
retrieving revision 1.19
diff -u -r1.19 Makefile.am
--- src/gnome-utils/Makefile.am	2001/11/08 18:15:16	1.19
+++ src/gnome-utils/Makefile.am	2001/11/09 22:14:25
@@ -31,6 +31,7 @@
   gnc-date-delta.c \
   gnc-date-edit.c \
   gnc-frequency.c \
+  gnc-general-select.c \
   gnc-gui-query.c \
   gnc-html-history.c \
   gnc-html-guppi.c \
@@ -54,6 +55,7 @@
   gnc-date-delta.h \
   gnc-date-edit.h \
   gnc-frequency.h \
+  gnc-general-select.h \
   gnc-gui-query.h \
   gnc-html-history.h \
   gnc-html-guppi.h \

Index: src/gnome-utils/dialog-options.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/dialog-options.c,v
retrieving revision 1.1
diff -u -r1.1 dialog-options.c
--- src/gnome-utils/dialog-options.c	2001/09/24 08:03:42	1.1
+++ src/gnome-utils/dialog-options.c	2001/11/09 22:14:25
@@ -30,6 +30,7 @@
 #include "global-options.h"
 #include "gnc-account-tree.h"
 #include "gnc-commodity-edit.h"
+#include "gnc-general-select.h"
 #include "gnc-currency-edit.h"
 #include "gnc-date-edit.h"
 #include "gnc-engine-util.h"
@@ -274,7 +275,7 @@
 
     commodity = gnc_scm_to_commodity (value);
     if (commodity)
-      gnc_currency_edit_set_currency(GNC_CURRENCY_EDIT(widget), commodity);
+      gnc_general_select_set_selected(GNC_GENERAL_SELECT(widget), commodity);
     else
       bad_value = TRUE;
   }
@@ -284,8 +285,7 @@
 
     commodity = gnc_scm_to_commodity (value);
     if (commodity)
-      gnc_commodity_edit_set_commodity(GNC_COMMODITY_EDIT (widget),
-                                       commodity);
+      gnc_general_select_set_selected(GNC_GENERAL_SELECT (widget), commodity);
     else
       bad_value = TRUE;
   }
@@ -564,7 +564,7 @@
     gnc_commodity *commodity;
 
     commodity =
-      gnc_currency_edit_get_currency(GNC_CURRENCY_EDIT(widget));
+      gnc_general_select_get_selected(GNC_GENERAL_SELECT(widget));
 
     result = gnc_commodity_to_scm (commodity);
   }
@@ -573,7 +573,7 @@
     gnc_commodity *commodity;
 
     commodity =
-      gnc_commodity_edit_get_commodity(GNC_COMMODITY_EDIT(widget));
+      gnc_general_select_get_selected(GNC_GENERAL_SELECT(widget));
 
     result = gnc_commodity_to_scm(commodity);
   }
@@ -1458,16 +1458,17 @@
     g_free(colon_name);
 
     enclosing = gtk_hbox_new(FALSE, 5);
-    value = gnc_commodity_edit_new();
+    value = gnc_general_select_new(gnc_commodity_edit_get_string,
+				   gnc_commodity_edit_new_select);
 
     gnc_option_set_widget (option, value);
     gnc_option_set_ui_value(option, FALSE);
 
     if (documentation != NULL)
-      gtk_tooltips_set_tip(tooltips, GNC_COMMODITY_EDIT(value)->entry,
+      gtk_tooltips_set_tip(tooltips, GNC_GENERAL_SELECT(value)->entry,
                            documentation, NULL);
 
-    gtk_signal_connect(GTK_OBJECT(GNC_COMMODITY_EDIT(value)->entry), "changed",
+    gtk_signal_connect(GTK_OBJECT(GNC_GENERAL_SELECT(value)->entry), "changed",
 		       GTK_SIGNAL_FUNC(gnc_option_changed_cb), option);
 
     gtk_box_pack_start(GTK_BOX(enclosing), label, FALSE, FALSE, 0);

Index: src/gnome-utils/gnc-commodity-edit.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/gnc-commodity-edit.c,v
retrieving revision 1.1
diff -u -r1.1 gnc-commodity-edit.c
--- src/gnome-utils/gnc-commodity-edit.c	2001/09/10 07:01:49	1.1
+++ src/gnome-utils/gnc-commodity-edit.c	2001/11/09 22:14:25
@@ -30,235 +30,24 @@
  * Commodity editor widget
  *
  * Authors: Dave Peticolas <dave@krondo.com>
+ * 	    Derek Atkins <warlord@MIT.EDU>
  */
 
 #include <config.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
 
 #include "dialog-commodity.h"
 #include "gnc-commodity-edit.h"
-#include "guile-util.h"
-#include "messages.h"
 
-/* Signal codes */
-enum
+const char * gnc_commodity_edit_get_string (gpointer ptr)
 {
-  COMMODITY_CHANGED,
-  LAST_SIGNAL
-};
-
-
-static void gnc_commodity_edit_init         (GNCCommodityEdit      *gce);
-static void gnc_commodity_edit_class_init   (GNCCommodityEditClass *class);
-static void gnc_commodity_edit_destroy      (GtkObject             *object);
-
-static GtkHBoxClass *parent_class;
-static guint commodity_edit_signals[LAST_SIGNAL];
-
-
-/**
- * gnc_commodity_edit_get_type:
- *
- * Returns the GtkType for the GNCCommodityEdit widget
- */
-guint
-gnc_commodity_edit_get_type (void)
-{
-	static guint commodity_edit_type = 0;
-
-	if (!commodity_edit_type){
-		GtkTypeInfo commodity_edit_info = {
-			"GNCCommodityEdit",
-			sizeof (GNCCommodityEdit),
-			sizeof (GNCCommodityEditClass),
-			(GtkClassInitFunc) gnc_commodity_edit_class_init,
-			(GtkObjectInitFunc) gnc_commodity_edit_init,
-			NULL,
-			NULL,
-		};
-
-		commodity_edit_type = gtk_type_unique (gtk_hbox_get_type (),
-                                                       &commodity_edit_info);
-	}
-
-	return commodity_edit_type;
-}
-
-static void
-gnc_commodity_edit_forall (GtkContainer *container, gboolean include_internals,
-                           GtkCallback callback, gpointer callback_data)
-{
-	g_return_if_fail (container != NULL);
-	g_return_if_fail (GNC_IS_COMMODITY_EDIT (container));
-	g_return_if_fail (callback != NULL);
-
-	/* Let GtkBox handle things only if the internal widgets need
-	 * to be poked. */
-        if (!include_internals)
-                return;
-
-        if (!GTK_CONTAINER_CLASS (parent_class)->forall)
-                return;
-
-        GTK_CONTAINER_CLASS (parent_class)->forall (container,
-                                                    include_internals,
-                                                    callback,
-                                                    callback_data);
+  gnc_commodity * comm = (gnc_commodity *)ptr;
+  return gnc_commodity_get_printname(comm);
 }
 
-static void
-gnc_commodity_edit_class_init (GNCCommodityEditClass *klass)
+gpointer gnc_commodity_edit_new_select (gpointer ptr, GtkWidget *toplevel)
 {
-	GtkObjectClass *object_class = (GtkObjectClass *) klass;
-	GtkContainerClass *container_class = (GtkContainerClass *) klass;
-
-	object_class = (GtkObjectClass*) klass;
-
-	parent_class = gtk_type_class (gtk_hbox_get_type ());
-
-        commodity_edit_signals[COMMODITY_CHANGED] =
-                gtk_signal_new("changed",
-                               GTK_RUN_FIRST,
-                               object_class->type,
-                               GTK_SIGNAL_OFFSET(GNCCommodityEditClass,
-                                                 changed),
-                               gtk_marshal_NONE__NONE,
-                               GTK_TYPE_NONE, 0);
-
-        gtk_object_class_add_signals(object_class,
-                                     commodity_edit_signals,
-                                     LAST_SIGNAL);
-
-	container_class->forall = gnc_commodity_edit_forall;
-
-	object_class->destroy = gnc_commodity_edit_destroy;
-
-        klass->changed = NULL;
-}
-
-static void
-gnc_commodity_edit_init (GNCCommodityEdit *gce)
-{
-        gce->selected_commodity = NULL;
-}
-
-static void
-gnc_commodity_edit_destroy (GtkObject *object)
-{
-        GNCCommodityEdit *gce;
-
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (GNC_IS_COMMODITY_EDIT (object));
-
-        gce = GNC_COMMODITY_EDIT (object);
-
-        gce->entry = NULL;
-        gce->button = NULL;
-
-	if (GTK_OBJECT_CLASS (parent_class)->destroy)
-		GTK_OBJECT_CLASS (parent_class)->destroy (object);
-}
-
-static void
-select_currency_cb(GtkButton * button, gpointer user_data)
-{
-        GNCCommodityEdit *gce = user_data;
-        gnc_commodity *new_commodity;
-        GtkWidget *toplevel;
-
-        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
-
-        new_commodity = gnc_ui_select_commodity_modal(gce->selected_commodity,
-                                                      toplevel);
-
-        /* NULL return means cancel; no change */
-        if (new_commodity == NULL)
-                return;
-
-        gnc_commodity_edit_set_commodity (gce, new_commodity);
-}
-
-static void
-create_children (GNCCommodityEdit *gce)
-{
-        gce->entry = gtk_entry_new ();
-        gtk_entry_set_editable (GTK_ENTRY (gce->entry), FALSE);
-	gtk_box_pack_start (GTK_BOX (gce), gce->entry, TRUE, TRUE, 0);
-        gtk_widget_show (gce->entry);
-
-        gce->button = gtk_button_new_with_label (_("Select..."));
-	gtk_box_pack_start (GTK_BOX (gce), gce->button, FALSE, FALSE, 0);
-        gtk_signal_connect (GTK_OBJECT (gce->button), "clicked",
-                            select_currency_cb, gce);
-        gtk_widget_show (gce->button);
-}
-
-/**
- * gnc_commodity_edit_new:
- *
- * Creates a new GNCCommodityEdit widget which can be used to provide
- * an easy way to enter ISO commodity codes.
- *
- * Returns a GNCCommodityEdit widget.
- */
-GtkWidget *
-gnc_commodity_edit_new (void)
-{
-	GNCCommodityEdit *gce;
-
-	gce = gtk_type_new (gnc_commodity_edit_get_type ());
-
-	create_children (gce);
-
-	return GTK_WIDGET (gce);
-}
-
-/**
- * gnc_commodity_edit_set_commodity:
- * @gce: the commodity editor widget
- * @commodity: the commodity code to select
- *
- * Sets the commodity value of the widget to a particular commodity.
- *
- * Returns nothing.
- */
-void
-gnc_commodity_edit_set_commodity (GNCCommodityEdit *gce,
-                                  gnc_commodity *commodity)
-{
-        const char *text;
-
-        g_return_if_fail(gce != NULL);
-        g_return_if_fail(GNC_IS_COMMODITY_EDIT(gce));
-
-        gce->selected_commodity = commodity;
-
-        if (commodity == NULL)
-                text = "";
-        else
-                text = gnc_commodity_get_printname(commodity);
-
-        gtk_entry_set_text(GTK_ENTRY(gce->entry), text);
-
-        gtk_signal_emit(GTK_OBJECT(gce),
-                        commodity_edit_signals[COMMODITY_CHANGED]);
-}
-
-/**
- * gnc_commodity_edit_get_commodity:
- * @gce: the commodity editor widget
- *
- * Returns the commodity currently selected by the widget.
- */
-gnc_commodity *
-gnc_commodity_edit_get_commodity (GNCCommodityEdit *gce)
-{
-        g_return_val_if_fail(gce != NULL, NULL);
-        g_return_val_if_fail(GNC_IS_COMMODITY_EDIT(gce), NULL);
-
-        return gce->selected_commodity;
+  gnc_commodity * comm = (gnc_commodity *)ptr;
+  return gnc_ui_select_commodity_modal(comm, toplevel);
 }
 
 /*

Index: src/gnome-utils/gnc-commodity-edit.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/gnc-commodity-edit.h,v
retrieving revision 1.2
diff -u -r1.2 gnc-commodity-edit.h
--- src/gnome-utils/gnc-commodity-edit.h	2001/09/24 22:58:35	1.2
+++ src/gnome-utils/gnc-commodity-edit.h	2001/11/09 22:14:25
@@ -5,6 +5,7 @@
  * All rights reserved.
  *
  * Dave Peticolas <dave@krondo.com>
+ * Derek Atkins <warlord@MIT.EDU>
  *
  * GnuCash is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Library General Public License as
@@ -32,41 +33,13 @@
 #define GNC_COMMODITY_EDIT_H
 
 #include <gnome.h>
-
 #include "gnc-commodity.h"
-
-BEGIN_GNOME_DECLS
-
-
-#define GNC_COMMODITY_EDIT(obj)          GTK_CHECK_CAST (obj, gnc_commodity_edit_get_type(), GNCCommodityEdit)
-#define GNC_COMMODITY_EDIT_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gnc_commodity_edit_get_type(), GNCCommodityEditClass)
-#define GNC_IS_COMMODITY_EDIT(obj)       GTK_CHECK_TYPE (obj, gnc_commodity_edit_get_type ())
-
-typedef struct {
-        GtkHBox hbox;
-
-        GtkWidget *entry;  /* display of commodity name */
-        GtkWidget *button; /* button for popping up commodity window */
-
-        gnc_commodity *selected_commodity;
-} GNCCommodityEdit;
-
-typedef struct {
-        GtkHBoxClass parent_class;
-
-        void (*changed) (GNCCommodityEdit *edit);
-} GNCCommodityEditClass;
-
-guint      gnc_commodity_edit_get_type       (void);
-
-GtkWidget *gnc_commodity_edit_new            (void);
-
-void       gnc_commodity_edit_set_commodity  (GNCCommodityEdit *gce,
-                                              gnc_commodity *commodity);
 
-gnc_commodity * gnc_commodity_edit_get_commodity (GNCCommodityEdit *gce);
+/* Callback function to return the printable string of a commodity */
+const char * gnc_commodity_edit_get_string (gpointer ptr);
 
-END_GNOME_DECLS
+/* Callback function to popup a new selection (modal) dialog */
+gpointer gnc_commodity_edit_new_select (gpointer ptr, GtkWidget *toplevel);
 
 #endif
 
Index: src/gnome-utils/gnc-general-select.c
===================================================================
--- /dev/null	Fri Mar 23 23:37:44 2001
+++ src/gnome-utils/gnc-general-select.c	Fri Nov  9 16:10:18 2001
@@ -0,0 +1,280 @@
+/*
+ * gnc-general-select.c --  General Selection Widget
+ *
+ * Copyright (C) 2001 Free Software Foundation
+ * All rights reserved.
+ *
+ * Derek Atkins <warlord@MIT.EDU>
+ *
+ * Gnucash is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Gnucash is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+ * Boston, MA  02111-1307,  USA       gnu@gnu.org
+ *
+ */
+/*
+  @NOTATION@
+ */
+
+#include <config.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "gnc-general-select.h"
+
+/* Signal codes */
+enum
+{
+  SELECTION_CHANGED,
+  LAST_SIGNAL
+};
+
+
+static void gnc_general_select_init         (GNCGeneralSelect      *gsl);
+static void gnc_general_select_class_init   (GNCGeneralSelectClass *class);
+static void gnc_general_select_destroy      (GtkObject             *object);
+
+static GtkHBoxClass *parent_class;
+static guint general_select_signals[LAST_SIGNAL];
+
+
+/**
+ * gnc_general_select_get_type:
+ *
+ * Returns the GtkType for the GNCGeneralSelect widget
+ */
+guint
+gnc_general_select_get_type (void)
+{
+	static guint general_select_type = 0;
+
+	if (!general_select_type){
+		GtkTypeInfo general_select_info = {
+			"GNCGeneralSelect",
+			sizeof (GNCGeneralSelect),
+			sizeof (GNCGeneralSelectClass),
+			(GtkClassInitFunc) gnc_general_select_class_init,
+			(GtkObjectInitFunc) gnc_general_select_init,
+			NULL,
+			NULL,
+		};
+
+		general_select_type = gtk_type_unique (gtk_hbox_get_type (),
+                                                       &general_select_info);
+	}
+
+	return general_select_type;
+}
+
+static void
+gnc_general_select_forall (GtkContainer *container, gboolean include_internals,
+                           GtkCallback callback, gpointer callback_data)
+{
+	g_return_if_fail (container != NULL);
+	g_return_if_fail (GNC_IS_GENERAL_SELECT (container));
+	g_return_if_fail (callback != NULL);
+
+	/* Let GtkBox handle things only if the internal widgets need
+	 * to be poked. */
+        if (!include_internals)
+                return;
+
+        if (!GTK_CONTAINER_CLASS (parent_class)->forall)
+                return;
+
+        GTK_CONTAINER_CLASS (parent_class)->forall (container,
+                                                    include_internals,
+                                                    callback,
+                                                    callback_data);
+}
+
+static void
+gnc_general_select_class_init (GNCGeneralSelectClass *klass)
+{
+	GtkObjectClass *object_class = (GtkObjectClass *) klass;
+	GtkContainerClass *container_class = (GtkContainerClass *) klass;
+
+	object_class = (GtkObjectClass*) klass;
+
+	parent_class = gtk_type_class (gtk_hbox_get_type ());
+
+        general_select_signals[SELECTION_CHANGED] =
+                gtk_signal_new("changed",
+                               GTK_RUN_FIRST,
+                               object_class->type,
+                               GTK_SIGNAL_OFFSET(GNCGeneralSelectClass,
+                                                 changed),
+                               gtk_marshal_NONE__NONE,
+                               GTK_TYPE_NONE, 0);
+
+        gtk_object_class_add_signals(object_class,
+                                     general_select_signals,
+                                     LAST_SIGNAL);
+
+	container_class->forall = gnc_general_select_forall;
+
+	object_class->destroy = gnc_general_select_destroy;
+
+        klass->changed = NULL;
+}
+
+static void
+gnc_general_select_init (GNCGeneralSelect *gsl)
+{
+        gsl->selected_item = NULL;
+}
+
+static void
+gnc_general_select_destroy (GtkObject *object)
+{
+        GNCGeneralSelect *gsl;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GNC_IS_GENERAL_SELECT (object));
+
+        gsl = GNC_GENERAL_SELECT (object);
+
+        gsl->entry = NULL;
+        gsl->button = NULL;
+
+	if (GTK_OBJECT_CLASS (parent_class)->destroy)
+		GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+select_cb(GtkButton * button, gpointer user_data)
+{
+        GNCGeneralSelect *gsl = user_data;
+	gpointer new_selection;
+        GtkWidget *toplevel;
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
+
+        new_selection = (gsl->new_select)(gsl->selected_item, toplevel);
+
+        /* NULL return means cancel; no change */
+        if (new_selection == NULL)
+                return;
+
+        gnc_general_select_set_selected (gsl, new_selection);
+}
+
+static void
+create_children (GNCGeneralSelect *gsl)
+{
+        gsl->entry = gtk_entry_new ();
+        gtk_entry_set_editable (GTK_ENTRY (gsl->entry), FALSE);
+	gtk_box_pack_start (GTK_BOX (gsl), gsl->entry, TRUE, TRUE, 0);
+        gtk_widget_show (gsl->entry);
+
+        gsl->button = gtk_button_new_with_label (_("Select..."));
+	gtk_box_pack_start (GTK_BOX (gsl), gsl->button, FALSE, FALSE, 0);
+        gtk_signal_connect (GTK_OBJECT (gsl->button), "clicked",
+                            select_cb, gsl);
+        gtk_widget_show (gsl->button);
+}
+
+/**
+ * gnc_general_select_new:
+ *
+ * Creates a new GNCGeneralSelect widget which can be used to provide
+ * an easy way to choose selections
+ *
+ * Returns a GNCGeneralSelect widget.
+ */
+GtkWidget *
+gnc_general_select_new (GNCGeneralSelectGetStringCB get_string,
+			GNCGeneralSelectNewSelectCB new_select)
+{
+	GNCGeneralSelect *gsl;
+	g_return_val_if_fail (get_string != NULL, NULL);
+	g_return_val_if_fail (new_select != NULL, NULL);
+
+	gsl = gtk_type_new (gnc_general_select_get_type ());
+
+	create_children (gsl);
+	gsl->get_string = get_string;
+	gsl->new_select = new_select;
+
+	return GTK_WIDGET (gsl);
+}
+
+/*
+ * gnc_general_select_get_printname:
+ * @gsl: the general selection widget
+ * @selection: the selection to get the printname
+ *
+ * returns the printable name of the selection
+ */
+const char *
+gnc_general_select_get_printname (GNCGeneralSelect *gsl, gpointer selection)
+{
+  g_return_val_if_fail (gsl != NULL, NULL);
+  g_return_val_if_fail (selection != NULL, NULL);
+
+  return (gsl->get_string)(selection);
+}
+
+/**
+ * gnc_general_select_set_selected:
+ * @gsl: the general selection widget
+ * @selection: the selection to point to
+ *
+ * Sets the selection value of the widget to a particular pointer.
+ *
+ * Returns nothing.
+ */
+void
+gnc_general_select_set_selected (GNCGeneralSelect *gsl, gpointer selection)
+{
+        const char *text;
+
+        g_return_if_fail(gsl != NULL);
+        g_return_if_fail(GNC_IS_GENERAL_SELECT(gsl));
+
+        gsl->selected_item = selection;
+
+        if (selection == NULL)
+                text = "";
+        else
+                text = gnc_general_select_get_printname(gsl, selection);
+
+        gtk_entry_set_text(GTK_ENTRY(gsl->entry), text);
+
+        gtk_signal_emit(GTK_OBJECT(gsl),
+                        general_select_signals[SELECTION_CHANGED]);
+}
+
+/**
+ * gnc_general_select_get_commodity:
+ * @gsl: the general selection widget
+ *
+ * Returns the current selection by the widget.
+ */
+gpointer
+gnc_general_select_get_selected (GNCGeneralSelect *gsl)
+{
+        g_return_val_if_fail(gsl != NULL, NULL);
+        g_return_val_if_fail(GNC_IS_GENERAL_SELECT(gsl), NULL);
+
+        return gsl->selected_item;
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 8
+  End:
+*/

Index: src/gnome-utils/gnc-general-select.h
===================================================================
--- /dev/null	Fri Mar 23 23:37:44 2001
+++ src/gnome-utils/gnc-general-select.h	Fri Nov  9 15:45:39 2001
@@ -0,0 +1,82 @@
+/*
+ * gnc-general-select.h -- General Selection Widget
+ *
+ * Copyright (C) 2001 Free Software Foundation
+ * All rights reserved.
+ *
+ * Derek Atkins <warlord@MIT.EDU>
+ *
+ * GnuCash is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Gnucash is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+ * Boston, MA  02111-1307,  USA       gnu@gnu.org
+ *
+ */
+/*
+  @NOTATION@
+ */
+
+#ifndef GNC_GENERAL_SELECT_H
+#define GNC_GENERAL_SELECT_H
+
+#include <gnome.h>
+
+BEGIN_GNOME_DECLS
+
+
+#define GNC_GENERAL_SELECT(obj)          GTK_CHECK_CAST (obj, gnc_general_select_get_type(), GNCGeneralSelect)
+#define GNC_GENERAL_SELECT_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gnc_general_select_get_type(), GNCGeneralSelectClass)
+#define GNC_IS_GENERAL_SELECT(obj)       GTK_CHECK_TYPE (obj, gnc_general_select_get_type ())
+
+typedef struct {
+  GtkHBox hbox;
+
+  GtkWidget *entry;  /* display of selection name */
+  GtkWidget *button; /* button for popping up selection window */
+
+  gpointer selected_item;
+
+  const char *	(*get_string) (gpointer ptr);
+  gpointer	(*new_select) (gpointer ptr, GtkWidget *toplevel);
+} GNCGeneralSelect;
+
+typedef struct {
+  GtkHBoxClass parent_class;
+
+  void 		(*changed) (GNCGeneralSelect *edit);
+} GNCGeneralSelectClass;
+
+typedef const char *	(*GNCGeneralSelectGetStringCB) (gpointer);
+typedef gpointer 	(*GNCGeneralSelectNewSelectCB) (gpointer, GtkWidget *);
+
+GtkWidget *gnc_general_select_new            (GNCGeneralSelectGetStringCB get_string,
+					      GNCGeneralSelectNewSelectCB new_select);
+void       gnc_general_select_set_selected   (GNCGeneralSelect *gsl,
+					      gpointer selected);
+gpointer   gnc_general_select_get_selected   (GNCGeneralSelect *gsl);
+const char *gnc_general_select_get_printname (GNCGeneralSelect *gsl,
+					      gpointer selection);
+guint      gnc_general_select_get_type       (void);
+
+
+END_GNOME_DECLS
+
+#endif
+
+/*
+  Local Variables:
+  c-basic-offset: 8
+  End:
+*/

-- 
       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL: http://web.mit.edu/warlord/    PP-ASEL-IA     N1NWH
       warlord@MIT.EDU                        PGP key available