50 G_DEFINE_TYPE (
GncHeader, gnc_header, GTK_TYPE_LAYOUT)
53 gnc_header_draw_offscreen (
GncHeader *header)
55 SheetBlockStyle *style = header->style;
56 GncItemEdit *item_edit = GNC_ITEM_EDIT(header->sheet->item_editor);
57 Table *
table = header->sheet->table;
58 VirtualLocation virt_loc;
61 GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(header));
68 virt_loc.vcell_loc.virt_row = 0;
69 virt_loc.vcell_loc.virt_col = 0;
70 virt_loc.phys_row_offset = 0;
71 virt_loc.phys_col_offset = 0;
73 gtk_style_context_save (stylectxt);
76 color_type = gnc_table_get_color (
table, virt_loc, NULL);
80 cairo_surface_destroy (header->surface);
81 header->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
85 cr = cairo_create (header->surface);
88 gtk_render_background (stylectxt, cr, 0, 0, header->width, header->height);
90 gdk_rgba_parse (&color,
"black");
91 cairo_set_source_rgb (cr, color.red, color.green, color.blue);
92 cairo_rectangle (cr, 0.5, 0.5, header->width - 1.0, header->height - 1.0);
93 cairo_set_line_width (cr, 1.0);
97 cairo_move_to (cr, 0.5, header->height - 1.5);
98 cairo_line_to (cr, header->width - 1.0, header->height - 1.5);
99 cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
100 cairo_set_line_width (cr, 1.0);
107 cb = vcell ? vcell->cellblock : NULL;
110 for (i = 0; i < style->nrows; i++)
114 virt_loc.phys_row_offset = i;
121 for (j = 0; j < style->ncols; j++)
128 PangoRectangle logical_rect;
132 virt_loc.phys_col_offset = j;
134 cd = gnucash_style_get_cell_dimensions (style, i, j);
137 height = cd->pixel_height;
138 if (header->in_resize && (j == header->resize_col))
139 width = header->resize_col_width;
141 width = cd->pixel_width;
144 if (!cell || !cell->cell_name)
150 cairo_rectangle (cr, col_offset - 0.5, row_offset + 0.5, width, height);
151 cairo_set_line_width (cr, 1.0);
155 table->current_cursor_loc.vcell_loc;
156 text = gnc_table_get_label (
table, virt_loc);
160 layout = gtk_widget_create_pango_layout (GTK_WIDGET(header->sheet), text);
162 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
164 gnucash_sheet_set_text_bounds (header->sheet, &rect,
165 col_offset, row_offset, width, height);
168 cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
171 x_offset = gnucash_sheet_get_text_offset (header->sheet, virt_loc,
172 rect.width, logical_rect.width);
174 gtk_render_layout (stylectxt, cr, rect.x + x_offset,
175 rect.y + gnc_item_edit_get_padding_border (item_edit, top), layout);
178 g_object_unref (layout);
182 row_offset += height;
184 gtk_style_context_restore (stylectxt);
191 gnc_header_get_cell_offset (
GncHeader *header, gint col, gint *cell_width)
193 SheetBlockStyle *style = header->style;
197 for (j = 0; j < style->ncols; j++)
201 cd = gnucash_style_get_cell_dimensions (style, 0, j);
206 *cell_width = cd->pixel_width;
209 offset = offset + cd->pixel_width;
216 gnc_header_draw (GtkWidget *header, cairo_t *cr)
218 GnucashSheet *sheet = GNC_HEADER(header)->sheet;
219 GdkWindow *sheet_layout_win = gtk_layout_get_bin_window (GTK_LAYOUT(sheet));
223 gdk_window_get_position (sheet_layout_win, &x, &y);
227 if (GNC_HEADER(header)->surface == NULL)
228 gnc_header_draw_offscreen (GNC_HEADER(header));
230 cairo_set_source_surface (cr, GNC_HEADER(header)->surface, x, 0);
238 gnc_header_request_redraw (
GncHeader *header)
243 gnc_header_draw_offscreen (header);
244 gtk_widget_queue_draw (GTK_WIDGET(header));
249 gnc_header_unrealize (GtkWidget *widget)
253 cairo_surface_destroy (header->surface);
254 header->surface = NULL;
256 if (header->resize_cursor)
257 g_object_unref (header->resize_cursor);
258 header->resize_cursor = NULL;
260 if (header->normal_cursor)
261 g_object_unref (header->normal_cursor);
262 header->normal_cursor = NULL;
264 if (GTK_WIDGET_CLASS(gnc_header_parent_class)->unrealize)
265 GTK_WIDGET_CLASS(gnc_header_parent_class)->unrealize (GTK_WIDGET(header));
270 gnc_header_finalize (GObject *
object)
274 header = GNC_HEADER(
object);
276 g_free (header->cursor_name);
277 header->cursor_name = NULL;
279 G_OBJECT_CLASS(gnc_header_parent_class)->finalize (
object);
284 gnc_header_reconfigure (
GncHeader *header)
287 SheetBlockStyle *old_style;
290 g_return_if_fail (header != NULL);
291 g_return_if_fail (GNC_IS_HEADER(header));
293 sheet = GNUCASH_SHEET(header->sheet);
294 old_style = header->style;
296 header->style = gnucash_sheet_get_style_from_cursor
297 (sheet, header->cursor_name);
299 if (header->style == NULL)
302 sheet->width = header->style->dimensions->width;
304 w = header->style->dimensions->width;
305 h = header->style->dimensions->height;
306 h *= header->num_phys_rows;
307 h /= header->style->nrows;
310 if (header->height != h ||
311 header->width != w ||
312 header->style != old_style)
316 gtk_layout_set_size (GTK_LAYOUT(header), w, h);
317 gtk_widget_set_size_request (GTK_WIDGET(header), -1, h);
318 gnc_header_request_redraw (header);
323 gnc_header_set_header_rows (
GncHeader *header,
326 g_return_if_fail (header != NULL);
327 g_return_if_fail (GNC_IS_HEADER(header));
329 header->num_phys_rows = num_phys_rows;
338 pointer_on_resize_line (
GncHeader *header,
int x, G_GNUC_UNUSED
int y,
int *col)
340 SheetBlockStyle *style = header->style;
341 gboolean on_the_line = FALSE;
346 for (j = 0; j < style->ncols; j++)
348 cd = gnucash_style_get_cell_dimensions (style, 0, j);
351 pixels += cd->pixel_width;
352 if (x >= pixels - 1 && x <= pixels + 1)
365 find_resize_col (
GncHeader *header,
int col)
367 SheetBlockStyle *style = header->style;
371 if (col < 0 || col >= style->ncols)
375 while ((col + 1 < style->ncols) &&
376 (cd = gnucash_style_get_cell_dimensions (style, 0, col + 1)) &&
377 cd && (cd->pixel_width == 0))
383 if (gnucash_style_col_is_resizable (style, col))
394 gnc_header_resize_column (
GncHeader *header, gint col, gint width)
396 GnucashSheet *sheet = header->sheet;
398 gnucash_sheet_set_col_width (sheet, col, width);
400 gnucash_cursor_configure (GNUCASH_CURSOR(sheet->cursor));
401 gnc_item_edit_configure (gnucash_sheet_get_item_edit (sheet));
403 gnc_header_reconfigure (header);
405 gnucash_sheet_set_scroll_region (sheet);
406 gnucash_sheet_update_adjustments (sheet);
408 gnc_header_request_redraw (header);
409 gnucash_sheet_redraw_all (sheet);
413 gnc_header_auto_resize_column (
GncHeader *header, gint col)
417 width = gnucash_sheet_col_max_width (header->sheet, 0, col);
419 gnc_header_resize_column (header, col, width);
423 gnc_header_event (GtkWidget *widget, GdkEvent *event)
426 GdkWindow *window = gtk_widget_get_window (widget);
430 if (!header->resize_cursor)
431 header->resize_cursor = gdk_cursor_new_for_display (gdk_window_get_display (window),
432 GDK_SB_H_DOUBLE_ARROW);
436 case GDK_MOTION_NOTIFY:
440 if (header->in_resize)
442 int change = x - header->resize_x;
443 int new_width = header->resize_col_width + change;
447 header->resize_x = x;
448 header->resize_col_width = new_width;
449 gnc_header_request_redraw (header);
455 if (pointer_on_resize_line (header, x, y, &col) &&
456 gnucash_style_col_is_resizable (header->style, col))
457 gdk_window_set_cursor (window, header->resize_cursor);
459 gdk_window_set_cursor (window, header->normal_cursor);
462 case GDK_BUTTON_PRESS:
466 if (event->button.button != 1)
472 if (pointer_on_resize_line (header, x, y, &col))
473 col = find_resize_col (header, col);
481 cd = gnucash_style_get_cell_dimensions
482 (header->style, 0, col);
485 header->in_resize = TRUE;
486 header->resize_col = col;
487 header->resize_col_width = cd->pixel_width;
488 header->resize_x = x;
492 case GDK_BUTTON_RELEASE:
494 if (event->button.button != 1)
497 if (header->in_resize)
499 if (header->resize_col_width == 0)
500 header->resize_col_width = 1;
502 gnc_header_resize_column
505 header->resize_col_width);
506 header->in_resize = FALSE;
507 header->resize_col = -1;
508 gnc_header_request_redraw (header);
513 case GDK_2BUTTON_PRESS:
519 if (event->button.button != 1)
525 on_line = pointer_on_resize_line (header, x, y, &ptr_col);
530 resize_col = find_resize_col (header, ptr_col);
532 resize_col = ptr_col;
536 header->in_resize = FALSE;
537 header->resize_col = -1;
538 gnc_header_auto_resize_column (header, resize_col);
557 gnc_header_get_property (GObject *
object,
567 g_value_take_object (value, header->sheet);
569 case PROP_CURSOR_NAME:
570 g_value_set_string (value, header->cursor_name);
573 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, param_id, pspec);
579 gnc_header_set_property (GObject *
object,
585 GtkLayout *layout = GTK_LAYOUT(header);
586 gboolean needs_update = FALSE;
592 header->sheet = GNUCASH_SHEET(g_value_get_object (value));
593 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE(layout), header->sheet->hadj);
596 case PROP_CURSOR_NAME:
597 old_name = header->cursor_name;
599 header->cursor_name = g_value_dup_string (value);
600 needs_update = !old_name || !header->cursor_name ||
601 strcmp (old_name, header->cursor_name) != 0;
605 G_OBJECT_WARN_INVALID_PROPERTY_ID(
object, param_id, pspec);
609 if ((header->sheet != NULL) && needs_update)
610 gnc_header_reconfigure (header);
617 header->sheet = NULL;
618 header->cursor_name = NULL;
619 header->in_resize = FALSE;
620 header->resize_col = -1;
621 header->resize_cursor = NULL;
622 header->normal_cursor = NULL;
625 header->style = NULL;
627 gtk_widget_add_events (GTK_WIDGET(header),
629 | GDK_BUTTON_PRESS_MASK
630 | GDK_BUTTON_RELEASE_MASK
631 | GDK_POINTER_MOTION_MASK
632 | GDK_POINTER_MOTION_HINT_MASK));
634 g_signal_connect (G_OBJECT(header),
"configure_event",
635 G_CALLBACK(gnc_header_reconfigure), NULL);
636 gtk_widget_show_all (GTK_WIDGET(header));
643 GObjectClass *object_class = G_OBJECT_CLASS(header_class);
644 GtkWidgetClass *item_class = GTK_WIDGET_CLASS(header_class);
646 gtk_widget_class_set_css_name (GTK_WIDGET_CLASS(header_class),
"gnc-id-header");
648 object_class->finalize = gnc_header_finalize;
649 object_class->get_property = gnc_header_get_property;
650 object_class->set_property = gnc_header_set_property;
652 g_object_class_install_property (object_class,
654 g_param_spec_object (
"sheet",
659 g_object_class_install_property (object_class,
661 g_param_spec_string (
"cursor_name",
668 item_class->unrealize = gnc_header_unrealize;
669 item_class->draw = gnc_header_draw;
670 item_class->event = gnc_header_event;
674 gnc_header_new (GnucashSheet *sheet)
678 layout = g_object_new (GNC_TYPE_HEADER,
683 sheet->header_item = layout;
holds information about each virtual cell.
Convenience wrapper around GdkRGBA for use in Register Gnome classes.
Public declarations for GnucashCursor class.
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.
VirtualCell * gnc_table_get_virtual_cell(Table *table, VirtualCellLocation vcell_loc)
returns the virtual cell associated with a particular virtual location.
#define CURSOR_HEADER
Standard Cursor Names.
Public declarations of GnucashRegister class.
Private declarations for GnucashSheet class.
Public declarations for GncItemEdit class.
Styling functions for RegisterGnome.
BasicCell * gnc_cellblock_get_cell(CellBlock *cellblock, int row, int col)
Retrieve the Cell at the specified coordinates.