gambas-source-code/gb.gtk/src/tablerender.cpp
Benoît Minisini 47d0aa711c [CONFIGURATION]
* NEW: Architecture detection.
* NEW: Updated libtool macros.

[DEVELOPMENT ENVIRONMENT]
* NEW: Highlight the current procedure in the editor procedure popup.

[INTERPRETER]
* BUG: Alignment fixes for the ARM architecture.

[GB.DRAW]
* NEW: Start implementing the new Paint interface.

[GB.GTK]
* BUG: GridView.Clear is now correctly implemented.


git-svn-id: svn://localhost/gambas/trunk@2505 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2009-12-24 02:02:05 +00:00

1555 lines
31 KiB
C++

/***************************************************************************
tablerender.cpp
(c) 2000-2009 Benoît Minisini <gambas@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***************************************************************************/
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "gmemory.h"
#include "ggridview.h"
#include "tablerender.h"
#define GET_ROW_SPAN(_span) ((int)(short)(((intptr_t)_span) & 0xFFFF))
#define GET_COL_SPAN(_span) ((int)(short)((((intptr_t)_span) >> 16) & 0xFFFF))
#define MAKE_SPAN(_rowspan, _colspan) ((gpointer)(((uint)(unsigned short)(_rowspan)) | (((uint)(unsigned short)(_colspan)) << 16)))
//***********************************
// gTableData
//***********************************
gTableData::gTableData()
{
text = NULL;
richText = NULL;
markup = NULL;
picture = NULL;
font = NULL;
bg = COLOR_DEFAULT;
fg = COLOR_DEFAULT;
padding = 0;
alignment = ALIGN_NORMAL;
wordWrap = false;
}
gTableData::~gTableData()
{
clear();
}
void gTableData::setText(const char *vl)
{
if (text)
g_free(text);
if (vl)
text = g_strdup(vl);
else
text = NULL;
}
void gTableData::setRichText(const char *vl)
{
if (richText)
{
g_free(richText);
g_free(markup);
}
if (vl)
{
richText = g_strdup(vl);
markup = gt_html_to_pango_string(richText, -1, true);
}
else
{
richText = NULL;
markup = NULL;
}
}
void gTableData::clear()
{
if (text) g_free(text);
if (richText) g_free(richText);
if (markup) g_free(markup);
gFont::assign(&font);
gPicture::assign(&picture);
text = NULL;
richText = NULL;
markup = NULL;
picture=NULL;
font=NULL;
bg = COLOR_DEFAULT;
fg = COLOR_DEFAULT;
padding = 0;
alignment = ALIGN_NORMAL;
}
//***********************************
// gTable
//***********************************
gboolean gTable_ecol(gTablePair *key,gTableData *data,int number)
{
if ( (key->row == number) && (key->col!=-1) ) return true;
return false;
}
gboolean gTable_remove_row(gTablePair *key,gTableData *data,int number)
{
if (key->row >= number) return true;
return false;
}
gboolean gTable_remove_col(gTablePair *key,gTableData *data,int number)
{
if (key->col >= number) return true;
return false;
}
gboolean gTable_equal (gTablePair *a, gTablePair *b)
{
if ( a->col != b->col) return false;
if ( a->row != b->row) return false;
return true;
}
void gTable_ekey(gTablePair *pair)
{
if (pair) g_free(pair);
}
void gTable_edata(gTableData *data)
{
if (data) delete data;
}
gTable::gTable()
{
colpos = colsize = NULL;
rowpos = rowsize = NULL;
columns = 0;
rows = 0;
doNotInvalidate = false;
seldata = g_hash_table_new_full((GHashFunc)g_int_hash, (GEqualFunc)gTable_equal, (GDestroyNotify)gTable_ekey, NULL);
spanHash = g_hash_table_new_full((GHashFunc)g_int_hash, (GEqualFunc)gTable_equal, (GDestroyNotify)gTable_ekey, NULL);
data = g_hash_table_new_full((GHashFunc)g_int_hash, (GEqualFunc)gTable_equal, (GDestroyNotify)gTable_ekey, (GDestroyNotify)gTable_edata);
}
gTable::~gTable()
{
g_hash_table_destroy(data);
g_hash_table_destroy(seldata);
g_hash_table_destroy(spanHash);
g_free(rowsize);
g_free(rowpos);
g_free(colsize);
g_free(colpos);
}
void gTable::clear()
{
g_hash_table_destroy(data);
g_hash_table_destroy(seldata);
g_hash_table_destroy(spanHash);
seldata = g_hash_table_new_full((GHashFunc)g_int_hash, (GEqualFunc)gTable_equal, (GDestroyNotify)gTable_ekey, NULL);
spanHash = g_hash_table_new_full((GHashFunc)g_int_hash, (GEqualFunc)gTable_equal, (GDestroyNotify)gTable_ekey, NULL);
data = g_hash_table_new_full((GHashFunc)g_int_hash, (GEqualFunc)gTable_equal, (GDestroyNotify)gTable_ekey, (GDestroyNotify)gTable_edata);
}
int gTable::columnCount()
{
return columns;
}
int gTable::rowCount()
{
return rows;
}
void gTable::setRowCount(int number)
{
int bc;
if (number<0) number=0;
if (number==rows) return;
if (number>rows)
{
if (!rows)
{
rowsize = g_new(int, number);
rowpos = g_new(int, number);
}
else
{
rowsize = g_renew(int, rowsize, number);
rowpos = g_renew(int, rowpos, number);
}
for (bc=rows; bc<number; bc++)
{
rowpos[bc] = -1;
rowsize[bc] = 20;
}
rowpos[0] = 0;
}
else
{
if (!number)
{
g_free(rowsize); rowsize = NULL;
g_free(rowpos); rowpos = NULL;
}
else
{
rowsize = g_renew(int, rowsize, number);
rowpos = g_renew(int, rowpos, number);
}
g_hash_table_foreach_remove(data, (GHRFunc)gTable_remove_row, (gpointer)number);
g_hash_table_foreach_remove(seldata, (GHRFunc)gTable_remove_row, (gpointer)number);
g_hash_table_foreach_remove(spanHash, (GHRFunc)gTable_remove_row, (gpointer)number);
}
rows = number;
}
void gTable::setColumnCount(int number)
{
int bc;
if (number<0) number=0;
if (number==columns) return;
if (number>columns)
{
if (!columns)
{
colsize = g_new(int, number);
colpos = g_new(int, number);
}
else
{
colsize = g_renew(int, colsize, number);
colpos = g_renew(int, colpos, number);
}
for (bc=columns; bc<number; bc++)
{
colpos[bc] = -1;
colsize[bc] = 8;
}
colpos[0] = 0;
}
else
{
if (!number)
{
g_free(colpos); colpos = NULL;
g_free(colsize); colsize = NULL;
}
else
{
colsize = g_renew(int, colsize, number);
colpos = g_renew(int, colpos, number);
}
g_hash_table_foreach_remove(data, (GHRFunc)gTable_remove_col, (gpointer)number);
g_hash_table_foreach_remove(seldata, (GHRFunc)gTable_remove_col, (gpointer)number);
g_hash_table_foreach_remove(spanHash, (GHRFunc)gTable_remove_col, (gpointer)number);
}
columns = number;
}
gTableData *gTable::getData(int row, int col, bool create)
{
static gTableData cell;
gTableData *d;
gTablePair pair = {row, col};
gTablePair *key;
if (col < 0 || col >= columns || row < 0 || row >= rows)
return NULL;
d = (gTableData*)g_hash_table_lookup(data, (gpointer)&pair);
if (!d)
{
if (create)
{
key = (gTablePair *)g_malloc(sizeof(gTablePair));
key->row = row;
key->col = col;
d = new gTableData();
g_hash_table_insert(data, (gpointer)key, (gpointer)d);
}
else
{
cell.clear();
if (voidCell) voidCell(&cell, row, col, userData);
d = &cell;
}
}
return d;
}
void gTable::moveCell(int srow, int scol, int drow, int dcol)
{
gTableData *d;
gTablePair pair;
gTablePair *key;
pair.row = drow;
pair.col = dcol;
g_hash_table_remove(data, (gpointer)&pair);
pair.row = srow;
pair.col = scol;
if (!g_hash_table_lookup_extended(data, (gconstpointer)&pair, POINTER(&key), POINTER(&d)))
return;
g_hash_table_steal(data, &pair);
key->row = drow;
key->col = dcol;
g_hash_table_insert(data, (gpointer)key, (gpointer)d);
}
void gTable::clearField (int col,int row)
{
gTableData *ptr;
gTablePair pair={row,col};
if ( (col<0) || (col>=columns) ) return;
if ( (row<0) || (row>=rows) ) return;
ptr=(gTableData*)g_hash_table_lookup(data,(gpointer)&pair);
if (!ptr) return;
g_hash_table_remove(data,(gpointer)&pair);
}
char* gTable::getFieldText(int col,int row)
{
gTableData *d = getData(row, col);
return d ? d->text : NULL;
}
void gTable::setFieldText(int col,int row, const char* value)
{
gTableData *d = getData(row, col, true);
d->setText(value);
}
char* gTable::getFieldRichText(int col,int row)
{
gTableData *d = getData(row, col);
return d ? d->richText : NULL;
}
void gTable::setFieldRichText(int col,int row, const char* value)
{
gTableData *d = getData(row, col, true);
d->setRichText(value);
}
gColor gTable::getFieldFg (int col,int row)
{
gTableData *d = getData(row, col);
return d ? d->fg : COLOR_DEFAULT;
}
void gTable::setFieldFg (int col,int row, gColor value)
{
gTableData *d = getData(row, col, true);
d->fg = value;
}
gColor gTable::getFieldBg (int col,int row)
{
gTableData *d = getData(row, col);
return d ? d->bg : COLOR_DEFAULT;
}
void gTable::setFieldBg (int col,int row, gColor value)
{
gTableData *d = getData(row, col, true);
d->bg = value;
}
int gTable::getFieldPadding(int col, int row)
{
gTableData *d = getData(row, col);
return d ? d->padding : 0;
}
void gTable::setFieldPadding(int col, int row, int value)
{
gTableData *d = getData(row, col, true);
d->padding = value;
}
int gTable::getFieldAlignment(int col, int row)
{
gTableData *d = getData(row, col);
return d ? d->alignment : 0;
}
void gTable::setFieldAlignment(int col, int row, int value)
{
gTableData *d = getData(row, col, true);
d->alignment = value;
}
gPicture *gTable::getFieldPicture(int col, int row)
{
gTableData *d = getData(row, col);
return d ? d->picture : 0;
}
void gTable::setFieldPicture(int col, int row, gPicture *value)
{
gTableData *d = getData(row, col, true);
d->setPicture(value);
}
gFont *gTable::getFieldFont(int col, int row)
{
gTableData *d = getData(row, col);
return d ? d->font : 0;
}
void gTable::setFieldFont(int col, int row, gFont *value)
{
gTableData *d = getData(row, col, true);
d->setFont(value);
}
bool gTable::getFieldWordWrap(int col, int row)
{
gTableData *d = getData(row, col);
return d ? d->wordWrap : false;
}
void gTable::setFieldWordWrap(int col, int row, bool value)
{
gTableData *d = getData(row, col, true);
d->wordWrap = value;
}
bool gTable::getRowSelected(int row)
{
gTablePair pair={row,-1};
if ( (row<0) || (row>=rows) ) return false;
if (g_hash_table_lookup(seldata,(gpointer)&pair)) return true;
return false;
}
void gTable::setRowSelected(int row,bool value)
{
gTablePair pair={row,-1};
gTablePair *key;
if ( (row<0) || (row>=rows) ) return;
if (g_hash_table_lookup(seldata,(gpointer)&pair))
{
if (value) return;
g_hash_table_remove(seldata,(gpointer)&pair);
}
if (value)
{
key=(gTablePair*)g_malloc(sizeof(gTablePair));
key->row=row;
key->col=-1;
g_hash_table_insert(seldata,(gpointer)key,(gpointer)true);
}
if (!value) g_hash_table_foreach_remove(seldata,(GHRFunc)gTable_ecol,(gpointer)row);
}
bool gTable::getFieldSelected (int col,int row)
{
gTablePair pair={row,col};
if ( (col<0) || (col>=columns) ) return false;
if ( (row<0) || (row>=rows) ) return false;
if (g_hash_table_lookup(seldata,(gpointer)&pair)) return true;
pair.col=-1;
if (g_hash_table_lookup(seldata,(gpointer)&pair)) return true;
return false;
}
void gTable::setFieldSelected (int col,int row,bool value)
{
gTablePair pair={row,col};
gTablePair *key;
int bc;
if ( (col<0) || (col>=columns) ) return;
if ( (row<0) || (row>=rows) ) return;
if (g_hash_table_lookup(seldata,(gpointer)&pair))
{
if (value) return;
g_hash_table_remove(seldata,(gpointer)&pair);
pair.col=-1;
if (g_hash_table_lookup(seldata,(gpointer)&pair))
g_hash_table_remove(seldata,(gpointer)&pair);
return;
}
if (!value)
{
pair.col=-1;
if (g_hash_table_lookup(seldata,(gpointer)&pair))
{
g_hash_table_remove(seldata,(gpointer)&pair);
for (bc=0; bc<columnCount(); bc++)
if (bc != col) setFieldSelected(bc,row,true);
}
return;
}
key=(gTablePair*)g_malloc(sizeof(gTablePair));
key->row=row;
key->col=col;
g_hash_table_insert(seldata,(gpointer)key,(gpointer)value);
}
void gTable::getSpan(int col, int row, int *colspan, int *rowspan)
{
gTablePair pair = { row, col };
gpointer span;
*colspan = 0;
*rowspan = 0;
if ((col < 0) || (col >= columns)) return;
if ((row < 0) || (row >= rows)) return;
span = g_hash_table_lookup(spanHash, (gpointer)&pair);
if (!span)
return;
*colspan = GET_COL_SPAN(span);
if (*colspan >= (columns - col - 1))
*colspan = columns - col - 1;
*rowspan = GET_ROW_SPAN(span);
if (*rowspan >= (rows - row - 1))
*rowspan = rows - row - 1;
}
void gTable::setSpan(int col, int row, int colspan, int rowspan)
{
gTablePair pair = { row, col };
gTablePair *key;
int i, j;
int oldcs, oldrs;
gpointer span;
if ((col < 0) || (col >= columns)) return;
if ((row < 0) || (row >= rows)) return;
if (rowspan < -32768 || rowspan > 32767)
return;
if (colspan < -32768 || colspan > 32767)
return;
span = g_hash_table_lookup(spanHash, (gpointer)&pair);
oldcs = GET_COL_SPAN(span);
oldrs = GET_ROW_SPAN(span);
if ((oldcs < 0 || oldrs < 0) && (colspan != 0 || rowspan != 0))
return;
g_hash_table_remove(spanHash, (gpointer)&pair);
if (oldcs > 0 || oldrs > 0)
{
i = 1; j = 0;
for(;;)
{
if (i > oldcs)
{
i = 0;
j++;
if (j > oldrs)
break;
}
setSpan(col + i, row + j, 0, 0);
i++;
}
}
if (rowspan == 0 && colspan == 0)
return;
key = (gTablePair*)g_malloc(sizeof(gTablePair));
key->row = row;
key->col = col;
g_hash_table_insert(spanHash, (gpointer)key, (gpointer)MAKE_SPAN(rowspan, colspan));
if (rowspan >= 0 && colspan >= 0)
{
i = 1; j = 0;
for(;;)
{
if (i > colspan)
{
i = 0;
j++;
if (j > rowspan)
break;
}
setSpan(col + i, row + j, -i, -j);
i++;
}
}
}
int gTable::getColumnPos(int index)
{
int pos, i;
if (index < 0 || index >= columns)
return -1;
pos = colpos[index];
if (pos < 0)
{
i = index;
for(;;)
{
i--;
if (colpos[i] >= 0)
break;
}
pos = colpos[i];
for(;;)
{
pos += colsize[i];
i++;
if (i > index)
break;
colpos[i] = pos;
}
pos = colpos[index];
}
return pos;
}
int gTable::getRowPos(int index)
{
int pos, i;
if (index < 0 || index >= rows)
return -1;
pos = rowpos[index];
if (pos < 0)
{
i = index;
for(;;)
{
i--;
if (rowpos[i] >= 0)
break;
}
pos = rowpos[i];
for(;;)
{
pos += rowsize[i];
i++;
if (i > index)
break;
rowpos[i] = pos;
}
pos = rowpos[index];
}
return pos;
}
int gTable::getColumnSize (int position)
{
if (position>=columns) return -1;
if (position<0) return -1;
return colsize[position];
}
void gTable::setColumnSize(int position, int value)
{
int i;
if (position < 0 || position >= columns) return;
if (value<0) value=0;
colsize[position]=value;
if (!doNotInvalidate)
{
for (i = position + 1; i < columns; i++)
colpos[i] = -1;
}
}
int gTable::getRowSize (int position)
{
if (position>=rows) return -1;
if (position<0) return -1;
return rowsize[position];
}
void gTable::setRowSize (int position,int value)
{
int i;
if (position < 0 || position >= rows)
return;
if (value < 0) value = 0;
rowsize[position] = value;
if (!doNotInvalidate)
{
for (i = position + 1; i < rows; i++)
rowpos[i] = -1;
}
}
//***********************************
// gTableRender
//***********************************
static gboolean tbrender_expose(GtkWidget *wid,GdkEventExpose *e,gTableRender *data)
{
data->render(&e->area);
return FALSE;
}
gTableRender::gTableRender(gGridView *v)
{
voidCell=NULL;
userData=NULL;
grid=true;
txt=(GtkCellRendererText*)gtk_cell_renderer_text_new();
g_object_ref_sink(txt);
pix=(GtkCellRendererPixbuf*)gtk_cell_renderer_pixbuf_new();
g_object_ref_sink(pix);
view = v;
sf = view->contents;
offX=0;
offY=0;
firstRow = offRow = 0;
firstCol = offCol = 0;
g_object_ref(G_OBJECT(sf));
g_signal_connect(G_OBJECT(sf),"expose-event",G_CALLBACK(tbrender_expose),this);
//g_signal_connect(G_OBJECT(sf),"size-allocate",G_CALLBACK(cb_render_size_allocate),this);
}
void gTableRender::queryUpdate(int row, int col)
{
GdkRectangle rect;
int i;
int srow, scol;
int rowspan, colspan;
if (row >= rowCount()) return;
if (col >= columnCount()) return;
if (!sf->window) return;
if (col < 0)
{
rect.x = -getOffsetX();
gdk_drawable_get_size(sf->window, &rect.width, NULL);
}
else
{
rect.x = getColumnPos(col) - getOffsetX();
rect.width = getColumnSize(col);
}
if (row < 0)
{
rect.y = -getOffsetY();
gdk_drawable_get_size(sf->window, NULL, &rect.height);
}
else
{
rect.y = getRowPos(row) - getOffsetY();
rect.height = getRowSize(row);
}
if (col < 0)
{
gdk_window_invalidate_rect(sf->window, &rect, TRUE);
for (i = 0; i < columnCount(); i++)
queryUpdate(row, i);
return;
}
if (row < 0)
{
gdk_window_invalidate_rect(sf->window, &rect, TRUE);
for (i = 0; i < rowCount(); i++)
queryUpdate(i, col);
return;
}
//for (i = 0; i < col; i++) rect.x += getColumnSize(i);
//for (i = 0; i < row; i++) rect.y += getRowSize(i);
getSpan(col, row, &colspan, &rowspan);
if (colspan >= 0 && rowspan >= 0)
{
for (i = 1; i <= colspan; i++)
rect.width += getColumnSize(col + i);
for (i = 1; i <= rowspan; i++)
rect.height += getRowSize(row + i);
}
else
{
srow = row + colspan;
scol = col + rowspan;
for (i = scol; i < col; i++)
rect.x -= getColumnSize(i);
for (i = srow; i < row; i++)
rect.y -= getRowSize(i);
getSpan(scol, srow, &colspan, &rowspan);
rect.width = 0;
rect.height = 0;
for (i = 0; i <= colspan; i++)
rect.width += getColumnSize(scol + i);
for (i = 0; i <= rowspan; i++)
rect.height += getRowSize(srow + i);
}
// if (col < 0)
// {
// rect.x = 0;
// gdk_drawable_get_size(sf->window,&rect.width,NULL);
// }
// if (row < 0)
// {
// rect.y = 0;
// gdk_drawable_get_size(sf->window,NULL,&rect.height);
// }
gdk_window_invalidate_rect(sf->window,&rect,TRUE);
}
gTableRender::~gTableRender()
{
g_object_unref(G_OBJECT(pix));
g_object_unref(G_OBJECT(txt));
if (sf) g_object_unref(G_OBJECT(sf));
}
bool gTableRender::drawGrid()
{
return grid;
}
void gTableRender::setDrawGrid(bool vl)
{
if (grid == vl) return;
grid=vl;
gtk_widget_queue_draw(sf);
}
int gTableRender::visibleWidth()
{
int vl;
if (!sf->window) return 0;
gdk_drawable_get_size (sf->window,&vl,NULL);
return vl;
}
int gTableRender::visibleHeight()
{
int vl;
if (!sf->window) return 0;
gdk_drawable_get_size (sf->window,NULL,&vl);
return vl;
}
int gTableRender::width()
{
if (columnCount() <= 0)
return 0;
else
return getColumnPos(columnCount() - 1) + getColumnSize(columnCount() - 1);
}
int gTableRender::height()
{
if (rowCount() <= 0)
return 0;
else
return getRowPos(rowCount() - 1) + getRowSize(rowCount() - 1);
}
int gTableRender::getOffsetX()
{
return offX;
}
int gTableRender::getOffsetY()
{
return offY;
}
void gTableRender::setOffsetX(int vl)
{
int diff;
if (offX != vl)
{
diff=offX-vl;
offX=vl;
/*for (offCol = 0, firstCol = 0; firstCol < columnCount(); firstCol++)
{
w = getColumnSize(firstCol);
if ((offCol + w) > offX)
break;
offCol += w;
}*/
firstCol = findColumn(offX);
offCol = getColumnPos(firstCol);
if (!sf->window) return;
gdk_window_scroll(sf->window,diff,0);
}
}
void gTableRender::setOffsetY(int vl)
{
int diff;
if (offY != vl)
{
diff=offY-vl;
offY=vl;
/*for (offRow = 0, firstRow = 0; firstRow < rowCount(); firstRow++)
{
h = getRowSize(firstRow);
if ((offRow + h) > offY)
break;
offRow += h;
}*/
firstRow = findRow(offY);
offRow = getRowPos(firstRow);
if (!sf->window) return;
gdk_window_scroll(sf->window,0,diff);
}
}
void gTableRender::renderCell(gTableData *data, GdkGC *gc, GdkRectangle *rect, bool sel)
{
GdkColor color;
char *markup = data->markup;
char *buf = data->text;
int padding = data->padding;
double xa, ya;
bool hasText = (markup && *markup) || (buf && *buf);
if (sel)
gdk_gc_set_foreground(gc, &sf->style->base[GTK_STATE_SELECTED]);
else if (data->bg != COLOR_DEFAULT)
{
fill_gdk_color(&color, data->bg);
gdk_gc_set_foreground(gc, &color);
}
else
goto __NO_BG; //fill_gdk_color(&color, view->realBackground());
gdk_draw_rectangle(sf->window, gc, TRUE, rect->x, rect->y, rect->width, rect->height);
__NO_BG:
if (grid)
{
gdk_gc_set_foreground(gc, &sf->style->mid[GTK_STATE_NORMAL]);
gdk_draw_line(sf->window, gc, rect->x + rect->width - 1, rect->y, rect->x + rect->width - 1, rect->y + rect->height - 1);
gdk_draw_line(sf->window, gc, rect->x, rect->y + rect->height - 1, rect->x + rect->width - 1, rect->y + rect->height - 1);
}
if (padding < 1)
padding = 1;
rect->x += padding;
rect->y += padding;
rect->width -= padding * 2;
rect->height -= padding * 2;
if (rect->width < 1 || rect->height < 1)
return;
xa = gt_from_alignment(data->alignment, false);
ya = gt_from_alignment(data->alignment, true);
if (data->picture)
{
g_object_set(G_OBJECT(pix),
"pixbuf", data->picture->getPixbuf(),
"xalign", hasText ? 0 : xa,
"yalign", hasText ? 0.5 : ya,
(void *)NULL);
gtk_cell_renderer_render(GTK_CELL_RENDERER(pix),sf->window,sf,rect,rect,rect,(GtkCellRendererState)0);
rect->x += data->picture->width() + padding;
rect->width -= data->picture->width() + padding;
if (rect->width < 1)
return;
}
g_object_set(G_OBJECT(txt),
/*"font-desc", data->font ? data->font->desc() : sf->style->font_desc,*/
"xalign", xa,
"yalign", ya,
"wrap-width", data->wordWrap ? rect->width : -1,
"wrap-mode", PANGO_WRAP_WORD_CHAR,
(void *)NULL);
gt_set_cell_renderer_text_from_font(txt, data->font ? data->font : view->font());
g_object_set(G_OBJECT(txt),
"foreground-set", sel || data->fg != COLOR_DEFAULT,
"background-set", FALSE,
(void *)NULL);
if (sel)
{
g_object_set(G_OBJECT(txt),"foreground-gdk", &sf->style->text[GTK_STATE_SELECTED],(void *)NULL);
}
else if (data->fg != COLOR_DEFAULT)
{
fill_gdk_color(&color, data->fg);
g_object_set(G_OBJECT(txt),"foreground-gdk", &color, (void *)NULL);
}
if (markup)
g_object_set(G_OBJECT(txt), "text", NULL, "markup", markup, (void *)NULL);
else
g_object_set(G_OBJECT(txt), "markup", NULL, "text", buf, (void *)NULL);
gtk_cell_renderer_render(GTK_CELL_RENDERER(txt),sf->window,sf,rect,rect,rect,(GtkCellRendererState)0);
}
void gTableRender::render(GdkRectangle *ar)
{
bool sel;
int bx,by,sbx,sby;
int bpos;
int cpos;
int pmaxX;
int pmaxY;
int colspan, rowspan;
int i;
GdkGC *gc;
GdkRectangle rect;
gTableData *cell;
gTableData *caux;
int fcol, frow;
if (!sf->window) return;
gdk_window_clear_area(sf->window,ar->x,ar->y,ar->width,ar->height);
//fprintf(stderr, "render: %d %d %d %d\n", ar->x,ar->y,ar->width,ar->height);
if ( (!rowCount()) || (!columnCount()) ) return;
caux=new gTableData();
// Prepare data
pmaxX=width();
pmaxY=height();
if (pmaxX>visibleWidth()) pmaxX=visibleWidth();
if (pmaxY>visibleHeight()) pmaxY=visibleHeight();
gc=gdk_gc_new(sf->window);
gdk_gc_set_background(gc,&sf->style->base[GTK_STATE_NORMAL]);
gdk_gc_set_clip_origin(gc,0,0);
gdk_gc_set_clip_rectangle(gc,ar);
#if 0
if (grid)
{
gdk_gc_set_clip_origin(gc,0,0);
gdk_gc_set_clip_rectangle(gc,ar);
//gint8 dashes[2] = { 1, 1 };
//gdk_gc_set_line_attributes(gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
gdk_gc_set_foreground(gc, &sf->style->mid[GTK_STATE_NORMAL]);
// Horizontal lines
//gdk_gc_set_dashes(gc, offY & 1, dashes, 2);
bpos = offRow;
for (bx = firstRow; bx < rowCount(); bx++)
{
bpos += getRowSize(bx);
pos = bpos - offY - 1;
if (pos > visibleHeight())
break;
if (pos >= 0)
gdk_draw_line(sf->window, gc, 0, pos, pmaxX - 1, pos);
}
// Vertical lines
//gdk_gc_set_dashes(gc, offX & 1, dashes, 2);
bpos = offCol;
for (bx = firstCol; bx < columnCount(); bx++)
{
bpos += getColumnSize(bx);
pos = bpos - offX - 1;
if (pos >= visibleWidth()) break;
if (pos >= 0)
gdk_draw_line(sf->window, gc, pos, 0, pos, pmaxY - 1);
}
}
#endif
// Rendering texts and pixbufs
fcol = frow = -1;
bpos = offCol;
for (bx=firstCol; bx<columnCount(); bx++)
{
if ((bpos + getColumnSize(bx) - offX) < ar->x)
{
bpos += getColumnSize(bx);
continue;
}
if ((bpos - offX) >= visibleWidth())
break;
if ((bpos - offX) >= (ar->x + ar->width))
break;
cpos = offRow;
if (fcol < 0)
fcol = bx;
for (by = firstRow; by < rowCount(); by++)
{
if ((cpos + getRowSize(by) - offY) < ar->y )
{
cpos += getRowSize(by);
continue;
}
if ((cpos - offY) >= visibleHeight())
break;
if ((cpos - offY) >= (ar->y + ar->height))
break;
if (frow < 0)
{
frow = by;
}
getSpan(bx, by, &colspan, &rowspan);
rect.x = bpos - offX;
rect.y = cpos - offY;
rect.width = 0;
rect.height = 0;
if (colspan >= 0 && rowspan >= 0)
{
sel = getFieldSelected(bx, by);
for (i = 0; i <= colspan; i++)
rect.width += getColumnSize(bx + i);
for (i = 0; i <= rowspan; i++)
rect.height += getRowSize(by + i);
gdk_gc_set_clip_rectangle(gc, &rect);
cell = getData(by, bx);
renderCell(cell, gc, &rect, sel);
}
else if ((bx == fcol && colspan < 0) || (by == frow && rowspan < 0))
{
sbx = bx + colspan;
sby = by + rowspan;
sel = getFieldSelected(sbx, sby);
cell = getData(sby, sbx);
for (i = sbx; i < bx; i++)
rect.x -= getColumnSize(i);
for (i = sby; i < by; i++)
rect.y -= getRowSize(i);
getSpan(sbx, sby, &colspan, &rowspan);
for (i = 0; i <= colspan; i++)
rect.width += getColumnSize(sbx + i);
for (i = 0; i <= rowspan; i++)
rect.height += getRowSize(sby + i);
gdk_gc_set_clip_rectangle(gc, &rect);
renderCell(cell, gc, &rect, sel);
}
cpos += getRowSize(by);
}
bpos += getColumnSize(bx);
}
delete caux;
g_object_unref(G_OBJECT(gc));
}
void gTableRender::setRowSize(int position,int value)
{
GdkRectangle rect={0,0,0,0};
int pos;
if (position<0) return;
if (position>=rowCount()) return;
gTable::setRowSize(position,value);
if (view->locked() || !view->isVisible())
return;
if (!sf->window) return;
gdk_drawable_get_size (sf->window,&rect.width,&rect.height);
pos = getRowPos(position) - offY;
if ((pos + getRowSize(position))<0) return;
if (pos > rect.height) return;
gdk_window_invalidate_rect(sf->window, &rect, TRUE);
}
void gTableRender::setColumnSize(int position,int value)
{
GdkRectangle rect={0,0,0,0};
int pos;
if (position<0) return;
if (position>=columnCount()) return;
gTable::setColumnSize(position,value);
if (view->locked() || !view->isVisible())
return;
if (!sf->window) return;
gdk_drawable_get_size (sf->window,&rect.width,&rect.height);
pos = getColumnPos(position) - offX;
if ((pos + getColumnSize(position)) < 0) return;
if (pos > rect.width) return;
gdk_window_invalidate_rect(sf->window, &rect, TRUE);
}
#define CHECK_COORD(_col, _row) if ((_col) < 0 || (_row) < 0 || (_col) >= columnCount() || (_row) > rowCount()) return
void gTableRender::clearField (int col,int row)
{
CHECK_COORD(col, row);
gTable::clearField(col,row);
queryUpdate(row,col);
}
void gTableRender::setFieldText (int col,int row, const char* value)
{
CHECK_COORD(col, row);
gTable::setFieldText(col,row,value);
queryUpdate(row,col);
}
void gTableRender::setFieldRichText (int col,int row, const char* value)
{
CHECK_COORD(col, row);
gTable::setFieldRichText(col,row,value);
queryUpdate(row,col);
}
void gTableRender::setFieldFg (int col,int row,gColor value)
{
CHECK_COORD(col, row);
gTable::setFieldFg(col,row,value);
queryUpdate(row,col);
}
void gTableRender::setFieldBg (int col,int row,gColor value)
{
CHECK_COORD(col, row);
gTable::setFieldBg(col,row,value);
queryUpdate(row,col);
}
void gTableRender::setFieldPadding(int col,int row,int value)
{
CHECK_COORD(col, row);
gTable::setFieldPadding(col,row,value);
queryUpdate(row,col);
}
void gTableRender::setFieldPicture(int col, int row, gPicture *value)
{
CHECK_COORD(col, row);
gTable::setFieldPicture(col, row, value);
queryUpdate(row, col);
}
void gTableRender::setFieldFont(int col, int row, gFont *value)
{
CHECK_COORD(col, row);
gTable::setFieldFont(col, row, value);
queryUpdate(row, col);
}
void gTableRender::setFieldWordWrap(int col, int row, bool value)
{
CHECK_COORD(col, row);
gTable::setFieldWordWrap(col, row, value);
queryUpdate(row, col);
}
void gTableRender::setFieldSelected(int col,int row,bool value)
{
gTable::setFieldSelected(col,row,value);
queryUpdate(row,-1);
}
void gTableRender::setRowSelected(int row,bool value)
{
if (row<0) return;
if (row>=rowCount()) return;
if (value == getRowSelected(row))
return;
gTable::setRowSelected(row,value);
queryUpdate(row, -1);
//view->emit(SIGNAL(view->onSelect));
}
void gTableRender::clearSelection()
{
g_hash_table_destroy(seldata);
seldata=g_hash_table_new_full((GHashFunc)g_int_hash,(GEqualFunc)gTable_equal,
(GDestroyNotify)gTable_ekey,NULL);
gtk_widget_queue_draw(sf);
//view->emit(SIGNAL(view->onSelect));
}
void gTableRender::selectRows(int start, int length, bool value)
{
int end, i;
if (length < 0)
length = rowCount();
end = start + length - 1;
if (end < start)
return;
if (start < 0)
start = 0;
if (end >= rowCount())
end = rowCount() - 1;
view->lock();
for (i = start; i <= end; i++)
setRowSelected(i, value);
view->unlock();
}
int gTableRender::findVisibleRow(int y)
{
int pos, row, h;
pos = offRow;
y += offY;
for (row = firstRow; row < rowCount(); row++)
{
h = getRowSize(row);
if (y < (pos + h))
return row;
pos += h;
}
return -1;
}
int gTableRender::findVisibleColumn(int x)
{
int pos, col, w;
pos = offCol;
x += offX;
for (col = firstCol; col < columnCount(); col++)
{
w = getColumnSize(col);
if (x < (pos + w))
return col;
pos += w;
}
return -1;
}
int gTableRender::findRow(int pos)
{
int d, f, row;
d = 0;
f = rowCount();
while (f > d)
{
row = (d + f) / 2;
if (pos < getRowPos(row))
{
f = row;
continue;
}
if (pos >= (getRowPos(row) + getRowSize(row)))
{
d = row + 1;
continue;
}
return row;
}
return -1;
}
int gTableRender::findColumn(int pos)
{
int d, f, col;
d = 0;
f = columnCount();
while (f > d)
{
col = (d + f) / 2;
if (pos < getColumnPos(col))
{
f = col;
continue;
}
if (pos >= (getColumnPos(col) + getColumnSize(col)))
{
d = col + 1;
continue;
}
return col;
}
return -1;
}
void gTableRender::insertRows(int start, int length)
{
int i, j, c;
if (start < 0 || length <= 0 || start > rowCount())
return;
c = rowCount();
setRowCount(rowCount() + length);
for (i = c - 1; i >= start; i--)
{
for (j = 0; j < columnCount(); j++)
moveCell(i, j, i + length, j);
queryUpdate(i, -1);
queryUpdate(i + length, -1);
}
}
void gTableRender::removeRows(int start, int length)
{
int i, j, dst;
dst = start;
for (i = start + length; i < rowCount(); i++)
{
for (j = 0; j < columnCount(); j++)
moveCell(i, j, dst, j);
queryUpdate(i, -1);
queryUpdate(dst, -1);
dst++;
}
setRowCount(rowCount() - length);
}
void gTableRender::clear()
{
gTable::clear();
queryUpdate(-1, -1);
}