Fix offscreen drawing for cairo.
[ntk.git] / FL / Fl_Table.H
blob55c06fdddaf1ee8d815dfbf54b9749c1c5400cc7
1 //
2 // "$Id: Fl_Table.H 8301 2011-01-22 22:40:11Z AlbrechtS $"
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; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 // Library General Public License for more details.
19 // You should have received a copy of the GNU Library General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 // USA.
24 // Please report all bugs and problems to "erco at seriss dot com".
26 // TODO:
27 //    o Auto scroll during dragged selection
28 //    o Keyboard navigation (up/down/left/right arrow)
31 #ifndef _FL_TABLE_H
32 #define _FL_TABLE_H
34 #include <sys/types.h>
35 #include <string.h>             // memcpy
36 #ifdef WIN32
37 #include <malloc.h>             // WINDOWS: malloc/realloc
38 #else /*WIN32*/
39 #include <stdlib.h>             // UNIX: malloc/realloc
40 #endif /*WIN32*/
42 #include <FL/Fl.H>
43 #include <FL/Fl_Group.H>
44 #include <FL/Fl_Scroll.H>
45 #include <FL/Fl_Box.H>
46 #include <FL/Fl_Scrollbar.H>
48 /**
49  A table of widgets or other content.
51  This is the base class for table widgets.
53  To be useful it must be subclassed and several virtual functions defined.
54  Normally applications use widgets derived from this widget, and do not use this 
55  widget directly; this widget is usually too low level to be used directly by 
56  applications.
58  This widget does \em not handle the data in the table. The draw_cell()
59  method must be overridden by a subclass to manage drawing the contents of 
60  the cells.
62  This widget can be used in several ways:
64  - As a custom widget; see examples/table-simple.cxx and test/table.cxx.
65    Very optimal for even extremely large tables.
66  - As a table made up of a single FLTK widget instanced all over the table,
67    simulating a numeric spreadsheet. See examples/table-spreadsheet.cxx and
68    examples/table-spreadsheet-with-keyboard-nav.cxx. Optimal for large tables.
69  - As a regular container of FLTK widgets, one widget per cell.
70    See examples/table-as-container.cxx. \em Not recommended for large tables.
72  \image html table-simple.png
73  \image latex table-simple.png "table-simple example" width=6cm
75  \image html table-as-container.png
76  \image latex table-as-container.png "table-as-container example" width=6cm
78  When acting as part of a custom widget, events on the cells and/or headings
79  generate callbacks when they are clicked by the user. You control when events 
80  are generated based on the setting for Fl_Table::when().
82  When acting as a container for FLTK widgets, the FLTK widgets maintain 
83  themselves. Although the draw_cell() method must be overridden, its contents 
84  can be very simple. See the draw_cell() code in examples/table-simple.cxx.
86  The following variables are available to classes deriving from Fl_Table:
88  \image html table-dimensions.png
89  \image latex table-dimensions.png "Fl_Table Dimensions" width=6cm
91  <table border=0>
92  <tr><td>x()/y()/w()/h()</td>
93  <td>Fl_Table widget's outer dimension. The outer edge of the border of the 
94  Fl_Table. (Red in the diagram above)</td></tr>
96  <tr><td>wix/wiy/wiw/wih</td>
97  <td>Fl_Table widget's inner dimension. The inner edge of the border of the 
98  Fl_Table. eg. if the Fl_Table's box() is FL_NO_BOX, these values are the same 
99  as x()/y()/w()/h(). (Yellow in the diagram above)</td></tr>
101  <tr><td>tox/toy/tow/toh</td>
102  <td>The table's outer dimension. The outer edge of the border around the cells,
103  but inside the row/col headings and scrollbars. (Green in the diagram above)
104  </td></tr>
106  <tr><td>tix/tiy/tiw/tih</td>
107  <td>The table's inner dimension. The inner edge of the border around the cells,
108  but inside the row/col headings and scrollbars. AKA the table's clip region. 
109  eg. if the table_box() is FL_NO_BOX, these values are the same as
110  tox/toyy/tow/toh. (Blue in the diagram above)
111  </td></tr></table>
113  CORE DEVELOPERS
115  - Greg Ercolano : 12/16/2002 - initial implementation 12/16/02. Fl_Table, Fl_Table_Row, docs.
116  - Jean-Marc Lienher : 02/22/2004 - added keyboard nav + mouse selection, and ported Fl_Table into fltk-utf8-1.1.4
118  OTHER CONTRIBUTORS
120  - Inspired by the Feb 2000 version of FLVW's Flvw_Table widget. Mucho thanks to those folks.
121  - Mister Satan : 04/07/2003 - MinGW porting mods, and singleinput.cxx; a cool Fl_Input oriented spreadsheet example
122  - Marek Paliwoda : 01/08/2003 - Porting mods for Borland
123  - Ori Berger : 03/16/2006 - Optimizations for >500k rows/cols
125  LICENSE
127  Greg added the following license to the original distribution of Fl_Table. He 
128  kindly gave his permission to integrate Fl_Table and Fl_Table_Row into FLTK,
129  allowing FLTK license to apply while his widgets are part of the library.
131  If used on its own, this is the license that applies:
133  \verbatim 
134  Fl_Table License
135  December 16, 2002
137  The Fl_Table library and included programs are provided under the terms
138  of the GNU Library General Public License (LGPL) with the following
139  exceptions:
141  1. Modifications to the Fl_Table configure script, config
142  header file, and makefiles by themselves to support
143  a specific platform do not constitute a modified or
144  derivative work.
146  The authors do request that such modifications be
147  contributed to the Fl_Table project - send all
148  contributions to "erco at seriss dot com".
150  2. Widgets that are subclassed from Fl_Table widgets do not
151  constitute a derivative work.
153  3. Static linking of applications and widgets to the
154  Fl_Table library does not constitute a derivative work
155  and does not require the author to provide source
156  code for the application or widget, use the shared
157  Fl_Table libraries, or link their applications or
158  widgets against a user-supplied version of Fl_Table.
160  If you link the application or widget to a modified
161  version of Fl_Table, then the changes to Fl_Table must be
162  provided under the terms of the LGPL in sections
163  1, 2, and 4.
165  4. You do not have to provide a copy of the Fl_Table license
166  with programs that are linked to the Fl_Table library, nor
167  do you have to identify the Fl_Table license in your
168  program or documentation as required by section 6
169  of the LGPL.
171  However, programs must still identify their use of Fl_Table.
172  The following example statement can be included in user
173  documentation to satisfy this requirement:
175  [program/widget] is based in part on the work of
176  the Fl_Table project http://seriss.com/people/erco/fltk/Fl_Table/
177  \endverbatim
180  */
181 class FL_EXPORT Fl_Table : public Fl_Group {
182 public:
183   /**
184    The context bit flags for Fl_Table related callbacks (eg. draw_cell(), callback(), etc)
185    */
186   enum TableContext {
187     CONTEXT_NONE       = 0,     ///< no known context
188     CONTEXT_STARTPAGE  = 0x01,  ///< before a page is redrawn
189     CONTEXT_ENDPAGE    = 0x02,  ///< after a page is redrawn
190     CONTEXT_ROW_HEADER = 0x04,  ///< in the row header
191     CONTEXT_COL_HEADER = 0x08,  ///< in the col header
192     CONTEXT_CELL       = 0x10,  ///< in one of the cells
193     CONTEXT_TABLE      = 0x20,  ///< in a dead zone of table
194     CONTEXT_RC_RESIZE  = 0x40   ///< column or row being resized
195   };
196   
197 private:
198   int _rows, _cols;     // total rows/cols
199   int _row_header_w;    // width of row header
200   int _col_header_h;    // height of column header
201   int _row_position;    // last row_position set (not necessarily == toprow!)
202   int _col_position;    // last col_position set (not necessarily == leftcol!)
203   
204   char _row_header;     // row header enabled?
205   char _col_header;     // col header enabled?
206   char _row_resize;     // row resizing enabled?
207   char _col_resize;     // col resizing enabled?
208   int _row_resize_min;  // row minimum resizing height (default=1)
209   int _col_resize_min;  // col minimum resizing width (default=1)
210   
211   // OPTIMIZATION: partial row/column redraw variables
212   int _redraw_toprow;
213   int _redraw_botrow;
214   int _redraw_leftcol;
215   int _redraw_rightcol;
216   Fl_Color _row_header_color;
217   Fl_Color _col_header_color;
218   
219   int _auto_drag;
220   int _selecting;
221   
222   // An STL-ish vector without templates
223   class FL_EXPORT IntVector {
224     int *arr;
225     unsigned int _size;
226     void init() {
227       arr = NULL;
228       _size = 0;
229     }
230     void copy(int *newarr, unsigned int newsize) {
231       size(newsize);
232       memcpy(arr, newarr, newsize * sizeof(int));
233     }
234   public:
235     IntVector() { init(); }                                     // CTOR
236     ~IntVector() { if ( arr ) free(arr); arr = NULL; }          // DTOR
237     IntVector(IntVector&o) { init(); copy(o.arr, o._size); }    // COPY CTOR
238     IntVector& operator=(IntVector&o) {                         // ASSIGN
239       init();
240       copy(o.arr, o._size);
241       return(*this);
242     }
243     int operator[](int x) const { return(arr[x]); }
244     int& operator[](int x) { return(arr[x]); }
245     unsigned int size() { return(_size); }
246     void size(unsigned int count) {
247       if ( count != _size ) {
248         arr = (int*)realloc(arr, count * sizeof(int));
249         _size = count;
250       }
251     }
252     int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
253     void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
254     int back() { return(arr[_size-1]); }
255   };
256   
257   IntVector _colwidths;                 // column widths in pixels
258   IntVector _rowheights;                // row heights in pixels
259   
260   Fl_Cursor _last_cursor;               // last mouse cursor before changed to 'resize' cursor
261   
262   // EVENT CALLBACK DATA
263   TableContext _callback_context;       // event context
264   int _callback_row, _callback_col;     // event row/col
265   
266   // handle() state variables.
267   //    Put here instead of local statics in handle(), so more
268   //    than one Fl_Table can exist without crosstalk between them.
269   //
270   int _resizing_col;                    // column being dragged
271   int _resizing_row;                    // row being dragged
272   int _dragging_x;                      // starting x position for horiz drag
273   int _dragging_y;                      // starting y position for vert drag
274   int _last_row;                        // last row we FL_PUSH'ed
275   
276   // Redraw single cell
277   void _redraw_cell(TableContext context, int R, int C);
278   
279   void _start_auto_drag();
280   void _stop_auto_drag();
281   void _auto_drag_cb();
282   static void _auto_drag_cb2(void *d);
283   
284 protected:
285   enum ResizeFlag {
286     RESIZE_NONE      = 0,
287     RESIZE_COL_LEFT  = 1,
288     RESIZE_COL_RIGHT = 2,
289     RESIZE_ROW_ABOVE = 3,
290     RESIZE_ROW_BELOW = 4
291   };
292   
293   int table_w, table_h;                         // table's virtual size (in pixels)
294   int toprow, botrow, leftcol, rightcol;        // four corners of viewable table
295   
296   // selection
297   int current_row, current_col;
298   int select_row, select_col;
299   
300   // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
301   int toprow_scrollpos;
302   int leftcol_scrollpos;
303   
304   // Dimensions
305   int tix, tiy, tiw, tih;                       // data table inner dimension xywh
306   int tox, toy, tow, toh;                       // data table outer dimension xywh
307   int wix, wiy, wiw, wih;                       // widget inner dimension xywh
308   
309   Fl_Scroll *table;                             // container for child fltk widgets (if any)
310   Fl_Scrollbar *vscrollbar;                     // vertical scrollbar
311   Fl_Scrollbar *hscrollbar;                     // horizontal scrollbar
312   
313   // Fltk
314   int handle(int e);                            // fltk handle() override
315   
316   // Class maintenance
317   void recalc_dimensions();
318   void table_resized();                         // table resized; recalc
319   void table_scrolled();                        // table scrolled; recalc
320   void get_bounds(TableContext context,         // return x/y/w/h bounds for context
321                   int &X, int &Y, int &W, int &H);
322   void change_cursor(Fl_Cursor newcursor);      // change mouse cursor to some other shape
323   TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
324   // find r/c given current x/y event
325   int find_cell(TableContext context,           // find cell's x/y/w/h given r/c
326                 int R, int C, int &X, int &Y, int &W, int &H);
327   int row_col_clamp(TableContext context, int &R, int &C);
328   // clamp r/c to known universe
329   
330   /**
331    Subclass should override this method to handle drawing the cells.
332    
333    This method will be called whenever the table is redrawn, once per cell.
334    
335    Only cells that are completely (or partially) visible will be told to draw.
336    
337    \p context will be one of the following:
338    
339    <table border=1>
340    <tr>
341    <td>\p Fl_Table::CONTEXT_STARTPAGE</td>
342    <td>When table, or parts of the table, are about to be redrawn.<br>
343        Use to initialize static data, such as font selections.<p>
344        R/C will be zero,<br>
345        X/Y/W/H will be the dimensions of the table's entire data area.<br>
346        (Useful for locking a database before accessing; see
347        also visible_cells())</td>
348    </tr><tr>
349    <td>\p Fl_Table::CONTEXT_ENDPAGE</td>
350    <td>When table has completed being redrawn.<br>
351        R/C will be zero, X/Y/W/H dimensions of table's data area.<br>
352        (Useful for unlocking a database after accessing)</td>
353    </tr><tr>
354    <td>\p Fl_Table::CONTEXT_ROW_HEADER</td>
355    <td>Whenever a row header cell needs to be drawn.<br>
356        R will be the row number of the header being redrawn,<br>
357        C will be zero,<br>
358        X/Y/W/H will be the fltk drawing area of the row header in the window </td>
359    </tr><tr>
360    <td>\p Fl_Table::CONTEXT_COL_HEADER</td>
361    <td>Whenever a column header cell needs to be drawn.<br>
362        R will be zero, <br>
363        C will be the column number of the header being redrawn,<br>
364        X/Y/W/H will be the fltk drawing area of the column header in the window </td>
365    </tr><tr>
366    <td>\p Fl_Table::CONTEXT_CELL</td>
367    <td>Whenever a data cell in the table needs to be drawn.<br>
368        R/C will be the row/column of the cell to be drawn,<br>
369        X/Y/W/H will be the fltk drawing area of the cell in the window </td>
370    </tr><tr>
371    <td>\p Fl_Table::CONTEXT_RC_RESIZE</td>
372    <td>Whenever table or row/column is resized or scrolled,
373        either interactively or via col_width() or row_height().<br>
374        R/C/X/Y/W/H will all be zero.
375        <p> 
376        Useful for fltk containers that need to resize or move
377        the child fltk widgets.</td>
378    </tr>
379    </table>
380    
381    \p row and \p col will be set to the row and column number
382    of the cell being drawn. In the case of row headers, \p col will be \a 0.
383    In the case of column headers, \p row will be \a 0.
384    
385    <tt>x/y/w/h</tt> will be the position and dimensions of where the cell
386    should be drawn.
387    
388    In the case of custom widgets, a minimal draw_cell() override might
389    look like the following. With custom widgets it is up to the caller to handle
390    drawing everything within the dimensions of the cell, including handling the
391    selection color.  Note all clipping must be handled as well; this allows drawing
392    outside the dimensions of the cell if so desired for 'custom effects'.
393    
394    \code
395    // This is called whenever Fl_Table wants you to draw a cell
396    void MyTable::draw_cell(TableContext context, int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0) {
397        static char s[40];
398        sprintf(s, "%d/%d", R, C);              // text for each cell
399        switch ( context ) {
400            case CONTEXT_STARTPAGE:             // Fl_Table telling us its starting to draw page
401                fl_font(FL_HELVETICA, 16);
402                return;
403        
404            case CONTEXT_ROW_HEADER:            // Fl_Table telling us it's draw row/col headers
405            case CONTEXT_COL_HEADER:
406                fl_push_clip(X, Y, W, H);
407                {
408                    fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color());
409                    fl_color(FL_BLACK);
410                    fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
411                }
412                fl_pop_clip();
413                return;
414            
415            case CONTEXT_CELL:                  // Fl_Table telling us to draw cells
416                fl_push_clip(X, Y, W, H);
417                {
418                    // BG COLOR
419                    fl_color( row_selected(R) ? selection_color() : FL_WHITE);
420                    fl_rectf(X, Y, W, H);
421                    
422                    // TEXT
423                    fl_color(FL_BLACK);
424                    fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
425                    
426                    // BORDER
427                    fl_color(FL_LIGHT2);
428                    fl_rect(X, Y, W, H);
429                }
430                fl_pop_clip();
431                return;
432            
433        default:
434            return;
435        }
436        //NOTREACHED
437    }
438    \endcode
439    */
440   virtual void draw_cell(TableContext context, int R=0, int C=0, 
441                          int X=0, int Y=0, int W=0, int H=0)
442   { }                                           // overridden by deriving class
443   
444   long row_scroll_position(int row);            // find scroll position of row (in pixels)
445   long col_scroll_position(int col);            // find scroll position of col (in pixels)
446   
447   int is_fltk_container() {                     // does table contain fltk widgets?
448     return( Fl_Group::children() > 3 );         // (ie. more than box and 2 scrollbars?)
449   }
450   
451   static void scroll_cb(Fl_Widget*,void*);      // h/v scrollbar callback
452   
453   void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
454   
455   void redraw_range(int toprow, int botrow, int leftcol, int rightcol) {
456     if ( _redraw_toprow == -1 ) {
457       // Initialize redraw range
458       _redraw_toprow = toprow;
459       _redraw_botrow = botrow;
460       _redraw_leftcol = leftcol;
461       _redraw_rightcol = rightcol;
462     } else {
463       // Extend redraw range
464       if ( toprow < _redraw_toprow ) _redraw_toprow = toprow;
465       if ( botrow > _redraw_botrow ) _redraw_botrow = botrow;
466       if ( leftcol < _redraw_leftcol ) _redraw_leftcol = leftcol;
467       if ( rightcol > _redraw_rightcol ) _redraw_rightcol = rightcol;
468     }
469     
470     // Indicate partial redraw needed of some cells
471     damage(FL_DAMAGE_CHILD);
472   }
473   
474 public:
475   /**
476    The constructor for the Fl_Table.
477    This creates an empty table with no rows or columns,
478    with headers and row/column resize behavior disabled.
479    */
480   Fl_Table(int X, int Y, int W, int H, const char *l=0);
481   
482   /**
483    The destructor for the Fl_Table.
484    Destroys the table and its associated widgets.
485    */
486   ~Fl_Table();
487   
488   /**
489    Clears the table to zero rows, zero columns.
490    Same as rows(0); cols(0);
491    \see rows(int), cols(int)
492    */
493   virtual void clear() { rows(0); cols(0); }
494   
495   // \todo: add topline(), middleline(), bottomline()
496   
497   /**
498    Sets the kind of box drawn around the data table,
499    the default being FL_NO_BOX. Changing this value will cause the table
500    to redraw.
501    */
502   inline void table_box(Fl_Boxtype val) {
503     table->box(val);
504     table_resized();
505   }
506   
507   /**
508    Returns the current box type used for the data table.
509    */
510   inline Fl_Boxtype table_box( void ) {
511     return(table->box());
512   }
513   
514   /**
515    Sets the number of rows in the table, and the table is redrawn.
516    */
517   virtual void rows(int val);                   // set/get number of rows
518   
519   /**
520    Returns the number of rows in the table.
521    */
522   inline int rows() {
523     return(_rows);
524   }
525   
526   /**
527    Set the number of columns in the table and redraw.
528    */
529   virtual void cols(int val);                   // set/get number of columns
530   
531   /** 
532    Get the number of columns in the table.
533    */
534   inline int cols() {
535     return(_cols);
536   }
537   
538   /**
539    Returns the range of row and column numbers for all visible 
540    and partially visible cells in the table.
541    
542    These values can be used e.g. by your draw_cell() routine during
543    CONTEXT_STARTPAGE to figure out what cells are about to be redrawn
544    for the purposes of locking the data from a database before it's drawn.
545    
546    \code
547           leftcol             rightcol
548              :                   :
549    toprow .. .-------------------.
550              |                   |
551              |  V I S I B L E    |
552              |                   |
553              |    T A B L E      |
554              |                   |
555    botrow .. '-------------------`
556    \endcode
557    
558    e.g. in a table where the visible rows are 5-20, and the
559    visible columns are 100-120, then those variables would be:
560    
561    - toprow = 5
562    - botrow = 20
563    - leftcol = 100
564    - rightcol = 120
565    */
566   inline void visible_cells(int& r1, int& r2, int& c1, int& c2) {
567     r1 = toprow;
568     r2 = botrow;
569     c1 = leftcol;
570     c2 = rightcol;
571   } 
572   
573   /**
574    Returns 1 if someone is interactively resizing a row or column.
575    You can currently call this only from within your callback().
576    */
577   int is_interactive_resize() {
578     return(_resizing_row != -1 || _resizing_col != -1);
579   } 
580   
581   /**
582    Returns the current value of this flag.
583    */
584   inline int row_resize() {
585     return(_row_resize);
586   }
587   
588   /**
589    Allows/disallows row resizing by the user.
590    1=allow interactive resizing, 0=disallow interactive resizing.
591    Since interactive resizing is done via the row headers,
592    row_header() must also be enabled to allow resizing.
593    */   
594   void row_resize(int flag) {                   // enable row resizing
595     _row_resize = flag;
596   }
597   
598   /**
599    Returns the current value of this flag.
600    */
601   inline int col_resize() {
602     return(_col_resize);
603   }
604   /**
605    Allows/disallows column resizing by the user.
606    1=allow interactive resizing, 0=disallow interactive resizing.
607    Since interactive resizing is done via the column headers,
608    \p col_header() must also be enabled to allow resizing.
609    */
610   void col_resize(int flag) {                   // enable col resizing
611     _col_resize = flag;
612   }
613   
614   /**
615    Sets the current column minimum resize value.
616    This is used to prevent the user from interactively resizing
617    any column to be smaller than 'pixels'. Must be a value >=1.
618    */
619   inline int col_resize_min() {                 // column minimum resizing width
620     return(_col_resize_min);
621   }
622   
623   /**
624    Returns the current column minimum resize value.
625    */
626   void col_resize_min(int val) {
627     _col_resize_min = ( val < 1 ) ? 1 : val;
628   } 
629   
630   /**
631    Returns the current row minimum resize value.
632    */
633   inline int row_resize_min() {                 // column minimum resizing width
634     return(_row_resize_min);
635   }
636   
637   /**
638    Sets the current row minimum resize value.
639    This is used to prevent the user from interactively resizing
640    any row to be smaller than 'pixels'. Must be a value >=1.
641    */
642   void row_resize_min(int val) {
643     _row_resize_min = ( val < 1 ) ? 1 : val;
644   }
645   
646   /**
647    Returns the value of this flag.
648    */
649   inline int row_header() {                     // set/get row header enable flag
650     return(_row_header);
651   }
652   
653   /**
654    Enables/disables showing the row headers. 1=enabled, 0=disabled.
655    If changed, the table is redrawn.
656    */
657   void row_header(int flag) {
658     _row_header = flag;
659     table_resized();
660     redraw();
661   }
662   
663   /**
664    Returns if column headers are enabled or not.
665    */
666   inline int col_header() {                     // set/get col header enable flag
667     return(_col_header);
668   }
669   
670   /**
671    Enable or disable column headers.
672    If changed, the table is redrawn.
673    */
674   void col_header(int flag) {
675     _col_header = flag;
676     table_resized();
677     redraw();
678   }
679   
680   /**
681    Sets the height in pixels for column headers and redraws the table.
682    */
683   inline void col_header_height(int height) {   // set/get col header height
684     _col_header_h = height;
685     table_resized();
686     redraw();
687   }
688   
689   /**
690    Gets the column header height.
691    */
692   inline int col_header_height() {
693     return(_col_header_h);
694   }
695   
696   /**
697    Sets the row header width to n and causes the screen to redraw.
698    */
699   inline void row_header_width(int width) {     // set/get row header width
700     _row_header_w = width;
701     table_resized();
702     redraw();
703   }
704   
705   /**
706    Returns the current row header width (in pixels).
707    */
708   inline int row_header_width() {
709     return(_row_header_w);
710   }
711   
712   /**
713    Sets the row header color and causes the screen to redraw.
714    */
715   inline void row_header_color(Fl_Color val) {  // set/get row header color
716     _row_header_color = val;
717     redraw();
718   }
719   
720   /**
721    Returns the current row header color.
722    */
723   inline Fl_Color row_header_color() {
724     return(_row_header_color);
725   } 
726   
727   /**
728    Sets the color for column headers and redraws the table.
729    */
730   inline void col_header_color(Fl_Color val) {  // set/get col header color
731     _col_header_color = val;
732     redraw();
733   }
734   
735   /**
736    Gets the color for column headers.
737    */
738   inline Fl_Color col_header_color() {
739     return(_col_header_color);
740   }
741   
742   /**
743    Sets the height of the specified row in pixels,
744    and the table is redrawn.
745    callback() will be invoked with CONTEXT_RC_RESIZE
746    if the row's height was actually changed, and when() is FL_WHEN_CHANGED.
747    */
748   void row_height(int row, int height);         // set/get row height
749   
750   /**
751    Returns the current height of the specified row as a value in pixels.
752    */
753   inline int row_height(int row) {
754     return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]);
755   }
756   
757   /**
758    Sets the width of the specified column in pixels, and the table is redrawn.
759    callback() will be invoked with CONTEXT_RC_RESIZE
760    if the column's width was actually changed, and when() is FL_WHEN_CHANGED.
761    */   
762   void col_width(int col, int width);           // set/get a column's width
763   
764   /**
765    Returns the current width of the specified column in pixels.
766    */
767   inline int col_width(int col) {
768     return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]);
769   }
770   
771   /**
772    Convenience method to set the height of all rows to the
773    same value, in pixels. The screen is redrawn.
774    */
775   void row_height_all(int height) {             // set all row/col heights
776     for ( int r=0; r<rows(); r++ ) {
777       row_height(r, height);
778     }
779   }
780   
781   /**
782    Convenience method to set the width of all columns to the
783    same value, in pixels. The screen is redrawn.
784    */
785   void col_width_all(int width) {
786     for ( int c=0; c<cols(); c++ ) {
787       col_width(c, width);
788     }
789   }
790   
791   /**
792    Sets the row scroll position to 'row', and causes the screen to redraw.
793    */
794   void row_position(int row);                   // set/get table's current scroll position
795   
796   /** 
797    Sets the column scroll position to column 'col', and causes the screen to redraw.
798    */
799   void col_position(int col);
800   
801   /**
802    Returns the current row scroll position as a row number.
803    */
804   int row_position() {                          // current row position
805     return(_row_position);
806   }
807   
808   /**
809    Returns the current column scroll position as a column number.
810    */
811   int col_position() {                          // current col position
812     return(_col_position);
813   }
814   
815   /**
816    Sets which row should be at the top of the table,
817    scrolling as necessary, and the table is redrawn. If the table
818    cannot be scrolled that far, it is scrolled as far as possible.
819    */
820   inline void top_row(int row) {                // set/get top row (deprecated)
821     row_position(row);
822   }
823   
824   /**
825    Returns the current top row shown in the table.
826    This row may be partially obscured.
827    */
828   inline int top_row() {
829     return(row_position());
830   }
831   int is_selected(int r, int c);                // selected cell
832   void get_selection(int &row_top, int &col_left, int &row_bot, int &col_right);
833   void set_selection(int row_top, int col_left, int row_bot, int col_right);
834   int move_cursor(int R, int C);
835   
836   /**
837    Changes the size of the Fl_Table, causing it to redraw.
838    */
839   void resize(int X, int Y, int W, int H);      // fltk resize() override
840   void draw(void);                              // fltk draw() override
841   
842   // This crashes sortapp() during init.
843   //  void box(Fl_Boxtype val) {
844   //    Fl_Group::box(val);
845   //    if ( table ) {
846   //      resize(x(), y(), w(), h());
847   //    }
848   //  }
849   //  Fl_Boxtype box(void) const {
850   //    return(Fl_Group::box());
851   //  }
852   
853   // Child group
854   void init_sizes() {
855     table->init_sizes();
856     table->redraw();
857   }
858   void add(Fl_Widget& w) {
859     table->add(w);
860   }
861   void add(Fl_Widget* w) {
862     table->add(w);
863   }
864   void insert(Fl_Widget& w, int n) {
865     table->insert(w,n);
866   }
867   void insert(Fl_Widget& w, Fl_Widget* w2) {
868     table->insert(w,w2);
869   }
870   void remove(Fl_Widget& w) {
871     table->remove(w);
872   }
873   void begin() {
874     table->begin();
875   }
876   void end() {
877     table->end();
878     // HACK: Avoid showing Fl_Scroll; seems to erase screen
879     //       causing unnecessary flicker, even if its box() is FL_NO_BOX.
880     //
881     if ( table->children() > 2 ) {
882       table->show();
883     } else {
884       table->hide();
885     } 
886     Fl_Group::current(Fl_Group::parent());
887   }
888   Fl_Widget * const *array() {
889     return(table->array());
890   }
891   
892   /**
893    Returns the child widget by an index.
894    
895    When using the Fl_Table as a container for FLTK widgets, this method returns 
896    the widget pointer from the internal array of widgets in the container.
897    
898    Typically used in loops, eg:
899    \code
900    for ( int i=0; i<children(); i++ ) {
901      Fl_Widget *w = child(i);
902      [..]
903    }
904    \endcode
905    */
906   Fl_Widget *child(int n) const {
907     return(table->child(n));
908   }
909   
910   /**
911    Returns the number of children in the table.
912    
913    When using the Fl_Table as a container for FLTK widgets, this method returns 
914    how many child widgets the table has.
915    
916    \see child(int)
917    */
918   int children() const {
919     return(table->children()-2);    // -2: skip Fl_Scroll's h/v scrollbar widgets
920   }
921   int find(const Fl_Widget *w) const {
922     return(table->find(w));
923   }
924   int find(const Fl_Widget &w) const {
925     return(table->find(w));
926   } 
927   // CALLBACKS
928   
929   /**
930    * Returns the current row the event occurred on.
931    *
932    * This function should only be used from within the user's callback function
933    */
934   int callback_row() {
935     return(_callback_row);
936   }
937   
938   /**
939    * Returns the current column the event occurred on.
940    *
941    * This function should only be used from within the user's callback function
942    */
943   int callback_col() {
944     return(_callback_col);
945   }
946   
947   /**
948    * Returns the current 'table context'.
949    *
950    * This function should only be used from within the user's callback function
951    */
952   TableContext callback_context() {
953     return(_callback_context);
954   }
955   
956   void do_callback(TableContext context, int row, int col) {
957     _callback_context = context;
958     _callback_row = row;
959     _callback_col = col;
960     Fl_Widget::do_callback();
961   }
962   
963 #if FL_DOXYGEN
964   /**
965    The Fl_Widget::when() function is used to set a group of flags, determining
966    when the widget callback is called:
967    
968    <table border=1>
969    <tr>
970    <td>\p FL_WHEN_CHANGED</td>
971    <td>
972    callback() will be called when rows or columns are resized (interactively or 
973    via col_width() or row_height()), passing CONTEXT_RC_RESIZE via 
974    callback_context().
975    </td>
976    </tr><tr>
977    <td>\p FL_WHEN_RELEASE</td>
978    <td>
979    callback() will be called during FL_RELEASE events, such as when someone 
980    releases a mouse button somewhere on the table.
981    </td>
982    </tr>
983    </table>
984    
985    The callback() routine is sent a TableContext that indicates the context the 
986    event occurred in, such as in a cell, in a header, or elsewhere on the table.  
987    When an event occurs in a cell or header, callback_row() and 
988    callback_col() can be used to determine the row and column. The callback can 
989    also look at the regular fltk event values (ie. Fl::event() and Fl::button()) 
990    to determine what kind of event is occurring.
991    */
992   void when(Fl_When flags);
993 #endif
994   
995 #if FL_DOXYGEN
996   /**
997    Callbacks will be called depending on the setting of Fl_Widget::when().
998    
999    Callback functions should use the following functions to determine the 
1000    context/row/column:
1001    
1002    * Fl_Table::callback_row() returns current row
1003    * Fl_Table::callback_col() returns current column
1004    * Fl_Table::callback_context() returns current table context
1005    
1006    callback_row() and callback_col() will be set to the row and column number the 
1007    event occurred on. If someone clicked on a row header, \p col will be \a 0.  
1008    If someone clicked on a column header, \p row will be \a 0.
1009    
1010    callback_context() will return one of the following:
1011    
1012    <table border=1>
1013    <tr><td><tt>Fl_Table::CONTEXT_ROW_HEADER</tt></td>
1014    <td>Someone clicked on a row header. Excludes resizing.</td>
1015    </tr><tr>
1016    <td><tt>Fl_Table::CONTEXT_COL_HEADER</tt></td>
1017    <td>Someone clicked on a column header. Excludes resizing.</td>
1018    </tr><tr>
1019    <td><tt>Fl_Table::CONTEXT_CELL</tt></td>
1020    <td>
1021    Someone clicked on a cell.
1022    
1023    To receive callbacks for FL_RELEASE events, you must set
1024    when(FL_WHEN_RELEASE).
1025    </td>
1026    </tr><tr>
1027    <td><tt>Fl_Table::CONTEXT_RC_RESIZE</tt></td>
1028    <td>
1029    Someone is resizing rows/columns either interactively,
1030    or via the col_width() or row_height() API.
1031    
1032    Use is_interactive_resize()
1033    to determine interactive resizing.
1034    
1035    If resizing a column, R=0 and C=column being resized.
1036    
1037    If resizing a row, C=0 and R=row being resized.
1038    
1039    NOTE: To receive resize events, you must set when(FL_WHEN_CHANGED).
1040    </td>
1041    </tr>
1042    </table>
1043    
1044    \code
1045    class MyTable : public Fl_Table {
1046      [..]
1047    private:
1048      // Handle events that happen on the table
1049      void event_callback2() {
1050        int R = callback_row(),                         // row where event occurred
1051        C = callback_col();                             // column where event occurred
1052        TableContext context = callback_context();      // which part of table
1053        fprintf(stderr, "callback: Row=%d Col=%d Context=%d Event=%d\n",
1054                R, C, (int)context, (int)Fl::event());
1055      }
1056    
1057      // Actual static callback
1058      static void event_callback(Fl_Widget*, void* data) {
1059        MyTable *o = (MyTable*)data;
1060        o-&gt;event_callback2();
1061      }
1062      
1063    public:
1064      // Constructor
1065      MyTable() {
1066        [..]
1067        table.callback(&event_callback, (void*)this);   // setup callback
1068        table.when(FL_WHEN_CHANGED|FL_WHEN_RELEASE);    // when to call it
1069      }
1070    };
1071    \endcode
1072    */
1073   void callback(Fl_Widget*, void*);
1074 #endif
1077 #endif /*_FL_TABLE_H*/
1080 // End of "$Id: Fl_Table.H 8301 2011-01-22 22:40:11Z AlbrechtS $".