From e65ce47c209498fc592e9bfb2720abdc0d2ffb9c Mon Sep 17 00:00:00 2001 From: Damon Chaplin Date: Sun, 25 Feb 2001 19:29:40 +0000 Subject: new abstract ECell subclass to be used as base class for popup ECells. 2001-02-25 Damon Chaplin * e-cell-popup.c: new abstract ECell subclass to be used as base class for popup ECells. * e-cell-combo.c: subclass of ECellPopup which pops up a simple list of strings. * e-table-item.c: Renamed eti_row_diff() to e_table_item_row_diff() and made public, since the ECellPopup subclasses need it. * Makefile.am: added e-cell-popup.[hc] and e-cell-combo.[hc] svn path=/trunk/; revision=8387 --- widgets/table/e-cell-popup.c | 504 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 504 insertions(+) create mode 100644 widgets/table/e-cell-popup.c (limited to 'widgets/table/e-cell-popup.c') diff --git a/widgets/table/e-cell-popup.c b/widgets/table/e-cell-popup.c new file mode 100644 index 0000000000..2acc921d12 --- /dev/null +++ b/widgets/table/e-cell-popup.c @@ -0,0 +1,504 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * Author : + * Damon Chaplin + * + * Copyright 2001, Ximian, Inc. + * + * 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 + */ + +/* + * ECellPopup - an abstract ECell class used to support popup selections like + * a GtkCombo widget. It contains a child ECell, e.g. an ECellText, but when + * selected it displays an arrow on the right edge which the user can click to + * show a popup. Subclasses implement the popup class function to show the + * popup. + */ + +#include +#include +#include "gal/util/e-util.h" +#include "e-table-item.h" +#include "e-cell-popup.h" + + +#define E_CELL_POPUP_ARROW_WIDTH 16 +#define E_CELL_POPUP_ARROW_XPAD 3 +#define E_CELL_POPUP_ARROW_YPAD 3 + + +static void e_cell_popup_class_init (GtkObjectClass *object_class); +static void e_cell_popup_init (ECellPopup *ecp); +static void e_cell_popup_destroy (GtkObject *object); + + +static ECellView* ecp_new_view (ECell *ecell, + ETableModel *table_model, + void *e_table_item_view); +static void ecp_kill_view (ECellView *ecv); +static void ecp_realize (ECellView *ecv); +static void ecp_unrealize (ECellView *ecv); +static void ecp_draw (ECellView *ecv, + GdkDrawable *drawable, + int model_col, + int view_col, + int row, + ECellFlags flags, + int x1, + int y1, + int x2, + int y2); +static gint ecp_event (ECellView *ecv, + GdkEvent *event, + int model_col, + int view_col, + int row, + ECellFlags flags, + ECellActions *actions); +static int ecp_height (ECellView *ecv, + int model_col, + int view_col, + int row); +static void* ecp_enter_edit (ECellView *ecv, + int model_col, + int view_col, + int row); +static void ecp_leave_edit (ECellView *ecv, + int model_col, + int view_col, + int row, + void *edit_context); +static void ecp_print (ECellView *ecv, + GnomePrintContext *context, + int model_col, + int view_col, + int row, + double width, + double height); +static gdouble ecp_print_height (ECellView *ecv, + GnomePrintContext *context, + int model_col, + int view_col, + int row, + double width); +static int ecp_max_width (ECellView *ecv, + int model_col, + int view_col); +static void ecp_show_tooltip (ECellView *ecv, + int model_col, + int view_col, + int row, + int col_width, + ETableTooltip *tooltip); + +static gint e_cell_popup_do_popup (ECellPopupView *ecp_view, + GdkEvent *event); + +static ECellClass *parent_class; + + +E_MAKE_TYPE (e_cell_popup, "ECellPopup", ECellPopup, e_cell_popup_class_init, + e_cell_popup_init, e_cell_get_type()); + + +static void +e_cell_popup_class_init (GtkObjectClass *object_class) +{ + ECellClass *ecc = (ECellClass *) object_class; + + object_class->destroy = e_cell_popup_destroy; + + ecc->new_view = ecp_new_view; + ecc->kill_view = ecp_kill_view; + ecc->realize = ecp_realize; + ecc->unrealize = ecp_unrealize; + ecc->draw = ecp_draw; + ecc->event = ecp_event; + ecc->height = ecp_height; + ecc->enter_edit = ecp_enter_edit; + ecc->leave_edit = ecp_leave_edit; + ecc->print = ecp_print; + ecc->print_height = ecp_print_height; + ecc->max_width = ecp_max_width; + ecc->show_tooltip = ecp_show_tooltip; + + parent_class = gtk_type_class (e_cell_get_type ()); +} + + +static void +e_cell_popup_init (ECellPopup *ecp) +{ + ecp->popup_shown = FALSE; +} + + +/** + * e_cell_popup_new: + * + * Creates a new ECellPopup renderer. + * + * Returns: an ECellPopup object. + */ +ECell * +e_cell_popup_new (void) +{ + ECellPopup *ecp = gtk_type_new (e_cell_popup_get_type ()); + + return (ECell*) ecp; +} + + +/* + * GtkObject::destroy method + */ +static void +e_cell_popup_destroy (GtkObject *object) +{ + ECellPopup *ecp = E_CELL_POPUP (object); + + gtk_object_unref (GTK_OBJECT (ecp->child)); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + + + +/* + * ECell::new_view method + */ +static ECellView * +ecp_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view) +{ + ECellPopup *ecp = E_CELL_POPUP (ecell); + ECellPopupView *ecp_view; + + /* We must have a child ECell before we create any views. */ + g_return_val_if_fail (ecp->child != NULL, NULL); + + ecp_view = g_new0 (ECellPopupView, 1); + + ecp_view->cell_view.ecell = ecell; + ecp_view->cell_view.e_table_model = table_model; + ecp_view->cell_view.e_table_item_view = e_table_item_view; + + ecp_view->child_view = e_cell_new_view (ecp->child, table_model, + e_table_item_view); + + return (ECellView*) ecp_view; +} + + +/* + * ECell::kill_view method + */ +static void +ecp_kill_view (ECellView *ecv) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + if (ecp_view->child_view) + e_cell_kill_view (ecp_view->child_view); + g_free (ecp_view); +} + + +/* + * ECell::realize method + */ +static void +ecp_realize (ECellView *ecv) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + e_cell_realize (ecp_view->child_view); + + if (parent_class->realize) + (* parent_class->realize) (ecv); +} + + +/* + * ECell::unrealize method + */ +static void +ecp_unrealize (ECellView *ecv) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + e_cell_realize (ecp_view->child_view); + + if (parent_class->unrealize) + (* parent_class->unrealize) (ecv); +} + + +/* + * ECell::draw method + */ +static void +ecp_draw (ECellView *ecv, GdkDrawable *drawable, + int model_col, int view_col, int row, ECellFlags flags, + int x1, int y1, int x2, int y2) +{ + ECellPopup *ecp = E_CELL_POPUP (ecv->ecell); + ETableItem *eti = E_TABLE_ITEM (ecv->e_table_item_view); + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (ecv->e_table_item_view)->canvas); + GtkShadowType shadow; + GdkRectangle rect; + gboolean show_popup_arrow = FALSE; + + /* Display the popup arrow if we are editing this cell, or the popup + is shown for this cell. */ + if (eti->editing_col == view_col && eti->editing_row == row) { + show_popup_arrow = TRUE; + ecp->popup_arrow_shown = TRUE; + + } else if (ecp->popup_shown && ecp->popup_view_col == view_col + && ecp->popup_row == row) { + show_popup_arrow = TRUE; + } + + if (eti->editing_col == -1) + ecp->popup_arrow_shown = FALSE; + +#if 0 + g_print ("In ecp_draw row:%i col: %i %i,%i %i,%i Show Arrow:%i\n", + row, view_col, x1, y1, x2, y2, show_popup_arrow); +#endif + + if (show_popup_arrow) { + e_cell_draw (ecp_view->child_view, drawable, model_col, + view_col, row, flags, + x1, y1, x2 - E_CELL_POPUP_ARROW_WIDTH, y2); + + rect.x = x2 - E_CELL_POPUP_ARROW_WIDTH; + rect.y = y1 + 1; + rect.width = E_CELL_POPUP_ARROW_WIDTH; + rect.height = y2 - y1 - 2; + + if (ecp->popup_shown) + shadow = GTK_SHADOW_IN; + else + shadow = GTK_SHADOW_OUT; + + gtk_paint_box (canvas->style, drawable, + GTK_STATE_NORMAL, shadow, + &rect, canvas, "ecellpopup", + rect.x, rect.y, rect.width, rect.height); + gtk_paint_arrow (canvas->style, drawable, + GTK_STATE_NORMAL, shadow, + &rect, canvas, NULL, + GTK_ARROW_DOWN, TRUE, + rect.x + E_CELL_POPUP_ARROW_XPAD, + rect.y + E_CELL_POPUP_ARROW_YPAD, + rect.width - E_CELL_POPUP_ARROW_XPAD * 2, + rect.height - E_CELL_POPUP_ARROW_YPAD * 2); + } else { + e_cell_draw (ecp_view->child_view, drawable, model_col, + view_col, row, flags, x1, y1, x2, y2); + } +} + + +/* + * ECell::event method + */ +static gint +ecp_event (ECellView *ecv, GdkEvent *event, int model_col, int view_col, + int row, ECellFlags flags, ECellActions *actions) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + ECellPopup *ecp = E_CELL_POPUP (ecp_view->cell_view.ecell); + ETableItem *eti = E_TABLE_ITEM (ecv->e_table_item_view); + int width; + + switch (event->type) { + case GDK_BUTTON_PRESS: + if (eti->editing_col == view_col && eti->editing_row == row + && ecp->popup_arrow_shown) { + width = e_table_header_col_diff (eti->header, view_col, + view_col + 1); + + g_print ("Event in item popup width: %i button: %g,%g\n", + width, event->button.x, event->button.y); + + /* FIXME: The event coords seem to be relative to the + text within the cell, so we have to add 4. */ + if (event->button.x + 4 >= width - E_CELL_POPUP_ARROW_WIDTH) { + return e_cell_popup_do_popup (ecp_view, event); + } + } + break; + case GDK_BUTTON_RELEASE: + break; + case GDK_KEY_PRESS: + if (event->key.state & GDK_MOD1_MASK + && event->key.keyval == GDK_Down) { + g_print ("## Enter key pressed\n"); + return e_cell_popup_do_popup (ecp_view, event); + } + g_print ("Key Press Event ECellPopup\n"); + break; + default: + break; + } + + return e_cell_event (ecp_view->child_view, event, model_col, view_col, + row, flags, actions); +} + + +/* + * ECell::height method + */ +static int +ecp_height (ECellView *ecv, int model_col, int view_col, int row) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + return e_cell_height (ecp_view->child_view, model_col, view_col, row); +} + + +/* + * ECellView::enter_edit method + */ +static void * +ecp_enter_edit (ECellView *ecv, int model_col, int view_col, int row) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + ECellPopup *ecp = E_CELL_POPUP (ecp_view->cell_view.ecell); + + g_print ("In ecp_enter_edit model_col: %i view_col: %i row: %i\n", + model_col, view_col, row); + + if (ecp->popup_view_col != view_col || ecp->popup_row != row) + ecp->popup_arrow_shown = FALSE; + + ecp->popup_view_col = view_col; + ecp->popup_row = row; + + return e_cell_enter_edit (ecp_view->child_view, model_col, view_col, row); +} + + +/* + * ECellView::leave_edit method + */ +static void +ecp_leave_edit (ECellView *ecv, int model_col, int view_col, int row, + void *edit_context) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + g_print ("In ecp_leave_edit model_col: %i view_col: %i row: %i\n", + model_col, view_col, row); + + e_cell_leave_edit (ecp_view->child_view, model_col, view_col, row, + edit_context); +} + + +static void +ecp_print (ECellView *ecv, GnomePrintContext *context, + int model_col, int view_col, int row, double width, double height) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + e_cell_print (ecp_view->child_view, context, model_col, view_col, row, + width, height); +} + + +static gdouble +ecp_print_height (ECellView *ecv, GnomePrintContext *context, + int model_col, int view_col, int row, + double width) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + return e_cell_print_height (ecp_view->child_view, context, model_col, + view_col, row, width); +} + + +static int +ecp_max_width (ECellView *ecv, + int model_col, + int view_col) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + return e_cell_max_width (ecp_view->child_view, model_col, view_col); +} + + +static void +ecp_show_tooltip (ECellView *ecv, + int model_col, + int view_col, + int row, + int col_width, + ETableTooltip *tooltip) +{ + ECellPopupView *ecp_view = (ECellPopupView *) ecv; + + e_cell_show_tooltip (ecp_view->child_view, model_col, view_col, row, + col_width, tooltip); +} + + + +ECell* +e_cell_popup_get_child (ECellPopup *ecp) +{ + g_return_val_if_fail (E_IS_CELL_POPUP (ecp), NULL); + + return ecp->child; +} + + +void +e_cell_popup_set_child (ECellPopup *ecp, + ECell *child) +{ + g_return_if_fail (E_IS_CELL_POPUP (ecp)); + + if (ecp->child) + gtk_object_unref (GTK_OBJECT (ecp->child)); + + ecp->child = child; + gtk_object_ref (GTK_OBJECT (child)); +} + + +static gint +e_cell_popup_do_popup (ECellPopupView *ecp_view, + GdkEvent *event) +{ + ECellPopup *ecp = E_CELL_POPUP (ecp_view->cell_view.ecell); + gint (*popup_func) (ECellPopup *ecp, GdkEvent *event); + + ecp->popup_cell_view = ecp_view; + + popup_func = E_CELL_POPUP_CLASS (GTK_OBJECT (ecp)->klass)->popup; + + return popup_func ? popup_func (ecp, event) : FALSE; +} -- cgit v1.2.3