/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2001-2002 CodeFactory AB * Copyright (C) 2001-2002 Richard Hult * Copyright (C) 2001-2002 Mikael Hallendal * * 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 of the * License, 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 #include #include #include #include #include #include #include #include #include #include "mg-popup-entry.h" static void mg_popup_entry_init (MgPopupEntry *entry); static void mg_popup_entry_class_init (MgPopupEntryClass *class); static void mpw_cell_editable_init (GtkCellEditableIface *iface); static gboolean mpw_key_press_event (GtkWidget *box, GdkEventKey *key_event); enum { ARROW_CLICKED, LAST_SIGNAL }; static GtkEventBoxClass *parent_class; static guint signals[LAST_SIGNAL]; GtkType mg_popup_entry_get_type (void) { static GtkType widget_type = 0; if (!widget_type) { static const GTypeInfo widget_info = { sizeof (MgPopupEntryClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) mg_popup_entry_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (MgPopupEntry), 0, /* n_preallocs */ (GInstanceInitFunc) mg_popup_entry_init, }; static const GInterfaceInfo cell_editable_info = { (GInterfaceInitFunc) mpw_cell_editable_init, /* interface_init */ NULL, /* interface_finalize */ NULL /* interface_data */ }; widget_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "MgPopupEntry", &widget_info, 0); g_type_add_interface_static (widget_type, GTK_TYPE_CELL_EDITABLE, &cell_editable_info); } return widget_type; } static void mg_popup_entry_init (MgPopupEntry *widget) { GtkWidget *arrow; widget->hbox = gtk_hbox_new (FALSE, 0); gtk_widget_show (widget->hbox); widget->entry = g_object_new (GTK_TYPE_ENTRY, "has_frame", FALSE, NULL); GTK_ENTRY (widget->entry)->is_cell_renderer = TRUE; gtk_widget_show (widget->entry); widget->button = gtk_button_new (); gtk_widget_show (widget->button); arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (arrow); gtk_container_add (GTK_CONTAINER (widget->button), arrow); gtk_box_pack_start (GTK_BOX (widget->hbox), widget->entry, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (widget->hbox), widget->button, FALSE, TRUE, 0); gtk_container_add (GTK_CONTAINER (widget), widget->hbox); GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_PRESS_MASK); gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_RELEASE_MASK); } static void mg_popup_entry_class_init (MgPopupEntryClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); widget_class->key_press_event = mpw_key_press_event; parent_class = GTK_EVENT_BOX_CLASS (g_type_class_peek_parent (klass)); signals[ARROW_CLICKED] = g_signal_new ("arrow-clicked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void mpw_arrow_clicked (GtkWidget *button, MgPopupEntry *widget) { g_signal_emit (widget, signals[ARROW_CLICKED], 0); } /* GtkCellEditable method implementations */ static void gtk_cell_editable_entry_activated (GtkEntry *entry, MgPopupEntry *widget) { gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget)); gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget)); } static gboolean gtk_cell_editable_key_press_event (GtkEntry *entry, GdkEventKey *key_event, MgPopupEntry *widget) { if (key_event->keyval == GDK_Escape) { widget->editing_canceled = TRUE; gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget)); gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget)); return TRUE; } return FALSE; } static gboolean mpw_key_press_event (GtkWidget *box, GdkEventKey *key_event) { MgPopupEntry *widget = MG_POPUP_ENTRY (box); GdkEvent tmp_event; if (key_event->keyval == GDK_Escape) { widget->editing_canceled = TRUE; gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget)); gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget)); return TRUE; } gtk_widget_grab_focus (widget->entry); /* Hackish :/ Synthesize a key press event for the entry. */ memcpy (&tmp_event, key_event, sizeof (GdkEventKey)); tmp_event.key.window = widget->entry->window; tmp_event.key.send_event = TRUE; gtk_widget_event (widget->entry, &tmp_event); return GTK_WIDGET_CLASS (parent_class)->key_press_event (GTK_WIDGET (widget), key_event); } static void mpw_start_editing (GtkCellEditable *cell_editable, GdkEvent *event) { MgPopupEntry *widget = MG_POPUP_ENTRY (cell_editable); gtk_editable_select_region (GTK_EDITABLE (widget->entry), 0, -1); g_signal_connect (G_OBJECT (widget->entry), "activate", G_CALLBACK (gtk_cell_editable_entry_activated), widget); g_signal_connect (G_OBJECT (widget->entry), "key_press_event", G_CALLBACK (gtk_cell_editable_key_press_event), widget); g_signal_connect (G_OBJECT (widget->button), "clicked", (GCallback) mpw_arrow_clicked, widget); } static void mpw_cell_editable_init (GtkCellEditableIface *iface) { iface->start_editing = mpw_start_editing; } void mg_popup_entry_set_text (MgPopupEntry *popup, const gchar *text) { g_return_if_fail (MG_IS_POPUP_ENTRY (popup)); gtk_entry_set_text (GTK_ENTRY (popup->entry), text ? text : ""); } const gchar * mg_popup_entry_get_text (MgPopupEntry *popup) { g_return_val_if_fail (MG_IS_POPUP_ENTRY (popup), NULL); return gtk_entry_get_text (GTK_ENTRY (popup->entry)); } gint mg_popup_get_button_width (void) { GtkWidget *window, *button, *arrow; gint width; GtkRequisition req; window = gtk_window_new (GTK_WINDOW_POPUP); button = gtk_button_new (); gtk_widget_show (button); gtk_container_add (GTK_CONTAINER (window), button); arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show (arrow); gtk_container_add (GTK_CONTAINER (button), arrow); gtk_window_move (GTK_WINDOW (window), -500, -500); gtk_widget_show (window); gtk_widget_size_request (window, &req); width = req.width; gtk_widget_destroy (window); return width; }