|
FLTK 1.3.2
|
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 //