|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $" 00003 // 00004 // Fl_Table_Row -- A row oriented table widget 00005 // 00006 // A class specializing in a table of rows. 00007 // Handles row-specific selection behavior. 00008 // 00009 // Copyright 2002 by Greg Ercolano. 00010 // 00011 // This library is free software; you can redistribute it and/or 00012 // modify it under the terms of the GNU Library General Public 00013 // License as published by the Free Software Foundation; either 00014 // version 2 of the License, or (at your option) any later version. 00015 // 00016 // This library is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 // Library General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU Library General Public 00022 // License along with this library; if not, write to the Free Software 00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00024 // USA. 00025 // 00026 // Please report all bugs and problems to "erco at seriss dot com". 00027 // 00028 // 00029 // TODO: 00030 // o Row headings (only column headings supported currently) 00031 // 00032 00033 #include <stdio.h> // for debugging 00034 #include <FL/Fl.H> 00035 #include <FL/fl_draw.H> 00036 #include <FL/Fl_Table_Row.H> 00037 00038 // Is row selected? 00039 int Fl_Table_Row::row_selected(int row) { 00040 if ( row < 0 || row >= rows() ) return(-1); 00041 return(_rowselect[row]); 00042 } 00043 00044 // Change row selection type 00045 void Fl_Table_Row::type(TableRowSelectMode val) { 00046 _selectmode = val; 00047 switch ( _selectmode ) { 00048 case SELECT_NONE: { 00049 for ( int row=0; row<rows(); row++ ) { 00050 _rowselect[row] = 0; 00051 } 00052 redraw(); 00053 break; 00054 } 00055 case SELECT_SINGLE: { 00056 int count = 0; 00057 for ( int row=0; row<rows(); row++ ) { 00058 if ( _rowselect[row] ) { 00059 if ( ++count > 1 ) { // only one allowed 00060 _rowselect[row] = 0; 00061 } 00062 } 00063 } 00064 redraw(); 00065 break; 00066 } 00067 case SELECT_MULTI: 00068 break; 00069 } 00070 } 00071 00072 // Change selection state for row 00073 // 00074 // flag: 00075 // 0 - clear selection 00076 // 1 - set selection 00077 // 2 - toggle selection 00078 // 00079 // Returns: 00080 // 0 - selection state did not change 00081 // 1 - selection state changed 00082 // -1 - row out of range or incorrect selection mode 00083 // 00084 int Fl_Table_Row::select_row(int row, int flag) { 00085 int ret = 0; 00086 if ( row < 0 || row >= rows() ) { return(-1); } 00087 switch ( _selectmode ) { 00088 case SELECT_NONE: 00089 return(-1); 00090 00091 case SELECT_SINGLE: { 00092 int oldval; 00093 for ( int t=0; t<rows(); t++ ) { 00094 if ( t == row ) { 00095 oldval = _rowselect[row]; 00096 if ( flag == 2 ) { _rowselect[row] ^= 1; } 00097 else { _rowselect[row] = flag; } 00098 if ( oldval != _rowselect[row] ) { 00099 redraw_range(row, row, leftcol, rightcol); 00100 ret = 1; 00101 } 00102 } 00103 else if ( _rowselect[t] ) { 00104 _rowselect[t] = 0; 00105 redraw_range(t, t, leftcol, rightcol); 00106 } 00107 } 00108 break; 00109 } 00110 00111 case SELECT_MULTI: { 00112 int oldval = _rowselect[row]; 00113 if ( flag == 2 ) { _rowselect[row] ^= 1; } 00114 else { _rowselect[row] = flag; } 00115 if ( _rowselect[row] != oldval ) { // select state changed? 00116 if ( row >= toprow && row <= botrow ) { // row visible? 00117 // Extend partial redraw range 00118 redraw_range(row, row, leftcol, rightcol); 00119 } 00120 ret = 1; 00121 } 00122 } 00123 } 00124 return(ret); 00125 } 00126 00127 // Select all rows to a known state 00128 void Fl_Table_Row::select_all_rows(int flag) { 00129 switch ( _selectmode ) { 00130 case SELECT_NONE: 00131 return; 00132 00133 case SELECT_SINGLE: 00134 if ( flag != 0 ) return; 00135 //FALLTHROUGH 00136 00137 case SELECT_MULTI: { 00138 char changed = 0; 00139 if ( flag == 2 ) { 00140 for ( int row=0; row<(int)_rowselect.size(); row++ ) { 00141 _rowselect[row] ^= 1; 00142 } 00143 changed = 1; 00144 } else { 00145 for ( int row=0; row<(int)_rowselect.size(); row++ ) { 00146 changed |= (_rowselect[row] != flag)?1:0; 00147 _rowselect[row] = flag; 00148 } 00149 } 00150 if ( changed ) { 00151 redraw(); 00152 } 00153 } 00154 } 00155 } 00156 00157 // Set number of rows 00158 void Fl_Table_Row::rows(int val) { 00159 Fl_Table::rows(val); 00160 while ( val > (int)_rowselect.size() ) { _rowselect.push_back(0); } // enlarge 00161 while ( val < (int)_rowselect.size() ) { _rowselect.pop_back(); } // shrink 00162 } 00163 00164 // #include "eventnames.h" // debugging 00165 // #include <stdio.h> 00166 00167 // Handle events 00168 int Fl_Table_Row::handle(int event) { 00169 00170 // fprintf(stderr, "** EVENT: %s: EVENT XY=%d,%d\n", 00171 // eventnames[event], Fl::event_x(), Fl::event_y()); // debugging 00172 00173 // Let base class handle event 00174 int ret = Fl_Table::handle(event); 00175 00176 // The following code disables cell selection.. why was it added? -erco 05/18/03 00177 // if ( ret ) { _last_y = Fl::event_y(); return(1); } // base class 'handled' it (eg. column resize) 00178 00179 int shiftstate = (Fl::event_state() & FL_CTRL) ? FL_CTRL : 00180 (Fl::event_state() & FL_SHIFT) ? FL_SHIFT : 0; 00181 00182 // Which row/column are we over? 00183 int R, C; // row/column being worked on 00184 ResizeFlag resizeflag; // which resizing area are we over? (0=none) 00185 TableContext context = cursor2rowcol(R, C, resizeflag); 00186 switch ( event ) { 00187 case FL_PUSH: 00188 if ( Fl::event_button() == 1 ) { 00189 _last_push_x = Fl::event_x(); // save regardless of context 00190 _last_push_y = Fl::event_y(); // " " 00191 00192 // Handle selection in table. 00193 // Select cell under cursor, and enable drag selection mode. 00194 // 00195 if ( context == CONTEXT_CELL ) { 00196 // Ctrl key? Toggle selection state 00197 switch ( shiftstate ) { 00198 case FL_CTRL: 00199 select_row(R, 2); // toggle 00200 break; 00201 00202 case FL_SHIFT: { 00203 select_row(R, 1); 00204 if ( _last_row > -1 ) { 00205 int srow = R, erow = _last_row; 00206 if ( srow > erow ) { 00207 srow = _last_row; 00208 erow = R; 00209 } 00210 for ( int row = srow; row <= erow; row++ ) { 00211 select_row(row, 1); 00212 } 00213 } 00214 break; 00215 } 00216 00217 default: 00218 select_all_rows(0); // clear all previous selections 00219 select_row(R, 1); 00220 break; 00221 } 00222 00223 _last_row = R; 00224 _dragging_select = 1; 00225 ret = 1; // FL_PUSH handled (ensures FL_DRAG will be sent) 00226 // redraw(); // redraw() handled by select_row() 00227 } 00228 } 00229 break; 00230 00231 case FL_DRAG: { 00232 if ( _dragging_select ) { 00233 // Dragged off table edges? Handle scrolling 00234 int offtop = toy - _last_y; // >0 if off top of table 00235 int offbot = _last_y - (toy + toh); // >0 if off bottom of table 00236 00237 if ( offtop > 0 && row_position() > 0 ) { 00238 // Only scroll in upward direction 00239 int diff = _last_y - Fl::event_y(); 00240 if ( diff < 1 ) { 00241 ret = 1; 00242 break; 00243 } 00244 row_position(row_position() - diff); 00245 context = CONTEXT_CELL; C = 0; R = row_position(); // HACK: fake it 00246 if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly 00247 } 00248 else if ( offbot > 0 && botrow < rows() ) { 00249 // Only scroll in downward direction 00250 int diff = Fl::event_y() - _last_y; 00251 if ( diff < 1 ) { 00252 ret = 1; 00253 break; 00254 } 00255 row_position(row_position() + diff); 00256 context = CONTEXT_CELL; C = 0; R = botrow; // HACK: fake it 00257 if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly 00258 } 00259 if ( context == CONTEXT_CELL ) { 00260 switch ( shiftstate ) { 00261 case FL_CTRL: 00262 if ( R != _last_row ) { // toggle if dragged to new row 00263 select_row(R, 2); // 2=toggle 00264 } 00265 break; 00266 00267 case FL_SHIFT: 00268 default: 00269 select_row(R, 1); 00270 if ( _last_row > -1 ) { 00271 int srow = R, erow = _last_row; 00272 if ( srow > erow ) { 00273 srow = _last_row; 00274 erow = R; 00275 } 00276 for ( int row = srow; row <= erow; row++ ) { 00277 select_row(row, 1); 00278 } 00279 } 00280 break; 00281 } 00282 ret = 1; // drag handled 00283 _last_row = R; 00284 } 00285 } 00286 break; 00287 } 00288 00289 case FL_RELEASE: 00290 if ( Fl::event_button() == 1 ) { 00291 _dragging_select = 0; 00292 ret = 1; // release handled 00293 // Clicked off edges of data table? 00294 // A way for user to clear the current selection. 00295 // 00296 int databot = tiy + table_h, 00297 dataright = tix + table_w; 00298 if ( 00299 ( _last_push_x > dataright && Fl::event_x() > dataright ) || 00300 ( _last_push_y > databot && Fl::event_y() > databot ) 00301 ) { 00302 select_all_rows(0); // clear previous selections 00303 } 00304 } 00305 break; 00306 00307 default: 00308 break; 00309 } 00310 _last_y = Fl::event_y(); 00311 return(ret); 00312 } 00313 00314 // 00315 // End of "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $". 00316 //