FLTK 1.3.2
|
00001 // 00002 // "$Id$" 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$". 01116 //