GnuCash  5.6-150-g038405b370+
gnucash-sheet-private.c
1 /********************************************************************\
2  * This program is free software; you can redistribute it and/or *
3  * modify it under the terms of the GNU General Public License as *
4  * published by the Free Software Foundation; either version 2 of *
5  * the License, or (at your option) any later version. *
6  * *
7  * This program is distributed in the hope that it will be useful, *
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
10  * GNU General Public License for more details. *
11  * *
12  * You should have received a copy of the GNU General Public License*
13  * along with this program; if not, contact: *
14  * *
15  * Free Software Foundation Voice: +1-617-542-5942 *
16  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
17  * Boston, MA 02110-1301, USA gnu@gnu.org *
18  * *
19 \********************************************************************/
20 
21 /*
22  * The Gnucash Grid drawing functions
23  *
24  * The gnucash grid used to be a fully fledged object. However it has no
25  * intelligence of its own, so instead I have reduced it to just a complex
26  * drawing function.
27  * It specializes in drawing the non-editable parts of a gnucash sheet, that is
28  * - the rows and columns with proper backgrounds and borders
29  * - the text for each cell in the table
30  * - dividing lines (red and blue)
31  *
32  * This could have been addedi directly into gnucash_sheet.c, but is kept
33  * separate to not oversize that file.
34  */
35 
36 #include <config.h>
37 
38 #include <string.h>
39 
40 #include "gnucash-sheet.h"
41 #include "gnucash-sheetP.h"
42 #include "gnucash-color.h"
43 #include "gnucash-style.h"
44 #include "gnc-gtk-utils.h"
45 
46 /*
47  * Sets virt_row, virt_col to the block coordinates for the
48  * block containing pixel (x, y). Also sets o_x, o_y, to the
49  * pixel coordinates of the origin of the block. Returns
50  * TRUE if a block is found, FALSE if (x,y) is not
51  * in any block.
52  *
53  * All coordinates are with respect to the canvas origin.
54  */
55 static SheetBlock *
56 find_block_by_pixel (GnucashSheet *sheet,
57  gint x, gint y,
58  VirtualCellLocation *vcell_loc)
59 {
60  SheetBlock *block;
61  VirtualCellLocation vc_loc = { 1, 0 };
62 
63  g_return_val_if_fail (y >= 0, NULL);
64  g_return_val_if_fail (x >= 0, NULL);
65 
66  do
67  {
68  block = gnucash_sheet_get_block (sheet, vc_loc);
69  if (!block)
70  return NULL;
71 
72  if (block->visible &&
73  y >= block->origin_y &&
74  y < block->origin_y + block->style->dimensions->height)
75  {
76  if (vcell_loc)
77  vcell_loc->virt_row = vc_loc.virt_row;
78  break;
79  }
80  vc_loc.virt_row++;
81  }
82  while (vc_loc.virt_row < sheet->num_virt_rows);
83 
84  if (vc_loc.virt_row == sheet->num_virt_rows)
85  return NULL;
86 
87  do
88  {
89  block = gnucash_sheet_get_block (sheet, vc_loc);
90  if (!block)
91  return NULL;
92 
93  if (block->visible &&
94  x >= block->origin_x &&
95  x < block->origin_x + block->style->dimensions->width)
96  {
97  if (vcell_loc)
98  vcell_loc->virt_col = vc_loc.virt_col;
99  break;
100  }
101  vc_loc.virt_col++;
102  }
103  while (vc_loc.virt_col < sheet->num_virt_cols);
104 
105  if (vc_loc.virt_col == sheet->num_virt_cols)
106  return NULL;
107 
108  return block;
109 }
110 
111 static gboolean
112 find_cell_by_pixel (GnucashSheet *sheet, gint x, gint y,
113  VirtualLocation *virt_loc)
114 {
115  SheetBlock *block;
116  SheetBlockStyle *style;
117  CellDimensions *cd;
118  gint row = 0;
119  gint col = 0;
120 
121  g_return_val_if_fail (virt_loc != NULL, FALSE);
122 
123  block = gnucash_sheet_get_block (sheet, virt_loc->vcell_loc);
124  if (block == NULL)
125  return FALSE;
126 
127  /* now make x, y relative to the block origin */
128  x -= block->origin_x;
129  y -= block->origin_y;
130 
131  style = block->style;
132  if (style == NULL)
133  return FALSE;
134 
135  do
136  {
137  cd = gnucash_style_get_cell_dimensions (style, row, 0);
138 
139  if (cd && y >= cd->origin_y && y < cd->origin_y + cd->pixel_height)
140  break;
141 
142  row++;
143  }
144  while (row < style->nrows);
145 
146  if (row == style->nrows)
147  return FALSE;
148 
149  do
150  {
151  cd = gnucash_style_get_cell_dimensions (style, row, col);
152 
153  if (cd && x >= cd->origin_x && x < cd->origin_x + cd->pixel_width)
154  break;
155 
156  col++;
157  }
158  while (col < style->ncols);
159 
160  if (col == style->ncols)
161  return FALSE;
162 
163  if (virt_loc)
164  virt_loc->phys_row_offset = row;
165  if (virt_loc)
166  virt_loc->phys_col_offset = col;
167 
168  return TRUE;
169 }
170 
171 gboolean
172 gnucash_sheet_find_loc_by_pixel (GnucashSheet *sheet, gint x, gint y,
173  VirtualLocation *virt_loc)
174 {
175  SheetBlock *block;
176 
177  if (virt_loc == NULL)
178  return FALSE;
179 
180  block = find_block_by_pixel (sheet, x, y,
181  &virt_loc->vcell_loc);
182  if (block == NULL)
183  return FALSE;
184 
185  return find_cell_by_pixel (sheet, x, y, virt_loc);
186 }
187 
188 static void
189 get_cell_borders (GnucashSheet *sheet, VirtualLocation virt_loc,
190  PhysicalCellBorders *borders)
191 {
192  VirtualLocation v_loc;
193  PhysicalCellBorders neighbor;
194 
195  gnucash_sheet_get_borders (sheet, virt_loc, borders);
196 
197  /* top */
198  v_loc = virt_loc;
199  if (gnc_table_move_vertical_position (sheet->table, &v_loc, -1))
200  {
201  gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
202  borders->top = MAX(borders->top, neighbor.bottom);
203  }
204 
205  /* bottom */
206  v_loc = virt_loc;
207  if (gnc_table_move_vertical_position (sheet->table, &v_loc, 1))
208  {
209  gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
210  borders->bottom = MAX(borders->bottom, neighbor.top);
211  }
212 
213  /* left */
214  v_loc = virt_loc;
215  v_loc.phys_col_offset--;
216  if (gnc_table_virtual_loc_valid (sheet->table, v_loc, TRUE))
217  {
218  gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
219  borders->left = MAX(borders->left, neighbor.right);
220  }
221 
222  /* right */
223  v_loc = virt_loc;
224  v_loc.phys_col_offset++;
225  if (gnc_table_virtual_loc_valid (sheet->table, v_loc, TRUE))
226  {
227  gnucash_sheet_get_borders (sheet, v_loc, &neighbor);
228  borders->right = MAX(borders->right, neighbor.left);
229  }
230 }
231 
232 
233 #ifdef READONLY_LINES_WITH_CHANGED_FG_COLOR
234 
238 static guint8 inc_intensity_byte (guint8 input, int numerator, int denominator)
239 {
240  guint8 result_inv, result;
241  guint8 input_inv = 0xff - input;
242  result_inv = (input_inv * numerator) / denominator;
243  result = 0xff - result_inv;
244  return result;
245 }
246 
250 static guint32 inc_intensity_10percent (guint32 argb)
251 {
252  guint32 result =
253  (inc_intensity_byte ((argb & 0x00FF0000) >> 16, 8, 10) << 16)
254  + (inc_intensity_byte ((argb & 0x0000FF00) >> 8, 8, 10) << 8)
255  + (inc_intensity_byte (argb & 0x000000FF, 8, 10));
256  return result;
257 }
258 #endif
259 
260 /* Actual drawing routines */
261 
262 static inline void
263 draw_cell_line (cairo_t *cr, GdkRGBA *bg_color,
264  double x1, double y1, double x2, double y2,
265  PhysicalCellBorderLineStyle style);
266 
267 void
268 draw_cell_line (cairo_t *cr, GdkRGBA *bg_color,
269  double x1, double y1, double x2, double y2,
270  PhysicalCellBorderLineStyle style)
271 {
272  GdkRGBA *fg_color;
273 
274  switch (style)
275  {
276  case CELL_BORDER_LINE_NONE:
277  fg_color = bg_color;
278  break;
279 
280  case CELL_BORDER_LINE_LIGHT:
281  fg_color = &gn_light_gray;
282  break;
283 
284  case CELL_BORDER_LINE_NORMAL:
285  case CELL_BORDER_LINE_HEAVY:
286  fg_color = &gn_black;
287  break;
288 
289  case CELL_BORDER_LINE_HIGHLIGHT:
290  fg_color = &gn_red;
291  break;
292 
293  default:
294  return;
295  }
296 
297  cairo_set_line_width (cr, 1.0);
298  cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
299  cairo_move_to (cr, x1, y1);
300  cairo_line_to (cr, x2, y2);
301  cairo_stroke (cr);
302 }
303 
304 static void
305 draw_hatching (cairo_t *cr, double x, double y,
306  G_GNUC_UNUSED double width, double height)
307 {
308  GdkRGBA *fg_color;
309  double h_x = x + 2.5;
310  double h_y = y + 2.5;
311  double h_size = height / 3 - 1;
312 
313  cairo_set_line_width (cr, 1.0);
314  fg_color = &gn_light_gray;
315  cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
316 
317  cairo_rectangle (cr, h_x, h_y, h_size, h_size);
318  cairo_move_to (cr, h_x, h_y);
319  cairo_rel_line_to (cr, h_size, h_size);
320  cairo_rel_move_to (cr, -h_size, 0);
321  cairo_rel_line_to (cr, h_size, -h_size);
322  cairo_stroke (cr);
323 }
324 
325 static void
326 draw_divider_line (cairo_t *cr, VirtualLocation virt_loc,
327  int div_row, int n_phys_rows, GdkRGBA *fg_color,
328  double x, double y, double width, double height)
329 {
330  double offset;
331  if (div_row < 0)
332  return;
333 
334  /* Test if divider line should be drawn before the current row */
335  if ((virt_loc.phys_row_offset == 0) &&
336  (virt_loc.vcell_loc.virt_row == div_row))
337  offset = 0.0;
338  /* Test if divider line should be drawn after the current row */
339  else if ((virt_loc.phys_row_offset == n_phys_rows - 1) &&
340  (virt_loc.vcell_loc.virt_row == div_row - 1))
341  offset = height;
342  else
343  return;
344 
345  cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
346 
347  cairo_set_line_width (cr, 3.0);
348  cairo_move_to (cr, x, y - 0.5 + offset);
349  cairo_rel_line_to (cr, width, 0);
350  cairo_stroke (cr);
351 }
352 
353 static void
354 set_cell_insensitive (GtkStyleContext *stylectxt)
355 {
356  if (!gtk_style_context_has_class (stylectxt, GTK_STYLE_CLASS_BACKGROUND))
357  gtk_style_context_set_state (stylectxt, GTK_STATE_FLAG_INSENSITIVE);
358 }
359 
360 static void
361 draw_cell (GnucashSheet *sheet, SheetBlock *block,
362  VirtualLocation virt_loc, cairo_t *cr,
363  int x, int y, int width, int height)
364 {
365  GncItemEdit *item_edit = GNC_ITEM_EDIT(sheet->item_editor);
366  Table *table = sheet->table;
367  PhysicalCellBorders borders;
368  const char *text;
369  PangoLayout *layout;
370  PangoContext *context;
371  PangoFontDescription *font;
372  PangoRectangle logical_rect;
373  GdkRGBA *bg_color, *fg_color;
374  GdkRectangle rect;
375  gboolean hatching;
376  guint32 color_type;
377  int x_offset;
378  GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(sheet));
379  GdkRGBA color;
380  gboolean use_neg_class = TRUE;
381 
382  gtk_style_context_save (stylectxt);
383 
384  text = gnc_table_get_entry (table, virt_loc);
385 
386  // test for any text, if no text we do not want to add gnc-class-negative-numbers
387  if (!text || *text == '\0')
388  use_neg_class = FALSE;
389 
390  // Get the color type and apply the css class
391  color_type = gnc_table_get_color (table, virt_loc, &hatching);
392  gnucash_get_style_classes (sheet, stylectxt, color_type, use_neg_class);
393 
394  if (sheet->read_only)
395  set_cell_insensitive (stylectxt);
396  else
397  {
398  if (gtk_style_context_has_class (stylectxt, GTK_STYLE_CLASS_BACKGROUND))
399  gtk_style_context_set_state (stylectxt, GTK_STATE_FLAG_NORMAL);
400  }
401 
402  // Are we in a read-only row? Then make the background color somewhat more grey.
403  if ((virt_loc.phys_row_offset < block->style->nrows)
404  && (table->model->dividing_row_upper >= 0))
405  {
406  if (table->model->reverse_sort)
407  {
408  if ((table->model->blank_trans_row < table->model->dividing_row_upper)
409  && (virt_loc.vcell_loc.virt_row >= table->model->dividing_row_upper))
410  {
411  set_cell_insensitive (stylectxt); // future trans after blank
412  }
413 
414  if ((virt_loc.vcell_loc.virt_row >= table->model->dividing_row_upper)
415  && (virt_loc.vcell_loc.virt_row < table->model->blank_trans_row))
416  {
417  set_cell_insensitive (stylectxt);
418  }
419  }
420  else // normal order
421  {
422  if (virt_loc.vcell_loc.virt_row < table->model->dividing_row_upper)
423  set_cell_insensitive (stylectxt);
424  }
425  }
426 
427  gtk_render_background (stylectxt, cr, x, y, width, height);
428 
429  gdk_rgba_parse (&color, "black");
430  gnc_style_context_get_background_color (stylectxt, gtk_style_context_get_state (stylectxt),
431  &color);
432  bg_color = &color;
433 
434  get_cell_borders (sheet, virt_loc, &borders);
435 
436  /* top */
437  draw_cell_line (cr, bg_color,
438  (borders.top >= borders.left ? x : x + 1.0),
439  y - 0.5,
440  (borders.top >= borders.right ?
441  x + width : x + width - 1),
442  y - 0.5,
443  borders.top);
444 
445  /* bottom */
446  draw_cell_line (cr, bg_color,
447  (borders.bottom >= borders.left ? x : x + 1.0),
448  y + height - 0.5,
449  (borders.bottom >= borders.right ?
450  x + width : x + width - 1),
451  y + height - 0.5,
452  borders.bottom);
453 
454  /* left */
455  draw_cell_line (cr, bg_color,
456  (x == 0 ? x + 0.5 : x - 0.5),
457  (borders.left > borders.top ? y : y),
458  (x == 0 ? x + 0.5 : x - 0.5),
459  (borders.left > borders.bottom ?
460  y + height : y + height),
461  borders.left);
462 
463  /* right */
464  draw_cell_line (cr, bg_color,
465  x + width - 0.5,
466  (borders.right > borders.top ? y : y),
467  x + width - 0.5,
468  (borders.right > borders.bottom ?
469  y + height : y + height),
470  borders.right);
471 
472  if (hatching)
473  draw_hatching (cr, x, y, width, height);
474 
475  /* dividing line upper (red) */
476  fg_color = &gn_red;
477  draw_divider_line (cr, virt_loc,
478  table->model->dividing_row_upper, block->style->nrows,
479  fg_color, x, y, width, height);
480 
481  /* dividing line (blue) */
482  fg_color = &gn_blue;
483  draw_divider_line (cr, virt_loc,
484  table->model->dividing_row, block->style->nrows,
485  fg_color, x, y, width, height);
486 
487  /* dividing line lower (blue) */
488  draw_divider_line (cr, virt_loc,
489  table->model->dividing_row_lower, block->style->nrows,
490  fg_color, x, y, width, height);
491 
492  layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), text);
493 
494  if (gtk_style_context_has_class (stylectxt, GTK_STYLE_CLASS_VIEW))
495  gtk_style_context_remove_class (stylectxt, GTK_STYLE_CLASS_VIEW);
496 
497  // We don't need word wrap or line wrap
498  pango_layout_set_width (layout, -1);
499  context = pango_layout_get_context (layout);
500  font = pango_font_description_copy (pango_context_get_font_description (context));
501 
502 #ifdef READONLY_LINES_WITH_CHANGED_FG_COLOR
503  // Are we in a read-only row? Then make the foreground color somewhat less black
504  if ((virt_loc.phys_row_offset < block->style->nrows)
505  && (table->model->dividing_row_upper >= 0)
506  && (virt_loc.vcell_loc.virt_row < table->model->dividing_row_upper))
507  {
508  // Make text color greyed
509  gtk_style_context_add_class (stylectxt, "gnc-class-lighter-grey-mix");
510  }
511 #endif
512 
513  if ((text != NULL) && (*text != '\0') && g_strcmp0 (PRICE_CELL_TYPE_NAME,
514  gnc_table_get_cell_type_name (table, virt_loc)) == 0)
515  {
516  int text_width;
517  int text_border_padding;
518 
519  pango_layout_get_pixel_size (layout, &text_width, NULL);
520 
521  text_border_padding = gnc_item_edit_get_margin (item_edit, left_right) +
522  gnc_item_edit_get_padding_border (item_edit, left_right);
523 
524  if (text_width + text_border_padding > width)
525  {
526  int pango_width = (width - text_border_padding) * PANGO_SCALE;
527 
528  pango_layout_set_width (layout, pango_width); //pango units
529  pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
530  }
531  }
532 
533  /* If this is the currently open transaction and
534  there is no text in this cell */
535  if ((table->current_cursor_loc.vcell_loc.virt_row ==
536  virt_loc.vcell_loc.virt_row) &&
537  (!text || strlen(text) == 0))
538  {
539  text = gnc_table_get_label (table, virt_loc);
540  if ((text == NULL) || (*text == '\0'))
541  goto exit;
542 
543  // Make text color greyed
544  gtk_style_context_add_class (stylectxt, "gnc-class-lighter-grey-mix");
545 
546  pango_layout_set_text (layout, text, strlen (text));
547  pango_font_description_set_style (font, PANGO_STYLE_ITALIC);
548  pango_context_set_font_description (context, font);
549  }
550 
551  if ((text == NULL) || (*text == '\0'))
552  {
553  goto exit;
554  }
555 
556  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
557 
558  gnucash_sheet_set_text_bounds (sheet, &rect, x, y, width, height);
559 
560  cairo_save (cr);
561  cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
562  cairo_clip (cr);
563 
564  x_offset = gnucash_sheet_get_text_offset (sheet, virt_loc,
565  rect.width, logical_rect.width);
566 
567  gtk_render_layout (stylectxt, cr, rect.x + x_offset,
568  rect.y + gnc_item_edit_get_padding_border (item_edit, top), layout);
569 
570  cairo_restore (cr);
571 
572 exit:
573  pango_font_description_set_style (font, PANGO_STYLE_NORMAL);
574  pango_context_set_font_description (context, font);
575  pango_font_description_free (font);
576  g_object_unref (layout);
577 
578  gtk_style_context_restore (stylectxt);
579 }
580 
581 static void
582 draw_block (GnucashSheet *sheet, SheetBlock *block,
583  VirtualLocation virt_loc, cairo_t *cr,
584  int x, int y, int width, int height)
585 {
586  CellDimensions *cd;
587  gint x_paint;
588  gint y_paint;
589  gint w, h;
590 
591  for (virt_loc.phys_row_offset = 0;
592  virt_loc.phys_row_offset < block->style->nrows ;
593  virt_loc.phys_row_offset++)
594  {
595  for (virt_loc.phys_col_offset = 0;
596  virt_loc.phys_col_offset < block->style->ncols ;
597  virt_loc.phys_col_offset++)
598  {
599  cd = gnucash_style_get_cell_dimensions
600  (block->style,
601  virt_loc.phys_row_offset,
602  virt_loc.phys_col_offset);
603 
604  if (!cd) break;
605 
606  x_paint = block->origin_x + cd->origin_x - x;
607  if (x_paint > width)
608  break;
609 
610  y_paint = block->origin_y + cd->origin_y - y;
611  if (y_paint > height)
612  return;
613 
614  h = cd->pixel_height;
615  w = cd->pixel_width;
616 
617  if (w == 0)
618  continue;
619 
620  if (x_paint + w < 0)
621  continue;
622 
623  if (y_paint + h < 0)
624  continue;
625 
626  draw_cell (sheet, block, virt_loc, cr,
627  x_paint, y_paint, w, h);
628  }
629  }
630 }
631 
632 gboolean
633 gnucash_sheet_draw_internal (GnucashSheet* sheet, cairo_t* cr,
634  GtkAllocation* alloc)
635 {
636  VirtualLocation virt_loc = {{0, 0}, 0, 0};
637  SheetBlock *sheet_block;
638  int x = 0;
639  int y = 0;
640  int width = alloc->width;
641  int height = alloc->height;
642  GtkAdjustment * adj;
643 
644  adj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE(sheet));
645  x = (gint) gtk_adjustment_get_value (adj);
646  adj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE(sheet));
647  y = (gint) gtk_adjustment_get_value (adj);
648 
649  if (x < 0 || y < 0)
650  return FALSE;
651 
652  /* compute our initial values where we start drawing */
653  sheet_block = find_block_by_pixel (sheet, x, y, &virt_loc.vcell_loc);
654  if (!sheet_block || !sheet_block->style)
655  return FALSE;
656 
657  sheet->read_only = gnc_table_model_read_only (sheet->table->model);
658 
659  for ( ; virt_loc.vcell_loc.virt_row < sheet->num_virt_rows;
660  virt_loc.vcell_loc.virt_row++ )
661  {
662  while (TRUE)
663  {
664  sheet_block = gnucash_sheet_get_block (sheet, virt_loc.vcell_loc);
665 
666  if (!sheet_block || !sheet_block->style)
667  return TRUE;
668 
669  if (sheet_block->visible)
670  break;
671 
672  virt_loc.vcell_loc.virt_row++;
673  }
674 
675  if (y + height < sheet_block->origin_y)
676  return TRUE;
677 
678  draw_block (sheet, sheet_block, virt_loc, cr,
679  x, y, width, height);
680  }
681  return TRUE;
682 }
683 
684 
685 void
686 gnucash_sheet_draw_cursor (GnucashCursor *cursor, cairo_t *cr)
687 {
688  GnucashCursorCell *cc = &(cursor->cell);
689  GdkRGBA *fg_color;
690  int x = 0;
691  int y = 0;
692  GtkAdjustment * adj;
693 
694  adj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE(cursor->sheet));
695  x = (gint) gtk_adjustment_get_value (adj);
696  adj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE(cursor->sheet));
697  y = (gint) gtk_adjustment_get_value (adj);
698 
699  fg_color = &gn_black;
700 
701  /* draw the rectangle around the entire active virtual row - transaction rows only - double line */
702  cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
703  if (cursor->x == 0)
704  cairo_rectangle (cr, cursor->x - x + 0.5, cursor->y - y - 0.5, cursor->w - 1.0, cursor->h - 2.0);
705  else
706  cairo_rectangle (cr, cursor->x - x - 0.5, cursor->y - y - 0.5, cursor->w, cursor->h - 2.0);
707 
708  cairo_set_line_width (cr, 1.0);
709  cairo_stroke (cr);
710 
711  // make the bottom line thicker
712  cairo_move_to (cr, cursor->x - x + 0.5, cursor->y - y + cursor->h - 3.5);
713  cairo_rel_line_to (cr, cursor->w, 0);
714  cairo_set_line_width (cr, 1.0);
715  cairo_stroke (cr);
716 
717  /* draw rectangle around the active cell */
718  cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
719  if (cc->x != 0)
720  cairo_rectangle (cr, cc->x - x - 0.5, cursor->y + cc->y - y - 0.5, cc->w, cc->h);
721  else
722  cairo_rectangle (cr, cc->x - x + 0.5, cursor->y + cc->y - y - 0.5, cc->w - 1.0, cc->h);
723 
724  cairo_set_line_width (cr, 1.0);
725  cairo_stroke (cr);
726 }
gtk helper routines.
Convenience wrapper around GdkRGBA for use in Register Gnome classes.
void gnc_style_context_get_background_color(GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
Wrapper to get the background color of a widget for a given state.
void gnucash_get_style_classes(GnucashSheet *sheet, GtkStyleContext *stylectxt, RegisterColor field_type, gboolean use_neg_class)
Map a cell color type to a css style class.
gboolean visible
y origin of block
Definition: gnucash-sheet.h:59
Public declarations of GnucashRegister class.
Private declarations for GnucashSheet class.
gboolean gnc_table_move_vertical_position(Table *table, VirtualLocation *virt_loc, int phys_row_offset)
Moves away from virtual location virt_loc by phys_row_offset physical rows.
SheetBlockStyle * style
The style for this block.
Definition: gnucash-sheet.h:54
Styling functions for RegisterGnome.
gint origin_y
x origin of block
Definition: gnucash-sheet.h:57