edelib  2.1.0
TableBase.h
1 //
2 // TableBase -- A table widget
3 //
4 // Copyright 2002 by Greg Ercolano.
5 // Copyright (c) 2004 O'ksi'D
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 // USA.
21 //
22 // Please report all bugs and problems to "erco at seriss dot com".
23 //
24 // TODO:
25 // o Auto scroll during dragged selection
26 // o Keyboard navigation (up/down/left/right arrow)
27 //
28 
29 #ifndef __EDELIB_TABLEBASE_H__
30 #define __EDELIB_TABLEBASE_H__
31 
32 #include "edelib-global.h"
33 
34 #include <sys/types.h>
35 #include <string.h> // memcpy
36 
37 #ifdef _WIN32
38 # include <malloc.h> // WINDOWS: malloc/realloc
39 #else
40 # include <stdlib.h> // UNIX: malloc/realloc
41 #endif
42 
43 #include <FL/Fl.H>
44 #include <FL/Fl_Group.H>
45 #include <FL/Fl_Scroll.H>
46 #include <FL/Fl_Box.H>
47 #include <FL/Fl_Scrollbar.H>
48 
49 EDELIB_NS_BEGIN
50 
166 class EDELIB_API TableBase : public Fl_Group {
167 public:
173  CONTEXT_NONE = 0,
174  CONTEXT_STARTPAGE = 0x01,
175  CONTEXT_ENDPAGE = 0x02,
176  CONTEXT_ROW_HEADER = 0x04,
177  CONTEXT_COL_HEADER = 0x08,
178  CONTEXT_CELL = 0x10,
179  CONTEXT_TABLE = 0x20,
180  CONTEXT_RC_RESIZE = 0x40
181  };
182 
183 private:
184  int _rows, _cols, // total rows/cols
185  _row_header_w, // width of row header
186  _col_header_h, // height of column header
187  _row_position, // last row_position set (not necessarily == toprow!)
188  _col_position; // last col_position set (not necessarily == leftcol!)
189 
190  char _row_header, // row header enabled?
191  _col_header, // col header enabled?
192  _row_resize, // row resizing enabled?
193  _col_resize; // col resizing enabled?
194  int
195  _row_resize_min, // row minimum resizing height (default=1)
196  _col_resize_min; // col minimum resizing width (default=1)
197 
198  // OPTIMIZATION: partial row/column redraw variables
199  int _redraw_toprow, _redraw_botrow,
200  _redraw_leftcol, _redraw_rightcol;
201 
202  Fl_Color _row_header_color,
203  _col_header_color;
204 
205  int _auto_drag;
206  int _selecting;
207 
212  class IntVector {
213  private:
214  int *arr;
215  unsigned int _size;
216 
217  void init() { arr = NULL; _size = 0; }
218  void copy(int *newarr, unsigned int newsize) { size(newsize); memcpy(arr, newarr, newsize * sizeof(int)); }
219  public:
221  IntVector() { init(); }
223  ~IntVector() { if ( arr ) free(arr); arr = NULL; }
225  IntVector(IntVector&o) { init(); copy(o.arr, o._size); }
227  IntVector& operator=(IntVector&o) { init(); copy(o.arr, o._size); return(*this); }
229  int operator[](int x) const { return(arr[x]); }
231  int& operator[](int x) { return(arr[x]); }
233  unsigned int size() { return(_size); }
235  void size(unsigned int count) {
236  if ( count != _size )
237  { arr = (int*)realloc(arr, count * sizeof(int)); _size = count; }
238  }
240  int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); }
242  void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; }
244  int back() { return(arr[_size-1]); }
245  };
246 
247  IntVector
248  _colwidths, // column widths in pixels
249  _rowheights; // row heights in pixels
250 
251  Fl_Cursor _last_cursor; // last mouse cursor before changed to 'resize' cursor
252 
253  // EVENT CALLBACK DATA
254  TableContext _callback_context; // event context
255  int _callback_row, _callback_col; // event row/col
256 
257  // handle() state variables.
258  // Put here instead of local statics in handle(), so more
259  // than one TableBase can exist without crosstalk between them.
260  //
261  int _resizing_col, // column being dragged
262  _resizing_row, // row being dragged
263  _dragging_x, // starting x position for horiz drag
264  _dragging_y, // starting y position for vert drag
265  _last_row; // last row we FL_PUSH'ed
266 
267  // Redraw single cell
268  void _redraw_cell(TableContext context, int R, int C);
269 
270  void _start_auto_drag();
271  void _stop_auto_drag();
272  void _auto_drag_cb();
273  static void _auto_drag_cb2(void *d);
274 
275 
276 protected:
277 #ifndef SKIP_DOCS
278  enum ResizeFlag {
279  RESIZE_NONE = 0,
280  RESIZE_COL_LEFT = 1,
281  RESIZE_COL_RIGHT = 2,
282  RESIZE_ROW_ABOVE = 3,
283  RESIZE_ROW_BELOW = 4
284  };
285 
286  int table_w, table_h; // table's virtual size (in pixels)
287  int toprow, botrow, // four corners of viewable table
288  leftcol, rightcol;
289 
290  // selection
291  int current_row, current_col;
292  int select_row, select_col;
293 
294  // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol
295  int toprow_scrollpos,
296  leftcol_scrollpos;
297 
298  // Dimensions
299  int tix, tiy, tiw, tih, // data table inner dimension xywh
300  tox, toy, tow, toh, // data table outer dimension xywh
301  wix, wiy, wiw, wih; // widget inner dimension xywh
302 
303  Fl_Scroll *table; // container for child fltk widgets (if any)
304  Fl_Scrollbar *vscrollbar, // vertical scrollbar
305  *hscrollbar; // horizontal scrollbar
306 
307  // Fltk
308  int handle(int e); // fltk handle() override
309 
310  // Class maintenance
311  void recalc_dimensions();
312  void table_resized(); // table resized; recalc
313  void table_scrolled(); // table scrolled; recalc
314  void get_bounds(TableContext context, // return x/y/w/h bounds for context
315  int &X, int &Y, int &W, int &H);
316  void change_cursor(Fl_Cursor newcursor); // change mouse cursor to some other shape
317  TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag);
318  // find r/c given current x/y event
319  int find_cell(TableContext context, // find cell's x/y/w/h given r/c
320  int R, int C, int &X, int &Y, int &W, int &H);
321  int row_col_clamp(TableContext context, int &R, int &C);
322  // clamp r/c to known universe
323 
324  // Called to draw cells
325  virtual void draw_cell(TableContext context, int R=0, int C=0,
326  int X=0, int Y=0, int W=0, int H=0)
327  { } // overridden by deriving class
328 
329  long row_scroll_position(int row); // find scroll position of row (in pixels)
330  long col_scroll_position(int col); // find scroll position of col (in pixels)
331 
332  int is_fltk_container() // does table contain fltk widgets?
333  { return( Fl_Group::children() > 3 ); } // (ie. more than box and 2 scrollbars?)
334 
335  static void scroll_cb(Fl_Widget*,void*); // h/v scrollbar callback
336 
337  void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0);
338 
339  void redraw_range(int trow, int brow, int lcol, int rcol) {
340  if ( _redraw_toprow == -1 ) {
341  // Initialize redraw range
342  _redraw_toprow = trow;
343  _redraw_botrow = brow;
344  _redraw_leftcol = lcol;
345  _redraw_rightcol = rcol;
346  } else {
347  // Extend redraw range
348  if ( trow < _redraw_toprow ) _redraw_toprow = trow;
349  if ( brow > _redraw_botrow ) _redraw_botrow = brow;
350  if ( lcol < _redraw_leftcol ) _redraw_leftcol = lcol;
351  if ( rcol > _redraw_rightcol ) _redraw_rightcol = rcol;
352  }
353 
354  // Indicate partial redraw needed of some cells
355  damage(FL_DAMAGE_CHILD);
356  }
357 
358  // TODO: maybe _redraw_cell() put protected directly?
359  void redraw_cell(TableContext context, int R, int C) { _redraw_cell(context, R, C); }
360 #endif
361 
362 public:
367  TableBase(int X, int Y, int W, int H, const char *l=0);
368 
372  ~TableBase();
373 
377  virtual void clear() { rows(0); cols(0); }
378 
383  inline void table_box(Fl_Boxtype val) { table->box(val); table_resized(); }
384 
388  inline Fl_Boxtype table_box( void ) { return(table->box()); }
389 
393  virtual void rows(int val);
394 
398  inline int rows() { return _rows; }
399 
403  virtual void cols(int val);
404 
408  inline int cols() { return _cols; }
409 
417  inline void visible_cells(int& r1, int& r2, int& c1, int& c2) { r1 = toprow; r2 = botrow; c1 = leftcol; c2 = rightcol; }
418 
422  int is_interactive_resize() { return (_resizing_row != -1 || _resizing_col != -1); }
423 
428  void row_resize(int flag) { _row_resize = flag; }
429 
433  inline int row_resize() { return _row_resize; }
434 
439  void col_resize(int flag) { _col_resize = flag; }
440 
444  inline int col_resize() { return _col_resize; }
445 
449  void col_resize_min(int val) { _col_resize_min = ( val < 1 ) ? 1 : val; }
450 
454  inline int col_resize_min() { return _col_resize_min; }
455 
459  void row_resize_min(int val) { _row_resize_min = ( val < 1 ) ? 1 : val; }
460 
464  inline int row_resize_min() { return _row_resize_min; }
465 
470  void row_header(int flag) { _row_header = flag; table_resized(); redraw(); }
471 
475  inline int row_header() { return _row_header; }
476 
481  void col_header(int flag) { _col_header = flag; table_resized(); redraw(); }
482 
486  inline int col_header() { return(_col_header); }
487 
491  inline void col_header_height(int height) { _col_header_h = height; table_resized(); redraw(); }
492 
496  inline int col_header_height() { return _col_header_h; }
497 
501  inline void row_header_width(int width) { _row_header_w = width; table_resized(); redraw(); }
502 
506  inline int row_header_width() { return _row_header_w; }
507 
511  inline void row_header_color(Fl_Color val) { _row_header_color = val; redraw(); }
512 
516  inline Fl_Color row_header_color() { return _row_header_color; }
517 
521  inline void col_header_color(Fl_Color val) { _col_header_color = val; redraw(); }
522 
526  inline Fl_Color col_header_color() { return _col_header_color; }
527 
532  void row_height(int row, int height);
533 
537  inline int row_height(int row) { return ((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]); }
538 
543  void col_width(int col, int width);
544 
548  inline int col_width(int col) { return ((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]); }
549 
553  void row_height_all(int height) { for ( int r=0; r<rows(); r++ ) row_height(r, height); }
554 
558  void col_width_all(int width) { for ( int c=0; c<cols(); c++ ) col_width(c, width); }
559 
563  void row_position(int row);
564 
568  int row_position() { return _row_position; }
569 
573  void col_position(int col);
574 
578  int col_position() { return _col_position; }
579 
583  inline void top_row(int row) { row_position(row); }
584 
588  inline int top_row() { return row_position(); }
589 
593  int is_selected(int r, int c);
594 
601  void get_selection(int& s_top, int& s_left, int& s_bottom, int& s_right);
602 
609  void set_selection(int s_top, int s_left, int s_bottom, int s_right);
610 
616  int move_cursor(int R, int C);
617 
621  void resize(int X, int Y, int W, int H);
622 
626  void draw(void);
627 
631  void init_sizes() { table->init_sizes(); table->redraw(); }
632 
636  void add(Fl_Widget& widget) { table->add(widget); }
637 
641  void add(Fl_Widget* widget) { table->add(widget); }
642 
646  void insert(Fl_Widget& widget, int n) { table->insert(widget,n); }
647 
651  void insert(Fl_Widget& widget1, Fl_Widget* widget2) { table->insert(widget1,widget2); }
652 
656  void remove(Fl_Widget& widget) { table->remove(widget); }
657 
661  void begin() { table->begin(); }
662 
666  void end() {
667  table->end();
668 
669  // HACK: Avoid showing Fl_Scroll; seems to erase screen
670  // causing unnecessary flicker, even if its box() is FL_NO_BOX.
671  //
672  if ( table->children() > 2 )
673  table->show();
674  else
675  table->hide();
676 
677  Fl_Group::current((Fl_Group*)(Fl_Group::parent()));
678  }
679 
680 #ifndef SKIP_DOCS
681  Fl_Widget * const *array() { return table->array(); }
682  Fl_Widget *child(int n) const { return table->child(n); }
683  int children() const { return table->children()-2; } // -2: skip Fl_Scroll's h/v scrollbar widgets
684  int find(const Fl_Widget *widget) const { return table->find(widget); }
685  int find(const Fl_Widget &widget) const { return table->find(widget); }
686 #endif
687 
692  int callback_row() { return _callback_row; }
693 
698  int callback_col() { return _callback_col; }
699 
703  TableContext callback_context() { return _callback_context; }
704 
708  void do_callback(TableContext context, int row, int col) {
709  _callback_context = context;
710  _callback_row = row;
711  _callback_col = col;
712  Fl_Widget::do_callback();
713  }
714 };
715 
716 EDELIB_NS_END
717 #endif
Fl_Color col_header_color()
Definition: TableBase.h:526
int row_header()
Definition: TableBase.h:475
A base class for table widgets.
Definition: TableBase.h:166
void begin()
Definition: TableBase.h:661
void col_header_color(Fl_Color val)
Definition: TableBase.h:521
int is_interactive_resize()
Definition: TableBase.h:422
void add(Fl_Widget &widget)
Definition: TableBase.h:636
int col_header()
Definition: TableBase.h:486
int row_position()
Definition: TableBase.h:568
void do_callback(TableContext context, int row, int col)
Definition: TableBase.h:708
int row_resize_min()
Definition: TableBase.h:464
int col_resize_min()
Definition: TableBase.h:454
void row_resize(int flag)
Definition: TableBase.h:428
int row_resize()
Definition: TableBase.h:433
void insert(Fl_Widget &widget, int n)
Definition: TableBase.h:646
void row_resize_min(int val)
Definition: TableBase.h:459
int col_resize()
Definition: TableBase.h:444
void col_resize_min(int val)
Definition: TableBase.h:449
void table_box(Fl_Boxtype val)
Definition: TableBase.h:383
int callback_row()
Definition: TableBase.h:692
void row_header_color(Fl_Color val)
Definition: TableBase.h:511
int cols()
Definition: TableBase.h:408
int col_header_height()
Definition: TableBase.h:496
int callback_col()
Definition: TableBase.h:698
void top_row(int row)
Definition: TableBase.h:583
TableContext
What happened in table callback.
Definition: TableBase.h:172
void add(Fl_Widget *widget)
Definition: TableBase.h:641
void row_height_all(int height)
Definition: TableBase.h:553
int col_width(int col)
Definition: TableBase.h:548
void row_header_width(int width)
Definition: TableBase.h:501
int top_row()
Definition: TableBase.h:588
void insert(Fl_Widget &widget1, Fl_Widget *widget2)
Definition: TableBase.h:651
void init_sizes()
Definition: TableBase.h:631
int col_position()
Definition: TableBase.h:578
void end()
Definition: TableBase.h:666
TableContext callback_context()
Definition: TableBase.h:703
virtual void clear()
Definition: TableBase.h:377
int rows()
Definition: TableBase.h:398
int row_header_width()
Definition: TableBase.h:506
void col_header(int flag)
Definition: TableBase.h:481
Fl_Boxtype table_box(void)
Definition: TableBase.h:388
void col_resize(int flag)
Definition: TableBase.h:439
Fl_Color row_header_color()
Definition: TableBase.h:516
void col_width_all(int width)
Definition: TableBase.h:558
void col_header_height(int height)
Definition: TableBase.h:491
void visible_cells(int &r1, int &r2, int &c1, int &c2)
Definition: TableBase.h:417
int row_height(int row)
Definition: TableBase.h:537
void row_header(int flag)
Definition: TableBase.h:470