]> git.sur5r.net Git - glabels/commitdiff
Create new glFieldButton widget family
authorJim Evins <evins@snaught.com>
Tue, 20 Oct 2009 03:59:02 +0000 (23:59 -0400)
committerJim Evins <evins@snaught.com>
Tue, 20 Oct 2009 03:59:02 +0000 (23:59 -0400)
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.

14 files changed:
data/builder/object-editor.builder
po/POTFILES.in
src/Makefile.am
src/debug.c
src/debug.h
src/field-button-menu.c [new file with mode: 0644]
src/field-button-menu.h [new file with mode: 0644]
src/field-button.c [new file with mode: 0644]
src/field-button.h [new file with mode: 0644]
src/object-editor-edit-page.c
src/object-editor-private.h
src/object-editor.c
src/wdgt-merge-menu.c [deleted file]
src/wdgt-merge-menu.h [deleted file]

index 5cfb9002717ec17f60073d92597a8a4dc53d347c..365f426741d2626e2a1448a938d945b3d92a9a96 100644 (file)
                         <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>
index de755fa95d46ec172d0d96065728ed244006244b..e0c51d34c83cb3c8f2d96863db7dd9834b263e93 100644 (file)
@@ -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
index 2c312744dcc0a8024425959470bbfce0686f305b..6008dee803d26ef77ba1f7222273ab4aef26183c 100644 (file)
@@ -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            \
index ce53820a018497c1078f91f32e9620a7f8ed9aa9..97972e5528ce2d8e5ceaff506e9c2e7840b46b30 100644 (file)
@@ -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;
 }
 
 
index 6dced6d49182a0c2218269324160d7084543d23c..b8bed98581ec0502a1d63e6ea0a56ad6d750bd4f 100644 (file)
@@ -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/field-button-menu.c b/src/field-button-menu.c
new file mode 100644 (file)
index 0000000..a59bb3b
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ *  field-button-menu.c
+ *  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/>.
+ */
+
+#include <config.h>
+
+#include "field-button-menu.h"
+
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include "marshal.h"
+
+#include "debug.h"
+
+
+/*===========================================*/
+/* Private types                             */
+/*===========================================*/
+
+
+struct _glFieldButtonMenuPrivate {
+
+        GList *menu_items;
+};
+
+enum {
+        KEY_SELECTED,
+        LAST_SIGNAL
+};
+
+typedef void (*glFieldButtonMenuSignal) (GObject * object, gpointer data);
+
+
+/*===========================================*/
+/* Private globals                           */
+/*===========================================*/
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
+
+/*===========================================*/
+/* Local function prototypes                 */
+/*===========================================*/
+
+static void gl_field_button_menu_finalize      (GObject              *object);
+
+
+/****************************************************************************/
+/* Boilerplate Object stuff.                                                */
+/****************************************************************************/
+G_DEFINE_TYPE (glFieldButtonMenu, gl_field_button_menu, GTK_TYPE_MENU);
+
+
+static void
+gl_field_button_menu_class_init (glFieldButtonMenuClass *class)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
+
+        gl_field_button_menu_parent_class = g_type_class_peek_parent (class);
+
+        object_class->finalize = gl_field_button_menu_finalize;
+
+        signals[KEY_SELECTED] =
+            g_signal_new ("key_selected",
+                          G_OBJECT_CLASS_TYPE(object_class),
+                          G_SIGNAL_RUN_LAST,
+                          G_STRUCT_OFFSET (glFieldButtonMenuClass, key_selected),
+                          NULL, NULL,
+                          gl_marshal_VOID__STRING,
+                          G_TYPE_NONE, 1, G_TYPE_STRING);
+
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
+}
+
+
+static void
+gl_field_button_menu_init (glFieldButtonMenu *merge_menu)
+{
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
+
+        merge_menu->priv = g_new0 (glFieldButtonMenuPrivate, 1);
+
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
+}
+
+
+static void
+gl_field_button_menu_finalize (GObject *object)
+{
+        glFieldButtonMenu *merge_menu = GL_FIELD_BUTTON_MENU (object);
+        GList           *p;
+        GtkWidget       *menu_item;
+        gchar           *field;
+
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GL_IS_FIELD_BUTTON_MENU (object));
+
+        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);
+        }
+        g_list_free (merge_menu->priv->menu_items);
+        g_free (merge_menu->priv);
+
+        G_OBJECT_CLASS (gl_field_button_menu_parent_class)->finalize (object);
+
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
+}
+
+
+GtkWidget *
+gl_field_button_menu_new (void)
+{
+        glFieldButtonMenu *merge_menu;
+
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
+
+        merge_menu = g_object_new (gl_field_button_menu_get_type (), NULL);
+
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
+
+        return GTK_WIDGET (merge_menu);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE.  Menu item activation callback.                                 */
+/*--------------------------------------------------------------------------*/
+static void
+activate_cb (GtkMenuItem       *menu_item,
+             glFieldButtonMenu *merge_menu)
+{
+        gchar *key;
+
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
+
+        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[KEY_SELECTED], 0, key);
+
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
+}
+
+
+/****************************************************************************/
+/* set key names.                                                           */
+/****************************************************************************/
+void
+gl_field_button_menu_set_keys (glFieldButtonMenu *merge_menu,
+                               GList             *key_list)
+{
+        GList     *p;
+        GtkWidget *menu_item;
+        gchar     *key;
+
+        gl_debug (DEBUG_FIELD_BUTTON, "START");
+
+        /*
+         * Remove all old menu items.
+         */
+        for ( p = merge_menu->priv->menu_items; p != NULL; p = p->next )
+        {
+                menu_item = GTK_WIDGET (p->data);
+                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);
+        merge_menu->priv->menu_items = NULL;
+
+        /*
+         * Add new menu items.
+         */
+        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), "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);
+                merge_menu->priv->menu_items =
+                        g_list_append (merge_menu->priv->menu_items, menu_item);
+        }
+
+        gl_debug (DEBUG_FIELD_BUTTON, "END");
+}
+
+
+
+/*
+ * 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-menu.h b/src/field-button-menu.h
new file mode 100644 (file)
index 0000000..cdb2a26
--- /dev/null
@@ -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 (file)
index 0000000..e307bfb
--- /dev/null
@@ -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 (file)
index 0000000..883558d
--- /dev/null
@@ -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
+ */
index 0e52015a6a75cfa6b8dc11e5e21644ca74f53a74..949f02396957dd3986245301a91c3748bb4d02cf 100644 (file)
@@ -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.                            */
 /*****************************************************************************/
