gambas-source-code/gb.gtk/src/ggridview.cpp
Benoît Minisini 550ead384c [GB.GTK]
* NEW: Remove useless old basic event handlers.
* BUG: Remove a debugging message.


git-svn-id: svn://localhost/gambas/trunk@2334 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2009-09-12 23:49:09 +00:00

1988 lines
42 KiB
C++

/***************************************************************************
ggridview.cpp
(c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
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 "widgets.h"
#include "widgets_private.h"
#include "tablerender.h"
#include "ggridview.h"
class gGridHeader
{
public:
char *header;
char *footer;
bool resizable;
gGridHeader();
~gGridHeader();
void setHeader(const char *vl);
void setFooter(const char *vl);
};
class gGridRow
{
public:
char *text;
bool resizable;
gGridRow();
~gGridRow();
void setText(const char *vl);
};
static char void_row_buffer[16];
/**************************************************************************
gGridHeader
***************************************************************************/
gGridHeader::gGridHeader()
{
resizable=true;
header=NULL;
footer=NULL;
}
gGridHeader::~gGridHeader()
{
if (header) g_free(header);
if (footer) g_free(footer);
}
void gGridHeader::setHeader(const char *vl)
{
if (!vl) vl="";
if (header) g_free(header);
header = g_strdup(vl);
}
void gGridHeader::setFooter(const char *vl)
{
if (!vl) vl="";
if (footer) g_free(footer);
footer = g_strdup(vl);
}
/**************************************************************************
gGridRow
***************************************************************************/
gGridRow::gGridRow()
{
resizable=false;
text=NULL;
}
gGridRow::~gGridRow()
{
if (text) g_free(text);
}
void gGridRow::setText(const char *vl)
{
if (!vl) vl="";
if (text) g_free(text);
text = g_strdup(text);
}
/**************************************************************************
gGridView
***************************************************************************/
static void gGridView_hbar(GtkAdjustment *adj,gGridView *data)
{
gtk_widget_queue_draw(data->header);
gtk_widget_queue_draw(data->footer);
data->render->setOffsetX((int)gtk_adjustment_get_value (adj));
if (data->onScroll) data->onScroll(data);
}
static void gGridView_vbar(GtkAdjustment *adj,gGridView *data)
{
gtk_widget_queue_draw(data->lateral);
data->render->setOffsetY((int)gtk_adjustment_get_value (adj));
if (data->onScroll) data->onScroll(data);
}
static gboolean gGridView_configure(GtkWidget *w,GdkEventConfigure *e,gGridView *data)
{
data->updateLastColumn();
data->calculateBars();
return false;
}
/*gboolean tbheader_leave(GtkWidget *wid,GdkEventCrossing *e,gGridView *data)
{
data->mouse_x=-1;
gdk_window_set_cursor(wid->window,NULL);
return false;
}
gboolean tblateral_leave(GtkWidget *wid,GdkEventCrossing *e,gGridView *data)
{
data->mouse_y=-1;
gdk_window_set_cursor(wid->window,NULL);
return false;
}*/
static gboolean tbheader_move(GtkWidget *wid, GdkEventMotion *e, gGridView *data)
{
int pos;
int width, min;
pos = (int)e->x + data->scrollX();
if (e->state & GDK_BUTTON1_MASK)
{
if (data->_index >= 0)
{
min = data->minColumnWidth(data->_index);
width = pos - data->columnPos(data->_index);
width = MAX(width, min);
if (data->_index == (data->columnCount() - 1))
data->_last_col_width = 0;
data->setColumnWidth(data->_index, width);
}
}
else
{
data->_index = data->findColumnSeparation(pos);
if (data->_index < 0)
gdk_window_set_cursor(wid->window, NULL);
else
gdk_window_set_cursor(wid->window, gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW));
}
return true;
}
static void tblateral_select(gGridView *data, int bcurrent, bool move)
{
int bc, col;
bool sel_changed;
data->getCursor(NULL, &col);
switch(data->selectionMode())
{
case SELECT_NONE:
return;
case SELECT_SINGLE:
if (!data->rowSelected(bcurrent))
{
data->setCursor(bcurrent, col);
data->emit(SIGNAL(data->onSelect));
}
break;
case SELECT_MULTIPLE:
if (!move)
{
data->setCursor(bcurrent, col);
data->getCursor(&bcurrent, &col);
data->sel_row = bcurrent;
if (data->sel_current != bcurrent)
{
data->sel_current = bcurrent;
data->clearSelection();
data->setRowSelected(bcurrent, true);
data->emit(SIGNAL(data->onSelect));
}
}
else
{
//data->clearSelection();
if (bcurrent < data->sel_row)
{
if (data->sel_current > data->sel_row)
{
data->clearSelection();
data->sel_current = data->sel_row;
}
if (bcurrent < data->sel_current)
{
for (bc = bcurrent; bc <= data->sel_current; bc++)
data->setRowSelected(bc, true);
sel_changed = true;
}
else
{
for (bc = data->sel_current; bc < bcurrent; bc++)
data->setRowSelected(bc, false);
sel_changed = true;
}
}
else
{
if (data->sel_current < data->sel_row)
{
data->clearSelection();
data->sel_current = data->sel_row;
}
if (bcurrent >= data->sel_current)
{
for (bc = data->sel_current; bc <= bcurrent; bc++)
data->setRowSelected(bc, true);
}
else
{
for (bc = bcurrent + 1; bc <= data->sel_current; bc++)
data->setRowSelected(bc, false);
}
}
if (data->sel_current != bcurrent)
{
data->sel_current = bcurrent;
data->emit(SIGNAL(data->onSelect));
}
data->setCursor(bcurrent, col);
//data->ensureVisible(bcurrent, -1);
}
break;
}
}
static gboolean tblateral_press(GtkWidget *wid,GdkEventButton *e,gGridView *data)
{
//int realmode;
int pos;
int bcurrent = -1;
bool is_lateral = (wid == data->lateral);
pos = (int)e->y + data->scrollY();
if (e->button != 1 || (is_lateral && data->findRowSeparation(pos) >= 0))
return false;
data->_index = -1;
bcurrent = data->findRow(pos);
if (bcurrent < 0) return false;
if (!is_lateral)
{
int row = bcurrent;
int col = data->render->findVisibleColumn((int)e->x);
data->setCursor(row, col);
data->getCursor(&row, &col);
bcurrent = row;
}
tblateral_select(data, bcurrent, false);
return false;
}
static gboolean lateral_do_move(gGridView *data)
{
int min, height, pos;
pos = data->mouse_pos + data->scrollY();
min = data->minRowHeight(data->_index);
height = pos - data->rowPos(data->_index);
height = MAX(height, min);
data->setRowHeight(data->_index, height);
return true;
}
static gboolean contents_do_move(gGridView *data)
{
int index, pos;
pos = data->mouse_pos + data->scrollY();
index = data->findRow(pos);
if (index >= 0)
tblateral_select(data, index, true);
return true;
}
static gboolean tblateral_move(GtkWidget *wid, GdkEventMotion *e, gGridView *data)
{
int pos;
bool is_lateral = (wid == data->lateral);
data->mouse_pos = (int)e->y;
pos = data->mouse_pos + data->scrollY();
if (e->state & GDK_BUTTON1_MASK)
{
if (is_lateral && data->_index >= 0)
lateral_do_move(data);
else
data->startScrollTimer((GSourceFunc)contents_do_move);
}
else if (is_lateral)
{
data->_index = data->findRowSeparation(pos);
if (data->_index < 0)
gdk_window_set_cursor(wid->window, NULL);
else
gdk_window_set_cursor(wid->window, gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW));
}
return false;
}
static gboolean tblateral_release(GtkWidget *wid,GdkEventButton *e,gGridView *data)
{
int pos;
int bcurrent = -1;
bool is_lateral = (wid == data->lateral);
pos = (int)e->y + data->scrollY();
data->stopScrollTimer();
if (e->button != 1 || data->_index >= 0)
return false;
bcurrent = data->findRow(pos);
if (bcurrent < 0) return false;
tblateral_select(data, bcurrent, true);
if (is_lateral)
{
data->emit(SIGNAL(data->onRowClick), bcurrent);
data->getCursor(NULL, &pos);
data->setCursor(bcurrent, pos);
}
else
{
int row = bcurrent;
int col = data->render->findVisibleColumn((int)e->x);
data->setCursor(row, col);
data->getCursor(&row, &col);
if (data->onClick)
data->onClick(data, row, col);
}
return false;
}
static gboolean cb_widget_expose(GtkWidget *wid, GdkEventExpose *e, gGridView *data)
{
int w, h, f;
if (data->headersVisible() == 3)
{
GdkRectangle rect;
f = data->getFrameWidth();
w = data->lateralWidth();
h = data->headerHeight();
rect.x = f;
rect.y = f;
rect.width = w;
rect.height = h;
gtk_paint_box(data->header->style,wid->window,
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
&rect, wid->parent, NULL, // "buttondefault"
0, 0, w + f, h + f);
}
if (data->footersVisible() && data->headersVisible() & 2)
{
GdkRectangle rect;
f = data->getFrameWidth();
w = data->lateralWidth();
h = data->footerHeight();
rect.x = f;
rect.y = data->height() - h - f;
rect.width = w;
rect.height = h;
gtk_paint_box(data->header->style,wid->window,
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
&rect, wid->parent, NULL, // "buttondefault"
0, rect.y, w + f, h + f);
}
return false;
}
static gboolean tbheader_expose(GtkWidget *wid,GdkEventExpose *e,gGridView *data)
{
GtkCellRenderer *rend=NULL;
GdkRectangle rect={0,0,0,0};
GdkGC *gc;
char *buf;
int bpos;
int pw,ph,maxw;
bool footer;
int bc;
footer = wid->window == data->footer->window;
gc=gdk_gc_new(wid->window);
gdk_gc_set_clip_origin(gc,0,0);
gdk_gc_set_clip_rectangle(gc,&e->area);
gdk_drawable_get_size(wid->window,&maxw,&ph);
if (footer)
{
gtk_paint_box(wid->style, wid->window,
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
NULL, wid->parent, "button", // "buttondefault"
-4, 0, maxw + 8, ph + 4);
}
else
{
gtk_paint_box(wid->style, wid->window,
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
NULL, wid->parent, "button", // "buttondefault"
-4, -4, maxw + 8, ph + 4);
}
/* if (data->render->firstCol == 0)
{
gtk_paint_vline(data->header->style, wid->window,
GTK_STATE_NORMAL,
NULL, wid->parent, NULL,
0, ph - 1, 0);
}*/
bpos = data->render->offCol - data->render->getOffsetX();
for (bc = data->render->firstCol; bc < data->columnCount(); bc++)
{
//if ((bpos+data->columnWidth(bc)) < 0) { bpos+=data->columnWidth(bc); continue; }
if (bpos > maxw)
break;
pw=data->columnWidth(bc);
if (footer)
{
gtk_paint_vline(wid->style, wid->window,
GTK_STATE_NORMAL,
NULL, wid->parent, NULL,
4, ph - 3, bpos + pw - 1);
}
else
{
gtk_paint_vline(wid->style, wid->window,
GTK_STATE_NORMAL,
NULL, wid->parent, NULL,
3, ph - 4, bpos + pw - 1);
}
if (footer) buf=data->footerText(bc);
else buf=data->headerText(bc);
if ( buf != NULL )
{
if (!rend) rend=gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(rend),
"text", buf,
"xalign", 0.5,
"yalign", 0.5,
"font-desc", data->font()->desc(),
(void *)NULL);
rect.x=bpos;
rect.y=0;
rect.width=pw-1;
rect.height=ph-1;
gtk_cell_renderer_render(GTK_CELL_RENDERER(rend),wid->window,wid,&rect,&rect,NULL,(GtkCellRendererState)0);
}
bpos += data->columnWidth(bc);
}
g_object_unref(G_OBJECT(gc));
return false;
}
static gboolean tblateral_expose(GtkWidget *wid,GdkEventExpose *e,gGridView *data)
{
GtkCellRenderer *rend=NULL;
GdkRectangle rect={0,0,0,0};
GdkGC *gc;
GdkWindow *win=data->lateral->window;
int pw,ph,maxh;
int bc;
int bpos;
gc=gdk_gc_new(win);
gdk_gc_set_clip_origin(gc,0,0);
gdk_gc_set_clip_rectangle(gc,&e->area);
gdk_drawable_get_size(win,&ph,&maxh);
gtk_paint_box(wid->style, wid->window,
GTK_STATE_NORMAL, GTK_SHADOW_OUT,
NULL, wid->parent, "button", // "buttondefault"
-4, -4, ph + 4, maxh + 8);
/* if (data->render->firstRow == 0)
{
gtk_paint_hline(data->header->style, wid->window,
GTK_STATE_NORMAL,
NULL, wid->parent, NULL,
0, ph - 1, 0);
}*/
bpos = data->render->offRow - data->render->getOffsetY();
for (bc=data->render->firstRow; bc<data->rowCount(); bc++)
{
if (bpos > maxh) break;
pw=data->rowHeight(bc);
/* gtk_paint_box(data->lateral->style,data->lateral->window,
GTK_STATE_NORMAL, GTK_SHADOW_NONE,
NULL, data->lateral->parent, "buttondefault",
0,bpos, ph-1, pw-1);
gtk_paint_shadow(data->lateral->style,data->lateral->window,
GTK_STATE_NORMAL, GTK_SHADOW_NONE,
NULL, data->lateral->parent, "buttondefault",
0,bpos, ph-1, pw-1);*/
gtk_paint_hline(wid->style, wid->window,
GTK_STATE_NORMAL,
NULL, wid->parent, NULL,
3, ph - 4, bpos + pw - 1);
if (!rend) rend=gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(rend),
"text", data->rowText(bc),
"xalign", 0.5,
"yalign", 0.5,
"font-desc", data->font()->desc(),
(void *)NULL);
rect.x = 0;
rect.y = bpos;
rect.width = ph-1;
rect.height = pw-1;
gtk_cell_renderer_render(GTK_CELL_RENDERER(rend),wid->window,wid,
&rect,&rect,NULL,(GtkCellRendererState)0);
bpos+=data->rowHeight(bc);
}
g_object_unref(G_OBJECT(gc));
return false;
}
static gboolean tbheader_release(GtkWidget *wid,GdkEventButton *e,gGridView *data)
{
int bc,bcurrent=-1;
bool bfooter=false;
char *buf=NULL;
if (e->button != 1 || data->_index >= 0) return false;
bcurrent = data->findColumn((int)e->x + data->scrollX());
if (bcurrent<0) return false;
g_object_get(G_OBJECT(wid),"name",&buf,(void *)NULL);
if (buf)
{
if (!strcmp(buf,"gambas-grid-footer")) bfooter=true;
g_free(buf); buf=NULL;
}
data->getCursor(&bc,NULL);
data->setCursor(bc,bcurrent);
data->getCursor(&bc,&bcurrent);
if (bfooter)
{ if (data->onFooterClick) data->onFooterClick(data,bcurrent); }
else
{ if (data->onColumnClick) data->onColumnClick(data,bcurrent); }
return TRUE;
}
static gboolean cb_contents_button_press(GtkWidget *wid, GdkEventButton *e, gGridView *data)
{
int row, col;
if (e->type != GDK_2BUTTON_PRESS)
return false;
if (e->button != 1)
return false;
data->getCursor(&row, &col);
if (data->onActivate) data->onActivate(data, row, col);
return false;
}
static gboolean cb_scroll(GtkWidget *wid, GdkEventScroll *e, gGridView *data)
{
GtkAdjustment *adj;
gdouble step;
if (e->direction == GDK_SCROLL_UP || e->direction == GDK_SCROLL_DOWN)
adj = gtk_range_get_adjustment(GTK_RANGE(data->vbar));
else
adj = gtk_range_get_adjustment(GTK_RANGE(data->hbar));
#if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 14
step = gtk_adjustment_get_step_increment(adj);
#else
g_object_get(G_OBJECT(adj), "step-increment", &step, (void *)NULL);
#endif
switch (e->direction)
{
case GDK_SCROLL_UP: data->setScrollY(data->scrollY() - (int)step); break;
case GDK_SCROLL_DOWN: data->setScrollY(data->scrollY() + (int)step); break;
case GDK_SCROLL_LEFT: data->setScrollX(data->scrollX() - (int)step); break;
case GDK_SCROLL_RIGHT: data->setScrollY(data->scrollX() + (int)step); break;
}
return TRUE;
}
static gboolean cb_keypress(GtkWidget *wid,GdkEventKey *e,gGridView *data)
{
int row,col;
bool bchange=false;
data->getCursor(&row,&col);
switch(e->keyval)
{
case GDK_Up:
if (row>0) { row--; bchange=true; }
break;
case GDK_Down:
if (row<(data->rowCount()-1)) { row++; bchange=true; }
break;
case GDK_Left:
if (col>0) { col--; bchange=true; }
break;
case GDK_Right:
if (col<(data->columnCount()-1)) { col++; bchange=true; }
break;
}
if (bchange)
{
data->ensureVisible(row,col);
data->setCursor(row,col);
return TRUE;
}
return false;
}
gGridView::gGridView(gContainer *parent) : gControl(parent)
{
GtkAdjustment *adj;
g_typ = Type_gGridView;
onChange = NULL;
onActivate = NULL;
onSelect = NULL;
onScroll = NULL;
onClick = NULL;
onColumnClick = NULL;
onFooterClick = NULL;
onRowClick = NULL;
onColumnResize = NULL;
onRowResize = NULL;
use_base = true;
_index = -1;
cursor_col=-1;
cursor_row=-1;
sel_row=-1;
sel_mode=0;
sel_current = -1;
scroll=3;
hdata=NULL;
vdata=NULL;
_last_col_width = 0;
scroll_timer = 0;
_updating_last_column = false;
_autoresize = true;
border=gtk_event_box_new();
widget=gtk_table_new(3,3,FALSE);
//gtk_container_set_border_width (GTK_CONTAINER(widget),1);
//gtk_container_add(GTK_CONTAINER(border),widget);
hbar=gtk_hscrollbar_new(NULL);
vbar=gtk_vscrollbar_new(NULL);
contents = gtk_drawing_area_new();
gtk_widget_add_events(contents, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
header=gtk_drawing_area_new();
footer=gtk_drawing_area_new();
lateral=gtk_drawing_area_new();
//gtk_widget_set_size_request(header,0,20);
//gtk_widget_set_size_request(footer,0,20);
//gtk_widget_set_size_request(lateral,16,0);
gtk_table_attach_defaults(GTK_TABLE(widget),contents,1,2,1,2);
gtk_table_attach(GTK_TABLE(widget),header,1,2,0,1,GTK_FILL,GTK_FILL,0,0);
gtk_table_attach(GTK_TABLE(widget),footer,1,2,2,3,GTK_FILL,GTK_FILL,0,0);
gtk_table_attach(GTK_TABLE(widget),lateral,0,1,1,2,GTK_FILL,GTK_FILL,0,0);
gtk_table_attach(GTK_TABLE(widget),hbar,0,2,3,4,GTK_FILL,GTK_FILL,0,0);
gtk_table_attach(GTK_TABLE(widget),vbar,2,3,0,3,GTK_FILL,GTK_FILL,0,0);
render=new gTableRender(this);
_no_default_mouse_event = true;
realize(true);
gtk_widget_add_events(border,GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
gtk_widget_add_events(contents,GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
gtk_widget_add_events(header,GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
gtk_widget_add_events(footer,GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
gtk_widget_add_events(lateral,GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
gtk_widget_add_events(header,GDK_BUTTON_PRESS_MASK | GDK_BUTTON1_MOTION_MASK);
gtk_widget_add_events(footer,GDK_BUTTON_PRESS_MASK | GDK_BUTTON1_MOTION_MASK);
gtk_widget_add_events(lateral,GDK_BUTTON_PRESS_MASK | GDK_BUTTON1_MOTION_MASK);
gtk_widget_add_events(header,GDK_BUTTON_RELEASE_MASK);
gtk_widget_add_events(footer,GDK_BUTTON_RELEASE_MASK);
gtk_widget_add_events(lateral,GDK_BUTTON_RELEASE_MASK);
g_object_set(G_OBJECT(header),"name","gambas-grid-header",(void *)NULL);
g_object_set(G_OBJECT(footer),"name","gambas-grid-footer",(void *)NULL);
g_signal_connect_after(G_OBJECT(border),"size-allocate",G_CALLBACK(gGridView_configure),(void*)this);
g_signal_connect(G_OBJECT(border), "key-press-event", G_CALLBACK(cb_keypress), this);
g_signal_connect(G_OBJECT(border), "scroll-event", G_CALLBACK(cb_scroll), this);
g_signal_connect(G_OBJECT(header),"expose-event",G_CALLBACK(tbheader_expose),this);
g_signal_connect(G_OBJECT(header),"motion-notify-event",G_CALLBACK(tbheader_move),this);
g_signal_connect(G_OBJECT(header),"button-release-event",G_CALLBACK(tbheader_release),this);
g_signal_connect(G_OBJECT(footer),"expose-event",G_CALLBACK(tbheader_expose),this);
g_signal_connect(G_OBJECT(footer),"motion-notify-event",G_CALLBACK(tbheader_move),this);
g_signal_connect(G_OBJECT(footer),"button-release-event",G_CALLBACK(tbheader_release),this);
g_signal_connect(G_OBJECT(lateral),"expose-event",G_CALLBACK(tblateral_expose),this);
g_signal_connect(G_OBJECT(lateral),"motion-notify-event",G_CALLBACK(tblateral_move),this);
g_signal_connect(G_OBJECT(lateral),"button-press-event",G_CALLBACK(tblateral_press),this);
g_signal_connect(G_OBJECT(lateral),"button-release-event",G_CALLBACK(tblateral_release),this);
g_signal_connect(G_OBJECT(widget),"expose-event",G_CALLBACK(cb_widget_expose),this);
g_signal_connect_after(G_OBJECT(contents),"event",G_CALLBACK(cb_contents_button_press),this);
g_signal_connect(G_OBJECT(contents),"motion-notify-event",G_CALLBACK(tblateral_move),this);
//g_signal_connect(G_OBJECT(contents),"button-release-event",G_CALLBACK(gcb_button_release),(gpointer)this);
//g_signal_connect(G_OBJECT(contents),"button-press-event",G_CALLBACK(gcb_button_press),(gpointer)this);
g_signal_connect(G_OBJECT(contents),"button-press-event",G_CALLBACK(tblateral_press),this);
g_signal_connect(G_OBJECT(contents),"button-release-event",G_CALLBACK(tblateral_release),this);
//g_signal_connect(G_OBJECT(contents),"event",G_CALLBACK(gridview_release),this);
g_object_set(G_OBJECT(vbar),"visible",FALSE,(void *)NULL);
g_object_set(G_OBJECT(hbar),"visible",FALSE,(void *)NULL);
g_object_set(G_OBJECT(footer),"visible",FALSE,(void *)NULL);
g_object_set(G_OBJECT(widget),"can-focus",TRUE,(void *)NULL);
gtk_widget_realize(footer);
gtk_widget_realize(contents);
adj=gtk_range_get_adjustment(GTK_RANGE(hbar));
g_signal_connect(G_OBJECT(adj),"value-changed",G_CALLBACK(gGridView_hbar),(void*)this);
adj=gtk_range_get_adjustment(GTK_RANGE(vbar));
g_signal_connect(G_OBJECT(adj),"value-changed",G_CALLBACK(gGridView_vbar),(void*)this);
// BM to see the result
//GtkStyle *st = gt_get_style("GtkEntry", GTK_TYPE_ENTRY);
//gtk_widget_set_style(contents, st);
//gtk_widget_modify_base(contents, GTK_STATE_NORMAL, &st->bg[GTK_STATE_NORMAL]);
//gtk_widget_modify_bg(contents, GTK_STATE_NORMAL, &st->base[GTK_STATE_NORMAL]);
setBackground();
setForeground();
setHeadersVisible(0);
setFootersVisible(false);
setBorder(true);
setDrawGrid(true);
}
gGridView::~gGridView()
{
setRowCount(0);
setColumnCount(0);
if (hdata) g_hash_table_destroy(hdata);
if (vdata) g_hash_table_destroy(vdata);
delete render;
}
int gGridView::selectionMode()
{
return sel_mode;
}
void gGridView::setSelectionMode(int vl)
{
if (vl<0) return;
if (vl>2) return;
sel_mode=vl;
if (sel_mode == SELECT_NONE)
clearSelection();
else if (sel_mode == SELECT_SINGLE)
setRowSelected(cursor_row, true);
}
void gGridView::setDataFunc(void *func,void *data)
{
render->voidCell=(void(*)(gTableData *,int,int,void *))func;
render->userData=data;
}
void gGridView::queryUpdate(int row,int col)
{
render->queryUpdate(row,col);
}
void gGridView::calculateBars()
{
GtkAdjustment *adj;
int obh,obv,px,py,ovw,ovh,vw,vh,rw,rh;
bool bh, bv;
GtkRequisition req;
gtk_widget_size_request(hbar, &req);
py = req.height;
gtk_widget_size_request(vbar, &req);
px = req.width;
obh = bh = GTK_WIDGET_VISIBLE(hbar);
obv = bv = GTK_WIDGET_VISIBLE(vbar);
vw = render->visibleWidth(); // + (obh ? px : 0);
vh = render->visibleHeight(); // + (obv ? py : 0);
rw = render->width();
rh = render->height();
if (vw > 1 && vh > 1)
{
ovw = vw + (obv ? px : 0);
ovh = vh + (obh ? py : 0);
//fprintf(stderr, "ovw = %d ovh = %d\n", ovw, ovh);
obv = false;
obh = false;
for(;;)
{
vw = ovw - (obv ? px : 0);
vh = ovh - (obh ? py : 0);
//fprintf(stderr, "rw = %d rh = %d / vw = %d vh = %d / bh = %d bv = %d\n", rw, rh, vw, vh, bh, bv);
bh = vw < rw && rw > 0 && (scroll & SCROLL_HORIZONTAL);
if (bh != obh)
{
obh = bh;
continue;
}
bv = vh < rh && rh > 0 && (scroll & SCROLL_VERTICAL);
if (bv != obv)
{
obv = bv;
continue;
}
break;
}
}
else
{
bh = false;
bv = false;
}
if (bh != GTK_WIDGET_VISIBLE(hbar))
{
g_object_set(G_OBJECT(hbar),"visible",bh,(void *)NULL);
if (!bh)
setScrollX(0);
}
if (bv != GTK_WIDGET_VISIBLE(vbar))
{
g_object_set(G_OBJECT(vbar),"visible",bv,(void *)NULL);
if (!bv)
setScrollY(0);
}
if (bh)
{
gtk_range_set_range(GTK_RANGE(hbar),0,render->width());
gtk_range_set_increments(GTK_RANGE(hbar),minColumnWidth(0) * 3,vw);
adj=gtk_range_get_adjustment(GTK_RANGE(hbar));
g_object_set(G_OBJECT(adj),"page-size",(gfloat)vw,(void *)NULL);
}
if (bv)
{
gtk_range_set_range(GTK_RANGE(vbar),0,render->height());
gtk_range_set_increments(GTK_RANGE(vbar),minRowHeight(0) * 3,vh);
adj=gtk_range_get_adjustment(GTK_RANGE(vbar));
g_object_set(G_OBJECT(adj),"page-size",(gfloat)vh,(void *)NULL);
}
}
// bool gGridView::getBorder()
// {
// return (bool)gtk_container_get_border_width(GTK_CONTAINER(widget));
// }
//
// void gGridView::setBorder(bool vl)
// {
// if (vl == getBorder() ) return;
// switch(vl)
// {
// case false:
// gtk_container_set_border_width(GTK_CONTAINER(widget),0); break;
// case true:
// gtk_container_set_border_width(GTK_CONTAINER(widget),1); break;
// }
// }
int gGridView::scrollBar()
{
return scroll;
}
void gGridView::setScrollBar(int vl)
{
if (vl==scroll) return;
scroll=vl;
if ( !(scroll & 1) ) g_object_set(G_OBJECT(hbar),"visible",FALSE,(void *)NULL);
if ( !(scroll & 2) ) g_object_set(G_OBJECT(vbar),"visible",FALSE,(void *)NULL);
calculateBars();
}
int gGridView::scrollX()
{
return render->getOffsetX();
}
int gGridView::scrollY()
{
return render->getOffsetY();
}
void gGridView::setScrollX(int vl)
{
GtkAdjustment* adj;
int max;
adj = gtk_range_get_adjustment(GTK_RANGE(hbar));
max = (int)(adj->upper - adj->page_size);
if (vl < 0)
vl = 0;
else if (vl > max)
vl = max;
gtk_adjustment_set_value(adj, (gdouble)vl);
}
void gGridView::setScrollY(int vl)
{
GtkAdjustment* adj;
int max;
adj = gtk_range_get_adjustment(GTK_RANGE(vbar));
max = (int)(adj->upper - adj->page_size);
if (vl < 0)
vl = 0;
else if (vl > max)
vl = max;
gtk_adjustment_set_value(adj, (gdouble)vl);
}
int gGridView::rowAt(int y)
{
int bpos=-render->getOffsetX();
int bc;
for (bc=0; bc<render->rowCount(); bc++)
{
if ( (bpos<=y) && ( (bpos+render->getRowSize(bc)))>=y ) return bc;
bpos+=render->getRowSize(bc);
}
return -1;
}
int gGridView::columnAt(int x)
{
int bpos=-render->getOffsetY();
int bc;
for (bc=0; bc<render->columnCount(); bc++)
{
if ( (bpos<=x) && ( (bpos+render->getColumnSize(bc)))>=x ) return bc;
bpos+=render->getColumnSize(bc);
}
return -1;
}
int gGridView::visibleLeft()
{
gboolean vl;
int w;
g_object_get(G_OBJECT(lateral),"visible",&vl,(void *)NULL);
if (!vl) return 0;
gtk_widget_get_size_request(lateral,&w,NULL);
return w;
}
int gGridView::visibleTop()
{
gboolean vl;
int h;
g_object_get(G_OBJECT(header),"visible",&vl,(void *)NULL);
if (!vl) return 0;
gtk_widget_get_size_request(header,NULL,&h);
return h;
}
int gGridView::visibleWidth()
{
return render->visibleWidth();
}
int gGridView::visibleHeight()
{
return render->visibleHeight();
}
void gGridView::ensureVisible(int row, int col)
{
int x, y, w, h;
GtEnsureVisible arg;
bool sx, sy;
arg.clientWidth = visibleWidth();
arg.clientHeight = visibleHeight();
arg.scrollX = scrollX();
arg.scrollY = scrollY();
arg.scrollWidth = render->width();
arg.scrollHeight = render->height();
sy = row >= 0 && row < rowCount();
sx = col >= 0 && col < columnCount();
if (!sy)
row = 0;
if (!sx)
col = 0;
x = columnPos(col);
y = rowPos(row);
w = columnWidth(col);
h = rowHeight(row);
gt_ensure_visible(&arg, x, y, w, h);
if (sx)
setScrollX(arg.scrollX);
if (sy)
setScrollY(arg.scrollY);
/* int vl;
//int bc;
GtkAdjustment *adj;
if (col >= 0 && col < columnCount())
{
vl = columnPos(col) - scrollX() + columnWidth(col) / 2;
//for (bc=0; bc<col; bc++)
// vl+=columnWidth(bc);
if (vl<0)
{
vl=render->getOffsetX()+vl;
adj=gtk_range_get_adjustment(GTK_RANGE(hbar));
g_object_set(G_OBJECT(adj),"value",(gfloat)vl,NULL);
}
else if ( (vl+columnWidth(col))>visibleWidth() )
{
vl=render->getOffsetX()+columnWidth(col)-(visibleWidth()-vl);
adj=gtk_range_get_adjustment(GTK_RANGE(hbar));
g_object_set(G_OBJECT(adj),"value",(gfloat)vl,NULL);
}
}
if (row >= 0 && row < rowCount())
{
vl = rowPos(row) - scrollY() + rowHeight(row) / 2;
//for (bc=0; bc<row; bc++)
// vl+=rowHeight(bc);
if (vl<0)
{
vl=render->getOffsetY()+vl;
adj=gtk_range_get_adjustment(GTK_RANGE(vbar));
g_object_set(G_OBJECT(adj),"value",(gfloat)vl,NULL);
}
else if ( (vl+rowHeight(col))>visibleHeight() )
{
vl=render->getOffsetY()+rowHeight(col)-(visibleHeight()-vl);
adj=gtk_range_get_adjustment(GTK_RANGE(vbar));
g_object_set(G_OBJECT(adj),"value",(gfloat)vl,NULL);
}
} */
}
bool gGridView::drawGrid()
{
return render->drawGrid();
}
void gGridView::setDrawGrid(bool vl)
{
render->setDrawGrid(vl);
}
void gGridView::getCursor(int *row,int *col)
{
if (row) *row=cursor_row;
if (col) *col=cursor_col;
}
void gGridView::setCursor(int row,int col)
{
int rowspan, colspan;
if (row < 0 || row >= rowCount())
row = -1;
if (col < 0 || col >= columnCount())
col = -1;
if (row == cursor_row && col == cursor_col)
return;
getItemSpan(row, col, &rowspan, &colspan);
if (rowspan < 0)
row += rowspan;
if (colspan < 0)
col += colspan;
cursor_row = row;
cursor_col = col;
if (selectionMode() == SELECT_SINGLE)
setRowSelected(cursor_row, true);
ensureVisible(cursor_row, cursor_col);
emit(SIGNAL(onChange));
}
void gGridView::setColumnCount(int vl)
{
int old, i;
if (vl<0) vl=0;
old = columnCount();
if (old == vl) return;
lock();
render->setColumnCount(vl);
render->doNotInvalidate = true;
for (i = old; i < vl; i++)
render->setColumnSize(i, 80);
render->doNotInvalidate = false;
unlock();
_last_col_width = 0;
updateLastColumn();
calculateBars();
if (vl==0) cursor_col=-1;
if (vl<=cursor_col) cursor_col=vl-1;
if ( (rowCount()>0) && (vl>0) && (cursor_col==-1) )
{
cursor_col=0;
cursor_row=0;
}
refresh();
}
void gGridView::setRowCount(int vl)
{
int old, i, h;
if (vl<0) vl=0;
old = rowCount();
if (old == vl) return;
lock();
render->setRowCount(vl);
if (vl)
{
h = minRowHeight(vl - 1);
render->doNotInvalidate = true;
for (i = old; i < vl; i++)
{
//if ((i % 1000) == 0)
// fprintf(stderr, "%d\r", i);
setRowHeight(i, h);
}
render->doNotInvalidate = false;
}
unlock();
calculateBars();
if (vl==0) cursor_row=-1;
if (vl<=cursor_row) cursor_row=vl-1;
if ( (columnCount()>0) && (vl>0) && (cursor_row==-1) )
{
cursor_row=0;
cursor_col=0;
}
updateHeaders();
refresh();
}
/*
int gGridView::findColumn(int pos)
{
int i;
int x = 0;
int x2;
for (i = 0; i < columnCount(); i++)
{
x2 = x + columnWidth(i);
if (pos >= x && pos < x2)
return i;
x = x2;
}
return -1;
}
*/
int gGridView::findColumnSeparation(int pos)
{
int i;
int x = 0;
for (i = 0; i < columnCount(); i++)
{
x += columnWidth(i);
if (pos > (x - 2) && pos < (x + 2))
return columnResizable(i) ? i : -1;
}
return -1;
}
/*
int gGridView::findRow(int pos)
{
int i;
int y = 0;
int y2;
for (i = 0; i < rowCount(); i++)
{
y2 = y + rowHeight(i);
if (pos >= y && pos < y2)
return i;
y = y2;
}
return -1;
}
*/
int gGridView::findRowSeparation(int pos)
{
int i;
int y = 0;
for (i = 0; i < rowCount(); i++)
{
y += rowHeight(i);
if (pos > (y - 2) && pos < (y + 2))
return rowResizable(i) ? i : -1;
}
return -1;
}
int gGridView::minColumnWidth(int index)
{
int w, w2;
w = font()->width(headerText(index));
w2 = font()->width(footerText(index));
if (w2 > w)
w = w2;
return 8 + MAX(w, 8);
}
void gGridView::setColumnWidth(int index,int vl)
{
if (index < 0 || index >= columnCount())
return;
if (vl < 0)
vl = minColumnWidth(index);
if (vl == columnWidth(index))
return;
render->setColumnSize(index,vl);
updateLastColumn();
gtk_widget_queue_draw(header);
gtk_widget_queue_draw(footer);
calculateBars();
gtk_widget_queue_draw(contents);
emit(SIGNAL(onColumnResize), index);
}
int gGridView::minRowHeight(int index)
{
return 8 + font()->height(" "); // rowText(index)
}
void gGridView::setRowHeight(int index,int vl)
{
if (index < 0 || index >= rowCount())
return;
if (vl < 0)
vl = minRowHeight(index);
render->setRowSize(index,vl);
if (locked())
return;
gtk_widget_queue_draw(lateral);
calculateBars();
gtk_widget_queue_draw(contents);
emit(SIGNAL(onRowResize), index);
}
int gGridView::itemX(int col)
{
int ret,bc;
if (col<0) return -1;
if (col>=render->columnCount()) return -1;
ret = -render->getOffsetX();
for (bc=0; bc<col; bc++)
ret+=render->getColumnSize(bc);
ret += rowWidth();
return ret + 2;
}
int gGridView::itemY(int row)
{
int ret,bc;
if (row<0) return -1;
if (row>=render->rowCount()) return -1;
ret = -render->getOffsetY();
for (bc=0; bc<row; bc++)
ret+=render->getRowSize(bc);
ret += headerHeight();
return ret + 2;
}
int gGridView::itemW(int col)
{
if (col<0) return -1;
if (col>=render->columnCount()) return -1;
return render->getColumnSize(col) - 1;
}
int gGridView::itemH(int row)
{
if (row<0) return -1;
if (row>=render->rowCount()) return -1;
return render->getRowSize(row) - 1;
}
char* gGridView::itemText(int row,int col)
{
return render->getFieldText(col,row);
}
char* gGridView::itemRichText(int row,int col)
{
return render->getFieldRichText(col,row);
}
gColor gGridView::itemFg(int row,int col)
{
return render->getFieldFg(col,row);
}
gColor gGridView::itemBg(int row,int col)
{
return render->getFieldBg(col,row);
}
int gGridView::itemPadding(int row,int col)
{
return render->getFieldPadding(col,row);
}
int gGridView::itemAlignment(int row,int col)
{
return render->getFieldAlignment(col,row);
}
gPicture *gGridView::itemPicture(int row, int col)
{
return render->getFieldPicture(col, row);
}
gFont *gGridView::itemFont(int row, int col)
{
return render->getFieldFont(col, row);
}
bool gGridView::itemWordWrap(int row,int col)
{
return render->getFieldWordWrap(col,row);
}
bool gGridView::itemSelected(int row,int col)
{
return render->getFieldSelected(col,row);
}
void gGridView::setItemText(int row,int col, const char *vl)
{
render->setFieldText(col,row,vl);
}
void gGridView::setItemRichText(int row,int col, const char *vl)
{
render->setFieldRichText(col,row,vl);
}
void gGridView::setItemFg(int row, int col, gColor vl)
{
render->setFieldFg(col,row,vl);
}
void gGridView::setItemBg(int row, int col, gColor vl)
{
render->setFieldBg(col,row,vl);
}
void gGridView::setItemPadding(int row,int col,int vl)
{
render->setFieldPadding(col,row,vl);
}
void gGridView::setItemWordWrap(int row,int col,bool vl)
{
render->setFieldWordWrap(col,row,vl);
}
void gGridView::setItemAlignment(int row,int col,int vl)
{
render->setFieldAlignment(col,row,vl);
}
void gGridView::setItemPicture(int row, int col, gPicture *vl)
{
render->setFieldPicture(col, row, vl);
}
void gGridView::setItemFont(int row, int col, gFont *vl)
{
render->setFieldFont(col, row, vl);
}
void gGridView::setItemSelected(int row,int col,bool vl)
{
render->setFieldSelected(col,row,vl);
}
void gGridView::clearItem(int row,int col)
{
render->clearField(col,row);
}
/*******************************************************************
Headers, Footers and Row Separators
********************************************************************/
int gGridView::headersVisible()
{
int val = 0;
//g_object_get(G_OBJECT(header),"visible",&hv,NULL);
//g_object_get(G_OBJECT(lateral),"visible",&lv,NULL);
if (GTK_WIDGET_VISIBLE(header)) val += 1;
if (GTK_WIDGET_VISIBLE(lateral)) val += 2;
return val;
}
void gGridView::setHeadersVisible(int vl)
{
/*gboolean now;
g_object_get(G_OBJECT(header),"visible",&now,NULL);
if (vl==now) return;
g_object_set(G_OBJECT(header),"visible",vl,NULL);*/
if (vl & 1)
gtk_widget_show(header);
else
gtk_widget_hide(header);
if (vl & 2)
gtk_widget_show(lateral);
else
gtk_widget_hide(lateral);
}
bool gGridView::footersVisible()
{
return GTK_WIDGET_VISIBLE(footer);
}
void gGridView::setFootersVisible(bool vl)
{
if (vl)
gtk_widget_show(footer);
else
gtk_widget_hide(footer);
}
void gridheader_destroy(gGridHeader *data)
{
delete data;
}
void gridrow_destroy(gGridRow *data)
{
delete data;
}
void gGridView::setHeaderText(int col, const char *value)
{
gGridHeader *head;
int w;
if ((col<0) || (col>=columnCount()) ) return;
if (!value) value="";
if (!hdata)
hdata=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,
(GDestroyNotify)gridheader_destroy);
head=(gGridHeader*)g_hash_table_lookup(hdata,(gpointer)col);
if (!head)
{
head=new gGridHeader();
g_hash_table_insert(hdata,(gpointer)col,(gpointer)head);
}
head->setHeader(value);
w = font()->width(value) + 8;
if (w > columnWidth(col))
setColumnWidth(col, w);
gtk_widget_queue_draw(header);
}
void gGridView::setFooterText(int col, const char *value)
{
gGridHeader *head;
if (!hdata)
hdata=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,
(GDestroyNotify)gridheader_destroy);
head=(gGridHeader*)g_hash_table_lookup(hdata,(gpointer)col);
if (!head)
{
head=new gGridHeader();
g_hash_table_insert(hdata,(gpointer)col,(gpointer)head);
}
head->setFooter(value);
gtk_widget_queue_draw(footer);
}
char* gGridView::headerText(int col)
{
gGridHeader *head;
if (!hdata) return NULL;
head=(gGridHeader*)g_hash_table_lookup(hdata,(gpointer)col);
if (!head) return NULL;
return head->header;
}
char* gGridView::footerText(int col)
{
gGridHeader *head;
if (!hdata) return NULL;
head=(gGridHeader*)g_hash_table_lookup(hdata,(gpointer)col);
if (!head) return NULL;
return head->footer;
}
bool gGridView::columnResizable(int index)
{
gGridHeader *head;
if (!hdata) return true;
head=(gGridHeader*)g_hash_table_lookup(hdata,(gpointer)index);
if (!head) return true;
return head->resizable;
}
void gGridView::setColumnResizable(int col,bool value)
{
gGridHeader *head;
if (!hdata)
hdata=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,
(GDestroyNotify)gridheader_destroy);
head=(gGridHeader*)g_hash_table_lookup(hdata,(gpointer)col);
if (!head)
{
head=new gGridHeader();
g_hash_table_insert(hdata,(gpointer)col,(gpointer)head);
}
head->resizable=value;
if (!value)
{
gdk_window_set_cursor(header->window,NULL);
gdk_window_set_cursor(footer->window,NULL);
}
}
char* gGridView::rowText(int col)
{
gGridRow *head;
if (vdata)
{
head = (gGridRow*)g_hash_table_lookup(vdata,(gpointer)col);
if (head)
return head->text;
}
sprintf(void_row_buffer, "%d", col + 1);
return void_row_buffer;
}
void gGridView::setRowText(int col, const char *value)
{
gGridRow *head;
if (!vdata)
vdata=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,
(GDestroyNotify)gridrow_destroy);
head=(gGridRow*)g_hash_table_lookup(vdata,(gpointer)col);
if (!head)
{
head=new gGridRow();
g_hash_table_insert(vdata,(gpointer)col,(gpointer)head);
}
head->setText(value);
updateLateralWidth(font()->width(value));
gtk_widget_queue_draw(lateral);
}
bool gGridView::rowResizable(int index)
{
gGridRow *head;
if (!vdata) return true;
head=(gGridRow*)g_hash_table_lookup(vdata,(gpointer)index);
if (!head) return true;
return head->resizable;
}
void gGridView::setRowResizable(int col,bool value)
{
gGridRow *head;
if (!vdata)
vdata=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,
(GDestroyNotify)gridrow_destroy);
head=(gGridRow*)g_hash_table_lookup(vdata,(gpointer)col);
if (!head)
{
head=new gGridRow();
g_hash_table_insert(vdata,(gpointer)col,(gpointer)head);
}
head->resizable=value;
if (!value) gdk_window_set_cursor(lateral->window,NULL);
}
bool gGridView::rowSelected(int index)
{
return render->getRowSelected(index);
}
void gGridView::setRowSelected(int col,bool value)
{
if (selectionMode() == SELECT_NONE)
return;
if (selectionMode() == SELECT_SINGLE)
clearSelection();
render->setRowSelected(col,value);
}
void gGridView::updateHeaders()
{
int h, wlat;
//int i, w, wd;
//char *text;
h = font()->height() + 8;
gtk_widget_set_size_request(header, header->requisition.width, h);
gtk_widget_set_size_request(footer, footer->requisition.width, h);
wlat = 8 + font()->width("9") * sprintf(void_row_buffer, "%d", rowCount());
/*wlat = 0;
for (i = 0; i < rowCount(); i++)
{
if (rowHeight(i) < h)
setRowHeight(i, h);
text = rowText(i);
if (text == void_row_buffer)
w = wd * strlen(text);
else
w = font()->width(text);
w += 8;
if (w > wlat)
wlat = w;
}*/
updateLateralWidth(wlat);
}
void gGridView::updateLateralWidth(int w)
{
if (w > lateral->allocation.width)
gtk_widget_set_size_request(lateral, w, lateral->allocation.height);
}
void gGridView::setFont(gFont *ft)
{
gControl::setFont(ft);
gtk_widget_modify_font(contents, font()->desc());
updateHeaders();
}
int gGridView::rowWidth()
{
if (GTK_WIDGET_VISIBLE(lateral))
return lateral->allocation.width;
else
return 0;
}
int gGridView::headerHeight()
{
if (GTK_WIDGET_VISIBLE(header))
return header->allocation.height;
else
return 0;
}
int gGridView::footerHeight()
{
if (GTK_WIDGET_VISIBLE(footer))
return footer->allocation.height;
else
return 0;
}
void gGridView::setBackground(gColor color)
{
gControl::setBackground(color);
if (color == COLOR_DEFAULT)
set_gdk_bg_color(contents, get_gdk_base_color(contents));
else
set_gdk_bg_color(contents, color);
//set_gdk_bg_color(header, color);
//set_gdk_bg_color(lateral, color);
}
void gGridView::setForeground(gColor color)
{
gControl::setForeground(color);
color = realForeground();
set_gdk_fg_color(contents, color);
//set_gdk_fg_color(header, color);
//set_gdk_fg_color(lateral, color);
}
void gGridView::updateLastColumn()
{
int n = columnCount() - 1;
int vw = visibleWidth();
if (n < 0)
return;
if (_updating_last_column || !_autoresize)
return;
_updating_last_column = true;
if (!_last_col_width)
_last_col_width = columnWidth(n);
//fprintf(stderr, "updateLastColumn: vw = %d columnPos = %d %d _lcw = %d \n", vw, columnPos(n), columnPos(n), _last_col_width);
if (((columnPos(n) + _last_col_width) < vw) && (columnWidth(n) != (vw - columnPos(n))))
{
//fprintf(stderr, "updateLastColumn: vw = %d -> %d\n", vw, vw - columnPos(n));
setColumnWidth(n, vw - columnPos(n));
}
_updating_last_column = false;
}
void gGridView::startScrollTimer(GSourceFunc func)
{
if (!scroll_timer)
{
(*func)(this);
scroll_timer = g_timeout_add(50, (GSourceFunc)func, this);
}
}
void gGridView::stopScrollTimer()
{
if (scroll_timer)
{
g_source_remove(scroll_timer);
scroll_timer = 0;
}
}
void gGridView::setAutoResize(bool v)
{
_autoresize = v;
updateLastColumn();
}
void gGridView::setItemSpan(int row, int col, int rowspan, int colspan)
{
if (rowspan < 0 || colspan < 0 || rowspan >= 32767 || colspan >= 32767)
return;
if (rowspan > 0 && colspan < 0)
colspan = 0;
if (colspan > 0 && rowspan < 0)
rowspan = 0;
render->setSpan(col, row, colspan, rowspan);
refresh();
}