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
This commit is contained in:
Matthias Melcher
2009-11-14 13:05:37 +00:00
parent 1238d1576b
commit fefa82e0b1
11 changed files with 2822 additions and 5 deletions

451
FL/Fl_Table.H Normal file
View File

@@ -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*/

150
FL/Fl_Table_Row.H Normal file
View File

@@ -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*/

View File

@@ -7,6 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
C904DE6E10AEDD2A00266003 /* Fl_Table_Row.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C904DE6C10AEDD2A00266003 /* Fl_Table_Row.cxx */; };
C904DE6F10AEDD2A00266003 /* Fl_Table.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C904DE6D10AEDD2A00266003 /* Fl_Table.cxx */; };
C904DE7910AEDD3700266003 /* table.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C918E1410DDA11BA00167E99 /* table.cxx */; };
C904DE7B10AEDD3700266003 /* fltk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9A3E9510DD6336500486E4F /* fltk.framework */; };
C904DE7D10AEDD3700266003 /* fltk.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = C9A3E9510DD6336500486E4F /* fltk.framework */; };
C918DB410DD9EE7500167E99 /* editor.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C918DB400DD9EE7500167E99 /* editor.cxx */; };
C918DB4D0DD9EE8F00167E99 /* fltk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9A3E9510DD6336500486E4F /* fltk.framework */; };
C918DB5F0DD9EED100167E99 /* fast_slow.fl in Resources */ = {isa = PBXBuildFile; fileRef = C918DB5E0DD9EED100167E99 /* fast_slow.fl */; };
@@ -124,7 +129,7 @@
C918E1180DD9FFB900167E99 /* fltk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9A3E9510DD6336500486E4F /* fltk.framework */; };
C918E1320DDA117700167E99 /* tabs.fl in Resources */ = {isa = PBXBuildFile; fileRef = C918E1310DDA117700167E99 /* tabs.fl */; };
C918E1390DDA11AF00167E99 /* fltk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9A3E9510DD6336500486E4F /* fltk.framework */; };
C918E1420DDA11BA00167E99 /* tabs.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C918E1410DDA11BA00167E99 /* tabs.cxx */; };
C918E1420DDA11BA00167E99 /* table.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C918E1410DDA11BA00167E99 /* table.cxx */; };
C918E15C0DDA11FE00167E99 /* threads.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C918E15B0DDA11FE00167E99 /* threads.cxx */; };
C918E1630DDA120800167E99 /* fltk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9A3E9510DD6336500486E4F /* fltk.framework */; };
C918E17C0DDA124500167E99 /* tile.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C918E17B0DDA124500167E99 /* tile.cxx */; };
@@ -562,6 +567,18 @@
);
script = "cp -f ${INPUT_FILE_DIR}../../test/demo.menu ${TARGET_BUILD_DIR}";
};
C904DE7E10AEDD3700266003 /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.proxy.script;
filePatterns = "*.fl";
fileType = pattern.proxy;
isEditable = 1;
outputFiles = (
"${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.cxx",
"${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.h",
);
script = "export DYLD_FRAMEWORK_PATH=${TARGET_BUILD_DIR} && cd ../../test && ${TARGET_BUILD_DIR}/Fluid.app/Contents/MacOS/Fluid -c ${INPUT_FILE_NAME}";
};
C918DB780DD9EF6800167E99 /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.proxy.script;
@@ -699,6 +716,20 @@
remoteGlobalIDString = C9A3E9500DD6336500486E4F;
remoteInfo = fltk;
};
C904DE7510AEDD3700266003 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C9A3E93C0DD6332D00486E4F /* Project object */;
proxyType = 1;
remoteGlobalIDString = C9A3E9500DD6336500486E4F;
remoteInfo = fltk;
};
C904DEB810AEE0BD00266003 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C9A3E93C0DD6332D00486E4F /* Project object */;
proxyType = 1;
remoteGlobalIDString = C904DE7110AEDD3700266003 /* table */;
remoteInfo = table;
};
C918DB3D0DD9EE4600167E99 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C9A3E93C0DD6332D00486E4F /* Project object */;
@@ -1927,6 +1958,16 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
C904DE7C10AEDD3700266003 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
C904DE7D10AEDD3700266003 /* fltk.framework in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C94A76BC0E76D4A800AAA38E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -2621,6 +2662,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
C904DE6C10AEDD2A00266003 /* Fl_Table_Row.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Table_Row.cxx; path = ../../src/Fl_Table_Row.cxx; sourceTree = SOURCE_ROOT; };
C904DE6D10AEDD2A00266003 /* Fl_Table.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Table.cxx; path = ../../src/Fl_Table.cxx; sourceTree = SOURCE_ROOT; };
C904DE8210AEDD3700266003 /* table.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = table.app; sourceTree = BUILT_PRODUCTS_DIR; };
C904DE8F10AEDD3800266003 /* tabs-Info copy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "tabs-Info copy.plist"; path = "plists/tabs-Info copy.plist"; sourceTree = "<group>"; };
C918DB370DD9EE4100167E99 /* editor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = editor.app; sourceTree = BUILT_PRODUCTS_DIR; };
C918DB390DD9EE4100167E99 /* editor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "editor-Info.plist"; path = "plists/editor-Info.plist"; sourceTree = "<group>"; };
C918DB400DD9EE7500167E99 /* editor.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = editor.cxx; path = ../../test/editor.cxx; sourceTree = SOURCE_ROOT; };
@@ -2748,7 +2793,7 @@
C918E1260DDA112A00167E99 /* tabs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tabs.app; sourceTree = BUILT_PRODUCTS_DIR; };
C918E1280DDA112B00167E99 /* tabs-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "tabs-Info.plist"; path = "plists/tabs-Info.plist"; sourceTree = "<group>"; };
C918E1310DDA117700167E99 /* tabs.fl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = tabs.fl; path = ../../test/tabs.fl; sourceTree = SOURCE_ROOT; };
C918E1410DDA11BA00167E99 /* tabs.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tabs.cxx; path = ../../test/tabs.cxx; sourceTree = SOURCE_ROOT; };
C918E1410DDA11BA00167E99 /* table.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = table.cxx; path = ../../test/table.cxx; sourceTree = SOURCE_ROOT; };
C918E1520DDA11E400167E99 /* threads.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = threads.app; sourceTree = BUILT_PRODUCTS_DIR; };
C918E1540DDA11E400167E99 /* threads-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "threads-Info.plist"; path = "plists/threads-Info.plist"; sourceTree = "<group>"; };
C918E15B0DDA11FE00167E99 /* threads.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = threads.cxx; path = ../../test/threads.cxx; sourceTree = SOURCE_ROOT; };
@@ -3121,6 +3166,14 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
C904DE7A10AEDD3700266003 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C904DE7B10AEDD3700266003 /* fltk.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C918DB350DD9EE4100167E99 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -3843,6 +3896,7 @@
C94A76DA0E77F59F00AAA38E /* utf8.app */,
C99E1EAE0E78628600AECCF6 /* curve.app */,
C9EAC2DC0E786725004F64F7 /* colbrowser.app */,
C904DE8210AEDD3700266003 /* table.app */,
);
name = Products;
sourceTree = "<group>";
@@ -3921,6 +3975,7 @@
C9A3E9610DD633C300486E4F /* hello-Info.plist */,
C9A3E9530DD6336500486E4F /* fltk-Info.plist */,
C94A76DD0E77F5A800AAA38E /* symbols-Info copy.plist */,
C904DE8F10AEDD3800266003 /* tabs-Info copy.plist */,
);
name = plists;
sourceTree = "<group>";
@@ -3928,6 +3983,8 @@
C9A3E9590DD6338B00486E4F /* Library Sources */ = {
isa = PBXGroup;
children = (
C904DE6C10AEDD2A00266003 /* Fl_Table_Row.cxx */,
C904DE6D10AEDD2A00266003 /* Fl_Table.cxx */,
C9A3EAD80DD634CC00486E4F /* Fl_get_key_mac.cxx */,
C9A3EAD70DD634CC00486E4F /* Fl_get_key_win32.cxx */,
C9A3EAD60DD634CC00486E4F /* Fl_get_system_colors.cxx */,
@@ -4196,7 +4253,7 @@
C918E0E10DD9FF2C00167E99 /* sudoku.cxx */,
C918E1100DD9FFAD00167E99 /* symbols.cxx */,
C918E1310DDA117700167E99 /* tabs.fl */,
C918E1410DDA11BA00167E99 /* tabs.cxx */,
C918E1410DDA11BA00167E99 /* table.cxx */,
C918E15B0DDA11FE00167E99 /* threads.cxx */,
C918E17B0DDA124500167E99 /* tile.cxx */,
C918E1A10DDA128900167E99 /* tiled_image.cxx */,
@@ -4374,6 +4431,26 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
C904DE7110AEDD3700266003 /* table */ = {
isa = PBXNativeTarget;
buildConfigurationList = C904DE7F10AEDD3700266003 /* Build configuration list for PBXNativeTarget "table" */;
buildPhases = (
C904DE7610AEDD3700266003 /* Resources */,
C904DE7810AEDD3700266003 /* Sources */,
C904DE7A10AEDD3700266003 /* Frameworks */,
C904DE7C10AEDD3700266003 /* CopyFiles */,
);
buildRules = (
C904DE7E10AEDD3700266003 /* PBXBuildRule */,
);
dependencies = (
C904DE7410AEDD3700266003 /* PBXTargetDependency */,
);
name = table;
productName = tabs;
productReference = C904DE8210AEDD3700266003 /* table.app */;
productType = "com.apple.product-type.application";
};
C918DB360DD9EE4100167E99 /* editor */ = {
isa = PBXNativeTarget;
buildConfigurationList = C918DB3C0DD9EE4100167E99 /* Build configuration list for PBXNativeTarget "editor" */;
@@ -5344,6 +5421,7 @@
C918E2300DDA13BC00167E99 /* PBXTargetDependency */,
C918E2320DDA13BC00167E99 /* PBXTargetDependency */,
C918E2340DDA13BC00167E99 /* PBXTargetDependency */,
C904DEB910AEE0BD00266003 /* PBXTargetDependency */,
C918E2360DDA13BC00167E99 /* PBXTargetDependency */,
C918E2380DDA13BC00167E99 /* PBXTargetDependency */,
C918E23A0DDA13BC00167E99 /* PBXTargetDependency */,
@@ -5919,6 +5997,7 @@
C918E0B80DD9FE9500167E99 /* subwindow */,
C918E0D70DD9FED700167E99 /* sudoku */,
C918E1060DD9FF9300167E99 /* symbols */,
C904DE7110AEDD3700266003 /* table */,
C918E1250DDA112A00167E99 /* tabs */,
C918E1510DDA11E400167E99 /* threads */,
C918E1710DDA122D00167E99 /* tile */,
@@ -5930,6 +6009,13 @@
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
C904DE7610AEDD3700266003 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C918DB330DD9EE4100167E99 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -6441,6 +6527,14 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
C904DE7810AEDD3700266003 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C904DE7910AEDD3700266003 /* table.cxx in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C918DB340DD9EE4100167E99 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -6752,7 +6846,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C918E1420DDA11BA00167E99 /* tabs.cxx in Sources */,
C918E1420DDA11BA00167E99 /* table.cxx in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -6981,6 +7075,8 @@
C99E1E9B0E78620B00AECCF6 /* case.c in Sources */,
C99E1E9C0E78620B00AECCF6 /* is_right2left.c in Sources */,
C99E1E9D0E78620B00AECCF6 /* is_spacing.c in Sources */,
C904DE6E10AEDD2A00266003 /* Fl_Table_Row.cxx in Sources */,
C904DE6F10AEDD2A00266003 /* Fl_Table.cxx in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -7263,6 +7359,16 @@
target = C9A3E9500DD6336500486E4F /* fltk */;
targetProxy = 01FBE4930E630405009E95B1 /* PBXContainerItemProxy */;
};
C904DE7410AEDD3700266003 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C9A3E9500DD6336500486E4F /* fltk */;
targetProxy = C904DE7510AEDD3700266003 /* PBXContainerItemProxy */;
};
C904DEB910AEE0BD00266003 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C904DE7110AEDD3700266003 /* table */;
targetProxy = C904DEB810AEE0BD00266003 /* PBXContainerItemProxy */;
};
C918DB3E0DD9EE4600167E99 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C9A3E9500DD6336500486E4F /* fltk */;
@@ -8141,6 +8247,53 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
C904DE8010AEDD3700266003 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
HEADER_SEARCH_PATHS = ../../;
INFOPLIST_FILE = "plists/table-Info.plist";
INSTALL_PATH = "$(HOME)/Applications";
OTHER_LDFLAGS = (
"-framework",
Carbon,
);
PREBINDING = NO;
PRODUCT_NAME = table;
WRAPPER_EXTENSION = app;
ZERO_LINK = YES;
};
name = Debug;
};
C904DE8110AEDD3700266003 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
HEADER_SEARCH_PATHS = ../../;
INFOPLIST_FILE = "plists/table-Info.plist";
INSTALL_PATH = "$(HOME)/Applications";
OTHER_LDFLAGS = (
"-framework",
Carbon,
);
PREBINDING = NO;
PRODUCT_NAME = table;
WRAPPER_EXTENSION = app;
ZERO_LINK = NO;
};
name = Release;
};
C918DB3A0DD9EE4100167E99 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -11585,6 +11738,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
C904DE7F10AEDD3700266003 /* Build configuration list for PBXNativeTarget "table" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C904DE8010AEDD3700266003 /* Debug */,
C904DE8110AEDD3700266003 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C918DB3C0DD9EE4100167E99 /* Build configuration list for PBXNativeTarget "editor" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.fltk.table</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>FLTK</string>
<key>CFBundleVersion</key>
<string>1.0</string>
</dict>
</plist>

1218
src/Fl_Table.cxx Normal file

File diff suppressed because it is too large Load Diff

317
src/Fl_Table_Row.cxx Normal file
View File

@@ -0,0 +1,317 @@
//
// 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".
//
//
// TODO:
// o Row headings (only column headings supported currently)
//
#include <stdio.h> // for debugging
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Table_Row.H>
// Is row selected?
int Fl_Table_Row::row_selected(int row) {
if ( row < 0 || row >= rows() ) return(-1);
return(_rowselect[row]);
}
// Change row selection type
void Fl_Table_Row::type(TableRowSelectMode val) {
_selectmode = val;
switch ( _selectmode ) {
case SELECT_NONE:
{
for ( int row=0; row<rows(); row++ ) {
_rowselect[row] = 0;
}
redraw();
break;
}
case SELECT_SINGLE:
{
int count = 0;
for ( int row=0; row<rows(); row++ ) {
if ( _rowselect[row] ) {
if ( ++count > 1 ) { // only one allowed
_rowselect[row] = 0;
}
}
}
redraw();
break;
}
case SELECT_MULTI:
break;
}
}
// Change selection state for row
//
// flag:
// 0 - clear selection
// 1 - set selection
// 2 - toggle selection
//
// Returns:
// 0 - selection state did not change
// 1 - selection state changed
// -1 - row out of range or incorrect selection mode
//
int Fl_Table_Row::select_row(int row, int flag) {
int ret = 0;
if ( row < 0 || row >= rows() ) { return(-1); }
switch ( _selectmode ) {
case SELECT_NONE:
return(-1);
case SELECT_SINGLE:
{
int oldval;
for ( int t=0; t<rows(); t++ ) {
if ( t == row ) {
oldval = _rowselect[row];
if ( flag == 2 ) { _rowselect[row] ^= 1; }
else { _rowselect[row] = flag; }
if ( oldval != _rowselect[row] ) {
redraw_range(row, row, leftcol, rightcol);
ret = 1;
}
}
else if ( _rowselect[t] ) {
_rowselect[t] = 0;
redraw_range(t, t, leftcol, rightcol);
}
}
break;
}
case SELECT_MULTI:
{
int oldval = _rowselect[row];
if ( flag == 2 ) { _rowselect[row] ^= 1; }
else { _rowselect[row] = flag; }
if ( _rowselect[row] != oldval ) { // select state changed?
if ( row >= toprow && row <= botrow ) { // row visible?
// Extend partial redraw range
redraw_range(row, row, leftcol, rightcol);
}
ret = 1;
}
}
}
return(ret);
}
// Select all rows to a known state
void Fl_Table_Row::select_all_rows(int flag) {
switch ( _selectmode ) {
case SELECT_NONE:
return;
case SELECT_SINGLE:
if ( flag != 0 ) return;
//FALLTHROUGH
case SELECT_MULTI:
{
char changed = 0;
if ( flag == 2 ) {
for ( int row=0; row<(int)_rowselect.size(); row++ ) {
_rowselect[row] ^= 1;
}
changed = 1;
} else {
for ( int row=0; row<(int)_rowselect.size(); row++ ) {
changed |= (_rowselect[row] != flag)?1:0;
_rowselect[row] = flag;
}
}
if ( changed ) {
redraw();
}
}
}
}
// Set number of rows
void Fl_Table_Row::rows(int val) {
Fl_Table::rows(val);
while ( val > (int)_rowselect.size() ) { _rowselect.push_back(0); } // enlarge
while ( val < (int)_rowselect.size() ) { _rowselect.pop_back(); } // shrink
}
// #include "eventnames.h" // debugging
// #include <stdio.h>
// Handle events
int Fl_Table_Row::handle(int event) {
// fprintf(stderr, "** EVENT: %s: EVENT XY=%d,%d\n",
// eventnames[event], Fl::event_x(), Fl::event_y()); // debugging
// Let base class handle event
int ret = Fl_Table::handle(event);
// The following code disables cell selection.. why was it added? -erco 05/18/03
// if ( ret ) { _last_y = Fl::event_y(); return(1); } // base class 'handled' it (eg. column resize)
int shiftstate = (Fl::event_state() & FL_CTRL) ? FL_CTRL :
(Fl::event_state() & FL_SHIFT) ? FL_SHIFT : 0;
// Which row/column are we over?
int R, C; // row/column being worked on
ResizeFlag resizeflag; // which resizing area are we over? (0=none)
TableContext context = cursor2rowcol(R, C, resizeflag);
switch ( event ) {
case FL_PUSH:
if ( Fl::event_button() == 1 ) {
_last_push_x = Fl::event_x(); // save regardless of context
_last_push_y = Fl::event_y(); // " "
// Handle selection in table.
// Select cell under cursor, and enable drag selection mode.
//
if ( context == CONTEXT_CELL ) {
// Ctrl key? Toggle selection state
switch ( shiftstate ) {
case FL_CTRL:
select_row(R, 2); // toggle
break;
case FL_SHIFT:
{
select_row(R, 1);
if ( _last_row > -1 ) {
int srow = R, erow = _last_row;
if ( srow > erow ) {
srow = _last_row;
erow = R;
}
for ( int row = srow; row <= erow; row++ ) {
select_row(row, 1);
}
}
break;
}
default:
select_all_rows(0); // clear all previous selections
select_row(R, 1);
break;
}
_last_row = R;
_dragging_select = 1;
ret = 1; // FL_PUSH handled (ensures FL_DRAG will be sent)
// redraw(); // redraw() handled by select_row()
}
}
break;
case FL_DRAG:
{
if ( _dragging_select ) {
// Dragged off table edges? Handle scrolling
int offtop = toy - _last_y; // >0 if off top of table
int offbot = _last_y - (toy + toh); // >0 if off bottom of table
if ( offtop > 0 && row_position() > 0 ) {
// Only scroll in upward direction
int diff = _last_y - Fl::event_y();
if ( diff < 1 ) {
ret = 1;
break;
}
row_position(row_position() - diff);
context = CONTEXT_CELL; C = 0; R = row_position(); // HACK: fake it
if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly
}
else if ( offbot > 0 && botrow < rows() ) {
// Only scroll in downward direction
int diff = Fl::event_y() - _last_y;
if ( diff < 1 ) {
ret = 1;
break;
}
row_position(row_position() + diff);
context = CONTEXT_CELL; C = 0; R = botrow; // HACK: fake it
if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly
}
if ( context == CONTEXT_CELL ) {
switch ( shiftstate ) {
case FL_CTRL:
if ( R != _last_row ) { // toggle if dragged to new row
select_row(R, 2); // 2=toggle
}
break;
case FL_SHIFT:
default:
select_row(R, 1);
if ( _last_row > -1 ) {
int srow = R, erow = _last_row;
if ( srow > erow ) {
srow = _last_row;
erow = R;
}
for ( int row = srow; row <= erow; row++ ) {
select_row(row, 1);
}
}
break;
}
ret = 1; // drag handled
_last_row = R;
}
}
break;
}
case FL_RELEASE:
if ( Fl::event_button() == 1 ) {
_dragging_select = 0;
ret = 1; // release handled
// Clicked off edges of data table?
// A way for user to clear the current selection.
//
int databot = tiy + table_h,
dataright = tix + table_w;
if (
( _last_push_x > dataright && Fl::event_x() > dataright ) ||
( _last_push_y > databot && Fl::event_y() > databot )
) {
select_all_rows(0); // clear previous selections
}
}
break;
default:
break;
}
_last_y = Fl::event_y();
return(ret);
}

BIN
src/Fl_Tabs.o Normal file

Binary file not shown.

View File

@@ -78,6 +78,8 @@ CPPFILES = \
Fl_Shared_Image.cxx \
Fl_Single_Window.cxx \
Fl_Slider.cxx \
Fl_Table.cxx \
Fl_Table_Row.cxx \
Fl_Tabs.cxx \
Fl_Text_Buffer.cxx \
Fl_Text_Display.cxx \

View File

@@ -90,6 +90,7 @@ CPPFILES =\
subwindow.cxx \
sudoku.cxx \
symbols.cxx \
table.cxx \
tabs.cxx \
threads.cxx \
tile.cxx \
@@ -152,6 +153,7 @@ ALL = \
subwindow$(EXEEXT) \
sudoku$(EXEEXT) \
symbols$(EXEEXT) \
table$(EXEEXT) \
tabs$(EXEEXT) \
$(THREADS) \
tile$(EXEEXT) \

View File

@@ -18,7 +18,9 @@
@x:Fl_Tile:tile
@x:Fl_Scroll:scroll
@x:Fl_Pack:pack
@x:Fl_Menu:menubar
@x:more...:@xm
@xm:Fl_Menu:menubar
@xm:Fl_Table:table
@main:Window\nTests:@w
@w:overlay:overlay

493
test/table.cxx Normal file
View File

@@ -0,0 +1,493 @@
//
// exercisetablerow -- Exercise all aspects of the Fl_Table_Row widget
//
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <stdlib.h> // atoi
#endif /*_WIN32*/
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/fl_draw.H>
#include <FL/fl_ask.H>
#include <FL/Fl_Table_Row.H>
// Simple demonstration class to derive from Fl_Table_Row
class DemoTable : public Fl_Table_Row
{
private:
Fl_Color cell_bgcolor; // color of cell's bg color
Fl_Color cell_fgcolor; // color of cell's fg color
protected:
void draw_cell(TableContext context, // table cell drawing
int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0);
static void event_callback(Fl_Widget*, void*);
void event_callback2(); // callback for table events
public:
DemoTable(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l)
{
cell_bgcolor = FL_WHITE;
cell_fgcolor = FL_BLACK;
callback(&event_callback, (void*)this);
end();
}
~DemoTable() { }
Fl_Color GetCellFGColor() const { return(cell_fgcolor); }
Fl_Color GetCellBGColor() const { return(cell_bgcolor); }
void SetCellFGColor(Fl_Color val) { cell_fgcolor = val; }
void SetCellBGColor(Fl_Color val) { cell_bgcolor = val; }
};
// Handle drawing all cells in table
void DemoTable::draw_cell(TableContext context,
int R, int C, int X, int Y, int W, int H)
{
static char s[40];
sprintf(s, "%d/%d", R, C); // text for each cell
switch ( context )
{
case CONTEXT_STARTPAGE:
fl_font(FL_HELVETICA, 16);
return;
case CONTEXT_COL_HEADER:
fl_push_clip(X, Y, W, H);
{
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color());
fl_color(FL_BLACK);
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
}
fl_pop_clip();
return;
case CONTEXT_ROW_HEADER:
fl_push_clip(X, Y, W, H);
{
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, row_header_color());
fl_color(FL_BLACK);
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
}
fl_pop_clip();
return;
case CONTEXT_CELL:
{
fl_push_clip(X, Y, W, H);
{
// BG COLOR
fl_color( row_selected(R) ? selection_color() : cell_bgcolor);
fl_rectf(X, Y, W, H);
// TEXT
fl_color(cell_fgcolor);
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
// BORDER
fl_color(color());
fl_rect(X, Y, W, H);
}
fl_pop_clip();
return;
}
case CONTEXT_TABLE:
fprintf(stderr, "TABLE CONTEXT CALLED\n");
return;
case CONTEXT_ENDPAGE:
case CONTEXT_RC_RESIZE:
case CONTEXT_NONE:
return;
}
}
// Callback whenever someone clicks on different parts of the table
void DemoTable::event_callback(Fl_Widget*, void *data)
{
DemoTable *o = (DemoTable*)data;
o->event_callback2();
}
void DemoTable::event_callback2()
{
int R = callback_row(),
C = callback_col();
TableContext context = callback_context();
printf("'%s' callback: ", (label() ? label() : "?"));
printf("Row=%d Col=%d Context=%d Event=%d InteractiveResize? %d\n",
R, C, (int)context, (int)Fl::event(), (int)is_interactive_resize());
}
// GLOBAL TABLE WIDGET
static DemoTable *G_table = 0;
void setrows_cb(Fl_Widget*, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int rows = atoi(in->value());
if ( rows < 0 ) rows = 0;
G_table->rows(rows);
}
void setcols_cb(Fl_Widget*, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int cols = atoi(in->value());
if ( cols < 0 ) cols = 0;
G_table->cols(cols);
}
void setrowheader_cb(Fl_Widget*, void *data)
{
Fl_Check_Button *check = (Fl_Check_Button*)data;
G_table->row_header(check->value());
}
void setcolheader_cb(Fl_Widget*, void *data)
{
Fl_Check_Button *check = (Fl_Check_Button*)data;
G_table->col_header(check->value());
}
void setrowresize_cb(Fl_Widget*, void *data)
{
Fl_Check_Button *check = (Fl_Check_Button*)data;
G_table->row_resize(check->value());
}
void setcolresize_cb(Fl_Widget*, void *data)
{
Fl_Check_Button *check = (Fl_Check_Button*)data;
G_table->col_resize(check->value());
}
void setpositionrow_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int toprow = atoi(in->value());
if ( toprow < 0 || toprow >= G_table->rows() )
{ fl_alert("Must be in range 0 thru #rows"); }
else
{ G_table->row_position(toprow); }
}
void setpositioncol_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int leftcol = atoi(in->value());
if ( leftcol < 0 || leftcol >= G_table->cols() )
{ fl_alert("Must be in range 0 thru #cols"); }
else
{ G_table->col_position(leftcol); }
}
void setrowheaderwidth_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 1 ) { val = 1; in->value("1"); }
G_table->row_header_width(val);
}
void setcolheaderheight_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 1 ) { val = 1; in->value("1"); }
G_table->col_header_height(val);
}
void setrowheadercolor_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { fl_alert("Must be a color >0"); }
else { G_table->row_header_color(Fl_Color(val)); }
}
void setcolheadercolor_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { fl_alert("Must be a color >0"); }
else { G_table->col_header_color(Fl_Color(val)); }
}
void setrowheightall_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { val = 0; in->value("0"); }
G_table->row_height_all(val);
}
void setcolwidthall_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { val = 0; in->value("0"); }
G_table->col_width_all(val);
}
void settablecolor_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { fl_alert("Must be a color >0"); }
else { G_table->color(Fl_Color(val)); }
G_table->redraw();
}
void setcellfgcolor_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { fl_alert("Must be a color >0"); }
else { G_table->SetCellFGColor(Fl_Color(val)); }
G_table->redraw();
}
void setcellbgcolor_cb(Fl_Widget *w, void *data)
{
Fl_Input *in = (Fl_Input*)data;
int val = atoi(in->value());
if ( val < 0 ) { fl_alert("Must be a color >0"); }
else { G_table->SetCellBGColor(Fl_Color(val)); }
G_table->redraw();
}
char *itoa(int val)
{
static char s[80];
sprintf(s, "%d", val);
return(s);
}
void tablebox_choice_cb(Fl_Widget *w, void *data)
{
G_table->table_box((Fl_Boxtype)(int)data);
G_table->redraw();
}
void widgetbox_choice_cb(Fl_Widget *w, void *data)
{
G_table->box((Fl_Boxtype)(int)data);
G_table->resize(G_table->x(), G_table->y(), G_table->w(), G_table->h());
}
void type_choice_cb(Fl_Widget *w, void *data)
{
G_table->type((Fl_Table_Row::TableRowSelectMode)(int)data);
}
Fl_Menu_Item tablebox_choices[] = {
{"No Box", 0, tablebox_choice_cb, (void*)FL_NO_BOX },
{"Flat Box", 0, tablebox_choice_cb, (void*)FL_FLAT_BOX },
{"Up Box", 0, tablebox_choice_cb, (void*)FL_UP_BOX },
{"Down Box", 0, tablebox_choice_cb, (void*)FL_DOWN_BOX },
{"Up Frame", 0, tablebox_choice_cb, (void*)FL_UP_FRAME },
{"Down Frame", 0, tablebox_choice_cb, (void*)FL_DOWN_FRAME },
{"Thin Up Box", 0, tablebox_choice_cb, (void*)FL_THIN_UP_BOX },
{"Thin Down Box", 0, tablebox_choice_cb, (void*)FL_THIN_DOWN_BOX },
{"Thin Up Frame", 0, tablebox_choice_cb, (void*)FL_THIN_UP_FRAME },
{"Thin Down Frame",0, tablebox_choice_cb, (void*)FL_THIN_DOWN_FRAME },
{"Engraved Box", 0, tablebox_choice_cb, (void*)FL_ENGRAVED_BOX },
{"Embossed Box", 0, tablebox_choice_cb, (void*)FL_EMBOSSED_BOX },
{"Engraved Frame", 0, tablebox_choice_cb, (void*)FL_ENGRAVED_FRAME },
{"Embossed Frame", 0, tablebox_choice_cb, (void*)FL_EMBOSSED_FRAME },
{"Border Box", 0, tablebox_choice_cb, (void*)FL_BORDER_BOX },
{"Shadow Box", 0, tablebox_choice_cb, (void*)FL_SHADOW_BOX },
{"Border Frame", 0, tablebox_choice_cb, (void*)FL_BORDER_FRAME },
{0}
};
Fl_Menu_Item widgetbox_choices[] = {
{"No Box", 0, widgetbox_choice_cb, (void*)FL_NO_BOX },
//{"Flat Box", 0, widgetbox_choice_cb, (void*)FL_FLAT_BOX },
//{"Up Box", 0, widgetbox_choice_cb, (void*)FL_UP_BOX },
//{"Down Box", 0, widgetbox_choice_cb, (void*)FL_DOWN_BOX },
{"Up Frame", 0, widgetbox_choice_cb, (void*)FL_UP_FRAME },
{"Down Frame", 0, widgetbox_choice_cb, (void*)FL_DOWN_FRAME },
//{"Thin Up Box", 0, widgetbox_choice_cb, (void*)FL_THIN_UP_BOX },
//{"Thin Down Box", 0, widgetbox_choice_cb, (void*)FL_THIN_DOWN_BOX },
{"Thin Up Frame", 0, widgetbox_choice_cb, (void*)FL_THIN_UP_FRAME },
{"Thin Down Frame",0, widgetbox_choice_cb, (void*)FL_THIN_DOWN_FRAME },
//{"Engraved Box", 0, widgetbox_choice_cb, (void*)FL_ENGRAVED_BOX },
//{"Embossed Box", 0, widgetbox_choice_cb, (void*)FL_EMBOSSED_BOX },
{"Engraved Frame", 0, widgetbox_choice_cb, (void*)FL_ENGRAVED_FRAME },
{"Embossed Frame", 0, widgetbox_choice_cb, (void*)FL_EMBOSSED_FRAME },
//{"Border Box", 0, widgetbox_choice_cb, (void*)FL_BORDER_BOX },
//{"Shadow Box", 0, widgetbox_choice_cb, (void*)FL_SHADOW_BOX },
{"Border Frame", 0, widgetbox_choice_cb, (void*)FL_BORDER_FRAME },
{0}
};
Fl_Menu_Item type_choices[] = {
{"SelectNone", 0, type_choice_cb, (void*)Fl_Table_Row::SELECT_NONE },
{"SelectSingle", 0, type_choice_cb, (void*)Fl_Table_Row::SELECT_SINGLE },
{"SelectMulti", 0, type_choice_cb, (void*)Fl_Table_Row::SELECT_MULTI },
{0}
};
int main(int argc, char **argv)
{
Fl_Window win(900, 730);
G_table = new DemoTable(20, 20, 860, 460, "Demo");
G_table->selection_color(FL_YELLOW);
G_table->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED);
G_table->table_box(FL_NO_BOX);
G_table->col_resize_min(4);
G_table->row_resize_min(4);
// ROWS
G_table->row_header(1);
G_table->row_header_width(60);
G_table->row_resize(1);
G_table->rows(500);
G_table->row_height_all(20);
// COLS
G_table->cols(500);
G_table->col_header(1);
G_table->col_header_height(25);
G_table->col_resize(1);
G_table->col_width_all(80);
// Add children to window
win.begin();
// ROW
Fl_Input setrows(150, 500, 120, 25, "Rows");
setrows.labelsize(12);
setrows.value(itoa(G_table->rows()));
setrows.callback(setrows_cb, (void*)&setrows);
setrows.when(FL_WHEN_RELEASE);
Fl_Input rowheightall(400, 500, 120, 25, "Row Height");
rowheightall.labelsize(12);
rowheightall.value(itoa(G_table->row_height(0)));
rowheightall.callback(setrowheightall_cb, (void*)&rowheightall);
rowheightall.when(FL_WHEN_RELEASE);
Fl_Input positionrow(650, 500, 120, 25, "Row Position");
positionrow.labelsize(12);
positionrow.value("1");
positionrow.callback(setpositionrow_cb, (void*)&positionrow);
positionrow.when(FL_WHEN_RELEASE);
// COL
Fl_Input setcols(150, 530, 120, 25, "Cols");
setcols.labelsize(12);
setcols.value(itoa(G_table->cols()));
setcols.callback(setcols_cb, (void*)&setcols);
setcols.when(FL_WHEN_RELEASE);
Fl_Input colwidthall(400, 530, 120, 25, "Col Width");
colwidthall.labelsize(12);
colwidthall.value(itoa(G_table->col_width(0)));
colwidthall.callback(setcolwidthall_cb, (void*)&colwidthall);
colwidthall.when(FL_WHEN_RELEASE);
Fl_Input positioncol(650, 530, 120, 25, "Col Position");
positioncol.labelsize(12);
positioncol.value("1");
positioncol.callback(setpositioncol_cb, (void*)&positioncol);
positioncol.when(FL_WHEN_RELEASE);
// ROW HEADER
Fl_Input rowheaderwidth(150, 570, 120, 25, "Row Header Width");
rowheaderwidth.labelsize(12);
rowheaderwidth.value(itoa(G_table->row_header_width()));
rowheaderwidth.callback(setrowheaderwidth_cb, (void*)&rowheaderwidth);
rowheaderwidth.when(FL_WHEN_RELEASE);
Fl_Input rowheadercolor(400, 570, 120, 25, "Row Header Color");
rowheadercolor.labelsize(12);
rowheadercolor.value(itoa((int)G_table->row_header_color()));
rowheadercolor.callback(setrowheadercolor_cb, (void*)&rowheadercolor);
rowheadercolor.when(FL_WHEN_RELEASE);
Fl_Check_Button rowheader(550, 570, 120, 25, "Row Headers?");
rowheader.labelsize(12);
rowheader.callback(setrowheader_cb, (void*)&rowheader);
rowheader.value(G_table->row_header() ? 1 : 0);
Fl_Check_Button rowresize(700, 570, 120, 25, "Row Resize?");
rowresize.labelsize(12);
rowresize.callback(setrowresize_cb, (void*)&rowresize);
rowresize.value(G_table->row_resize() ? 1 : 0);
// COL HEADER
Fl_Input colheaderheight(150, 600, 120, 25, "Col Header Height");
colheaderheight.labelsize(12);
colheaderheight.value(itoa(G_table->col_header_height()));
colheaderheight.callback(setcolheaderheight_cb, (void*)&colheaderheight);
colheaderheight.when(FL_WHEN_RELEASE);
Fl_Input colheadercolor(400, 600, 120, 25, "Col Header Color");
colheadercolor.labelsize(12);
colheadercolor.value(itoa((int)G_table->col_header_color()));
colheadercolor.callback(setcolheadercolor_cb, (void*)&colheadercolor);
colheadercolor.when(FL_WHEN_RELEASE);
Fl_Check_Button colheader(550, 600, 120, 25, "Col Headers?");
colheader.labelsize(12);
colheader.callback(setcolheader_cb, (void*)&colheader);
colheader.value(G_table->col_header() ? 1 : 0);
Fl_Check_Button colresize(700, 600, 120, 25, "Col Resize?");
colresize.labelsize(12);
colresize.callback(setcolresize_cb, (void*)&colresize);
colresize.value(G_table->col_resize() ? 1 : 0);
Fl_Choice tablebox(150, 640, 120, 25, "Table Box");
tablebox.labelsize(12);
tablebox.textsize(12);
tablebox.menu(tablebox_choices);
tablebox.value(0);
Fl_Choice widgetbox(150, 670, 120, 25, "Widget Box");
widgetbox.labelsize(12);
widgetbox.textsize(12);
widgetbox.menu(widgetbox_choices);
widgetbox.value(2); // down frame
Fl_Input tablecolor(400, 640, 120, 25, "Table Color");
tablecolor.labelsize(12);
tablecolor.value(itoa((int)G_table->color()));
tablecolor.callback(settablecolor_cb, (void*)&tablecolor);
tablecolor.when(FL_WHEN_RELEASE);
Fl_Input cellbgcolor(400, 670, 120, 25, "Cell BG Color");
cellbgcolor.labelsize(12);
cellbgcolor.value(itoa((int)G_table->GetCellBGColor()));
cellbgcolor.callback(setcellbgcolor_cb, (void*)&cellbgcolor);
cellbgcolor.when(FL_WHEN_RELEASE);
Fl_Input cellfgcolor(400, 700, 120, 25, "Cell FG Color");
cellfgcolor.labelsize(12);
cellfgcolor.value(itoa((int)G_table->GetCellFGColor()));
cellfgcolor.callback(setcellfgcolor_cb, (void*)&cellfgcolor);
cellfgcolor.when(FL_WHEN_RELEASE);
Fl_Choice type(650, 640, 120, 25, "Type");
type.labelsize(12);
type.textsize(12);
type.menu(type_choices);
type.value(2);
win.end();
win.resizable(*G_table);
win.show(argc, argv);
return(Fl::run());
}