~hitmuri/vjpirate/trunk

« back to all changes in this revision

Viewing changes to os/mac/include/FL/Fl_Table.H

  • Committer: Florent Berthaut
  • Date: 2014-07-26 18:53:16 UTC
  • mfrom: (5.1.12 mac)
  • Revision ID: flo@localhost.localdomain-20140726185316-c2ucnwmgm5kij4e2
Merged mac branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
13
//
 
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.
 
18
//
 
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.
 
23
//
 
24
// Please report all bugs and problems to "erco at seriss dot com".
 
25
//
 
26
// TODO:
 
27
//    o Auto scroll during dragged selection
 
28
//    o Keyboard navigation (up/down/left/right arrow)
 
29
//
 
30
 
 
31
#ifndef _FL_TABLE_H
 
32
#define _FL_TABLE_H
 
33
 
 
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*/
 
41
 
 
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>
 
47
 
 
48
/**
 
49
 A table of widgets or other content.
 
50
 
 
51
 This is the base class for table widgets.
 
52
 
 
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.
 
57
 
 
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.
 
61
 
 
62
 This widget can be used in several ways:
 
63
 
 
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.
 
71
 
 
72
 \image html table-simple.png
 
73
 \image latex table-simple.png "table-simple example" width=6cm
 
74
 
 
75
 \image html table-as-container.png
 
76
 \image latex table-as-container.png "table-as-container example" width=6cm
 
77
 
 
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().
 
81
 
 
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.
 
85
 
 
86
 The following variables are available to classes deriving from Fl_Table:
 
87
 
 
88
 \image html table-dimensions.png
 
89
 \image latex table-dimensions.png "Fl_Table Dimensions" width=6cm
 
90
 
 
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>
 
95
 
 
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>
 
100
 
 
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>
 
105
 
 
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>
 
112
 
 
113
 CORE DEVELOPERS
 
114
 
 
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
 
117
 
 
118
 OTHER CONTRIBUTORS
 
119
 
 
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
 
124
 
 
125
 LICENSE
 
126
 
 
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.
 
130
 
 
131
 If used on its own, this is the license that applies:
 
132
 
 
133
 \verbatim 
 
134
 Fl_Table License
 
135
 December 16, 2002
 
136
 
 
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:
 
140
 
 
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.
 
145
 
 
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".
 
149
 
 
150
 2. Widgets that are subclassed from Fl_Table widgets do not
 
151
 constitute a derivative work.
 
152
 
 
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.
 
159
 
 
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.
 
164
 
 
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.
 
170
 
 
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:
 
174
 
 
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
 
178
 
 
179
 
 
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
 
1075
};
 
1076
 
 
1077
#endif /*_FL_TABLE_H*/
 
1078
 
 
1079
//
 
1080
// End of "$Id: Fl_Table.H 8301 2011-01-22 22:40:11Z AlbrechtS $".
 
1081
//