33 #include <libgnomecanvas/libgnomecanvas.h>
35 #include "gnucash-sheet.h"
36 #include "gnucash-sheetP.h"
37 #include "gnucash-grid.h"
38 #include "gnucash-color.h"
39 #include "gnucash-style.h"
44 GnomeCanvasItem canvas_item;
62 GdkColor default_color;
68 GnomeCanvasItemClass parent_class;
71 static GnomeCanvasItem *gnucash_grid_parent_class;
82 gnucash_grid_realize (GnomeCanvasItem *item)
88 if (GNOME_CANVAS_ITEM_CLASS (gnucash_grid_parent_class)->realize)
89 (GNOME_CANVAS_ITEM_CLASS
90 (gnucash_grid_parent_class)->realize)(item);
92 gnucash_grid = GNUCASH_GRID (item);
93 window = GTK_WIDGET (item->canvas)->window;
96 gnucash_grid->grid_gc = gc = gdk_gc_new (window);
97 gnucash_grid->fill_gc = gdk_gc_new (window);
98 gnucash_grid->gc = gdk_gc_new (window);
101 gnucash_grid->background = gn_white;
102 gnucash_grid->grid_color = gn_black;
103 gnucash_grid->default_color = gn_black;
105 gdk_gc_set_foreground (gc, &gnucash_grid->grid_color);
106 gdk_gc_set_background (gc, &gnucash_grid->background);
108 gdk_gc_set_foreground (gnucash_grid->fill_gc,
109 &gnucash_grid->background);
110 gdk_gc_set_background (gnucash_grid->fill_gc,
111 &gnucash_grid->grid_color);
116 gnucash_grid_unrealize (GnomeCanvasItem *item)
120 if (gnucash_grid->grid_gc != NULL)
122 g_object_unref(gnucash_grid->grid_gc);
123 gnucash_grid->grid_gc = NULL;
126 if (gnucash_grid->fill_gc != NULL)
128 g_object_unref(gnucash_grid->fill_gc);
129 gnucash_grid->fill_gc = NULL;
132 if (gnucash_grid->gc != NULL)
134 g_object_unref(gnucash_grid->gc);
135 gnucash_grid->gc = NULL;
138 if (GNOME_CANVAS_ITEM_CLASS (gnucash_grid_parent_class)->unrealize)
139 (*GNOME_CANVAS_ITEM_CLASS
140 (gnucash_grid_parent_class)->unrealize)(item);
145 gnucash_grid_update (GnomeCanvasItem *item,
double *affine,
146 ArtSVP *clip_path,
int flags)
148 if (GNOME_CANVAS_ITEM_CLASS (gnucash_grid_parent_class)->update)
149 (* GNOME_CANVAS_ITEM_CLASS (gnucash_grid_parent_class)->update)
150 (item, affine, clip_path, flags);
154 item->x2 = INT_MAX / 2 - 1;
155 item->y2 = INT_MAX / 2 - 1;
169 gnucash_grid_find_block_by_pixel (
GnucashGrid *grid,
176 g_return_val_if_fail(y >= 0, NULL);
177 g_return_val_if_fail(x >= 0, NULL);
181 block = gnucash_sheet_get_block (grid->sheet, vc_loc);
185 if (block->visible &&
186 y >= block->origin_y &&
187 y < block->origin_y + block->style->dimensions->height)
190 vcell_loc->virt_row = vc_loc.virt_row;
195 while (vc_loc.virt_row < grid->sheet->num_virt_rows);
197 if (vc_loc.virt_row == grid->sheet->num_virt_rows)
202 block = gnucash_sheet_get_block (grid->sheet, vc_loc);
206 if (block->visible &&
207 x >= block->origin_x &&
208 x < block->origin_x + block->style->dimensions->width)
211 vcell_loc->virt_col = vc_loc.virt_col;
216 while (vc_loc.virt_col < grid->sheet->num_virt_cols);
218 if (vc_loc.virt_col == grid->sheet->num_virt_cols)
225 gnucash_grid_find_cell_by_pixel (
GnucashGrid *grid, gint x, gint y,
234 g_return_val_if_fail (virt_loc != NULL, FALSE);
236 block = gnucash_sheet_get_block (grid->sheet, virt_loc->vcell_loc);
241 x -= block->origin_x;
242 y -= block->origin_y;
244 style = block->style;
250 cd = gnucash_style_get_cell_dimensions (style, row, 0);
252 if (y >= cd->origin_y && y < cd->origin_y + cd->pixel_height)
257 while (row < style->nrows);
259 if (row == style->nrows)
264 cd = gnucash_style_get_cell_dimensions (style, row, col);
266 if (x >= cd->origin_x && x < cd->origin_x + cd->pixel_width)
271 while (col < style->ncols);
273 if (col == style->ncols)
277 virt_loc->phys_row_offset = row;
279 virt_loc->phys_col_offset = col;
285 gnucash_grid_find_loc_by_pixel (
GnucashGrid *grid, gint x, gint y,
290 if (virt_loc == NULL)
293 block = gnucash_grid_find_block_by_pixel (grid, x, y,
294 &virt_loc->vcell_loc);
298 return gnucash_grid_find_cell_by_pixel (grid, x, y, virt_loc);
302 draw_cell_line (GdkDrawable *drawable,
303 GdkGC *gc, GdkColor *bg_color,
304 int x1,
int y1,
int x2,
int y2,
305 PhysicalCellBorderLineStyle style);
308 draw_cell_line (GdkDrawable *drawable,
309 GdkGC *gc, GdkColor *bg_color,
310 int x1,
int y1,
int x2,
int y2,
311 PhysicalCellBorderLineStyle style)
317 case CELL_BORDER_LINE_NONE:
321 case CELL_BORDER_LINE_LIGHT:
322 fg_color = &gn_light_gray;
325 case CELL_BORDER_LINE_NORMAL:
326 case CELL_BORDER_LINE_HEAVY:
327 fg_color = &gn_black;
330 case CELL_BORDER_LINE_HIGHLIGHT:
338 gdk_gc_set_foreground (gc, fg_color);
339 gdk_draw_line (drawable, gc, x1, y1, x2, y2);
349 gnucash_sheet_get_borders (sheet, virt_loc, borders);
355 gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
356 borders->top = MAX (borders->top, neighbor.bottom);
363 gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
364 borders->bottom = MAX (borders->bottom, neighbor.top);
369 v_loc.phys_col_offset--;
370 if (gnc_table_virtual_loc_valid (sheet->table, v_loc, TRUE))
372 gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
373 borders->left = MAX (borders->left, neighbor.right);
378 v_loc.phys_col_offset++;
379 if (gnc_table_virtual_loc_valid (sheet->table, v_loc, TRUE))
381 gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
382 borders->right = MAX (borders->right, neighbor.left);
387 gnucash_draw_hatching (GdkDrawable *drawable, GdkGC *gc,
388 int x,
int y,
int width,
int height)
390 gdk_gc_set_foreground (gc, &gn_light_gray);
392 gdk_draw_rectangle (drawable, gc, FALSE,
393 x + 2, y + 2, height / 3, height / 3);
395 gdk_draw_line (drawable, gc,
396 x + 2, y + 2 + height / 3, x + 2 + height / 3, y + 2);
398 gdk_draw_line (drawable, gc,
399 x + 2, y + 2, x + 2 + height / 3, y + 2 + height / 3);
402 #ifdef READONLY_LINES_WITH_CHANGED_FG_COLOR
407 static guint8 inc_intensity_byte(guint8 input,
int numerator,
int denominator)
409 guint8 result_inv, result;
410 guint8 input_inv = 0xff - input;
411 result_inv = (input_inv * numerator) / denominator;
412 result = 0xff - result_inv;
419 static guint32 inc_intensity_10percent(guint32 argb)
422 (inc_intensity_byte((argb & 0x00FF0000) >> 16, 8, 10) << 16)
423 + (inc_intensity_byte((argb & 0x0000FF00) >> 8, 8, 10) << 8)
424 + (inc_intensity_byte(argb & 0x000000FF, 8, 10));
433 static guint8 dec_intensity_byte(guint8 input,
int numerator,
int denominator)
436 result = (input * numerator) / denominator;
442 static guint32 dec_intensity_10percent(guint32 argb)
447 (dec_intensity_byte((argb & 0x00FF0000) >> 16, 9, 10) << 16)
448 + (dec_intensity_byte((argb & 0x0000FF00) >> 8, 9, 10) << 8)
449 + (dec_intensity_byte(argb & 0x000000FF, 9, 10));
457 GdkDrawable *drawable,
458 int x,
int y,
int width,
int height)
464 PangoContext *context;
465 PangoFontDescription *font;
466 PangoRectangle logical_rect;
472 guint32 argb, color_type;
475 gdk_gc_set_background (grid->gc, &gn_white);
477 if (grid->sheet->use_theme_colors)
479 color_type = gnc_table_get_gtkrc_bg_color (table, virt_loc,
481 bg_color = get_gtkrc_color(grid->sheet, color_type);
485 argb = gnc_table_get_bg_color (table, virt_loc, &hatching);
487 if ((virt_loc.phys_row_offset == (block->style->nrows - 1))
488 && (table->model->dividing_row_upper >= 0)
489 && (virt_loc.vcell_loc.virt_row < table->model->dividing_row_upper))
491 argb = dec_intensity_10percent(argb);
493 bg_color = gnucash_color_argb_to_gdk (argb);
496 gdk_gc_set_foreground (grid->gc, bg_color);
497 gdk_draw_rectangle (drawable, grid->gc, TRUE,
498 x + 1, y + 1, width - 1, height - 1);
500 get_cell_borders (grid->sheet, virt_loc, &borders);
503 draw_cell_line (drawable, grid->gc, bg_color,
504 borders.top >= borders.left ? x : x + 1,
506 (borders.top >= borders.right ?
507 x + width : x + width - 1),
512 draw_cell_line (drawable, grid->gc, bg_color,
513 borders.bottom >= borders.left ? x : x + 1,
515 (borders.bottom >= borders.right ?
516 x + width : x + width - 1),
521 draw_cell_line (drawable, grid->gc, bg_color,
523 borders.left > borders.top ? y : y + 1,
525 (borders.left > borders.bottom ?
526 y + height : y + height - 1),
530 draw_cell_line (drawable, grid->gc, bg_color,
532 borders.right > borders.top ? y : y + 1,
534 (borders.right > borders.bottom ?
535 y + height : y + height - 1),
539 gnucash_draw_hatching (drawable, grid->gc,
540 x, y, width, height);
543 if ((virt_loc.phys_row_offset == 0) &&
544 (table->model->dividing_row_upper >= 0))
546 if (virt_loc.vcell_loc.virt_row == table->model->dividing_row_upper)
548 gdk_gc_set_foreground (grid->gc, &gn_red);
549 gdk_draw_line (drawable, grid->gc, x, y - 1, x + width, y - 1);
550 gdk_draw_line (drawable, grid->gc, x, y, x + width, y);
551 gdk_draw_line (drawable, grid->gc, x, y + 1, x + width, y + 1);
555 if ((virt_loc.phys_row_offset == (block->style->nrows - 1)) &&
556 (table->model->dividing_row_upper >= 0))
558 if (virt_loc.vcell_loc.virt_row ==
559 (table->model->dividing_row_upper - 1))
561 gdk_gc_set_foreground (grid->gc, &gn_red);
562 gdk_draw_line (drawable, grid->gc, x, y + height - 1,
563 x + width, y + height - 1);
564 gdk_draw_line (drawable, grid->gc, x, y + height,
565 x + width, y + height);
566 gdk_draw_line (drawable, grid->gc, x, y + height + 1,
567 x + width, y + height + 1);
572 if ((virt_loc.phys_row_offset == 0) &&
573 (table->model->dividing_row >= 0))
575 if (virt_loc.vcell_loc.virt_row == table->model->dividing_row)
577 gdk_gc_set_foreground (grid->gc, &gn_blue);
578 gdk_draw_line (drawable, grid->gc, x, y - 1, x + width, y - 1);
579 gdk_draw_line (drawable, grid->gc, x, y, x + width, y);
580 gdk_draw_line (drawable, grid->gc, x, y + 1, x + width, y + 1);
584 if ((virt_loc.phys_row_offset == (block->style->nrows - 1)) &&
585 (table->model->dividing_row >= 0))
587 if (virt_loc.vcell_loc.virt_row ==
588 (table->model->dividing_row - 1))
590 gdk_gc_set_foreground (grid->gc, &gn_blue);
591 gdk_draw_line (drawable, grid->gc, x, y + height - 1,
592 x + width, y + height - 1);
593 gdk_draw_line (drawable, grid->gc, x, y + height,
594 x + width, y + height);
595 gdk_draw_line (drawable, grid->gc, x, y + height + 1,
596 x + width, y + height + 1);
601 if ((virt_loc.phys_row_offset == 0) &&
602 (table->model->dividing_row_lower >= 0))
604 if (virt_loc.vcell_loc.virt_row == table->model->dividing_row_lower)
606 gdk_gc_set_foreground (grid->gc, &gn_blue);
607 gdk_draw_line (drawable, grid->gc, x, y - 1, x + width, y - 1);
608 gdk_draw_line (drawable, grid->gc, x, y, x + width, y);
609 gdk_draw_line (drawable, grid->gc, x, y + 1, x + width, y + 1);
613 if ((virt_loc.phys_row_offset == (block->style->nrows - 1)) &&
614 (table->model->dividing_row_lower >= 0))
616 if (virt_loc.vcell_loc.virt_row ==
617 (table->model->dividing_row_lower - 1))
619 gdk_gc_set_foreground (grid->gc, &gn_blue);
620 gdk_draw_line (drawable, grid->gc, x, y + height - 1,
621 x + width, y + height - 1);
622 gdk_draw_line (drawable, grid->gc, x, y + height,
623 x + width, y + height);
624 gdk_draw_line (drawable, grid->gc, x, y + height + 1,
625 x + width, y + height + 1);
629 text = gnc_table_get_entry (table, virt_loc);
631 layout = gtk_widget_create_pango_layout (GTK_WIDGET (grid->sheet), text);
633 pango_layout_set_width (layout, -1);
634 context = pango_layout_get_context (layout);
635 font = pango_font_description_copy (pango_context_get_font_description (context));
637 if (grid->sheet->use_theme_colors)
639 color_type = gnc_table_get_gtkrc_fg_color (table, virt_loc);
640 fg_color = get_gtkrc_color(grid->sheet, color_type);
644 argb = gnc_table_get_fg_color (table, virt_loc);
645 #ifdef READONLY_LINES_WITH_CHANGED_FG_COLOR
647 if ((virt_loc.phys_row_offset == (block->style->nrows - 1))
648 && (table->model->dividing_row_upper >= 0)
649 && (virt_loc.vcell_loc.virt_row < table->model->dividing_row_upper))
651 argb = inc_intensity_10percent(argb);
654 fg_color = gnucash_color_argb_to_gdk (argb);
657 gdk_gc_set_foreground (grid->gc, fg_color);
661 if ((table->current_cursor_loc.vcell_loc.virt_row ==
662 virt_loc.vcell_loc.virt_row) &&
663 (!text || strlen(text) == 0))
665 text = gnc_table_get_label (table, virt_loc);
666 if ((text == NULL) || (*text ==
'\0'))
668 gdk_gc_set_foreground (grid->gc, &gn_light_gray);
669 pango_layout_set_text (layout, text, strlen (text));
670 pango_font_description_set_style (font, PANGO_STYLE_ITALIC);
671 pango_context_set_font_description (context, font);
674 if ((text == NULL) || (*text ==
'\0'))
683 pango_layout_get_pixel_extents(layout,
687 rect.x = x + CELL_HPADDING;
688 rect.y = y + CELL_VPADDING;
689 rect.width = MAX (0, width - (2 * CELL_HPADDING));
690 rect.height = height - 2;
692 gdk_gc_set_clip_rectangle (grid->gc, &rect);
695 switch (gnc_table_get_align (table, virt_loc))
698 case CELL_ALIGN_LEFT:
702 case CELL_ALIGN_RIGHT:
703 x_offset = width - 2 * CELL_HPADDING - logical_rect.width;
706 case CELL_ALIGN_CENTER:
707 if (logical_rect.width > width - 2 * CELL_HPADDING)
710 x_offset = (width - 2 * CELL_HPADDING -
711 logical_rect.width) / 2;
717 gdk_draw_layout (drawable,
719 x + CELL_HPADDING + x_offset,
720 y + CELL_VPADDING + 1,
723 gdk_gc_set_clip_rectangle (grid->gc, NULL);
726 pango_font_description_set_style (font, PANGO_STYLE_NORMAL);
727 pango_context_set_font_description (context, font);
728 pango_font_description_free (font);
729 g_object_unref (layout);
736 GdkDrawable *drawable,
737 int x,
int y,
int width,
int height)
744 for ( virt_loc.phys_row_offset = 0;
745 virt_loc.phys_row_offset < block->style->nrows ;
746 virt_loc.phys_row_offset++ )
748 for ( virt_loc.phys_col_offset = 0;
749 virt_loc.phys_col_offset < block->style->ncols ;
750 virt_loc.phys_col_offset++ )
752 cd = gnucash_style_get_cell_dimensions
754 virt_loc.phys_row_offset,
755 virt_loc.phys_col_offset);
757 x_paint = block->origin_x + cd->origin_x;
758 if (x_paint > x + width)
761 y_paint = block->origin_y + cd->origin_y;
762 if (y_paint > y + height)
765 h = cd->pixel_height;
777 draw_cell (grid, block, virt_loc, drawable,
778 x_paint - x, y_paint - y, w, h);
784 gnucash_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
785 int x,
int y,
int width,
int height)
795 sheet_block = gnucash_grid_find_block_by_pixel (grid, x, y,
796 &virt_loc.vcell_loc);
797 if (!sheet_block || !sheet_block->style)
800 for ( ; virt_loc.vcell_loc.virt_row < grid->sheet->num_virt_rows;
801 virt_loc.vcell_loc.virt_row++ )
805 sheet_block = gnucash_sheet_get_block
806 (grid->sheet, virt_loc.vcell_loc);
808 if (!sheet_block || !sheet_block->style)
811 if (sheet_block->visible)
814 virt_loc.vcell_loc.virt_row++;
817 if (y + height < sheet_block->origin_y)
820 draw_block (grid, sheet_block, virt_loc, drawable,
821 x, y, width, height);
829 GnomeCanvasItem *item = GNOME_CANVAS_ITEM (grid);
837 grid->top_offset = 0;
838 grid->left_offset = 0;
843 gnucash_grid_set_property (GObject *
object,
854 GNUCASH_SHEET (g_value_get_object (value));
869 gnucash_grid_get_property (GObject *
object,
879 g_value_take_object (value, grid->sheet);
890 GObjectClass *object_class;
891 GnomeCanvasItemClass *item_class;
893 object_class = G_OBJECT_CLASS (klass);
894 item_class = GNOME_CANVAS_ITEM_CLASS (klass);
896 gnucash_grid_parent_class = g_type_class_peek_parent (klass);
899 object_class->set_property = gnucash_grid_set_property;
900 object_class->get_property = gnucash_grid_get_property;
903 item_class->update = gnucash_grid_update;
904 item_class->realize = gnucash_grid_realize;
905 item_class->unrealize = gnucash_grid_unrealize;
906 item_class->draw = gnucash_grid_draw;
909 g_object_class_install_property
912 g_param_spec_object (
"sheet",
921 gnucash_grid_get_type (
void)
923 static GType gnucash_grid_type = 0;
925 if (!gnucash_grid_type)
927 static const GTypeInfo gnucash_grid_info =
932 (GClassInitFunc) gnucash_grid_class_init,
937 (GInstanceInitFunc) gnucash_grid_init
941 g_type_register_static (gnome_canvas_item_get_type (),
943 &gnucash_grid_info, 0);
946 return gnucash_grid_type;
gboolean gnc_table_move_vertical_position(Table *table, VirtualLocation *virt_loc, int phys_row_offset)