Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-entry-action.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  This program 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 2, or (at your option)
 *  any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "kz-entry-action.h"

#include <kz-entry.h>
#include <glib/gi18n.h>

#include "gobject-utils.h"

enum {
  PROP_0,
  PROP_TEXT
};

static void       kz_entry_action_init         (KzEntryAction *action);
static void       kz_entry_action_class_init   (KzEntryActionClass *class);

static void       kz_entry_action_dispose      (GObject *object);
static void       kz_entry_action_set_property (GObject      *object,
                                     guint         prop_id,
                                     const GValue *value,
                                     GParamSpec   *pspec);
static void       kz_entry_action_get_property (GObject      *object,
                                     guint         prop_id,
                                     GValue       *value,
                                     GParamSpec   *pspec);

static GtkWidget *create_menu_item              (GtkAction *action);
static GtkWidget *create_tool_item              (GtkAction *action);

static void       connect_proxy                 (GtkAction *action,
                                     GtkWidget *proxy);
static void       disconnect_proxy              (GtkAction *action,
                                     GtkWidget *proxy);

static GtkEntry  *kz_entry_action_real_get_entry_widget (KzEntryAction *action,
                                            GtkWidget      *proxy);

static GtkActionClass *parent_class = NULL;

KZ_OBJECT_GET_TYPE(kz_entry_action, "KzEntryAction", KzEntryAction,
               kz_entry_action_class_init, kz_entry_action_init,
               GTK_TYPE_ACTION)

static void
kz_entry_action_class_init (KzEntryActionClass *klass)
{
      GObjectClass *object_class;
      GtkActionClass *action_class;

      parent_class = g_type_class_peek_parent(klass);
      object_class = G_OBJECT_CLASS(klass);
      action_class = GTK_ACTION_CLASS(klass);

      object_class->dispose      = kz_entry_action_dispose;
      object_class->set_property = kz_entry_action_set_property;
      object_class->get_property = kz_entry_action_get_property;

      action_class->create_menu_item = create_menu_item;
      action_class->create_tool_item = create_tool_item;
      action_class->connect_proxy    = connect_proxy;
      action_class->disconnect_proxy = disconnect_proxy;

      action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;

      klass->get_entry_widget = kz_entry_action_real_get_entry_widget;

      g_object_class_install_property(
            object_class,
            PROP_TEXT,
            g_param_spec_string("text",
                            _("Text"),
                            _("Text in entries."),
                            NULL,
                            G_PARAM_READWRITE));
}


static void
kz_entry_action_init (KzEntryAction *action)
{
}


static void
kz_entry_action_dispose (GObject *object)
{
      KzEntryAction *action = KZ_ENTRY_ACTION(object);

      if (action->text)
            g_free (action->text);
      action->text = NULL;

      if (G_OBJECT_CLASS (parent_class)->dispose)
            G_OBJECT_CLASS (parent_class)->dispose(object);
}


static void
kz_entry_action_set_property (GObject      *object,
                         guint         prop_id,
                         const GValue *value,
                         GParamSpec   *pspec)
{
      KzEntryAction *action;

      action = KZ_ENTRY_ACTION(object);

      switch (prop_id)
      {
      case PROP_TEXT:
            g_free(action->text);
            action->text = g_value_dup_string(value);
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
            break;
      }
}


static void
kz_entry_action_get_property (GObject    *object,
                         guint       prop_id,
                         GValue     *value,
                         GParamSpec *pspec)
{
      KzEntryAction *action;

      action = KZ_ENTRY_ACTION(object);

      switch (prop_id)
      {
      case PROP_TEXT:
            g_value_set_string(value, action->text);
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
            break;
      }
}

#if 0
static gboolean
cb_menu_item_entry_button_press (GtkWidget *widget)
{
      /* don't propagate to parent */
      return TRUE;
}


static gboolean
cb_menu_item_entry_button_release (GtkWidget *widget)
{
      /* don't propagate to parent */
      return TRUE;
}


static gboolean
cb_menu_item_entry_enter (GtkWidget *widget, GdkEventCrossing *event)
{
      gtk_grab_add(GTK_BIN(widget)->child);
      gtk_widget_grab_focus(GTK_BIN(widget)->child);

      return TRUE;
}


static gboolean
cb_menu_item_entry_leave (GtkWidget *widget, GdkEventCrossing *event)
{
      gtk_grab_remove(GTK_BIN(widget)->child);

      return TRUE;
}
#endif

static GtkWidget *
create_menu_item (GtkAction *action)
{
      GtkWidget *widget, *entry;

#warning FIXME! implement as our original widget and force blink cursor.
      widget = gtk_menu_item_new();
      entry = kz_entry_new();
      gtk_widget_show(entry);
      gtk_container_add(GTK_CONTAINER(widget), entry);
#if 0
      g_signal_connect_after(widget, "button-press-event",
                         G_CALLBACK(cb_menu_item_entry_button_press),
                         NULL);
      g_signal_connect_after(widget, "button-release-event",
                         G_CALLBACK(cb_menu_item_entry_button_release),
                         NULL);

      g_signal_connect(widget, "enter-notify-event",
                   G_CALLBACK(cb_menu_item_entry_enter), NULL);
      g_signal_connect(widget, "leave-notify-event",
                   G_CALLBACK(cb_menu_item_entry_leave), NULL);
#endif
      return widget;
}


static void
cb_entry_changed(GtkEditable *editable, GtkAction *action)
{
      GtkEntry *entry;
      const gchar *text;

      entry = GTK_ENTRY(editable);
      text = gtk_entry_get_text(entry);

      g_object_set(G_OBJECT(action), "text", text, NULL);
}


