static gboolean gnc_table_find_valid_cell_horiz (Table *table, VirtualLocation *virt_loc, gboolean exact_cell) { VirtualLocation vloc; VirtualCell *vcell; int left; int right; if (table == NULL) return FALSE; if (virt_loc == NULL) return FALSE; if (gnc_table_virtual_cell_out_of_bounds (table, virt_loc->vcell_loc)) return FALSE; if (gnc_table_virtual_loc_valid (table, *virt_loc, exact_cell)) return TRUE; vloc = *virt_loc; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); if (vcell == NULL) return FALSE; if (vcell->cellblock == NULL) return FALSE; if (vloc.phys_col_offset < 0) vloc.phys_col_offset = 0; if (vloc.phys_col_offset >= vcell->cellblock->num_cols) vloc.phys_col_offset = vcell->cellblock->num_cols - 1; left = vloc.phys_col_offset - 1; right = vloc.phys_col_offset + 1; while (left >= 0 || right < vcell->cellblock->num_cols) { vloc.phys_col_offset = right; if (gnc_table_virtual_loc_valid(table, vloc, FALSE)) { *virt_loc = vloc; return TRUE; } vloc.phys_col_offset = left; if (gnc_table_virtual_loc_valid(table, vloc, FALSE)) { *virt_loc = vloc; return TRUE; } left--; right++; } return FALSE; }
void gnc_table_set_vcell (Table *table, CellBlock *cursor, gconstpointer vcell_data, gboolean visible, gboolean start_primary_color, VirtualCellLocation vcell_loc) { VirtualCell *vcell; if ((table == NULL) || (cursor == NULL)) return; if ((vcell_loc.virt_row >= table->num_virt_rows) || (vcell_loc.virt_col >= table->num_virt_cols)) gnc_table_resize (table, MAX (table->num_virt_rows, vcell_loc.virt_row + 1), MAX (table->num_virt_cols, vcell_loc.virt_col + 1)); vcell = gnc_table_get_virtual_cell (table, vcell_loc); if (vcell == NULL) return; /* this cursor is the handler for this block */ vcell->cellblock = cursor; /* copy the vcell user data */ if (table->model->cell_data_copy) table->model->cell_data_copy (vcell->vcell_data, vcell_data); else vcell->vcell_data = (gpointer) vcell_data; vcell->visible = visible ? 1 : 0; vcell->start_primary_color = start_primary_color ? 1 : 0; }
VirtualCell * gnc_table_get_header_cell (Table *table) { VirtualCellLocation vcell_loc = { 0, 0 }; return gnc_table_get_virtual_cell (table, vcell_loc); }
static void gnucash_cursor_get_pixel_coords (GnucashCursor *cursor, gint *x, gint *y, gint *w, gint *h) { GnucashSheet *sheet = cursor->sheet; VirtualCellLocation vcell_loc; CellDimensions *cd; VirtualCell *vcell; SheetBlock *block; gint col; vcell_loc.virt_row = cursor->row; vcell_loc.virt_col = cursor->col; block = gnucash_sheet_get_block (sheet, vcell_loc); if (!block) return; vcell = gnc_table_get_virtual_cell (sheet->table, vcell_loc); if (!vcell) return; for (col = 0; col < vcell->cellblock->num_cols; col++) { BasicCell *cell; cell = gnc_cellblock_get_cell (vcell->cellblock, 0, col); if (cell && cell->cell_name) break; } *y = block->origin_y; cd = gnucash_style_get_cell_dimensions (block->style, 0, col); if (cd) *x = cd->origin_x; else *x = block->origin_x; for (col = vcell->cellblock->num_cols - 1; col >= 0; col--) { BasicCell *cell; cell = gnc_cellblock_get_cell (vcell->cellblock, 0, col); if (cell && cell->cell_name) break; } *h = block->style->dimensions->height; cd = gnucash_style_get_cell_dimensions (block->style, 0, col); if (cd) *w = cd->origin_x + cd->pixel_width - *x; else *w = block->style->dimensions->width - *x; }
gpointer gnc_table_get_vcell_data (Table *table, VirtualCellLocation vcell_loc) { VirtualCell *vcell; if (!table) return NULL; vcell = gnc_table_get_virtual_cell (table, vcell_loc); if (vcell == NULL) return NULL; return vcell->vcell_data; }
gboolean gnc_table_virtual_loc_valid(Table *table, VirtualLocation virt_loc, gboolean exact_pointer) { VirtualCell *vcell; CellIOFlags io_flags; if (!table) return FALSE; /* header rows cannot be modified */ if (virt_loc.vcell_loc.virt_row == 0) return FALSE; vcell = gnc_table_get_virtual_cell(table, virt_loc.vcell_loc); if (vcell == NULL) return FALSE; if (!vcell->visible) return FALSE; /* verify that offsets are valid. This may occur if the app that is * using the table has a paritally initialized cursor. (probably due * to a programming error, but maybe they meant to do this). */ if ((0 > virt_loc.phys_row_offset) || (0 > virt_loc.phys_col_offset)) return FALSE; /* check for a cell handler, but only if cell address is valid */ if (vcell->cellblock == NULL) return FALSE; /* if table is read-only, any cell is ok :) */ if (gnc_table_model_read_only (table->model)) return TRUE; io_flags = gnc_table_get_io_flags (table, virt_loc); /* if the cell allows ENTER, then it is ok */ if (io_flags & XACC_CELL_ALLOW_ENTER) return TRUE; /* if cell is marked as output-only, you can't enter */ if (0 == (XACC_CELL_ALLOW_INPUT & io_flags)) return FALSE; /* if cell is pointer only and this is not an exact pointer test, * it cannot be entered. */ if (!exact_pointer && ((XACC_CELL_ALLOW_EXACT_ONLY & io_flags) != 0)) return FALSE; return TRUE; }
void gnc_table_set_virt_cell_cursor (Table *table, VirtualCellLocation vcell_loc, CellBlock *cursor) { VirtualCell *vcell; if (table == NULL) return; vcell = gnc_table_get_virtual_cell (table, vcell_loc); if (vcell == NULL) return; vcell->cellblock = cursor; }
void gnc_table_set_virt_cell_visible (Table *table, VirtualCellLocation vcell_loc, gboolean visible) { VirtualCell *vcell; if (table == NULL) return; vcell = gnc_table_get_virtual_cell (table, vcell_loc); if (vcell == NULL) return; vcell->visible = visible ? 1 : 0; }
BasicCell * gnc_table_get_cell (Table *table, VirtualLocation virt_loc) { VirtualCell *vcell; if (!table) return NULL; vcell = gnc_table_get_virtual_cell (table, virt_loc.vcell_loc); if (!vcell) return NULL; return gnc_cellblock_get_cell (vcell->cellblock, virt_loc.phys_row_offset, virt_loc.phys_col_offset); }
static void gnc_entry_ledger_move_cursor (VirtualLocation *p_new_virt_loc, gpointer user_data) { GncEntryLedger *ledger = user_data; VirtualLocation new_virt_loc = *p_new_virt_loc; GncEntry *new_entry; GncEntry *old_entry; gboolean saved; if (!ledger) return; old_entry = gnc_entry_ledger_get_current_entry (ledger); new_entry = gnc_entry_ledger_get_entry (ledger, new_virt_loc.vcell_loc); gnc_suspend_gui_refresh (); saved = gnc_entry_ledger_save (ledger, old_entry != new_entry); gnc_resume_gui_refresh (); /* redrawing can muck everything up */ if (saved) { VirtualCellLocation vcell_loc; /* redraw */ gnc_entry_ledger_display_refresh (ledger); if (ledger->traverse_to_new) new_entry = gnc_entry_ledger_get_blank_entry (ledger); /* if the entry we were going to is still in the register, * then it may have moved. Find out where it is now. */ if (gnc_entry_ledger_find_entry (ledger, new_entry, &vcell_loc)) { VirtualCell *vcell; vcell = gnc_table_get_virtual_cell (ledger->table, vcell_loc); new_virt_loc.vcell_loc = vcell_loc; } else new_virt_loc.vcell_loc = ledger->table->current_cursor_loc.vcell_loc; } gnc_table_find_close_valid_cell (ledger->table, &new_virt_loc, FALSE); *p_new_virt_loc = new_virt_loc; }
gboolean gnc_table_get_cell_location (Table *table, const char *cell_name, VirtualCellLocation vcell_loc, VirtualLocation *virt_loc) { VirtualCell *vcell; CellBlock *cellblock; int cell_row, cell_col; if (table == NULL) return FALSE; vcell = gnc_table_get_virtual_cell (table, vcell_loc); if (vcell == NULL) return FALSE; cellblock = vcell->cellblock; for (cell_row = 0; cell_row < cellblock->num_rows; cell_row++) for (cell_col = 0; cell_col < cellblock->num_cols; cell_col++) { BasicCell *cell; cell = gnc_cellblock_get_cell (cellblock, cell_row, cell_col); if (!cell) continue; if (gnc_basic_cell_has_name (cell, cell_name)) { if (virt_loc != NULL) { virt_loc->vcell_loc = vcell_loc; virt_loc->phys_row_offset = cell_row; virt_loc->phys_col_offset = cell_col; } return TRUE; } } return FALSE; }
void gnc_table_set_virt_cell_data (Table *table, VirtualCellLocation vcell_loc, gconstpointer vcell_data) { VirtualCell *vcell; if (table == NULL) return; vcell = gnc_table_get_virtual_cell (table, vcell_loc); if (vcell == NULL) return; if (table->model->cell_data_copy) table->model->cell_data_copy (vcell->vcell_data, vcell_data); else vcell->vcell_data = (gpointer) vcell_data; }
static guint32 gnc_entry_ledger_get_bg_color (VirtualLocation virt_loc, gboolean *hatching, gpointer user_data) { GncEntryLedger *ledger = user_data; VirtualCell *vcell; guint32 bg_color; gboolean is_current; if (hatching) *hatching = FALSE; bg_color = 0xffffff; /* white */ if (!ledger) return bg_color; if (gnc_table_virtual_location_in_header (ledger->table, virt_loc)) return reg_colors.header_bg_color; vcell = gnc_table_get_virtual_cell (ledger->table, virt_loc.vcell_loc); if (!vcell || !vcell->cellblock) return bg_color; if ((virt_loc.phys_col_offset < vcell->cellblock->start_col) || (virt_loc.phys_col_offset > vcell->cellblock->stop_col)) return bg_color; is_current = virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc, virt_loc.vcell_loc); if (is_current) return vcell->start_primary_color ? reg_colors.primary_active_bg_color : reg_colors.secondary_active_bg_color; return vcell->start_primary_color ? reg_colors.primary_bg_color : reg_colors.secondary_bg_color; }
static void gnc_header_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) { GncHeader *header = GNC_HEADER(item); SheetBlockStyle *style = header->style; Table *table = header->sheet->table; VirtualLocation virt_loc; VirtualCell *vcell; CellDimensions *cd; GdkColor *bg_color; int xpaint, ypaint; const char *text; CellBlock *cb; guint32 argb, color_type; int i, j; int w, h; PangoLayout *layout; virt_loc.vcell_loc.virt_row = 0; virt_loc.vcell_loc.virt_col = 0; virt_loc.phys_row_offset = 0; virt_loc.phys_col_offset = 0; if (header->sheet->use_theme_colors) { color_type = gnc_table_get_gtkrc_bg_color (table, virt_loc, NULL); bg_color = get_gtkrc_color(header->sheet, color_type); } else { argb = gnc_table_get_bg_color (table, virt_loc, NULL); bg_color = gnucash_color_argb_to_gdk (argb); } h = style->dimensions->height; h *= header->num_phys_rows; h /= header->style->nrows; gdk_gc_set_foreground (header->gc, bg_color); gdk_draw_rectangle (drawable, header->gc, TRUE, 0, 0, style->dimensions->width, h); gdk_gc_set_line_attributes (header->gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_gc_set_foreground (header->gc, &gn_black); gdk_draw_rectangle (drawable, header->gc, FALSE, -x, -y, style->dimensions->width, h); gdk_draw_line (drawable, header->gc, 0, h + 1, style->dimensions->width, h + 1); gdk_gc_set_line_attributes (header->gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); gdk_gc_set_background (header->gc, &gn_white); gdk_gc_set_foreground (header->gc, &gn_black); /*font = gnucash_register_font;*/ vcell = gnc_table_get_virtual_cell (table, table->current_cursor_loc.vcell_loc); cb = vcell ? vcell->cellblock : NULL; ypaint = -y; h = 0; for (i = 0; i < style->nrows; i++) { xpaint = -x; virt_loc.phys_row_offset = i; /* TODO: This routine is duplicated in several places. Can we abstract at least the cell drawing routine? That way we'll be sure everything is drawn consistently, and cut down on maintenance issues. */ for (j = 0; j < style->ncols; j++) { /* gint x_offset, y_offset;*/ GdkRectangle rect; BasicCell *cell; virt_loc.phys_col_offset = j; cd = gnucash_style_get_cell_dimensions (style, i, j); if (header->in_resize && (j == header->resize_col)) w = header->resize_col_width; else w = cd->pixel_width; cell = gnc_cellblock_get_cell (cb, i, j); if (!cell || !cell->cell_name) { xpaint += w; continue; } h = cd->pixel_height; gdk_draw_rectangle (drawable, header->gc, FALSE, xpaint, ypaint, w, h); virt_loc.vcell_loc = table->current_cursor_loc.vcell_loc; text = gnc_table_get_label (table, virt_loc); if (!text) text = ""; layout = gtk_widget_create_pango_layout (GTK_WIDGET (header->sheet), text); /*y_offset = ((h / 2) + (((font->ascent + font->descent) / 2) - font->descent)); y_offset++;*/ switch (gnc_table_get_align (table, virt_loc)) { default: case CELL_ALIGN_LEFT: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; case CELL_ALIGN_RIGHT: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case CELL_ALIGN_CENTER: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; } rect.x = xpaint + CELL_HPADDING; rect.y = ypaint + 1; rect.width = MAX (0, w - (2 * CELL_HPADDING)); rect.height = h - 2; gdk_gc_set_clip_rectangle (header->gc, &rect); gdk_draw_layout (drawable, header->gc, xpaint + CELL_HPADDING, ypaint + 1, layout); g_object_unref (layout); gdk_gc_set_clip_rectangle (header->gc, NULL); xpaint += w; } ypaint += h; } }
static void gnc_table_move_cursor_internal (Table *table, VirtualLocation new_virt_loc, gboolean do_move_gui) { int cell_row, cell_col; VirtualLocation virt_loc; VirtualCell *vcell; CellBlock *curs; ENTER("new_virt=(%d %d) do_move_gui=%d\n", new_virt_loc.vcell_loc.virt_row, new_virt_loc.vcell_loc.virt_col, do_move_gui); /* call the callback, allowing the app to commit any changes * associated with the current location of the cursor. Note that * this callback may recursively call this routine. */ if (table->control->move_cursor && table->control->allow_move) { table->control->move_cursor (&new_virt_loc, table->control->user_data); /* The above callback can cause this routine to be called * recursively. As a result of this recursion, the cursor may * have gotten repositioned. We need to make sure we make * passive again. */ if (do_move_gui) gnc_table_refresh_current_cursor_gui (table, FALSE); } /* invalidate the cursor for now; we'll fix it back up below */ gnc_virtual_location_init (&table->current_cursor_loc); curs = table->current_cursor; table->current_cursor = NULL; /* check for out-of-bounds conditions (which may be deliberate) */ if ((new_virt_loc.vcell_loc.virt_row < 0) || (new_virt_loc.vcell_loc.virt_col < 0)) { /* if the location is invalid, then we should take this * as a command to unmap the cursor gui. */ if (do_move_gui && curs) { for (cell_row = 0; cell_row < curs->num_rows; cell_row++) for (cell_col = 0; cell_col < curs->num_cols; cell_col++) { BasicCell *cell; cell = gnc_cellblock_get_cell (curs, cell_row, cell_col); if (cell) { cell->changed = FALSE; cell->conditionally_changed = FALSE; if (cell->gui_move) cell->gui_move (cell); } } } LEAVE("out of bounds\n"); return; } if (!gnc_table_virtual_loc_valid (table, new_virt_loc, TRUE)) { PWARN("bad table location"); LEAVE(""); return; } /* ok, we now have a valid position. Find the new cursor to use, * and initialize its cells */ vcell = gnc_table_get_virtual_cell (table, new_virt_loc.vcell_loc); curs = vcell->cellblock; table->current_cursor = curs; /* record the new position */ table->current_cursor_loc = new_virt_loc; virt_loc.vcell_loc = new_virt_loc.vcell_loc; /* update the cell values to reflect the new position */ for (cell_row = 0; cell_row < curs->num_rows; cell_row++) for (cell_col = 0; cell_col < curs->num_cols; cell_col++) { BasicCell *cell; CellIOFlags io_flags; virt_loc.phys_row_offset = cell_row; virt_loc.phys_col_offset = cell_col; cell = gnc_cellblock_get_cell(curs, cell_row, cell_col); if (cell) { /* if a cell has a GUI, move that first, before setting * the cell value. Otherwise, we'll end up putting the * new values in the old cell locations, and that would * lead to confusion of all sorts. */ if (do_move_gui && cell->gui_move) cell->gui_move (cell); /* OK, now copy the string value from the table at large * into the cell handler. */ io_flags = gnc_table_get_io_flags (table, virt_loc); if (io_flags & XACC_CELL_ALLOW_SHADOW) { const char *entry; gboolean conditionally_changed = FALSE; entry = gnc_table_get_entry_internal (table, virt_loc, &conditionally_changed); gnc_basic_cell_set_value (cell, entry); cell->changed = FALSE; cell->conditionally_changed = conditionally_changed; } } } LEAVE("did move\n"); }
gboolean gnc_table_move_vertical_position (Table *table, VirtualLocation *virt_loc, int phys_row_offset) { VirtualLocation vloc; VirtualCell *vcell; gint last_visible_row; if ((table == NULL) || (virt_loc == NULL)) return FALSE; vloc = *virt_loc; last_visible_row = vloc.vcell_loc.virt_row; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); if ((vcell == NULL) || (vcell->cellblock == NULL)) return FALSE; while (phys_row_offset != 0) { /* going up */ if (phys_row_offset < 0) { phys_row_offset++; /* room left in the current cursor */ if (vloc.phys_row_offset > 0) { vloc.phys_row_offset--; continue; } /* end of the line */ if (vloc.vcell_loc.virt_row == 1) break; do { vloc.vcell_loc.virt_row--; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); } while (vcell && vcell->cellblock && !vcell->visible); if (!vcell || !vcell->cellblock) break; last_visible_row = vloc.vcell_loc.virt_row; vloc.phys_row_offset = vcell->cellblock->num_rows - 1; } /* going down */ else { phys_row_offset--; /* room left in the current cursor */ if (vloc.phys_row_offset < (vcell->cellblock->num_rows - 1)) { vloc.phys_row_offset++; continue; } /* end of the line */ if (vloc.vcell_loc.virt_row == (table->num_virt_rows - 1)) break; do { vloc.vcell_loc.virt_row++; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); } while (vcell && vcell->cellblock && !vcell->visible); if (!vcell || !vcell->cellblock) break; last_visible_row = vloc.vcell_loc.virt_row; vloc.phys_row_offset = 0; } } vloc.vcell_loc.virt_row = last_visible_row; { gboolean changed = !virt_loc_equal (vloc, *virt_loc); *virt_loc = vloc; return changed; } }
gboolean gnc_table_move_tab (Table *table, VirtualLocation *virt_loc, gboolean move_right) { VirtualCell *vcell; VirtualLocation vloc; BasicCell *cell; if ((table == NULL) || (virt_loc == NULL)) return FALSE; vloc = *virt_loc; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); if ((vcell == NULL) || (vcell->cellblock == NULL) || !vcell->visible) return FALSE; while (1) { CellIOFlags io_flags; if (move_right) { vloc.phys_col_offset++; if (vloc.phys_col_offset >= vcell->cellblock->num_cols) { if (!gnc_table_move_vertical_position (table, &vloc, 1)) return FALSE; vloc.phys_col_offset = 0; } } else { vloc.phys_col_offset--; if (vloc.phys_col_offset < 0) { if (!gnc_table_move_vertical_position (table, &vloc, -1)) return FALSE; vloc.phys_col_offset = vcell->cellblock->num_cols - 1; } } vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); if ((vcell == NULL) || (vcell->cellblock == NULL) || !vcell->visible) return FALSE; cell = gnc_cellblock_get_cell (vcell->cellblock, vloc.phys_row_offset, vloc.phys_col_offset); if (!cell) continue; io_flags = gnc_table_get_io_flags (table, vloc); if (!(io_flags & XACC_CELL_ALLOW_INPUT)) continue; if (io_flags & XACC_CELL_ALLOW_EXACT_ONLY) continue; break; } { gboolean changed = !virt_loc_equal (vloc, *virt_loc); *virt_loc = vloc; return changed; } }
static void gnc_header_draw_offscreen (GncHeader *header) { SheetBlockStyle *style = header->style; Table *table = header->sheet->table; VirtualLocation virt_loc; VirtualCell *vcell; guint32 color_type; GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(header)); GdkRGBA color; int row_offset; CellBlock *cb; int i; cairo_t *cr; virt_loc.vcell_loc.virt_row = 0; virt_loc.vcell_loc.virt_col = 0; virt_loc.phys_row_offset = 0; virt_loc.phys_col_offset = 0; gtk_style_context_save (stylectxt); // Get the background color type and apply the css class color_type = gnc_table_get_bg_color (table, virt_loc, NULL); gnucash_get_style_classes (header->sheet, stylectxt, color_type); if (header->surface) cairo_surface_destroy (header->surface); header->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, header->width, header->height); cr = cairo_create (header->surface); // Fill background color of header gtk_render_background (stylectxt, cr, 0, 0, header->width, header->height); gdk_rgba_parse (&color, "black"); cairo_set_source_rgb (cr, color.red, color.green, color.blue); cairo_rectangle (cr, 0.5, 0.5, header->width - 1.0, header->height - 1.0); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); // Draw bottom horizontal line, makes bottom line thicker cairo_move_to (cr, 0.5, header->height - 1.5); cairo_line_to (cr, header->width - 1.0, header->height - 1.5); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); /*font = gnucash_register_font;*/ vcell = gnc_table_get_virtual_cell (table, table->current_cursor_loc.vcell_loc); cb = vcell ? vcell->cellblock : NULL; row_offset = 0; for (i = 0; i < style->nrows; i++) { int col_offset = 0; int h = 0, j; virt_loc.phys_row_offset = i; /* TODO: This routine is duplicated in several places. Can we abstract at least the cell drawing routine? That way we'll be sure everything is drawn consistently, and cut down on maintenance issues. */ for (j = 0; j < style->ncols; j++) { CellDimensions *cd; double text_x, text_y, text_w, text_h; BasicCell *cell; const char *text; int w; PangoLayout *layout; virt_loc.phys_col_offset = j; cd = gnucash_style_get_cell_dimensions (style, i, j); h = cd->pixel_height; if (header->in_resize && (j == header->resize_col)) w = header->resize_col_width; else w = cd->pixel_width; cell = gnc_cellblock_get_cell (cb, i, j); if (!cell || !cell->cell_name) { col_offset += w; continue; } cairo_rectangle (cr, col_offset - 0.5, row_offset + 0.5, w, h); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); virt_loc.vcell_loc = table->current_cursor_loc.vcell_loc; text = gnc_table_get_label (table, virt_loc); if (!text) text = ""; layout = gtk_widget_create_pango_layout (GTK_WIDGET (header->sheet), text); switch (gnc_table_get_align (table, virt_loc)) { default: case CELL_ALIGN_LEFT: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; case CELL_ALIGN_RIGHT: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case CELL_ALIGN_CENTER: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; } text_x = col_offset + CELL_HPADDING; text_y = row_offset + 1; text_w = MAX (0, w - (2 * CELL_HPADDING)); text_h = h - 2; cairo_save (cr); cairo_rectangle (cr, text_x, text_y, text_w, text_h); cairo_clip (cr); gtk_render_layout (stylectxt, cr, text_x, text_y, layout); cairo_restore (cr); g_object_unref (layout); col_offset += w; } row_offset += h; } gtk_style_context_restore (stylectxt); cairo_destroy (cr); }
static gboolean gnc_table_find_valid_row_vert (Table *table, VirtualLocation *virt_loc) { VirtualLocation vloc; VirtualCell *vcell = NULL; int top; int bottom; if (table == NULL) return FALSE; if (virt_loc == NULL) return FALSE; vloc = *virt_loc; if (vloc.vcell_loc.virt_row < 1) vloc.vcell_loc.virt_row = 1; if (vloc.vcell_loc.virt_row >= table->num_virt_rows) vloc.vcell_loc.virt_row = table->num_virt_rows - 1; top = vloc.vcell_loc.virt_row; bottom = vloc.vcell_loc.virt_row + 1; while (top >= 1 || bottom < table->num_virt_rows) { vloc.vcell_loc.virt_row = top; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); if (vcell && vcell->cellblock && vcell->visible) { vloc.phys_row_offset = 0; vloc.phys_col_offset = 0; if (gnc_table_find_valid_cell_horiz (table, &vloc, FALSE)) break; } vloc.vcell_loc.virt_row = bottom; vcell = gnc_table_get_virtual_cell (table, vloc.vcell_loc); if (vcell && vcell->cellblock && vcell->visible) { vloc.phys_row_offset = 0; vloc.phys_col_offset = 0; if (gnc_table_find_valid_cell_horiz (table, &vloc, FALSE)) break; } top--; bottom++; } if (!vcell || !vcell->cellblock || !vcell->visible) return FALSE; if (vloc.phys_row_offset < 0) vloc.phys_row_offset = 0; if (vloc.phys_row_offset >= vcell->cellblock->num_rows) vloc.phys_row_offset = vcell->cellblock->num_rows - 1; virt_loc->vcell_loc = vloc.vcell_loc; return TRUE; }