50G_DEFINE_TYPE (
GncHeader, gnc_header, GTK_TYPE_LAYOUT)
53gnc_header_draw_offscreen (
GncHeader *header)
55 g_return_if_fail (GTK_IS_WIDGET(header));
57 if (!gtk_widget_get_realized (GTK_WIDGET(header)))
60 SheetBlockStyle *style = header->style;
61 GncItemEdit *item_edit = GNC_ITEM_EDIT(header->sheet->item_editor);
62 Table *
table = header->sheet->table;
63 VirtualLocation virt_loc;
66 GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(header));
74 virt_loc.vcell_loc.virt_row = 0;
75 virt_loc.vcell_loc.virt_col = 0;
76 virt_loc.phys_row_offset = 0;
77 virt_loc.phys_col_offset = 0;
79 gtk_style_context_save (stylectxt);
82 color_type = gnc_table_get_color (
table, virt_loc, NULL);
86 cairo_surface_destroy (header->surface);
87 scale = gtk_widget_get_scale_factor (GTK_WIDGET(header));
90 header->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
91 header->width * scale,
92 header->height * scale);
93 cairo_surface_set_device_scale (header->surface, scale, scale);
95 cr = cairo_create (header->surface);
98 gtk_render_background (stylectxt, cr, 0, 0, header->width, header->height);
100 gdk_rgba_parse (&color,
"black");
101 cairo_set_source_rgb (cr, color.red, color.green, color.blue);
102 cairo_rectangle (cr, 0.5, 0.5, header->width - 1.0, header->height - 1.0);
103 cairo_set_line_width (cr, 1.0);
107 cairo_move_to (cr, 0.5, header->height - 1.5);
108 cairo_line_to (cr, header->width - 1.0, header->height - 1.5);
109 cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
110 cairo_set_line_width (cr, 1.0);
117 cb = vcell ? vcell->cellblock : NULL;
120 for (i = 0; i < style->nrows; i++)
124 virt_loc.phys_row_offset = i;
131 for (j = 0; j < style->ncols; j++)
138 PangoRectangle logical_rect;
142 virt_loc.phys_col_offset = j;
144 cd = gnucash_style_get_cell_dimensions (style, i, j);
147 height = cd->pixel_height;
148 if (header->in_resize && (j == header->resize_col))
149 width = header->resize_col_width;
151 width = cd->pixel_width;
154 if (!cell || !cell->cell_name)
160 cairo_rectangle (cr, col_offset - 0.5, row_offset + 0.5, width, height);
161 cairo_set_line_width (cr, 1.0);
165 table->current_cursor_loc.vcell_loc;
166 text = gnc_table_get_label (
table, virt_loc);
170 layout = gtk_widget_create_pango_layout (GTK_WIDGET(header->sheet), text);
172 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
174 gnucash_sheet_set_text_bounds (header->sheet, &rect,
175 col_offset, row_offset, width, height);
178 cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
181 x_offset = gnucash_sheet_get_text_offset (header->sheet, virt_loc,
182 rect.width, logical_rect.width);
184 gtk_render_layout (stylectxt, cr, rect.x + x_offset,
185 rect.y + gnc_item_edit_get_padding_border (item_edit, top), layout);
188 g_object_unref (layout);
192 row_offset += height;
194 gtk_style_context_restore (stylectxt);
201gnc_header_get_cell_offset (
GncHeader *header, gint col, gint *cell_width)
203 SheetBlockStyle *style = header->style;
207 for (j = 0; j < style->ncols; j++)
211 cd = gnucash_style_get_cell_dimensions (style, 0, j);
216 *cell_width = cd->pixel_width;
219 offset = offset + cd->pixel_width;
226gnc_header_draw (GtkWidget *header, cairo_t *cr)
228 GnucashSheet *sheet = GNC_HEADER(header)->sheet;
229 GdkWindow *sheet_layout_win = gtk_layout_get_bin_window (GTK_LAYOUT(sheet));
233 gdk_window_get_position (sheet_layout_win, &x, &y);
237 if (GNC_HEADER(header)->surface == NULL)
238 gnc_header_draw_offscreen (GNC_HEADER(header));
240 cairo_set_source_surface (cr, GNC_HEADER(header)->surface, x, 0);
248gnc_header_request_redraw (
GncHeader *header)
253 gnc_header_draw_offscreen (header);
254 gtk_widget_queue_draw (GTK_WIDGET(header));
259gnc_header_unrealize (GtkWidget *widget)
263 cairo_surface_destroy (header->surface);
264 header->surface = NULL;
266 if (header->resize_cursor)
267 g_object_unref (header->resize_cursor);
268 header->resize_cursor = NULL;
270 if (header->normal_cursor)
271 g_object_unref (header->normal_cursor);
272 header->normal_cursor = NULL;
274 if (GTK_WIDGET_CLASS(gnc_header_parent_class)->unrealize)
275 GTK_WIDGET_CLASS(gnc_header_parent_class)->unrealize (GTK_WIDGET(header));
280gnc_header_finalize (GObject *
object)
284 header = GNC_HEADER(
object);
286 g_free (header->cursor_name);
287 header->cursor_name = NULL;
289 G_OBJECT_CLASS(gnc_header_parent_class)->finalize (
object);
294gnc_header_reconfigure (
GncHeader *header)
297 SheetBlockStyle *old_style;
300 g_return_if_fail (header != NULL);
301 g_return_if_fail (GNC_IS_HEADER(header));
303 sheet = GNUCASH_SHEET(header->sheet);
304 old_style = header->style;
306 header->style = gnucash_sheet_get_style_from_cursor
307 (sheet, header->cursor_name);
309 if (header->style == NULL)
312 sheet->width = header->style->dimensions->width;
314 w = header->style->dimensions->width;
315 h = header->style->dimensions->height;
316 h *= header->num_phys_rows;
317 h /= header->style->nrows;
320 if (header->height != h ||
321 header->width != w ||
322 header->style != old_style)
326 gtk_layout_set_size (GTK_LAYOUT(header), w, h);
327 gtk_widget_set_size_request (GTK_WIDGET(header), -1, h);
328 gnc_header_request_redraw (header);
333gnc_header_set_header_rows (
GncHeader *header,
336 g_return_if_fail (header != NULL);
337 g_return_if_fail (GNC_IS_HEADER(header));
339 header->num_phys_rows = num_phys_rows;
348pointer_on_resize_line (
GncHeader *header,
int x, G_GNUC_UNUSED
int y,
int *col)
350 SheetBlockStyle *style = header->style;
351 gboolean on_the_line = FALSE;
356 for (j = 0; j < style->ncols; j++)
358 cd = gnucash_style_get_cell_dimensions (style, 0, j);
361 pixels += cd->pixel_width;
362 if (x >= pixels - 1 && x <= pixels + 1)
375find_resize_col (
GncHeader *header,
int col)
377 SheetBlockStyle *style = header->style;
381 if (col < 0 || col >= style->ncols)
385 while ((col + 1 < style->ncols) &&
386 (cd = gnucash_style_get_cell_dimensions (style, 0, col + 1)) &&
387 cd && (cd->pixel_width == 0))
393 if (gnucash_style_col_is_resizable (style, col))
404gnc_header_resize_column (
GncHeader *header, gint col, gint width)
406 GnucashSheet *sheet = header->sheet;
408 gnucash_sheet_set_col_width (sheet, col, width);
410 gnucash_cursor_configure (GNUCASH_CURSOR(sheet->cursor));
411 gnc_item_edit_configure (gnucash_sheet_get_item_edit (sheet));
413 gnc_header_reconfigure (header);
415 gnucash_sheet_set_scroll_region (sheet);
416 gnucash_sheet_update_adjustments (sheet);
418 gnc_header_request_redraw (header);
419 gnucash_sheet_redraw_all (sheet);
423gnc_header_auto_resize_column (
GncHeader *header, gint col)
427 width = gnucash_sheet_col_max_width (header->sheet, 0, col);
429 gnc_header_resize_column (header, col, width);
433gnc_header_event (GtkWidget *widget, GdkEvent *event)
436 GdkWindow *window = gtk_widget_get_window (widget);
440 if (!header->resize_cursor)
441 header->resize_cursor = gdk_cursor_new_for_display (gdk_window_get_display (window),
442 GDK_SB_H_DOUBLE_ARROW);
446 case GDK_MOTION_NOTIFY:
450 if (header->in_resize)
452 int change = x - header->resize_x;
453 int new_width = header->resize_col_width + change;
457 header->resize_x = x;
458 header->resize_col_width = new_width;
459 gnc_header_request_redraw (header);
465 if (pointer_on_resize_line (header, x, y, &col) &&
466 gnucash_style_col_is_resizable (header->style, col))
467 gdk_window_set_cursor (window, header->resize_cursor);
469 gdk_window_set_cursor (window, header->normal_cursor);
472 case GDK_BUTTON_PRESS:
476 if (event->button.button != 1)
482 if (pointer_on_resize_line (header, x, y, &col))
483 col = find_resize_col (header, col);
491 cd = gnucash_style_get_cell_dimensions
492 (header->style, 0, col);
495 header->in_resize = TRUE;
496 header->resize_col = col;
497 header->resize_col_width = cd->pixel_width;
498 header->resize_x = x;
502 case GDK_BUTTON_RELEASE:
504 if (event->button.button != 1)
507 if (header->in_resize)
509 if (header->resize_col_width == 0)
510 header->resize_col_width = 1;
512 gnc_header_resize_column
515 header->resize_col_width);
516 header->in_resize = FALSE;
517 header->resize_col = -1;
518 gnc_header_request_redraw (header);
523 case GDK_2BUTTON_PRESS:
529 if (event->button.button != 1)
535 on_line = pointer_on_resize_line (header, x, y, &ptr_col);
540 resize_col = find_resize_col (header, ptr_col);
542 resize_col = ptr_col;
546 header->in_resize = FALSE;
547 header->resize_col = -1;
548 gnc_header_auto_resize_column (header, resize_col);
567gnc_header_get_property (GObject *
object,
577 g_value_take_object (value, header->sheet);
579 case PROP_CURSOR_NAME:
580 g_value_set_string (value, header->cursor_name);
583 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, param_id, pspec);
589gnc_header_set_property (GObject *
object,
595 GtkLayout *layout = GTK_LAYOUT(header);
596 gboolean needs_update = FALSE;
602 header->sheet = GNUCASH_SHEET(g_value_get_object (value));
603 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE(layout), header->sheet->hadj);
606 case PROP_CURSOR_NAME:
607 old_name = header->cursor_name;
609 header->cursor_name = g_value_dup_string (value);
610 needs_update = !old_name || !header->cursor_name ||
611 strcmp (old_name, header->cursor_name) != 0;
615 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, param_id, pspec);
619 if ((header->sheet != NULL) && needs_update)
620 gnc_header_reconfigure (header);
627 header->sheet = NULL;
628 header->cursor_name = NULL;
629 header->in_resize = FALSE;
630 header->resize_col = -1;
631 header->resize_cursor = NULL;
632 header->normal_cursor = NULL;
635 header->style = NULL;
637 gtk_widget_add_events (GTK_WIDGET(header),
639 | GDK_BUTTON_PRESS_MASK
640 | GDK_BUTTON_RELEASE_MASK
641 | GDK_POINTER_MOTION_MASK
642 | GDK_POINTER_MOTION_HINT_MASK));
644 g_signal_connect (G_OBJECT(header),
"configure_event",
645 G_CALLBACK(gnc_header_reconfigure), NULL);
646 gtk_widget_show_all (GTK_WIDGET(header));
653 GObjectClass *object_class = G_OBJECT_CLASS(header_class);
654 GtkWidgetClass *item_class = GTK_WIDGET_CLASS(header_class);
656 gtk_widget_class_set_css_name (GTK_WIDGET_CLASS(header_class),
"gnc-id-header");
658 object_class->finalize = gnc_header_finalize;
659 object_class->get_property = gnc_header_get_property;
660 object_class->set_property = gnc_header_set_property;
662 g_object_class_install_property (object_class,
664 g_param_spec_object (
"sheet",
669 g_object_class_install_property (object_class,
671 g_param_spec_string (
"cursor_name",
678 item_class->unrealize = gnc_header_unrealize;
679 item_class->draw = gnc_header_draw;
680 item_class->event = gnc_header_event;
684gnc_header_new (GnucashSheet *sheet)
688 layout = g_object_new (GNC_TYPE_HEADER,
693 sheet->header_item = layout;
Convenience wrapper around GdkRGBA for use in Register Gnome classes.
Public declarations for GnucashCursor class.
Public declarations for GncItemEdit class.
Private declarations for GnucashSheet class.
Public declarations of GnucashRegister class.
Styling functions for RegisterGnome.
BasicCell * gnc_cellblock_get_cell(CellBlock *cellblock, int row, int col)
Retrieve the Cell at the specified coordinates.
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.
#define CURSOR_HEADER
Standard Cursor Names.
VirtualCell * gnc_table_get_virtual_cell(Table *table, VirtualCellLocation vcell_loc)
returns the virtual cell associated with a particular virtual location.
holds information about each virtual cell.