include/gui/widgets/Fl_Table/Fl_Table.H

Go to the documentation of this file.
00001 //
00002 // Fl_Table -- A table widget
00003 //
00004 // Copyright 2002 by Greg Ercolano.
00005 // Copyright (c) 2004 O'ksi'D
00006 //
00007 // This library is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Library General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 2 of the License, or (at your option) any later version.
00011 //
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 // Library General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Library General Public
00018 // License along with this library; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020 // USA.
00021 //
00022 // Please report all bugs and problems to "erco at seriss dot com".
00023 //
00024 // TODO:
00025 //    o Auto scroll during dragged selection
00026 //    o Keyboard navigation (up/down/left/right arrow)
00027 //
00028 
00029 #ifndef _FL_TABLE_H
00030 #define _FL_TABLE_H
00031 
00032 #include <corelib/ncbistd.hpp>
00033 #include <gui/gui_export.h>
00034 
00035 #include <sys/types.h>
00036 #include <string.h>     // memcpy
00037 #ifdef _WIN32
00038 #include <malloc.h>     // WINDOWS: malloc/realloc
00039 #else /*_WIN32*/
00040 #include <stdlib.h>     // UNIX: malloc/realloc
00041 #endif /*_WIN32*/
00042 
00043 #include <FL/Fl.H>
00044 #include <FL/Fl_Group.H>
00045 #include <FL/Fl_Scroll.H>
00046 #include <FL/Fl_Box.H>
00047 #include <FL/Fl_Scrollbar.H>
00048 
00049 class  Fl_Table : public Fl_Group
00050 {
00051 public:
00052     enum TableContext
00053     {
00054     CONTEXT_NONE       = 0,
00055     CONTEXT_STARTPAGE  = 0x01,  // before a page is redrawn
00056     CONTEXT_ENDPAGE    = 0x02,  // after a page is redrawn
00057     CONTEXT_ROW_HEADER = 0x04,  // in the row header
00058     CONTEXT_COL_HEADER = 0x08,  // in the col header
00059     CONTEXT_CELL       = 0x10,  // in one of the cells
00060     CONTEXT_TABLE      = 0x20,  // in the table
00061     CONTEXT_RC_RESIZE  = 0x40   // column or row being resized
00062     };
00063 
00064 private:
00065     int _rows, _cols,       // total rows/cols
00066     _row_header_w,      // width of row header
00067     _col_header_h,      // height of column header
00068     _row_position,      // last row_position set (not necessarily == toprow!)
00069     _col_position;      // last col_position set (not necessarily == leftcol!)
00070 
00071     char _row_header,       // row header enabled?
00072          _col_header,       // col header enabled?
00073      _row_resize,       // row resizing enabled?
00074      _col_resize;       // col resizing enabled?
00075     int
00076      _row_resize_min,   // row minimum resizing height (default=1)
00077      _col_resize_min;   // col minimum resizing width (default=1)
00078 
00079     // OPTIMIZATION: partial row/column redraw variables
00080     int _redraw_toprow, _redraw_botrow,
00081         _redraw_leftcol, _redraw_rightcol;
00082 
00083     Fl_Color _row_header_color,
00084              _col_header_color;
00085 
00086     int _auto_drag;
00087     int _selecting;
00088 
00089     // An STL-ish vector without templates
00090     class IntVector
00091     {
00092         int *arr;
00093     unsigned int _size;
00094     void init()
00095         { arr = NULL; _size = 0; }
00096     void copy(int *newarr, unsigned int newsize)
00097         { size(newsize); memcpy(arr, newarr, newsize * sizeof(int)); }
00098     public:
00099         IntVector() { init(); }                     // CTOR
00100     ~IntVector() { if ( arr ) free(arr); arr = NULL; }      // DTOR
00101     IntVector(IntVector&o) { init(); copy(o.arr, o._size); }    // COPY CTOR
00102     IntVector& operator=(IntVector&o)               // ASSIGN
00103         { init(); copy(o.arr, o._size); return(*this); }
00104     int operator[](int x) const { return(arr[x]); }
00105     int& operator[](int x) { return(arr[x]); }
00106     unsigned int size() { return(_size); }
00107     void size(unsigned int count)
00108     {
00109         if ( count != _size )
00110         { arr = (int*)realloc(arr, count * sizeof(int)); _size = count; }
00111     }
00112     int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
00113     void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
00114     int back() { return(arr[_size-1]); }
00115     };
00116 
00117     IntVector
00118         _colwidths,     // column widths in pixels
00119         _rowheights;        // row heights in pixels
00120 
00121     Fl_Cursor _last_cursor; // last mouse cursor before changed to 'resize' cursor
00122 
00123     // EVENT CALLBACK DATA
00124     TableContext _callback_context; // event context
00125     int _callback_row, _callback_col;   // event row/col
00126 
00127     // handle() state variables.
00128     //    Put here instead of local statics in handle(), so more
00129     //    than one Fl_Table can exist without crosstalk between them.
00130     //
00131     int _resizing_col,          // column being dragged
00132     _resizing_row,          // row being dragged
00133     _dragging_x,            // starting x position for horiz drag
00134     _dragging_y,            // starting y position for vert drag
00135     _last_row;          // last row we FL_PUSH'ed
00136 
00137     // Redraw single cell
00138     void _redraw_cell(TableContext context, int R, int C);
00139 
00140     void _start_auto_drag();
00141     void _stop_auto_drag();
00142     void _auto_drag_cb();
00143     static void _auto_drag_cb2(void *d);
00144 
00145 
00146 protected:
00147     enum ResizeFlag
00148     {
00149         RESIZE_NONE      = 0,
00150         RESIZE_COL_LEFT  = 1,
00151         RESIZE_COL_RIGHT = 2,
00152         RESIZE_ROW_ABOVE = 3,
00153         RESIZE_ROW_BELOW = 4
00154     };
00155 
00156     int table_w, table_h;           // table's virtual size (in pixels)
00157     int toprow, botrow,             // four corners of viewable table
00158     leftcol, rightcol;
00159 
00160     // selection
00161     int current_row, current_col;
00162     int select_row, select_col;
00163 
00164     // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
00165     int toprow_scrollpos,
00166         leftcol_scrollpos;
00167 
00168     // Dimensions
00169     int tix, tiy, tiw, tih,         // data table inner dimension xywh
00170         tox, toy, tow, toh,         // data table outer dimension xywh
00171     wix, wiy, wiw, wih;         // widget inner dimension xywh
00172 
00173     Fl_Scroll *table;               // container for child fltk widgets (if any)
00174     Fl_Scrollbar *vscrollbar,           // vertical scrollbar
00175                  *hscrollbar;           // horizontal scrollbar
00176 
00177     // Fltk
00178     int handle(int e);              // fltk handle() override
00179 
00180     // Class maintenance
00181     void recalc_dimensions();
00182     void table_resized();           // table resized; recalc
00183     void table_scrolled();          // table scrolled; recalc
00184     void get_bounds(TableContext context,   // return x/y/w/h bounds for context
00185                     int &X, int &Y, int &W, int &H);
00186     void change_cursor(Fl_Cursor newcursor);    // change mouse cursor to some other shape
00187     TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
00188                         // find r/c given current x/y event
00189     int find_cell(TableContext context,     // find cell's x/y/w/h given r/c
00190              int R, int C, int &X, int &Y, int &W, int &H);
00191     int row_col_clamp(TableContext context, int &R, int &C);
00192                             // clamp r/c to known universe
00193 
00194     // Called to draw cells
00195     virtual void draw_cell(TableContext context, int R=0, int C=0,
00196                    int X=0, int Y=0, int W=0, int H=0)
00197     { }                 // overridden by deriving class
00198 
00199     long row_scroll_position(int row);      // find scroll position of row (in pixels)
00200     long col_scroll_position(int col);      // find scroll position of col (in pixels)
00201 
00202     int is_fltk_container()             // does table contain fltk widgets?
00203         { return( Fl_Group::children() > 3 ); } // (ie. more than box and 2 scrollbars?)
00204 
00205     static void scroll_cb(Fl_Widget*,void*);    // h/v scrollbar callback
00206 
00207     void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
00208 
00209     void redraw_range(int toprow, int botrow, int leftcol, int rightcol)
00210     {
00211         if ( _redraw_toprow == -1 )
00212     {
00213         // Initialize redraw range
00214         _redraw_toprow = toprow;
00215         _redraw_botrow = botrow;
00216         _redraw_leftcol = leftcol;
00217         _redraw_rightcol = rightcol;
00218     }
00219     else
00220     {
00221         // Extend redraw range
00222         if ( toprow < _redraw_toprow ) _redraw_toprow = toprow;
00223         if ( botrow > _redraw_botrow ) _redraw_botrow = botrow;
00224         if ( leftcol < _redraw_leftcol ) _redraw_leftcol = leftcol;
00225         if ( rightcol > _redraw_rightcol ) _redraw_rightcol = rightcol;
00226     }
00227 
00228     // Indicate partial redraw needed of some cells
00229     damage(FL_DAMAGE_CHILD);
00230     }
00231 
00232 public:
00233     Fl_Table(int X, int Y, int W, int H, const char *l=0);
00234     ~Fl_Table();
00235 
00236     virtual void clear() { rows(0); cols(0); }
00237 
00238     // topline()
00239     // middleline()
00240     // bottomline()
00241 
00242     inline void table_box(Fl_Boxtype val) { table->box(val); table_resized(); }
00243     inline Fl_Boxtype table_box( void ) { return(table->box()); }
00244 
00245     virtual void rows(int val);             // set/get number of rows
00246     inline int rows() const
00247         { return(_rows); }
00248 
00249     virtual void cols(int val);             // set/get number of columns
00250     inline int cols() const
00251         { return(_cols); }
00252 
00253     inline void visible_cells(int& r1, int& r2, int& c1, int& c2)
00254         { r1 = toprow; r2 = botrow; c1 = leftcol; c2 = rightcol; }
00255 
00256     // Interactive resizing happening?
00257     int is_interactive_resize()
00258         { return(_resizing_row != -1 || _resizing_col != -1); }
00259 
00260     inline int row_resize()
00261         { return(_row_resize); }
00262     void row_resize(int flag)           // enable row resizing
00263         { _row_resize = flag; }
00264 
00265     inline int col_resize()
00266         { return(_col_resize); }
00267     void col_resize(int flag)           // enable col resizing
00268         { _col_resize = flag; }
00269 
00270     inline int col_resize_min()         // column minimum resizing width
00271         { return(_col_resize_min); }
00272     void col_resize_min(int val)
00273         { _col_resize_min = ( val < 1 ) ? 1 : val; }
00274 
00275     inline int row_resize_min()         // column minimum resizing width
00276         { return(_row_resize_min); }
00277     void row_resize_min(int val)
00278         { _row_resize_min = ( val < 1 ) ? 1 : val; }
00279 
00280     inline int row_header()         // set/get row header enable flag
00281         { return(_row_header); }
00282     void row_header(int flag)
00283         { _row_header = flag; table_resized(); redraw(); }
00284 
00285     inline int col_header()         // set/get col header enable flag
00286         { return(_col_header); }
00287     void col_header(int flag)
00288         { _col_header = flag; table_resized(); redraw(); }
00289 
00290     inline void col_header_height(int height)   // set/get col header height
00291         { _col_header_h = height; table_resized(); redraw(); }
00292     inline int col_header_height()
00293         { return(_col_header_h); }
00294 
00295     inline void row_header_width(int width) // set/get row header width
00296         { _row_header_w = width; table_resized(); redraw(); }
00297     inline int row_header_width()
00298         { return(_row_header_w); }
00299 
00300     inline void row_header_color(Fl_Color val)  // set/get row header color
00301         { _row_header_color = val; redraw(); }
00302     inline Fl_Color row_header_color()
00303         { return(_row_header_color); }
00304 
00305     inline void col_header_color(Fl_Color val)  // set/get col header color
00306         { _col_header_color = val; redraw(); }
00307     inline Fl_Color col_header_color()
00308         { return(_col_header_color); }
00309 
00310     void row_height(const int* row_ht_arr, int size, int start = 0);
00311     void row_height(int row, int height);   // set/get row height
00312     inline int row_height(int row)
00313     { return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]); }
00314 
00315     void col_width(int col, int width);     // set/get a column's width
00316     inline int col_width(int col)
00317     { return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]); }
00318 
00319     void row_height_all(int height)     // set all row/col heights
00320         { for ( int r=0; r<rows(); r++ ) row_height(r, height); }
00321     void col_width_all(int width)
00322         { for ( int c=0; c<cols(); c++ ) col_width(c, width); }
00323 
00324     void row_position(int row);         // set/get table's current scroll position
00325     void col_position(int col);
00326     int row_position()              // current row position
00327     { return(_row_position); }
00328     int col_position()              // current col position
00329     { return(_col_position); }
00330 
00331     inline void top_row(int row)        // set/get top row (deprecated)
00332         { row_position(row); }
00333     inline int top_row()
00334         { return(row_position()); }
00335 
00336     int is_selected(int r, int c);             // selected cell
00337     void get_selection(int& s_top, int& s_left, int& s_bottom, int& s_right);
00338     void set_selection(int s_top, int s_left, int s_bottom, int s_right);
00339     int move_cursor(int R, int C);
00340 
00341     void resize(int X, int Y, int W, int H);    // fltk resize() override
00342     void draw(void);                // fltk draw() override
00343 
00344     // Child group
00345     void init_sizes() { table->init_sizes(); table->redraw(); }
00346     void add(Fl_Widget& w) { table->add(w); }
00347     void add(Fl_Widget* w) { table->add(w); }
00348     void insert(Fl_Widget& w, int n) { table->insert(w,n); }
00349     void insert(Fl_Widget& w, Fl_Widget* w2) { table->insert(w,w2); }
00350     void remove(Fl_Widget& w) { table->remove(w); }
00351     void begin() { table->begin(); }
00352     void end()
00353     {
00354         table->end();
00355 
00356     // HACK: Avoid showing Fl_Scroll; seems to erase screen
00357     //       causing unnecessary flicker, even if its box() is FL_NO_BOX.
00358     //
00359     if ( table->children() > 2 ) { table->show(); }
00360     else { table->hide(); }
00361 
00362     Fl_Group::current((Fl_Group*)(Fl_Group::parent()));
00363     }
00364     Fl_Widget * const *array()
00365         { return(table->array()); }
00366     Fl_Widget *child(int n) const
00367         { return(table->child(n)); }
00368     int children() const
00369         { return(table->children()-2); }    // -2: skip Fl_Scroll's h/v scrollbar widgets
00370     int find(const Fl_Widget *w) const
00371         { return(table->find(w)); }
00372     int find(const Fl_Widget &w) const
00373         { return(table->find(w)); }
00374 
00375     // CALLBACKS
00376     int callback_row() { return(_callback_row); }
00377     int callback_col() { return(_callback_col); }
00378     TableContext callback_context() { return(_callback_context); }
00379     void do_callback(TableContext context, int row, int col)
00380     {
00381     _callback_context = context;
00382     _callback_row = row;
00383     _callback_col = col;
00384     Fl_Widget::do_callback();
00385     }
00386 };
00387 
00388 
00389 #endif /*_FL_TABLE_H*/
00390 
00391 

Generated on Sun Feb 8 21:34:38 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Feb 09 14:46:54 2009 by modify_doxy.py rev. 117643