コード例 #1
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #2
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #3
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
VirtualCell *
gnc_table_get_header_cell (Table *table)
{
    VirtualCellLocation vcell_loc = { 0, 0 };

    return gnc_table_get_virtual_cell (table, vcell_loc);
}
コード例 #4
0
ファイル: gnucash-cursor.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #5
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #6
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #7
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #8
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #9
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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);
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #12
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}
コード例 #13
0
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;
}
コード例 #14
0
ファイル: gnucash-header.c プロジェクト: nishmu/gnucash
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;
    }
}
コード例 #15
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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");
}
コード例 #16
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
    }
}
コード例 #17
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
    }
}
コード例 #18
0
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);
}
コード例 #19
0
ファイル: table-allgui.c プロジェクト: Gnucash/gnucash
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;
}