From 065fae4f87d271b52e43f59923928c14834646ef Mon Sep 17 00:00:00 2001 From: Vedran Ljubovic Date: Mon, 20 Aug 2007 16:53:43 +0000 Subject: [PATCH] Import local copy of Flu_Wrap_Group with a minor change (enable to compile outside FLU) --- efiler/Flu_Wrap_Group.cpp | 412 ++++++++++++++++++++++++++++++++++++++ efiler/Flu_Wrap_Group.h | 196 ++++++++++++++++++ efiler/Jamfile | 2 +- 3 files changed, 609 insertions(+), 1 deletion(-) create mode 100644 efiler/Flu_Wrap_Group.cpp create mode 100644 efiler/Flu_Wrap_Group.h diff --git a/efiler/Flu_Wrap_Group.cpp b/efiler/Flu_Wrap_Group.cpp new file mode 100644 index 0000000..513c563 --- /dev/null +++ b/efiler/Flu_Wrap_Group.cpp @@ -0,0 +1,412 @@ +// $Id: Flu_Wrap_Group.cpp,v 1.8 2004/01/27 21:44:24 jbryan Exp $ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#include "Flu_Wrap_Group.h" +#include +#include + +#define MAX( x, y ) ( (x)>(y) ? (x) : (y) ) + +#define SCROLL_SIZE 15 + +Flu_Wrap_Group :: Scrollbar :: Scrollbar( int x, int y, int w, int h, const char *l ) + : Fl_Scrollbar( x, y, w, h, l ) +{ +} + +int Flu_Wrap_Group :: Scrollbar :: handle( int event ) +{ + if( event == FL_MOUSEWHEEL ) + { + handle_drag( clamp( value() + linesize() * Fl::e_dy ) ); + return 1; + } + else + return Fl_Scrollbar::handle( event ); +} + +Flu_Wrap_Group :: Flu_Wrap_Group( int x, int y, int w, int h, const char *l ) + : Fl_Group( x, y, w, h, l ), scrollbar( x+w-SCROLL_SIZE, y, SCROLL_SIZE, h ), group( x, y, w-SCROLL_SIZE, h ) +{ + offset( 0, 0 ); + spacing( 0, 0 ); + _type = FL_VERTICAL; + scrollTo = NULL; + + Fl_Group::add( &scrollbar ); + scrollbar.callback( _scrollCB, this ); + scrollbar.linesize( 10 ); + scrollbar.range( 0, 100 ); + scrollbar.show(); + + Fl_Group::add( &group ); + Fl_Group::resizable( group ); + Fl_Group::end(); + group.begin(); +} + +void Flu_Wrap_Group :: resize( int x, int y, int w, int h ) +{ + group.resizable( NULL ); + Fl_Group::resize( x, y, w, h ); + if( type() == FL_VERTICAL ) + { + scrollbar.resize( x+w-SCROLL_SIZE-Fl::box_dx(box()), y+Fl::box_dy(box()), SCROLL_SIZE, h-Fl::box_dh(box()) ); + group.resize( x, y, w-SCROLL_SIZE-Fl::box_dx(box()), h ); + } + else + { + scrollbar.resize( x+Fl::box_dx(box()), y+h-SCROLL_SIZE-Fl::box_dy(box()), w-Fl::box_dw(box()), SCROLL_SIZE ); + group.resize( x, y, w, h-SCROLL_SIZE-Fl::box_dh(box()) ); + } + Fl_Group::init_sizes(); + redraw(); +} + +void Flu_Wrap_Group :: scroll_to( const Fl_Widget *w ) +{ + scrollTo = w; + redraw(); +} + +void Flu_Wrap_Group :: scroll_to_beginning() +{ + ((Fl_Valuator*)&scrollbar)->value( scrollbar.minimum() ); +} + +void Flu_Wrap_Group :: scroll_to_end() +{ + ((Fl_Valuator*)&scrollbar)->value( scrollbar.maximum() ); +} + +void Flu_Wrap_Group :: type( int t ) +{ + _type = t; + resize( x(), y(), w(), h() ); +} + +Fl_Widget* Flu_Wrap_Group :: next( Fl_Widget* w ) +{ + for( int i = 0; i < group.children()-1; i++ ) + { + if( w == group.child(i) ) + return group.child(i+1); + } + return NULL; +} + +Fl_Widget* Flu_Wrap_Group :: previous( Fl_Widget* w ) +{ + for( int i = 1; i < group.children(); i++ ) + { + if( w == group.child(i) ) + return group.child(i-1); + } + return NULL; +} + +Fl_Widget* Flu_Wrap_Group :: above( Fl_Widget* w ) +{ + for( int i = 0; i < group.children(); i++ ) + { + if( w == group.child(i) ) + { + int measure[2]; + measure[0] = w->x() + w->w()/2; + measure[1] = w->y() - _spacing[1]; + int index = layout( scrollbar.visible(), false, measure ); + if( index >= 0 ) + return group.child(index); + else + return group.child(0); + } + } + return NULL; +} + +Fl_Widget* Flu_Wrap_Group :: below( Fl_Widget* w ) +{ + for( int i = 0; i < group.children(); i++ ) + { + if( w == group.child(i) ) + { + int measure[2]; + measure[0] = w->x() + w->w()/2; + measure[1] = w->y() + w->h() + _spacing[1]; + int index = layout( scrollbar.visible(), false, measure ); + if( index >= 0 ) + return group.child(index); + else + return group.child(group.children()-1); + } + } + return NULL; +} + +Fl_Widget* Flu_Wrap_Group :: left( Fl_Widget* w ) +{ + for( int i = 0; i < group.children(); i++ ) + { + if( w == group.child(i) ) + { + int measure[2]; + measure[0] = w->x() - _spacing[0]; + measure[1] = w->y() + w->h()/2; + int index = layout( scrollbar.visible(), false, measure ); + if( index >= 0 ) + return group.child(index); + else + return group.child(0); + } + } + return NULL; +} + +Fl_Widget* Flu_Wrap_Group :: right( Fl_Widget* w ) +{ + for( int i = 0; i < group.children(); i++ ) + { + if( w == group.child(i) ) + { + int measure[2]; + measure[0] = w->x() + w->w() + _spacing[0] + 1; + measure[1] = w->y() + w->h()/2; + int index = layout( scrollbar.visible(), false, measure ); + if( index >= 0 ) + return group.child(index); + else + return group.child(group.children()-1); + } + } + return NULL; +} + +int Flu_Wrap_Group :: layout( bool sbVisible, bool doScrollTo, int *measure ) +{ + int xx = x()+Fl::box_dx(box()), yy = y()+Fl::box_dy(box()), + ww = w()-Fl::box_dw(box()), hh = h()-Fl::box_dh(box()); + + if( type() == FL_VERTICAL ) + { + int i, X, Y, maxH, H, col, row, maxW, scrollY; + Fl_Widget *c; + + scrollbar.type( FL_VERTICAL ); + + BEGIN_H: + + X = xx+_offset[0]; + Y = yy+_offset[1] - (sbVisible ? scrollbar.value() : 0); + maxH = _offset[1]; + H = 0; + col = 0; + row = 0; + scrollY = 0; + maxW = xx + ww - (sbVisible ? scrollbar.w() : 0); + + for( i = 0; i < group.children(); i++ ) + { + c = group.child(i); + if( !c->visible() ) + continue; + H = MAX( H, c->h() ); + if( col == 0 ) + maxH += H + _spacing[1]; + if( ( X + c->w() ) > maxW ) + { + Y += H + _spacing[1]; + scrollY += H + _spacing[1]; + if( i == group.children()-1 ) + maxH += H + _spacing[1]; + + if( measure ) + { + if( xx+_offset[0] <= measure[0] && measure[0] <= xx+c->w()+_offset[0]+_spacing[0] && + Y <= measure[1] && measure[1] <= Y+c->h()+_spacing[1] ) + return i; + } + else + c->position( xx+_offset[0], Y ); + + col = 0; + row++; + H = 0; + X = xx+c->w() + _offset[0] + _spacing[0]; + } + else + { + if( measure ) + { + if( X <= measure[0] && measure[0] <= X+c->w()+_spacing[0] && + Y <= measure[1] && measure[1] <= Y+c->h()+_spacing[1] ) + return i; + } + else + c->position( X, Y ); + X += c->w() + _spacing[0]; + col++; + } + + if( doScrollTo && (c == scrollTo) ) + { + if( scrollY > scrollbar.maximum() ) + scrollY = (int)scrollbar.maximum(); + ((Fl_Valuator*)&scrollbar)->value( scrollY ); + scrollTo = NULL; + goto BEGIN_H; + } + + // if we exceed the height and the scrollbar is not visible, + // then it will soon become visible so we don't need to process anymore + if( !measure && !sbVisible && maxH > hh ) + return 1; + } + + if( measure ) + return -1; + else if( maxH > hh ) + { + scrollbar.range( 0, maxH-hh ); + scrollbar.slider_size( MAX( float(scrollbar.h()-(maxH-hh))/float(scrollbar.h()), 0.08f ) ); + return 1; + } + else + return 0; + } + else + { + int i, X, Y, W, maxW, maxH, col, row, scrollX; + Fl_Widget *c; + + scrollbar.type( FL_HORIZONTAL ); + + BEGIN_W: + + X = xx+_offset[0] - (sbVisible ? scrollbar.value() : 0); + Y = yy+_offset[1]; + maxW = _offset[0]; + W = 0; + col = 0; + row = 0; + scrollX = 0; + maxH = yy + hh - (sbVisible ? scrollbar.h() : 0); + + for( i = 0; i < group.children(); i++ ) + { + c = group.child(i); + if( !c->visible() ) + continue; + + W = MAX( W, c->w() ); + + if( row == 0 ) + maxW += W + _spacing[0]; + + if( ( Y + c->h() ) > maxH ) + { + X += W + _spacing[0]; + scrollX += W + _spacing[0]; + if( i == group.children()-1 ) + maxW += W + _spacing[0]; + + if( measure ) + { + if( X <= measure[0] && measure[0] <= X+c->w()+_spacing[0] && + yy+_offset[1] <= measure[1] && measure[1] <= yy+c->h()+_offset[1]+_spacing[1] ) + return i; + } + else + c->position( X, yy+_offset[1] ); + + row = 0; + col++; + W = 0; + Y = yy+c->h() + _offset[1] + _spacing[1]; + } + else + { + if( measure ) + { + if( X <= measure[0] && measure[0] <= X+c->w()+_spacing[0] && + Y <= measure[1] && measure[1] <= Y+c->h()+_spacing[1] ) + return i; + } + else + c->position( X, Y ); + Y += c->h() + _spacing[1]; + row++; + } + + if( doScrollTo && (c == scrollTo) ) + { + if( scrollX > scrollbar.maximum() ) + scrollX = (int)scrollbar.maximum(); + ((Fl_Valuator*)&scrollbar)->value( scrollX ); + scrollTo = NULL; + goto BEGIN_W; + } + + // if we exceed the width and the scrollbar is not visible, + // then it will soon become visible so we don't need to process anymore + if( !measure && !sbVisible && maxW > ww ) + return 1; + } + + if( measure ) + return -1; + else if( maxW > ww ) + { + scrollbar.range( 0, maxW-ww ); + scrollbar.slider_size( MAX( float(scrollbar.w()-(maxW-ww))/float(scrollbar.w()), 0.08f ) ); + return 1; + } + else + return 0; + } +} + +void Flu_Wrap_Group :: draw() +{ + // we first try to fit all children assuming no scrollbar. if they do not all fit, + // we have to turn the scrollbar on and try again + if( layout( false, false ) ) + { + scrollbar.show(); + layout( true, false ); + } + else + scrollbar.hide(); + + // hack to look right when resizing smaller + if( scrollbar.value() > scrollbar.maximum() ) + { + ((Fl_Valuator*)&scrollbar)->value( scrollbar.maximum() ); + layout( scrollbar.visible(), scrollTo!=NULL ); + } + else if( scrollTo ) + layout( scrollbar.visible(), true ); + + scrollTo = NULL; + + if( damage() & ~FL_DAMAGE_CHILD) + { + draw_box(); + draw_label(); + } + fl_push_clip( x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), + w()-Fl::box_dw(box()), h()-Fl::box_dh(box()) ); + draw_children(); + fl_pop_clip(); +} diff --git a/efiler/Flu_Wrap_Group.h b/efiler/Flu_Wrap_Group.h new file mode 100644 index 0000000..d8d0d3f --- /dev/null +++ b/efiler/Flu_Wrap_Group.h @@ -0,0 +1,196 @@ +// $Id: Flu_Wrap_Group.h,v 1.10 2004/01/27 21:44:21 jbryan Exp $ + +/*************************************************************** + * FLU - FLTK Utility Widgets + * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University + * + * This file and its content is protected by a software license. + * You should have received a copy of this license with this file. + * If not, please contact the Ohio Supercomputer Center immediately: + * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212 + * + ***************************************************************/ + + + +#ifndef _FLU_WRAP_GROUP_H +#define _FLU_WRAP_GROUP_H + +/* fltk includes */ +#include +#include +#include +#include + +//#include "FLU/Flu_Enumerations.h" +#define FLU_EXPORT + +//! This class provides an alternative to Fl_Group that automatically arranges the children either left to right and top to bottom (for type() == \c FL_VERTICAL), or top to bottom and left to right (for type() == \c FL_HORIZONTAL), within the available size of the group, with a scrollbar turning on if they don't all fit +/*! This class is a group with a scrollbar and an \b Fl_Group inside (both publicly exposed). The \b Fl_Group + contains the actual child widgets of this group. + + Most of the \b Fl_Group member functions are reimplemented here in a pass-through fashion to the + internal group. This means that casual use of a descendent instance will be almost exactly the same + as for a regular \b Fl_Group, with any additional access provided directly through member \b group. + + The goal of this class is to provide a group that dynamically and evenly distributes its children within + a fixed space, similar to those available in other GUI toolkits. +*/ +class FLU_EXPORT Flu_Wrap_Group : public Fl_Group +{ + + public: + + class Scrollbar : public Fl_Scrollbar + { + public: + Scrollbar( int x, int y, int w, int h, const char *l = 0 ); + int handle( int event ); + }; + + //! Normal FLTK constructor + Flu_Wrap_Group( int x, int y, int w, int h, const char *l = 0 ); + + //! \return the widget that is visibly above \b w in the group, or \c NULL if no such widget exists + Fl_Widget *above( Fl_Widget* w ); + + //! \return the widget that is visibly below \b w in the group, or \c NULL if no such widget exists + Fl_Widget *below( Fl_Widget* w ); + + //! Override of Fl_Group::draw() + void draw(); + + //! \return the widget that is visibly to the left of \b w in the group, or \c NULL if no such widget exists + Fl_Widget *left( Fl_Widget* w ); + + //! \return the widget that is logically after \b w in the groups order, or \c NULL if no such widget exists + Fl_Widget *next( Fl_Widget* w ); + + //! Set the offset for where the first child starts + inline void offset( int x, int y ) + { _offset[0] = x, _offset[1] = y; redraw(); } + + //! \return the x offset for where the first child starts + inline int offset_x() const + { return _offset[0]; } + + //! \return the y offset for where the first child starts + inline int offset_y() const + { return _offset[1]; } + + //! \return the widget that is logically before \b w in the groups order, or \c NULL if no such widget exists + Fl_Widget *previous( Fl_Widget* w ); + + //! Override of Fl_Group::resize() + void resize( int x, int y, int w, int h ); + + //! \return the widget that is visibly to the right of \b w in the group, or \c NULL if no such widget exists + Fl_Widget *right( Fl_Widget* w ); + + //! Scroll the group so that the given widget is shown (usually aligned to the left/top) + void scroll_to( const Fl_Widget *w ); + + //! Scroll the group so that the given widget is shown (usually aligned to the left/top) + inline void scroll_to( const Fl_Widget& w ) + { scroll_to( &w ); } + + //! Scroll the group to the beginning of the list + void scroll_to_beginning(); + + //! Scroll the group to the end of the list + void scroll_to_end(); + + //! Set the spacing between children + inline void spacing( int x, int y ) + { _spacing[0] = x, _spacing[1] = y; redraw(); } + + //! \return the x spacing between children + inline int spacing_x() const + { return _spacing[0]; } + + //! \return the y spacing between children + inline int spacing_y() const + { return _spacing[1]; } + + //! Set the wrap type. Must be either \c FL_VERTICAL (children wrap according to the width, with a vertical scrollbar) or \c FL_HORIZONTAL (children wrap according to the height, with a horizontal scrollbar). Default is \c FL_HORIZONTAL + void type( int t ); + + //! Get the wrap type + inline int type() const + { return _type; } + + /*! \name Pass-through functions for the internal Fl_Group + * These are strictly for convenience. Only the most commonly called functions have been re-implemented. + * You can also explicitly access the group object for more control. + */ + //@{ + + inline Fl_Widget* const* array() const + { return group.array(); } + + inline int find( const Fl_Widget* w ) const + { return group.find( w ); } + + inline int find( const Fl_Widget& w ) const + { return group.find( w ); } + + inline void clear() + { group.clear(); } + + inline Fl_Widget *child(int n) const + { return group.child(n); } + + inline int children() const + { return group.children(); } + + inline void begin() + { group.begin(); } + + inline void end() + { group.end(); Fl_Group::end(); } + + inline void resizable(Fl_Widget *box) + { group.resizable(box); } + + inline void resizable(Fl_Widget &box) + { group.resizable(box); } + + inline Fl_Widget *resizable() const + { return group.resizable(); } + + inline void add( Fl_Widget &w ) + { group.add( w ); } + + inline void add( Fl_Widget *w ) + { group.add( w ); } + + inline void insert( Fl_Widget &w, int n ) + { group.insert( w, n ); } + + inline void insert( Fl_Widget &w, Fl_Widget* beforethis ) + { group.insert( w, beforethis ); } + + inline void remove( Fl_Widget &w ) + { group.remove( w ); } + + inline void add_resizable( Fl_Widget &box ) + { group.add_resizable( box ); } + + //@} + + Scrollbar scrollbar; + Fl_Group group; + + protected: + + inline static void _scrollCB( Fl_Widget*, void *arg ) + { ((Flu_Wrap_Group*)arg)->redraw(); } + + int layout( bool sbVisible, bool doScrollTo, int *measure = 0 ); + + const Fl_Widget *scrollTo; + int _offset[2], _spacing[2], _type; + +}; + +#endif diff --git a/efiler/Jamfile b/efiler/Jamfile index 8ddf9f3..0343ba9 100644 --- a/efiler/Jamfile +++ b/efiler/Jamfile @@ -10,7 +10,7 @@ SubDir TOP efiler ; -SOURCE = Fl_Icon_Browser.cxx EDE_Browser.cpp EDE_DirTree.cpp Util.cpp efiler.cpp fileops.cpp filesystem.cpp ede_ask.cpp ; +SOURCE = Fl_Icon_Browser.cxx EDE_Browser.cpp EDE_DirTree.cpp Util.cpp efiler.cpp fileops.cpp filesystem.cpp ede_ask.cpp Flu_Wrap_Group.cpp; EdeProgram efiler : $(SOURCE) ; #EdeManual doc/efiler.txt : doc/efiler.jpg ;