Mercurial > dillo_port1.3
view dw/fltkviewport.cc @ 1255:5d6869b28e4d
treat ideographic characters (Chinese/Japanese) as words
author | corvid <corvid@lavabit.com> |
---|---|
date | Sun, 02 Aug 2009 03:59:14 +0000 |
parents | 1c3bfd950353 |
children | 4704ad910042 |
line wrap: on
line source
/* * 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, see <http://www.gnu.org/licenses/>. */ #include "fltkviewport.hh" #include <fltk/draw.h> #include <fltk/damage.h> #include <fltk/events.h> #include <stdio.h> #include "../lout/msg.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) { _MSG("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::KEY: /* Tell fltk we want to receive KEY events as SHORTCUT. * As we don't know the exact keybindings set by the user, we ask * for all of them (except TabKey to keep form navigation). */ if (::fltk::event_key() != TabKey) return 0; break; 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; } 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::scroll (core::ScrollCommand cmd) { if (cmd == core::SCREEN_UP_CMD) { scroll (0, -vscrollbar->pagesize ()); } else if (cmd == core::SCREEN_DOWN_CMD) { scroll (0, vscrollbar->pagesize ()); } else if (cmd == core::LINE_UP_CMD) { scroll (0, (int) -vscrollbar->linesize ()); } else if (cmd == core::LINE_DOWN_CMD) { scroll (0, (int) vscrollbar->linesize ()); } else if (cmd == core::LEFT_CMD) { scroll ((int) -hscrollbar->linesize (), 0); } else if (cmd == core::RIGHT_CMD) { scroll ((int) hscrollbar->linesize (), 0); } else if (cmd == core::TOP_CMD) { scrollTo (scrollX, 0); } else if (cmd == core::BOTTOM_CMD) { scrollTo (scrollX, canvasHeight); /* gets adjusted in scrollTo () */ } } 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