Include a stripped-down version of FLTK in tree and add a USE_INCLUDED_FLTK option to build against it.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4603 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/fltk/src/Fl_Table_Row.cxx b/common/fltk/src/Fl_Table_Row.cxx
new file mode 100644
index 0000000..6e24bba
--- /dev/null
+++ b/common/fltk/src/Fl_Table_Row.cxx
@@ -0,0 +1,316 @@
+//
+// "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $"
+//
+// 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);
+}
+
+//
+// End of "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $".
+//