[glabels] Create new glFieldButton widget family



commit 797627cec95e55d0305a0b7aa81811cd5be291a4
Author: Jim Evins <evins snaught com>
Date:   Mon Oct 19 23:59:02 2009 -0400

    Create new glFieldButton widget family
    
    Created new glFieldButton widget family modelled after glFontCombo.  This
    widget is for inserting merge fields into text.  This button will pop-up
    a menu containing possible field keys.  The button attempts to place the
    menu intelligently, rather than simply where the button was pressed.
    
    Renamed glWdgtMergeMenu to glFieldButtonMenu.

 data/builder/object-editor.builder             |   10 +-
 po/POTFILES.in                                 |    6 +-
 src/Makefile.am                                |    6 +-
 src/debug.c                                    |    4 +-
 src/debug.h                                    |    4 +-
 src/{wdgt-merge-menu.c => field-button-menu.c} |   97 ++++----
 src/field-button-menu.h                        |   82 +++++++
 src/field-button.c                             |  294 ++++++++++++++++++++++++
 src/field-button.h                             |   82 +++++++
 src/object-editor-edit-page.c                  |   40 +---
 src/object-editor-private.h                    |    2 +-
 src/object-editor.c                            |   10 +-
 src/wdgt-merge-menu.h                          |   82 -------
 13 files changed, 540 insertions(+), 179 deletions(-)
---
diff --git a/data/builder/object-editor.builder b/data/builder/object-editor.builder
index 5cfb900..365f426 100644
--- a/data/builder/object-editor.builder
+++ b/data/builder/object-editor.builder
@@ -86,12 +86,12 @@
                         <property name="visible">True</property>
                         <property name="spacing">12</property>
                         <child>
-                          <object class="GtkButton" id="edit_insert_field_button">
-                            <property name="label" translatable="yes">Insert merge field</property>
+                          <object class="GtkVBox" id="edit_insert_field_vbox">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <placeholder/>
+                            </child>
                           </object>
                           <packing>
                             <property name="fill">False</property>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index de755fa..e0c51d3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -38,6 +38,10 @@ src/critical-error-handler.c
 src/critical-error-handler.h
 src/debug.c
 src/debug.h
+src/field-button.c
+src/field-button.h
+src/field-button-menu.c
+src/field-button-menu.h
 src/file.c
 src/file.h
 src/file-util.c
@@ -167,8 +171,6 @@ src/wdgt-chain-button.c
 src/wdgt-chain-button.h
 src/wdgt-media-select.c
 src/wdgt-media-select.h
-src/wdgt-merge-menu.c
-src/wdgt-merge-menu.h
 src/window.c
 src/window.h
 src/xml-label-04.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 2c31274..6008dee 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -179,8 +179,10 @@ glabels_SOURCES = 			\
 	rotate-label-button.h		\
 	wdgt-chain-button.c		\
 	wdgt-chain-button.h		\
-	wdgt-merge-menu.c		\
-	wdgt-merge-menu.h		\
+	field-button.c			\
+	field-button.h			\
+	field-button-menu.c		\
+	field-button-menu.h		\
 	color-combo.c			\
 	color-combo.h			\
 	color-combo-button.c		\
diff --git a/src/debug.c b/src/debug.c
index ce53820..97972e5 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -91,8 +91,8 @@ gl_debug_init (void)
 		debug_flags |= GLABELS_DEBUG_WDGT;
 	if (g_getenv ("GLABELS_DEBUG_PATH") != NULL)
 		debug_flags |= GLABELS_DEBUG_PATH;
-	if (g_getenv ("GLABELS_DEBUG_MERGE_MENU") != NULL)
-		debug_flags |= GLABELS_DEBUG_MERGE_MENU;
+	if (g_getenv ("GLABELS_DEBUG_FIELD_BUTTON") != NULL)
+		debug_flags |= GLABELS_DEBUG_FIELD_BUTTON;
 }
 
 
