FLTK 1.3.2
Fl_Table.H
1 //
2 // "$Id: Fl_Table.H 9731 2012-11-23 20:07:22Z 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 
214  // An STL-ish vector without templates
215  class FL_EXPORT IntVector {
216  int *arr;
217  unsigned int _size;
218  void init() {
219  arr = NULL;
220  _size = 0;
221  }
222  void copy(int *newarr, unsigned int newsize) {
223  size(newsize);
224  memcpy(arr, newarr, newsize * sizeof(int));
225  }
226  public:
227  IntVector() { init(); } // CTOR
228  ~IntVector() { if ( arr ) free(arr); arr = NULL; } // DTOR
229  IntVector(IntVector&o) { init(); copy(o.arr, o._size); } // COPY CTOR
230  IntVector& operator=(IntVector&o) { // ASSIGN
231  init();
232  copy(o.arr, o._size);
233  return(*this);
234  }
235  int operator[](int x) const { return(arr[x]); }
236  int& operator[](int x) { return(arr[x]); }
237  unsigned int size() { return(_size); }
238  void size(unsigned int count) {
239  if ( count != _size ) {
240  arr = (int*)realloc(arr, count * sizeof(int));
241  _size = count;
242  }
243  }
244  int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
245  void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
246  int back() { return(arr[_size-1]); }
247  };
248 
249  IntVector _colwidths; // column widths in pixels
250  IntVector _rowheights; // row heights in pixels
251 
252  Fl_Cursor _last_cursor; // last mouse cursor before changed to 'resize' cursor
253 
254  // EVENT CALLBACK DATA
255  TableContext _callback_context; // event context
256  int _callback_row, _callback_col; // event row/col
257 
258  // handle() state variables.
259  // Put here instead of local statics in handle(), so more
260  // than one Fl_Table can exist without crosstalk between them.
261  //
262  int _resizing_col; // column being dragged
263  int _resizing_row; // row being dragged
264  int _dragging_x; // starting x position for horiz drag
265  int _dragging_y; // starting y position for vert drag
266  int _last_row; // last row we FL_PUSH'ed
267 
268  // Redraw single cell
269  void _redraw_cell(TableContext context, int R, int C);
270 
271  void _start_auto_drag();
272  void _stop_auto_drag();
273  void _auto_drag_cb();
274  static void _auto_drag_cb2(void *d);
275 
276 protected:
277  enum ResizeFlag {
278  RESIZE_NONE = 0,
279  RESIZE_COL_LEFT = 1,
280  RESIZE_COL_RIGHT = 2,
281  RESIZE_ROW_ABOVE = 3,
282  RESIZE_ROW_BELOW = 4
283  };
284 
285  int table_w, table_h; // table's virtual size (in pixels)
286  int toprow, botrow, leftcol, rightcol; // four corners of viewable table
287 
288  // selection
289  int current_row, current_col;
290  int select_row, select_col;
291 
292  // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
293  int toprow_scrollpos;
294  int leftcol_scrollpos;
295 
296  // Dimensions
297  int tix, tiy, tiw, tih; // data table inner dimension xywh
298  int tox, toy, tow, toh; // data table outer dimension xywh
299  int wix, wiy, wiw, wih; // widget inner dimension xywh
300 
301  Fl_Scroll *table; // container for child fltk widgets (if any)
302  Fl_Scrollbar *vscrollbar; // vertical scrollbar
303  Fl_Scrollbar *hscrollbar; // horizontal scrollbar
304 
305  // Fltk
306  int handle(int e); // fltk handle() override
307 
308  // Class maintenance
309  void recalc_dimensions();
310  void table_resized(); // table resized; recalc
311  void table_scrolled(); // table scrolled; recalc
312  void get_bounds(TableContext context, // return x/y/w/h bounds for context
313  int &X, int &Y, int &W, int &H);
314  void change_cursor(Fl_Cursor newcursor); // change mouse cursor to some other shape
315  TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
316  // find r/c given current x/y event
317  int find_cell(TableContext context, // find cell's x/y/w/h given r/c
318  int R, int C, int &X, int &Y, int &W, int &H);
319  int row_col_clamp(TableContext context, int &R, int &C);
320  // clamp r/c to known universe
321 
432  virtual void draw_cell(TableContext context, int R=0, int C=0,
433  int X=0, int Y=0, int W=0, int H=0)
434  { } // overridden by deriving class
435 
436  long row_scroll_position(int row); // find scroll position of row (in pixels)
437  long col_scroll_position(int col); // find scroll position of col (in pixels)
438 
439  int is_fltk_container() { // does table contain fltk widgets?
440  return( Fl_Group::children() > 3 ); // (ie. more than box and 2 scrollbars?)
441  }
442 
443  static void scroll_cb(Fl_Widget*,void*); // h/v scrollbar callback
444 
445  void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
446 
447  void redraw_range(int topRow, int botRow, int leftCol, int rightCol) {
448  if ( _redraw_toprow == -1 ) {
449  // Initialize redraw range
450  _redraw_toprow = topRow;
451  _redraw_botrow = botRow;
452  _redraw_leftcol = leftCol;
453  _redraw_rightcol = rightCol;
454  } else {
455  // Extend redraw range
456  if ( topRow < _redraw_toprow ) _redraw_toprow = topRow;
457  if ( botRow > _redraw_botrow ) _redraw_botrow = botRow;
458  if ( leftCol < _redraw_leftcol ) _redraw_leftcol = leftCol;
459  if ( rightCol > _redraw_rightcol ) _redraw_rightcol = rightCol;
460  }
461 
462  // Indicate partial redraw needed of some cells
463  damage(FL_DAMAGE_CHILD);
464  }
465 
466 public:
472  Fl_Table(int X, int Y, int W, int H, const char *l=0);
473 
478  ~Fl_Table();
479 
485  virtual void clear() { rows(0); cols(0); table->clear(); }
486 
487  // \todo: add topline(), middleline(), bottomline()
488 
494  inline void table_box(Fl_Boxtype val) {
495  table->box(val);
496  table_resized();
497  }
498 
502  inline Fl_Boxtype table_box( void ) {
503  return(table->box());
504  }
505 
509  virtual void rows(int val); // set/get number of rows
510 
514  inline int rows() {
515  return(_rows);
516  }
517 
521  virtual void cols(int val); // set/get number of columns
522 
526  inline int cols() {
527  return(_cols);
528  }
529 
558  inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
559  r1 = toprow;
560  r2 = botrow;
561  c1 = leftcol;
562  c2 = rightcol;
563  }
564 
570  return(_resizing_row != -1 || _resizing_col != -1);
571  }
572 
576  inline int row_resize() {
577  return(_row_resize);
578  }
579 
586  void row_resize(int flag) { // enable row resizing
587  _row_resize = flag;
588  }
589 
593  inline int col_resize() {
594  return(_col_resize);
595  }
602  void col_resize(int flag) { // enable col resizing
603  _col_resize = flag;
604  }
605 
611  inline int col_resize_min() { // column minimum resizing width
612  return(_col_resize_min);
613  }
614 
618  void col_resize_min(int val) {
619  _col_resize_min = ( val < 1 ) ? 1 : val;
620  }
621 
625  inline int row_resize_min() { // column minimum resizing width
626  return(_row_resize_min);
627  }
628 
634  void row_resize_min(int val) {
635  _row_resize_min = ( val < 1 ) ? 1 : val;
636  }
637 
641  inline int row_header() { // set/get row header enable flag
642  return(_row_header);
643  }
644 
649  void row_header(int flag) {
650  _row_header = flag;
651  table_resized();
652  redraw();
653  }
654 
658  inline int col_header() { // set/get col header enable flag
659  return(_col_header);
660  }
661 
666  void col_header(int flag) {
667  _col_header = flag;
668  table_resized();
669  redraw();
670  }
671 
675  inline void col_header_height(int height) { // set/get col header height
676  _col_header_h = height;
677  table_resized();
678  redraw();
679  }
680 
684  inline int col_header_height() {
685  return(_col_header_h);
686  }
687 
691  inline void row_header_width(int width) { // set/get row header width
692  _row_header_w = width;
693  table_resized();
694  redraw();
695  }
696 
700  inline int row_header_width() {
701  return(_row_header_w);
702  }
703 
707  inline void row_header_color(Fl_Color val) { // set/get row header color
708  _row_header_color = val;
709  redraw();
710  }
711 
716  return(_row_header_color);
717  }
718 
722  inline void col_header_color(Fl_Color val) { // set/get col header color
723  _col_header_color = val;
724  redraw();
725  }
726 
731  return(_col_header_color);
732  }
733 
740  void row_height(int row, int height); // set/get row height
741 
745  inline int row_height(int row) {
746  return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]);
747  }
748 
754  void col_width(int col, int width); // set/get a column's width
755 
759  inline int col_width(int col) {
760  return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]);
761  }
762 
767  void row_height_all(int height) { // set all row/col heights
768  for ( int r=0; r<rows(); r++ ) {
769  row_height(r, height);
770  }
771  }
772 
777  void col_width_all(int width) {
778  for ( int c=0; c<cols(); c++ ) {
779  col_width(c, width);
780  }
781  }
782 
786  void row_position(int row); // set/get table's current scroll position
787 
791  void col_position(int col);
792 
796  int row_position() { // current row position
797  return(_row_position);
798  }
799 
803  int col_position() { // current col position
804  return(_col_position);
805  }
806 
812  inline void top_row(int row) { // set/get top row (deprecated)
813  row_position(row);
814  }
815 
820  inline int top_row() {
821  return(row_position());
822  }
823  int is_selected(int r, int c); // selected cell
824  void get_selection(int &row_top, int &col_left, int &row_bot, int &col_right);
825  void set_selection(int row_top, int col_left, int row_bot, int col_right);
826  int move_cursor(int R, int C);
827 
831  void resize(int X, int Y, int W, int H); // fltk resize() override
832  void draw(void); // fltk draw() override
833 
834  // This crashes sortapp() during init.
835  // void box(Fl_Boxtype val) {
836  // Fl_Group::box(val);
837  // if ( table ) {
838  // resize(x(), y(), w(), h());
839  // }
840  // }
841  // Fl_Boxtype box(void) const {
842  // return(Fl_Group::box());
843  // }
844 
845  // Child group
846  void init_sizes() {
847  table->init_sizes();
848  table->redraw();
849  }
850  void add(Fl_Widget& wgt) {
851  table->add(wgt);
852  if ( table->children() > 2 ) {
853  table->show();
854  } else {
855  table->hide();
856  }
857  }
858  void add(Fl_Widget* wgt) {
859  add(*wgt);
860  }
861  void insert(Fl_Widget& wgt, int n) {
862  table->insert(wgt,n);
863  }
864  void insert(Fl_Widget& wgt, Fl_Widget* w2) {
865  table->insert(wgt,w2);
866  }
867  void remove(Fl_Widget& wgt) {
868  table->remove(wgt);
869  }
870  void begin() {
871  table->begin();
872  }
873  void end() {
874  table->end();
875  // HACK: Avoid showing Fl_Scroll; seems to erase screen
876  // causing unnecessary flicker, even if its box() is FL_NO_BOX.
877  //
878  if ( table->children() > 2 ) {
879  table->show();
880  } else {
881  table->hide();
882  }
884  }
885  Fl_Widget * const *array() {
886  return(table->array());
887  }
888 
903  Fl_Widget *child(int n) const {
904  return(table->child(n));
905  }
906 
915  int children() const {
916  return(table->children()-2); // -2: skip Fl_Scroll's h/v scrollbar widgets
917  }
918  int find(const Fl_Widget *wgt) const {
919  return(table->find(wgt));
920  }
921  int find(const Fl_Widget &wgt) const {
922  return(table->find(wgt));
923  }
924  // CALLBACKS
925 
931  int callback_row() {
932  return(_callback_row);
933  }
934 
940  int callback_col() {
941  return(_callback_col);
942  }
943 
950  return(_callback_context);
951  }
952 
953  void do_callback(TableContext context, int row, int col) {
954  _callback_context = context;
955  _callback_row = row;
956  _callback_col = col;
958  }
959 
960 #if FL_DOXYGEN
961 
989  void when(Fl_When flags);
990 #endif
991 
992 #if FL_DOXYGEN
993 
1070  void callback(Fl_Widget*, void*);
1071 #endif
1072 
1073 #if FLTK_ABI_VERSION >= 10301
1074  // NEW
1084  int scrollbar_size() const {
1085  return(_scrollbar_size);
1086  }
1105  void scrollbar_size(int newSize) {
1106  if ( newSize != _scrollbar_size ) redraw();
1107  _scrollbar_size = newSize;
1108  }
1109 #endif
1110 };
1111 
1112 #endif /*_FL_TABLE_H*/
1113 
1114 //
1115 // End of "$Id: Fl_Table.H 9731 2012-11-23 20:07:22Z greg.ercolano $".
1116 //
void col_resize(int flag)
Allows/disallows column resizing by the user.
Definition: Fl_Table.H:602
Fl_Widget is the base class for all widgets in FLTK.
Definition: Fl_Widget.H:100
int row_resize_min()
Returns the current row minimum resize value.
Definition: Fl_Table.H:625
A table of widgets or other content.
Definition: Fl_Table.H:170
Fl_Boxtype table_box(void)
Returns the current box type used for the data table.
Definition: Fl_Table.H:502
Fl_Cursor
The following constants define the mouse cursors that are available in FLTK.
Definition: Enumerations.H:888
int rows()
Returns the number of rows in the table.
Definition: Fl_Table.H:514
int row_header()
Returns the value of this flag.
Definition: Fl_Table.H:641
virtual void hide()
Makes a widget invisible.
Definition: Fl_Widget.cxx:264
int col_header_height()
Gets the column header height.
Definition: Fl_Table.H:684
int callback_col()
Returns the current column the event occurred on.
Definition: Fl_Table.H:940
void redraw()
Schedules the drawing of the widget.
Definition: Fl.cxx:1627
Fl_Widget * child(int n) const
Returns the child widget by an index.
Definition: Fl_Table.H:903
void table_box(Fl_Boxtype val)
Sets the kind of box drawn around the data table, the default being FL_NO_BOX.
Definition: Fl_Table.H:494
void col_header_height(int height)
Sets the height in pixels for column headers and redraws the table.
Definition: Fl_Table.H:675
Fl static class.
virtual void clear()
Clears the table to zero rows (rows(0)), zero columns (cols(0)), and clears any widgets (table->clear...
Definition: Fl_Table.H:485
int col_header()
Returns if column headers are enabled or not.
Definition: Fl_Table.H:658
void col_width_all(int width)
Convenience method to set the width of all columns to the same value, in pixels.
Definition: Fl_Table.H:777
void clear()
Clear all but the scrollbars...
Definition: Fl_Scroll.cxx:25
void remove(int index)
Removes the widget at index from the group but does not delete it.
Definition: Fl_Group.cxx:501
Fl_When
These constants determine when a callback is performed.
Definition: Enumerations.H:309
Fl_Group * parent() const
Returns a pointer to the parent widget.
Definition: Fl_Widget.H:242
Fl_Color row_header_color()
Returns the current row header color.
Definition: Fl_Table.H:715
void init_sizes()
Resets the internal array of widget sizes and positions.
Definition: Fl_Group.cxx:570
TableContext
The context bit flags for Fl_Table related callbacks (eg.
Definition: Fl_Table.H:175
Fl_Widget * child(int n) const
Returns array()[n].
Definition: Fl_Group.H:74
void end()
Exactly the same as current(this->parent()).
Definition: Fl_Group.cxx:75
void row_resize_min(int val)
Sets the current row minimum resize value.
Definition: Fl_Table.H:634
A child needs to be redrawn.
Definition: Enumerations.H:945
Fl_Color col_header_color()
Gets the color for column headers.
Definition: Fl_Table.H:730
void visible_cells(int &r1, int &r2, int &c1, int &c2)
Returns the range of row and column numbers for all visible and partially visible cells in the table...
Definition: Fl_Table.H:558
Fl_Boxtype
Definition: Enumerations.H:469
int cols()
Get the number of columns in the table.
Definition: Fl_Table.H:526
void row_height_all(int height)
Convenience method to set the height of all rows to the same value, in pixels.
Definition: Fl_Table.H:767
void insert(Fl_Widget &, int i)
The widget is removed from its current group (if any) and then inserted into this group...
Definition: Fl_Group.cxx:456
The Fl_Group class is the FLTK container widget.
Definition: Fl_Group.H:36
int is_interactive_resize()
Returns 1 if someone is interactively resizing a row or column.
Definition: Fl_Table.H:569
void add(Fl_Widget &)
The widget is removed from its current group (if any) and then added to the end of this group...
Definition: Fl_Group.cxx:489
int find(const Fl_Widget *) const
Searches the child array for the widget and returns the index.
Definition: Fl_Group.cxx:52
Fl_Boxtype box() const
Gets the box type of the widget.
Definition: Fl_Widget.H:351
void row_header_color(Fl_Color val)
Sets the row header color and causes the screen to redraw.
Definition: Fl_Table.H:707
int col_width(int col)
Returns the current width of the specified column in pixels.
Definition: Fl_Table.H:759
int row_position()
Returns the current row scroll position as a row number.
Definition: Fl_Table.H:796
void begin()
Sets the current group so you can build the widget tree by just constructing the widgets.
Definition: Fl_Group.cxx:69
void col_header(int flag)
Enable or disable column headers.
Definition: Fl_Table.H:666
void row_resize(int flag)
Allows/disallows row resizing by the user.
Definition: Fl_Table.H:586
virtual void show()
Makes a widget visible.
Definition: Fl_Widget.cxx:252
virtual void draw_cell(TableContext context, int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0)
Subclass should override this method to handle drawing the cells.
Definition: Fl_Table.H:432
int col_resize()
Returns the current value of this flag.
Definition: Fl_Table.H:593
void top_row(int row)
Sets which row should be at the top of the table, scrolling as necessary, and the table is redrawn...
Definition: Fl_Table.H:812
int row_height(int row)
Returns the current height of the specified row as a value in pixels.
Definition: Fl_Table.H:745
void col_header_color(Fl_Color val)
Sets the color for column headers and redraws the table.
Definition: Fl_Table.H:722
int children() const
Returns how many child widgets the group has.
Definition: Fl_Group.H:70
int top_row()
Returns the current top row shown in the table.
Definition: Fl_Table.H:820
int row_header_width()
Returns the current row header width (in pixels).
Definition: Fl_Table.H:700
void col_resize_min(int val)
Returns the current column minimum resize value.
Definition: Fl_Table.H:618
unsigned int Fl_Color
an FLTK color value
Definition: Enumerations.H:774
void do_callback()
Calls the widget callback.
Definition: Fl_Widget.H:827
Fl_Widget *const * array() const
Returns a pointer to the array of children.
Definition: Fl_Group.cxx:44
int children() const
Returns the number of children in the table.
Definition: Fl_Table.H:915
This container widget lets you maneuver around a set of widgets much larger than your window...
Definition: Fl_Scroll.H:87
int callback_row()
Returns the current row the event occurred on.
Definition: Fl_Table.H:931
int col_resize_min()
Sets the current column minimum resize value.
Definition: Fl_Table.H:611
int row_resize()
Returns the current value of this flag.
Definition: Fl_Table.H:576
int col_position()
Returns the current column scroll position as a column number.
Definition: Fl_Table.H:803
TableContext callback_context()
Returns the current 'table context'.
Definition: Fl_Table.H:949
The Fl_Scrollbar widget displays a slider with arrow buttons at the ends of the scrollbar.
Definition: Fl_Scrollbar.H:43
void row_header_width(int width)
Sets the row header width to n and causes the screen to redraw.
Definition: Fl_Table.H:691
static Fl_Group * current()
Returns the currently active group.
Definition: Fl_Group.cxx:84
void row_header(int flag)
Enables/disables showing the row headers.
Definition: Fl_Table.H:649