2007-12-30 16:41:49 +00:00
|
|
|
/***************************************************************************
|
|
|
|
|
2009-08-17 10:41:51 +00:00
|
|
|
gdrawingarea.cpp
|
2007-12-30 16:41:49 +00:00
|
|
|
|
|
|
|
(c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
|
2009-08-17 10:41:51 +00:00
|
|
|
|
2007-12-30 16:41:49 +00:00
|
|
|
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
|
2009-08-17 10:41:51 +00:00
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 16:41:49 +00:00
|
|
|
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 "gdrawingarea.h"
|
|
|
|
|
|
|
|
/****************************************************************************************
|
|
|
|
|
|
|
|
gDrawingArea Widget
|
|
|
|
|
|
|
|
*****************************************************************************************/
|
|
|
|
|
|
|
|
static gboolean cb_expose(GtkWidget *wid, GdkEventExpose *e, gDrawingArea *data)
|
|
|
|
{
|
|
|
|
if (data->cached())
|
|
|
|
{
|
2010-03-07 17:14:54 +00:00
|
|
|
gdk_window_clear(GTK_WIDGET(wid)->window);
|
2007-12-30 16:41:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (data->onExpose)
|
|
|
|
data->onExpose(data,e->area.x,e->area.y,e->area.width,e->area.height);
|
|
|
|
data->drawBorder();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cb_size(GtkWidget *wid, GtkAllocation *a, gDrawingArea *data)
|
|
|
|
{
|
|
|
|
data->updateCache();
|
|
|
|
}
|
|
|
|
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 00:25:48 +00:00
|
|
|
static gboolean cb_button_press(GtkWidget *wid, GdkEventButton *event, gDrawingArea *data)
|
|
|
|
{
|
|
|
|
if (data->canFocus())
|
|
|
|
data->setFocus();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-12-30 16:41:49 +00:00
|
|
|
gDrawingArea::gDrawingArea(gContainer *parent) : gContainer(parent)
|
|
|
|
{
|
|
|
|
g_typ = Type_gDrawingArea;
|
|
|
|
|
|
|
|
_cached = false;
|
|
|
|
buffer = NULL;
|
|
|
|
_old_bg_id = 0;
|
|
|
|
_resize_cache = false;
|
2010-03-07 17:14:54 +00:00
|
|
|
_transparent = false;
|
2007-12-30 16:41:49 +00:00
|
|
|
|
|
|
|
border = gtk_event_box_new();
|
2010-03-07 17:14:54 +00:00
|
|
|
widget = gtk_fixed_new();
|
|
|
|
//widget = border; //gtk_layout_new(0,0);
|
2007-12-30 16:41:49 +00:00
|
|
|
|
|
|
|
realize(false);
|
|
|
|
|
|
|
|
//gtk_event_box_set_visible_window(GTK_EVENT_BOX(border), false);
|
|
|
|
|
|
|
|
gtk_widget_add_events(widget, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
|
|
|
|
| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
|
|
|
|
| GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 00:25:48 +00:00
|
|
|
|
2010-03-07 17:14:54 +00:00
|
|
|
//GTK_WIDGET_UNSET_FLAGS(border, GTK_APP_PAINTABLE);
|
2010-02-07 23:10:41 +00:00
|
|
|
GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
|
2007-12-30 16:41:49 +00:00
|
|
|
|
|
|
|
_event_mask = gtk_widget_get_events(widget);
|
|
|
|
|
|
|
|
onExpose = NULL;
|
|
|
|
g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(cb_expose), (gpointer)this);
|
|
|
|
g_signal_connect(G_OBJECT(widget), "size-allocate", G_CALLBACK(cb_size), (gpointer)this);
|
[DEVELOPMENT ENVIRONMENT]
* BUG: Use TextEdit.RichText insted of TextEdit.Text.
* BUG: END SUB can be the end of a method. The class analyze now takes
that into account.
[HELP]
* BUG: Fixed the generated treeview.
[COMPILER]
* OPT: The NOT operator used just at the beginning of a conditional
expression is optimized. Consequently, an expression like 'IF NOT 2' is
now equivalent to 'IF 2 = 0' and not to 'IF (NOT 2) <> 0' as before. In
other words, the boolean conversion is now done before the NOT, and not
after. The following instructions are concerned: IF, WHILE, UNTIL.
* NEW: BYREF is new keyword that is a more readable synonymous of '@'.
[GB.DB.FORM]
* BUG: Correctly manage data controls inside TabStrip-like containers.
* BUG: Setting the focus on a non-initialized DataControl does not raise
an error anymore.
[GB.GTK]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Window arrangement is done before the Open event is raised, as in
gb.qt.
* BUG: Keyboard, focus and mouse events now work correctly on Window and
DrawingArea controls.
[GB.QT]
* BUG: HSplitter.Layout and VSplitter.Layout now work correctly. It is a
list of children widths, hidden children having a zero width.
* BUG: Many warning fixes.
* BUG: Now the Control.Visible property works like in gb.gtk, i.e. it
returns if the control was not explicitely hidden.
git-svn-id: svn://localhost/gambas/trunk@1060 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-02-06 00:25:48 +00:00
|
|
|
g_signal_connect(G_OBJECT(border), "button-press-event",G_CALLBACK(cb_button_press),(gpointer)this);
|
|
|
|
|
2007-12-30 16:41:49 +00:00
|
|
|
//resize(100,30);
|
|
|
|
}
|
|
|
|
|
|
|
|
gDrawingArea::~gDrawingArea()
|
|
|
|
{
|
|
|
|
setCached(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::resize(int w, int h)
|
|
|
|
{
|
|
|
|
// TODO Do not resize cache if the DrawingArea is being painted
|
|
|
|
gContainer::resize(w,h);
|
|
|
|
//updateCache();
|
|
|
|
}
|
|
|
|
|
2010-03-07 17:14:54 +00:00
|
|
|
bool gDrawingArea::canFocus() const
|
2007-12-30 16:41:49 +00:00
|
|
|
{
|
|
|
|
return GTK_WIDGET_CAN_FOCUS(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::setCanFocus(bool vl)
|
|
|
|
{
|
|
|
|
if (vl) GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
|
|
|
|
else GTK_WIDGET_UNSET_FLAGS(widget,GTK_CAN_FOCUS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::updateEventMask()
|
|
|
|
{
|
|
|
|
if (!enabled())
|
|
|
|
{
|
|
|
|
gtk_widget_set_events(widget, GDK_EXPOSURE_MASK);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_set_events(widget, _event_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::setEnabled(bool vl)
|
|
|
|
{
|
|
|
|
gContainer::setEnabled(vl);
|
|
|
|
updateEventMask();
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::setCached(bool vl)
|
|
|
|
{
|
|
|
|
if (vl == cached()) return;
|
|
|
|
|
|
|
|
_cached = vl;
|
|
|
|
|
|
|
|
gtk_widget_set_double_buffered(widget, !_cached);
|
|
|
|
|
|
|
|
if (!_cached)
|
|
|
|
{
|
|
|
|
g_object_unref(G_OBJECT(buffer));
|
|
|
|
buffer = NULL;
|
|
|
|
set_gdk_bg_color(widget, background());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_realize(widget);
|
|
|
|
resizeCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::resizeCache()
|
|
|
|
{
|
|
|
|
int bw, bh;
|
|
|
|
int w, h;
|
|
|
|
GdkPixmap *buf;
|
|
|
|
GdkGC *gc2;
|
|
|
|
GdkWindow *win;
|
|
|
|
|
2010-03-07 17:14:54 +00:00
|
|
|
win = GTK_WIDGET(widget)->window;
|
2007-12-30 16:41:49 +00:00
|
|
|
if (!win)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//gdk_drawable_get_size(border->window, &w, &h);
|
|
|
|
w = width();
|
|
|
|
h = height();
|
|
|
|
|
|
|
|
if (buffer)
|
|
|
|
gdk_drawable_get_size(buffer, &bw, &bh);
|
|
|
|
else
|
|
|
|
bw = bh = 0;
|
|
|
|
|
|
|
|
if (bw != w || bh != h)
|
|
|
|
{
|
|
|
|
buf = gdk_pixmap_new(win, w, h, -1);
|
|
|
|
gc2 = gdk_gc_new(buf);
|
|
|
|
gdk_gc_set_foreground(gc2, &widget->style->bg[GTK_STATE_NORMAL]);
|
|
|
|
|
|
|
|
if (w > bw || h > bh || !buffer)
|
|
|
|
gdk_draw_rectangle(buf, gc2, true, 0, 0, w, h);
|
|
|
|
|
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
if (bw > w) bw = w;
|
|
|
|
if (bh > h) bh = h;
|
|
|
|
gdk_draw_drawable(buf, gc2, buffer, 0, 0, 0, 0, bw, bh);
|
|
|
|
g_object_unref(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = buf;
|
|
|
|
g_object_unref(gc2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::setCache()
|
|
|
|
{
|
|
|
|
GdkWindow *win;
|
|
|
|
|
2010-03-07 17:14:54 +00:00
|
|
|
win = GTK_WIDGET(widget)->window;
|
2007-12-30 16:41:49 +00:00
|
|
|
if (!win)
|
|
|
|
return;
|
|
|
|
|
|
|
|
drawBorder(buffer);
|
|
|
|
gdk_window_set_back_pixmap(win, buffer, FALSE);
|
|
|
|
//gdk_window_set_back_pixmap(border->window, buffer, FALSE);
|
|
|
|
//gdk_window_set_back_pixmap(widget->window, NULL, TRUE);
|
|
|
|
//gdk_window_set_back_pixmap(win, NULL, TRUE);
|
|
|
|
refreshCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean resize_cache(gDrawingArea *data)
|
|
|
|
{
|
|
|
|
//fprintf(stderr, "resize_cache\n");
|
|
|
|
data->resizeCache();
|
|
|
|
data->setCache();
|
|
|
|
data->_resize_cache = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::updateCache()
|
|
|
|
{
|
|
|
|
if (!_cached)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!_resize_cache)
|
|
|
|
{
|
|
|
|
_resize_cache = true;
|
|
|
|
g_timeout_add(10, (GSourceFunc)resize_cache, (gpointer)this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::clear()
|
|
|
|
{
|
|
|
|
GdkGC *gc2;
|
|
|
|
|
|
|
|
if (_cached && buffer)
|
|
|
|
{
|
|
|
|
gc2=gdk_gc_new(buffer);
|
|
|
|
gdk_gc_set_foreground(gc2,&widget->style->bg[GTK_STATE_NORMAL]);
|
|
|
|
gdk_draw_rectangle(buffer,gc2,true,0,0,width(),height());
|
|
|
|
g_object_unref(G_OBJECT(gc2));
|
2009-05-15 17:57:29 +00:00
|
|
|
drawBorder(buffer);
|
|
|
|
refreshCache();
|
2007-12-30 16:41:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-01 16:27:45 +00:00
|
|
|
refresh(); //gdk_window_clear(GTK_LAYOUT(widget)->bin_window);
|
2007-12-30 16:41:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDrawingArea::refreshCache()
|
|
|
|
{
|
|
|
|
if (_cached)
|
|
|
|
{
|
2010-03-07 17:14:54 +00:00
|
|
|
if (GTK_WIDGET(widget)->window)
|
|
|
|
gdk_window_clear(GTK_WIDGET(widget)->window);
|
2007-12-30 16:41:49 +00:00
|
|
|
}
|
|
|
|
}
|
2010-03-07 17:14:54 +00:00
|
|
|
|
|
|
|
void gDrawingArea::setTransparent(bool vl)
|
|
|
|
{
|
|
|
|
_transparent = vl;
|
|
|
|
//gtk_widget_set_double_buffered(widget, !_transparent);
|
|
|
|
//gtk_widget_set_app_paintable(border, _transparent);
|
|
|
|
}
|