GnuCash  5.6-150-g038405b370+
gnucash-style.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  * configure the cursor styles
23  */
24 
25 #include <config.h>
26 #include "gnucash-color.h"
27 #include "gnucash-item-edit.h"
28 #include "gnucash-sheet.h"
29 #include "gnucash-sheetP.h"
30 #include "gnucash-style.h"
31 #include "gnc-engine.h" // For debugging, e.g. ENTER(), LEAVE()
32 
34 /* This static indicates the debugging module that this .o belongs to. */
35 #define DEFAULT_STYLE_WIDTH 680
36 
37 
40 /* This static indicates the debugging module that this .o belongs to. */
41 static QofLogModule log_module = GNC_MOD_REGISTER;
42 
43 
46 static gpointer
47 style_get_key (SheetBlockStyle *style)
48 {
49  static gint key;
50 
51  key = style->cursor->num_rows;
52 
53  return &key;
54 }
55 
56 static gpointer
57 style_create_key (SheetBlockStyle *style)
58 {
59  gint key = style->cursor->num_rows;
60 
61  gint *new_key = g_new(gint, 1);
62  *new_key = key;
63 
64  return new_key;
65 }
66 
67 static void
68 cell_dimensions_construct (gpointer _cd, gpointer user_data)
69 {
70  CellDimensions *cd = _cd;
71 
72  cd->pixel_width = -1;
73  cd->can_span_over = TRUE;
74 }
75 
76 
77 static BlockDimensions *
78 style_dimensions_new (SheetBlockStyle *style)
79 {
80  BlockDimensions *dimensions;
81 
82  dimensions = g_new0 (BlockDimensions, 1);
83 
84  dimensions->nrows = style->nrows;
85  dimensions->ncols = style->ncols;
86 
87  dimensions->cell_dimensions = g_table_new (sizeof (CellDimensions),
88  cell_dimensions_construct,
89  NULL, NULL);
90 
91  g_table_resize (dimensions->cell_dimensions,
92  style->nrows, style->ncols);
93 
94  return dimensions;
95 }
96 
97 static void
98 style_dimensions_destroy (BlockDimensions *dimensions)
99 {
100  if (dimensions == NULL)
101  return;
102 
103  dimensions->refcount--;
104 
105  if (dimensions->refcount == 0)
106  {
107  g_table_destroy (dimensions->cell_dimensions);
108  dimensions->cell_dimensions = NULL;
109 
110  g_free(dimensions);
111  }
112 }
113 
114 
115 static void
116 gnucash_style_dimensions_init (GnucashSheet *sheet, SheetBlockStyle *style)
117 {
118  BlockDimensions *dimensions;
119 
120  dimensions = g_hash_table_lookup (sheet->dimensions_hash_table,
121  style_get_key (style));
122 
123  if (!dimensions)
124  {
125  dimensions = style_dimensions_new (style);
126  g_hash_table_insert (sheet->dimensions_hash_table,
127  style_create_key (style), dimensions);
128  }
129 
130  dimensions->refcount++;
131 
132  style->dimensions = dimensions;
133 }
134 
135 
137 gnucash_style_get_cell_dimensions (SheetBlockStyle *style, int row, int col)
138 {
139  if (style == NULL)
140  return NULL;
141  if (style->dimensions == NULL)
142  return NULL;
143  if (style->dimensions->cell_dimensions == NULL)
144  return NULL;
145 
146  return g_table_index (style->dimensions->cell_dimensions, row, col);
147 }
148 
149 static int
150 compute_row_width (BlockDimensions *dimensions, int row, int col1, int col2)
151 {
152  int j;
153  int width = 0;
154 
155  col1 = MAX(0, col1);
156  col2 = MIN(col2, dimensions->ncols - 1);
157 
158  for (j = col1; j <= col2; j++)
159  {
160  CellDimensions *cd;
161  cd = g_table_index (dimensions->cell_dimensions, row, j);
162 
163  if (!cd)
164  continue;
165 
166  width += cd->pixel_width;
167  }
168 
169  return width;
170 }
171 
172 
173 /* This sets the initial sizes of the cells, based on the sample_text */
174 static void
175 set_dimensions_pass_one (GnucashSheet *sheet, CellBlock *cursor,
176  BlockDimensions *dimensions)
177 {
178  CellDimensions *cd;
179  int row, col;
180  gint max_height = -1;
181  PangoLayout *layout;
182  GncItemEdit *item_edit = GNC_ITEM_EDIT(sheet->item_editor);
183 
184  /* g_return_if_fail (font != NULL); */
185 
186  for (row = 0; row < cursor->num_rows; row++)
187  {
188  for (col = 0; col < cursor->num_cols; col++)
189  {
190  int width;
191  char *text;
192  BasicCell *cell;
193 
194  cd = g_table_index (dimensions->cell_dimensions,
195  row, col);
196 
197  cell = gnc_cellblock_get_cell (cursor, row, col);
198  if (!cell || !cd)
199  continue;
200 
201  text = cell->sample_text;
202  if (text)
203  cd->can_span_over = FALSE;
204 
205  if (text)
206  {
207  layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), text);
208  pango_layout_get_pixel_size (layout, &width, &cd->pixel_height);
209  g_object_unref (layout);
210  width += gnc_item_edit_get_margin (item_edit, left_right) +
211  gnc_item_edit_get_padding_border (item_edit, left_right);
212 
213  // This is used on new popup cells to get the default
214  // width of text plus toggle button.
215  if (cell && cell->is_popup)
216  width += gnc_item_edit_get_button_width (item_edit) + 2; // + 2 for the button margin
217 
218  cd->pixel_height += gnc_item_edit_get_margin (item_edit, top_bottom) +
219  gnc_item_edit_get_padding_border (item_edit, top_bottom);
220  }
221  else
222  {
223  width = 0;
224  cd->pixel_height = gnc_item_edit_get_margin (item_edit, top_bottom) +
225  gnc_item_edit_get_padding_border (item_edit, top_bottom);
226  }
227  // add 1 to cd->pixel_height to allow for a cell border
228  max_height = MAX(max_height, cd->pixel_height + 1);
229 
230  if (cd->pixel_width > 0)
231  continue;
232 
233  cd->pixel_width = MAX (cd->pixel_width, width);
234  }
235 
236  dimensions->height += max_height;
237  }
238 
239  for (row = 0; row < cursor->num_rows; row++)
240  {
241  for (col = 0; col < cursor->num_cols; col++)
242  {
243  cd = g_table_index (dimensions->cell_dimensions,
244  row, col);
245  if (!cd)
246  continue;
247 
248  cd->pixel_height = max_height;
249  }
250  }
251 }
252 
253 
254 /* Now adjust things to make everything even. This code assumes that
255  * all cursors have the same number of columns!!! */
256 static void
257 set_dimensions_pass_two (GnucashSheet *sheet, int default_width)
258 {
259  SheetBlockStyle *style;
260  GncItemEdit *item_edit = GNC_ITEM_EDIT(sheet->item_editor);
261  BlockDimensions *dimensions;
262  CellDimensions *cd;
263  GTable *cd_table;
264  CellBlock *cursor;
265  GList *cursors;
266  GList *node;
267 
268  int num_cols;
269  int *widths;
270  int width;
271  int row, col;
272 
273  style = gnucash_sheet_get_style_from_cursor (sheet, CURSOR_HEADER);
274  dimensions = style->dimensions;
275  cd_table = dimensions->cell_dimensions;
276  cursor = style->cursor;
277 
278  width = 0;
279  num_cols = cursor->num_cols;
280  widths = g_new0 (int, num_cols);
281 
282  /* find header widths */
283  for (col = 0; col < num_cols; col++)
284  {
285  cd = g_table_index (cd_table, 0, col);
286 
287  if (!cd)
288  continue;
289 
290  widths[col] = cd->pixel_width;
291  width += cd->pixel_width;
292  }
293 
294  if (width < default_width)
295  for (col = 0; col < num_cols; col++)
296  {
297  BasicCell *cell;
298 
299  cell = gnc_cellblock_get_cell (cursor, 0, col);
300 
301  if (!cell || !cell->expandable)
302  continue;
303 
304  cd = g_table_index (cd_table, 0, col);
305 
306  if (!cd)
307  continue;
308 
309  cd->pixel_width += (default_width - width);
310  widths[col] = cd->pixel_width;
311 
312  break;
313  }
314  else if (width > default_width && width == sheet->window_width)
315  {
316  for (col = 0; col < num_cols; col++)
317  {
318  BasicCell *cell;
319  const char *text;
320  int sample_width;
321  PangoLayout *layout;
322 
323  cell = gnc_cellblock_get_cell (cursor, 0, col);
324 
325  if (!cell || !cell->expandable)
326  continue;
327 
328  cd = g_table_index (cd_table, 0, col);
329 
330  if (!cd)
331  continue;
332 
333  cd->pixel_width += (default_width - width);
334 
335  text = cell->sample_text;
336  if (text)
337  {
338  layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), text);
339  pango_layout_get_pixel_size (layout, &sample_width, NULL);
340  g_object_unref (layout);
341  /*sample_width = gdk_string_width (font, text);*/
342  sample_width += gnc_item_edit_get_margin (item_edit, left_right) +
343  gnc_item_edit_get_padding_border (item_edit, left_right);
344  }
345  else
346  sample_width = 0;
347 
348  cd->pixel_width = MAX (cd->pixel_width, sample_width);
349 
350  widths[col] = cd->pixel_width;
351 
352  break;
353  }
354  }
355 
356  cursors = gnc_table_layout_get_cursors (sheet->table->layout);
357 
358  /* adjust widths to be consistent */
359  for (node = cursors; node; node = node->next)
360  {
361  cursor = node->data;
362  style = gnucash_sheet_get_style_from_cursor
363  (sheet, cursor->cursor_name);
364  dimensions = style->dimensions;
365  cd_table = dimensions->cell_dimensions;
366 
367  for (row = 0; row < cursor->num_rows; row++)
368  for (col = 0; col < num_cols; col++)
369  {
370  cd = g_table_index (cd_table, row, col);
371 
372  if (!cd)
373  continue;
374 
375  cd->pixel_width = widths[col];
376  }
377  }
378 
379  /* now expand spanning cells */
380  for (node = cursors; node; node = node->next)
381  {
382  CellDimensions *cd_span;
383 
384  cursor = node->data;
385  style = gnucash_sheet_get_style_from_cursor
386  (sheet, cursor->cursor_name);
387  dimensions = style->dimensions;
388  cd_table = dimensions->cell_dimensions;
389 
390  for (row = 0; row < cursor->num_rows; row++)
391  {
392  cd_span = NULL;
393 
394  for (col = 0; col < num_cols; col++)
395  {
396  BasicCell *cell;
397 
398  cell = gnc_cellblock_get_cell (cursor,
399  row, col);
400  if (!cell)
401  continue;
402 
403  cd = g_table_index (cd_table, row, col);
404 
405  if (cell->span)
406  {
407  cd_span = cd;
408  continue;
409  }
410 
411  if (!cd || !cd->can_span_over)
412  continue;
413 
414  if (cd_span == NULL)
415  continue;
416 
417  if (cell->sample_text != NULL)
418  {
419  cd_span = NULL;
420  continue;
421  }
422 
423  if (cd->pixel_width <= 0)
424  continue;
425 
426  cd_span->pixel_width += cd->pixel_width;
427  cd->pixel_width = 0;
428  }
429  }
430  }
431 
432  g_free (widths);
433 }
434 
435 gint
436 gnucash_style_row_width(SheetBlockStyle *style, int row)
437 {
438  BlockDimensions *dimensions;
439 
440  dimensions = style->dimensions;
441 
442  return compute_row_width(dimensions, row, 0, dimensions->ncols - 1);
443 }
444 
445 static void
446 compute_cell_origins_x (BlockDimensions *dimensions)
447 {
448  int x;
449  int i, j;
450 
451  for (i = 0; i < dimensions->nrows; i++)
452  {
453  x = 0;
454 
455  for (j = 0; j < dimensions->ncols; j++)
456  {
457  CellDimensions *cd;
458 
459  cd = g_table_index (dimensions->cell_dimensions, i, j);
460 
461  if (!cd)
462  continue;
463 
464  cd->origin_x = x;
465  x += cd->pixel_width;
466  }
467  }
468 }
469 
470 static void
471 compute_cell_origins_y (BlockDimensions *dimensions)
472 {
473  CellDimensions *cd;
474  int y = 0;
475  int i, j;
476 
477  for (i = 0; i < dimensions->nrows; i++)
478  {
479  for (j = 0; j < dimensions->ncols; j++)
480  {
481  cd = g_table_index (dimensions->cell_dimensions, i, j);
482 
483  if (!cd)
484  continue;
485 
486  cd->origin_y = y;
487  }
488  cd = g_table_index (dimensions->cell_dimensions, i, 0);
489 
490  if (!cd)
491  continue;
492 
493  y += cd->pixel_height;
494  }
495 }
496 
497 /* Calculate the widths and offsets */
498 static void
499 set_dimensions_pass_three (GnucashSheet *sheet)
500 {
501  GList *cursors;
502  GList *node;
503 
504  cursors = gnc_table_layout_get_cursors (sheet->table->layout);
505 
506  for (node = cursors; node; node = node->next)
507  {
508  CellBlock *cursor = node->data;
509 
510  SheetBlockStyle *style;
511  BlockDimensions *dimensions;
512 
513  style = gnucash_sheet_get_style_from_cursor
514  (sheet, cursor->cursor_name);
515  dimensions = style->dimensions;
516 
517  dimensions->width = compute_row_width (dimensions, 0, 0,
518  dimensions->ncols - 1);
519 
520  compute_cell_origins_x (dimensions);
521  compute_cell_origins_y (dimensions);
522  }
523 }
524 
525 static void
526 styles_recompute_layout_dimensions (GnucashSheet *sheet, int default_width)
527 {
528  CellBlock *cursor;
529  SheetBlockStyle *style;
530  BlockDimensions *dimensions;
531  GList *cursors;
532  GList *node;
533 
534  cursors = gnc_table_layout_get_cursors (sheet->table->layout);
535 
536  for (node = cursors; node; node = node->next)
537  {
538  cursor = node->data;
539 
540  style = gnucash_sheet_get_style_from_cursor
541  (sheet, cursor->cursor_name);
542 
543  dimensions = style->dimensions;
544 
545  dimensions->height = 0;
546  dimensions->width = default_width;
547 
548  set_dimensions_pass_one (sheet, cursor, dimensions);
549  }
550 
551  set_dimensions_pass_two (sheet, default_width);
552  set_dimensions_pass_three (sheet);
553 }
554 
555 void
556 gnucash_sheet_styles_set_dimensions (GnucashSheet *sheet, int default_width)
557 {
558  g_return_if_fail (sheet != NULL);
559  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
560 
561  styles_recompute_layout_dimensions (sheet, default_width);
562 }
563 
564 gint
565 gnucash_style_col_is_resizable (SheetBlockStyle *style, int col)
566 {
567  if (col < 0 || col >= style->ncols)
568  return FALSE;
569 
570  return TRUE;
571 }
572 
573 void
574 gnucash_sheet_set_col_width (GnucashSheet *sheet, int col, int width)
575 {
576  CellDimensions *cd;
577  SheetBlockStyle *style;
578  int total;
579  int diff;
580 
581  g_return_if_fail (sheet != NULL);
582  g_return_if_fail (GNUCASH_IS_SHEET(sheet));
583  g_return_if_fail (col >= 0);
584 
585  if (width < 0)
586  return;
587 
588  style = gnucash_sheet_get_style_from_cursor (sheet, CURSOR_HEADER);
589 
590  g_return_if_fail (col < style->ncols);
591 
592  cd = gnucash_style_get_cell_dimensions (style, 0, col);
593  if (!cd) return;
594 
595  /* adjust the overall width of this style */
596  diff = cd->pixel_width - width;
597  cd->pixel_width = width;
598 
599  total = MAX (sheet->window_width, sheet->width - diff);
600 
601  set_dimensions_pass_two (sheet, total);
602  set_dimensions_pass_three (sheet);
603 }
604 
605 
606 void
607 gnucash_sheet_styles_recompile(GnucashSheet *sheet)
608 {
609 }
610 
611 
612 void
613 gnucash_sheet_get_borders (GnucashSheet *sheet, VirtualLocation virt_loc,
614  PhysicalCellBorders *borders)
615 {
616  SheetBlockStyle *style;
617  PhysicalCellBorderLineStyle line_style;
618 
619  g_return_if_fail (sheet != NULL);
620  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
621 
622  line_style = sheet->use_horizontal_lines ?
623  CELL_BORDER_LINE_NORMAL : CELL_BORDER_LINE_NONE;
624 
625  borders->top = line_style;
626  borders->bottom = line_style;
627 
628  line_style = sheet->use_vertical_lines ?
629  CELL_BORDER_LINE_NORMAL : CELL_BORDER_LINE_NONE;
630 
631  borders->left = line_style;
632  borders->right = line_style;
633 
634  style = gnucash_sheet_get_style_from_cursor (sheet, CURSOR_HEADER);
635  if (style)
636  if (virt_loc.phys_col_offset == (style->ncols - 1))
637  borders->right = CELL_BORDER_LINE_NORMAL;
638 
639  if (virt_cell_loc_equal (virt_loc.vcell_loc,
640  sheet->table->current_cursor_loc.vcell_loc))
641  {
642  borders->top = CELL_BORDER_LINE_NORMAL;
643  borders->bottom = CELL_BORDER_LINE_NORMAL;
644  }
645 
646  gnc_table_get_borders (sheet->table, virt_loc, borders);
647 }
648 
649 
650 static SheetBlockStyle *
651 gnucash_sheet_style_new (GnucashSheet *sheet, CellBlock *cursor)
652 {
653  SheetBlockStyle *style;
654 
655  g_return_val_if_fail (sheet != NULL, NULL);
656  g_return_val_if_fail (GNUCASH_IS_SHEET (sheet), NULL);
657  g_return_val_if_fail (cursor != NULL, NULL);
658 
659  style = g_new0 (SheetBlockStyle, 1);
660 
661  style->cursor = cursor;
662 
663  style->nrows = cursor->num_rows;
664  style->ncols = cursor->num_cols;
665 
666  gnucash_style_dimensions_init (sheet, style);
667 
668  return style;
669 }
670 
671 static void
672 destroy_style_helper (gpointer key, gpointer value, gpointer user_data)
673 {
674  char *cursor_name = key;
675  SheetBlockStyle *style = value;
676  GnucashSheet *sheet = user_data;
677 
678  gnucash_sheet_style_unref (sheet, style);
679  g_free (cursor_name);
680 }
681 
682 void
683 gnucash_sheet_clear_styles (GnucashSheet *sheet)
684 {
685  g_return_if_fail (sheet != NULL);
686  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
687 
688  g_hash_table_foreach (sheet->cursor_styles,
689  destroy_style_helper, sheet);
690 }
691 
692 void
693 gnucash_sheet_create_styles (GnucashSheet *sheet)
694 {
695  GList *cursors;
696  GList *node;
697 
698  g_return_if_fail (sheet != NULL);
699  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
700 
701  gnucash_sheet_clear_styles (sheet);
702 
703  cursors = gnc_table_layout_get_cursors (sheet->table->layout);
704 
705  for (node = cursors; node; node = node->next)
706  {
707  CellBlock *cursor = node->data;
708  SheetBlockStyle *style = gnucash_sheet_style_new (sheet, cursor);
709 
710  gnucash_sheet_style_ref (sheet, style);
711  g_hash_table_insert (sheet->cursor_styles,
712  g_strdup (cursor->cursor_name),
713  style);
714  }
715 }
716 
717 void
718 gnucash_sheet_compile_styles (GnucashSheet *sheet)
719 {
720  g_return_if_fail (sheet != NULL);
721  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
722 
723  ENTER("sheet=%p", sheet);
724 
725  gnucash_sheet_styles_set_dimensions (sheet, DEFAULT_STYLE_WIDTH);
726 
727  LEAVE(" ");
728 }
729 
730 void
731 gnucash_sheet_style_destroy (GnucashSheet *sheet, SheetBlockStyle *style)
732 {
733  if (sheet == NULL)
734  return;
735  if (style == NULL)
736  return;
737 
738  style->dimensions->refcount--;
739 
740  if (style->dimensions->refcount == 0)
741  {
742  style_dimensions_destroy (style->dimensions);
743  g_hash_table_remove (sheet->dimensions_hash_table,
744  style_get_key (style));
745  }
746 
747  g_free (style);
748 }
749 
750 
751 void
752 gnucash_sheet_style_get_cell_pixel_rel_coords (SheetBlockStyle *style,
753  gint cell_row, gint cell_col,
754  gint *x, gint *y,
755  gint *w, gint *h)
756 {
757  CellDimensions *cd;
758 
759  g_return_if_fail (style != NULL);
760  g_return_if_fail (cell_row >= 0 && cell_row <= style->nrows);
761  g_return_if_fail (cell_col >= 0 && cell_col <= style->ncols);
762 
763  cd = gnucash_style_get_cell_dimensions (style, cell_row, cell_col);
764  if (!cd) return;
765 
766  *x = cd->origin_x;
767  *y = cd->origin_y;
768  *h = cd->pixel_height;
769  *w = cd->pixel_width;
770 }
771 
772 
773 SheetBlockStyle *
774 gnucash_sheet_get_style (GnucashSheet *sheet, VirtualCellLocation vcell_loc)
775 {
776  SheetBlock *block;
777 
778  g_return_val_if_fail (sheet != NULL, NULL);
779  g_return_val_if_fail (GNUCASH_IS_SHEET(sheet), NULL);
780 
781  block = gnucash_sheet_get_block (sheet, vcell_loc);
782 
783  if (block)
784  return block->style;
785  else
786  return NULL;
787 }
788 
789 
790 SheetBlockStyle *
791 gnucash_sheet_get_style_from_table (GnucashSheet *sheet,
792  VirtualCellLocation vcell_loc)
793 {
794  Table *table;
795  VirtualCell *vcell;
796  CellBlock *cursor;
797  SheetBlockStyle *style;
798 
799  g_return_val_if_fail (sheet != NULL, NULL);
800  g_return_val_if_fail (GNUCASH_IS_SHEET(sheet), NULL);
801 
802  table = sheet->table;
803 
804  vcell = gnc_table_get_virtual_cell (table, vcell_loc);
805 
806  if (!vcell)
807  return NULL;
808 
809  cursor = vcell->cellblock;
810 
811  style = gnucash_sheet_get_style_from_cursor (sheet,
812  cursor->cursor_name);
813  if (style)
814  return style;
815 
816  return gnucash_sheet_get_style_from_cursor (sheet, CURSOR_HEADER);
817 }
818 
819 SheetBlockStyle *
820 gnucash_sheet_get_style_from_cursor (GnucashSheet *sheet,
821  const char *cursor_name)
822 {
823  g_return_val_if_fail (sheet != NULL, NULL);
824  g_return_val_if_fail (GNUCASH_IS_SHEET (sheet), NULL);
825 
826  if (!cursor_name)
827  return NULL;
828 
829  return g_hash_table_lookup (sheet->cursor_styles, cursor_name);
830 }
831 
832 /*
833  * For now, refcounting doesn't do much, but later we may want to
834  * destroy styles
835  */
836 
837 void
838 gnucash_sheet_style_ref (GnucashSheet *sheet, SheetBlockStyle *style)
839 {
840  g_return_if_fail (style != NULL);
841 
842  style->refcount++;
843 }
844 
845 
846 void
847 gnucash_sheet_style_unref (GnucashSheet *sheet, SheetBlockStyle *style)
848 {
849  g_return_if_fail (style != NULL);
850 
851  style->refcount--;
852 
853  if (style->refcount == 0)
854  gnucash_sheet_style_destroy (sheet, style);
855 }
856 
857 typedef struct
858 {
859  char *cell_name;
860  int width;
861 } WidthNode;
862 
863 GNCHeaderWidths
864 gnc_header_widths_new (void)
865 {
866  return g_hash_table_new (g_str_hash, g_str_equal);
867 }
868 
869 static void
870 header_width_destroy_helper (gpointer key, gpointer value, gpointer user_data)
871 {
872  WidthNode *wn = value;
873 
874  g_free (wn->cell_name);
875  wn->cell_name = NULL;
876 
877  g_free (wn);
878 }
879 
880 void
881 gnc_header_widths_destroy (GNCHeaderWidths widths)
882 {
883  if (!widths) return;
884  g_hash_table_foreach (widths, header_width_destroy_helper, NULL);
885  g_hash_table_destroy (widths);
886 }
887 
888 void
889 gnc_header_widths_set_width (GNCHeaderWidths widths,
890  const char *cell_name,
891  int width)
892 {
893  WidthNode *wn;
894 
895  g_return_if_fail (widths != NULL);
896  g_return_if_fail (cell_name != NULL);
897 
898  wn = g_hash_table_lookup (widths, cell_name);
899  if (!wn)
900  {
901  wn = g_new0 (WidthNode, 1);
902 
903  wn->cell_name = g_strdup (cell_name);
904 
905  g_hash_table_insert (widths, wn->cell_name, wn);
906  }
907 
908  wn->width = width;
909 }
910 
911 int
912 gnc_header_widths_get_width (GNCHeaderWidths widths,
913  const char *cell_name)
914 {
915  WidthNode *wn;
916 
917  g_return_val_if_fail (widths != NULL, 0);
918 
919  wn = g_hash_table_lookup (widths, cell_name);
920  if (!wn)
921  return 0;
922 
923  return wn->width;
924 }
925 
926 void
927 gnucash_sheet_get_header_widths (GnucashSheet *sheet,
928  GNCHeaderWidths widths)
929 {
930  SheetBlockStyle *style;
931  CellBlock *header;
932  int row, col;
933 
934  g_return_if_fail (sheet != NULL);
935  g_return_if_fail (GNUCASH_IS_SHEET(sheet));
936 
937  style = gnucash_sheet_get_style_from_cursor (sheet, CURSOR_HEADER);
938  g_return_if_fail (style != NULL);
939 
940  header = style->cursor;
941  g_return_if_fail (header != NULL);
942 
943  for (row = 0; row < style->nrows; row++)
944  for (col = 0; col < style->ncols; col++)
945  {
946  CellDimensions *cd;
947  BasicCell *cell;
948 
949  cd = gnucash_style_get_cell_dimensions (style,
950  row, col);
951  if (cd == NULL)
952  continue;
953 
954  cell = gnc_cellblock_get_cell (header, row, col);
955  if (!cell || !cell->cell_name)
956  continue;
957 
958  gnc_header_widths_set_width (widths,
959  cell->cell_name,
960  cd->pixel_width);
961  }
962 }
963 
964 void
965 gnucash_sheet_set_header_widths (GnucashSheet *sheet,
966  GNCHeaderWidths widths)
967 {
968  SheetBlockStyle *style;
969  CellBlock *header;
970  int row, col;
971 
972  g_return_if_fail (sheet != NULL);
973  g_return_if_fail (GNUCASH_IS_SHEET(sheet));
974 
975  style = gnucash_sheet_get_style_from_cursor (sheet, CURSOR_HEADER);
976  g_return_if_fail (style != NULL);
977 
978  header = style->cursor;
979  g_return_if_fail (header != NULL);
980 
981  for (row = 0; row < style->nrows; row++)
982  for (col = 0; col < style->ncols; col++)
983  {
984  CellDimensions *cd;
985  BasicCell *cell;
986 
987  cd = gnucash_style_get_cell_dimensions (style,
988  row, col);
989 
990  cell = gnc_cellblock_get_cell (header, row, col);
991  if (!cell || !cell->cell_name || !cd)
992  continue;
993 
994  cd->pixel_width = gnc_header_widths_get_width
995  (widths, cell->cell_name);
996  }
997 }
998 
999 gboolean
1000 gnucash_style_init (void)
1001 {
1002  return TRUE;
1003 }
1004 
1005 
GTable * g_table_new(guint entry_size, g_table_entry_constructor constructor, g_table_entry_destroyer destroyer, gpointer user_data)
Create a new table with the given entry constructor and destroyer.
Definition: gtable.c:44
gpointer g_table_index(GTable *gtable, int row, int col)
Return the element at the given row and column.
Definition: gtable.c:84
holds information about each virtual cell.
Definition: table-allgui.h:132
Convenience wrapper around GdkRGBA for use in Register Gnome classes.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
VirtualCell * gnc_table_get_virtual_cell(Table *table, VirtualCellLocation vcell_loc)
returns the virtual cell associated with a particular virtual location.
Definition: table-allgui.c:227
#define CURSOR_HEADER
Standard Cursor Names.
Definition: table-layout.h:36
Definition: gtable.c:28
Public declarations of GnucashRegister class.
Private declarations for GnucashSheet class.
All type declarations for the whole Gnucash engine.
SheetBlockStyle * style
The style for this block.
Definition: gnucash-sheet.h:54
void g_table_destroy(GTable *gtable)
Free the table and all associated table elements.
Definition: gtable.c:69
Public declarations for GncItemEdit class.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Styling functions for RegisterGnome.
void g_table_resize(GTable *gtable, int rows, int cols)
Resize the table, allocating and deallocating extra table members if needed.
Definition: gtable.c:104
BasicCell * gnc_cellblock_get_cell(CellBlock *cellblock, int row, int col)
Retrieve the Cell at the specified coordinates.
Definition: cellblock.c:109