diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2012-12-10 21:09:59 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2012-12-13 03:33:43 +0800 |
commit | d09d8de870b6697c8a8b262e7e077b871a69b315 (patch) | |
tree | 3b718882e7a0bb0a996daf2967a033d91714c9b5 /widgets/table/e-cell-combo.c | |
parent | b61331ed03ac1c7a9b8614e25510040b9c60ae02 (diff) | |
download | gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.gz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.bz2 gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.lz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.xz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.zst gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.zip |
Consolidate base utility libraries into libeutil.
Evolution consists of entirely too many small utility libraries, which
increases linking and loading time, places a burden on higher layers of
the application (e.g. modules) which has to remember to link to all the
small in-tree utility libraries, and makes it difficult to generate API
documentation for these utility libraries in one Gtk-Doc module.
Merge the following utility libraries under the umbrella of libeutil,
and enforce a single-include policy on libeutil so we can reorganize
the files as desired without disrupting its pseudo-public API.
libemail-utils/libemail-utils.la
libevolution-utils/libevolution-utils.la
filter/libfilter.la
widgets/e-timezone-dialog/libetimezonedialog.la
widgets/menus/libmenus.la
widgets/misc/libemiscwidgets.la
widgets/table/libetable.la
widgets/text/libetext.la
This also merges libedataserverui from the Evolution-Data-Server module,
since Evolution is its only consumer nowadays, and I'd like to make some
improvements to those APIs without concern for backward-compatibility.
And finally, start a Gtk-Doc module for libeutil. It's going to be a
project just getting all the symbols _listed_ much less _documented_.
But the skeletal structure is in place and I'm off to a good start.
Diffstat (limited to 'widgets/table/e-cell-combo.c')
-rw-r--r-- | widgets/table/e-cell-combo.c | 839 |
1 files changed, 0 insertions, 839 deletions
diff --git a/widgets/table/e-cell-combo.c b/widgets/table/e-cell-combo.c deleted file mode 100644 index bc82042d7a..0000000000 --- a/widgets/table/e-cell-combo.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * e-cell-combo.c: Combo cell renderer - * - * This program 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) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Damon Chaplin <damon@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* - * ECellCombo - a subclass of ECellPopup used to support popup lists like a - * GtkCombo widget. It only supports a basic popup list of strings at present, - * with no auto-completion. - */ - -/* - * Notes: (handling pointer grabs and GTK+ grabs is a nightmare!) - * - * o We must grab the pointer when we show the popup, so that if any buttons - * are pressed outside the application we hide the popup. - * - * o We have to be careful when popping up any widgets which also grab the - * pointer at some point, since we will lose our own pointer grab. - * When we pop up a list it will grab the pointer itself when an item is - * selected, and release the grab when the button is released. - * Fortunately we hide the popup at this point, so it isn't a problem. - * But for other types of widgets in the popup it could cause trouble. - * - I think GTK+ should provide help for this (nested pointer grabs?). - * - * o We must set the 'owner_events' flag of the pointer grab to TRUE so that - * pointer events get reported to all the application windows as normal. - * If we don't do this then the widgets in the popup may not work properly. - * - * o We must do a gtk_grab_add() so that we only allow events to go to the - * widgets within the popup (though some special events still get reported - * to the widget owning the window). Doing th gtk_grab_add() on the toplevel - * popup window should be fine. We can then check for any events that should - * close the popup, like the Escape key, or a button press outside the popup. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include <glib/gi18n.h> -#include "e-util/e-util.h" -#include "e-util/e-unicode.h" - -#include "e-table-item.h" -#include "e-cell-combo.h" -#include "e-cell-text.h" - -#define d(x) - -/* The height to make the popup list if there aren't any items in it. */ -#define E_CELL_COMBO_LIST_EMPTY_HEIGHT 15 - -static void e_cell_combo_dispose (GObject *object); -static gint e_cell_combo_do_popup (ECellPopup *ecp, - GdkEvent *event, - gint row, - gint view_col); -static void e_cell_combo_select_matching_item - (ECellCombo *ecc); -static void e_cell_combo_show_popup (ECellCombo *ecc, - gint row, - gint view_col); -static void e_cell_combo_get_popup_pos (ECellCombo *ecc, - gint row, - gint view_col, - gint *x, - gint *y, - gint *height, - gint *width); -static void e_cell_combo_selection_changed (GtkTreeSelection *selection, - ECellCombo *ecc); -static gint e_cell_combo_button_press (GtkWidget *popup_window, - GdkEvent *button_event, - ECellCombo *ecc); -static gint e_cell_combo_button_release (GtkWidget *popup_window, - GdkEvent *button_event, - ECellCombo *ecc); -static gint e_cell_combo_key_press (GtkWidget *popup_window, - GdkEvent *key_event, - ECellCombo *ecc); -static void e_cell_combo_update_cell (ECellCombo *ecc); -static void e_cell_combo_restart_edit (ECellCombo *ecc); - -G_DEFINE_TYPE (ECellCombo, e_cell_combo, E_TYPE_CELL_POPUP) - -static void -e_cell_combo_class_init (ECellComboClass *class) -{ - ECellPopupClass *ecpc = E_CELL_POPUP_CLASS (class); - GObjectClass *object_class = G_OBJECT_CLASS (class); - - object_class->dispose = e_cell_combo_dispose; - - ecpc->popup = e_cell_combo_do_popup; -} - -static void -e_cell_combo_init (ECellCombo *ecc) -{ - GtkWidget *frame; - AtkObject *a11y; - GtkListStore *store; - GtkTreeSelection *selection; - GtkScrolledWindow *scrolled_window; - - /* We create one popup window for the ECell, since there will only - * ever be one popup in use at a time. */ - ecc->popup_window = gtk_window_new (GTK_WINDOW_POPUP); - - gtk_window_set_type_hint ( - GTK_WINDOW (ecc->popup_window), GDK_WINDOW_TYPE_HINT_COMBO); - gtk_window_set_resizable (GTK_WINDOW (ecc->popup_window), TRUE); - - frame = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (ecc->popup_window), frame); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_widget_show (frame); - - ecc->popup_scrolled_window = gtk_scrolled_window_new (NULL, NULL); - scrolled_window = GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window); - - gtk_scrolled_window_set_policy ( - scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_set_can_focus ( - gtk_scrolled_window_get_hscrollbar (scrolled_window), FALSE); - gtk_widget_set_can_focus ( - gtk_scrolled_window_get_vscrollbar (scrolled_window), FALSE); - gtk_container_add (GTK_CONTAINER (frame), ecc->popup_scrolled_window); - gtk_widget_show (ecc->popup_scrolled_window); - - store = gtk_list_store_new (1, G_TYPE_STRING); - ecc->popup_tree_view = - gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); - g_object_unref (store); - - gtk_tree_view_append_column ( - GTK_TREE_VIEW (ecc->popup_tree_view), - gtk_tree_view_column_new_with_attributes ( - "Text", gtk_cell_renderer_text_new (), - "text", 0, NULL)); - - gtk_tree_view_set_headers_visible ( - GTK_TREE_VIEW (ecc->popup_tree_view), FALSE); - - selection = gtk_tree_view_get_selection ( - GTK_TREE_VIEW (ecc->popup_tree_view)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - gtk_scrolled_window_add_with_viewport ( - GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window), - ecc->popup_tree_view); - gtk_container_set_focus_vadjustment ( - GTK_CONTAINER (ecc->popup_tree_view), - gtk_scrolled_window_get_vadjustment ( - GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window))); - gtk_container_set_focus_hadjustment ( - GTK_CONTAINER (ecc->popup_tree_view), - gtk_scrolled_window_get_hadjustment ( - GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window))); - gtk_widget_show (ecc->popup_tree_view); - - a11y = gtk_widget_get_accessible (ecc->popup_tree_view); - atk_object_set_name (a11y, _("popup list")); - - g_signal_connect ( - selection, "changed", - G_CALLBACK (e_cell_combo_selection_changed), ecc); - g_signal_connect ( - ecc->popup_window, "button_press_event", - G_CALLBACK (e_cell_combo_button_press), ecc); - g_signal_connect ( - ecc->popup_window, "button_release_event", - G_CALLBACK (e_cell_combo_button_release), ecc); - g_signal_connect ( - ecc->popup_window, "key_press_event", - G_CALLBACK (e_cell_combo_key_press), ecc); -} - -/** - * e_cell_combo_new: - * - * Creates a new ECellCombo renderer. - * - * Returns: an ECellCombo object. - */ -ECell * -e_cell_combo_new (void) -{ - return g_object_new (E_TYPE_CELL_COMBO, NULL); -} - -/* - * GObject::dispose method - */ -static void -e_cell_combo_dispose (GObject *object) -{ - ECellCombo *ecc = E_CELL_COMBO (object); - - if (ecc->popup_window != NULL) { - gtk_widget_destroy (ecc->popup_window); - ecc->popup_window = NULL; - } - - if (ecc->grabbed_keyboard != NULL) { - gdk_device_ungrab (ecc->grabbed_keyboard, GDK_CURRENT_TIME); - g_object_unref (ecc->grabbed_keyboard); - ecc->grabbed_keyboard = NULL; - } - - if (ecc->grabbed_pointer != NULL) { - gdk_device_ungrab (ecc->grabbed_pointer, GDK_CURRENT_TIME); - g_object_unref (ecc->grabbed_pointer); - ecc->grabbed_pointer = NULL; - } - - G_OBJECT_CLASS (e_cell_combo_parent_class)->dispose (object); -} - -void -e_cell_combo_set_popdown_strings (ECellCombo *ecc, - GList *strings) -{ - GList *elem; - GtkListStore *store; - - g_return_if_fail (E_IS_CELL_COMBO (ecc)); - g_return_if_fail (strings != NULL); - - store = GTK_LIST_STORE ( - gtk_tree_view_get_model ( - GTK_TREE_VIEW (ecc->popup_tree_view))); - gtk_list_store_clear (store); - - for (elem = strings; elem; elem = elem->next) { - GtkTreeIter iter; - gchar *utf8_text = elem->data; - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, utf8_text, -1); - } -} - -static gint -e_cell_combo_do_popup (ECellPopup *ecp, - GdkEvent *event, - gint row, - gint view_col) -{ - ECellCombo *ecc = E_CELL_COMBO (ecp); - GtkTreeSelection *selection; - GdkGrabStatus grab_status; - GdkWindow *window; - GdkDevice *keyboard; - GdkDevice *pointer; - GdkDevice *event_device; - guint32 event_time; - - g_return_val_if_fail (ecc->grabbed_keyboard == NULL, FALSE); - g_return_val_if_fail (ecc->grabbed_pointer == NULL, FALSE); - - selection = gtk_tree_view_get_selection ( - GTK_TREE_VIEW (ecc->popup_tree_view)); - - g_signal_handlers_block_by_func ( - selection, e_cell_combo_selection_changed, ecc); - - e_cell_combo_show_popup (ecc, row, view_col); - e_cell_combo_select_matching_item (ecc); - - g_signal_handlers_unblock_by_func ( - selection, e_cell_combo_selection_changed, ecc); - - window = gtk_widget_get_window (ecc->popup_tree_view); - - event_device = gdk_event_get_device (event); - event_time = gdk_event_get_time (event); - - if (gdk_device_get_source (event_device) == GDK_SOURCE_KEYBOARD) { - keyboard = event_device; - pointer = gdk_device_get_associated_device (event_device); - } else { - keyboard = gdk_device_get_associated_device (event_device); - pointer = event_device; - } - - if (pointer != NULL) { - grab_status = gdk_device_grab ( - pointer, - window, - GDK_OWNERSHIP_NONE, - TRUE, - GDK_ENTER_NOTIFY_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK, - NULL, - event_time); - - if (grab_status != GDK_GRAB_SUCCESS) - return FALSE; - - ecc->grabbed_pointer = g_object_ref (pointer); - } - - gtk_grab_add (ecc->popup_window); - - if (keyboard != NULL) { - grab_status = gdk_device_grab ( - keyboard, - window, - GDK_OWNERSHIP_NONE, - TRUE, - GDK_KEY_PRESS_MASK | - GDK_KEY_RELEASE_MASK, - NULL, - event_time); - - if (grab_status != GDK_GRAB_SUCCESS) { - if (ecc->grabbed_pointer != NULL) { - gdk_device_ungrab ( - ecc->grabbed_pointer, - event_time); - g_object_unref (ecc->grabbed_pointer); - ecc->grabbed_pointer = NULL; - } - return FALSE; - } - - ecc->grabbed_keyboard = g_object_ref (keyboard); - } - - return TRUE; -} - -static void -e_cell_combo_select_matching_item (ECellCombo *ecc) -{ - ECellPopup *ecp = E_CELL_POPUP (ecc); - ECellView *ecv = (ECellView *) ecp->popup_cell_view; - ECellText *ecell_text = E_CELL_TEXT (ecp->child); - ETableItem *eti; - ETableCol *ecol; - gboolean found = FALSE; - gchar *cell_text; - gboolean valid; - GtkTreeSelection *selection; - GtkTreeIter iter; - GtkTreeModel *model; - - eti = E_TABLE_ITEM (ecp->popup_cell_view->cell_view.e_table_item_view); - - ecol = e_table_header_get_column (eti->header, ecp->popup_view_col); - cell_text = e_cell_text_get_text ( - ecell_text, ecv->e_table_model, - ecol->col_idx, ecp->popup_row); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (ecc->popup_tree_view)); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ecc->popup_tree_view)); - - for (valid = gtk_tree_model_get_iter_first (model, &iter); - valid && !found; - valid = gtk_tree_model_iter_next (model, &iter)) { - gchar *str = NULL; - - gtk_tree_model_get (model, &iter, 0, &str, -1); - - if (str && g_str_equal (str, cell_text)) { - GtkTreePath *path; - - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_view_set_cursor ( - GTK_TREE_VIEW (ecc->popup_tree_view), - path, NULL, FALSE); - gtk_tree_path_free (path); - - found = TRUE; - } - - g_free (str); - } - - if (!found) - gtk_tree_selection_unselect_all (selection); - - e_cell_text_free_text (ecell_text, cell_text); -} - -static void -e_cell_combo_show_popup (ECellCombo *ecc, - gint row, - gint view_col) -{ - GdkWindow *window; - GtkAllocation allocation; - gint x, y, width, height, old_width, old_height; - - gtk_widget_get_allocation (ecc->popup_window, &allocation); - - /* This code is practically copied from GtkCombo. */ - old_width = allocation.width; - old_height = allocation.height; - - e_cell_combo_get_popup_pos (ecc, row, view_col, &x, &y, &height, &width); - - /* workaround for gtk_scrolled_window_size_allocate bug */ - if (old_width != width || old_height != height) { - gtk_widget_hide ( - gtk_scrolled_window_get_hscrollbar ( - GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window))); - gtk_widget_hide ( - gtk_scrolled_window_get_vscrollbar ( - GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window))); - } - - gtk_window_move (GTK_WINDOW (ecc->popup_window), x, y); - gtk_widget_set_size_request (ecc->popup_window, width, height); - gtk_widget_realize (ecc->popup_window); - window = gtk_widget_get_window (ecc->popup_window); - gdk_window_resize (window, width, height); - gtk_widget_show (ecc->popup_window); - - e_cell_popup_set_shown (E_CELL_POPUP (ecc), TRUE); - d (g_print ("%s: popup_shown = TRUE\n", __FUNCTION__)); -} - -/* Calculates the size and position of the popup window (like GtkCombo). */ -static void -e_cell_combo_get_popup_pos (ECellCombo *ecc, - gint row, - gint view_col, - gint *x, - gint *y, - gint *height, - gint *width) -{ - ECellPopup *ecp = E_CELL_POPUP (ecc); - ETableItem *eti; - GtkWidget *canvas; - GtkWidget *widget; - GtkWidget *popwin_child; - GtkWidget *popup_child; - GtkStyle *popwin_style; - GtkStyle *popup_style; - GdkWindow *window; - GtkBin *popwin; - GtkScrolledWindow *popup; - GtkRequisition requisition; - GtkRequisition list_requisition; - gboolean show_vscroll = FALSE, show_hscroll = FALSE; - gint avail_height, avail_width, min_height, work_height, screen_width; - gint column_width, row_height, scrollbar_width; - gdouble x1, y1; - gdouble wx, wy; - - eti = E_TABLE_ITEM (ecp->popup_cell_view->cell_view.e_table_item_view); - canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (eti)->canvas); - - /* This code is practically copied from GtkCombo. */ - popup = GTK_SCROLLED_WINDOW (ecc->popup_scrolled_window); - popwin = GTK_BIN (ecc->popup_window); - - window = gtk_widget_get_window (canvas); - gdk_window_get_origin (window, x, y); - - x1 = e_table_header_col_diff (eti->header, 0, view_col + 1); - y1 = e_table_item_row_diff (eti, 0, row + 1); - column_width = e_table_header_col_diff ( - eti->header, view_col, view_col + 1); - row_height = e_table_item_row_diff (eti, row, row + 1); - gnome_canvas_item_i2w (GNOME_CANVAS_ITEM (eti), &x1, &y1); - - gnome_canvas_world_to_window ( - GNOME_CANVAS (canvas), x1, y1, &wx, &wy); - - x1 = wx; - y1 = wy; - - *x += x1; - /* The ETable positions don't include the grid lines, I think, so we add 1. */ - *y += y1 + 1 - (gint) - gtk_adjustment_get_value ( - gtk_scrollable_get_vadjustment ( - GTK_SCROLLABLE (&((GnomeCanvas *) canvas)->layout))) - + ((GnomeCanvas *) canvas)->zoom_yofs; - - widget = gtk_scrolled_window_get_vscrollbar (popup); - gtk_widget_get_preferred_size (widget, &requisition, NULL); - - scrollbar_width = - requisition.width - + GTK_SCROLLED_WINDOW_CLASS (G_OBJECT_GET_CLASS (popup))->scrollbar_spacing; - - avail_height = gdk_screen_height () - *y; - - /* We'll use the entire screen width if needed, but we save space for - * the vertical scrollbar in case we need to show that. */ - screen_width = gdk_screen_width (); - avail_width = screen_width - scrollbar_width; - - widget = gtk_scrolled_window_get_vscrollbar (popup); - gtk_widget_get_preferred_size (widget, &requisition, NULL); - - gtk_widget_get_preferred_size (ecc->popup_tree_view, &list_requisition, NULL); - min_height = MIN (list_requisition.height, requisition.height); - if (!gtk_tree_model_iter_n_children ( - gtk_tree_view_get_model ( - GTK_TREE_VIEW (ecc->popup_tree_view)), NULL)) - list_requisition.height += E_CELL_COMBO_LIST_EMPTY_HEIGHT; - - popwin_child = gtk_bin_get_child (popwin); - popwin_style = gtk_widget_get_style (popwin_child); - - popup_child = gtk_bin_get_child (GTK_BIN (popup)); - popup_style = gtk_widget_get_style (popup_child); - - /* Calculate the desired width. */ - *width = list_requisition.width - + 2 * popwin_style->xthickness - + 2 * gtk_container_get_border_width (GTK_CONTAINER (popwin_child)) - + 2 * gtk_container_get_border_width (GTK_CONTAINER (popup)) - + 2 * gtk_container_get_border_width (GTK_CONTAINER (popup_child)) - + 2 * popup_style->xthickness; - - /* Use at least the same width as the column. */ - if (*width < column_width) - *width = column_width; - - /* If it is larger than the available width, use that instead and show - * the horizontal scrollbar. */ - if (*width > avail_width) { - *width = avail_width; - show_hscroll = TRUE; - } - - /* Calculate all the borders etc. that we need to add to the height. */ - work_height = (2 * popwin_style->ythickness - + 2 * gtk_container_get_border_width (GTK_CONTAINER (popwin_child)) - + 2 * gtk_container_get_border_width (GTK_CONTAINER (popup)) - + 2 * gtk_container_get_border_width (GTK_CONTAINER (popup_child)) - + 2 * popup_style->xthickness); - - widget = gtk_scrolled_window_get_hscrollbar (popup); - gtk_widget_get_preferred_size (widget, &requisition, NULL); - - /* Add on the height of the horizontal scrollbar if we need it. */ - if (show_hscroll) - work_height += - requisition.height + - GTK_SCROLLED_WINDOW_GET_CLASS (popup)->scrollbar_spacing; - - /* Check if it fits in the available height. */ - if (work_height + list_requisition.height > avail_height) { - /* It doesn't fit, so we see if we have the minimum space - * needed. */ - if (work_height + min_height > avail_height - && *y - row_height > avail_height) { - /* We don't, so we show the popup above the cell - * instead of below it. */ - avail_height = *y - row_height; - *y -= (work_height + list_requisition.height - + row_height); - if (*y < 0) - *y = 0; - } - } - - /* Check if we still need the vertical scrollbar. */ - if (work_height + list_requisition.height > avail_height) { - *width += scrollbar_width; - show_vscroll = TRUE; - } - - /* We try to line it up with the right edge of the column, but we don't - * want it to go off the edges of the screen. */ - if (*x > screen_width) - *x = screen_width; - *x -= *width; - if (*x < 0) - *x = 0; - - if (show_vscroll) - *height = avail_height; - else - *height = work_height + list_requisition.height; -} - -static void -e_cell_combo_selection_changed (GtkTreeSelection *selection, - ECellCombo *ecc) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - if (!gtk_widget_get_realized (ecc->popup_window) || - !gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - e_cell_combo_update_cell (ecc); - e_cell_combo_restart_edit (ecc); -} - -/* This handles button press events in the popup window. - * Note that since we have a pointer grab on this window, we also get button - * press events for windows outside the application here, so we hide the popup - * window if that happens. We also get propagated events from child widgets - * which we ignore. */ -static gint -e_cell_combo_button_press (GtkWidget *popup_window, - GdkEvent *button_event, - ECellCombo *ecc) -{ - GtkWidget *event_widget; - guint32 event_time; - - event_time = gdk_event_get_time (button_event); - event_widget = gtk_get_event_widget (button_event); - - /* If the button press was for a widget inside the popup list, but - * not the popup window itself, then we ignore the event and return - * FALSE. Otherwise we will hide the popup. - * Note that since we have a pointer grab on the popup list, button - * presses outside the application will be reported to this window, - * which is why we hide the popup in this case. */ - while (event_widget) { - event_widget = gtk_widget_get_parent (event_widget); - if (event_widget == ecc->popup_tree_view) - return FALSE; - } - - gtk_grab_remove (ecc->popup_window); - - if (ecc->grabbed_keyboard != NULL) { - gdk_device_ungrab (ecc->grabbed_keyboard, event_time); - g_object_unref (ecc->grabbed_keyboard); - ecc->grabbed_keyboard = NULL; - } - - if (ecc->grabbed_pointer != NULL) { - gdk_device_ungrab (ecc->grabbed_pointer, event_time); - g_object_unref (ecc->grabbed_pointer); - ecc->grabbed_pointer = NULL; - } - - gtk_widget_hide (ecc->popup_window); - - e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE); - d (g_print ("%s: popup_shown = FALSE\n", __FUNCTION__)); - - /* We don't want to update the cell here. Since the list is in browse - * mode there will always be one item selected, so when we popup the - * list one item is selected even if it doesn't match the current text - * in the cell. So if you click outside the popup (which is what has - * happened here) it is better to not update the cell. */ - /*e_cell_combo_update_cell (ecc);*/ - e_cell_combo_restart_edit (ecc); - - return TRUE; -} - -/* This handles button release events in the popup window. If the button is - * released inside the list, we want to hide the popup window and update the - * cell with the new selection. */ -static gint -e_cell_combo_button_release (GtkWidget *popup_window, - GdkEvent *button_event, - ECellCombo *ecc) -{ - GtkWidget *event_widget; - guint32 event_time; - - event_time = gdk_event_get_time (button_event); - event_widget = gtk_get_event_widget (button_event); - - /* See if the button was released in the list (or its children). */ - while (event_widget && event_widget != ecc->popup_tree_view) - event_widget = gtk_widget_get_parent (event_widget); - - /* If it wasn't, then we just ignore the event. */ - if (event_widget != ecc->popup_tree_view) - return FALSE; - - /* The button was released inside the list, so we hide the popup and - * update the cell to reflect the new selection. */ - - gtk_grab_remove (ecc->popup_window); - - if (ecc->grabbed_keyboard != NULL) { - gdk_device_ungrab (ecc->grabbed_keyboard, event_time); - g_object_unref (ecc->grabbed_keyboard); - ecc->grabbed_keyboard = NULL; - } - - if (ecc->grabbed_pointer != NULL) { - gdk_device_ungrab (ecc->grabbed_pointer, event_time); - g_object_unref (ecc->grabbed_pointer); - ecc->grabbed_pointer = NULL; - } - - gtk_widget_hide (ecc->popup_window); - - e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE); - d (g_print ("%s: popup_shown = FALSE\n", __FUNCTION__)); - - e_cell_combo_update_cell (ecc); - e_cell_combo_restart_edit (ecc); - - return TRUE; -} - -/* This handles key press events in the popup window. If the Escape key is - * pressed we hide the popup, and do not change the cell contents. */ -static gint -e_cell_combo_key_press (GtkWidget *popup_window, - GdkEvent *key_event, - ECellCombo *ecc) -{ - guint event_keyval = 0; - guint32 event_time; - - gdk_event_get_keyval (key_event, &event_keyval); - event_time = gdk_event_get_time (key_event); - - /* If the Escape key is pressed we hide the popup. */ - if (event_keyval != GDK_KEY_Escape - && event_keyval != GDK_KEY_Return - && event_keyval != GDK_KEY_KP_Enter - && event_keyval != GDK_KEY_ISO_Enter - && event_keyval != GDK_KEY_3270_Enter) - return FALSE; - - if (event_keyval == GDK_KEY_Escape && - (!ecc->popup_window || !gtk_widget_get_visible (ecc->popup_window))) - return FALSE; - - gtk_grab_remove (ecc->popup_window); - - if (ecc->grabbed_keyboard != NULL) { - gdk_device_ungrab (ecc->grabbed_keyboard, event_time); - g_object_unref (ecc->grabbed_keyboard); - ecc->grabbed_keyboard = NULL; - } - - if (ecc->grabbed_pointer != NULL) { - gdk_device_ungrab (ecc->grabbed_pointer, event_time); - g_object_unref (ecc->grabbed_pointer); - ecc->grabbed_pointer = NULL; - } - - gtk_widget_hide (ecc->popup_window); - - e_cell_popup_set_shown (E_CELL_POPUP (ecc), FALSE); - d (g_print ("%s: popup_shown = FALSE\n", __FUNCTION__)); - - if (event_keyval != GDK_KEY_Escape) - e_cell_combo_update_cell (ecc); - - e_cell_combo_restart_edit (ecc); - - return TRUE; -} - -static void -e_cell_combo_update_cell (ECellCombo *ecc) -{ - ECellPopup *ecp = E_CELL_POPUP (ecc); - ECellView *ecv = (ECellView *) ecp->popup_cell_view; - ECellText *ecell_text = E_CELL_TEXT (ecp->child); - ETableItem *eti = E_TABLE_ITEM (ecv->e_table_item_view); - ETableCol *ecol; - GtkTreeSelection *selection = gtk_tree_view_get_selection ( - GTK_TREE_VIEW (ecc->popup_tree_view)); - GtkTreeModel *model; - GtkTreeIter iter; - gchar *text = NULL, *old_text; - - /* Return if no item is selected. */ - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - /* Get the text of the selected item. */ - gtk_tree_model_get (model, &iter, 0, &text, -1); - g_return_if_fail (text != NULL); - - /* Compare it with the existing cell contents. */ - ecol = e_table_header_get_column (eti->header, ecp->popup_view_col); - - old_text = e_cell_text_get_text ( - ecell_text, ecv->e_table_model, - ecol->col_idx, ecp->popup_row); - - /* If they are different, update the cell contents. */ - if (old_text && strcmp (old_text, text)) { - e_cell_text_set_value ( - ecell_text, ecv->e_table_model, - ecol->col_idx, ecp->popup_row, text); - } - - e_cell_text_free_text (ecell_text, old_text); - g_free (text); -} - -static void -e_cell_combo_restart_edit (ECellCombo *ecc) -{ - /* This doesn't work. ETable stops the edit straight-away again. */ -#if 0 - ECellView *ecv = (ECellView *) ecc->popup_cell_view; - ETableItem *eti = E_TABLE_ITEM (ecv->e_table_item_view); - - e_table_item_enter_edit (eti, ecc->popup_view_col, ecc->popup_row); -#endif -} - |