diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2009-11-14 14:34:29 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2009-11-14 14:34:29 +0000 |
| commit | e649ce327e49630a7793cafdfdc6f0ce202c350c (patch) | |
| tree | fae8df897cf7b7845abd04df215bafdec3f48c8f | |
| parent | a77971caf020b773d6590413ecc180610e7aa1c1 (diff) | |
Added doxygenified documentation for Fl_Table
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6931 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | FL/Fl_Table.H | 546 | ||||
| -rw-r--r-- | documentation/src/table-dimensions.gif | bin | 0 -> 5556 bytes |
2 files changed, 544 insertions, 2 deletions
diff --git a/FL/Fl_Table.H b/FL/Fl_Table.H index 3dfc18400..eb8e73616 100644 --- a/FL/Fl_Table.H +++ b/FL/Fl_Table.H @@ -43,6 +43,61 @@ #include <FL/Fl_Box.H> #include <FL/Fl_Scrollbar.H> +/** + \brief This is the base class for table widgets. + + To be useful it must be subclassed and several virtual functions defined. + Normally applications use widgets derived from this widget, and do not use this + widget directly; this widget is usually too low level to be used directly by + applications. + + This widget does \em not handle the data in the table. The draw_cell() + method must be overridden by a subclass to manage drawing the contents of + the cells. + + This widget can be used in several ways: + + - As a custom widget; see test/testtablerow.cxx. Very optimal for even + extremely large tables. + - As a table made up of a single FLTK widget instanced all over the table; + see test/singleinput.cxx. Very optimal for even extremely large tables; + - As a regular container of FLTK widgets, one widget per cell. + See test/widgettable.cxx. \em Not recommended for large tables. + + When acting as part of a custom widget, events on the cells and/or headings + generate callbacks when they are clicked by the user. You control when events + are generated based on the setting for Fl_Table::when(). + + When acting as a container for FLTK widgets, the FLTK widgets maintain + themselves. Although the draw_cell() method must be overridden, its contents + can be very simple. See the draw_cell() code in test/widgettable.cxx. + + The following variables are available to classes deriving from Fl_Table: + + \image html table-dimensions.gif + + <table border=0> + <tr><td>x()/y()/w()/h()</td> + <td>Fl_Table widget's outer dimension. The outer edge of the border of the + Fl_Table. (Red in the diagram above)</td></tr> + + <tr><td>wix/wiy/wiw/wih</td> + <td>Fl_Table widget's inner dimension. The inner edge of the border of the + Fl_Table. eg. if the Fl_Table's box() is FL_NO_BOX, these values are the same + as x()/y()/w()/h(). (Yellow in the diagram above)</td></tr> + + <tr><td>tox/toy/tow/toh</td> + <td>The table's outer dimension. The outer edge of the border around the cells, + but inside the row/col headings and scrollbars. (Green in the diagram above) + </td></tr> + + <tr><td>tix/tiy/tiw/tih</td> + <td>The table's inner dimension. The inner edge of the border around the cells, + but inside the row/col headings and scrollbars. AKA the table's clip region. + eg. if the table_box() is FL_NO_BOX, these values are the same as + tox/toyy/tow/toh. (Blue in the diagram above) + </td></tr></table> + */ class Fl_Table : public Fl_Group { public: enum TableContext { @@ -189,7 +244,109 @@ protected: int row_col_clamp(TableContext context, int &R, int &C); // clamp r/c to known universe - // Called to draw cells + /** + Subclass should override this method to handle drawing the cells. + + This method will be called whenever the table is redrawn, once per cell. + + Only cells that are completely (or partially) visible will be told to draw. + + \p context will be one of the following: + + <table border=1> + <tr> + <td>\p Fl_Table::CONTEXT_STARTPAGE</td> + <td> When table, or parts of the table, are about to be redrawn. + Use to initialize static data, such as font selections. + r/c will be zero, x/y/w/h will be the dimensions of the + table's entire data area. + (Useful for locking a database before accessing; see + also visible_cells())</td> + </tr><tr> + <td>\p Fl_Table::CONTEXT_ENDPAGE</td> + <td>When table has completed being redrawn. + r/c will be zero, x/y/w/h dimensions of table's data area. + (Useful for unlocking a database after accessing)</td> + </tr><tr> + <td>\p Fl_Table::CONTEXT_ROW_HEADER</td> + <td>Whenever a row header cell needs to be drawn.</td> + </tr><tr> + <td>\p Fl_Table::CONTEXT_COL_HEADER</td> + <td>Whenever a column header cell needs to be drawn.</td> + </tr><tr> + <td>\p Fl_Table::CONTEXT_CELL</td> + <td>Whenever a data cell in the table needs to be drawn.</td> + </tr><tr> + <td>\p Fl_Table::CONTEXT_RC_RESIZE</td> + <td>Whenever table or row/column is resized or scrolled, + either interactively or via col_width() or row_height(). + + Useful for fltk containers that need to resize or move + the child fltk widgets.</td> + </tr> + </table> + + \p row and \p col will be set to the row and column number + the user clicked on. In the case of row headers, \p col will be \a 0. + In the case of column headers, \p row will be \a 0. + + <tt>x/y/w/h</tt> will be the position and dimensions of where the cell + should be drawn. + + In the case of custom widgets, a minimal draw_cell() override might + look like the following. With custom widgets it is up to the caller to handle + drawing everything within the dimensions of the cell, including handling the + selection color. Note all clipping must be handled as well; this allows drawing + outside the dimensions of the cell if so desired for 'custom effects'. + + \code + // This is called whenever Fl_Table wants you to draw a cell + void MyTable::draw_cell(TableContext context, int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0) + { + static char s[40]; + sprintf(s, "%d/%d", R, C); // text for each cell + switch ( context ) + { + case CONTEXT_STARTPAGE: // Fl_Table telling us its starting to draw page + fl_font(FL_HELVETICA, 16); + return; + + case CONTEXT_ROW_HEADER: // Fl_Table telling us it's draw row/col headers + case CONTEXT_COL_HEADER: + fl_push_clip(X, Y, W, H); + { + fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color()); + fl_color(FL_BLACK); + fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); + } + fl_pop_clip(); + return; + + case CONTEXT_CELL: // Fl_Table telling us to draw cells + fl_push_clip(X, Y, W, H); + { + // BG COLOR + fl_color( row_selected(R) ? selection_color() : FL_WHITE); + fl_rectf(X, Y, W, H); + + // TEXT + fl_color(FL_BLACK); + fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); + + // BORDER + fl_color(FL_LIGHT2); + fl_rect(X, Y, W, H); + } + fl_pop_clip(); + return; + + default: + return; + } + //NOTREACHED + } + \endcode + */ 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 @@ -225,139 +382,361 @@ protected: } public: + /** + The constructor for the Fl_Table. + This creates an empty table with no rows or columns, + with headers and row/column resize behavior disabled. + */ Fl_Table(int X, int Y, int W, int H, const char *l=0); + + /** + The destructor for the Fl_Table. + Destroys the table and its associated widgets. + */ ~Fl_Table(); + /** + Clears the table to zero rows, zero columns. + Same as rows(0); cols(0); + \see rows(int), cols(int) + */ virtual void clear() { rows(0); cols(0); } // topline() // middleline() // bottomline() + /** + Sets the kind of box drawn around the data table, + the default being FL_NO_BOX. Changing this value will cause the table + to redraw. + */ inline void table_box(Fl_Boxtype val) { table->box(val); table_resized(); } + + /** + Returns the current box type used for the data table. + */ inline Fl_Boxtype table_box( void ) { return(table->box()); } + + /** + Sets the number of rows in the table, and the table is redrawn. + */ virtual void rows(int val); // set/get number of rows + + /** + Returns the number of rows in the table. + */ inline int rows() { return(_rows); } + + /** + Set the number of columns in the table and redraw. + */ virtual void cols(int val); // set/get number of columns + + /** + Get the number of columns in the table. + */ inline int cols() { return(_cols); } + + /** + Returns the range of row and column numbers for all the + visible (and partially visible) cells in the table. + + These values can be used e.g. by your draw_cell() routine during + CONTEXT_STARTPAGE to figure out what cells are about to be redrawn, + for the purposes of locking the data from a database before it's drawn. + + \code + leftcol rightcol + : : + toprow .. .-------------------. + | | + | V I S I B L E | + | | + | T A B L E | + | | + botrow .. '-------------------` + \endcode + + e.g. in a table where the visible rows are 5-20, and the + visible columns are 100-120, then those variables would be: + + - toprow = 5 + - botrow = 20 + - leftcol = 100 + - rightcol = 120 + */ inline void visible_cells(int& r1, int& r2, int& c1, int& c2) { r1 = toprow; r2 = botrow; c1 = leftcol; c2 = rightcol; } - // Interactive resizing happening? + + /** + Returns 1 if someone is interactively resizing a row or column. + You can currently call this only from within your callback(). + */ int is_interactive_resize() { return(_resizing_row != -1 || _resizing_col != -1); } + + /** + Returns the current value of this flag. + */ inline int row_resize() { return(_row_resize); } + + /** + Allows/disallows row resizing by the user. + 1=allow interactive resizing, 0=disallow interactive resizing. + Since interactive resizing is done via the row headers, + row_header() must also be enabled to allow resizing. + */ void row_resize(int flag) { // enable row resizing _row_resize = flag; } + + /** + Returns the current value of this flag. + */ inline int col_resize() { return(_col_resize); } + /** + Allows/disallows column resizing by the user. + 1=allow interactive resizing, 0=disallow interactive resizing. + Since interactive resizing is done via the column headers, + \p col_header() must also be enabled to allow resizing. + */ void col_resize(int flag) { // enable col resizing _col_resize = flag; } + + /** + Sets the current column minimum resize value. + This is used to prevent the user from interactively resizing + any column to be smaller than 'pixels'. Must be a value >=1. + */ inline int col_resize_min() { // column minimum resizing width return(_col_resize_min); } + + /** + Returns the current column minimum resize value. + */ void col_resize_min(int val) { _col_resize_min = ( val < 1 ) ? 1 : val; } + + /** + Returns the current row minimum resize value. + */ inline int row_resize_min() { // column minimum resizing width return(_row_resize_min); } + + /** + Sets the current row minimum resize value. + This is used to prevent the user from interactively resizing + any row to be smaller than 'pixels'. Must be a value >=1. + */ void row_resize_min(int val) { _row_resize_min = ( val < 1 ) ? 1 : val; } + + /** + Returns the value of this flag. + */ inline int row_header() { // set/get row header enable flag return(_row_header); } + + /** + Enables/disables showing the row headers. 1=enabled, 0=disabled. + If changed, the table is redrawn. + */ void row_header(int flag) { _row_header = flag; table_resized(); redraw(); } + + /** + Returns if column headers are enabled or not. + */ inline int col_header() { // set/get col header enable flag return(_col_header); } + + /** + Enable or disable column headers. + If changed, the table is redrawn. + */ void col_header(int flag) { _col_header = flag; table_resized(); redraw(); } + + /** + Sets the height in pixels for column headers and redraws the table. + */ inline void col_header_height(int height) { // set/get col header height _col_header_h = height; table_resized(); redraw(); } + + /** + Gets the column header height. + */ inline int col_header_height() { return(_col_header_h); } + + /** + Sets the row header width to n and causes the screen to redraw. + */ inline void row_header_width(int width) { // set/get row header width _row_header_w = width; table_resized(); redraw(); } + + /** + Returns the current row header width (in pixels). + */ inline int row_header_width() { return(_row_header_w); } + + /** + Sets the row header color and causes the screen to redraw. + */ inline void row_header_color(Fl_Color val) { // set/get row header color _row_header_color = val; redraw(); } + + /** + Returns the current row header color. + */ inline Fl_Color row_header_color() { return(_row_header_color); } + + /** + Sets the color for column headers and redraws the table. + */ inline void col_header_color(Fl_Color val) { // set/get col header color _col_header_color = val; redraw(); } + + /** + Gets the color for column headers. + */ inline Fl_Color col_header_color() { return(_col_header_color); } + + /** + Sets the height of the specified row in pixels, + and the table is redrawn. + callback() will be invoked with CONTEXT_RC_RESIZE + if the row's height was actually changed, and when() is FL_WHEN_CHANGED. + */ void row_height(int row, int height); // set/get row height + + /** + Returns the current height of the specified row as a value in pixels. + */ inline int row_height(int row) { return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]); } + + /** + Sets the width of the specified column in pixels, and the table is redrawn. + callback() will be invoked with CONTEXT_RC_RESIZE + if the column's width was actually changed, and when() is FL_WHEN_CHANGED. + */ void col_width(int col, int width); // set/get a column's width + + /** + Returns the current width of the specified column in pixels. + */ inline int col_width(int col) { return((col<0 || col>=(int)_colwidths.size()) ? 0 : _colwidths[col]); } + + /** + Convenience method to set the height of all rows to the + same value, in pixels. The screen is redrawn. + */ void row_height_all(int height) { // set all row/col heights for ( int r=0; r<rows(); r++ ) { row_height(r, height); } } + + /** + Convenience method to set the width of all columns to the + same value, in pixels. The screen is redrawn. + */ void col_width_all(int width) { for ( int c=0; c<cols(); c++ ) { col_width(c, width); } } + + /** + Sets the row scroll position to 'row', and causes the screen to redraw. + */ void row_position(int row); // set/get table's current scroll position + + /** + Sets the column scroll position to column 'col', and causes the screen to redraw. + */ void col_position(int col); + + /** + Returns the current row scroll position as a row number. + */ int row_position() { // current row position return(_row_position); } + + /** + Returns the current column scroll position as a column number. + */ int col_position() { // current col position return(_col_position); } + + /** + Sets which row should be at the top of the table, + scrolling as necessary, and the table is redrawn. If the table + cannot be scrolled that far, it is scrolled as far as possible. + */ inline void top_row(int row) { // set/get top row (deprecated) row_position(row); } + + /** + Returns the current top row shown in the table. + This row may be partially obscured. + */ inline int top_row() { return(row_position()); } @@ -366,6 +745,9 @@ public: void set_selection(int s_top, int s_left, int s_bottom, int s_right); int move_cursor(int R, int C); + /** + Changes the size of the Fl_Table, causing it to redraw. + */ void resize(int X, int Y, int W, int H); // fltk resize() override void draw(void); // fltk draw() override @@ -418,9 +800,34 @@ public: Fl_Widget * const *array() { return(table->array()); } + + /** + Returns the child widget by an index. + + When using the Fl_Table as a container for FLTK widgets, this method returns + the widget pointer from the internal array of widgets in the container. + + Typically used in loops, eg: + \code + for ( int i=0; i<children(); i++ ) + { + Fl_Widget *w = child(i); + [..] + } + \endcode + */ Fl_Widget *child(int n) const { return(table->child(n)); } + + /** + Returns the number of children in the table. + + When using the Fl_Table as a container for FLTK widgets, this method returns + how many child widgets the table has. + + \see child(int) + */ int children() const { return(table->children()-2); // -2: skip Fl_Scroll's h/v scrollbar widgets } @@ -431,21 +838,156 @@ public: return(table->find(w)); } // CALLBACKS + + /** + * Returns the current row the event occurred on. + * + * This function should only be used from within the user's callback function + */ int callback_row() { return(_callback_row); } + + /** + * Returns the current column the event occurred on. + * + * This function should only be used from within the user's callback function + */ int callback_col() { return(_callback_col); } + + /** + * Returns the current 'table context'. + * + * This function should only be used from within the user's callback function + */ 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(); } + +#if DOXYGEN + /** + The Fl_Widget::when() function is used to set a group of flags, determining + when the widget callback is called: + + <table border=1> + <tr> + <td>\p FL_WHEN_CHANGED</td> + <td> + callback() will be called when rows or columns are resized (interactively or + via col_width() or row_height()), passing CONTEXT_RC_RESIZE via + callback_context(). + </td> + </tr><tr> + <td>\p FL_WHEN_RELEASE</td> + <td> + callback() will be called during FL_RELEASE events, such as when someone + releases a mouse button somewhere on the table. + </td> + </tr> + </table> + + The callback() routine is sent a TableContext that indicates the context the + event occurred in, such as in a cell, in a header, or elsewhere on the table. + When an event occurs in a cell or header, callback_row() and + callback_col() can be used to determine the row and column. The callback can + also look at the regular fltk event values (ie. Fl::event() and Fl::button()) + to determine what kind of event is occurring. + */ + void when(Fl_When flags); +#endif + +#if DOXYGEN + /** + Callbacks will be called depending on the setting of Fl_Widget::when(). + + Callback functions should use the following functions to determine the + context/row/column: + + * Fl_Table::callback_row() returns current row + * Fl_Table::callback_col() returns current column + * Fl_Table::callback_context() returns current table context + + callback_row() and callback_col() will be set to the row and column number the + event occurred on. If someone clicked on a row header, \p col will be \a 0. + If someone clicked on a column header, \p row will be \a 0. + + callback_context() will return one of the following: + + <table border=1> + <tr><td><tt>Fl_Table::CONTEXT_ROW_HEADER</tt></td> + <td>Someone clicked on a row header. Excludes resizing.</td> + </tr><tr> + <td><tt>Fl_Table::CONTEXT_COL_HEADER</tt></td> + <td>Someone clicked on a column header. Excludes resizing.</td> + </tr><tr> + <td><tt>Fl_Table::CONTEXT_CELL</tt></td> + <td> + Someone clicked on a cell. + + To receive callbacks for FL_RELEASE events, you must set + when(FL_WHEN_RELEASE). + </td> + </tr><tr> + <td><tt>Fl_Table::CONTEXT_RC_RESIZE</tt></td> + <td> + Someone is resizing rows/columns either interactively, + or via the col_width() or row_height() API. + + Use is_interactive_resize() + to determine interactive resizing. + + If resizing a column, R=0 and C=column being resized. + + If resizing a row, C=0 and R=row being resized. + + NOTE: To receive resize events, you must set when(FL_WHEN_CHANGED). + </td> + </tr> + </table> + + \code + class MyTable + { + [..] + private: + // Handle events that happen on the table + void event_callback2() + { + int R = callback_row(), // row where event occurred + C = callback_col(); // column where event occurred + TableContext context = callback_context(); // which part of table + fprintf(stderr, "callback: Row=%d Col=%d Context=%d Event=%d\n", + R, C, (int)context, (int)Fl::event()); + } + + // Actual static callback + static void event_callback(Fl_Widget*, void* data) + { + MyTable *o = (MyTable*)data; + o->event_callback2(); + } + + public: + MyTable() // Constructor + { + [..] + table.callback(&event_callback, (void*)this); // setup callback + table.when(FL_WHEN_CHANGED|FL_WHEN_RELEASE); // when to call it + } + }; + \endcode + */ + void callback(Fl_Widget*, void*); +#endif }; #endif /*_FL_TABLE_H*/ diff --git a/documentation/src/table-dimensions.gif b/documentation/src/table-dimensions.gif Binary files differnew file mode 100644 index 000000000..e38ea5d5c --- /dev/null +++ b/documentation/src/table-dimensions.gif |
