#include #include #include "gnumeric.h" #include "item-grid.h" #include "item-edit.h" #include "item-debug.h" #define CURSOR_LEN 4 static GnomeCanvasItem *item_edit_parent_class; /* The arguments we take */ enum { ARG_0, ARG_SHEET, /* The Sheet * argument */ ARG_ITEM_GRID, /* The ItemGrid * argument */ ARG_GTK_ENTRY, /* The GtkEntry * argument */ ARG_COL, /* The column where this should edit */ ARG_ROW, /* The row where this should edit */ }; /* * Returns the cordinates for the editor bounding box */ static void item_edit_get_pixel_coords (ItemEdit *item_edit, int *x, int *y, int *w, int *h) { ItemGrid *item_grid = item_edit->item_grid; Sheet *sheet = item_edit->sheet; *x = sheet_col_get_distance (sheet, item_grid->left_col, item_edit->col); *y = sheet_row_get_distance (sheet, item_grid->top_row, item_edit->row); *w = sheet_col_get_distance (sheet, item_edit->col, item_edit->col + item_edit->col_span); *h = sheet_row_get_distance (sheet, item_edit->row, item_edit->row + 1); } static void item_edit_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { GtkWidget *canvas = GTK_WIDGET (item->canvas); ItemEdit *item_edit = ITEM_EDIT (item); GdkFont *font; ColRowInfo *ci; int xd, yd, wd, hd, dx, dy; char *text; int cursor_pos, text_len, first_part_len, total_len; font = item_edit->style->font->font; text = gtk_entry_get_text (GTK_ENTRY (item_edit->editor)); text_len = strlen (text); cursor_pos = GTK_EDITABLE (item_edit->editor)->current_pos; total_len = gdk_text_width (font, text, text_len); ci = sheet_col_get_info (item_edit->sheet, item_edit->col); total_len += ci->margin_a + ci->margin_b + CURSOR_LEN; /* Adjust the col_span if necesary */ do { item_edit_get_pixel_coords (item_edit, &xd, &yd, &wd, &hd); if (total_len >= wd) item_edit->col_span++; } while (total_len >= wd); dx = xd - x; dy = yd - y; /* Do the drawing */ gdk_draw_rectangle (drawable, canvas->style->white_gc, TRUE, dx + 1, dy + 1, wd - 1, hd - 1); /* The margin, plus the pixel consumed by the border */ dx += ci->margin_a + 1; first_part_len = gdk_text_width (font, text, cursor_pos); /* * FIXME: * The -1 from "font->descent - 1" should actually be * cell->row->margin_b */ gdk_draw_text (drawable, font, canvas->style->black_gc, dx, dy + hd - font->descent - 1, text, cursor_pos); gdk_draw_line (drawable, canvas->style->black_gc, first_part_len + dx, dy + hd - font->descent, first_part_len + dx, dy + hd - (font->ascent + font->descent)); gdk_draw_text (drawable, font, canvas->style->black_gc, dx + first_part_len, dy + hd - font->descent - 1, text + cursor_pos, text_len - cursor_pos); } static double item_edit_point (GnomeCanvasItem *item, double c_x, double c_y, int cx, int cy, GnomeCanvasItem **actual_item) { int x, y, w, h; item_edit_get_pixel_coords (ITEM_EDIT (item), &x, &y, &w, &h); *actual_item = NULL; if ((cx < x) || (cy < y) || (cx > x+w) || (cy > y+w)) return 10000.0; *actual_item = item; return 0.0; } static void item_edit_translate (GnomeCanvasItem *item, double dx, double dy) { printf ("item_cursor_translate %g, %g\n", dx, dy); } static int item_edit_event (GnomeCanvasItem *item, GdkEvent *event) { return 0; } static void item_edit_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) { ItemEdit *item_edit = ITEM_EDIT (item); int x, y, w, h; if (GNOME_CANVAS_ITEM_CLASS (item_edit_parent_class)->update) (*GNOME_CANVAS_ITEM_CLASS(item_edit_parent_class)->update)(item, affine, clip_path, flags); item_edit_get_pixel_coords (item_edit, &x, &y, &w, &h); item->x1 = x; item->y1 = y; item->x2 = x + w; item->y2 = y + h; gnome_canvas_group_child_bounds ( GNOME_CANVAS_GROUP (item->parent), item); if (item_edit->style) style_destroy (item_edit->style); item_edit->style = sheet_style_compute ( item_edit->sheet, item_edit->col, item_edit->row, NULL); } /* * Instance initialization */ static void item_edit_init (ItemEdit *item_edit) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_edit); item->x1 = 0; item->y1 = 0; item->x2 = 1; item->y2 = 1; item_edit->col_span = 1; /* Set invalid values so that we know when we have been fully initialized */ item_edit->sheet = 0; item_edit->col = -1; item_edit->row = -1; } static void queue_sync (ItemEdit *item_edit) { GnomeCanvas *canvas = GNOME_CANVAS_ITEM (item_edit)->canvas; int x, y, w, h; item_edit_get_pixel_coords (item_edit, &x, &y, &w, &h); gnome_canvas_request_redraw (canvas, x, y, x+w, y+h); } static void entry_changed (GtkEntry *entry, void *data) { queue_sync (ITEM_EDIT (data)); } static void item_edit_destroy (GtkObject *o) { ItemEdit *item_edit = ITEM_EDIT (o); int x, y, w, h; /* Repaint the area where we had edited */ style_destroy (item_edit->style); item_edit_get_pixel_coords (item_edit, &x, &y, &w, &h); gnome_canvas_request_redraw (GNOME_CANVAS_ITEM (item_edit)->canvas, x, y, x+w, y+h); gtk_signal_disconnect (GTK_OBJECT (item_edit->editor), item_edit->signal); gtk_signal_disconnect (GTK_OBJECT (item_edit->editor), item_edit->signal2); if (GTK_OBJECT_CLASS (item_edit_parent_class)->destroy) (*GTK_OBJECT_CLASS (item_edit_parent_class)->destroy)(o); } static int entry_event (GtkEntry *entry, GdkEvent *event, ItemEdit *item_edit) { switch (event->type){ case GDK_KEY_PRESS: case GDK_KEY_RELEASE: case GDK_BUTTON_PRESS: queue_sync (item_edit); default: break; } return FALSE; } static void item_edit_set_editor (ItemEdit *item_edit, void *data) { item_edit->editor = GTK_WIDGET (data); item_edit->signal = gtk_signal_connect ( GTK_OBJECT (item_edit->editor), "changed", GTK_SIGNAL_FUNC(entry_changed), item_edit); item_edit->signal2 = gtk_signal_connect_after ( GTK_OBJECT (item_edit->editor), "event", GTK_SIGNAL_FUNC(entry_event), item_edit); } static void item_edit_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) { GnomeCanvasItem *item; ItemEdit *item_edit; item = GNOME_CANVAS_ITEM (o); item_edit = ITEM_EDIT (o); switch (arg_id){ case ARG_SHEET: item_edit->sheet = (Sheet *) GTK_VALUE_POINTER (*arg); break; case ARG_ITEM_GRID: item_edit->item_grid = GTK_VALUE_POINTER (*arg); break; case ARG_GTK_ENTRY: item_edit_set_editor (item_edit, GTK_VALUE_POINTER (*arg)); break; case ARG_COL: item_edit->col = GTK_VALUE_INT (*arg); break; case ARG_ROW: item_edit->row = GTK_VALUE_INT (*arg); break; } /* Once all of our parameters have been set, do the reconfiguration */ if (item_edit->sheet && item_edit->col != -1 && item_edit->row != -1) item_edit_update (item, NULL, NULL, 0); } /* * ItemEdit class initialization */ static void item_edit_class_init (ItemEditClass *item_edit_class) { GtkObjectClass *object_class; GnomeCanvasItemClass *item_class; item_edit_parent_class = gtk_type_class (gnome_canvas_item_get_type()); object_class = (GtkObjectClass *) item_edit_class; item_class = (GnomeCanvasItemClass *) item_edit_class; gtk_object_add_arg_type ("ItemEdit::Sheet", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_SHEET); gtk_object_add_arg_type ("ItemEdit::Grid", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_ITEM_GRID); gtk_object_add_arg_type ("ItemEdit::GtkEntry", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_GTK_ENTRY); gtk_object_add_arg_type ("ItemEdit::Col", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_COL); gtk_object_add_arg_type ("ItemEdit::Row", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_ROW); object_class->set_arg = item_edit_set_arg; object_class->destroy = item_edit_destroy; /* GnomeCanvasItem method overrides */ item_class->update = item_edit_update; item_class->draw = item_edit_draw; item_class->point = item_edit_point; item_class->translate = item_edit_translate; item_class->event = item_edit_event; } GtkType item_edit_get_type (void) { static GtkType item_edit_type = 0; if (!item_edit_type) { GtkTypeInfo item_edit_info = { "ItemEdit", sizeof (ItemEdit), sizeof (ItemEditClass), (GtkClassInitFunc) item_edit_class_init, (GtkObjectInitFunc) item_edit_init, NULL, /* reserved_1 */ NULL, /* reserved_2 */ (GtkClassInitFunc) NULL }; item_edit_type = gtk_type_unique (gnome_canvas_item_get_type (), &item_edit_info); } return item_edit_type; }