From 405b846e5b5ab98ecb0d1a3545df3972df044730 Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Fri, 15 Aug 2003 20:23:12 +0000 Subject: extracted from ect_draw (draw_expander): new gtktreeview-like expander 2003-08-15 Mike Kestner * e-cell-tree.c (draw_retro_expander): extracted from ect_draw (draw_expander): new gtktreeview-like expander drawing (ect_draw): draw lines and expanders based on retro_look style prop (adjust_event_position): extracted method from ect_event (event_in_expander): new checks for motion/clicks in expander (ect_event): handle prelight for new expanders * e-table-item.c (eti_init): init new motion col/row (eti_event): synthesize leave_notify events for cells and propogate existing motion events to the cells. * e-tree.c (e_tree_class_init): add retro_look and expander_size style props. svn path=/trunk/; revision=22251 --- widgets/table/e-cell-tree.c | 228 ++++++++++++++++++++++++++++--------------- widgets/table/e-table-item.c | 46 +++++++-- widgets/table/e-table-item.h | 2 + widgets/table/e-tree.c | 17 ++++ 4 files changed, 207 insertions(+), 86 deletions(-) diff --git a/widgets/table/e-cell-tree.c b/widgets/table/e-cell-tree.c index 03a454e2c5..18c8146369 100644 --- a/widgets/table/e-cell-tree.c +++ b/widgets/table/e-cell-tree.c @@ -43,6 +43,7 @@ #include #include "e-tree-table-adapter.h" +#include "e-tree.h" #include "e-tree-model.h" #include "gal/util/e-util.h" #include "e-table-item.h" @@ -59,6 +60,8 @@ typedef struct { GdkGC *gc; GnomeCanvas *canvas; + gboolean retro_look; + gboolean prelit; } ECellTreeView; @@ -186,6 +189,40 @@ ect_unrealize (ECellView *ecv) (* parent_class->unrealize) (ecv); } +static void +draw_retro_expander (ECellTreeView *ectv, GdkDrawable *drawable, gboolean expanded, GdkRectangle *rect) +{ + GdkPixbuf *image; + int image_width, image_height; + ECellTree *ect = E_CELL_TREE(ectv->cell_view.ecell); + + image = expanded ? ect->open_pixbuf : ect->closed_pixbuf; + + image_width = gdk_pixbuf_get_width(image); + image_height = gdk_pixbuf_get_height(image); + + gdk_pixbuf_render_to_drawable_alpha (image, + drawable, + rect->x, rect->y, + rect->width - image_width / 2, + rect->height - image_height / 2, + image_width, image_height, + GDK_PIXBUF_ALPHA_BILEVEL, + 128, + GDK_RGB_DITHER_NORMAL, + image_width, 0); +} + +static void +draw_expander (ECellTreeView *ectv, GdkDrawable *drawable, gboolean expanded, GtkStateType state, GdkRectangle *rect) +{ + GtkWidget *tree = GTK_WIDGET (ectv->canvas)->parent; + gint exp_size; + gtk_widget_style_get (tree, "expander_size", &exp_size, NULL); + + gtk_paint_expander (tree->style, drawable, state, rect, tree, "treeview", rect->x + rect->width - exp_size / 2, rect->y + rect->height / 2, expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED); +} + /* * ECell::draw method */ @@ -213,6 +250,12 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, GdkPixbuf *node_image; int node_image_width = 0, node_image_height = 0; ETreePath parent_node; + ETree *tree = E_TREE (canvas->parent); + + gtk_widget_style_get (GTK_WIDGET (tree), + "retro_look", &tree_view->retro_look, + NULL); + tree_view->prelit = FALSE; node = e_cell_tree_get_node (ecell_view->e_table_model, row); @@ -247,7 +290,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, gdk_gc_set_foreground (tree_view->gc, foreground); /* draw our lines */ - if (E_CELL_TREE(tree_view->cell_view.ecell)->draw_lines) { + if (tree_view->retro_look && E_CELL_TREE(tree_view->cell_view.ecell)->draw_lines) { int depth; @@ -291,26 +334,19 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, /* now draw our icon if we're expandable */ if (e_tree_model_node_is_expandable (tree_model, node)) { - GdkPixbuf *image; - int image_width, image_height; - - image = (e_tree_table_adapter_node_is_expanded (tree_table_adapter, node) - ? E_CELL_TREE(tree_view->cell_view.ecell)->open_pixbuf - : E_CELL_TREE(tree_view->cell_view.ecell)->closed_pixbuf); - - image_width = gdk_pixbuf_get_width(image); - image_height = gdk_pixbuf_get_height(image); - - gdk_pixbuf_render_to_drawable_alpha (image, - drawable, - 0, 0, - x1 + subcell_offset - INDENT_AMOUNT / 2 - image_width / 2, - y1 + (y2 - y1) / 2 - image_height / 2, - image_width, image_height, - GDK_PIXBUF_ALPHA_BILEVEL, - 128, - GDK_RGB_DITHER_NORMAL, - image_width, 0); + gboolean expanded = e_tree_table_adapter_node_is_expanded (tree_table_adapter, node); + GdkRectangle r; + if (tree_view->retro_look) { + r.x = 0; + r.y = 0; + r.width = x1 + subcell_offset - INDENT_AMOUNT / 2, + r.height = y1 + (y2 - y1) / 2, + draw_retro_expander (tree_view, drawable, expanded, &r); + } else { + r = rect; + r.width -= node_image_width + 2; + draw_expander (tree_view, drawable, expanded, GTK_STATE_NORMAL, &r); + } } if (node_image) { @@ -340,6 +376,51 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, } } +static void +adjust_event_position (GdkEvent *event, gint offset) +{ + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + event->button.x += offset; + break; + case GDK_MOTION_NOTIFY: + event->motion.x += offset; + break; + default: + break; + } +} + +static gboolean +event_in_expander (GdkEvent *event, gint offset, gint height) +{ + switch (event->type) { + case GDK_BUTTON_PRESS: + return (event->button.x > (offset - INDENT_AMOUNT) && event->button.x < offset); + case GDK_MOTION_NOTIFY: + return (event->motion.x > (offset - INDENT_AMOUNT) && event->motion.x < offset && + event->motion.y > 2 && event->motion.y < (height - 2)); + default: + break; + } + + return FALSE; +} + +/* + * ECell::height method + */ +static int +ect_height (ECellView *ecell_view, int model_col, int view_col, int row) +{ + ECellTreeView *tree_view = (ECellTreeView *) ecell_view; + + return (((e_cell_height (tree_view->subcell_view, model_col, view_col, row)) + 1) / 2) * 2; +} + /* * ECell::event method */ @@ -348,78 +429,72 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, { ECellTreeView *tree_view = (ECellTreeView *) ecell_view; ETreeModel *tree_model = e_cell_tree_get_tree_model (ecell_view->e_table_model, row); - ETreeTableAdapter *tree_table_adapter = e_cell_tree_get_tree_table_adapter(ecell_view->e_table_model, row); + ETreeTableAdapter *etta = e_cell_tree_get_tree_table_adapter(ecell_view->e_table_model, row); ETreePath node = e_cell_tree_get_node (ecell_view->e_table_model, row); int offset = offset_of_node (ecell_view->e_table_model, row); + gint result; switch (event->type) { - case GDK_BUTTON_PRESS: { - /* if the event happened in our area of control (and - we care about it), handle it. */ + case GDK_BUTTON_PRESS: - /* only activate the tree control if the click/release happens in the icon's area. */ - if (event->button.x > (offset - INDENT_AMOUNT) && event->button.x < offset) { + if (event_in_expander (event, offset, 0)) { if (e_tree_model_node_is_expandable (tree_model, node)) { - e_tree_table_adapter_node_set_expanded (tree_table_adapter, - node, - !e_tree_table_adapter_node_is_expanded(tree_table_adapter, node)); + gboolean expanded = !e_tree_table_adapter_node_is_expanded(etta, node); + e_tree_table_adapter_node_set_expanded (etta, node, expanded); return TRUE; } } else if (event->button.x < (offset - INDENT_AMOUNT)) return FALSE; - } - default: { - gint return_value; - - /* modify the event and pass it off to our subcell_view */ - switch (event->type) { - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - event->button.x -= offset; - break; - case GDK_MOTION_NOTIFY: - event->motion.x -= offset; - break; - default: - /* nada */ - break; - } + break; + + case GDK_MOTION_NOTIFY: + + if (!tree_view->retro_look && e_tree_model_node_is_expandable (tree_model, node)) { + gint height = ect_height (ecell_view, model_col, view_col, row); + GdkRectangle area; + gboolean in_expander = event_in_expander (event, offset, height); + + if (tree_view->prelit ^ in_expander) { + gint tmp_row = row; + e_table_item_get_cell_geometry (tree_view->cell_view.e_table_item_view, + &tmp_row, &view_col, &area.x, &area.y, NULL, &area.height); + area.width = offset - 2; + draw_expander (tree_view, GTK_LAYOUT (tree_view->canvas)->bin_window, + e_tree_table_adapter_node_is_expanded (etta, node), + in_expander ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL, + &area); + tree_view->prelit = in_expander; + return TRUE; + } - return_value = e_cell_event(tree_view->subcell_view, event, model_col, view_col, row, flags, actions); - - /* modify the event and pass it off to our subcell_view */ - switch (event->type) { - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - case GDK_2BUTTON_PRESS: - case GDK_3BUTTON_PRESS: - event->button.x += offset; - break; - case GDK_MOTION_NOTIFY: - event->motion.x += offset; - break; - default: - /* nada */ - break; } + break; + + case GDK_LEAVE_NOTIFY: + + if (tree_view->prelit) { + gint tmp_row = row; + GdkRectangle area; + e_table_item_get_cell_geometry (tree_view->cell_view.e_table_item_view, + &tmp_row, &view_col, &area.x, &area.y, NULL, &area.height); + area.width = offset - 2; + draw_expander (tree_view, GTK_LAYOUT (tree_view->canvas)->bin_window, + e_tree_table_adapter_node_is_expanded (etta, node), + GTK_STATE_NORMAL, &area); + tree_view->prelit = FALSE; + } + return TRUE; - return return_value; - } + default: + break; } -} -/* - * ECell::height method - */ -static int -ect_height (ECellView *ecell_view, int model_col, int view_col, int row) -{ - ECellTreeView *tree_view = (ECellTreeView *) ecell_view; + adjust_event_position (event, -offset); + result = e_cell_event(tree_view->subcell_view, event, model_col, view_col, row, flags, actions); + adjust_event_position (event, offset); - return (((e_cell_height (tree_view->subcell_view, model_col, view_col, row)) + 1) / 2) * 2; + return result; } /* @@ -775,3 +850,4 @@ e_cell_tree_new (GdkPixbuf *open_pixbuf, return (ECell *) ect; } + diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index b125c8495d..ea2dc4297f 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -1558,6 +1558,8 @@ eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); + eti->motion_row = -1; + eti->motion_col = -1; eti->editing_col = -1; eti->editing_row = -1; eti->height = 0; @@ -2512,7 +2514,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) break; } case GDK_MOTION_NOTIFY: { - int col, row; + int col, row, flags; double x1, y1; gint cursor_col, cursor_row; @@ -2536,6 +2538,19 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (!find_cell (eti, e->motion.x, e->motion.y, &col, &row, &x1, &y1)) return TRUE; + if (eti->motion_row != -1 && eti->motion_col != -1 && + (row != eti->motion_row || col != eti->motion_col)) { + GdkEvent *cross = gdk_event_new (GDK_LEAVE_NOTIFY); + cross->crossing.time = e->motion.time; + return_val = eti_e_cell_event (eti, eti->cell_views [eti->motion_col], + cross, cross->crossing.time, + view_to_model_col(eti, eti->motion_col), + eti->motion_col, eti->motion_row, 0); + } + + eti->motion_row = row; + eti->motion_col = col; + g_object_get(eti->selection, "cursor_row", &cursor_row, "cursor_col", &cursor_col, @@ -2555,18 +2570,21 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } #endif + flags = 0; if (cursor_row == view_to_model_row(eti, row) && cursor_col == view_to_model_col(eti, col)){ - ecell_view = eti->cell_views [col]; + flags = E_CELL_EDITING | E_CELL_CURSOR; + } - /* - * Adjust the event positions - */ - e->motion.x = x1; - e->motion.y = y1; + ecell_view = eti->cell_views [col]; - return_val = eti_e_cell_event (eti, ecell_view, e, e->motion.time, - view_to_model_col(eti, col), col, row, E_CELL_EDITING | E_CELL_CURSOR); - } + /* + * Adjust the event positions + */ + e->motion.x = x1; + e->motion.y = y1; + + return_val = eti_e_cell_event (eti, ecell_view, e, e->motion.time, + view_to_model_col(eti, col), col, row, flags); break; } @@ -2782,6 +2800,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti->tooltip->timer) gtk_timeout_remove (eti->tooltip->timer); eti->tooltip->timer = 0; + if (eti->motion_row != -1 && eti->motion_col != -1) + return_val = eti_e_cell_event (eti, eti->cell_views [eti->motion_col], + e, e->crossing.time, + view_to_model_col(eti, eti->motion_col), + eti->motion_col, eti->motion_row, 0); + eti->motion_row = -1; + eti->motion_col = -1; + break; case GDK_FOCUS_CHANGE: diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h index ef22cd9ab7..4776bc8ca7 100644 --- a/widgets/table/e-table-item.h +++ b/widgets/table/e-table-item.h @@ -150,6 +150,8 @@ typedef struct { gint row_guess; ECursorMode cursor_mode; + int motion_col, motion_row; + /* * During editing */ diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c index 938fd45136..84b5fb2a95 100644 --- a/widgets/table/e-tree.c +++ b/widgets/table/e-tree.c @@ -3292,6 +3292,23 @@ e_tree_class_init (ETreeClass *class) _( "Always search" ), FALSE, G_PARAM_READWRITE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("retro_look", + _("Retro Look"), + _("Draw lines and +/- expanders."), + FALSE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("expander_size", + _("Expander Size"), + _("Size of the expander arrow"), + 0, + G_MAXINT, + 10, + G_PARAM_READABLE)); + } E_MAKE_TYPE(e_tree, "ETree", ETree, e_tree_class_init, e_tree_init, PARENT_TYPE) -- cgit