diff options
Diffstat (limited to 'src/idoentrymenuitem.c')
-rw-r--r-- | src/idoentrymenuitem.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/idoentrymenuitem.c b/src/idoentrymenuitem.c new file mode 100644 index 0000000..1d5bd54 --- /dev/null +++ b/src/idoentrymenuitem.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2010 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Cody Russell <crussell@canonical.com> + */ + +#include "idoentrymenuitem.h" + +static void ido_entry_menu_item_select (GtkItem *item); +static void ido_entry_menu_item_deselect (GtkItem *item); +static gboolean ido_entry_menu_item_button_release (GtkWidget *widget, + GdkEventButton *event); +static gboolean ido_entry_menu_item_key_press (GtkWidget *widget, + GdkEventKey *event, + gpointer data); +static gboolean ido_entry_menu_item_button_press (GtkWidget *widget, + GdkEventButton *event); +static void ido_entry_menu_item_send_focus_change (GtkWidget *widget, + gboolean in); +static void entry_realized_cb (GtkWidget *widget, + IdoEntryMenuItem *item); +static void entry_move_focus_cb (GtkWidget *widget, + GtkDirectionType direction, + IdoEntryMenuItem *item); + +struct _IdoEntryMenuItemPrivate +{ + GtkWidget *entry; + gboolean selected; +}; + +G_DEFINE_TYPE (IdoEntryMenuItem, ido_entry_menu_item, GTK_TYPE_MENU_ITEM) + +#define IDO_ENTRY_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IDO_TYPE_ENTRY_MENU_ITEM, IdoEntryMenuItemPrivate)) + +static void +ido_entry_menu_item_class_init (IdoEntryMenuItemClass *klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + GtkMenuItemClass *menu_item_class; + GtkItemClass *item_class; + + gobject_class = G_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + menu_item_class = GTK_MENU_ITEM_CLASS (klass); + item_class = GTK_ITEM_CLASS (klass); + + widget_class->button_release_event = ido_entry_menu_item_button_release; + widget_class->button_press_event = ido_entry_menu_item_button_press; + + item_class->select = ido_entry_menu_item_select; + item_class->deselect = ido_entry_menu_item_deselect; + + menu_item_class->hide_on_activate = FALSE; + + g_type_class_add_private (gobject_class, sizeof (IdoEntryMenuItemPrivate)); +} + +static void +ido_entry_menu_item_init (IdoEntryMenuItem *item) +{ + IdoEntryMenuItemPrivate *priv; + + priv = item->priv = IDO_ENTRY_MENU_ITEM_GET_PRIVATE (item); + + priv->entry = gtk_entry_new (); + g_signal_connect (priv->entry, + "realize", + G_CALLBACK (entry_realized_cb), + item); + g_signal_connect (priv->entry, + "move-focus", + G_CALLBACK (entry_move_focus_cb), + item); + + gtk_widget_set_size_request (priv->entry, 100, -1); + + gtk_container_add (GTK_CONTAINER (item), priv->entry); + + gtk_widget_show (priv->entry); +} + +static gboolean +ido_entry_menu_item_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + return TRUE; +} + +static gboolean +ido_entry_menu_item_key_press (GtkWidget *widget, + GdkEventKey *event, + gpointer data) +{ + IdoEntryMenuItem *menuitem = (IdoEntryMenuItem *)data; + + if (menuitem->priv->selected) + { + gtk_widget_event (menuitem->priv->entry, + (GdkEvent *)event); + } + + return FALSE; +} + +static void +ido_entry_menu_item_send_focus_change (GtkWidget *widget, + gboolean in) +{ + GdkEvent *event = gdk_event_new (GDK_FOCUS_CHANGE); + + g_object_ref (widget); + + if (in) + { + GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); + } + else + { + GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); + } + + event->focus_change.type = GDK_FOCUS_CHANGE; + event->focus_change.window = g_object_ref (widget->window); + event->focus_change.in = in; + + gtk_widget_event (widget, event); + + g_object_notify (G_OBJECT (widget), "has-focus"); + + g_object_unref (widget); + gdk_event_free (event); +} + +static gboolean +ido_entry_menu_item_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GtkWidget *entry; + + entry = IDO_ENTRY_MENU_ITEM (widget)->priv->entry; + + if (entry->window != NULL) + { + gdk_window_raise (entry->window); + } + + if (!GTK_WIDGET_HAS_FOCUS (entry)) + { + gtk_widget_grab_focus (entry); + } + + return FALSE; +} + +static void +ido_entry_menu_item_select (GtkItem *item) +{ + IDO_ENTRY_MENU_ITEM (item)->priv->selected = TRUE; + + ido_entry_menu_item_send_focus_change (GTK_WIDGET (IDO_ENTRY_MENU_ITEM (item)->priv->entry), TRUE); +} + +static void +ido_entry_menu_item_deselect (GtkItem *item) +{ + IDO_ENTRY_MENU_ITEM (item)->priv->selected = FALSE; + + ido_entry_menu_item_send_focus_change (GTK_WIDGET (IDO_ENTRY_MENU_ITEM (item)->priv->entry), FALSE); +} + + +static void +entry_realized_cb (GtkWidget *widget, + IdoEntryMenuItem *item) +{ + if (widget->window != NULL) + { + gdk_window_raise (widget->window); + } + + g_signal_connect (GTK_WIDGET (item)->parent, + "key-press-event", + G_CALLBACK (ido_entry_menu_item_key_press), + item); + + ido_entry_menu_item_send_focus_change (widget, TRUE); +} + +static void +entry_move_focus_cb (GtkWidget *widget, + GtkDirectionType direction, + IdoEntryMenuItem *item) +{ + ido_entry_menu_item_send_focus_change (GTK_WIDGET (IDO_ENTRY_MENU_ITEM (item)->priv->entry), FALSE); + + g_signal_emit_by_name (item, + "move-focus", + GTK_DIR_TAB_FORWARD); +} + +/* Public API */ +GtkWidget * +ido_entry_menu_item_new (void) +{ + return g_object_new (IDO_TYPE_ENTRY_MENU_ITEM, NULL); +} + +GtkWidget * +ido_entry_menu_item_get_entry (IdoEntryMenuItem *item) +{ + g_return_val_if_fail (IDO_IS_ENTRY_MENU_ITEM (item), NULL); + + return item->priv->entry; +} |