diff --git a/ChangeLog-1999-07-09 b/ChangeLog-1999-07-09 index e845174a235caa4056377139670fa4c5f834c990..3eb0932b738f682f79f306b398ffb90bf1d90d03 100644 --- a/ChangeLog-1999-07-09 +++ b/ChangeLog-1999-07-09 @@ -1,3 +1,20 @@ +1998-07-09 Miguel de Icaza + + * src/item-grid.c: + New paint strategy for the grid (uses what apparently Excel does); + It now correctly uses the coordinate system from the canvas (ie, + zoom in and zoom out work); + + * src/item-cursor.c: Implemented new version of the cursor. I am + using black lines for the cursor. One day, when I find the + strenght, I will use inversion and the inversion will do the right + thing. + + * src/item-bar.c: New file. Implements the titles for the columns + and rows; + + * src/*: made stuff fit together. + 1998-07-06 Raja R Harinath * configure.in: Remove duplicated AM_GNU_GETTEXT. diff --git a/ChangeLog-2000-02-23 b/ChangeLog-2000-02-23 index e845174a235caa4056377139670fa4c5f834c990..3eb0932b738f682f79f306b398ffb90bf1d90d03 100644 --- a/ChangeLog-2000-02-23 +++ b/ChangeLog-2000-02-23 @@ -1,3 +1,20 @@ +1998-07-09 Miguel de Icaza + + * src/item-grid.c: + New paint strategy for the grid (uses what apparently Excel does); + It now correctly uses the coordinate system from the canvas (ie, + zoom in and zoom out work); + + * src/item-cursor.c: Implemented new version of the cursor. I am + using black lines for the cursor. One day, when I find the + strenght, I will use inversion and the inversion will do the right + thing. + + * src/item-bar.c: New file. Implements the titles for the columns + and rows; + + * src/*: made stuff fit together. + 1998-07-06 Raja R Harinath * configure.in: Remove duplicated AM_GNU_GETTEXT. diff --git a/OChangeLog-1999-07-09 b/OChangeLog-1999-07-09 index e845174a235caa4056377139670fa4c5f834c990..3eb0932b738f682f79f306b398ffb90bf1d90d03 100644 --- a/OChangeLog-1999-07-09 +++ b/OChangeLog-1999-07-09 @@ -1,3 +1,20 @@ +1998-07-09 Miguel de Icaza + + * src/item-grid.c: + New paint strategy for the grid (uses what apparently Excel does); + It now correctly uses the coordinate system from the canvas (ie, + zoom in and zoom out work); + + * src/item-cursor.c: Implemented new version of the cursor. I am + using black lines for the cursor. One day, when I find the + strenght, I will use inversion and the inversion will do the right + thing. + + * src/item-bar.c: New file. Implements the titles for the columns + and rows; + + * src/*: made stuff fit together. + 1998-07-06 Raja R Harinath * configure.in: Remove duplicated AM_GNU_GETTEXT. diff --git a/OChangeLog-2000-02-23 b/OChangeLog-2000-02-23 index e845174a235caa4056377139670fa4c5f834c990..3eb0932b738f682f79f306b398ffb90bf1d90d03 100644 --- a/OChangeLog-2000-02-23 +++ b/OChangeLog-2000-02-23 @@ -1,3 +1,20 @@ +1998-07-09 Miguel de Icaza + + * src/item-grid.c: + New paint strategy for the grid (uses what apparently Excel does); + It now correctly uses the coordinate system from the canvas (ie, + zoom in and zoom out work); + + * src/item-cursor.c: Implemented new version of the cursor. I am + using black lines for the cursor. One day, when I find the + strenght, I will use inversion and the inversion will do the right + thing. + + * src/item-bar.c: New file. Implements the titles for the columns + and rows; + + * src/*: made stuff fit together. + 1998-07-06 Raja R Harinath * configure.in: Remove duplicated AM_GNU_GETTEXT. diff --git a/src/Makefile.am b/src/Makefile.am index 59b1c0ecfbf47a093fcb913d4bf94faae3f3af5a..bfe173545896f0cf8a578a7a96b52b44dade3935 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,8 @@ gnumeric_SOURCES = \ gnumeric-sheet.h \ gnumeric-sheet.c \ gnumeric.h \ + item-bar.c \ + item-bar.h \ item-cursor.c \ item-cursor.h \ item-debug.c \ diff --git a/src/cell.h b/src/cell.h index 2c7053b82148846d93c7da83af2e337263c2466e..e8d0ca2d6568bc45dee3c7a65e926ff751392541 100644 --- a/src/cell.h +++ b/src/cell.h @@ -29,8 +29,30 @@ typedef struct { } CellColor; typedef struct { - ColType col; - RowType row; + RowType row; + Style *style; /* if existant, this row style */ + + /* The height */ + int unit_height; /* In units */ + int top_margin; /* in pixels: top margin */ + int bottom_margin; /* in pixels: bottom margin */ + int height; /* we compute this from the above parameters */ +} RowInfo; + +typedef struct { + ColType col; + Style *style; /* if existant, this column style */ + + /* The width */ + int unit_width; /* in units */ + int left_margin; /* in pixels: left margin */ + int right_margin; /* in pixels: right margin */ + int width; /* w2pix (unit_width) + margins */ +} ColInfo; + +typedef struct { + ColInfo *col; + RowInfo *row; /* Text as entered by the user */ char *entered_text; diff --git a/src/gnumeric-canvas.c b/src/gnumeric-canvas.c index df24a25c2ce3dcf5263c087d2b841e9c04f78590..a3ea5d0d05957a2d1804cf65db55b85b04d930cc 100644 --- a/src/gnumeric-canvas.c +++ b/src/gnumeric-canvas.c @@ -44,7 +44,7 @@ gnumeric_sheet_create (Sheet *sheet) gsheet->sheet = sheet; gsheet->top_col = 0; gsheet->top_row = 0; - + return gsheet; } @@ -55,9 +55,13 @@ gnumeric_sheet_move_cursor_horizontal (GnumericSheet *sheet, int count) int new_left; new_left = item_cursor->start_col + count; + + if (new_left < 0) + return; if (new_left < sheet->top_col){ - g_warning ("scroll grip left"); + g_warning ("do scroll\n"); + return; } if (new_left < 0) @@ -75,12 +79,14 @@ gnumeric_sheet_move_cursor_vertical (GnumericSheet *sheet, int count) int new_top; new_top = item_cursor->start_row + count; - if (new_top < sheet->top_row){ - g_warning ("scroll grid up"); - } if (new_top < 0) - new_top = 0; + return; + + if (new_top < sheet->top_row){ + g_warning ("do scroll\n"); + return; + } item_cursor_set_bounds (item_cursor, item_cursor->start_col, item_cursor->end_col, @@ -92,8 +98,6 @@ gnumeric_sheet_key (GtkWidget *widget, GdkEventKey *event) { GnumericSheet *sheet = GNUMERIC_SHEET (widget); - printf ("tecla\n"); - switch (event->keyval){ case GDK_Left: gnumeric_sheet_move_cursor_horizontal (sheet, -1); @@ -147,7 +151,7 @@ gnumeric_sheet_new (Sheet *sheet) "ItemCursor::Grid", gsheet->item_grid, NULL); gsheet->item_cursor = ITEM_CURSOR (item); - + widget = GTK_WIDGET (gsheet); return widget; @@ -158,7 +162,6 @@ gnumeric_sheet_realize (GtkWidget *widget) { if (GTK_WIDGET_CLASS (sheet_parent_class)->realize) (*GTK_WIDGET_CLASS (sheet_parent_class)->realize)(widget); - printf ("Window ID=%d\n", GDK_WINDOW_XWINDOW (widget->window)); } static void @@ -187,9 +190,6 @@ gnumeric_sheet_init (GnumericSheet *gsheet) GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS); GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_DEFAULT); - - printf ("idel_id=%d\n", canvas->idle_id); - printf ("pixs=%g\n", canvas->pixels_per_unit); } GtkType @@ -214,4 +214,3 @@ gnumeric_sheet_get_type (void) return gnumeric_sheet_type; } - diff --git a/src/gnumeric-canvas.h b/src/gnumeric-canvas.h index e0f28e41b06ce4024f794550638ba4e5e58ea310..3f5a91e1a9a3f36612ef7733818a44ec3acef810 100644 --- a/src/gnumeric-canvas.h +++ b/src/gnumeric-canvas.h @@ -3,6 +3,7 @@ #include "item-grid.h" #include "item-cursor.h" +#include "item-bar.h" #define GNUMERIC_TYPE_SHEET (gnumeric_sheet_get_type ()) #define GNUMERIC_SHEET(obj) (GTK_CHECK_CAST((obj), GNUMERIC_TYPE_SHEET, GnumericSheet)) @@ -13,11 +14,13 @@ typedef struct { GnomeCanvas canvas; Sheet *sheet; + ColType top_col; RowType top_row; ItemGrid *item_grid; ItemCursor *item_cursor; + ItemBar *item_bar_col; } GnumericSheet; GtkType gnumeric_sheet_get_type (void); diff --git a/src/gnumeric-sheet.c b/src/gnumeric-sheet.c index df24a25c2ce3dcf5263c087d2b841e9c04f78590..a3ea5d0d05957a2d1804cf65db55b85b04d930cc 100644 --- a/src/gnumeric-sheet.c +++ b/src/gnumeric-sheet.c @@ -44,7 +44,7 @@ gnumeric_sheet_create (Sheet *sheet) gsheet->sheet = sheet; gsheet->top_col = 0; gsheet->top_row = 0; - + return gsheet; } @@ -55,9 +55,13 @@ gnumeric_sheet_move_cursor_horizontal (GnumericSheet *sheet, int count) int new_left; new_left = item_cursor->start_col + count; + + if (new_left < 0) + return; if (new_left < sheet->top_col){ - g_warning ("scroll grip left"); + g_warning ("do scroll\n"); + return; } if (new_left < 0) @@ -75,12 +79,14 @@ gnumeric_sheet_move_cursor_vertical (GnumericSheet *sheet, int count) int new_top; new_top = item_cursor->start_row + count; - if (new_top < sheet->top_row){ - g_warning ("scroll grid up"); - } if (new_top < 0) - new_top = 0; + return; + + if (new_top < sheet->top_row){ + g_warning ("do scroll\n"); + return; + } item_cursor_set_bounds (item_cursor, item_cursor->start_col, item_cursor->end_col, @@ -92,8 +98,6 @@ gnumeric_sheet_key (GtkWidget *widget, GdkEventKey *event) { GnumericSheet *sheet = GNUMERIC_SHEET (widget); - printf ("tecla\n"); - switch (event->keyval){ case GDK_Left: gnumeric_sheet_move_cursor_horizontal (sheet, -1); @@ -147,7 +151,7 @@ gnumeric_sheet_new (Sheet *sheet) "ItemCursor::Grid", gsheet->item_grid, NULL); gsheet->item_cursor = ITEM_CURSOR (item); - + widget = GTK_WIDGET (gsheet); return widget; @@ -158,7 +162,6 @@ gnumeric_sheet_realize (GtkWidget *widget) { if (GTK_WIDGET_CLASS (sheet_parent_class)->realize) (*GTK_WIDGET_CLASS (sheet_parent_class)->realize)(widget); - printf ("Window ID=%d\n", GDK_WINDOW_XWINDOW (widget->window)); } static void @@ -187,9 +190,6 @@ gnumeric_sheet_init (GnumericSheet *gsheet) GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS); GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_DEFAULT); - - printf ("idel_id=%d\n", canvas->idle_id); - printf ("pixs=%g\n", canvas->pixels_per_unit); } GtkType @@ -214,4 +214,3 @@ gnumeric_sheet_get_type (void) return gnumeric_sheet_type; } - diff --git a/src/gnumeric-sheet.h b/src/gnumeric-sheet.h index e0f28e41b06ce4024f794550638ba4e5e58ea310..3f5a91e1a9a3f36612ef7733818a44ec3acef810 100644 --- a/src/gnumeric-sheet.h +++ b/src/gnumeric-sheet.h @@ -3,6 +3,7 @@ #include "item-grid.h" #include "item-cursor.h" +#include "item-bar.h" #define GNUMERIC_TYPE_SHEET (gnumeric_sheet_get_type ()) #define GNUMERIC_SHEET(obj) (GTK_CHECK_CAST((obj), GNUMERIC_TYPE_SHEET, GnumericSheet)) @@ -13,11 +14,13 @@ typedef struct { GnomeCanvas canvas; Sheet *sheet; + ColType top_col; RowType top_row; ItemGrid *item_grid; ItemCursor *item_cursor; + ItemBar *item_bar_col; } GnumericSheet; GtkType gnumeric_sheet_get_type (void); diff --git a/src/item-bar.c b/src/item-bar.c new file mode 100644 index 0000000000000000000000000000000000000000..0e1c6b7913a5e926d5ba267a9d5edd753afc7c50 --- /dev/null +++ b/src/item-bar.c @@ -0,0 +1,348 @@ +#include + +#include +#include "gnumeric.h" +#include "item-bar.h" +#include "item-debug.h" + +/* The signals we emit */ +enum { + ITEM_BAR_TEST, + ITEM_BAR_LAST_SIGNAL +}; +static guint item_bar_signals [ITEM_BAR_LAST_SIGNAL] = { 0 }; + +static GnomeCanvasItem *item_bar_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_SHEET, + ARG_ORIENTATION, + ARG_FIRST_ELEMENT +}; + +static void +item_bar_destroy (GtkObject *object) +{ + ItemBar *bar; + + bar = ITEM_BAR (object); + + if (GTK_OBJECT_CLASS (item_bar_parent_class)->destroy) + (*GTK_OBJECT_CLASS (item_bar_parent_class)->destroy)(object); +} + +static void +item_bar_realize (GnomeCanvasItem *item) +{ + ItemBar *item_bar; + GdkWindow *window; + GdkGC *gc; + + item_bar = ITEM_BAR (item); + window = GTK_WIDGET (item->canvas)->window; + + /* Configure our gc */ + item_bar->gc = gc = gdk_gc_new (window); + + item_bar->normal_cursor = gdk_cursor_new (GDK_ARROW); + if (item_bar->orientation == GTK_ORIENTATION_VERTICAL) + item_bar->change_cursor = gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW); + else + item_bar->change_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW); +} + +static void +item_bar_unrealize (GnomeCanvasItem *item) +{ + ItemBar *item_bar = ITEM_BAR (item); + + gdk_gc_unref (item_bar->gc); + gdk_cursor_destroy (item_bar->change_cursor); + gdk_cursor_destroy (item_bar->normal_cursor); +} + +static void +item_bar_reconfigure (GnomeCanvasItem *item) +{ + GnomeCanvas *canvas = item->canvas; + ItemBar *item_bar = ITEM_BAR (item); + + item->x1 = 0; + item->y1 = 0; + item->x2 = INT_MAX; + item->y2 = INT_MAX; + gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item); +} + +static char * +get_row_name (int n) +{ + static char x [32]; + + sprintf (x, "%d", n); + return x; +} + +static char * +get_col_name (int n) +{ + static char x [3]; + + g_assert (n < 256); + + if (n < 'z'-'a'){ + x [0] = n + 'A'; + x [1] = 0; + } else { + x [0] = (n / ('z'-'a')) + 'A'; + x [1] = (n % ('z'-'a')) + 'A'; + x [2] = 0; + } + return x; +} + +static void +bar_draw_cell (ItemBar *item_bar, GdkDrawable *drawable, char *str, int x1, int y1, int x2, int y2) +{ + GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item_bar)->canvas); + GdkFont *font = canvas->style->font; + int len, texth; + + len = gdk_string_width (font, str); + texth = gdk_string_height (font, str); + + gtk_draw_shadow (canvas->style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, + x1, y1, x2-x1, y2-y1); + gdk_draw_string (drawable, font, item_bar->gc, x1 + ((x2 - x1)-len)/2, + y2 - font->descent, + str); + +} + +static void +item_bar_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) +{ + ItemBar *item_bar = ITEM_BAR (item); + Sheet *sheet = item_bar->sheet; + ColInfo *ci; + RowInfo *ri; + int element, total, pixels, limit; + char *str; + + element = item_bar->first_element; + + if (item_bar->orientation == GTK_ORIENTATION_VERTICAL) + limit = y + height; + else + limit = x + width; + + total = 0; + do { + if (item_bar->orientation == GTK_ORIENTATION_VERTICAL){ + ri = sheet_get_row_info (sheet, element); + pixels = ri->height; + if (total+pixels >= y){ + str = get_row_name (element); + bar_draw_cell (item_bar, drawable, str, + -x, 1 + total - y, + item->canvas->width - x, + 1 + total + pixels - y); + } + } else { + ci = sheet_get_col_info (sheet, element); + pixels = ci->width; + if (total+pixels >= x){ + str = get_col_name (element); + bar_draw_cell (item_bar, drawable, str, + 1 + total - x, -y, + 1 + total + pixels - x, + item->canvas->height - y); + } + } + + total += pixels; + element++; + } while (total < limit); +} + +static double +item_bar_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, + GnomeCanvasItem **actual_item) +{ + *actual_item = item; + return 0.0; +} + +static void +item_bar_translate (GnomeCanvasItem *item, double dx, double dy) +{ + printf ("item_bar_translate %g, %g\n", dx, dy); +} + +static int +is_pointer_on_division (ItemBar *item_bar, int pos) +{ + ColInfo *ci; + RowInfo *ri; + int i, total, pixels; + + total = 0; + + for (i = item_bar->first_element; total < pos; i++){ + if (item_bar->orientation == GTK_ORIENTATION_VERTICAL){ + ri = sheet_get_row_info (item_bar->sheet, i); + pixels = ri->height; + } else { + ci = sheet_get_col_info (item_bar->sheet, i); + pixels = ci->width; + } + total += pixels; + + if ((total - 4 < pos) && (pos < total + 4)) + return 1; + } + return 0; +} + +static void +set_cursor (ItemBar *item_bar, int pos) +{ + GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item_bar)->canvas); + + if (is_pointer_on_division (item_bar, pos)) + gdk_window_set_cursor(canvas->window, item_bar->change_cursor); + else + gdk_window_set_cursor(canvas->window, item_bar->normal_cursor); +} + +static gint +item_bar_event (GnomeCanvasItem *item, GdkEvent *event) +{ + ItemBar *item_bar = ITEM_BAR (item); + int pos; + + switch (event->type){ + case GDK_ENTER_NOTIFY: + if (item_bar->orientation == GTK_ORIENTATION_VERTICAL) + pos = event->crossing.y; + else + pos = event->crossing.x; + set_cursor (item_bar, pos); + break; + + case GDK_MOTION_NOTIFY: + if (item_bar->orientation == GTK_ORIENTATION_VERTICAL) + pos = event->motion.y; + else + pos = event->motion.x; + set_cursor (item_bar, pos); + break; + default: + return FALSE; + } + return TRUE; +} + +/* + * Instance initialization + */ +static void +item_bar_init (ItemBar *item_bar) +{ + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_bar); + + item->x1 = 0; + item->y1 = 0; + item->x2 = 0; + item->y2 = 0; + + item_bar->first_element = 0; + item_bar->orientation = GTK_ORIENTATION_VERTICAL; +} + +static void +item_bar_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ItemBar *item_bar; + int v; + + item = GNOME_CANVAS_ITEM (o); + item_bar = ITEM_BAR (o); + + switch (arg_id){ + case ARG_SHEET: + item_bar->sheet = GTK_VALUE_POINTER (*arg); + break; + case ARG_ORIENTATION: + item_bar->orientation = GTK_VALUE_INT (*arg); + break; + case ARG_FIRST_ELEMENT: + v = GTK_VALUE_INT (*arg); + if (item_bar->first_element != v){ + item_bar->first_element = v; + g_warning ("ARG_FIRST_ELEMENT: do scroll\n"); + } + break; + default: + } + item_bar_reconfigure (item); +} + +/* + * ItemBar class initialization + */ +static void +item_bar_class_init (ItemBarClass *item_bar_class) +{ + GtkObjectClass *object_class; + GnomeCanvasItemClass *item_class; + + item_bar_parent_class = gtk_type_class (gnome_canvas_item_get_type()); + + object_class = (GtkObjectClass *) item_bar_class; + item_class = (GnomeCanvasItemClass *) item_bar_class; + + gtk_object_add_arg_type ("ItemBar::Sheet", GTK_TYPE_POINTER, + GTK_ARG_WRITABLE, ARG_SHEET); + gtk_object_add_arg_type ("ItemBar::Orientation", GTK_TYPE_INT, + GTK_ARG_WRITABLE, ARG_ORIENTATION); + gtk_object_add_arg_type ("ItemBar::First", GTK_TYPE_INT, + GTK_ARG_WRITABLE, ARG_FIRST_ELEMENT); + + object_class->set_arg = item_bar_set_arg; + + /* GnomeCanvasItem method overrides */ + item_class->realize = item_bar_realize; + item_class->unrealize = item_bar_unrealize; + item_class->reconfigure = item_bar_reconfigure; + item_class->draw = item_bar_draw; + item_class->point = item_bar_point; + item_class->translate = item_bar_translate; + item_class->event = item_bar_event; +} + +GtkType +item_bar_get_type (void) +{ + static GtkType item_bar_type = 0; + + if (!item_bar_type) { + GtkTypeInfo item_bar_info = { + "ItemBar", + sizeof (ItemBar), + sizeof (ItemBarClass), + (GtkClassInitFunc) item_bar_class_init, + (GtkObjectInitFunc) item_bar_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + item_bar_type = gtk_type_unique (gnome_canvas_item_get_type (), &item_bar_info); + } + + return item_bar_type; +} diff --git a/src/item-bar.h b/src/item-bar.h new file mode 100644 index 0000000000000000000000000000000000000000..d98f93bd32b4cacfddc6335f6a99efb2cd0b5df1 --- /dev/null +++ b/src/item-bar.h @@ -0,0 +1,24 @@ +#ifndef ITEM_BAR_H +#define ITEM_BAR_H + +#define ITEM_BAR(obj) (GTK_CHECK_CAST((obj), item_bar_get_type (), ItemBar)) +#define ITEM_BAR_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), item_bar_get_type ())) +#define IS_ITEM_BAR(o) (GTK_CHECK_TYPE((o), item_bar_get_type ())) + +typedef struct { + GnomeCanvasItem canvas_item; + Sheet *sheet; + int first_element; + GtkOrientation orientation; /* horizontal, vertical */ + GdkGC *gc; /* Draw gc */ + GdkCursor *normal_cursor; + GdkCursor *change_cursor; +} ItemBar; + +GtkType item_bar_get_type (void); + +typedef struct { + GnomeCanvasItemClass parent_class; +} ItemBarClass; + +#endif diff --git a/src/item-cursor.c b/src/item-cursor.c index d48560213da89a5a42be216d5738507e971abf7b..372afe4d30f8f814bf6d8b5410aca14117260a70 100644 --- a/src/item-cursor.c +++ b/src/item-cursor.c @@ -39,12 +39,16 @@ item_cursor_realize (GnomeCanvasItem *item) ItemCursor *item_cursor; GdkWindow *window; GdkGC *gc; + GdkColor black; item_cursor = ITEM_CURSOR (item); window = GTK_WIDGET (item->canvas)->window; gc = item_cursor->gc = gdk_gc_new (window); - gdk_gc_set_function (gc, GDK_INVERT); +#if 0 + gdk_color_black (item->canvas->colormap, &black); + gdk_gc_set_foreground (gc, &black); +#endif } static void @@ -59,7 +63,6 @@ item_cursor_unrealize (GnomeCanvasItem *item) static void item_cursor_reconfigure (GnomeCanvasItem *item) { - g_warning ("item_cursor_reconfigure\n"); } static void @@ -73,17 +76,17 @@ item_cursor_get_pixel_coords (ItemCursor *item_cursor, int *x, int *y, int *w, i *w = sheet_col_get_distance (sheet, item_cursor->start_col, item_cursor->end_col); *h = sheet_row_get_distance (sheet, item_cursor->start_row, item_cursor->end_row); - } static void item_cursor_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { ItemCursor *item_cursor = ITEM_CURSOR (item); - Sheet *sheet; int xd, yd, dx, dy; int cursor_width, cursor_height; - GdkPoint points [5]; + GdkPoint points [40]; + int draw_external, draw_internal, draw_handle, draw_center; + int remove; item_cursor_get_pixel_coords (item_cursor, &xd, &yd, &cursor_width, &cursor_height); @@ -91,27 +94,77 @@ item_cursor_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, in dx = xd - x; dy = yd - y; + draw_external = draw_internal = draw_handle = draw_center = 0; switch (item_cursor->style){ case ITEM_CURSOR_SELECTION: - gdk_gc_set_line_attributes (item_cursor->gc, 3, - GDK_LINE_SOLID, GDK_CAP_PROJECTING, - GDK_JOIN_MITER); - points [0].x = xd + cursor_width - 1; - points [0].y = yd + cursor_height + 4; + draw_internal = 1; + draw_external = 1; + draw_center = 0; + draw_handle = 1; + break; + + case ITEM_CURSOR_EDITING: + draw_internal = 0; + draw_handle = 0; + draw_center = 0; + draw_external = 1; + + case ITEM_CURSOR_ANTED: + draw_internal = 0; + draw_handle = 0; + draw_center = 1; + draw_external = 0; + }; + + if (draw_handle) + remove = 5; + else + remove = 0; + + if (draw_external){ + points [0].x = dx + cursor_width + 1; + points [0].y = dy + cursor_height + 1 - remove; points [1].x = points [0].x; - points [1].y = yd - 1; - points [2].x = xd - 1; - points [2].y = points [1].y; - points [3].x = points [2].x; - points [3].y = yd + cursor_height + 1; - points [4].x = xd + cursor_width - 4; + points [1].y = dy - 1; + points [2].x = dx - 1; + points [2].y = dy - 1; + points [3].x = dx - 1; + points [3].y = dy + cursor_height + 1; + points [4].x = dx + cursor_width + 1 - remove; points [4].y = points [3].y; - gdk_draw_lines (drawable, item_cursor->gc, points, 5); + } + + if (draw_external && draw_internal){ + points [0].x -= 2; + points [1].x -= 2; + points [1].y += 2; + points [2].x += 2; + points [2].y += 2; + points [3].x += 2; + points [3].y -= 2; + points [4].y -= 2; + gdk_draw_lines (drawable, item_cursor->gc, points, 5); + } - default: + if (draw_handle){ + gdk_draw_rectangle (drawable, item_cursor->gc, TRUE, + dx + cursor_width - 2, + dy + cursor_height - 2, + 2, 2); + gdk_draw_rectangle (drawable, item_cursor->gc, TRUE, + dx + cursor_width + 1, + dy + cursor_height - 2, + 2, 2); + gdk_draw_rectangle (drawable, item_cursor->gc, TRUE, + dx + cursor_width - 2, + dy + cursor_height + 1, + 2, 2); + gdk_draw_rectangle (drawable, item_cursor->gc, TRUE, + dx + cursor_width + 1, + dy + cursor_height + 1, + 2, 2); } - } static void @@ -121,7 +174,7 @@ item_cursor_request_redraw (ItemCursor *item_cursor) int x, y, w, h; item_cursor_get_pixel_coords (item_cursor, &x, &y, &w, &h); - gnome_canvas_request_redraw (canvas, x-1, y-1, x+w+1, y+h+1); + gnome_canvas_request_redraw (canvas, x - 2, y - 2, x + w + 5, y + h + 5); } void diff --git a/src/item-grid.c b/src/item-grid.c index b9baeba3a95b2ef54023afb28268dc86a3d6f1c8..4e9cf0b9f294adb9813aaf2e5cfd2500a3933bc9 100644 --- a/src/item-grid.c +++ b/src/item-grid.c @@ -3,6 +3,7 @@ #include #include "gnumeric.h" #include "item-grid.h" +#include "item-debug.h" /* The signals we emit */ enum { @@ -81,7 +82,15 @@ item_grid_unrealize (GnomeCanvasItem *item) static void item_grid_reconfigure (GnomeCanvasItem *item) { - g_warning ("item_grid_reconfigure\n"); + GnomeCanvas *canvas = item->canvas; + ItemGrid *item_grid = ITEM_GRID (item); + + item->x1 = 0; + item->y1 = 0; + item->x2 = INT_MAX; + item->y2 = INT_MAX; + + gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item); } /* @@ -151,12 +160,23 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int { ItemGrid *item_grid = ITEM_GRID (item); Sheet *sheet = item_grid->sheet; - int end_x; - int end_y; - int paint_col, paint_row, col, row; + GdkGC *grid_gc = item_grid->grid_gc; + int end_x, end_y; + int paint_col, paint_row; + int col, row; int x_paint, y_paint; int diff_x, diff_y; + if (x < 0){ + g_warning ("x < 0\n"); + return; + } + + if (y < 0){ + g_warning ("y < 0\n"); + return; + } + paint_col = find_col (item_grid, x, &x_paint); paint_row = find_row (item_grid, y, &y_paint); #ifdef DEBUG_EXPOSES @@ -170,6 +190,31 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int diff_y = y - y_paint; end_y = height + diff_y; + /* 1. The default background */ + gdk_draw_rectangle (drawable, item_grid->fill_gc, TRUE, + 0, 0, width, height); + + /* 2. the grids */ + for (x_paint = -diff_x; x_paint < end_x; col++){ + ColInfo *ci; + + ci = sheet_get_col_info (sheet, col); + g_assert (ci->width != 0); + + gdk_draw_line (drawable, grid_gc, x_paint, 0, x_paint, height); + + x_paint += ci->width; + } + + row = paint_row; + for (y_paint = -diff_y; y_paint < end_y; row++){ + RowInfo *ri; + + ri = sheet_get_row_info (sheet, row); + gdk_draw_line (drawable, grid_gc, 0, y_paint, width, y_paint); + y_paint += ri->height; + } + for (x_paint = -diff_x; x_paint < end_x; col++){ ColInfo *ci; @@ -180,19 +225,25 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int RowInfo *ri; ri = sheet_get_row_info (sheet, row); +#if 0 + item_debug_cross (drawable, item_grid->grid_gc, + x_paint, y_paint, + x_paint + ci->width, + y_paint + ri->height); item_grid_draw_cell (drawable, item_grid, x_paint, y_paint, x_paint + ci->width, y_paint + ri->height); - +#endif y_paint += ri->height; } x_paint += ci->width; } + #undef DEBUG_EXPOSES #ifdef DEBUG_EXPOSES - cross (drawable, item_grid->grid_gc, 0, 0, width, height); + item_debug_cross (drawable, item_grid->grid_gc, 0, 0, width, height); #endif } @@ -226,23 +277,16 @@ static void item_grid_init (ItemGrid *item_grid) { GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_grid); - + item->x1 = 0; item->y1 = 0; - - /* A big number for now */ - item->x2 = 9999999; - item->y2 = 9999999; + item->x2 = 0; + item->y2 = 0; item_grid->left_col = 0; item_grid->top_row = 0; item_grid->top_offset = 0; item_grid->left_offset = 0; - -#if 0 - gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), - item); -#endif } static void @@ -255,7 +299,7 @@ item_grid_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) item_grid = ITEM_GRID (o); switch (arg_id){ - ARG_SHEET: + case ARG_SHEET: item_grid->sheet = GTK_VALUE_POINTER (*arg); break; } diff --git a/src/sheet.c b/src/sheet.c index 5019d06bf5a8fbb9149edeabd1426d9881eef1ce..a7155396644881fb77773249f52a882d36186640 100644 --- a/src/sheet.c +++ b/src/sheet.c @@ -2,6 +2,82 @@ #include "gnumeric.h" #include "gnumeric-sheet.h" +static void +sheet_init_dummy_stuff (Sheet *sheet) +{ + int x, y; + ColInfo c, *cp; + RowInfo *rp; + + c.col = 0; + c.style = NULL; + c.unit_width = 40; + c.width = 0; + c.left_margin = 0; + c.right_margin = 0; + + sheet->default_col_style = c; + + /* Initialize some of the columns */ + for (x = 0; x < 40; x += 2){ + cp = g_new0 (ColInfo, 1); + + *cp = c; + cp->col = x; + cp->unit_width = (x+1) * 30; + sheet->cols_info = g_list_append (sheet->cols_info, cp); + } + + /* Rows, we keep them consistent for now */ + sheet->default_row_style.row = 0; + sheet->default_row_style.style = NULL; + sheet->default_row_style.unit_height = 20; + sheet->default_row_style.height = 0; + sheet->default_row_style.top_margin = 0; + sheet->default_row_style.bottom_margin = 0; + + for (y = 0; y < 6; y += 2){ + rp = g_new0 (RowInfo, 1); + + *rp = sheet->default_row_style; + rp->row = y; + rp->unit_height = (20 * (y + 1)); + sheet->rows_info = g_list_append (sheet->rows_info, rp); + } +} + +static GtkWidget * +new_canvas_bar (Sheet *sheet, GtkOrientation o, GnomeCanvasItem **itemp) +{ + GnomeCanvasGroup *group; + GnomeCanvasItem *item; + GtkWidget *canvas; + int w, h; + + canvas = gnome_canvas_new ( + gtk_widget_get_default_visual (), + gtk_widget_get_default_colormap ()); + + if (o == GTK_ORIENTATION_VERTICAL){ + w = 60; + h = 1; + } else { + w = 1; + h = 20; + } + gnome_canvas_set_size (GNOME_CANVAS (canvas), w, h); + group = GNOME_CANVAS_GROUP (GNOME_CANVAS (canvas)->root); + item = gnome_canvas_item_new (GNOME_CANVAS (canvas), group, + item_bar_get_type (), + "ItemBar::Sheet", sheet, + "ItemBar::Orientation", o, + "ItemBar::First", 0, + NULL); + *itemp = GNOME_CANVAS_ITEM (item); + gtk_widget_show (canvas); + return canvas; +} + Sheet * sheet_new (Workbook *wb, char *name) { @@ -10,35 +86,141 @@ sheet_new (Workbook *wb, char *name) sheet = g_new0 (Sheet, 1); sheet->parent_workbook = wb; sheet->name = g_strdup (name); + sheet->last_zoom_factor_used = -1.0; + sheet->toplevel = gtk_table_new (0, 0, 0); + + /* Dummy initialization */ + sheet_init_dummy_stuff (sheet); + sheet->sheet_view = gnumeric_sheet_new (sheet); gtk_widget_show (sheet->sheet_view); + gtk_widget_show (sheet->toplevel); + + gtk_table_attach (GTK_TABLE (sheet->toplevel), sheet->sheet_view, + 1, 2, 1, 2, + GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); + + /* Column canvas */ + sheet->col_canvas = new_canvas_bar (sheet, GTK_ORIENTATION_HORIZONTAL, &sheet->col_item); + gtk_table_attach (GTK_TABLE (sheet->toplevel), sheet->col_canvas, + 1, 2, 0, 1, + GTK_FILL | GTK_EXPAND, 0, 0, 0); + + /* Row canvas */ + sheet->row_canvas = new_canvas_bar (sheet, GTK_ORIENTATION_VERTICAL, &sheet->row_item); + gtk_table_attach (GTK_TABLE (sheet->toplevel), sheet->row_canvas, + 0, 1, 1, 2, + 0, GTK_FILL | GTK_EXPAND, 0, 0); + sheet_set_zoom_factor (sheet, 1.0); return sheet; } +void +sheet_foreach_col (Sheet *sheet, sheet_col_callback callback, void *user_data) +{ + GList *l = sheet->cols_info; + + /* Invoke the callback for the default style */ + (*callback)(sheet, &sheet->default_col_style, user_data); + + /* And then for the rest */ + while (l){ + (*callback)(sheet, l->data, user_data); + l = l->next; + } +} + +void +sheet_foreach_row (Sheet *sheet, sheet_row_callback callback, void *user_data) +{ + GList *l = sheet->rows_info; + + /* Invoke the callback for the default style */ + (callback)(sheet, &sheet->default_row_style, user_data); + + /* And then for the rest */ + while (l){ + (*callback)(sheet, l->data, user_data); + l = l->next; + } +} + +static void +sheet_compute_col_size (Sheet *sheet, ColInfo *ci, void *data) +{ + double pix_per_unit = sheet->last_zoom_factor_used; + + ci->width = (ci->unit_width * pix_per_unit) + + ci->left_margin + ci->right_margin + 1; +} + +static void +sheet_compute_row_size (Sheet *sheet, RowInfo *ri, void *data) +{ + double pix_per_unit = sheet->last_zoom_factor_used; + + ri->height = (ri->unit_height * pix_per_unit) + + ri->top_margin + ri->bottom_margin + 1; +} + +/* + * Updates the values used for display after a zoom change + */ +static void +sheet_reconfigure_zoom (Sheet *sheet) +{ + GnomeCanvas *gnumeric_canvas = GNOME_CANVAS (sheet->sheet_view); + double pixels_per_unit = gnumeric_canvas->pixels_per_unit; + + if (pixels_per_unit == sheet->last_zoom_factor_used) + return; + + sheet->last_zoom_factor_used = pixels_per_unit; + sheet_foreach_col (sheet, sheet_compute_col_size, NULL); + sheet_foreach_row (sheet, sheet_compute_row_size, NULL); +} + +void +sheet_set_zoom_factor (Sheet *sheet, double factor) +{ + gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (sheet->sheet_view), factor); + gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (sheet->col_canvas), factor); + gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (sheet->row_canvas), factor); + sheet_reconfigure_zoom (sheet); + gnome_canvas_scroll_to (GNOME_CANVAS (sheet->sheet_view), 0, 0); + gnome_canvas_scroll_to (GNOME_CANVAS (sheet->col_canvas), 0, 0); + gnome_canvas_scroll_to (GNOME_CANVAS (sheet->row_canvas), 0, 0); +} + ColInfo * sheet_get_col_info (Sheet *sheet, int col) { - static ColInfo c; + GList *l = sheet->cols_info; - c.col = col; - c.width = (col + 1) * 15; - c.style = NULL; + for (; l; l = l->next){ + ColInfo *ci = l->data; - return &c; + if (ci->col == col) + return ci; + } + + return &sheet->default_col_style; } RowInfo * sheet_get_row_info (Sheet *sheet, int row) { - static RowInfo r; + GList *l = sheet->rows_info; - /* Just a stub for now */ - r.row = row; - r.height = 20; - r.style = NULL; + for (; l; l = l->next){ + RowInfo *ri = l->data; + + if (ri->row == row) + return ri; + } - return &r; + return &sheet->default_row_style; } /* @@ -51,7 +233,10 @@ sheet_col_get_distance (Sheet *sheet, int from_col, int to_col) int pixels = 0, i; g_assert (from_col <= to_col); - + + /* This can be optimized, yes, but the implementation + * of the RowInfo, ColInfo sets is going to change anyways + */ for (i = from_col; i < to_col; i++){ ci = sheet_get_col_info (sheet, i); pixels += ci->width; @@ -70,9 +255,24 @@ sheet_row_get_distance (Sheet *sheet, int from_row, int to_row) g_assert (from_row <= to_row); + /* This can be optimized, yes, but the implementation + * of the RowInfo, ColInfo sets is going to change anyways + */ for (i = from_row; i < to_row; i++){ ri = sheet_get_row_info (sheet, i); pixels += ri->height; } return pixels; } + +void +sheet_get_cell_bounds (Sheet *sheet, ColType col, RowType row, int *x, int *y, int *w, int *h) +{ + GnumericSheet *gsheet = GNUMERIC_SHEET (sheet->sheet_view); + + *x = sheet_col_get_distance (sheet, gsheet->top_col, col); + *y = sheet_row_get_distance (sheet, gsheet->top_row, row); + + *w = sheet_col_get_distance (sheet, col, col + 1); + *h = sheet_row_get_distance (sheet, row, row + 1); +} diff --git a/src/sheet.h b/src/sheet.h index b5f26d1808942c0bd4ddd0cb1b6932f0348733bc..2306bf060b945875edc8b043417fd08d448d7d59 100644 --- a/src/sheet.h +++ b/src/sheet.h @@ -5,18 +5,6 @@ typedef GList ColStyleList; struct Workbook; -typedef struct { - RowType row; - int height; - Style *style; /* if existant, this row style */ -} RowInfo; - -typedef struct { - ColType col; - int width; - Style *style; /* if existant, this column style */ -} ColInfo; - typedef struct { GtkWidget *toplevel; GtkWidget *notebook; @@ -27,7 +15,11 @@ typedef struct { typedef struct { Workbook *parent_workbook; + GtkWidget *toplevel, *col_canvas, *row_canvas; GtkWidget *sheet_view; + GnomeCanvasItem *col_item, *row_item; + + double last_zoom_factor_used; char *name; Style style; @@ -40,12 +32,18 @@ typedef struct { void *contents; } Sheet; +typedef void (*sheet_col_callback)(Sheet *sheet, ColInfo *ci, void *user_data); +typedef void (*sheet_row_callback)(Sheet *sheet, RowInfo *ci, void *user_data); + Sheet *sheet_new (Workbook *wb, char *name); ColInfo *sheet_get_col_info (Sheet *, int col); RowInfo *sheet_get_row_info (Sheet *, int row); int sheet_col_get_distance (Sheet *sheet, int from_col, int to_col); int sheet_row_get_distance (Sheet *sheet, int from_row, int to_row); - +void sheet_foreach_col (Sheet *sheet, sheet_col_callback, void *user_data); +void sheet_foreach_row (Sheet *sheet, sheet_row_callback, void *user_data); +void sheet_set_zoom_factor (Sheet *sheet, double factor); +void sheet_get_cell_bounds (Sheet *sheet, ColType col, RowType row, int *x, int *y, int *w, int *h); Workbook *workbook_new (void); Workbook *workbook_new_with_sheets (int sheet_count); diff --git a/src/workbook.c b/src/workbook.c index f1f7199ff89342b8816073c2650bbdaedcef4104..721af53fbf653f04265c06455c07be2f888a31a4 100644 --- a/src/workbook.c +++ b/src/workbook.c @@ -40,14 +40,63 @@ workbook_new (void) return wb; } +static void +zoom_in (GtkButton *b, Sheet *sheet) +{ + double pix = GNOME_CANVAS (sheet->sheet_view)->pixels_per_unit; + + if (pix < 10.0){ + pix += 0.5; + sheet_set_zoom_factor (sheet, pix); + } +} + +static void +zoom_out (GtkButton *b, Sheet *sheet) +{ + double pix = GNOME_CANVAS (sheet->sheet_view)->pixels_per_unit; + + if (pix > 1.0){ + pix -= 0.5; + sheet_set_zoom_factor (sheet, pix); + } +} + +static void +buttons (Sheet *sheet, GtkTable *table) +{ + GtkWidget *b; + + b = gtk_button_new_with_label ("Zoom out"); + gtk_table_attach (table, b, + 0, 1, 1, 2, 0, 0, 0, 0); + gtk_signal_connect (GTK_OBJECT (b), "clicked", + GTK_SIGNAL_FUNC (zoom_out), sheet); + + b = gtk_button_new_with_label ("Zoom in"); + gtk_table_attach (table, b, + 1, 2, 1, 2, 0, 0, 0, 0); + gtk_signal_connect (GTK_OBJECT (b), "clicked", + GTK_SIGNAL_FUNC (zoom_in), sheet); + +} + void workbook_attach_sheet (Workbook *wb, Sheet *sheet) { + GtkWidget *t; + g_hash_table_insert (wb->sheets, sheet->name, sheet); + + t = gtk_table_new (0, 0, 0); + gtk_table_attach (GTK_TABLE (t), sheet->toplevel, + 0, 3, 0, 1, + GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); + buttons (sheet, GTK_TABLE (t)); + gtk_widget_show_all (t); gtk_notebook_append_page (GTK_NOTEBOOK (wb->notebook), - sheet->sheet_view, - gtk_label_new (sheet->name)); - gtk_widget_grab_focus (GTK_WIDGET (sheet->sheet_view)); + t, gtk_label_new (sheet->name)); + gtk_widget_grab_focus (GTK_WIDGET (sheet->toplevel)); } Workbook *