diff options
author | jcid <devnull@localhost> | 2008-09-24 18:44:40 +0200 |
---|---|---|
committer | jcid <devnull@localhost> | 2008-09-24 18:44:40 +0200 |
commit | c377e06400f138325a9a9d43d91a9272691867a1 (patch) | |
tree | 49f3ca1c46af11a058a68714899d4137ec717618 /dw/fltkviewbase.cc | |
parent | 642f9b3e747859a7256ea12fab9f9ed50aa9253a (diff) |
- Moved the dw2 tree into dillo2's tree.
Diffstat (limited to 'dw/fltkviewbase.cc')
-rw-r--r-- | dw/fltkviewbase.cc | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/dw/fltkviewbase.cc b/dw/fltkviewbase.cc new file mode 100644 index 00000000..fbbd15bd --- /dev/null +++ b/dw/fltkviewbase.cc @@ -0,0 +1,524 @@ +/* + * Dillo Widget + * + * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org> + * + * 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 3 of the License, 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 "fltkviewport.hh" + +#include <fltk/draw.h> +#include <fltk/damage.h> +#include <fltk/layout.h> +#include <fltk/events.h> +#include <fltk/Cursor.h> +#include <fltk/run.h> + +#include <stdio.h> + +using namespace fltk; +using namespace lout::object; +using namespace lout::container::typed; + +namespace dw { +namespace fltk { + +::fltk::Image *FltkViewBase::backBuffer; +bool FltkViewBase::backBufferInUse; + +FltkViewBase::FltkViewBase (int x, int y, int w, int h, const char *label): + Group (x, y, w, h, label) +{ + canvasWidth = 1; + canvasHeight = 1; + bgColor = WHITE; + lastDraw = time(0); + drawDelay = 2; /* in seconds */ + mouse_x = mouse_y = 0; +#ifndef NO_DOUBLEBUFFER + if (!backBuffer) { + backBuffer = new Image (); + } +#endif +} + +FltkViewBase::~FltkViewBase () +{ + cancelQueueDraw (); +} + +void FltkViewBase::draw () +{ + int d = damage (); + + if ((d & DAMAGE_VALUE) && !(d & DAMAGE_EXPOSE)) { + container::typed::Iterator <core::Rectangle> it; + + for (it = drawRegion.rectangles (); it.hasNext (); ) { + drawRectangle (it.getNext (), true); + } + + drawRegion.clear (); + d &= ~DAMAGE_VALUE; + } + + if (d & DAMAGE_CHILD) { + drawChildWidgets (); + d &= ~DAMAGE_CHILD; + } + + if (d) { + dw::core::Rectangle rect ( + translateViewXToCanvasX (0), + translateViewYToCanvasY (0), + w (), + h ()); + + drawRectangle (&rect, false); + + if (! (d & DAMAGE_SCROLL)) { + drawRegion.clear (); + } + } +} + +void FltkViewBase::drawRectangle (const core::Rectangle *rect, + bool doubleBuffer) +{ + int offsetX = 0, offsetY = 0; + + /* fltk-clipping does not use widget coordinates */ + transform (offsetX, offsetY); + + ::fltk::Rectangle viewRect ( + translateCanvasXToViewX (rect->x) + offsetX, + translateCanvasYToViewY (rect->y) + offsetY, + rect->width, rect->height); + + ::fltk::intersect_with_clip (viewRect); + + viewRect.x (viewRect.x () - offsetX); + viewRect.y (viewRect.y () - offsetY); + + if (! viewRect.empty ()) { + dw::core::Rectangle r ( + translateViewXToCanvasX (viewRect.x ()), + translateViewYToCanvasY (viewRect.y ()), + viewRect.w (), + viewRect.h ()); + +#ifdef NO_DOUBLEBUFFER + push_clip (viewRect); +#endif + + if (doubleBuffer && backBuffer && !backBufferInUse) { + backBufferInUse = true; + { + GSave gsave; + + backBuffer->setsize (viewRect.w (), viewRect.h ()); + backBuffer->make_current (); + translate (-viewRect.x (), -viewRect.y ()); + + setcolor (bgColor); + fillrect (viewRect); + theLayout->expose (this, &r); + } + + backBuffer->draw (Rectangle (0, 0, viewRect.w (), viewRect.h ()), + viewRect); + + backBufferInUse = false; + } else { + setcolor (bgColor); + fillrect (viewRect); + theLayout->expose (this, &r); + } + +#ifdef NO_DOUBLEBUFFER + pop_clip (); +#endif + } +} + +void FltkViewBase::drawChildWidgets () { + for (int i = children () - 1; i >= 0; i--) { + Widget& w = *child(i); + if (w.damage() & DAMAGE_CHILD_LABEL) { + draw_outside_label(w); + w.set_damage(w.damage() & ~DAMAGE_CHILD_LABEL); + } + update_child(w); + } +} + +core::ButtonState getDwButtonState () +{ + int s1 = event_state (); + int s2 = (core::ButtonState)0; + + if(s1 & SHIFT) s2 |= core::SHIFT_MASK; + if(s1 & CTRL) s2 |= core::CONTROL_MASK; + if(s1 & ALT) s2 |= core::META_MASK; + if(s1 & BUTTON1) s2 |= core::BUTTON1_MASK; + if(s1 & BUTTON2) s2 |= core::BUTTON2_MASK; + if(s1 & BUTTON3) s2 |= core::BUTTON3_MASK; + + return (core::ButtonState)s2; +} + +int FltkViewBase::handle (int event) +{ + bool processed; + + /** + * \todo Consider, whether this from the FLTK documentation has any + * impacts: "To receive fltk::RELEASE events you must return non-zero + * when passed a fltk::PUSH event. " + */ + switch(event) { + case PUSH: + processed = + theLayout->buttonPress (this, event_clicks () + 1, + translateViewXToCanvasX (event_x ()), + translateViewYToCanvasY (event_y ()), + getDwButtonState (), event_button ()); + //printf ("PUSH => %s\n", processed ? "true" : "false"); + return processed ? true : Group::handle (event); + + case RELEASE: + processed = + theLayout->buttonRelease (this, event_clicks () + 1, + translateViewXToCanvasX (event_x ()), + translateViewYToCanvasY (event_y ()), + getDwButtonState (), event_button ()); + //printf ("RELEASE => %s\n", processed ? "true" : "false"); + return processed ? true : Group::handle (event); + + case MOVE: + mouse_x = event_x(); + mouse_y = event_y(); + processed = + theLayout->motionNotify (this, + translateViewXToCanvasX (mouse_x), + translateViewYToCanvasY (mouse_y), + getDwButtonState ()); + //printf ("MOVE => %s\n", processed ? "true" : "false"); + return processed ? true : Group::handle (event); + + case DRAG: + processed = + theLayout->motionNotify (this, + translateViewXToCanvasX (event_x ()), + translateViewYToCanvasY (event_y ()), + getDwButtonState ()); + //printf ("DRAG => %s\n", processed ? "true" : "false"); + return processed ? true : Group::handle (event); + + case ENTER: + theLayout->enterNotify (this, translateViewXToCanvasX (event_x ()), + translateViewYToCanvasY (event_y ()), + getDwButtonState ()); + return Group::handle (event); + + case LEAVE: + theLayout->leaveNotify (this, getDwButtonState ()); + return Group::handle (event); + + default: + return Group::handle (event); + } +} + +// ---------------------------------------------------------------------- + +void FltkViewBase::setLayout (core::Layout *layout) +{ + theLayout = layout; +} + +void FltkViewBase::setCanvasSize (int width, int ascent, int descent) +{ + canvasWidth = width; + canvasHeight = ascent + descent; +} + +void FltkViewBase::setCursor (core::style::Cursor cursor) +{ + static Cursor *mapDwToFltk[] = { + CURSOR_CROSS, + CURSOR_ARROW, + CURSOR_HAND, + CURSOR_MOVE, + CURSOR_WE, + CURSOR_NESW, + CURSOR_NWSE, + CURSOR_NS, + CURSOR_NWSE, + CURSOR_NESW, + CURSOR_NS, + CURSOR_WE, + CURSOR_INSERT, + CURSOR_WAIT, + CURSOR_HELP + }; + + /* + static char *cursorName[] = { + "CURSOR_CROSS", + "CURSOR_ARROW", + "CURSOR_HAND", + "CURSOR_MOVE", + "CURSOR_WE", + "CURSOR_NESW", + "CURSOR_NWSE", + "CURSOR_NS", + "CURSOR_NWSE", + "CURSOR_NESW", + "CURSOR_NS", + "CURSOR_WE", + "CURSOR_INSERT", + "CURSOR_WAIT", + "CURSOR_HELP" + }; + + printf ("Cursor changes to '%s'.\n", cursorName[cursor]); + */ + + /** \bug Does not work */ + this->cursor (mapDwToFltk[cursor]); +} + +void FltkViewBase::setBgColor (core::style::Color *color) +{ + bgColor = color ? + ((FltkColor*)color)->colors[dw::core::style::Color::SHADING_NORMAL] : + WHITE; +} + +void FltkViewBase::startDrawing (core::Rectangle *area) +{ +} + +void FltkViewBase::finishDrawing (core::Rectangle *area) +{ +} + +void FltkViewBase::queueDraw (core::Rectangle *area) +{ + drawRegion.addRectangle (area); + /** DAMAGE_VALUE is just an arbitrary value other than DAMAGE_EXPOSE here */ + redraw (DAMAGE_VALUE); +} + +static void drawTotalTimeout (void *data) +{ + FltkViewBase *view = (FltkViewBase*) data; + if (time(0) >= view->lastDraw + view->drawDelay) { + view->drawTotal (); + } else { + ::fltk::add_timeout (0.2f, drawTotalTimeout, data); + } +} + +void FltkViewBase::drawTotal () +{ + //static int calls = 0; + //printf(" FltkViewBase::drawTotal calls = %d\n", ++calls); + redraw (DAMAGE_EXPOSE); + lastDraw = time (0); + cancelQueueDraw (); +} + +void FltkViewBase::queueDrawTotal () +{ + drawTotal (); +} + +void FltkViewBase::cancelQueueDraw () +{ + ::fltk::remove_timeout (drawTotalTimeout, this); +} + +void FltkViewBase::drawPoint (core::style::Color *color, + core::style::Color::Shading shading, + int x, int y) +{ +} + +void FltkViewBase::drawLine (core::style::Color *color, + core::style::Color::Shading shading, + int x1, int y1, int x2, int y2) +{ + setcolor(((FltkColor*)color)->colors[shading]); + drawline (translateCanvasXToViewX (x1), translateCanvasYToViewY (y1), + translateCanvasXToViewX (x2), translateCanvasYToViewY (y2)); +} + +void FltkViewBase::drawRectangle (core::style::Color *color, + core::style::Color::Shading shading, + bool filled, + int x, int y, int width, int height) +{ + setcolor(((FltkColor*)color)->colors[shading]); + int x1 = translateCanvasXToViewX (x); + int y1 = translateCanvasYToViewY (y); + int x2 = translateCanvasXToViewX (x + width); + int y2 = translateCanvasYToViewY (y + height); + ::fltk::Rectangle rect (x1, y1, x2 - x1, y2 - y1); + if (filled) + fillrect (rect); + else + strokerect (rect); +} + +void FltkViewBase::drawArc (core::style::Color *color, + core::style::Color::Shading shading, bool filled, + int x, int y, int width, int height, + int angle1, int angle2) +{ + setcolor(((FltkColor*)color)->colors[shading]); + int x1 = translateCanvasXToViewX (x); + int y1 = translateCanvasYToViewY (y); + ::fltk::Rectangle rect (x1, y1, width, height); + addchord(rect, angle1, angle2); + closepath(); + if (filled) + fillpath(); + else + strokepath(); +} + +void FltkViewBase::drawPolygon (core::style::Color *color, + core::style::Color::Shading shading, + bool filled, int points[][2], int npoints) +{ + if (npoints > 0) { + for (int i = 0; i < npoints; i++) { + points[i][0] = translateCanvasXToViewX(points[i][0]); + points[i][1] = translateCanvasYToViewY(points[i][1]); + } + setcolor(((FltkColor*)color)->colors[shading]); + addvertices(npoints, points); + closepath(); + if (filled) + fillpath(); + else + strokepath(); + } +} + +core::View *FltkViewBase::getClippingView (int x, int y, int width, int height) +{ + push_clip (translateCanvasXToViewX (x), translateCanvasYToViewY (y), + width, height); + return this; +} + +void FltkViewBase::mergeClippingView (core::View *clippingView) +{ + pop_clip (); +} + +// ---------------------------------------------------------------------- + +FltkWidgetView::FltkWidgetView (int x, int y, int w, int h, + const char *label): + FltkViewBase (x, y, w, h, label) +{ +} + +FltkWidgetView::~FltkWidgetView () +{ +} + +void FltkWidgetView::layout () { + /** + * pass layout to child widgets. This is needed for complex fltk + * widgets as TextEditor. + * We can't use Group::layout() as that would rearrange the widgets. + */ + for (int i = children () - 1; i >= 0; i--) { + ::fltk::Widget *widget = child (i); + + if (widget->layout_damage ()) { + widget->layout (); + } + } +} + +void FltkWidgetView::drawText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, const char *text, int len) +{ + FltkFont *ff = (FltkFont*)font; + setfont(ff->font, ff->size); + setcolor(((FltkColor*)color)->colors[shading]); + drawtext(text, len, + translateCanvasXToViewX (x), translateCanvasYToViewY (y)); +} + +void FltkWidgetView::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, + int x, int y, int width, int height) +{ + ((FltkImgbuf*)imgbuf)->draw (this, + translateCanvasXToViewX (xRoot), + translateCanvasYToViewY (yRoot), + x, y, width, height); +} + +bool FltkWidgetView::usesFltkWidgets () +{ + return true; +} + +void FltkWidgetView::addFltkWidget (::fltk::Widget *widget, + core::Allocation *allocation) +{ + allocateFltkWidget (widget, allocation); + add (widget); +} + +void FltkWidgetView::removeFltkWidget (::fltk::Widget *widget) +{ + remove (widget); +} + +void FltkWidgetView::allocateFltkWidget (::fltk::Widget *widget, + core::Allocation *allocation) +{ + widget->x (translateCanvasXToViewX (allocation->x)); + widget->y (translateCanvasYToViewY (allocation->y)); + widget->w (allocation->width); + widget->h (allocation->ascent + allocation->descent); + + /* widgets created tiny and later resized need this flag to display */ + uchar damage = widget->layout_damage (); + damage |= LAYOUT_XYWH; + widget->layout_damage (damage); +} + +void FltkWidgetView::drawFltkWidget (::fltk::Widget *widget, + core::Rectangle *area) +{ + draw_child (*widget); +} + +} // namespace fltk +} // namespace dw |