index 6858075955cc23e4a87070c4c9c5f6b8d0b26607..d585f310c354c59013b025044ca25ab83adce59e 100644 (file)
@@ -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;
index 3edf5815aaa81999f43d50db2b72be4a508f6bd2..e63831ad4643465f8b7c7d3888d186e9b9645b9f 100644 (file)
@@ -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;
diff --git a/src/wdgt-merge-menu.c b/src/wdgt-merge-menu.c
deleted file mode 100644 (file)
index 9f0d132..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *  wdgt-merge-menu.c
- *  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/>.
- */
-
-#include <config.h>
-
-#include "wdgt-merge-menu.h"
-
-#include <string.h>
-#include <gtk/gtk.h>
-
-#include "marshal.h"
-
-#include "debug.h"
-
-
-/*===========================================*/
-/* Private types                             */
-/*===========================================*/
-
-
-struct _glWdgtMergeMenuPrivate {
-
-        GList *menu_items;
-};
-
-enum {
-        FIELD_SELECTED,
-        LAST_SIGNAL
-};
-
-typedef void (*glWdgtMergeMenuSignal) (GObject * object, gpointer data);
-
-
-/*===========================================*/
-/* Private globals                           */
-/*===========================================*/
-
-static gint signals[LAST_SIGNAL] = { 0 };
-
-
-/*===========================================*/
-/* Local function prototypes                 */
-/*===========================================*/
-
-static void gl_wdgt_merge_menu_finalize      (GObject              *object);
-
-
-/****************************************************************************/
-/* Boilerplate Object stuff.                                                */
-/****************************************************************************/
-G_DEFINE_TYPE (glWdgtMergeMenu, gl_wdgt_merge_menu, GTK_TYPE_MENU);
-
-
-static void
-gl_wdgt_merge_menu_class_init (glWdgtMergeMenuClass *class)
-{
-        GObjectClass *object_class = G_OBJECT_CLASS (class);
-
-        gl_debug (DEBUG_MERGE_MENU, "START");
-
-        gl_wdgt_merge_menu_parent_class = g_type_class_peek_parent (class);
-
-        object_class->finalize = gl_wdgt_merge_menu_finalize;
-
-        signals[FIELD_SELECTED] =
-            g_signal_new ("field_selected",
-                          G_OBJECT_CLASS_TYPE(object_class),
-                          G_SIGNAL_RUN_LAST,
-                          G_STRUCT_OFFSET (glWdgtMergeMenuClass, field_selected),
-                          NULL, NULL,
-                          gl_marshal_VOID__STRING,
-                          G_TYPE_NONE, 1, G_TYPE_STRING);
-
-        gl_debug (DEBUG_MERGE_MENU, "END");
-}
-
-
-static void
-gl_wdgt_merge_menu_init (glWdgtMergeMenu *merge_menu)
-{
-        gl_debug (DEBUG_MERGE_MENU, "START");
-
-        merge_menu->priv = g_new0 (glWdgtMergeMenuPrivate, 1);
-
-        gl_debug (DEBUG_MERGE_MENU, "END");
-}
-
-
-static void
-gl_wdgt_merge_menu_finalize (GObject *object)
-{
-        glWdgtMergeMenu *merge_menu = GL_WDGT_MERGE_MENU (object);
-        GList           *p;
-        GtkWidget       *menu_item;
-        gchar           *field;
-
-        gl_debug (DEBUG_MERGE_MENU, "START");
-
-        g_return_if_fail (object != NULL);
-        g_return_if_fail (GL_IS_WDGT_MERGE_MENU (object));
-
-        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);
-        }
-        g_list_free (merge_menu->priv->menu_items);
-        g_free (merge_menu->priv);
-
-        G_OBJECT_CLASS (gl_wdgt_merge_menu_parent_class)->finalize (object);
-
-        gl_debug (DEBUG_MERGE_MENU, "END");
-}
-
-
-GtkWidget *
-gl_wdgt_merge_menu_new (void)
-{
-        glWdgtMergeMenu *merge_menu;
-
-        gl_debug (DEBUG_MERGE_MENU, "START");
-
-        merge_menu = g_object_new (gl_wdgt_merge_menu_get_type (), NULL);
-
-        gl_debug (DEBUG_MERGE_MENU, "END");
-
-        return GTK_WIDGET (merge_menu);
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE.  Menu item activation callback.                                 */
-/*--------------------------------------------------------------------------*/
-static void
-activate_cb (GtkMenuItem     *menu_item,
-             glWdgtMergeMenu *merge_menu)
-{
-        gchar *field;
-
-        gl_debug (DEBUG_MERGE_MENU, "START");
-
-        field = g_object_get_data (G_OBJECT (menu_item), "field");
-        gl_debug (DEBUG_MERGE_MENU, "Field activated: \"%s\"\n", field );
-
-        g_signal_emit (G_OBJECT (merge_menu), signals[FIELD_SELECTED], 0, field);
-
-        gl_debug (DEBUG_MERGE_MENU, "END");
-}
-
-
-/****************************************************************************/
-/* set field names.                                                         */
-/****************************************************************************/
-void
-gl_wdgt_merge_menu_set_fields (glWdgtMergeMenu *merge_menu,
-                               GList           *field_list)
-{
-        GList     *p;
-        GtkWidget *menu_item;
-        gchar     *field;
-
-        gl_debug (DEBUG_MERGE_MENU, "START");
-
-        /*
-         * Remove all old menu items.
-         */
-        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);
-                gtk_widget_destroy (menu_item);
-        }
-        g_list_free (merge_menu->priv->menu_items);
-        merge_menu->priv->menu_items = NULL;
-
-        /*
-         * Add new menu items.
-         */
-        for ( p = field_list; p != NULL; p = p->next )
-        {
-                menu_item = gtk_menu_item_new_with_label (p->data);
-                g_object_set_data (G_OBJECT (menu_item), "field", 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);
-                merge_menu->priv->menu_items =
-                        g_list_append (merge_menu->priv->menu_items, menu_item);
-        }
-
-        gl_debug (DEBUG_MERGE_MENU, "END");
-}
-
-
-
-/*
- * 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/wdgt-merge-menu.h b/src/wdgt-merge-menu.h
deleted file mode 100644 (file)
index 2c406dc..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  wdgt-merge-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 __WDGT_MERGE_MENU_H__
-#define __WDGT_MERGE_MENU_H__
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GL_TYPE_WDGT_MERGE_MENU (gl_wdgt_merge_menu_get_type ())
-#define GL_WDGT_MERGE_MENU(obj) \
-        (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_WDGT_MERGE_MENU, glWdgtMergeMenu ))
-#define GL_WDGT_MERGE_MENU_CLASS(klass) \
-        (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_WDGT_MERGE_MENU, glWdgtMergeMenuClass))
-#define GL_IS_WDGT_MERGE_MENU(obj) \
-        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_WDGT_MERGE_MENU))
-#define GL_IS_WDGT_MERGE_MENU_CLASS(klass) \
-        (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_WDGT_MERGE_MENU))
-
-
-typedef struct _glWdgtMergeMenu         glWdgtMergeMenu;
-typedef struct _glWdgtMergeMenuClass    glWdgtMergeMenuClass;
-
-typedef struct _glWdgtMergeMenuPrivate  glWdgtMergeMenuPrivate;
-
-
-struct _glWdgtMergeMenu {
-        GtkMenu                  parent_widget;
-
-        glWdgtMergeMenuPrivate  *priv;
-};
-
-
-struct _glWdgtMergeMenuClass {
-        GtkMenuClass             parent_class;
-
-        void (*field_selected) (glWdgtMergeMenu *merge_menu,
-                                gchar           *field,
-                                gpointer         user_data);
-};
-
-
-GType      gl_wdgt_merge_menu_get_type      (void) G_GNUC_CONST;
-
-GtkWidget *gl_wdgt_merge_menu_new           (void);
-
-void       gl_wdgt_merge_menu_set_fields    (glWdgtMergeMenu *merge_menu,
-                                             GList           *field_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
- */