diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2009-11-14 13:05:37 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2009-11-14 13:05:37 +0000 |
| commit | fefa82e0b1e98d784455148940d84b454a128aad (patch) | |
| tree | 9d888cb9bc402708e0ad035a1c55d4b7703376a4 /FL/Fl_Table.H | |
| parent | 1238d1576b8e2bc15c097b23ebe0fdc4d3cdb527 (diff) | |
Adding Gerg's Fl_Table widget to FLTK 1.3 with kind permission. Documentation not yet added Support for both Visual Studio IDE's not yet added.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6929 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'FL/Fl_Table.H')
| -rw-r--r-- | FL/Fl_Table.H | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/FL/Fl_Table.H b/FL/Fl_Table.H new file mode 100644 index 000000000..3dfc18400 --- /dev/null +++ b/FL/Fl_Table.H @@ -0,0 +1,451 @@ +// +// Fl_Table -- A table widget +// +// Copyright 2002 by Greg Ercolano. +// Copyright (c) 2004 O'ksi'D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems to "erco at seriss dot com". +// +// TODO: +// o Auto scroll during dragged selection +// o Keyboard navigation (up/down/left/right arrow) +// + +#ifndef _FL_TABLE_H +#define _FL_TABLE_H + +#include <sys/types.h> +#include <string.h> // memcpy +#ifdef _WIN32 +#include <malloc.h> // WINDOWS: malloc/realloc +#else /*_WIN32*/ +#include <stdlib.h> // UNIX: malloc/realloc +#endif /*_WIN32*/ + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Scroll.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Scrollbar.H> + +class Fl_Table : public Fl_Group { +public: + enum TableContext { + CONTEXT_NONE = 0, + CONTEXT_STARTPAGE = 0x01, // before a page is redrawn + CONTEXT_ENDPAGE = 0x02, // after a page is redrawn + CONTEXT_ROW_HEADER = 0x04, // in the row header + CONTEXT_COL_HEADER = 0x08, // in the col header + CONTEXT_CELL = 0x10, // in one of the cells + CONTEXT_TABLE = 0x20, // in the table + CONTEXT_RC_RESIZE = 0x40 // column or row being resized + }; + +private: + int _rows, _cols; // total rows/cols + int _row_header_w; // width of row header + int _col_header_h; // height of column header + int _row_position; // last row_position set (not necessarily == toprow!) + int _col_position; // last col_position set (not necessarily == leftcol!) + + char _row_header; // row header enabled? + char _col_header; // col header enabled? + char _row_resize; // row resizing enabled? + char _col_resize; // col resizing enabled? + int _row_resize_min; // row minimum resizing height (default=1) + int _col_resize_min; // col minimum resizing width (default=1) + + // OPTIMIZATION: partial row/column redraw variables + int _redraw_toprow; + int _redraw_botrow; + int _redraw_leftcol; + int _redraw_rightcol; + Fl_Color _row_header_color; + Fl_Color _col_header_color; + + int _auto_drag; + int _selecting; + + // An STL-ish vector without templates + class IntVector { + int *arr; + unsigned int _size; + void init() { + arr = NULL; + _size = 0; + } + void copy(int *newarr, unsigned int newsize) { + size(newsize); + memcpy(arr, newarr, newsize * sizeof(int)); + } + public: + IntVector() { init(); } // CTOR + ~IntVector() { if ( arr ) free(arr); arr = NULL; } // DTOR + IntVector(IntVector&o) { init(); copy(o.arr, o._size); } // COPY CTOR + IntVector& operator=(IntVector&o) { // ASSIGN + init(); + copy(o.arr, o._size); + return(*this); + } + int operator[](int x) const { return(arr[x]); } + int& operator[](int x) { return(arr[x]); } + unsigned int size() { return(_size); } + void size(unsigned int count) { + if ( count != _size ) { + arr = (int*)realloc(arr, count * sizeof(int)); + _size = count; + } + } + int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); } + void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; } + int back() { return(arr[_size-1]); } + }; + + IntVector _colwidths; // column widths in pixels + IntVector _rowheights; // row heights in pixels + + Fl_Cursor _last_cursor; // last mouse cursor before changed to 'resize' cursor + + // EVENT CALLBACK DATA + TableContext _callback_context; // event context + int _callback_row, _callback_col; // event row/col + + // handle() state variables. + // Put here instead of local statics in handle(), so more + // than one Fl_Table can exist without crosstalk between them. + // + int _resizing_col; // column being dragged + int _resizing_row; // row being dragged + int _dragging_x; // starting x position for horiz drag + int _dragging_y; // starting y position for vert drag + int _last_row; // last row we FL_PUSH'ed + + // Redraw single cell + void _redraw_cell(TableContext context, int R, int C); + + void _start_auto_drag(); + void _stop_auto_drag(); + void _auto_drag_cb(); + static void _auto_drag_cb2(void *d); + +protected: + enum ResizeFlag { + RESIZE_NONE = 0, + RESIZE_COL_LEFT = 1, + RESIZE_COL_RIGHT = 2, + RESIZE_ROW_ABOVE = 3, + RESIZE_ROW_BELOW = 4 + }; + + int table_w, table_h; // table's virtual size (in pixels) + int toprow, botrow, leftcol, rightcol; // four corners of viewable table + + // selection + int current_row, current_col; + int select_row, select_col; + + // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol + int toprow_scrollpos; + int leftcol_scrollpos; + + // Dimensions + int tix, tiy, tiw, tih; // data table inner dimension xywh + int tox, toy, tow, toh; // data table outer dimension xywh + int wix, wiy, wiw, wih; // widget inner dimension xywh + + Fl_Scroll *table; // container for child fltk widgets (if any) + Fl_Scrollbar *vscrollbar; // vertical scrollbar + Fl_Scrollbar *hscrollbar; // horizontal scrollbar + + // Fltk + int handle(int e); // fltk handle() override + + // Class maintenance + void recalc_dimensions(); + void table_resized(); // table resized; recalc + void table_scrolled(); // table scrolled; recalc + void get_bounds(TableContext context, // return x/y/w/h bounds for context + int &X, int &Y, int &W, int &H); + void change_cursor(Fl_Cursor newcursor); // change mouse cursor to some other shape + TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag); + // find r/c given current x/y event + int find_cell(TableContext context, // find cell's x/y/w/h given r/c + int R, int C, int &X, int &Y, int &W, int &H); + int row_col_clamp(TableContext context, int &R, int &C); + // clamp r/c to known universe + + // Called to draw cells + virtual void draw_cell(TableContext context, int R=0, int C=0, + int X=0, int Y=0, int W=0, int H=0) + { } // overridden by deriving class + + long row_scroll_position(int row); // find scroll position of row (in pixels) + long col_scroll_position(int col); // find scroll position of col (in pixels) + + int is_fltk_container() { // does table contain fltk widgets? + return( Fl_Group::children() > 3 ); // (ie. more than box and 2 scrollbars?) + } + + static void scroll_cb(Fl_Widget*,void*); // h/v scrollbar callback + + void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0); + + void redraw_range(int toprow, int botrow, int leftcol, int rightcol) { + if ( _redraw_toprow == -1 ) { + // Initialize redraw range + _redraw_toprow = toprow; + _redraw_botrow = botrow; + _redraw_leftcol = leftcol; + _redraw_rightcol = rightcol; + } else { + // Extend redraw range + if ( toprow < _redraw_toprow ) _redraw_toprow = toprow; + if ( botrow > _redraw_botrow ) _redraw_botrow = botrow; + if ( leftcol < _redraw_leftcol ) _redraw_leftcol = leftcol; + if ( rightcol > _redraw_rightcol ) _redraw_rightcol = rightcol; + } + + // Indicate partial redraw needed of some cells + damage(FL_DAMAGE_CHILD); + } + +public: + Fl_Table(int X, int Y, int W, int H, const char *l=0); + ~Fl_Table(); + + virtual void clear() { rows(0); cols(0); } + + // topline() + // middleline() + // bottomline() + + inline void table_box(Fl_Boxtype val) { + table->box(val); + table_resized(); + } + inline Fl_Boxtype table_box( void ) { + return(table->box()); + } + virtual void rows(int val); // set/get number of rows + inline int rows() { + return(_rows); + } + virtual void cols(int val); // set/get number of columns + inline int cols() { + return(_cols); + } + inline void visible_cells(int& r1, int& r2, int& c1, int& c2) { + r1 = toprow; + r2 = botrow; + c1 = leftcol; + c2 = rightcol; + } + // Interactive resizing happening? + int is_interactive_resize() { + return(_resizing_row != -1 || _resizing_col != -1); + } + inline int row_resize() { + return(_row_resize); + } + void row_resize(int flag) { // enable row resizing + _row_resize = flag; + } + inline int col_resize() { + return(_col_resize); + } + void col_resize(int flag) { // enable col resizing + _col_resize = flag; + } + inline int col_resize_min() { // column minimum resizing width + return(_col_resize_min); + } + void col_resize_min(int val) { + _col_resize_min = ( val < 1 ) ? 1 : val; + } + inline int row_resize_min() { // column minimum resizing width + return(_row_resize_min); + } + void row_resize_min(int val) { + _row_resize_min = ( val < 1 ) ? 1 : val; + } + inline int row_header() { // set/get row header enable flag + return(_row_header); + } + void row_header(int flag) { + _row_header = flag; + table_resized(); + redraw(); + } + inline int col_header() { // set/get col header enable flag + return(_col_header); + } + void col_header(int flag) { + _col_header = flag; + table_resized(); + redraw(); + } + inline void col_header_height(int height) { // set/get col header height + _col_header_h = height; + table_resized(); + redraw(); + } + inline int col_header_height() { + return(_col_header_h); + } + inline void row_header_width(int width) { // set/get row header width + _row_header_w = width; + table_resized(); + redraw(); + } + inline int row_header_width() { + return(_row_header_w); + } + inline void row_header_color(Fl_Color val) { // set/get row header color + _row_header_color = val; + redraw(); + } + inline Fl_Color row_header_color() { + return(_row_header_color); + } + inline void col_header_color(Fl_Color val) { // set/get col header color + _col_header_color = val; + redraw(); + } + inline Fl_Color col_header_color() { + return(_col_header_color); + } + void row_height(int row, int height); // set/get row height + inline int row_height(int row) { + return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]); + } + void col_width(int col, int width); // set/get a column's width + inline int col_width(int col) { + return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]); + } + void row_height_all(int height) { // set all row/col heights + for ( int r=0; r<rows(); r++ ) { + row_height(r, height); + } + } + void col_width_all(int width) { + for ( int c=0; c<cols(); c++ ) { + col_width(c, width); + } + } + void row_position(int row); // set/get table's current scroll position + void col_position(int col); + int row_position() { // current row position + return(_row_position); + } + int col_position() { // current col position + return(_col_position); + } + inline void top_row(int row) { // set/get top row (deprecated) + row_position(row); + } + inline int top_row() { + return(row_position()); + } + int is_selected(int r, int c); // selected cell + void get_selection(int& s_top, int& s_left, int& s_bottom, int& s_right); + void set_selection(int s_top, int s_left, int s_bottom, int s_right); + int move_cursor(int R, int C); + + void resize(int X, int Y, int W, int H); // fltk resize() override + void draw(void); // fltk draw() override + +// This crashes sortapp() during init. +// void box(Fl_Boxtype val) { +// Fl_Group::box(val); +// if ( table ) { +// resize(x(), y(), w(), h()); +// } +// } +// Fl_Boxtype box(void) const { +// return(Fl_Group::box()); +// } + + // Child group + void init_sizes() { + table->init_sizes(); + table->redraw(); + } + void add(Fl_Widget& w) { + table->add(w); + } + void add(Fl_Widget* w) { + table->add(w); + } + void insert(Fl_Widget& w, int n) { + table->insert(w,n); + } + void insert(Fl_Widget& w, Fl_Widget* w2) { + table->insert(w,w2); + } + void remove(Fl_Widget& w) { + table->remove(w); + } + void begin() { + table->begin(); + } + void end() { + table->end(); + // HACK: Avoid showing Fl_Scroll; seems to erase screen + // causing unnecessary flicker, even if its box() is FL_NO_BOX. + // + if ( table->children() > 2 ) { + table->show(); + } else { + table->hide(); + } + Fl_Group::current((Fl_Group*)(Fl_Group::parent())); + } + Fl_Widget * const *array() { + return(table->array()); + } + Fl_Widget *child(int n) const { + return(table->child(n)); + } + int children() const { + return(table->children()-2); // -2: skip Fl_Scroll's h/v scrollbar widgets + } + int find(const Fl_Widget *w) const { + return(table->find(w)); + } + int find(const Fl_Widget &w) const { + return(table->find(w)); + } + // CALLBACKS + int callback_row() { + return(_callback_row); + } + int callback_col() { + return(_callback_col); + } + TableContext callback_context() { + return(_callback_context); + } + void do_callback(TableContext context, int row, int col) { + _callback_context = context; + _callback_row = row; + _callback_col = col; + Fl_Widget::do_callback(); + } +}; + +#endif /*_FL_TABLE_H*/ |
