FLTK 1.3.2

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List
- File Members

Fl_Table.H

    00001 //
    00002 // "$Id: Fl_Table.H 9731 2012-11-23 20:07:22Z 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
    00214   // An STL-ish vector without templates
    00215   class FL_EXPORT IntVector {
    00216     int *arr;
    00217     unsigned int _size;
    00218     void init() {
    00219       arr = NULL;
    00220       _size = 0;
    00221     }
    00222     void copy(int *newarr, unsigned int newsize) {
    00223       size(newsize);
    00224       memcpy(arr, newarr, newsize * sizeof(int));
    00225     }
    00226   public:
    00227     IntVector() { init(); }                                     // CTOR
    00228     ~IntVector() { if ( arr ) free(arr); arr = NULL; }          // DTOR
    00229     IntVector(IntVector&o) { init(); copy(o.arr, o._size); }    // COPY CTOR
    00230     IntVector& operator=(IntVector&o) {                         // ASSIGN
    00231       init();
    00232       copy(o.arr, o._size);
    00233       return(*this);
    00234     }
    00235     int operator[](int x) const { return(arr[x]); }
    00236     int& operator[](int x) { return(arr[x]); }
    00237     unsigned int size() { return(_size); }
    00238     void size(unsigned int count) {
    00239       if ( count != _size ) {
    00240         arr = (int*)realloc(arr, count * sizeof(int));
    00241         _size = count;
    00242       }
    00243     }
    00244     int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
    00245     void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
    00246     int back() { return(arr[_size-1]); }
    00247   };
    00248
    00249   IntVector _colwidths;                 // column widths in pixels
    00250   IntVector _rowheights;                // row heights in pixels
    00251
    00252   Fl_Cursor _last_cursor;               // last mouse cursor before changed to 'resize' cursor
    00253
    00254   // EVENT CALLBACK DATA
    00255   TableContext _callback_context;       // event context
    00256   int _callback_row, _callback_col;     // event row/col
    00257
    00258   // handle() state variables.
    00259   //    Put here instead of local statics in handle(), so more
    00260   //    than one Fl_Table can exist without crosstalk between them.
    00261   //
    00262   int _resizing_col;                    // column being dragged
    00263   int _resizing_row;                    // row being dragged
    00264   int _dragging_x;                      // starting x position for horiz drag
    00265   int _dragging_y;                      // starting y position for vert drag
    00266   int _last_row;                        // last row we FL_PUSH'ed
    00267
    00268   // Redraw single cell
    00269   void _redraw_cell(TableContext context, int R, int C);
    00270
    00271   void _start_auto_drag();
    00272   void _stop_auto_drag();
    00273   void _auto_drag_cb();
    00274   static void _auto_drag_cb2(void *d);
    00275
    00276 protected:
    00277   enum ResizeFlag {
    00278     RESIZE_NONE      = 0,
    00279     RESIZE_COL_LEFT  = 1,
    00280     RESIZE_COL_RIGHT = 2,
    00281     RESIZE_ROW_ABOVE = 3,
    00282     RESIZE_ROW_BELOW = 4
    00283   };
    00284
    00285   int table_w, table_h;                         // table's virtual size (in pixels)
    00286   int toprow, botrow, leftcol, rightcol;        // four corners of viewable table
    00287
    00288   // selection
    00289   int current_row, current_col;
    00290   int select_row, select_col;
    00291
    00292   // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
    00293   int toprow_scrollpos;
    00294   int leftcol_scrollpos;
    00295
    00296   // Dimensions
    00297   int tix, tiy, tiw, tih;                       // data table inner dimension xywh
    00298   int tox, toy, tow, toh;                       // data table outer dimension xywh
    00299   int wix, wiy, wiw, wih;                       // widget inner dimension xywh
    00300
    00301   Fl_Scroll *table;                             // container for child fltk widgets (if any)
    00302   Fl_Scrollbar *vscrollbar;                     // vertical scrollbar
    00303   Fl_Scrollbar *hscrollbar;                     // horizontal scrollbar
    00304
    00305   // Fltk
    00306   int handle(int e);                            // fltk handle() override
    00307
    00308   // Class maintenance
    00309   void recalc_dimensions();
    00310   void table_resized();                         // table resized; recalc
    00311   void table_scrolled();                        // table scrolled; recalc
    00312   void get_bounds(TableContext context,         // return x/y/w/h bounds for context
    00313                   int &X, int &Y, int &W, int &H);
    00314   void change_cursor(Fl_Cursor newcursor);      // change mouse cursor to some other shape
    00315   TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
    00316   // find r/c given current x/y event
    00317   int find_cell(TableContext context,           // find cell's x/y/w/h given r/c
    00318                 int R, int C, int &X, int &Y, int &W, int &H);
    00319   int row_col_clamp(TableContext context, int &R, int &C);
    00320   // clamp r/c to known universe
    00321
    00432   virtual void draw_cell(TableContext context, int R=0, int C=0,
    00433                          int X=0, int Y=0, int W=0, int H=0)
    00434   { }                                           // overridden by deriving class
    00435
    00436   long row_scroll_position(int row);            // find scroll position of row (in pixels)
    00437   long col_scroll_position(int col);            // find scroll position of col (in pixels)
    00438
    00439   int is_fltk_container() {                     // does table contain fltk widgets?
    00440     return( Fl_Group::children() > 3 );         // (ie. more than box and 2 scrollbars?)
    00441   }
    00442
    00443   static void scroll_cb(Fl_Widget*,void*);      // h/v scrollbar callback
    00444
    00445   void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
    00446
    00447   void redraw_range(int topRow, int botRow, int leftCol, int rightCol) {
    00448     if ( _redraw_toprow == -1 ) {
    00449       // Initialize redraw range
    00450       _redraw_toprow = topRow;
    00451       _redraw_botrow = botRow;
    00452       _redraw_leftcol = leftCol;
    00453       _redraw_rightcol = rightCol;
    00454     } else {
    00455       // Extend redraw range
    00456       if ( topRow < _redraw_toprow ) _redraw_toprow = topRow;
    00457       if ( botRow > _redraw_botrow ) _redraw_botrow = botRow;
    00458       if ( leftCol < _redraw_leftcol ) _redraw_leftcol = leftCol;
    00459       if ( rightCol > _redraw_rightcol ) _redraw_rightcol = rightCol;
    00460     }
    00461
    00462     // Indicate partial redraw needed of some cells
    00463     damage(FL_DAMAGE_CHILD);
    00464   }
    00465
    00466 public:
    00472   Fl_Table(int X, int Y, int W, int H, const char *l=0);
    00473
    00478   ~Fl_Table();
    00479
    00485   virtual void clear() { rows(0); cols(0); table->clear(); }
    00486
    00487   // \todo: add topline(), middleline(), bottomline()
    00488
    00494   inline void table_box(Fl_Boxtype val) {
    00495     table->box(val);
    00496     table_resized();
    00497   }
    00498
    00502   inline Fl_Boxtype table_box( void ) {
    00503     return(table->box());
    00504   }
    00505
    00509   virtual void rows(int val);                   // set/get number of rows
    00510
    00514   inline int rows() {
    00515     return(_rows);
    00516   }
    00517
    00521   virtual void cols(int val);                   // set/get number of columns
    00522
    00526   inline int cols() {
    00527     return(_cols);
    00528   }
    00529
    00558   inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
    00559     r1 = toprow;
    00560     r2 = botrow;
    00561     c1 = leftcol;
    00562     c2 = rightcol;
    00563   }
    00564
    00569   int is_interactive_resize() {
    00570     return(_resizing_row != -1 || _resizing_col != -1);
    00571   }
    00572
    00576   inline int row_resize() {
    00577     return(_row_resize);
    00578   }
    00579
    00586   void row_resize(int flag) {                   // enable row resizing
    00587     _row_resize = flag;
    00588   }
    00589
    00593   inline int col_resize() {
    00594     return(_col_resize);
    00595   }
    00602   void col_resize(int flag) {                   // enable col resizing
    00603     _col_resize = flag;
    00604   }
    00605
    00611   inline int col_resize_min() {                 // column minimum resizing width
    00612     return(_col_resize_min);
    00613   }
    00614
    00618   void col_resize_min(int val) {
    00619     _col_resize_min = ( val < 1 ) ? 1 : val;
    00620   }
    00621
    00625   inline int row_resize_min() {                 // column minimum resizing width
    00626     return(_row_resize_min);
    00627   }
    00628
    00634   void row_resize_min(int val) {
    00635     _row_resize_min = ( val < 1 ) ? 1 : val;
    00636   }
    00637
    00641   inline int row_header() {                     // set/get row header enable flag
    00642     return(_row_header);
    00643   }
    00644
    00649   void row_header(int flag) {
    00650     _row_header = flag;
    00651     table_resized();
    00652     redraw();
    00653   }
    00654
    00658   inline int col_header() {                     // set/get col header enable flag
    00659     return(_col_header);
    00660   }
    00661
    00666   void col_header(int flag) {
    00667     _col_header = flag;
    00668     table_resized();
    00669     redraw();
    00670   }
    00671
    00675   inline void col_header_height(int height) {   // set/get col header height
    00676     _col_header_h = height;
    00677     table_resized();
    00678     redraw();
    00679   }
    00680
    00684   inline int col_header_height() {
    00685     return(_col_header_h);
    00686   }
    00687
    00691   inline void row_header_width(int width) {     // set/get row header width
    00692     _row_header_w = width;
    00693     table_resized();
    00694     redraw();
    00695   }
    00696
    00700   inline int row_header_width() {
    00701     return(_row_header_w);
    00702   }
    00703
    00707   inline void row_header_color(Fl_Color val) {  // set/get row header color
    00708     _row_header_color = val;
    00709     redraw();
    00710   }
    00711
    00715   inline Fl_Color row_header_color() {
    00716     return(_row_header_color);
    00717   }
    00718
    00722   inline void col_header_color(Fl_Color val) {  // set/get col header color
    00723     _col_header_color = val;
    00724     redraw();
    00725   }
    00726
    00730   inline Fl_Color col_header_color() {
    00731     return(_col_header_color);
    00732   }
    00733
    00740   void row_height(int row, int height);         // set/get row height
    00741
    00745   inline int row_height(int row) {
    00746     return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]);
    00747   }
    00748
    00754   void col_width(int col, int width);           // set/get a column's width
    00755
    00759   inline int col_width(int col) {
    00760     return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]);
    00761   }
    00762
    00767   void row_height_all(int height) {             // set all row/col heights
    00768     for ( int r=0; r<rows(); r++ ) {
    00769       row_height(r, height);
    00770     }
    00771   }
    00772
    00777   void col_width_all(int width) {
    00778     for ( int c=0; c<cols(); c++ ) {
    00779       col_width(c, width);
    00780     }
    00781   }
    00782
    00786   void row_position(int row);                   // set/get table's current scroll position
    00787
    00791   void col_position(int col);
    00792
    00796   int row_position() {                          // current row position
    00797     return(_row_position);
    00798   }
    00799
    00803   int col_position() {                          // current col position
    00804     return(_col_position);
    00805   }
    00806
    00812   inline void top_row(int row) {                // set/get top row (deprecated)
    00813     row_position(row);
    00814   }
    00815
    00820   inline int top_row() {
    00821     return(row_position());
    00822   }
    00823   int is_selected(int r, int c);                // selected cell
    00824   void get_selection(int &row_top, int &col_left, int &row_bot, int &col_right);
    00825   void set_selection(int row_top, int col_left, int row_bot, int col_right);
    00826   int move_cursor(int R, int C);
    00827
    00831   void resize(int X, int Y, int W, int H);      // fltk resize() override
    00832   void draw(void);                              // fltk draw() override
    00833
    00834   // This crashes sortapp() during init.
    00835   //  void box(Fl_Boxtype val) {
    00836   //    Fl_Group::box(val);
    00837   //    if ( table ) {
    00838   //      resize(x(), y(), w(), h());
    00839   //    }
    00840   //  }
    00841   //  Fl_Boxtype box(void) const {
    00842   //    return(Fl_Group::box());
    00843   //  }
    00844
    00845   // Child group
    00846   void init_sizes() {
    00847     table->init_sizes();
    00848     table->redraw();
    00849   }
    00850   void add(Fl_Widget& wgt) {
    00851     table->add(wgt);
    00852     if ( table->children() > 2 ) {
    00853       table->show();
    00854     } else {
    00855       table->hide();
    00856     }
    00857   }
    00858   void add(Fl_Widget* wgt) {
    00859     add(*wgt);
    00860   }
    00861   void insert(Fl_Widget& wgt, int n) {
    00862     table->insert(wgt,n);
    00863   }
    00864   void insert(Fl_Widget& wgt, Fl_Widget* w2) {
    00865     table->insert(wgt,w2);
    00866   }
    00867   void remove(Fl_Widget& wgt) {
    00868     table->remove(wgt);
    00869   }
    00870   void begin() {
    00871     table->begin();
    00872   }
    00873   void end() {
    00874     table->end();
    00875     // HACK: Avoid showing Fl_Scroll; seems to erase screen
    00876     //       causing unnecessary flicker, even if its box() is FL_NO_BOX.
    00877     //
    00878     if ( table->children() > 2 ) {
    00879       table->show();
    00880     } else {
    00881       table->hide();
    00882     }
    00883     Fl_Group::current(Fl_Group::parent());
    00884   }
    00885   Fl_Widget * const *array() {
    00886     return(table->array());
    00887   }
    00888
    00903   Fl_Widget *child(int n) const {
    00904     return(table->child(n));
    00905   }
    00906
    00915   int children() const {
    00916     return(table->children()-2);    // -2: skip Fl_Scroll's h/v scrollbar widgets
    00917   }
    00918   int find(const Fl_Widget *wgt) const {
    00919     return(table->find(wgt));
    00920   }
    00921   int find(const Fl_Widget &wgt) const {
    00922     return(table->find(wgt));
    00923   }
    00924   // CALLBACKS
    00925
    00931   int callback_row() {
    00932     return(_callback_row);
    00933   }
    00934
    00940   int callback_col() {
    00941     return(_callback_col);
    00942   }
    00943
    00949   TableContext callback_context() {
    00950     return(_callback_context);
    00951   }
    00952
    00953   void do_callback(TableContext context, int row, int col) {
    00954     _callback_context = context;
    00955     _callback_row = row;
    00956     _callback_col = col;
    00957     Fl_Widget::do_callback();
    00958   }
    00959
    00960 #if FL_DOXYGEN
    00961
    00989   void when(Fl_When flags);
    00990 #endif
    00991
    00992 #if FL_DOXYGEN
    00993
    01070   void callback(Fl_Widget*, void*);
    01071 #endif
    01072
    01073 #if FLTK_ABI_VERSION >= 10301
    01074   // NEW
    01084   int scrollbar_size() const {
    01085       return(_scrollbar_size);
    01086   }
    01105   void scrollbar_size(int newSize) {
    01106       if ( newSize != _scrollbar_size ) redraw();
    01107       _scrollbar_size = newSize;
    01108   }
    01109 #endif
    01110 };
    01111
    01112 #endif /*_FL_TABLE_H*/
    01113
    01114 //
    01115 // End of "$Id: Fl_Table.H 9731 2012-11-23 20:07:22Z greg.ercolano $".
    01116 //