aboutsummaryrefslogtreecommitdiff
path: root/dw/fltkviewport.cc
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2008-09-24 18:44:40 +0200
committerjcid <devnull@localhost>2008-09-24 18:44:40 +0200
commitc377e06400f138325a9a9d43d91a9272691867a1 (patch)
tree49f3ca1c46af11a058a68714899d4137ec717618 /dw/fltkviewport.cc
parent642f9b3e747859a7256ea12fab9f9ed50aa9253a (diff)
- Moved the dw2 tree into dillo2's tree.
Diffstat (limited to 'dw/fltkviewport.cc')
-rw-r--r--dw/fltkviewport.cc496
1 files changed, 496 insertions, 0 deletions
diff --git a/dw/fltkviewport.cc b/dw/fltkviewport.cc
new file mode 100644
index 00000000..c999745a
--- /dev/null
+++ b/dw/fltkviewport.cc
@@ -0,0 +1,496 @@
+/*
+ * 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/events.h>
+
+#include <stdio.h>
+
+using namespace fltk;
+using namespace lout::object;
+using namespace lout::container::typed;
+
+namespace dw {
+namespace fltk {
+
+FltkViewport::FltkViewport (int x, int y, int w, int h, const char *label):
+ FltkWidgetView (x, y, w, h, label)
+{
+ hscrollbar = new Scrollbar (0, 0, 1, 1);
+ hscrollbar->set_horizontal();
+ hscrollbar->callback (hscrollbarCallback, this);
+ add (hscrollbar);
+
+ vscrollbar = new Scrollbar (0, 0, 1, 1);
+ vscrollbar->set_vertical();
+ vscrollbar->callback (vscrollbarCallback, this);
+ add (vscrollbar);
+
+ scrollX = scrollY = scrollDX = scrollDY = 0;
+ dragScrolling = 0;
+
+ gadgetOrientation[0] = GADGET_HORIZONTAL;
+ gadgetOrientation[1] = GADGET_HORIZONTAL;
+ gadgetOrientation[2] = GADGET_VERTICAL;
+ gadgetOrientation[3] = GADGET_HORIZONTAL;
+
+ gadgets =
+ new container::typed::List <object::TypedPointer < ::fltk::Widget> >
+ (true);
+}
+
+FltkViewport::~FltkViewport ()
+{
+ delete gadgets;
+}
+
+void FltkViewport::adjustScrollbarsAndGadgetsAllocation ()
+{
+ int hdiff = 0, vdiff = 0;
+ int visibility = 0;
+
+ if (hscrollbar->visible ())
+ visibility |= 1;
+ if (vscrollbar->visible ())
+ visibility |= 2;
+
+ if (gadgets->size () > 0) {
+ switch (gadgetOrientation [visibility]) {
+ case GADGET_VERTICAL:
+ hdiff = SCROLLBAR_THICKNESS;
+ vdiff = SCROLLBAR_THICKNESS * gadgets->size ();
+ break;
+
+ case GADGET_HORIZONTAL:
+ hdiff = SCROLLBAR_THICKNESS * gadgets->size ();
+ vdiff = SCROLLBAR_THICKNESS;
+ break;
+ }
+ } else {
+ hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+ vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+ }
+
+ hscrollbar->x (0);
+ hscrollbar->y (0 + h () - SCROLLBAR_THICKNESS);
+ hscrollbar->w (w () - hdiff);
+ hscrollbar->h (SCROLLBAR_THICKNESS);
+
+ vscrollbar->x (0 + w () - SCROLLBAR_THICKNESS);
+ vscrollbar->y (0);
+ vscrollbar->h (h () - vdiff);
+ vscrollbar->w (SCROLLBAR_THICKNESS);
+
+ int x = w () - SCROLLBAR_THICKNESS, y = h () - SCROLLBAR_THICKNESS;
+ for(Iterator <TypedPointer < ::fltk::Widget> > it = gadgets->iterator ();
+ it.hasNext (); ) {
+ ::fltk::Widget *widget = it.getNext()->getTypedValue ();
+ widget->x (0);
+ widget->y (0);
+ widget->w (SCROLLBAR_THICKNESS);
+ widget->h (SCROLLBAR_THICKNESS);
+
+ switch (gadgetOrientation [visibility]) {
+ case GADGET_VERTICAL:
+ y -= SCROLLBAR_THICKNESS;
+ break;
+
+ case GADGET_HORIZONTAL:
+ x -= SCROLLBAR_THICKNESS;
+ break;
+ }
+ }
+}
+
+void FltkViewport::adjustScrollbarValues ()
+{
+ hscrollbar->value (scrollX, hscrollbar->w (), 0, canvasWidth);
+ vscrollbar->value (scrollY, vscrollbar->h (), 0, canvasHeight);
+}
+
+void FltkViewport::hscrollbarChanged ()
+{
+ scroll (hscrollbar->value () - scrollX, 0);
+}
+
+void FltkViewport::vscrollbarChanged ()
+{
+ scroll (0, vscrollbar->value () - scrollY);
+}
+
+void FltkViewport::vscrollbarCallback (Widget *vscrollbar, void *viewportPtr)
+{
+ ((FltkViewport*)viewportPtr)->vscrollbarChanged ();
+}
+
+void FltkViewport::hscrollbarCallback (Widget *hscrollbar, void *viewportPtr)
+{
+ ((FltkViewport*)viewportPtr)->hscrollbarChanged ();
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewport::layout ()
+{
+ theLayout->viewportSizeChanged (this, w(), h());
+ adjustScrollbarsAndGadgetsAllocation ();
+
+ FltkWidgetView::layout ();
+}
+
+void FltkViewport::draw_area (void *data, const Rectangle& cr )
+{
+ FltkViewport *vp = (FltkViewport*) data;
+ push_clip(cr);
+
+ vp->FltkWidgetView::draw ();
+
+ for(Iterator <TypedPointer < ::fltk::Widget> > it = vp->gadgets->iterator ();
+ it.hasNext (); ) {
+ ::fltk::Widget *widget = it.getNext()->getTypedValue ();
+ vp->draw_child (*widget);
+ }
+
+ pop_clip();
+
+}
+
+void FltkViewport::draw ()
+{
+ int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+ int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+ Rectangle cr (0, 0, w () - hdiff, h () - vdiff);
+ int d = damage();
+
+ if (d & DAMAGE_SCROLL) {
+ set_damage (DAMAGE_SCROLL);
+ scrollrect(cr, -scrollDX, -scrollDY, draw_area, this);
+ d &= ~DAMAGE_SCROLL;
+ set_damage (d);
+ }
+
+ if (d) {
+ draw_area(this, cr);
+
+ if (d == DAMAGE_CHILD) {
+ if (hscrollbar->damage ())
+ draw_child (*hscrollbar);
+ if (vscrollbar->damage ())
+ draw_child (*vscrollbar);
+ } else {
+ draw_child (*hscrollbar);
+ draw_child (*vscrollbar);
+ }
+ }
+
+ scrollDX = 0;
+ scrollDY = 0;
+}
+
+int FltkViewport::handle (int event)
+{
+ //printf("FltkViewport::handle %d\n", event);
+
+ if (hscrollbar->Rectangle::contains (event_x (), event_y ()) &&
+ !(event_state() & (SHIFT | CTRL | ALT)) &&
+ hscrollbar->send (event)) {
+ return 1;
+ }
+
+ if (vscrollbar->Rectangle::contains (event_x (), event_y ()) &&
+ vscrollbar->send (event)) {
+ return 1;
+ }
+
+ switch(event) {
+ case ::fltk::FOCUS:
+ /** \bug Draw focus box. */
+ return 1;
+
+ case ::fltk::UNFOCUS:
+ /** \bug Undraw focus box. */
+ return 1;
+
+ case ::fltk::PUSH:
+ take_focus();
+ if (::fltk::event_button() == ::fltk::MiddleButton) {
+ /* pass event so that middle click can open link in new window */
+ if (FltkWidgetView::handle (event) == 0) {
+ dragScrolling = 1;
+ dragX = ::fltk::event_x();
+ dragY = ::fltk::event_y();
+ setCursor (core::style::CURSOR_MOVE);
+ }
+ return 1;
+ }
+ break;
+
+ case ::fltk::DRAG:
+ if (::fltk::event_button() == ::fltk::MiddleButton) {
+ if (dragScrolling) {
+ scroll(dragX - ::fltk::event_x(), dragY - ::fltk::event_y());
+ dragX = ::fltk::event_x();
+ dragY = ::fltk::event_y();
+ return 1;
+ }
+ }
+ break;
+
+ case ::fltk:: MOUSEWHEEL:
+ return (event_dx() ? hscrollbar : vscrollbar)->handle(event);
+ break;
+
+ case ::fltk::RELEASE:
+ if (::fltk::event_button() == ::fltk::MiddleButton) {
+ dragScrolling = 0;
+ setCursor (core::style::CURSOR_DEFAULT);
+ }
+ break;
+
+ case ::fltk::ENTER:
+ /* could be the result of, e.g., closing another window. */
+ mouse_x = ::fltk::event_x();
+ mouse_y = ::fltk::event_y();
+ positionChanged();
+ break;
+
+ case ::fltk::LEAVE:
+ mouse_x = mouse_y = -1;
+ break;
+
+ case ::fltk::KEY:
+ /* tell fltk we want to receive these KEY events as SHORTCUT */
+ switch (::fltk::event_key()) {
+ case PageUpKey:
+ case PageDownKey:
+ case SpaceKey:
+ case DownKey:
+ case UpKey:
+ case RightKey:
+ case LeftKey:
+ case HomeKey:
+ case EndKey:
+ return 0;
+ }
+ break;
+
+ case ::fltk::SHORTCUT:
+ switch (::fltk::event_key()) {
+ case PageUpKey:
+ case 'b':
+ case 'B':
+ scroll (0, -vscrollbar->pagesize ());
+ return 1;
+
+ case PageDownKey:
+ case SpaceKey:
+ scroll (0, vscrollbar->pagesize ());
+ return 1;
+
+ case DownKey:
+ scroll (0, (int) vscrollbar->linesize ());
+ return 1;
+
+ case UpKey:
+ scroll (0, (int) -vscrollbar->linesize ());
+ return 1;
+
+ case RightKey:
+ scroll ((int) hscrollbar->linesize (), 0);
+ return 1;
+
+ case LeftKey:
+ scroll ((int) -hscrollbar->linesize (), 0);
+ return 1;
+
+ case HomeKey:
+ scrollTo (scrollX, 0);
+ return 1;
+
+ case EndKey:
+ scrollTo (scrollX, canvasHeight); /* gets adjusted in scrollTo () */
+ return 1;
+ }
+ }
+
+ return FltkWidgetView::handle (event);
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewport::setCanvasSize (int width, int ascent, int descent)
+{
+ FltkWidgetView::setCanvasSize (width, ascent, descent);
+ adjustScrollbarValues ();
+}
+
+/*
+ * This is used to simulate mouse motion (e.g., when scrolling).
+ */
+void FltkViewport::positionChanged ()
+{
+ if (mouse_x != -1)
+ (void)theLayout->motionNotify (this,
+ translateViewXToCanvasX (mouse_x),
+ translateViewYToCanvasY (mouse_y),
+ (core::ButtonState)0);
+}
+
+/*
+ * For scrollbars, this currently sets the same step to both vertical and
+ * horizontal. It may me differentiated if necessary.
+ */
+void FltkViewport::setScrollStep(int step)
+{
+ vscrollbar->linesize(step);
+ hscrollbar->linesize(step);
+}
+
+bool FltkViewport::usesViewport ()
+{
+ return true;
+}
+
+int FltkViewport::getHScrollbarThickness ()
+{
+ return SCROLLBAR_THICKNESS;
+}
+
+int FltkViewport::getVScrollbarThickness ()
+{
+ return SCROLLBAR_THICKNESS;
+}
+
+void FltkViewport::scrollTo (int x, int y)
+{
+ int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+ int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+
+ x = misc::min (x, canvasWidth - w() + hdiff);
+ x = misc::max (x, 0);
+
+ y = misc::min (y, canvasHeight - h() + vdiff);
+ y = misc::max (y, 0);
+
+ if (x == scrollX && y == scrollY) {
+ return;
+ }
+
+ /* multiple calls to scroll can happen before a redraw occurs.
+ * scrollDX / scrollDY can therefore be non-zero here.
+ */
+ updateCanvasWidgets (x - scrollX, y - scrollY);
+ scrollDX += x - scrollX;
+ scrollDY += y - scrollY;
+
+ scrollX = x;
+ scrollY = y;
+
+ adjustScrollbarValues ();
+ redraw (DAMAGE_SCROLL);
+ theLayout->scrollPosChanged (this, scrollX, scrollY);
+ positionChanged();
+}
+
+void FltkViewport::scroll (int dx, int dy)
+{
+ scrollTo (scrollX + dx, scrollY + dy);
+}
+
+void FltkViewport::setViewportSize (int width, int height,
+ int hScrollbarThickness,
+ int vScrollbarThickness)
+{
+ if (hScrollbarThickness > 0)
+ hscrollbar->show ();
+ else
+ hscrollbar->hide ();
+ if (vScrollbarThickness > 0)
+ vscrollbar->show ();
+ else
+ vscrollbar->hide ();
+
+ /* If no scrollbar, go to the beginning */
+ scroll(hScrollbarThickness ? 0 : -scrollX,
+ vScrollbarThickness ? 0 : -scrollY);
+}
+
+void FltkViewport::updateCanvasWidgets (int dx, int dy)
+{
+ // scroll all child widgets except scroll bars
+ for (int i = children () - 1; i > 0; i--) {
+ ::fltk::Widget *widget = child (i);
+
+ if (widget == hscrollbar || widget == vscrollbar)
+ continue;
+
+ widget->x (widget->x () - dx);
+ widget->y (widget->y () - dy);
+ }
+}
+
+int FltkViewport::translateViewXToCanvasX (int x)
+{
+ return x + scrollX;
+}
+
+int FltkViewport::translateViewYToCanvasY (int y)
+{
+ return y + scrollY;
+}
+
+int FltkViewport::translateCanvasXToViewX (int x)
+{
+ return x - scrollX;
+}
+
+int FltkViewport::translateCanvasYToViewY (int y)
+{
+ return y - scrollY;
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewport::setGadgetOrientation (bool hscrollbarVisible,
+ bool vscrollbarVisible,
+ FltkViewport::GadgetOrientation
+ gadgetOrientation)
+{
+ this->gadgetOrientation[(hscrollbarVisible ? 0 : 1) |
+ (vscrollbarVisible ? 0 : 2)] = gadgetOrientation;
+ adjustScrollbarsAndGadgetsAllocation ();
+}
+
+void FltkViewport::addGadget (::fltk::Widget *gadget)
+{
+ /** \bug Reparent? */
+
+ gadgets->append (new TypedPointer < ::fltk::Widget> (gadget));
+ adjustScrollbarsAndGadgetsAllocation ();
+}
+
+
+} // namespace fltk
+} // namespace dw