edelib 1.0

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

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:
172 enum TableContext {
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