diff options
-rw-r--r-- | widgets/e-table/ChangeLog | 35 | ||||
-rw-r--r-- | widgets/e-table/Makefile.am | 3 | ||||
-rw-r--r-- | widgets/e-table/e-cell-text.c | 184 | ||||
-rw-r--r-- | widgets/e-table/e-cell-tree.c | 20 | ||||
-rw-r--r-- | widgets/e-table/e-cell.c | 15 | ||||
-rw-r--r-- | widgets/e-table/e-cell.h | 3 | ||||
-rw-r--r-- | widgets/e-table/e-table-header-item.c | 136 | ||||
-rw-r--r-- | widgets/e-table/e-table-item.c | 64 | ||||
-rw-r--r-- | widgets/e-table/e-table-item.h | 6 | ||||
-rw-r--r-- | widgets/e-table/e-table-tooltip.h | 17 | ||||
-rw-r--r-- | widgets/table/e-cell-text.c | 184 | ||||
-rw-r--r-- | widgets/table/e-cell-tree.c | 20 | ||||
-rw-r--r-- | widgets/table/e-cell.c | 15 | ||||
-rw-r--r-- | widgets/table/e-cell.h | 3 | ||||
-rw-r--r-- | widgets/table/e-table-header-item.c | 136 | ||||
-rw-r--r-- | widgets/table/e-table-item.c | 64 | ||||
-rw-r--r-- | widgets/table/e-table-item.h | 6 | ||||
-rw-r--r-- | widgets/table/e-table-tooltip.h | 17 |
18 files changed, 841 insertions, 87 deletions
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index deb498d9d6..580ad91e79 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,8 +1,36 @@ 2000-09-15 Iain Holmes <iain@helixcode.com> - * e-table-header-item.c (draw_button): Replace the NULL in the - gtk_paint_box call with a pointer to the canvas. Fixes a crash - reported and solved by Radek + * e-cell-tree.c (ect_show_tooltip): If the cursor is inside + the subcell, call the show_tooltip on it. + + * e-table-header-item.c (draw_button): Draw the arrow first, + then take it's size into account when calculating how to draw + the text. Use ellipsis if the text it too long. + +2000-09-15 Iain Holmes <iain@helixcode.com> + + * e-table-header-item.c (draw_button): Fix a crash by passing + the canvas widget to gtk_paint_box. Reported by Radek. + +2000-09-14 Iain Holmes <iain@helixcode.com> + + * e-table-header-item.c (set_cursor): The column isn't resizable + if it is the last, or if all other columns after it are not + resizable. + + * e-cell-text.c (ect_max_width): Correctly calculate the width + of the line of text. Unbuild the current cell and unref the lines + as well. + (build_current_cell): Initialize cell->style to 0; + +2000-09-14 Iain Holmes <iain@helixcode.com> + + * e-table-item.c: Start timers for the tooltip to appear, on motion + events. + + * e-cell.[ch]: Add a new show_tooltip method. + + * e-cell-text.c (ect_show_tooltip): Show the tooltip. 2000-09-14 Peter Williams <peter@beta.newton.cx> @@ -67,7 +95,6 @@ * e-tree-simple.c: Fixed the ETableModel callbacks. ->>>>>>> 1.273 2000-09-08 Christopher James Lahey <clahey@helixcode.com> * e-tree-example-1.c: Added base ETableModel functions. diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index 31ad6397fd..4b64af40d2 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -92,7 +92,8 @@ libetable_a_SOURCES = \ e-tree-model.c \ e-tree-model.h \ e-tree-simple.c \ - e-tree-simple.h + e-tree-simple.h \ + e-table-tooltip.h noinst_PROGRAMS = \ table-test table-example-1 table-example-2 table-size-test tree-example-1 tree-example-2 diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index ac8f3df7b2..411ffe03d5 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -39,6 +39,7 @@ #include "e-table-item.h" #include "e-text-event-processor.h" #include "e-text-event-processor-emacs-like.h" +#include "e-table-tooltip.h" #include <gdk/gdkx.h> /* for BlackPixel */ #include <ctype.h> @@ -1284,15 +1285,194 @@ ect_max_width (ECellView *ecell_view, for (row = 0; row < number_of_rows; row++) { CurrentCell cell; + struct line *line; + int width; + build_current_cell (&cell, text_view, model_col, view_col, row); split_into_lines (&cell); calc_line_widths (&cell); - max_width = MAX (max_width, cell.breaks->max_width); + + line = (struct line *)cell.breaks->lines; + width = e_font_utf8_text_width (font, cell.style, + line->text, line->length); + max_width = MAX (max_width, width); + unref_lines (&cell); + unbuild_current_cell (&cell); } return max_width; } +static gint +tooltip_event (GtkWidget *window, + GdkEvent *event, + ETableTooltip *tooltip) +{ + gint ret_val = FALSE; + + switch (event->type) { + case GDK_LEAVE_NOTIFY: + if (tooltip->window) { + gtk_widget_destroy (tooltip->window); + tooltip->window = NULL; + } + break; + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + if (event->type == GDK_BUTTON_RELEASE) { + if (tooltip->window) { + gtk_widget_destroy (tooltip->window); + tooltip->window = NULL; + } + } + + gtk_signal_emit_by_name (GTK_OBJECT (tooltip->eti), "event", + event, &ret_val); + break; + default: + break; + } + + return ret_val; +} + +static void +ect_show_tooltip (ECellView *ecell_view, + int model_col, + int view_col, + int row, + ETableTooltip *tooltip) +{ + ECellTextView *text_view = (ECellTextView *) ecell_view; + CurrentCell cell; + struct line *lines; + GtkWidget *canvas; + int i; + gdouble max_width; + gboolean cut_off; + double i2c[6]; + ArtPoint origin = {0, 0}; + ArtPoint pixel_origin; + int canvas_x, canvas_y; + GnomeCanvasItem *tooltip_text; + double tooltip_width; + double tooltip_height; + double tooltip_x; + double tooltip_y; + GnomeCanvasItem *rect; + double text_height; + + tooltip->timer = 0; + + build_current_cell (&cell, text_view, model_col, view_col, row); + split_into_lines (&cell); + calc_line_widths (&cell); + + cut_off = FALSE; + for (lines = cell.breaks->lines, i = 0; i < cell.breaks->num_lines; + lines++, i++) { + if (lines->length > lines->ellipsis_length) { + cut_off = TRUE; + break; + } + } + + if (!cut_off) { + tooltip->timer = 0; + return; + } + + gnome_canvas_item_i2c_affine (GNOME_CANVAS_ITEM (tooltip->eti), i2c); + art_affine_point (&pixel_origin, &origin, i2c); + + g_print ("%d,%d\n", pixel_origin.x, pixel_origin.y); + gdk_window_get_origin (GTK_WIDGET (text_view->canvas)->window, + &canvas_x, &canvas_y); + pixel_origin.x += canvas_x; + pixel_origin.y += canvas_y; + pixel_origin.x -= (int) gtk_layout_get_hadjustment (GTK_LAYOUT (text_view->canvas))->value; + pixel_origin.y -= (int) gtk_layout_get_vadjustment (GTK_LAYOUT (text_view->canvas))->value; + + tooltip->window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_container_set_border_width (GTK_CONTAINER (tooltip->window), 1); + + canvas = e_canvas_new (); + gtk_container_add (GTK_CONTAINER (tooltip->window), canvas); + + max_width = 0.0; + for (lines = cell.breaks->lines, i = 0; i < cell.breaks->num_lines; + lines++, i++) { + gdouble line_width; + + line_width = e_font_utf8_text_width (text_view->font, + E_FONT_PLAIN, lines->text, + lines->length); + max_width = MAX (max_width, line_width); + } + + text_height = e_font_height (text_view->font) * cell.breaks->num_lines + 4; + rect = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), + gnome_canvas_rect_get_type (), + "x1", (double) 0.0, + "y1", (double) 0.0, + "x2", (double) max_width + 4, + "y2", (double) text_height, + "fill_color", "yellow", + NULL); + + tooltip_text = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), + e_text_get_type (), + "anchor", GTK_ANCHOR_NW, +/* "font_gdk", text_view->font, */ + "text", cell.text, + "editable", FALSE, + "clip_width", max_width, + "clip_height", (double) text_height, + "clip", TRUE, + "line_wrap", FALSE, + "justification", E_CELL_TEXT (text_view->cell_view.ecell)->justify, + NULL); + + tooltip_width = max_width; + tooltip_height = text_height; + tooltip_y = tooltip->y; + + switch (E_CELL_TEXT (text_view->cell_view.ecell)->justify) { + case GTK_JUSTIFY_CENTER: + tooltip_x = - tooltip_width / 2; + break; + case GTK_JUSTIFY_RIGHT: + tooltip_x = tooltip_width / 2; + break; + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + tooltip_x = tooltip->x; + break; + } + + gnome_canvas_item_set (rect, + "x2", (double) tooltip_width, + "y2", (double) tooltip->row_height, + NULL); + gtk_widget_set_usize (tooltip->window, tooltip_width, + tooltip->row_height); + gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0.0, 0.0, + (double) tooltip_width, + (double) tooltip_height); + gtk_widget_show (canvas); + gtk_widget_realize (tooltip->window); + gtk_signal_connect (GTK_OBJECT (tooltip->window), "event", + GTK_SIGNAL_FUNC (tooltip_event), tooltip); + + gtk_widget_popup (tooltip->window, pixel_origin.x + tooltip->x, + pixel_origin.y + tooltip->y); + + unref_lines (&cell); + unbuild_current_cell (&cell); + + return; +} + /* * GtkObject::destroy method */ @@ -1384,6 +1564,7 @@ e_cell_text_class_init (GtkObjectClass *object_class) ecc->print = ect_print; ecc->print_height = ect_print_height; ecc->max_width = ect_max_width; + ecc->show_tooltip = ect_show_tooltip; object_class->get_arg = ect_get_arg; object_class->set_arg = ect_set_arg; @@ -2331,6 +2512,7 @@ build_current_cell (CurrentCell *cell, ECellTextView *text_view, int model_col, cell->width = e_table_header_get_column ( ((ETableItem *)ecell_view->e_table_item_view)->header, view_col)->width - 8; + cell->style = 0; } static void diff --git a/widgets/e-table/e-cell-tree.c b/widgets/e-table/e-cell-tree.c index 48ae9f4af1..5a055fce0e 100644 --- a/widgets/e-table/e-cell-tree.c +++ b/widgets/e-table/e-cell-tree.c @@ -411,7 +411,24 @@ ect_max_width (ECellView *ecell_view, int model_col, int view_col) return max_width; } - +/* + * ECellView::show_tooltip method + */ +static void +ect_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, + ETableTooltip *tooltip) +{ + ECellTreeView *tree_view = (ECellTreeView *) ecell_view; + ETreeModel *tree_model = e_cell_tree_get_tree_model (ecell_view->e_table_model, row); + ETreePath *node = e_cell_tree_get_node (tree_model, row); + int offset = offset_of_node (tree_model, node); + + /* if the tooltip happened in the subcell, then handle it */ + + if (tooltip->cx > offset) { + e_cell_show_tooltip (tree_view->subcell_view, model_col, view_col, row, tooltip); + } +} /* * ECellView::enter_edit method @@ -572,6 +589,7 @@ e_cell_tree_class_init (GtkObjectClass *object_class) ecc->print = ect_print; ecc->print_height = ect_print_height; ecc->max_width = ect_max_width; + ecc->show_tooltip = ect_show_tooltip; parent_class = gtk_type_class (PARENT_TYPE); } diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c index ddab43dbd6..f5d2abf733 100644 --- a/widgets/e-table/e-cell.c +++ b/widgets/e-table/e-cell.c @@ -90,6 +90,12 @@ ec_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void } static void +ec_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, ETableTooltip *tooltip) +{ + /* Do nothing */ +} + +static void e_cell_class_init (GtkObjectClass *object_class) { ECellClass *ecc = (ECellClass *) object_class; @@ -107,6 +113,8 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->leave_edit = ec_leave_edit; ecc->print = NULL; ecc->print_height = NULL; + ecc->max_width = NULL; + ecc->show_tooltip = ec_show_tooltip; } static void @@ -206,3 +214,10 @@ e_cell_max_width (ECellView *ecell_view, int model_col, int view_col) (ecell_view, model_col, view_col); } +void +e_cell_show_tooltip (ECellView *ecell_view, int model_col, int view_col, + int row, ETableTooltip *tooltip) +{ + return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->show_tooltip + (ecell_view, model_col, view_col, row, tooltip); +} diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h index d097a7d6bd..028cdad077 100644 --- a/widgets/e-table/e-cell.h +++ b/widgets/e-table/e-cell.h @@ -5,6 +5,7 @@ #include <gdk/gdktypes.h> #include <libgnomeprint/gnome-print.h> #include "e-table-model.h" +#include "e-table-tooltip.h" #define E_CELL_TYPE (e_cell_get_type ()) #define E_CELL(o) (GTK_CHECK_CAST ((o), E_CELL_TYPE, ECell)) @@ -70,6 +71,7 @@ typedef struct { gdouble (*print_height) (ECellView *ecell_view, GnomePrintContext *context, int model_col, int view_col, int row, gdouble width); int (*max_width) (ECellView *ecell_view, int model_col, int view_col); + void (*show_tooltip) (ECellView *ecell_view, int model_col, int view_col, int row, ETableTooltip *tooltip); } ECellClass; GtkType e_cell_get_type (void); @@ -90,6 +92,7 @@ void e_cell_print (ECellView *ecell_view, GnomePrintContext *context, gdouble e_cell_print_height (ECellView *ecell_view, GnomePrintContext *context, int model_col, int view_col, int row, gdouble width); int e_cell_max_width (ECellView *ecell_view, int model_col, int view_col); +void e_cell_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, ETableTooltip *tooltip); void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index ec25e0d0f0..903d6b954f 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -740,40 +740,6 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, gdk_gc_set_clip_rectangle (ethi->gc, &clip); - if (col->is_pixbuf){ - xtra = (clip.width - gdk_pixbuf_get_width (col->pixbuf))/2; - - xtra += HEADER_PADDING / 2; - - gdk_pixbuf_render_to_drawable_alpha (col->pixbuf, - drawable, - 0, 0, - x + xtra, y + (clip.height - gdk_pixbuf_get_height (col->pixbuf)) / 2, - gdk_pixbuf_get_width (col->pixbuf), gdk_pixbuf_get_height(col->pixbuf), - GDK_PIXBUF_ALPHA_FULL, 128, - GDK_RGB_DITHER_NORMAL, - 0, 0); - } else { - /* Center the thing */ - xtra = (clip.width - gdk_string_measure (ethi->font, col->text))/2; - - /* Skip over border */ - if (xtra < 0) - xtra = 0; - - xtra += HEADER_PADDING / 2; - - gdk_draw_text ( - drawable, ethi->font, - ethi->gc, x + xtra, y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, - col->text, strlen (col->text)); - } - - if (col->pixbuf){ - if ((gdk_pixbuf_get_width (col->pixbuf) + MIN_ARROW_SIZE + 4) > width) - return; - } - switch (arrow){ case E_TABLE_COL_ARROW_NONE: break; @@ -794,8 +760,81 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, y + (ethi->height - MIN_ARROW_SIZE) / 2, MIN_ARROW_SIZE, MIN_ARROW_SIZE); + + clip.width -= (MIN_ARROW_SIZE + 2 + HEADER_PADDING); break; } + + if (col->is_pixbuf){ + xtra = (clip.width - gdk_pixbuf_get_width (col->pixbuf))/2; + + xtra += HEADER_PADDING / 2; + + gdk_pixbuf_render_to_drawable_alpha (col->pixbuf, + drawable, + 0, 0, + x + xtra, y + (clip.height - gdk_pixbuf_get_height (col->pixbuf)) / 2, + gdk_pixbuf_get_width (col->pixbuf), gdk_pixbuf_get_height(col->pixbuf), + GDK_PIXBUF_ALPHA_FULL, 128, + GDK_RGB_DITHER_NORMAL, + 0, 0); + } else { + int str_width, ellipsis_width, text_len; + + text_len = strlen (col->text); + ellipsis_width = gdk_text_width (ethi->font, "...", 3); + + str_width = gdk_text_width (ethi->font, col->text, text_len); + + if (str_width < clip.width) { + /* Center the thing */ + xtra = (clip.width - gdk_string_measure (ethi->font, col->text))/2; + + /* Skip over border */ + if (xtra < 0) + xtra = 0; + + xtra += HEADER_PADDING / 2; + + gdk_draw_text ( + drawable, ethi->font, + ethi->gc, x + xtra, y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, + col->text, text_len); + } else { + /* Need ellipsis */ + gchar *p; + int ellipsis_length = 0; + + for (p = col->text; p && *p && (p - col->text) < text_len; p++) { + if (gdk_text_width (ethi->font, col->text, p - col->text) + ellipsis_width <= clip.width) + ellipsis_length = p - col->text; + else + break; + } + + xtra = (clip.width - gdk_text_measure (ethi->font, col->text, ellipsis_length) - gdk_string_measure (ethi->font, "..."))/2; + + if (xtra < 0) + xtra = 0; + + xtra += HEADER_PADDING / 2; + + gdk_draw_text (drawable, ethi->font, ethi->gc, + x + xtra, y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, + col->text, ellipsis_length); + gdk_draw_string (drawable, ethi->font, ethi->gc, + x + xtra + gdk_text_width (ethi->font, + col->text, + ellipsis_length), + y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, + "..."); + } + } + + if (col->pixbuf){ + if ((gdk_pixbuf_get_width (col->pixbuf) + MIN_ARROW_SIZE + 4) > width) + return; + } } static void @@ -912,19 +951,37 @@ set_cursor (ETableHeaderItem *ethi, int pos) { int col; GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas); + gboolean resizeable = FALSE; /* We might be invoked before we are realized */ if (!canvas->window) return; if (is_pointer_on_division (ethi, pos, NULL, &col)) { + int last_col = ethi->eth->col_count - 1; ETableCol *ecol = e_table_header_get_column (ethi->eth, col); - if (ecol->resizeable) - e_cursor_set (canvas->window, E_CURSOR_SIZE_X); - else - e_cursor_set (canvas->window, E_CURSOR_ARROW); - } else + /* Last column is not resizable */ + if (ecol->resizeable && col != last_col) { + int c = col + 1; + + /* Column is not resizable if all columns after it + are also not resizable */ + for (; c <= last_col; c++){ + ETableCol *ecol2; + + ecol2 = e_table_header_get_column (ethi->eth, c); + if (ecol2->resizeable) { + resizeable = TRUE; + break; + } + } + } + } + + if (resizeable) + e_cursor_set (canvas->window, E_CURSOR_SIZE_X); + else e_cursor_set (canvas->window, E_CURSOR_ARROW); } @@ -1325,6 +1382,7 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) e_table_header_set_size (ethi->eth, ethi->resize_col, width + 10); gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(ethi)); + ethi->maybe_drag = FALSE; } break; diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index 186587838c..b1fdfc66d3 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -881,6 +881,10 @@ eti_destroy (GtkObject *object) g_free (eti->height_cache); + if (eti->tooltip->window) + gtk_widget_destroy (eti->tooltip->window); + g_free (eti->tooltip); + if (GTK_OBJECT_CLASS (eti_parent_class)->destroy) (*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object); } @@ -1010,6 +1014,8 @@ eti_init (GnomeCanvasItem *item) eti->needs_redraw = 0; eti->needs_compute_height = 0; + eti->tooltip = g_new0 (ETableTooltip, 1); + e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (eti), eti_reflow); } @@ -1414,6 +1420,34 @@ eti_cursor_move_down (ETableItem *eti) eti_cursor_move (eti, model_to_view_row(eti, cursor_row) + 1, model_to_view_col(eti, cursor_col)); } +static int +_do_tooltip (ETableItem *eti) +{ + ECellView *ecell_view; + int x = 0, y = 0; + int i; + + ecell_view = eti->cell_views[eti->tooltip->col]; + + for (i = 0; i < eti->tooltip->col; i++) + x += eti->header->columns[i]->width; + eti->tooltip->x = x; + + for (i = 0; i < eti->tooltip->row; i++) + y += ETI_ROW_HEIGHT (eti, i); + eti->tooltip->y = y; + eti->tooltip->eti = eti; + eti->tooltip->row_height = ETI_ROW_HEIGHT (eti, i); + + g_print ("Tooltip at %d,%d\n", x, y); + e_cell_show_tooltip (ecell_view, + view_to_model_col (eti, eti->tooltip->col), + eti->tooltip->col, + eti->tooltip->row, + eti->tooltip); + return FALSE; +} + /* FIXME: cursor */ static int eti_event (GnomeCanvasItem *item, GdkEvent *e) @@ -1428,6 +1462,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) int col, row; gint cursor_row, cursor_col; + if (eti->tooltip->timer) { + gtk_timeout_remove (eti->tooltip->timer); + eti->tooltip->timer = 0; + } + if (eti->tooltip->window) { + gtk_widget_destroy (eti->tooltip->window); + eti->tooltip->window = NULL; + } e_canvas_item_grab_focus(GNOME_CANVAS_ITEM(eti)); switch (e->button.button) { @@ -1495,6 +1537,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) int col, row; gint cursor_row, cursor_col; + if (eti->tooltip->timer) { + gtk_timeout_remove (eti->tooltip->timer); + eti->tooltip->timer = 0; + } + if (eti->tooltip->window) { + gtk_widget_destroy (eti->tooltip->window); + eti->tooltip->window = NULL; + } switch (e->button.button) { case 1: /* Fall through. */ case 2: @@ -1563,6 +1613,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) "cursor_col", &cursor_col, NULL); + if (eti->tooltip->timer > 0) + gtk_timeout_remove (eti->tooltip->timer); + eti->tooltip->col = col; + eti->tooltip->row = row; + eti->tooltip->cx = e->motion.x; + eti->tooltip->cy = e->motion.y; + eti->tooltip->timer = gtk_timeout_add (1000, _do_tooltip, eti); + if (cursor_row == view_to_model_row(eti, row) && cursor_col == view_to_model_col(eti, col)){ ecell_view = eti->cell_views [col]; @@ -1711,6 +1769,12 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) break; } + case GDK_LEAVE_NOTIFY: + case GDK_ENTER_NOTIFY: + if (eti->tooltip->timer > 0) + gtk_timeout_remove (eti->tooltip->timer); + break; + default: return_val = FALSE; } diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h index e89f2587e5..504563081c 100644 --- a/widgets/e-table/e-table-item.h +++ b/widgets/e-table/e-table-item.h @@ -7,6 +7,7 @@ #include "e-table-header.h" #include "e-table-selection-model.h" #include "e-table-defines.h" +#include "e-table-tooltip.h" #include <e-util/e-printable.h> #define E_TABLE_ITEM_TYPE (e_table_item_get_type ()) @@ -92,6 +93,11 @@ typedef struct { int editing_col, editing_row; void *edit_ctx; + /* + * Tooltip + */ + ETableTooltip *tooltip; + } ETableItem; typedef struct { diff --git a/widgets/e-table/e-table-tooltip.h b/widgets/e-table/e-table-tooltip.h new file mode 100644 index 0000000000..4bc3e5f8eb --- /dev/null +++ b/widgets/e-table/e-table-tooltip.h @@ -0,0 +1,17 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_TOOLTIP_H_ +#define _E_TABLE_TOOLTIP_H_ + +#include <libgnomeui/gnome-canvas.h> + +typedef struct { + GtkWidget *window; + gint timer; + int col, row; + int row_height; + int x, y; + int cx, cy; + GnomeCanvasItem *eti; +} ETableTooltip; + +#endif diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index ac8f3df7b2..411ffe03d5 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -39,6 +39,7 @@ #include "e-table-item.h" #include "e-text-event-processor.h" #include "e-text-event-processor-emacs-like.h" +#include "e-table-tooltip.h" #include <gdk/gdkx.h> /* for BlackPixel */ #include <ctype.h> @@ -1284,15 +1285,194 @@ ect_max_width (ECellView *ecell_view, for (row = 0; row < number_of_rows; row++) { CurrentCell cell; + struct line *line; + int width; + build_current_cell (&cell, text_view, model_col, view_col, row); split_into_lines (&cell); calc_line_widths (&cell); - max_width = MAX (max_width, cell.breaks->max_width); + + line = (struct line *)cell.breaks->lines; + width = e_font_utf8_text_width (font, cell.style, + line->text, line->length); + max_width = MAX (max_width, width); + unref_lines (&cell); + unbuild_current_cell (&cell); } return max_width; } +static gint +tooltip_event (GtkWidget *window, + GdkEvent *event, + ETableTooltip *tooltip) +{ + gint ret_val = FALSE; + + switch (event->type) { + case GDK_LEAVE_NOTIFY: + if (tooltip->window) { + gtk_widget_destroy (tooltip->window); + tooltip->window = NULL; + } + break; + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + if (event->type == GDK_BUTTON_RELEASE) { + if (tooltip->window) { + gtk_widget_destroy (tooltip->window); + tooltip->window = NULL; + } + } + + gtk_signal_emit_by_name (GTK_OBJECT (tooltip->eti), "event", + event, &ret_val); + break; + default: + break; + } + + return ret_val; +} + +static void +ect_show_tooltip (ECellView *ecell_view, + int model_col, + int view_col, + int row, + ETableTooltip *tooltip) +{ + ECellTextView *text_view = (ECellTextView *) ecell_view; + CurrentCell cell; + struct line *lines; + GtkWidget *canvas; + int i; + gdouble max_width; + gboolean cut_off; + double i2c[6]; + ArtPoint origin = {0, 0}; + ArtPoint pixel_origin; + int canvas_x, canvas_y; + GnomeCanvasItem *tooltip_text; + double tooltip_width; + double tooltip_height; + double tooltip_x; + double tooltip_y; + GnomeCanvasItem *rect; + double text_height; + + tooltip->timer = 0; + + build_current_cell (&cell, text_view, model_col, view_col, row); + split_into_lines (&cell); + calc_line_widths (&cell); + + cut_off = FALSE; + for (lines = cell.breaks->lines, i = 0; i < cell.breaks->num_lines; + lines++, i++) { + if (lines->length > lines->ellipsis_length) { + cut_off = TRUE; + break; + } + } + + if (!cut_off) { + tooltip->timer = 0; + return; + } + + gnome_canvas_item_i2c_affine (GNOME_CANVAS_ITEM (tooltip->eti), i2c); + art_affine_point (&pixel_origin, &origin, i2c); + + g_print ("%d,%d\n", pixel_origin.x, pixel_origin.y); + gdk_window_get_origin (GTK_WIDGET (text_view->canvas)->window, + &canvas_x, &canvas_y); + pixel_origin.x += canvas_x; + pixel_origin.y += canvas_y; + pixel_origin.x -= (int) gtk_layout_get_hadjustment (GTK_LAYOUT (text_view->canvas))->value; + pixel_origin.y -= (int) gtk_layout_get_vadjustment (GTK_LAYOUT (text_view->canvas))->value; + + tooltip->window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_container_set_border_width (GTK_CONTAINER (tooltip->window), 1); + + canvas = e_canvas_new (); + gtk_container_add (GTK_CONTAINER (tooltip->window), canvas); + + max_width = 0.0; + for (lines = cell.breaks->lines, i = 0; i < cell.breaks->num_lines; + lines++, i++) { + gdouble line_width; + + line_width = e_font_utf8_text_width (text_view->font, + E_FONT_PLAIN, lines->text, + lines->length); + max_width = MAX (max_width, line_width); + } + + text_height = e_font_height (text_view->font) * cell.breaks->num_lines + 4; + rect = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), + gnome_canvas_rect_get_type (), + "x1", (double) 0.0, + "y1", (double) 0.0, + "x2", (double) max_width + 4, + "y2", (double) text_height, + "fill_color", "yellow", + NULL); + + tooltip_text = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), + e_text_get_type (), + "anchor", GTK_ANCHOR_NW, +/* "font_gdk", text_view->font, */ + "text", cell.text, + "editable", FALSE, + "clip_width", max_width, + "clip_height", (double) text_height, + "clip", TRUE, + "line_wrap", FALSE, + "justification", E_CELL_TEXT (text_view->cell_view.ecell)->justify, + NULL); + + tooltip_width = max_width; + tooltip_height = text_height; + tooltip_y = tooltip->y; + + switch (E_CELL_TEXT (text_view->cell_view.ecell)->justify) { + case GTK_JUSTIFY_CENTER: + tooltip_x = - tooltip_width / 2; + break; + case GTK_JUSTIFY_RIGHT: + tooltip_x = tooltip_width / 2; + break; + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + tooltip_x = tooltip->x; + break; + } + + gnome_canvas_item_set (rect, + "x2", (double) tooltip_width, + "y2", (double) tooltip->row_height, + NULL); + gtk_widget_set_usize (tooltip->window, tooltip_width, + tooltip->row_height); + gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0.0, 0.0, + (double) tooltip_width, + (double) tooltip_height); + gtk_widget_show (canvas); + gtk_widget_realize (tooltip->window); + gtk_signal_connect (GTK_OBJECT (tooltip->window), "event", + GTK_SIGNAL_FUNC (tooltip_event), tooltip); + + gtk_widget_popup (tooltip->window, pixel_origin.x + tooltip->x, + pixel_origin.y + tooltip->y); + + unref_lines (&cell); + unbuild_current_cell (&cell); + + return; +} + /* * GtkObject::destroy method */ @@ -1384,6 +1564,7 @@ e_cell_text_class_init (GtkObjectClass *object_class) ecc->print = ect_print; ecc->print_height = ect_print_height; ecc->max_width = ect_max_width; + ecc->show_tooltip = ect_show_tooltip; object_class->get_arg = ect_get_arg; object_class->set_arg = ect_set_arg; @@ -2331,6 +2512,7 @@ build_current_cell (CurrentCell *cell, ECellTextView *text_view, int model_col, cell->width = e_table_header_get_column ( ((ETableItem *)ecell_view->e_table_item_view)->header, view_col)->width - 8; + cell->style = 0; } static void diff --git a/widgets/table/e-cell-tree.c b/widgets/table/e-cell-tree.c index 48ae9f4af1..5a055fce0e 100644 --- a/widgets/table/e-cell-tree.c +++ b/widgets/table/e-cell-tree.c @@ -411,7 +411,24 @@ ect_max_width (ECellView *ecell_view, int model_col, int view_col) return max_width; } - +/* + * ECellView::show_tooltip method + */ +static void +ect_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, + ETableTooltip *tooltip) +{ + ECellTreeView *tree_view = (ECellTreeView *) ecell_view; + ETreeModel *tree_model = e_cell_tree_get_tree_model (ecell_view->e_table_model, row); + ETreePath *node = e_cell_tree_get_node (tree_model, row); + int offset = offset_of_node (tree_model, node); + + /* if the tooltip happened in the subcell, then handle it */ + + if (tooltip->cx > offset) { + e_cell_show_tooltip (tree_view->subcell_view, model_col, view_col, row, tooltip); + } +} /* * ECellView::enter_edit method @@ -572,6 +589,7 @@ e_cell_tree_class_init (GtkObjectClass *object_class) ecc->print = ect_print; ecc->print_height = ect_print_height; ecc->max_width = ect_max_width; + ecc->show_tooltip = ect_show_tooltip; parent_class = gtk_type_class (PARENT_TYPE); } diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c index ddab43dbd6..f5d2abf733 100644 --- a/widgets/table/e-cell.c +++ b/widgets/table/e-cell.c @@ -90,6 +90,12 @@ ec_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void } static void +ec_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, ETableTooltip *tooltip) +{ + /* Do nothing */ +} + +static void e_cell_class_init (GtkObjectClass *object_class) { ECellClass *ecc = (ECellClass *) object_class; @@ -107,6 +113,8 @@ e_cell_class_init (GtkObjectClass *object_class) ecc->leave_edit = ec_leave_edit; ecc->print = NULL; ecc->print_height = NULL; + ecc->max_width = NULL; + ecc->show_tooltip = ec_show_tooltip; } static void @@ -206,3 +214,10 @@ e_cell_max_width (ECellView *ecell_view, int model_col, int view_col) (ecell_view, model_col, view_col); } +void +e_cell_show_tooltip (ECellView *ecell_view, int model_col, int view_col, + int row, ETableTooltip *tooltip) +{ + return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->show_tooltip + (ecell_view, model_col, view_col, row, tooltip); +} diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h index d097a7d6bd..028cdad077 100644 --- a/widgets/table/e-cell.h +++ b/widgets/table/e-cell.h @@ -5,6 +5,7 @@ #include <gdk/gdktypes.h> #include <libgnomeprint/gnome-print.h> #include "e-table-model.h" +#include "e-table-tooltip.h" #define E_CELL_TYPE (e_cell_get_type ()) #define E_CELL(o) (GTK_CHECK_CAST ((o), E_CELL_TYPE, ECell)) @@ -70,6 +71,7 @@ typedef struct { gdouble (*print_height) (ECellView *ecell_view, GnomePrintContext *context, int model_col, int view_col, int row, gdouble width); int (*max_width) (ECellView *ecell_view, int model_col, int view_col); + void (*show_tooltip) (ECellView *ecell_view, int model_col, int view_col, int row, ETableTooltip *tooltip); } ECellClass; GtkType e_cell_get_type (void); @@ -90,6 +92,7 @@ void e_cell_print (ECellView *ecell_view, GnomePrintContext *context, gdouble e_cell_print_height (ECellView *ecell_view, GnomePrintContext *context, int model_col, int view_col, int row, gdouble width); int e_cell_max_width (ECellView *ecell_view, int model_col, int view_col); +void e_cell_show_tooltip (ECellView *ecell_view, int model_col, int view_col, int row, ETableTooltip *tooltip); void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index ec25e0d0f0..903d6b954f 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -740,40 +740,6 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, gdk_gc_set_clip_rectangle (ethi->gc, &clip); - if (col->is_pixbuf){ - xtra = (clip.width - gdk_pixbuf_get_width (col->pixbuf))/2; - - xtra += HEADER_PADDING / 2; - - gdk_pixbuf_render_to_drawable_alpha (col->pixbuf, - drawable, - 0, 0, - x + xtra, y + (clip.height - gdk_pixbuf_get_height (col->pixbuf)) / 2, - gdk_pixbuf_get_width (col->pixbuf), gdk_pixbuf_get_height(col->pixbuf), - GDK_PIXBUF_ALPHA_FULL, 128, - GDK_RGB_DITHER_NORMAL, - 0, 0); - } else { - /* Center the thing */ - xtra = (clip.width - gdk_string_measure (ethi->font, col->text))/2; - - /* Skip over border */ - if (xtra < 0) - xtra = 0; - - xtra += HEADER_PADDING / 2; - - gdk_draw_text ( - drawable, ethi->font, - ethi->gc, x + xtra, y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, - col->text, strlen (col->text)); - } - - if (col->pixbuf){ - if ((gdk_pixbuf_get_width (col->pixbuf) + MIN_ARROW_SIZE + 4) > width) - return; - } - switch (arrow){ case E_TABLE_COL_ARROW_NONE: break; @@ -794,8 +760,81 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, y + (ethi->height - MIN_ARROW_SIZE) / 2, MIN_ARROW_SIZE, MIN_ARROW_SIZE); + + clip.width -= (MIN_ARROW_SIZE + 2 + HEADER_PADDING); break; } + + if (col->is_pixbuf){ + xtra = (clip.width - gdk_pixbuf_get_width (col->pixbuf))/2; + + xtra += HEADER_PADDING / 2; + + gdk_pixbuf_render_to_drawable_alpha (col->pixbuf, + drawable, + 0, 0, + x + xtra, y + (clip.height - gdk_pixbuf_get_height (col->pixbuf)) / 2, + gdk_pixbuf_get_width (col->pixbuf), gdk_pixbuf_get_height(col->pixbuf), + GDK_PIXBUF_ALPHA_FULL, 128, + GDK_RGB_DITHER_NORMAL, + 0, 0); + } else { + int str_width, ellipsis_width, text_len; + + text_len = strlen (col->text); + ellipsis_width = gdk_text_width (ethi->font, "...", 3); + + str_width = gdk_text_width (ethi->font, col->text, text_len); + + if (str_width < clip.width) { + /* Center the thing */ + xtra = (clip.width - gdk_string_measure (ethi->font, col->text))/2; + + /* Skip over border */ + if (xtra < 0) + xtra = 0; + + xtra += HEADER_PADDING / 2; + + gdk_draw_text ( + drawable, ethi->font, + ethi->gc, x + xtra, y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, + col->text, text_len); + } else { + /* Need ellipsis */ + gchar *p; + int ellipsis_length = 0; + + for (p = col->text; p && *p && (p - col->text) < text_len; p++) { + if (gdk_text_width (ethi->font, col->text, p - col->text) + ellipsis_width <= clip.width) + ellipsis_length = p - col->text; + else + break; + } + + xtra = (clip.width - gdk_text_measure (ethi->font, col->text, ellipsis_length) - gdk_string_measure (ethi->font, "..."))/2; + + if (xtra < 0) + xtra = 0; + + xtra += HEADER_PADDING / 2; + + gdk_draw_text (drawable, ethi->font, ethi->gc, + x + xtra, y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, + col->text, ellipsis_length); + gdk_draw_string (drawable, ethi->font, ethi->gc, + x + xtra + gdk_text_width (ethi->font, + col->text, + ellipsis_length), + y + ethi->height - ethi->font->descent - HEADER_PADDING / 2, + "..."); + } + } + + if (col->pixbuf){ + if ((gdk_pixbuf_get_width (col->pixbuf) + MIN_ARROW_SIZE + 4) > width) + return; + } } static void @@ -912,19 +951,37 @@ set_cursor (ETableHeaderItem *ethi, int pos) { int col; GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas); + gboolean resizeable = FALSE; /* We might be invoked before we are realized */ if (!canvas->window) return; if (is_pointer_on_division (ethi, pos, NULL, &col)) { + int last_col = ethi->eth->col_count - 1; ETableCol *ecol = e_table_header_get_column (ethi->eth, col); - if (ecol->resizeable) - e_cursor_set (canvas->window, E_CURSOR_SIZE_X); - else - e_cursor_set (canvas->window, E_CURSOR_ARROW); - } else + /* Last column is not resizable */ + if (ecol->resizeable && col != last_col) { + int c = col + 1; + + /* Column is not resizable if all columns after it + are also not resizable */ + for (; c <= last_col; c++){ + ETableCol *ecol2; + + ecol2 = e_table_header_get_column (ethi->eth, c); + if (ecol2->resizeable) { + resizeable = TRUE; + break; + } + } + } + } + + if (resizeable) + e_cursor_set (canvas->window, E_CURSOR_SIZE_X); + else e_cursor_set (canvas->window, E_CURSOR_ARROW); } @@ -1325,6 +1382,7 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) e_table_header_set_size (ethi->eth, ethi->resize_col, width + 10); gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(ethi)); + ethi->maybe_drag = FALSE; } break; diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index 186587838c..b1fdfc66d3 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -881,6 +881,10 @@ eti_destroy (GtkObject *object) g_free (eti->height_cache); + if (eti->tooltip->window) + gtk_widget_destroy (eti->tooltip->window); + g_free (eti->tooltip); + if (GTK_OBJECT_CLASS (eti_parent_class)->destroy) (*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object); } @@ -1010,6 +1014,8 @@ eti_init (GnomeCanvasItem *item) eti->needs_redraw = 0; eti->needs_compute_height = 0; + eti->tooltip = g_new0 (ETableTooltip, 1); + e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (eti), eti_reflow); } @@ -1414,6 +1420,34 @@ eti_cursor_move_down (ETableItem *eti) eti_cursor_move (eti, model_to_view_row(eti, cursor_row) + 1, model_to_view_col(eti, cursor_col)); } +static int +_do_tooltip (ETableItem *eti) +{ + ECellView *ecell_view; + int x = 0, y = 0; + int i; + + ecell_view = eti->cell_views[eti->tooltip->col]; + + for (i = 0; i < eti->tooltip->col; i++) + x += eti->header->columns[i]->width; + eti->tooltip->x = x; + + for (i = 0; i < eti->tooltip->row; i++) + y += ETI_ROW_HEIGHT (eti, i); + eti->tooltip->y = y; + eti->tooltip->eti = eti; + eti->tooltip->row_height = ETI_ROW_HEIGHT (eti, i); + + g_print ("Tooltip at %d,%d\n", x, y); + e_cell_show_tooltip (ecell_view, + view_to_model_col (eti, eti->tooltip->col), + eti->tooltip->col, + eti->tooltip->row, + eti->tooltip); + return FALSE; +} + /* FIXME: cursor */ static int eti_event (GnomeCanvasItem *item, GdkEvent *e) @@ -1428,6 +1462,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) int col, row; gint cursor_row, cursor_col; + if (eti->tooltip->timer) { + gtk_timeout_remove (eti->tooltip->timer); + eti->tooltip->timer = 0; + } + if (eti->tooltip->window) { + gtk_widget_destroy (eti->tooltip->window); + eti->tooltip->window = NULL; + } e_canvas_item_grab_focus(GNOME_CANVAS_ITEM(eti)); switch (e->button.button) { @@ -1495,6 +1537,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) int col, row; gint cursor_row, cursor_col; + if (eti->tooltip->timer) { + gtk_timeout_remove (eti->tooltip->timer); + eti->tooltip->timer = 0; + } + if (eti->tooltip->window) { + gtk_widget_destroy (eti->tooltip->window); + eti->tooltip->window = NULL; + } switch (e->button.button) { case 1: /* Fall through. */ case 2: @@ -1563,6 +1613,14 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) "cursor_col", &cursor_col, NULL); + if (eti->tooltip->timer > 0) + gtk_timeout_remove (eti->tooltip->timer); + eti->tooltip->col = col; + eti->tooltip->row = row; + eti->tooltip->cx = e->motion.x; + eti->tooltip->cy = e->motion.y; + eti->tooltip->timer = gtk_timeout_add (1000, _do_tooltip, eti); + if (cursor_row == view_to_model_row(eti, row) && cursor_col == view_to_model_col(eti, col)){ ecell_view = eti->cell_views [col]; @@ -1711,6 +1769,12 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) break; } + case GDK_LEAVE_NOTIFY: + case GDK_ENTER_NOTIFY: + if (eti->tooltip->timer > 0) + gtk_timeout_remove (eti->tooltip->timer); + break; + default: return_val = FALSE; } diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h index e89f2587e5..504563081c 100644 --- a/widgets/table/e-table-item.h +++ b/widgets/table/e-table-item.h @@ -7,6 +7,7 @@ #include "e-table-header.h" #include "e-table-selection-model.h" #include "e-table-defines.h" +#include "e-table-tooltip.h" #include <e-util/e-printable.h> #define E_TABLE_ITEM_TYPE (e_table_item_get_type ()) @@ -92,6 +93,11 @@ typedef struct { int editing_col, editing_row; void *edit_ctx; + /* + * Tooltip + */ + ETableTooltip *tooltip; + } ETableItem; typedef struct { diff --git a/widgets/table/e-table-tooltip.h b/widgets/table/e-table-tooltip.h new file mode 100644 index 0000000000..4bc3e5f8eb --- /dev/null +++ b/widgets/table/e-table-tooltip.h @@ -0,0 +1,17 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_TOOLTIP_H_ +#define _E_TABLE_TOOLTIP_H_ + +#include <libgnomeui/gnome-canvas.h> + +typedef struct { + GtkWidget *window; + gint timer; + int col, row; + int row_height; + int x, y; + int cx, cy; + GnomeCanvasItem *eti; +} ETableTooltip; + +#endif |