summaryrefslogtreecommitdiff
path: root/FL
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2009-11-14 13:05:37 +0000
committerMatthias Melcher <fltk@matthiasm.com>2009-11-14 13:05:37 +0000
commitfefa82e0b1e98d784455148940d84b454a128aad (patch)
tree9d888cb9bc402708e0ad035a1c55d4b7703376a4 /FL
parent1238d1576b8e2bc15c097b23ebe0fdc4d3cdb527 (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')
-rw-r--r--FL/Fl_Table.H451
-rw-r--r--FL/Fl_Table_Row.H150
2 files changed, 601 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*/
diff --git a/FL/Fl_Table_Row.H b/FL/Fl_Table_Row.H
new file mode 100644
index 000000000..e7b38a48d
--- /dev/null
+++ b/FL/Fl_Table_Row.H
@@ -0,0 +1,150 @@
+#ifndef _FL_TABLE_ROW_H
+#define _FL_TABLE_ROW_H
+
+//
+// Fl_Table_Row -- A row oriented table widget
+//
+// A class specializing in a table of rows.
+// Handles row-specific selection behavior.
+//
+// Copyright 2002 by Greg Ercolano.
+//
+// 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".
+//
+//
+
+#include "Fl_Table.H"
+
+class Fl_Table_Row : public Fl_Table {
+public:
+ enum TableRowSelectMode {
+ SELECT_NONE, // no selection allowed
+ SELECT_SINGLE, // single row selection
+ SELECT_MULTI // multiple row selection (default)
+ };
+private:
+ // An STL-ish vector without templates
+ class CharVector {
+ char *arr;
+ int _size;
+ void init() {
+ arr = NULL;
+ _size = 0;
+ }
+ void copy(char *newarr, int newsize) {
+ size(newsize);
+ memcpy(arr, newarr, newsize * sizeof(char));
+ }
+ public:
+ CharVector() { // CTOR
+ init();
+ }
+ ~CharVector() { // DTOR
+ if ( arr ) free(arr);
+ arr = NULL;
+ }
+ CharVector(CharVector&o) { // COPY CTOR
+ init();
+ copy(o.arr, o._size);
+ }
+ CharVector& operator=(CharVector&o) { // ASSIGN
+ init();
+ copy(o.arr, o._size);
+ return(*this);
+ }
+ char operator[](int x) const {
+ return(arr[x]);
+ }
+ char& operator[](int x) {
+ return(arr[x]);
+ }
+ int size() {
+ return(_size);
+ }
+ void size(int count) {
+ if ( count != _size ) {
+ arr = (char*)realloc(arr, count * sizeof(char));
+ _size = count;
+ }
+ }
+ char pop_back() {
+ char tmp = arr[_size-1];
+ _size--;
+ return(tmp);
+ }
+ void push_back(char val) {
+ int x = _size;
+ size(_size+1);
+ arr[x] = val;
+ }
+ char back() {
+ return(arr[_size-1]);
+ }
+ };
+ CharVector _rowselect; // selection flag for each row
+
+ // handle() state variables.
+ // Put here instead of local statics in handle(), so more
+ // than one instance can exist without crosstalk between.
+ //
+ int _dragging_select; // dragging out a selection?
+ int _last_row;
+ int _last_y; // last event's Y position
+ int _last_push_x; // last PUSH event's X position
+ int _last_push_y; // last PUSH event's Y position
+
+ TableRowSelectMode _selectmode;
+
+protected:
+ int handle(int 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) {
+ return(Fl_Table::find_cell(context, R, C, X, Y, W, H));
+ }
+
+public:
+ Fl_Table_Row(int X, int Y, int W, int H, const char *l=0) : Fl_Table(X,Y,W,H,l) {
+ _dragging_select = 0;
+ _last_row = -1;
+ _last_y = -1;
+ _last_push_x = -1;
+ _last_push_y = -1;
+ _selectmode = SELECT_MULTI;
+ }
+ ~Fl_Table_Row() { }
+
+ void rows(int val); // set number of rows
+ int rows() { // get number of rows
+ return(Fl_Table::rows());
+ }
+ void type(TableRowSelectMode val); // set selection mode
+ TableRowSelectMode type() const { // get selection mode
+ return(_selectmode);
+ }
+ int row_selected(int row); // is row selected? (0=no, 1=yes, -1=range err)
+ int select_row(int row, int flag=1); // select state for row: flag:0=off, 1=on, 2=toggle
+ // returns: 0=no change, 1=changed, -1=range err
+ void select_all_rows(int flag=1); // all rows to a known state
+ void clear() {
+ rows(0); // implies clearing selection
+ cols(0);
+ Fl_Table::clear(); // clear the table
+ }
+};
+
+#endif /*_FL_TABLE_ROW_H*/