Mercurial > dillo_port1.3
view dw/fltkviewport.cc @ 2128:88157bfc5a24
dillorc font suggestions
author | corvid <corvid@lavabit.com> |
---|---|
date | Tue, 12 Jul 2011 23:26:30 +0000 |
parents | eca3cff41427 |
children |
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 <FL/Fl.H> #include <FL/fl_draw.H> #include <FL/names.h> #include <stdio.h> #include "../lout/msg.h" using namespace lout; using namespace lout::object; using namespace lout::container::typed; namespace dw { namespace fltk { /* * Lets SHIFT+{Left,Right} go to the parent */ class CustScrollbar : public Fl_Scrollbar { public: CustScrollbar(int x, int y, int w, int h) : Fl_Scrollbar(x,y,w,h) {}; int handle(int e) { if (e == FL_SHORTCUT && Fl::event_state() == FL_SHIFT && (Fl::event_key() == FL_Left || Fl::event_key() == FL_Right)) return 0; return Fl_Scrollbar::handle(e); } }; FltkViewport::FltkViewport (int X, int Y, int W, int H, const char *label): FltkWidgetView (X, Y, W, H, label) { hscrollbar = new CustScrollbar (x (), y (), 1, 1); hscrollbar->type(FL_HORIZONTAL); hscrollbar->callback (hscrollbarCallback, this); hscrollbar->hide(); add (hscrollbar); vscrollbar = new Fl_Scrollbar (x (), y(), 1, 1); vscrollbar->type(FL_VERTICAL); vscrollbar->callback (vscrollbarCallback, this); vscrollbar->hide(); add (vscrollbar); hasDragScroll = 1; scrollX = scrollY = scrollDX = scrollDY = 0; horScrolling = verScrolling = 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 < Fl_Widget> > (true); } FltkViewport::~FltkViewport () { delete gadgets; } void FltkViewport::adjustScrollbarsAndGadgetsAllocation () { int hdiff = 0, vdiff = 0; int visibility = 0; _MSG(" >>FltkViewport::adjustScrollbarsAndGadgetsAllocation\n"); 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->resize(x (), y () + h () - SCROLLBAR_THICKNESS, w () - hdiff, SCROLLBAR_THICKNESS); vscrollbar->resize(x () + w () - SCROLLBAR_THICKNESS, y (), SCROLLBAR_THICKNESS, h () - vdiff); int X = x () + w () - SCROLLBAR_THICKNESS; int Y = y () + h () - SCROLLBAR_THICKNESS; for (Iterator <TypedPointer < Fl_Widget> > it = gadgets->iterator (); it.hasNext (); ) { Fl_Widget *widget = it.getNext()->getTypedValue (); widget->resize(x (), y (), SCROLLBAR_THICKNESS, 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 (Fl_Widget *vscrollbar,void *viewportPtr) { ((FltkViewport*)viewportPtr)->vscrollbarChanged (); } void FltkViewport::hscrollbarCallback (Fl_Widget *hscrollbar,void *viewportPtr) { ((FltkViewport*)viewportPtr)->hscrollbarChanged (); } // ---------------------------------------------------------------------- void FltkViewport::resize(int X, int Y, int W, int H) { bool dimension_changed = W != w() || H != h(); Fl_Group::resize(X, Y, W, H); if (dimension_changed) { theLayout->viewportSizeChanged (this, W, H); adjustScrollbarsAndGadgetsAllocation (); } } void FltkViewport::draw_area (void *data, int x, int y, int w, int h) { FltkViewport *vp = (FltkViewport*) data; fl_push_clip(x, y, w, h); vp->FltkWidgetView::draw (); for (Iterator <TypedPointer < Fl_Widget> > it = vp->gadgets->iterator(); it.hasNext (); ) { Fl_Widget *widget = it.getNext()->getTypedValue (); vp->draw_child (*widget); } fl_pop_clip(); } void FltkViewport::draw () { int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; int d = damage(); if (d & FL_DAMAGE_SCROLL) { clear_damage (FL_DAMAGE_SCROLL); fl_scroll(x(), y(), w() - hdiff, h() - vdiff, -scrollDX, -scrollDY, draw_area, this); clear_damage (d & ~FL_DAMAGE_SCROLL); } if (d) { draw_area(this, x(), y(), w () - hdiff, h () - vdiff); if (d == FL_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 %s\n", fl_eventnames[event]); switch(event) { case FL_KEYBOARD: /* When the viewport has focus (and not one of its children), FLTK * sends the event here. Returning zero tells FLTK to resend the * event as SHORTCUT, which we finally route to the parent. */ /* As we don't know the exact keybindings set by the user, we ask * for all of them (except Tab to keep form navigation). */ if (Fl::event_key() != FL_Tab) return 0; break; case FL_SHORTCUT: /* send it to the parent (UI) */ return 0; case FL_FOCUS: /** \bug Draw focus box. */ break; case FL_UNFOCUS: /** \bug Undraw focus box. */ break; case FL_PUSH: if (vscrollbar->visible() && Fl::event_inside(vscrollbar)) { if (vscrollbar->handle(event)) verScrolling = 1; } else if (hscrollbar->visible() && Fl::event_inside(hscrollbar)) { if (hscrollbar->handle(event)) horScrolling = 1; } else if (FltkWidgetView::handle(event) == 0 && Fl::event_button() == FL_MIDDLE_MOUSE) { if (!hasDragScroll) { /* let the parent widget handle it... */ return 0; } else { /* receive FL_DRAG and FL_RELEASE */ dragScrolling = 1; dragX = Fl::event_x(); dragY = Fl::event_y(); setCursor (core::style::CURSOR_MOVE); } } return 1; break; case FL_DRAG: if (dragScrolling && Fl::event_button() == FL_MIDDLE_MOUSE) { scroll(dragX - Fl::event_x(), dragY - Fl::event_y()); dragX = Fl::event_x(); dragY = Fl::event_y(); return 1; } else if (verScrolling) { vscrollbar->handle(event); return 1; } else if (horScrolling) { hscrollbar->handle(event); return 1; } break; case FL_MOUSEWHEEL: return (Fl::event_dx() ? hscrollbar : vscrollbar)->handle(event); break; case FL_RELEASE: if (Fl::event_button() == FL_MIDDLE_MOUSE) { dragScrolling = 0; setCursor (core::style::CURSOR_DEFAULT); } else if (verScrolling && vscrollbar->handle(event)) { verScrolling = 0; return 1; } else if (horScrolling && hscrollbar->handle(event)) { horScrolling = 0; return 1; } break; case FL_ENTER: /* could be the result of, e.g., closing another window. */ mouse_x = Fl::event_x(); mouse_y = Fl::event_y(); positionChanged(); break; case FL_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 && dragScrolling == false) (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 (); damage(FL_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, -h () + vscrollbar->linesize ()); } else if (cmd == core::SCREEN_DOWN_CMD) { scroll (0, h () - vscrollbar->linesize ()); } 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) { int adjustReq = (hscrollbar->visible() ? !hScrollbarThickness : hScrollbarThickness) || (vscrollbar->visible() ? !vScrollbarThickness : vScrollbarThickness); _MSG("FltkViewport::setViewportSize old_w,old_h=%dx%d -> w,h=%dx%d\n" "\t hThick=%d hVis=%d, vThick=%d vVis=%d, adjustReq=%d\n", w(),h(),width,height, hScrollbarThickness,hscrollbar->visible(), vScrollbarThickness,vscrollbar->visible(), adjustReq); (hScrollbarThickness > 0) ? hscrollbar->show () : hscrollbar->hide (); (vScrollbarThickness > 0) ? vscrollbar->show () : vscrollbar->hide (); /* If no scrollbar, go to the beginning */ scroll(hScrollbarThickness ? 0 : -scrollX, vScrollbarThickness ? 0 : -scrollY); /* Adjust when scrollbar visibility changes */ if (adjustReq) adjustScrollbarsAndGadgetsAllocation (); } void FltkViewport::updateCanvasWidgets (int dx, int dy) { // scroll all child widgets except scroll bars for (int i = children () - 1; i > 0; i--) { Fl_Widget *widget = child (i); if (widget == hscrollbar || widget == vscrollbar) continue; widget->position(widget->x () - dx, widget->y () - dy); } } int FltkViewport::translateViewXToCanvasX (int X) { return X - x () + scrollX; } int FltkViewport::translateViewYToCanvasY (int Y) { return Y - y () + scrollY; } int FltkViewport::translateCanvasXToViewX (int X) { return X + x () - scrollX; } int FltkViewport::translateCanvasYToViewY (int Y) { return Y + 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 (Fl_Widget *gadget) { /** \bug Reparent? */ gadgets->append (new TypedPointer < Fl_Widget> (gadget)); adjustScrollbarsAndGadgetsAllocation (); } } // namespace fltk } // namespace dw