/*******************************************************************************/ /* Copyright (C) 2010 Jonathan Moore Liles */ /* */ /* 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 2 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; see the file COPYING. If not,write to the Free Software */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ /* Scrolling group suitable for containing a single child (a * pack). When the Fl_Packscroller is resized, the child will be resized * too. No scrollbars are displayed, but the widget responds to * FL_MOUSEWHEEL events. */ #pragma once #include #include #include /* FIXME: Optimize scroll */ class Fl_Packscroller : public Fl_Group { int _increment; int _yposition; static const int sbh = 15; /* scroll button height */ public: Fl_Packscroller ( int X, int Y, int W, int H, const char *L = 0 ) : Fl_Group( X, Y, W, H, L ) { _increment = 30; _yposition = 0; // color( FL_WHITE ); } int increment ( void ) const { return _increment; } void increment ( int v ) { _increment = v; } void yposition ( int v ) { if ( ! children() ) return; int Y = v; if ( Y > 0 ) Y = 0; const int H = h(); // - (sbh * 2); Fl_Widget *o = child( 0 ); if ( o->h() > H && Y + o->h() < H ) Y = H - o->h(); else if ( o->h() < H ) Y = 0; if ( _yposition != Y ) { _yposition = Y; damage( FL_DAMAGE_SCROLL ); } } int yposition ( void ) const { if ( children() ) return child( 0 )->y() - (y() + sbh); return 0; } void bbox ( int &X, int &Y, int &W, int &H ) { X = x(); Y = y() + ( sbh * top_sb_visible() ); W = w(); H = h() - ( sbh * ( top_sb_visible() + bottom_sb_visible() ) ); } int top_sb_visible ( void ) { return children() && child(0)->y() != y() ? 1 : 0; } int bottom_sb_visible ( void ) { if ( children() ) { Fl_Widget *o = child( 0 ); if ( o->h() > h() && o->y() + o->h() != y() + h() ) return 1; } return 0; } virtual void draw ( void ) { if ( damage() & FL_DAMAGE_ALL ) { fl_rectf( x(), y(), w(), h(), color() ); } if ( ! children() ) return; Fl_Widget *o = child( 0 ); o->position( x(), y() + _yposition ); const int top_sb = top_sb_visible(); const int bottom_sb = bottom_sb_visible(); fl_push_clip( x(), y() + ( sbh * top_sb ), w(), h() - (sbh * (top_sb + bottom_sb) )); draw_children(); fl_pop_clip(); fl_font( FL_HELVETICA, 12 ); if ( top_sb ) { fl_draw_box( box(), x(), y(), w(), sbh, color() ); fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); fl_draw( "@2<", x(), y(), w(), sbh, FL_ALIGN_CENTER ); } if ( bottom_sb ) { fl_draw_box( box(), x(), y() + h() - sbh, w(), sbh, color() ); fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); fl_draw( "@2>", x(), y() + h() - sbh, w(), sbh, FL_ALIGN_CENTER ); } } virtual int handle ( int m ) { static int _button; int r = 0; switch ( m ) { case FL_PUSH: _button = Fl::event_button(); if ( top_sb_visible() && Fl::event_inside( x(), y(), w(), sbh ) ) { return 1; } else if ( bottom_sb_visible() && Fl::event_inside( x(), y() + h() - sbh, w(), sbh ) ) { return 1; } break; case FL_RELEASE: { int b = _button; _button = 0; if ( b == 1 ) { if ( top_sb_visible() && Fl::event_inside( x(), y(), w(), sbh ) ) { yposition( yposition() + ( h() / 4 ) ); return 1; } else if ( bottom_sb_visible() && Fl::event_inside( x(), y() + h() - sbh, w(), sbh ) ) { yposition( yposition() - (h() / 4 ) ); return 1; } } break; } case FL_KEYBOARD: { if ( Fl::event_key() == FL_Up ) { yposition( yposition() + ( h() / 4 ) ); return 1; } else if ( Fl::event_key() == FL_Down ) { yposition( yposition() - (h() / 4 ) ); return 1; } break; } case FL_MOUSEWHEEL: { yposition( yposition() - ( Fl::event_dy() * _increment ) ); return 1; } } return Fl_Group::handle( m ) | r; } };