diff options
author | Miguel de Icaza <miguel@gnu.org> | 1999-12-10 15:36:51 +0800 |
---|---|---|
committer | Arturo Espinosa <unammx@src.gnome.org> | 1999-12-10 15:36:51 +0800 |
commit | 48618eb6eb0d02a6bc74d19d0241ac6b0849d136 (patch) | |
tree | df66b3707b394dd8737d579f04ec9a401eb2f9b4 /widgets/table/e-table-header-item.c | |
parent | 54e2b5022a8eca59e4aac0d5b0d3cb125d54c008 (diff) | |
download | gsoc2013-evolution-48618eb6eb0d02a6bc74d19d0241ac6b0849d136.tar.gz gsoc2013-evolution-48618eb6eb0d02a6bc74d19d0241ac6b0849d136.tar.zst gsoc2013-evolution-48618eb6eb0d02a6bc74d19d0241ac6b0849d136.zip |
fix this routine.
1999-12-09 Miguel de Icaza <miguel@gnu.org>
* e-table-header.c (e_table_header_col_diff): fix this routine.
1999-12-04 Miguel de Icaza <miguel@gnu.org>
* e-table-header-item.c (ethi_event): Started drag and drop
support.
* e-table-item.c (eti_table_model_changed): The columns are
controled by the Header, not by the TableModel.
* e-table-header-item.c (ethi_draw): Fixed redraw logic to support
arbitrary header positioning.
* e-cell.h: Revamped e-cell interface. We now provide the model
column and the view column to all methods (so that the methods can
talk to the view and to the model at the same time).
* e-table-item.c: Update to new API
* e-cell-test.c: Update to new API
1999-12-03 Miguel de Icaza <miguel@gnu.org>
* e-cell.c (e_cell_class_init): Provide emtpy methods for
enter_edit, and leave_edit.
* e-table-item.c: Killed draw cell.
(eti_draw): Perform column mapping here.
(e_table_item_leave_edit): ditto.
(e_table_item_enter_edit): ditto.
(eti_event): ditto.
svn path=/trunk/; revision=1478
Diffstat (limited to 'widgets/table/e-table-header-item.c')
-rw-r--r-- | widgets/table/e-table-header-item.c | 316 |
1 files changed, 292 insertions, 24 deletions
diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index 5368f10602..0b5be9b84a 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -8,10 +8,19 @@ */ #include <config.h> #include <gtk/gtksignal.h> +#include <gtk/gtkdnd.h> +#include <libgnomeui/gnome-canvas.h> +#include <libgnomeui/gnome-canvas-util.h> +#include <libgnomeui/gnome-canvas-polygon.h> +#include <libgnomeui/gnome-canvas-rect-ellipse.h> #include "e-table-header.h" #include "e-table-header-item.h" +#include "e-table-col-dnd.h" #include "e-cursors.h" +#include "add-col.xpm" +#include "remove-col.xpm" + /* Padding above and below of the string in the header display */ #define PADDING 4 @@ -22,8 +31,17 @@ #define PARENT_OBJECT_TYPE gnome_canvas_item_get_type () +#define ELEMENTS(x) (sizeof (x) / sizeof (x[0])) + static GnomeCanvasItemClass *ethi_parent_class; +/* + * DnD icons + */ +static GdkColormap *dnd_colormap; +static GdkPixmap *remove_col_pixmap, *remove_col_mask; +static GdkPixmap *add_col_pixmap, *add_col_mask; + enum { ARG_0, ARG_TABLE_HEADER, @@ -32,6 +50,14 @@ enum { ARG_TABLE_FONTSET }; +static GtkTargetEntry ethi_drag_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + +static GtkTargetEntry ethi_drop_types [] = { + { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER }, +}; + static void ethi_destroy (GtkObject *object) { @@ -151,6 +177,177 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) ethi_update (item, NULL, NULL, 0); } +static int +ethi_find_col_by_x (ETableHeaderItem *ethi, int x) +{ + const int cols = e_table_header_count (ethi->eth); + int x1 = ethi->x1; + int col; + + if (x < x1) + return -1; + + for (col = 0; col < cols; col++){ + ETableCol *ecol = e_table_header_get_column (ethi->eth, col); + + if ((x >= x1) && (x <= x1 + ecol->width)) + return col; + + x1 += ecol->width; + } + return -1; +} + +static void +ethi_remove_drop_marker (ETableHeaderItem *ethi) +{ + if (ethi->drag_mark == -1) + return; + + ethi->drag_mark = -1; + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + ethi->drag_mark_item = NULL; +} + +static void +ethi_add_drop_marker (ETableHeaderItem *ethi, int col) +{ + GnomeCanvasPoints *points; + int x; + + if (ethi->drag_mark == col) + return; + + if (ethi->drag_mark_item) + gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item)); + + ethi->drag_mark = col; + + ethi->drag_mark_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_group_get_type (), + "x", 0, + "y", 0, + NULL); + + points = gnome_canvas_points_new (3); + + x = e_table_header_col_diff (ethi->eth, 0, col); + + points->coords [0] = ethi->x1 + x - 5; + points->coords [1] = ethi->y1; + points->coords [2] = points->coords [0] + 10; + points->coords [3] = points->coords [1]; + points->coords [4] = ethi->x1 + x; + points->coords [5] = ethi->y1 + 5; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + points->coords [0] --; + points->coords [1] += ethi->height - 1; + points->coords [3] = points->coords [1]; + points->coords [5] = points->coords [1] - 6; + + gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (ethi->drag_mark_item), + gnome_canvas_polygon_get_type (), + "points", points, + "fill_color", "red", + NULL); + + gnome_canvas_points_unref (points); +} + +#define gray50_width 2 +#define gray50_height 2 +static char gray50_bits [] = { + 0x02, 0x01, }; + +static void +ethi_add_destroy_marker (ETableHeaderItem *ethi) +{ + double x1; + + if (ethi->remove_item) + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + + if (!ethi->stipple) + ethi->stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height); + + x1 = ethi->x1 + (double) e_table_header_col_diff (ethi->eth, 0, ethi->drag_col); + ethi->remove_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root), + gnome_canvas_rect_get_type (), + "x1", x1 + 1, + "y1", (double) ethi->y1 + 1, + "x2", (double) x1 + e_table_header_col_diff (ethi->eth, ethi->drag_col, ethi->drag_col+1) - 2, + "y2", (double) ethi->y1 + ethi->height - 2, + "fill_color", "red", + "fill_stipple", ethi->stipple, + NULL); +} + +static void +ethi_remove_destroy_marker (ETableHeaderItem *ethi) +{ + if (!ethi->remove_item) + return; + + gtk_object_destroy (GTK_OBJECT (ethi->remove_item)); + ethi->remove_item = NULL; +} + +static gboolean +ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, + gint x, gint y, guint time, + ETableHeaderItem *ethi) +{ + + if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && + (y >= ethi->y1) && (y <= (ethi->y1 + ethi->height))){ + int col; + + col = ethi_find_col_by_x (ethi, x); + + if (col != -1){ + ethi_remove_destroy_marker (ethi); + ethi_add_drop_marker (ethi, col); + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + } else { + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); + } + + gdk_drag_status (context, context->suggested_action, time); + + return TRUE; +} + +static void +ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi) +{ + printf ("Ending\n"); + + ethi_remove_drop_marker (ethi); + ethi_remove_destroy_marker (ethi); + ethi->drag_col = -1; +} + +static void +ethi_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, ETableHeaderItem *ethi) +{ + ethi_remove_drop_marker (ethi); + ethi_add_destroy_marker (ethi); +} + static void ethi_realize (GnomeCanvasItem *item) { @@ -171,19 +368,47 @@ ethi_realize (GnomeCanvasItem *item) if (!ethi->font) ethi_font_load (ethi, "fixed"); + + /* + * Now, configure DnD + */ + gtk_drag_dest_set (GTK_WIDGET (item->canvas), GTK_DEST_DEFAULT_ALL, + ethi_drop_types, ELEMENTS (ethi_drop_types), + GDK_ACTION_MOVE); + + ethi->drag_motion_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_motion", + GTK_SIGNAL_FUNC (ethi_drag_motion), ethi); + + ethi->drag_leave_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_leave", + GTK_SIGNAL_FUNC (ethi_drag_leave), ethi); + + ethi->drag_end_id = gtk_signal_connect ( + GTK_OBJECT (item->canvas), "drag_end", + GTK_SIGNAL_FUNC (ethi_drag_end), ethi); } static void ethi_unrealize (GnomeCanvasItem *item) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); - + gdk_gc_unref (ethi->gc); ethi->gc = NULL; gdk_cursor_destroy (ethi->normal_cursor); ethi->normal_cursor = NULL; + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_motion_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_end_id); + gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_leave_id); + + if (ethi->stipple){ + gdk_bitmap_unref (ethi->stipple); + ethi->stipple = NULL; + } + if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize) (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item); } @@ -228,25 +453,21 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, } static void -ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height) +ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item); GnomeCanvas *canvas = item->canvas; GdkGC *gc; const int cols = e_table_header_count (ethi->eth); - int x2 = x1 + width; - int col, total; - int x; - - total = 0; - x = -x1; + int x1, x2; + int col; #if 0 printf ("My coords are: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); #endif - - for (col = 0; col < cols; col++){ + x1 = x2 = ethi->x1; + for (col = 0; col < cols; col++, x1 = x2){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); int col_width; @@ -255,23 +476,19 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int wid else col_width = ecol->width; - if (x1 > total + col_width){ - total += col_width; - x += col_width; - continue; - } - - if (x2 < total) - return; + x2 += col_width; + + if (x1 > (x + width)) + break; + if (x2 < x) + continue; + gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE]; draw_button (ethi, ecol, drawable, gc, GTK_WIDGET (canvas)->style, - x, ethi->y1 - y1, col_width, ethi->height); - - x += col_width; - total += col_width; + x1 - x, ethi->y1 - y, col_width, ethi->height); } } @@ -356,6 +573,35 @@ ethi_end_resize (ETableHeaderItem *ethi, int new_size) ethi_request_redraw (ethi); } +static gboolean +ethi_maybe_start_drag (ETableHeaderItem *ethi, GdkEventMotion *event) +{ + if (!ethi->maybe_drag) + return FALSE; + + if (MAX (abs (ethi->click_x - event->x), + abs (ethi->click_y - event->y)) <= 3) + return FALSE; + + return TRUE; +} + +static void +ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) +{ + GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas); + GtkTargetList *list; + GdkDragContext *context; + + ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); + if (ethi->drag_col == -1) + return; + + list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); + context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event); + ethi->maybe_drag = FALSE; +} + /* * Handles the events on the ETableHeaderItem, particularly it handles resizing */ @@ -405,6 +651,8 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width); ethi_request_redraw (ethi); + } else if (ethi_maybe_start_drag (ethi, &e->motion)){ + ethi_start_drag (ethi, e); } else set_cursor (ethi, x); break; @@ -430,6 +678,12 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) ethi->resize_width = ecol->width; ethi->resize_start_pos = start - ecol->width; ethi->resize_min_width = ecol->min_width; + } else { + if (e->button.button == 1){ + ethi->click_x = e->button.x; + ethi->click_y = e->button.y; + ethi->maybe_drag = TRUE; + } } break; @@ -439,8 +693,6 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (e->button.button != 1) break; - - printf ("Resize this guy\n"); break; case GDK_BUTTON_RELEASE: { @@ -453,6 +705,7 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); + ethi->maybe_drag = FALSE; break; } @@ -487,6 +740,18 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); + + /* + * Create our pixmaps for DnD + */ + dnd_colormap = gtk_widget_get_default_colormap (); + remove_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &remove_col_mask, NULL, remove_col_xpm); + + add_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, dnd_colormap, + &add_col_mask, NULL, add_col_xpm); } static void @@ -500,6 +765,9 @@ ethi_init (GnomeCanvasItem *item) item->y1 = 0; item->x2 = 0; item->y2 = 0; + + ethi->drag_col = -1; + ethi->drag_mark = -1; } GtkType |