diff --git a/src/debug.h b/src/debug.h
index 6dced6d..b8bed98 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -62,7 +62,7 @@ typedef enum {
 	GLABELS_DEBUG_EDITOR       = 1 << 19,
 	GLABELS_DEBUG_WDGT         = 1 << 20,
         GLABELS_DEBUG_PATH         = 1 << 21,
-	GLABELS_DEBUG_MERGE_MENU   = 1 << 22,
+	GLABELS_DEBUG_FIELD_BUTTON = 1 << 22,
 } glDebugSection;
 
 
@@ -92,7 +92,7 @@ typedef enum {
 #define	DEBUG_EDITOR	GLABELS_DEBUG_EDITOR, __FILE__, __LINE__, __FUNCTION__
 #define	DEBUG_WDGT	GLABELS_DEBUG_WDGT,   __FILE__, __LINE__, __FUNCTION__
 #define	DEBUG_PATH      GLABELS_DEBUG_PATH,   __FILE__, __LINE__, __FUNCTION__
-#define	DEBUG_MERGE_MENU      GLABELS_DEBUG_MERGE_MENU,   __FILE__, __LINE__, __FUNCTION__
+#define	DEBUG_FIELD_BUTTON      GLABELS_DEBUG_FIELD_BUTTON,   __FILE__, __LINE__, __FUNCTION__
 
 void gl_debug_init (void);
 
diff --git a/src/wdgt-merge-menu.c b/src/field-button-menu.c
similarity index 60%
rename from src/wdgt-merge-menu.c
rename to src/field-button-menu.c
index 9f0d132..a59bb3b 100644
--- a/src/wdgt-merge-menu.c
+++ b/src/field-button-menu.c
@@ -1,5 +1,5 @@
 /*
- *  wdgt-merge-menu.c
+ *  field-button-menu.c
  *  Copyright (C) 2008-2009  Jim Evins <evins snaught com>.
  *
  *  This file is part of gLabels.
@@ -20,7 +20,7 @@
 
 #include <config.h>
 
-#include "wdgt-merge-menu.h"
+#include "field-button-menu.h"
 
 #include <string.h>
 #include <gtk/gtk.h>
@@ -35,17 +35,17 @@
 /*===========================================*/
 
 
-struct _glWdgtMergeMenuPrivate {
+struct _glFieldButtonMenuPrivate {
 
         GList *menu_items;
 };
 
 enum {
-        FIELD_SELECTED,
+        KEY_SELECTED,
         LAST_SIGNAL
 };
 
-typedef void (*glWdgtMergeMenuSignal) (GObject * object, gpointer data);
+typedef void (*glFieldButtonMenuSignal) (GObject * object, gpointer data);
 
 
 /*===========================================*/
@@ -59,62 +59,62 @@ static gint signals[LAST_SIGNAL] = { 0 };
 /* Local function prototypes                 */
 /*===========================================*/
 
-static void gl_wdgt_merge_menu_finalize      (GObject              *object);
+static void gl_field_button_menu_finalize      (GObject              *object);
 
 
 /****************************************************************************/
 /* Boilerplate Object stuff.                                                */
 /****************************************************************************/
-G_DEFINE_TYPE (glWdgtMergeMenu, gl_wdgt_merge_menu, GTK_TYPE_MENU);
+G_DEFINE_TYPE (glFieldButtonMenu, gl_field_button_menu, GTK_TYPE_MENU);
 
 
 static void
-gl_wdgt_merge_menu_class_init (glWdgtMergeMenuClass *class)
+gl_field_button_menu_class_init (glFieldButtonMenuClass *class)
 {
         GObjectClass *object_class = G_OBJECT_CLASS (class);
 
-        gl_debug (DEBUG_MERGE_MENU, "START");
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
 
-        gl_wdgt_merge_menu_parent_class = g_type_class_peek_parent (class);
+        gl_field_button_menu_parent_class = g_type_class_peek_parent (class);
 
-        object_class->finalize = gl_wdgt_merge_menu_finalize;
+        object_class->finalize = gl_field_button_menu_finalize;
 
-        signals[FIELD_SELECTED] =
-            g_signal_new ("field_selected",
+        signals[KEY_SELECTED] =
+            g_signal_new ("key_selected",
                           G_OBJECT_CLASS_TYPE(object_class),
                           G_SIGNAL_RUN_LAST,
-                          G_STRUCT_OFFSET (glWdgtMergeMenuClass, field_selected),
+                          G_STRUCT_OFFSET (glFieldButtonMenuClass, key_selected),
                           NULL, NULL,
                           gl_marshal_VOID__STRING,
                           G_TYPE_NONE, 1, G_TYPE_STRING);
 
-        gl_debug (DEBUG_MERGE_MENU, "END");
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
 }
 
 
 static void
-gl_wdgt_merge_menu_init (glWdgtMergeMenu *merge_menu)
+gl_field_button_menu_init (glFieldButtonMenu *merge_menu)
 {
-        gl_debug (DEBUG_MERGE_MENU, "START");
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
 
-        merge_menu->priv = g_new0 (glWdgtMergeMenuPrivate, 1);
+        merge_menu->priv = g_new0 (glFieldButtonMenuPrivate, 1);
 
-        gl_debug (DEBUG_MERGE_MENU, "END");
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
 }
 
 
 static void
-gl_wdgt_merge_menu_finalize (GObject *object)
+gl_field_button_menu_finalize (GObject *object)
 {
-        glWdgtMergeMenu *merge_menu = GL_WDGT_MERGE_MENU (object);
+        glFieldButtonMenu *merge_menu = GL_FIELD_BUTTON_MENU (object);
         GList           *p;
         GtkWidget       *menu_item;
         gchar           *field;
 
-        gl_debug (DEBUG_MERGE_MENU, "START");
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
 
         g_return_if_fail (object != NULL);
-        g_return_if_fail (GL_IS_WDGT_MERGE_MENU (object));
+        g_return_if_fail (GL_IS_FIELD_BUTTON_MENU (object));
 
         for ( p = merge_menu->priv->menu_items; p != NULL; p = p->next )
         {
@@ -125,22 +125,22 @@ gl_wdgt_merge_menu_finalize (GObject *object)
         g_list_free (merge_menu->priv->menu_items);
         g_free (merge_menu->priv);
 
-        G_OBJECT_CLASS (gl_wdgt_merge_menu_parent_class)->finalize (object);
+        G_OBJECT_CLASS (gl_field_button_menu_parent_class)->finalize (object);
 
-        gl_debug (DEBUG_MERGE_MENU, "END");
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
 }
 
 
 GtkWidget *
-gl_wdgt_merge_menu_new (void)
+gl_field_button_menu_new (void)
 {
-        glWdgtMergeMenu *merge_menu;
+        glFieldButtonMenu *merge_menu;
 
-        gl_debug (DEBUG_MERGE_MENU, "START");
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
 
-        merge_menu = g_object_new (gl_wdgt_merge_menu_get_type (), NULL);
+        merge_menu = g_object_new (gl_field_button_menu_get_type (), NULL);
 
-        gl_debug (DEBUG_MERGE_MENU, "END");
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
 
         return GTK_WIDGET (merge_menu);
 }
@@ -150,34 +150,34 @@ gl_wdgt_merge_menu_new (void)
 /* PRIVATE.  Menu item activation callback.                                 */
 /*--------------------------------------------------------------------------*/
 static void
-activate_cb (GtkMenuItem     *menu_item,
-             glWdgtMergeMenu *merge_menu)
+activate_cb (GtkMenuItem       *menu_item,
+             glFieldButtonMenu *merge_menu)
 {
-        gchar *field;
+        gchar *key;
 
-        gl_debug (DEBUG_MERGE_MENU, "START");
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
 
-        field = g_object_get_data (G_OBJECT (menu_item), "field");
-        gl_debug (DEBUG_MERGE_MENU, "Field activated: \"%s\"\n", field );
+        key = g_object_get_data (G_OBJECT (menu_item), "key");
+        gl_debug (DEBUG_FIELD_BUTTON, "Key activated: \"%s\"\n", key );
 
-        g_signal_emit (G_OBJECT (merge_menu), signals[FIELD_SELECTED], 0, field);
+        g_signal_emit (G_OBJECT (merge_menu), signals[KEY_SELECTED], 0, key);
 
-        gl_debug (DEBUG_MERGE_MENU, "END");
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
 }
 
 
 /****************************************************************************/
-/* set field names.                                                         */
+/* set key names.                                                           */
 /****************************************************************************/
 void
-gl_wdgt_merge_menu_set_fields (glWdgtMergeMenu *merge_menu,
-                               GList           *field_list)
+gl_field_button_menu_set_keys (glFieldButtonMenu *merge_menu,
+                               GList             *key_list)
 {
         GList     *p;
         GtkWidget *menu_item;
-        gchar     *field;
+        gchar     *key;
 
-        gl_debug (DEBUG_MERGE_MENU, "START");
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
 
         /*
          * Remove all old menu items.
@@ -185,8 +185,8 @@ gl_wdgt_merge_menu_set_fields (glWdgtMergeMenu *merge_menu,
         for ( p = merge_menu->priv->menu_items; p != NULL; p = p->next )
         {
                 menu_item = GTK_WIDGET (p->data);
-                field = g_object_get_data (G_OBJECT (menu_item), "field");
-                g_free (field);
+                key = g_object_get_data (G_OBJECT (menu_item), "key");
+                g_free (key);
                 gtk_widget_destroy (menu_item);
         }
         g_list_free (merge_menu->priv->menu_items);
@@ -195,10 +195,11 @@ gl_wdgt_merge_menu_set_fields (glWdgtMergeMenu *merge_menu,
         /*
          * Add new menu items.
          */
-        for ( p = field_list; p != NULL; p = p->next )
+        for ( p = key_list; p != NULL; p = p->next )
         {
+                gl_debug (DEBUG_FIELD_BUTTON, "Adding key: %s", p->data);
                 menu_item = gtk_menu_item_new_with_label (p->data);
-                g_object_set_data (G_OBJECT (menu_item), "field", g_strdup (p->data));
+                g_object_set_data (G_OBJECT (menu_item), "key", g_strdup (p->data));
                 g_signal_connect (G_OBJECT (menu_item), "activate", 
                                   G_CALLBACK (activate_cb), merge_menu);
                 gtk_menu_shell_append (GTK_MENU_SHELL (merge_menu), menu_item);
@@ -206,7 +207,7 @@ gl_wdgt_merge_menu_set_fields (glWdgtMergeMenu *merge_menu,
                         g_list_append (merge_menu->priv->menu_items, menu_item);
         }
 
-        gl_debug (DEBUG_MERGE_MENU, "END");
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
 }
 
 
diff --git a/src/field-button-menu.h b/src/field-button-menu.h
new file mode 100644
index 0000000..cdb2a26
--- /dev/null
+++ b/src/field-button-menu.h
@@ -0,0 +1,82 @@
+/*
+ *  field-button-menu.h
+ *  Copyright (C) 2008-2009  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  gLabels 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FIELD_BUTTON_MENU_H__
+#define __FIELD_BUTTON_MENU_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GL_TYPE_FIELD_BUTTON_MENU (gl_field_button_menu_get_type ())
+#define GL_FIELD_BUTTON_MENU(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_FIELD_BUTTON_MENU, glFieldButtonMenu ))
+#define GL_FIELD_BUTTON_MENU_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_FIELD_BUTTON_MENU, glFieldButtonMenuClass))
+#define GL_IS_FIELD_BUTTON_MENU(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_FIELD_BUTTON_MENU))
+#define GL_IS_FIELD_BUTTON_MENU_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_FIELD_BUTTON_MENU))
+
+
+typedef struct _glFieldButtonMenu         glFieldButtonMenu;
+typedef struct _glFieldButtonMenuClass    glFieldButtonMenuClass;
+
+typedef struct _glFieldButtonMenuPrivate  glFieldButtonMenuPrivate;
+
+
+struct _glFieldButtonMenu {
+        GtkMenu                    parent_widget;
+
+        glFieldButtonMenuPrivate  *priv;
+};
+
+
+struct _glFieldButtonMenuClass {
+        GtkMenuClass               parent_class;
+
+        void (*key_selected) (glFieldButtonMenu *merge_menu,
+                              gchar             *key,
+                              gpointer           user_data);
+};
+
+
+GType      gl_field_button_menu_get_type    (void) G_GNUC_CONST;
+
+GtkWidget *gl_field_button_menu_new         (void);
+
+void       gl_field_button_menu_set_keys    (glFieldButtonMenu *merge_menu,
+                                             GList             *key_list);
+
+
+G_END_DECLS
+
+#endif
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/field-button.c b/src/field-button.c
new file mode 100644
index 0000000..e307bfb
--- /dev/null
+++ b/src/field-button.c
@@ -0,0 +1,294 @@
+/*
+ *  field-button.c
+ *  Copyright (C) 2009  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  gLabels 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "field-button.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "field-button-menu.h"
+#include "marshal.h"
+
+
+
+/*========================================================*/
+/* Private types.                                         */
+/*========================================================*/
+
+/** GL_FIELD_BUTTON Private fields */
+struct _glFieldButtonPrivate {
+
+        GtkWidget  *label;
+
+        GtkWidget  *menu;
+};
+
+enum {
+        KEY_SELECTED,
+        LAST_SIGNAL
+};
+
+
+/*========================================================*/
+/* Private globals.                                       */
+/*========================================================*/
+
+static guint signals[LAST_SIGNAL] = {0};
+
+
+/*========================================================*/
+/* Private function prototypes.                           */
+/*========================================================*/
+
+static void gl_field_button_finalize      (GObject             *object);
+
+static gboolean
+button_press_event_cb (GtkWidget          *widget,
+                       GdkEventButton     *event,
+                       glFieldButton      *this);
+
+static void
+menu_key_selected_cb  (glFieldButtonMenu  *menu,
+                       gchar              *key,
+                       glFieldButton      *this);
+
+static void
+menu_selection_done_cb (GtkMenuShell      *object,
+                        glFieldButton     *this);
+
+
+/*****************************************************************************/
+/* Object infrastructure.                                                    */
+/*****************************************************************************/
+G_DEFINE_TYPE (glFieldButton, gl_field_button, GTK_TYPE_TOGGLE_BUTTON);
+
+
+/*****************************************************************************/
+/* Class Init Function.                                                      */
+/*****************************************************************************/
+static void
+gl_field_button_class_init (glFieldButtonClass *class)
+{
+        GObjectClass      *gobject_class = (GObjectClass *) class;
+
+        gl_field_button_parent_class = g_type_class_peek_parent (class);
+
+        gobject_class->finalize = gl_field_button_finalize;
+
+        signals[KEY_SELECTED] =
+                g_signal_new ("key_selected",
+                              G_OBJECT_CLASS_TYPE (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (glFieldButtonClass, key_selected),
+                              NULL, NULL,
+                              gl_marshal_VOID__STRING,
+                              G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
+
+/*****************************************************************************/
+/* Object Instance Init Function.                                            */
+/*****************************************************************************/
+static void
+gl_field_button_init (glFieldButton *this)
+{
+        GtkWidget *hbox;
+        GtkWidget *arrow;
+
+        this->priv = g_new0 (glFieldButtonPrivate, 1);
+
+        hbox = gtk_hbox_new (FALSE, 3);
+        gtk_container_add (GTK_CONTAINER (this), hbox);
+        
+        this->priv->label = gtk_label_new ("");
+        gtk_misc_set_alignment (GTK_MISC (this->priv->label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (hbox), this->priv->label, TRUE, TRUE, 0);
+
+        arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
+        gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
+
+        g_signal_connect (this, "button_press_event",
+                          G_CALLBACK(button_press_event_cb), this);
+}
+
+
+/*****************************************************************************/
+/* Finalize Method.                                                          */
+/*****************************************************************************/
+static void
+gl_field_button_finalize (GObject *object)
+{
+        glFieldButton    *this;
+
+        g_return_if_fail (object && IS_GL_FIELD_BUTTON (object));
+        this = GL_FIELD_BUTTON (object);
+
+        g_object_ref_sink (this->priv->menu);
+        g_free (this->priv);
+
+        G_OBJECT_CLASS (gl_field_button_parent_class)->finalize (object);
+}
+
+
+/*****************************************************************************/
+/** New Object Generator.                                                    */
+/*****************************************************************************/
+GtkWidget *
+gl_field_button_new (const gchar  *name)
+{
+        glFieldButton  *this;
+
+        this = g_object_new (TYPE_GL_FIELD_BUTTON, NULL);
+
+        gtk_label_set_text (GTK_LABEL (this->priv->label), name);
+
+        this->priv->menu = gl_field_button_menu_new ();
+
+        gtk_widget_show_all (this->priv->menu);
+
+        g_signal_connect (this->priv->menu, "key_selected",
+                          G_CALLBACK (menu_key_selected_cb), this);
+        g_signal_connect (this->priv->menu, "selection_done",
+                          G_CALLBACK (menu_selection_done_cb), this);
+
+        return GTK_WIDGET (this);
+}
+
+
+/*****************************************************************************/
+/* Set key list.                                                             */
+/*****************************************************************************/
+void
+gl_field_button_set_keys (glFieldButton  *this,
+                          GList          *key_list)
+{
+        gl_field_button_menu_set_keys (GL_FIELD_BUTTON_MENU (this->priv->menu),
+                                       key_list);
+
+        gtk_widget_show_all (this->priv->menu);
+}
+
+
+/*****************************************************************************/
+/* Menu positioning function.                                                */
+/*****************************************************************************/
+static void
+menu_position_function (GtkMenu  *menu,
+                        gint     *x,
+                        gint     *y,
+                        gboolean *push_in,
+                        gpointer  user_data)
+{
+        glFieldButton  *this = GL_FIELD_BUTTON (user_data);
+        GdkWindow    *window;
+        gint          x1, y1;
+        gint          menu_h, menu_w;
+
+        window = gtk_widget_get_window (GTK_WIDGET (this));
+
+        gdk_window_get_origin (window, &x1, &y1);
+        *x = x1 + GTK_WIDGET (this)->allocation.x;
+        *y = y1 + GTK_WIDGET (this)->allocation.y +
+                GTK_WIDGET (this)->allocation.height;
+                
+        menu_h = this->priv->menu->allocation.height;
+        menu_w = this->priv->menu->allocation.width;
+
+        if ((*y + menu_h) > gdk_screen_height ())
+        {
+                *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h;
+                if ( *y < 0 )
+                {
+                        *y = gdk_screen_height () - menu_h;
+                }
+        }
+
+        if ((*x + menu_w) > gdk_screen_width ())
+        {
+                *x = gdk_screen_width () - menu_w;
+        }
+
+        *push_in = TRUE;
+}
+
+
+/*****************************************************************************/
+/* Button "button_press_event" callback.                                     */
+/*****************************************************************************/
+static gboolean
+button_press_event_cb (GtkWidget      *widget,
+                       GdkEventButton *event,
+                       glFieldButton   *this)
+{
+        switch (event->button)
+        {
+
+        case 1:
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), TRUE);
+
+                gtk_menu_popup (GTK_MENU (this->priv->menu),
+                                NULL, NULL,
+                                menu_position_function, this,
+                                event->button, event->time);
+                break;
+
+        default:
+                break;
+
+        }
+
+        return FALSE;
+}
+
+
+/*****************************************************************************/
+/* Menu "key selected" callback.                                             */
+/*****************************************************************************/
+static void
+menu_key_selected_cb (glFieldButtonMenu     *menu,
+                      gchar                 *field,
+                      glFieldButton         *this)
+{
+        g_signal_emit (this, signals[KEY_SELECTED], 0, field);
+}
+
+
+/*****************************************************************************/
+/* Menu "selection done" callback.                                           */
+/*****************************************************************************/
+static void
+menu_selection_done_cb (GtkMenuShell         *object,
+                        glFieldButton         *this)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), FALSE);
+}
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/field-button.h b/src/field-button.h
new file mode 100644
index 0000000..883558d
--- /dev/null
+++ b/src/field-button.h
@@ -0,0 +1,82 @@
+/*
+ *  field-button.h
+ *  Copyright (C) 2009  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  gLabels 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GL_FIELD_BUTTON_H__
+#define __GL_FIELD_BUTTON_H__
+
+
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define TYPE_GL_FIELD_BUTTON              (gl_field_button_get_type ())
+#define GL_FIELD_BUTTON(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_GL_FIELD_BUTTON, glFieldButton))
+#define GL_FIELD_BUTTON_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_GL_FIELD_BUTTON, glFieldButtonClass))
+#define IS_GL_FIELD_BUTTON(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_GL_FIELD_BUTTON))
+#define IS_GL_FIELD_BUTTON_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_GL_FIELD_BUTTON))
+#define GL_FIELD_BUTTON_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_GL_FIELD_BUTTON, glFieldButtonClass))
+
+
+typedef struct _glFieldButton          glFieldButton;
+typedef struct _glFieldButtonPrivate   glFieldButtonPrivate;
+typedef struct _glFieldButtonClass     glFieldButtonClass;
+
+
+struct _glFieldButton {
+        GtkToggleButton               parent;
+
+        glFieldButtonPrivate         *priv;
+};
+
+struct _glFieldButtonClass {
+        GtkToggleButtonClass          parent_class;
+
+        /*
+         * Signals
+         */
+        void (*key_selected) (glFieldButton *object,
+                              gchar         *key,
+                              gpointer       user_data);
+
+};
+
+
+GType            gl_field_button_get_type          (void) G_GNUC_CONST;
+
+GtkWidget       *gl_field_button_new               (const gchar     *name);
+
+void             gl_field_button_set_keys          (glFieldButton   *this,
+                                                    GList           *key_list);
+
+G_END_DECLS
+
+#endif /* __GL_COLOR_COMBO_H__ */
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/object-editor-edit-page.c b/src/object-editor-edit-page.c
index 0e52015..949f023 100644
--- a/src/object-editor-edit-page.c
+++ b/src/object-editor-edit-page.c
@@ -28,7 +28,7 @@
 
 #include "prefs.h"
 #include "color.h"
-#include "wdgt-merge-menu.h"
+#include "field-button.h"
 #include "builder-util.h"
 
 #include "object-editor-private.h"
@@ -55,9 +55,7 @@
 /* Local function prototypes                 */
 /*===========================================*/
 
-static void insert_button_cb (glObjectEditor  *editor);
-
-static void field_selected_cb (glObjectEditor *editor, gchar *field);
+static void key_selected_cb (glObjectEditor *editor, gchar *key);
 
 
 /*--------------------------------------------------------------------------*/
@@ -72,22 +70,20 @@ gl_object_editor_prepare_edit_page (glObjectEditor       *editor)
         gl_builder_util_get_widgets (editor->priv->builder,
                                      "edit_page_vbox",           &editor->priv->edit_page_vbox,
                                      "edit_text_view",           &editor->priv->edit_text_view,
-                                     "edit_insert_field_button", &editor->priv->edit_insert_field_button,
+                                     "edit_insert_field_vbox",   &editor->priv->edit_insert_field_vbox,
                                      NULL);
 
-	editor->priv->edit_insert_field_menu = gl_wdgt_merge_menu_new ();
+	editor->priv->edit_insert_field_button = gl_field_button_new (_("Insert merge field"));
+        gtk_box_pack_start (GTK_BOX (editor->priv->edit_insert_field_vbox),
+                            editor->priv->edit_insert_field_button, FALSE, FALSE, 0);
 
 	/* Un-hide */
 	gtk_widget_show_all (editor->priv->edit_page_vbox);
 
 	/* Connect signals */
 	g_signal_connect_swapped (G_OBJECT (editor->priv->edit_insert_field_button),
-				  "clicked",
-				  G_CALLBACK (insert_button_cb),
-				  G_OBJECT (editor));
-	g_signal_connect_swapped (G_OBJECT (editor->priv->edit_insert_field_menu),
-				  "field_selected",
-				  G_CALLBACK (field_selected_cb),
+				  "key_selected",
+				  G_CALLBACK (key_selected_cb),
 				  G_OBJECT (editor));
 
 	gl_debug (DEBUG_EDITOR, "END");
@@ -98,14 +94,14 @@ gl_object_editor_prepare_edit_page (glObjectEditor       *editor)
 /* PRIVATE.  Menu item activated callback.                                  */
 /*--------------------------------------------------------------------------*/
 static void
-field_selected_cb (glObjectEditor *editor, gchar *field)
+key_selected_cb (glObjectEditor *editor, gchar *key)
 {
         GtkTextBuffer *buffer;
         gchar *field_string;
  
         gl_debug (DEBUG_EDITOR, "START");
  
-        field_string = g_strdup_printf ("${%s}", field);
+        field_string = g_strdup_printf ("${%s}", key);
         gl_debug (DEBUG_WDGT, "Inserting %s", field_string);
  
         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->edit_text_view));
@@ -117,22 +113,6 @@ field_selected_cb (glObjectEditor *editor, gchar *field)
 }
 
 
-/*--------------------------------------------------------------------------*/
-/* PRIVATE.  Insert button callback.                                        */
-/*--------------------------------------------------------------------------*/
-static void
-insert_button_cb (glObjectEditor  *editor)
-{
-        gl_debug (DEBUG_EDITOR, "START");
- 
-        gtk_widget_show_all (editor->priv->edit_insert_field_menu);
-        gtk_menu_popup (GTK_MENU (editor->priv->edit_insert_field_menu),
-                        NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
-
-        gl_debug (DEBUG_EDITOR, "END");
-}
-
-
 /*****************************************************************************/
 /* Set text buffer as model for text view/editor.                            */
 /*****************************************************************************/
diff --git a/src/object-editor-private.h b/src/object-editor-private.h
index 6858075..d585f31 100644
--- a/src/object-editor-private.h
+++ b/src/object-editor-private.h
@@ -113,8 +113,8 @@ struct _glObjectEditorPrivate {
 
 	GtkWidget  *edit_page_vbox;
 	GtkWidget  *edit_text_view;
+	GtkWidget  *edit_insert_field_vbox;
 	GtkWidget  *edit_insert_field_button;
-        GtkWidget  *edit_insert_field_menu;
 
 	GtkWidget  *bc_page_vbox;
 	GtkWidget  *bc_style_combo;
diff --git a/src/object-editor.c b/src/object-editor.c
index 3edf581..e63831a 100644
--- a/src/object-editor.c
+++ b/src/object-editor.c
@@ -30,7 +30,7 @@
 #include "color-combo.h"
 #include "color.h"
 #include "wdgt-chain-button.h"
-#include "wdgt-merge-menu.h"
+#include "field-button.h"
 #include "marshal.h"
 #include "combo-util.h"
 #include "builder-util.h"
@@ -386,7 +386,7 @@ gl_object_editor_set_key_names (glObjectEditor      *editor,
 {
         GList     *keys;
 	GtkWidget *combo;
-	GtkWidget *menu;
+	GtkWidget *button;
 	gboolean   fixed_flag;
 	gboolean   state;
  
@@ -529,9 +529,9 @@ gl_object_editor_set_key_names (glObjectEditor      *editor,
 		gl_combo_util_set_strings (GTK_COMBO_BOX (combo), keys);
 	}
 
-	menu = editor->priv->edit_insert_field_menu;
-	if (menu) {
-		gl_wdgt_merge_menu_set_fields (GL_WDGT_MERGE_MENU(menu), keys);
+	button = editor->priv->edit_insert_field_button;
+	if (button) {
+		gl_field_button_set_keys (GL_FIELD_BUTTON(button), keys);
 	}
 
 	combo = editor->priv->data_key_combo;



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