static void
cb_entry_activate(GtkEntry *entry, GtkAction *action)
{
      g_return_if_fail(KZ_IS_ENTRY_ACTION(action));

      gtk_action_activate(action);
}


static void
sync_text (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
{
      GtkEntry *entry;
      
      entry = kz_entry_action_get_entry_widget(KZ_ENTRY_ACTION(action), proxy);
      if (!entry) return;

      g_signal_handlers_block_by_func(entry,
                              G_CALLBACK(cb_entry_changed),
                              action);
      gtk_entry_set_text(entry,
                     KZ_ENTRY_ACTION(action)->text);
      g_signal_handlers_unblock_by_func(entry,
                                G_CALLBACK(cb_entry_changed),
                                action);
}


static GtkWidget *
create_tool_item (GtkAction *action)
{
      GtkWidget *widget, *entry;

      widget = (*GTK_ACTION_CLASS(parent_class)->create_tool_item) (action);
      gtk_tool_item_set_expand (GTK_TOOL_ITEM(widget), TRUE);

      entry = kz_entry_new();
      gtk_container_add(GTK_CONTAINER(widget), entry);
      gtk_widget_show(entry);

      return widget;
}


static GtkEntry *
kz_entry_action_real_get_entry_widget(KzEntryAction *action, GtkWidget *proxy)
{
      GtkEntry *entry = NULL;

      g_return_val_if_fail(proxy, NULL);

      if (GTK_IS_BIN(proxy))
      {
            if (GTK_IS_ENTRY(GTK_BIN(proxy)->child))
            {
                  entry = GTK_ENTRY(GTK_BIN(proxy)->child);
            }
            else if (GTK_IS_COMBO_BOX(GTK_BIN(proxy)->child))
            {
                  entry = GTK_ENTRY(GTK_BIN(GTK_BIN(proxy)->child)->child);
            }
      }
      else if (GTK_IS_ENTRY(proxy))
      {
            entry = GTK_ENTRY(proxy);
      }
      else if (GTK_IS_COMBO_BOX(proxy))
      {
            entry = GTK_ENTRY(GTK_BIN(proxy)->child);
      }

      if (GTK_IS_ENTRY(entry))
            return entry;

      return NULL;
}


GtkEntry *
kz_entry_action_get_entry_widget(KzEntryAction *action, GtkWidget *proxy)
{
      KzEntryActionClass *klass;

      g_return_val_if_fail(KZ_IS_ENTRY_ACTION(action), NULL);

      klass = KZ_ENTRY_ACTION_GET_CLASS(action);

      if (klass->get_entry_widget)
            return klass->get_entry_widget(action, proxy);

      return NULL;
}


static void
connect_proxy (GtkAction *action, GtkWidget *proxy)
{
      KzEntryAction *entry_action;
      GtkEntry *entry = NULL;

      entry_action = KZ_ENTRY_ACTION (action);

      entry = kz_entry_action_get_entry_widget(entry_action, proxy);
      if (GTK_IS_ENTRY(entry))
      {
            g_signal_connect(entry, "changed",
                         G_CALLBACK(cb_entry_changed), action);
            g_signal_connect(entry, "activate",
                         G_CALLBACK(cb_entry_activate), action);

            g_object_ref(action);
            g_object_set_data_full(G_OBJECT(proxy), "gtk-action", action,
                               g_object_unref);
#if 0
            /* add this widget to the list of proxies */
            action->proxies = g_slist_prepend(action->proxies, proxy);
            g_signal_connect(proxy, "destroy",
                         G_CALLBACK(gtk_action_remove_proxy), action);

            g_signal_connect_object (action, "notify::sensitive",
                               G_CALLBACK (gtk_action_sync_property),
                               proxy, 0);
            gtk_widget_set_sensitive(proxy, action->sensitive);

            g_signal_connect_object(action, "notify::visible",
                              G_CALLBACK(gtk_action_sync_property),
                              proxy, 0);
            if (action->visible)
                  gtk_widget_show(proxy);
            else
                  gtk_widget_hide(proxy);

#endif 
            /* sync entry text */
            g_signal_connect_object(action, "notify::text",
                              G_CALLBACK(sync_text),
                              entry, 0);

            if (entry_action->text)
                  gtk_entry_set_text(entry, entry_action->text);
      }
      GTK_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);
}


static void
disconnect_proxy (GtkAction *action, GtkWidget *proxy)
{
      KzEntryAction *entry_action;
      GtkEntry *entry;

      entry_action = KZ_ENTRY_ACTION (action);

      entry = kz_entry_action_get_entry_widget(entry_action, proxy);
      if (entry)
      {
            g_signal_handlers_disconnect_by_func
                  (entry,  G_CALLBACK(cb_entry_changed), action);
            g_signal_handlers_disconnect_by_func
                  (entry, G_CALLBACK(cb_entry_activate), action);
      }

      /* other signals will be remove by parent */
      GTK_ACTION_CLASS (parent_class)->disconnect_proxy(action, proxy);
}


void
kz_entry_action_set_text (KzEntryAction *action,
                    const gchar *text)
{
      g_return_if_fail(KZ_IS_ENTRY_ACTION(action));

      g_object_set(action, "text", text, NULL);
}


const gchar *
kz_entry_action_get_text (KzEntryAction *action)
{
      g_return_val_if_fail(KZ_IS_ENTRY_ACTION(action), NULL);

      return action->text;
}


Generated by  Doxygen 1.6.0   Back to index