FLTK 1.3.3
Fl_Table.H
1 //
2 // "$Id: Fl_Table.H 9843 2013-03-23 08:14:08Z greg.ercolano $"
3 //
4 // Fl_Table -- A table widget
5 //
6 // Copyright 2002 by Greg Ercolano.
7 // Copyright (c) 2004 O'ksi'D
8 //
9 // This library is free software. Distribution and use rights are outlined in
10 // the file "COPYING" which should have been included with this file. If this
11 // file is missing or damaged, see the license at:
12 //
13 // http://www.fltk.org/COPYING.php
14 //
15 // Please report all bugs and problems on the following page:
16 //
17 // http://www.fltk.org/str.php
18 //
19 
20 #ifndef _FL_TABLE_H
21 #define _FL_TABLE_H
22 
23 #include <sys/types.h>
24 #include <string.h> // memcpy
25 #ifdef WIN32
26 #include <malloc.h> // WINDOWS: malloc/realloc
27 #else /*WIN32*/
28 #include <stdlib.h> // UNIX: malloc/realloc
29 #endif /*WIN32*/
30 
31 #include <FL/Fl.H>
32 #include <FL/Fl_Group.H>
33 #include <FL/Fl_Scroll.H>
34 #include <FL/Fl_Box.H>
35 #include <FL/Fl_Scrollbar.H>
36 
170 class FL_EXPORT Fl_Table : public Fl_Group {
171 public:
176  CONTEXT_NONE = 0,
177  CONTEXT_STARTPAGE = 0x01,
178  CONTEXT_ENDPAGE = 0x02,
179  CONTEXT_ROW_HEADER = 0x04,
180  CONTEXT_COL_HEADER = 0x08,
181  CONTEXT_CELL = 0x10,
182  CONTEXT_TABLE = 0x20,
183  CONTEXT_RC_RESIZE = 0x40
184  };
185 
186 private:
187  int _rows, _cols; // total rows/cols
188  int _row_header_w; // width of row header
189  int _col_header_h; // height of column header
190  int _row_position; // last row_position set (not necessarily == toprow!)
191  int _col_position; // last col_position set (not necessarily == leftcol!)
192 
193  char _row_header; // row header enabled?
194  char _col_header; // col header enabled?
195  char _row_resize; // row resizing enabled?
196  char _col_resize; // col resizing enabled?
197  int _row_resize_min; // row minimum resizing height (default=1)
198  int _col_resize_min; // col minimum resizing width (default=1)
199 
200  // OPTIMIZATION: partial row/column redraw variables
201  int _redraw_toprow;
202  int _redraw_botrow;
203  int _redraw_leftcol;
204  int _redraw_rightcol;
205  Fl_Color _row_header_color;
206  Fl_Color _col_header_color;
207 
208  int _auto_drag;
209  int _selecting;
210 #if FLTK_ABI_VERSION >= 10301
211  int _scrollbar_size;
212 #endif
213 #if FLTK_ABI_VERSION >= 10303
214  enum {
215  TABCELLNAV = 1<<0,
216  };
217  unsigned int flags_;
218 #endif
219 
220  // An STL-ish vector without templates
221  class FL_EXPORT IntVector {
222  int *arr;
223  unsigned int _size;
224  void init() {
225  arr = NULL;
226  _size = 0;
227  }
228  void copy(int *newarr, unsigned int newsize) {
229  size(newsize);
230  memcpy(arr, newarr, newsize * sizeof(int));
231  }
232  public:
233  IntVector() { init(); } // CTOR
234  ~IntVector() { if ( arr ) free(arr); arr = NULL; } // DTOR
235  IntVector(IntVector&o) { init(); copy(o.arr, o._size); } // COPY CTOR
236  IntVector& operator=(IntVector&o) { // ASSIGN
237  init();
238  copy(o.arr, o._size);
239  return(*this);
240  }
241  int operator[](int x) const { return(arr[x]); }
242  int& operator[](int x) { return(arr[x]); }
243  unsigned int size() { return(_size); }
244  void size(unsigned int count) {
245  if ( count != _size ) {
246  arr = (int*)realloc(arr, count * sizeof(int));
247  _size = count;
248  }
249  }
250  int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
251  void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
252  int back() { return(arr[_size-1]); }
253  };
254 
255  IntVector _colwidths; // column widths in pixels
256  IntVector _rowheights; // row heights in pixels
257 
258  Fl_Cursor _last_cursor; // last mouse cursor before changed to 'resize' cursor
259 
260  // EVENT CALLBACK DATA
261  TableContext _callback_context; // event context
262  int _callback_row, _callback_col; // event row/col
263 
264  // handle() state variables.
265  // Put here instead of local statics in handle(), so more
266  // than one Fl_Table can exist without crosstalk between them.
267  //
268  int _resizing_col; // column being dragged
269  int _resizing_row; // row being dragged
270  int _dragging_x; // starting x position for horiz drag
271  int _dragging_y; // starting y position for vert drag
272  int _last_row; // last row we FL_PUSH'ed
273 
274  // Redraw single cell
275  void _redraw_cell(TableContext context, int R, int C);
276 
277  void _start_auto_drag();
278  void _stop_auto_drag();
279  void _auto_drag_cb();
280  static void _auto_drag_cb2(void *d);
281 
282 protected:
283  enum ResizeFlag {
284  RESIZE_NONE = 0,
285  RESIZE_COL_LEFT = 1,
286  RESIZE_COL_RIGHT = 2,
287  RESIZE_ROW_ABOVE = 3,
288  RESIZE_ROW_BELOW = 4
289  };
290 
291  int table_w, table_h; // table's virtual size (in pixels)
292  int toprow, botrow, leftcol, rightcol; // four corners of viewable table
293 
294  // selection
295  int current_row, current_col;
296  int select_row, select_col;
297 
298  // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
299  int toprow_scrollpos;
300  int leftcol_scrollpos;
301 
302  // Dimensions
303  int tix, tiy, tiw, tih; // data table inner dimension xywh
304  int tox, toy, tow, toh; // data table outer dimension xywh
305  int wix, wiy, wiw, wih; // widget inner dimension xywh
306 
307  Fl_Scroll *table; // container for child fltk widgets (if any)
308  Fl_Scrollbar *vscrollbar; // vertical scrollbar
309  Fl_Scrollbar *hscrollbar; // horizontal scrollbar
310 
311  // Fltk
312  int handle(int e); // fltk handle() override
313 
314  // Class maintenance
315  void recalc_dimensions();
316  void table_resized(); // table resized; recalc
317  void table_scrolled(); // table scrolled; recalc
318  void get_bounds(TableContext context, // return x/y/w/h bounds for context
319  int &X, int &Y, int &W, int &H);
320  void change_cursor(Fl_Cursor newcursor); // change mouse cursor to some other shape
321  TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
322  // find r/c given current x/y event
323  int find_cell(TableContext context, // find cell's x/y/w/h given r/c
324  int R, int C, int &X, int &Y, int &W, int &H);
325  int row_col_clamp(TableContext context, int &R, int &C);
326  // clamp r/c to known universe
327 
438  virtual void draw_cell(TableContext context, int R=0, int C=0,
439  int X=0, int Y=0, int W=0, int H=0)
440  { } // overridden by deriving class
441 
442  long row_scroll_position(int row); // find scroll position of row (in pixels)
443  long col_scroll_position(int col); // find scroll position of col (in pixels)
444 
445  int is_fltk_container() { // does table contain fltk widgets?
446  return( Fl_Group::children() > 3 ); // (ie. more than box and 2 scrollbars?)
447  }
448 
449  static void scroll_cb(Fl_Widget*,void*); // h/v scrollbar callback
450 
451  void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
452 
453  void redraw_range(int topRow, int botRow, int leftCol, int rightCol) {
454  if ( _redraw_toprow == -1 ) {
455  // Initialize redraw range
456  _redraw_toprow = topRow;
457  _redraw_botrow = botRow;
458  _redraw_leftcol = leftCol;
459  _redraw_rightcol = rightCol;
460  } else {
461  // Extend redraw range
462  if ( topRow < _redraw_toprow ) _redraw_toprow = topRow;
463  if ( botRow > _redraw_botrow ) _redraw_botrow = botRow;
464  if ( leftCol < _redraw_leftcol ) _redraw_leftcol = leftCol;
465  if ( rightCol > _redraw_rightcol ) _redraw_rightcol = rightCol;
466  }
467 
468  // Indicate partial redraw needed of some cells
469  damage(FL_DAMAGE_CHILD);
470  }
471 
472 public:
478  Fl_Table(int X, int Y, int W, int H, const char *l=0);
479 
484  ~Fl_Table();
485 
491  virtual void clear() { rows(0); cols(0); table->clear(); }
492 
493  // \todo: add topline(), middleline(), bottomline()
494 
500  inline void table_box(Fl_Boxtype val) {
501  table->box(val);
502  table_resized();
503  }
504 
508  inline Fl_Boxtype table_box( void ) {
509  return(table->box());
510  }
511 
515  virtual void rows(int val); // set/get number of rows
516 
520  inline int rows() {
521  return(_rows);
522  }
523 
527  virtual void cols(int val); // set/get number of columns
528 
532  inline int cols() {
533  return(_cols);
534  }
535 
564  inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
565  r1 = toprow;
566  r2 = botrow;
567  c1 = leftcol;
568  c2 = rightcol;
569  }
570 
576  return(_resizing_row != -1 || _resizing_col != -1);
577  }
578 
582  inline int row_resize() {
583  return(_row_resize);
584  }
585 
592  void row_resize(int flag) { // enable row resizing
593  _row_resize = flag;
594  }
595 
599  inline int col_resize() {
600  return(_col_resize);
601  }
608  void col_resize(int flag) { // enable col resizing
609  _col_resize = flag;
610  }
611 
617  inline int col_resize_min() { // column minimum resizing width
618  return(_col_resize_min);
619  }
620 
624  void col_resize_min(int val) {
625  _col_resize_min = ( val < 1 ) ? 1 : val;
626  }
627 
631  inline int row_resize_min() { // column minimum resizing width
632  return(_row_resize_min);
633  }
634 
640  void row_resize_min(int val) {
641  _row_resize_min = ( val < 1 ) ? 1 : val;
642  }
643 
647  inline int row_header() { // set/get row header enable flag
648  return(_row_header);
649  }
650 
655  void row_header(int flag) {
656  _row_header = flag;
657  table_resized();
658  redraw();
659  }
660 
664  inline int col_header() { // set/get col header enable flag
665  return(_col_header);
666  }
667 
672  void col_header(int flag) {
673  _col_header = flag;
674  table_resized();
675  redraw();
676  }
677 
681  inline void col_header_height(int height) { // set/get col header height
682  _col_header_h = height;
683  table_resized();
684  redraw();
685  }
686 
690  inline int col_header_height() {
691  return(_col_header_h);
692  }
693 
697  inline void row_header_width(int width) { // set/get row header width
698  _row_header_w = width;
699  table_resized();
700  redraw();
701  }
702 
706  inline int row_header_width() {
707  return(_row_header_w);
708  }
709 
713  inline void row_header_color(Fl_Color val) { // set/get row header color
714  _row_header_color = val;
715  redraw();
716  }
717 
722  return(_row_header_color);
723  }
724 
728  inline void col_header_color(Fl_Color val) { // set/get col header color
729  _col_header_color = val;
730  redraw();
731  }
732 
737  return(_col_header_color);
738  }
739 
746  void row_height(int row, int height); // set/get row height
747 
751  inline int row_height(int row) {
752  return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]);
753  }
754 
760  void col_width(int col, int width); // set/get a column's width
761 
765  inline int col_width(int col) {
766  return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]);
767  }
768 
773  void row_height_all(int height) { // set all row/col heights
774  for ( int r=0; r<rows(); r++ ) {
775  row_height(r, height);
776  }
777  }
778 
783  void col_width_all(int width) {
784  for ( int c=0; c<cols(); c++ ) {
785  col_width(c, width);
786  }
787  }
788 
792  void row_position(int row); // set/get table's current scroll position
793 
797  void col_position(int col);
798 
802  int row_position() { // current row position
803  return(_row_position);
804  }
805 
809  int col_position() { // current col position
810  return(_col_position);
811  }
812 
818  inline void top_row(int row) { // set/get top row (deprecated)
819  row_position(row);
820  }
821 
826  inline int top_row() {
827  return(row_position());
828  }
829  int is_selected(int r, int c); // selected cell
830  void get_selection(int &row_top, int &col_left, int &row_bot, int &col_right);
831  void set_selection(int row_top, int col_left, int row_bot, int col_right);
832  int move_cursor(int R, int C, int shiftselect);
833  int move_cursor(int R, int C);
834 
838  void resize(int X, int Y, int W, int H); // fltk resize() override
839  void draw(void); // fltk draw() override
840 
841  // This crashes sortapp() during init.
842  // void box(Fl_Boxtype val) {
843  // Fl_Group::box(val);
844  // if ( table ) {
845  // resize(x(), y(), w(), h());
846  // }
847  // }
848  // Fl_Boxtype box(void) const {
849  // return(Fl_Group::box());
850  // }
851 
852  // Child group
853  void init_sizes() {
854  table->init_sizes();
855  table->redraw();
856  }
857  void add(Fl_Widget& wgt) {
858  table->add(wgt);
859  if ( table->children() > 2 ) {
860  table->show();
861  } else {
862  table->hide();
863  }
864  }
865  void add(Fl_Widget* wgt) {
866  add(*wgt);
867  }
868  void insert(Fl_Widget& wgt, int n) {
869  table->insert(wgt,n);
870  }
871  void insert(Fl_Widget& wgt, Fl_Widget* w2) {
872  table->insert(wgt,w2);
873  }
874  void remove(Fl_Widget& wgt) {
875  table->remove(wgt);
876  }
877  void begin() {
878  table->begin();
879  }
880  void end() {
881  table->end();
882  // HACK: Avoid showing Fl_Scroll; seems to erase screen
883  // causing unnecessary flicker, even if its box() is FL_NO_BOX.
884  //
885  if ( table->children() > 2 ) {
886  table->show();
887  } else {
888  table->hide();
889  }
891  }
892  Fl_Widget * const *array() {
893  return(table->array());
894  }
895 
910  Fl_Widget *child(int n) const {
911  return(table->child(n));
912  }
913 
922  int children() const {
923  return(table->children()-2); // -2: skip Fl_Scroll's h/v scrollbar widgets
924  }
925  int find(const Fl_Widget *wgt) const {
926  return(table->find(wgt));
927  }
928  int find(const Fl_Widget &wgt) const {
929  return(table->find(wgt));
930  }
931  // CALLBACKS
932 
938  int callback_row() {
939  return(_callback_row);
940  }
941 
947  int callback_col() {
948  return(_callback_col);
949  }
950 
957  return(_callback_context);
958  }
959 
960  void do_callback(TableContext context, int row, int col) {
961  _callback_context = context;
962  _callback_row = row;
963  _callback_col = col;
965  }
966 
967 #if FL_DOXYGEN
968 
996  void when(Fl_When flags);
997 #endif
998 
999 #if FL_DOXYGEN
1000 
1077  void callback(Fl_Widget*, void*);
1078 #endif
1079 
1080 #if FLTK_ABI_VERSION >= 10301
1081  // NEW
1091  int scrollbar_size() const {
1092  return(_scrollbar_size);
1093  }
1112  void scrollbar_size(int newSize) {
1113  if ( newSize != _scrollbar_size ) redraw();
1114  _scrollbar_size = newSize;
1115  }
1116 #endif
1117 #if FLTK_ABI_VERSION >= 10303
1118 
1131  void tab_cell_nav(int val) {
1132  if ( val ) flags_ |= TABCELLNAV;
1133  else flags_ &= ~TABCELLNAV;
1134  }
1135 
1143  int tab_cell_nav() const {
1144  return(flags_ & TABCELLNAV ? 1 : 0);
1145  }
1146 #endif
1147 };
1148 
1149 #endif /*_FL_TABLE_H*/
1150 
1151 //
1152 // End of "$Id: Fl_Table.H 9843 2013-03-23 08:14:08Z greg.ercolano $".
1153 //