FLTK 1.3.2
Fl_Table.H
00001 //
00002 // "$Id: Fl_Table.H 9843 2013-03-23 08:14:08Z greg.ercolano $"
00003 //
00004 // Fl_Table -- A table widget
00005 //
00006 // Copyright 2002 by Greg Ercolano.
00007 // Copyright (c) 2004 O'ksi'D
00008 //
00009 // This library is free software. Distribution and use rights are outlined in
00010 // the file "COPYING" which should have been included with this file.  If this
00011 // file is missing or damaged, see the license at:
00012 //
00013 //     http://www.fltk.org/COPYING.php
00014 //
00015 // Please report all bugs and problems on the following page:
00016 //
00017 //     http://www.fltk.org/str.php
00018 //
00019 
00020 #ifndef _FL_TABLE_H
00021 #define _FL_TABLE_H
00022 
00023 #include <sys/types.h>
00024 #include <string.h>             // memcpy
00025 #ifdef WIN32
00026 #include <malloc.h>             // WINDOWS: malloc/realloc
00027 #else /*WIN32*/
00028 #include <stdlib.h>             // UNIX: malloc/realloc
00029 #endif /*WIN32*/
00030 
00031 #include <FL/Fl.H>
00032 #include <FL/Fl_Group.H>
00033 #include <FL/Fl_Scroll.H>
00034 #include <FL/Fl_Box.H>
00035 #include <FL/Fl_Scrollbar.H>
00036 
00170 class FL_EXPORT Fl_Table : public Fl_Group {
00171 public:
00175   enum TableContext {
00176     CONTEXT_NONE       = 0,     
00177     CONTEXT_STARTPAGE  = 0x01,  
00178     CONTEXT_ENDPAGE    = 0x02,  
00179     CONTEXT_ROW_HEADER = 0x04,  
00180     CONTEXT_COL_HEADER = 0x08,  
00181     CONTEXT_CELL       = 0x10,  
00182     CONTEXT_TABLE      = 0x20,  
00183     CONTEXT_RC_RESIZE  = 0x40   
00184   };
00185   
00186 private:
00187   int _rows, _cols;     // total rows/cols
00188   int _row_header_w;    // width of row header
00189   int _col_header_h;    // height of column header
00190   int _row_position;    // last row_position set (not necessarily == toprow!)
00191   int _col_position;    // last col_position set (not necessarily == leftcol!)
00192   
00193   char _row_header;     // row header enabled?
00194   char _col_header;     // col header enabled?
00195   char _row_resize;     // row resizing enabled?
00196   char _col_resize;     // col resizing enabled?
00197   int _row_resize_min;  // row minimum resizing height (default=1)
00198   int _col_resize_min;  // col minimum resizing width (default=1)
00199   
00200   // OPTIMIZATION: partial row/column redraw variables
00201   int _redraw_toprow;
00202   int _redraw_botrow;
00203   int _redraw_leftcol;
00204   int _redraw_rightcol;
00205   Fl_Color _row_header_color;
00206   Fl_Color _col_header_color;
00207   
00208   int _auto_drag;
00209   int _selecting;
00210 #if FLTK_ABI_VERSION >= 10301
00211   int _scrollbar_size;
00212 #endif
00213 #if FLTK_ABI_VERSION >= 10303
00214   enum {
00215     TABCELLNAV = 1<<0,                  
00216   };
00217   unsigned int flags_;
00218 #endif
00219   
00220   // An STL-ish vector without templates
00221   class FL_EXPORT IntVector {
00222     int *arr;
00223     unsigned int _size;
00224     void init() {
00225       arr = NULL;
00226       _size = 0;
00227     }
00228     void copy(int *newarr, unsigned int newsize) {
00229       size(newsize);
00230       memcpy(arr, newarr, newsize * sizeof(int));
00231     }
00232   public:
00233     IntVector() { init(); }                                     // CTOR
00234     ~IntVector() { if ( arr ) free(arr); arr = NULL; }          // DTOR
00235     IntVector(IntVector&o) { init(); copy(o.arr, o._size); }    // COPY CTOR
00236     IntVector& operator=(IntVector&o) {                         // ASSIGN
00237       init();
00238       copy(o.arr, o._size);
00239       return(*this);
00240     }
00241     int operator[](int x) const { return(arr[x]); }
00242     int& operator[](int x) { return(arr[x]); }
00243     unsigned int size() { return(_size); }
00244     void size(unsigned int count) {
00245       if ( count != _size ) {
00246         arr = (int*)realloc(arr, count * sizeof(int));
00247         _size = count;
00248       }
00249     }
00250     int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
00251     void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
00252     int back() { return(arr[_size-1]); }
00253   };
00254   
00255   IntVector _colwidths;                 // column widths in pixels
00256   IntVector _rowheights;                // row heights in pixels
00257   
00258   Fl_Cursor _last_cursor;               // last mouse cursor before changed to 'resize' cursor
00259   
00260   // EVENT CALLBACK DATA
00261   TableContext _callback_context;       // event context
00262   int _callback_row, _callback_col;     // event row/col
00263   
00264   // handle() state variables.
00265   //    Put here instead of local statics in handle(), so more
00266   //    than one Fl_Table can exist without crosstalk between them.
00267   //
00268   int _resizing_col;                    // column being dragged
00269   int _resizing_row;                    // row being dragged
00270   int _dragging_x;                      // starting x position for horiz drag
00271   int _dragging_y;                      // starting y position for vert drag
00272   int _last_row;                        // last row we FL_PUSH'ed
00273   
00274   // Redraw single cell
00275   void _redraw_cell(TableContext context, int R, int C);
00276   
00277   void _start_auto_drag();
00278   void _stop_auto_drag();
00279   void _auto_drag_cb();
00280   static void _auto_drag_cb2(void *d);
00281   
00282 protected:
00283   enum ResizeFlag {
00284     RESIZE_NONE      = 0,
00285     RESIZE_COL_LEFT  = 1,
00286     RESIZE_COL_RIGHT = 2,
00287     RESIZE_ROW_ABOVE = 3,
00288     RESIZE_ROW_BELOW = 4
00289   };
00290   
00291   int table_w, table_h;                         // table's virtual size (in pixels)
00292   int toprow, botrow, leftcol, rightcol;        // four corners of viewable table
00293   
00294   // selection
00295   int current_row, current_col;
00296   int select_row, select_col;
00297   
00298   // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
00299   int toprow_scrollpos;
00300   int leftcol_scrollpos;
00301   
00302   // Dimensions
00303   int tix, tiy, tiw, tih;                       // data table inner dimension xywh
00304   int tox, toy, tow, toh;                       // data table outer dimension xywh
00305   int wix, wiy, wiw, wih;                       // widget inner dimension xywh
00306   
00307   Fl_Scroll *table;                             // container for child fltk widgets (if any)
00308   Fl_Scrollbar *vscrollbar;                     // vertical scrollbar
00309   Fl_Scrollbar *hscrollbar;                     // horizontal scrollbar
00310   
00311   // Fltk
00312   int handle(int e);                            // fltk handle() override
00313   
00314   // Class maintenance
00315   void recalc_dimensions();
00316   void table_resized();                         // table resized; recalc
00317   void table_scrolled();                        // table scrolled; recalc
00318   void get_bounds(TableContext context,         // return x/y/w/h bounds for context
00319                   int &X, int &Y, int &W, int &H);
00320   void change_cursor(Fl_Cursor newcursor);      // change mouse cursor to some other shape
00321   TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
00322   // find r/c given current x/y event
00323   int find_cell(TableContext context,           // find cell's x/y/w/h given r/c
00324                 int R, int C, int &X, int &Y, int &W, int &H);
00325   int row_col_clamp(TableContext context, int &R, int &C);
00326   // clamp r/c to known universe
00327   
00438   virtual void draw_cell(TableContext context, int R=0, int C=0, 
00439                          int X=0, int Y=0, int W=0, int H=0)
00440   { }                                           // overridden by deriving class
00441   
00442   long row_scroll_position(int row);            // find scroll position of row (in pixels)
00443   long col_scroll_position(int col);            // find scroll position of col (in pixels)
00444   
00445   int is_fltk_container() {                     // does table contain fltk widgets?
00446     return( Fl_Group::children() > 3 );         // (ie. more than box and 2 scrollbars?)
00447   }
00448   
00449   static void scroll_cb(Fl_Widget*,void*);      // h/v scrollbar callback
00450   
00451   void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
00452   
00453   void redraw_range(int topRow, int botRow, int leftCol, int rightCol) {
00454     if ( _redraw_toprow == -1 ) {
00455       // Initialize redraw range
00456       _redraw_toprow = topRow;
00457       _redraw_botrow = botRow;
00458       _redraw_leftcol = leftCol;
00459       _redraw_rightcol = rightCol;
00460     } else {
00461       // Extend redraw range
00462       if ( topRow < _redraw_toprow ) _redraw_toprow = topRow;
00463       if ( botRow > _redraw_botrow ) _redraw_botrow = botRow;
00464       if ( leftCol < _redraw_leftcol ) _redraw_leftcol = leftCol;
00465       if ( rightCol > _redraw_rightcol ) _redraw_rightcol = rightCol;
00466     }
00467     
00468     // Indicate partial redraw needed of some cells
00469     damage(FL_DAMAGE_CHILD);
00470   }
00471   
00472 public:
00478   Fl_Table(int X, int Y, int W, int H, const char *l=0);
00479   
00484   ~Fl_Table();
00485   
00491   virtual void clear() { rows(0); cols(0); table->clear(); }
00492   
00493   // \todo: add topline(), middleline(), bottomline()
00494   
00500   inline void table_box(Fl_Boxtype val) {
00501     table->box(val);
00502     table_resized();
00503   }
00504   
00508   inline Fl_Boxtype table_box( void ) {
00509     return(table->box());
00510   }
00511   
00515   virtual void rows(int val);                   // set/get number of rows
00516   
00520   inline int rows() {
00521     return(_rows);
00522   }
00523   
00527   virtual void cols(int val);                   // set/get number of columns
00528   
00532   inline int cols() {
00533     return(_cols);
00534   }
00535   
00564   inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
00565     r1 = toprow;
00566     r2 = botrow;
00567     c1 = leftcol;
00568     c2 = rightcol;
00569   } 
00570   
00575   int is_interactive_resize() {
00576     return(_resizing_row != -1 || _resizing_col != -1);
00577   } 
00578   
00582   inline int row_resize() {
00583     return(_row_resize);
00584   }
00585   
00592   void row_resize(int flag) {                   // enable row resizing
00593     _row_resize = flag;
00594   }
00595   
00599   inline int col_resize() {
00600     return(_col_resize);
00601   }
00608   void col_resize(int flag) {                   // enable col resizing
00609     _col_resize = flag;
00610   }
00611   
00617   inline int col_resize_min() {                 // column minimum resizing width
00618     return(_col_resize_min);
00619   }
00620   
00624   void col_resize_min(int val) {
00625     _col_resize_min = ( val < 1 ) ? 1 : val;
00626   } 
00627   
00631   inline int row_resize_min() {                 // column minimum resizing width
00632     return(_row_resize_min);
00633   }
00634   
00640   void row_resize_min(int val) {
00641     _row_resize_min = ( val < 1 ) ? 1 : val;
00642   }
00643   
00647   inline int row_header() {                     // set/get row header enable flag
00648     return(_row_header);
00649   }
00650   
00655   void row_header(int flag) {
00656     _row_header = flag;
00657     table_resized();
00658     redraw();
00659   }
00660   
00664   inline int col_header() {                     // set/get col header enable flag
00665     return(_col_header);
00666   }
00667   
00672   void col_header(int flag) {
00673     _col_header = flag;
00674     table_resized();
00675     redraw();
00676   }
00677   
00681   inline void col_header_height(int height) {   // set/get col header height
00682     _col_header_h = height;
00683     table_resized();
00684     redraw();
00685   }
00686   
00690   inline int col_header_height() {
00691     return(_col_header_h);
00692   }
00693   
00697   inline void row_header_width(int width) {     // set/get row header width
00698     _row_header_w = width;
00699     table_resized();
00700     redraw();
00701   }
00702   
00706   inline int row_header_width() {
00707     return(_row_header_w);
00708   }
00709   
00713   inline void row_header_color(Fl_Color val) {  // set/get row header color
00714     _row_header_color = val;
00715     redraw();
00716   }
00717   
00721   inline Fl_Color row_header_color() {
00722     return(_row_header_color);
00723   } 
00724   
00728   inline void col_header_color(Fl_Color val) {  // set/get col header color
00729     _col_header_color = val;
00730     redraw();
00731   }
00732   
00736   inline Fl_Color col_header_color() {
00737     return(_col_header_color);
00738   }
00739   
00746   void row_height(int row, int height);         // set/get row height
00747   
00751   inline int row_height(int row) {
00752     return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]);
00753   }
00754   
00760   void col_width(int col, int width);           // set/get a column's width
00761   
00765   inline int col_width(int col) {
00766     return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]);
00767   }
00768   
00773   void row_height_all(int height) {             // set all row/col heights
00774     for ( int r=0; r<rows(); r++ ) {
00775       row_height(r, height);
00776     }
00777   }
00778   
00783   void col_width_all(int width) {
00784     for ( int c=0; c<cols(); c++ ) {
00785       col_width(c, width);
00786     }
00787   }
00788   
00792   void row_position(int row);                   // set/get table's current scroll position
00793   
00797   void col_position(int col);
00798   
00802   int row_position() {                          // current row position
00803     return(_row_position);
00804   }
00805   
00809   int col_position() {                          // current col position
00810     return(_col_position);
00811   }
00812   
00818   inline void top_row(int row) {                // set/get top row (deprecated)
00819     row_position(row);
00820   }
00821   
00826   inline int top_row() {
00827     return(row_position());
00828   }
00829   int is_selected(int r, int c);                // selected cell
00830   void get_selection(int &row_top, int &col_left, int &row_bot, int &col_right);
00831   void set_selection(int row_top, int col_left, int row_bot, int col_right);
00832   int move_cursor(int R, int C, int shiftselect);
00833   int move_cursor(int R, int C);
00834   
00838   void resize(int X, int Y, int W, int H);      // fltk resize() override
00839   void draw(void);                              // fltk draw() override
00840   
00841   // This crashes sortapp() during init.
00842   //  void box(Fl_Boxtype val) {
00843   //    Fl_Group::box(val);
00844   //    if ( table ) {
00845   //      resize(x(), y(), w(), h());
00846   //    }
00847   //  }
00848   //  Fl_Boxtype box(void) const {
00849   //    return(Fl_Group::box());
00850   //  }
00851   
00852   // Child group
00853   void init_sizes() {
00854     table->init_sizes();
00855     table->redraw();
00856   }
00857   void add(Fl_Widget& wgt) {
00858     table->add(wgt);
00859     if ( table->children() > 2 ) {
00860       table->show();
00861     } else {
00862       table->hide();
00863     } 
00864   }
00865   void add(Fl_Widget* wgt) {
00866     add(*wgt);
00867   }
00868   void insert(Fl_Widget& wgt, int n) {
00869     table->insert(wgt,n);
00870   }
00871   void insert(Fl_Widget& wgt, Fl_Widget* w2) {
00872     table->insert(wgt,w2);
00873   }
00874   void remove(Fl_Widget& wgt) {
00875     table->remove(wgt);
00876   }
00877   void begin() {
00878     table->begin();
00879   }
00880   void end() {
00881     table->end();
00882     // HACK: Avoid showing Fl_Scroll; seems to erase screen
00883     //       causing unnecessary flicker, even if its box() is FL_NO_BOX.
00884     //
00885     if ( table->children() > 2 ) {
00886       table->show();
00887     } else {
00888       table->hide();
00889     } 
00890     Fl_Group::current(Fl_Group::parent());
00891   }
00892   Fl_Widget * const *array() {
00893     return(table->array());
00894   }
00895   
00910   Fl_Widget *child(int n) const {
00911     return(table->child(n));
00912   }
00913   
00922   int children() const {
00923     return(table->children()-2);    // -2: skip Fl_Scroll's h/v scrollbar widgets
00924   }
00925   int find(const Fl_Widget *wgt) const {
00926     return(table->find(wgt));
00927   }
00928   int find(const Fl_Widget &wgt) const {
00929     return(table->find(wgt));
00930   } 
00931   // CALLBACKS
00932   
00938   int callback_row() {
00939     return(_callback_row);
00940   }
00941   
00947   int callback_col() {
00948     return(_callback_col);
00949   }
00950   
00956   TableContext callback_context() {
00957     return(_callback_context);
00958   }
00959   
00960   void do_callback(TableContext context, int row, int col) {
00961     _callback_context = context;
00962     _callback_row = row;
00963     _callback_col = col;
00964     Fl_Widget::do_callback();
00965   }
00966   
00967 #if FL_DOXYGEN
00968 
00996   void when(Fl_When flags);
00997 #endif
00998   
00999 #if FL_DOXYGEN
01000 
01077   void callback(Fl_Widget*, void*);
01078 #endif
01079 
01080 #if FLTK_ABI_VERSION >= 10301
01081   // NEW
01091   int scrollbar_size() const {
01092       return(_scrollbar_size);
01093   }
01112   void scrollbar_size(int newSize) {
01113       if ( newSize != _scrollbar_size ) redraw();
01114       _scrollbar_size = newSize;
01115   }   
01116 #endif
01117 #if FLTK_ABI_VERSION >= 10303
01118 
01131   void tab_cell_nav(int val) {
01132     if ( val ) flags_ |=  TABCELLNAV;
01133     else       flags_ &= ~TABCELLNAV;
01134   }
01135 
01143   int tab_cell_nav() const {
01144     return(flags_ & TABCELLNAV ? 1 : 0);
01145   }
01146 #endif
01147 };
01148 
01149 #endif /*_FL_TABLE_H*/
01150 
01151 //
01152 // End of "$Id: Fl_Table.H 9843 2013-03-23 08:14:08Z greg.ercolano $".
01153 //