Tweak themes for more color consistency.
[ntk.git] / src / Fl_Table_Row.cxx
blob6e24bba0a6978c9aacf505c994688db93d45ca0b
1 //
2 // "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $"
3 //
4 // Fl_Table_Row -- A row oriented table widget
5 //
6 // A class specializing in a table of rows.
7 // Handles row-specific selection behavior.
8 //
9 // Copyright 2002 by Greg Ercolano.
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Library General Public
13 // License as published by the Free Software Foundation; either
14 // version 2 of the License, or (at your option) any later version.
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Library General Public License for more details.
21 // You should have received a copy of the GNU Library General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 // USA.
26 // Please report all bugs and problems to "erco at seriss dot com".
29 // TODO:
30 // o Row headings (only column headings supported currently)
33 #include <stdio.h> // for debugging
34 #include <FL/Fl.H>
35 #include <FL/fl_draw.H>
36 #include <FL/Fl_Table_Row.H>
38 // Is row selected?
39 int Fl_Table_Row::row_selected(int row) {
40 if ( row < 0 || row >= rows() ) return(-1);
41 return(_rowselect[row]);
44 // Change row selection type
45 void Fl_Table_Row::type(TableRowSelectMode val) {
46 _selectmode = val;
47 switch ( _selectmode ) {
48 case SELECT_NONE: {
49 for ( int row=0; row<rows(); row++ ) {
50 _rowselect[row] = 0;
52 redraw();
53 break;
55 case SELECT_SINGLE: {
56 int count = 0;
57 for ( int row=0; row<rows(); row++ ) {
58 if ( _rowselect[row] ) {
59 if ( ++count > 1 ) { // only one allowed
60 _rowselect[row] = 0;
64 redraw();
65 break;
67 case SELECT_MULTI:
68 break;
72 // Change selection state for row
74 // flag:
75 // 0 - clear selection
76 // 1 - set selection
77 // 2 - toggle selection
79 // Returns:
80 // 0 - selection state did not change
81 // 1 - selection state changed
82 // -1 - row out of range or incorrect selection mode
84 int Fl_Table_Row::select_row(int row, int flag) {
85 int ret = 0;
86 if ( row < 0 || row >= rows() ) { return(-1); }
87 switch ( _selectmode ) {
88 case SELECT_NONE:
89 return(-1);
91 case SELECT_SINGLE: {
92 int oldval;
93 for ( int t=0; t<rows(); t++ ) {
94 if ( t == row ) {
95 oldval = _rowselect[row];
96 if ( flag == 2 ) { _rowselect[row] ^= 1; }
97 else { _rowselect[row] = flag; }
98 if ( oldval != _rowselect[row] ) {
99 redraw_range(row, row, leftcol, rightcol);
100 ret = 1;
103 else if ( _rowselect[t] ) {
104 _rowselect[t] = 0;
105 redraw_range(t, t, leftcol, rightcol);
108 break;
111 case SELECT_MULTI: {
112 int oldval = _rowselect[row];
113 if ( flag == 2 ) { _rowselect[row] ^= 1; }
114 else { _rowselect[row] = flag; }
115 if ( _rowselect[row] != oldval ) { // select state changed?
116 if ( row >= toprow && row <= botrow ) { // row visible?
117 // Extend partial redraw range
118 redraw_range(row, row, leftcol, rightcol);
120 ret = 1;
124 return(ret);
127 // Select all rows to a known state
128 void Fl_Table_Row::select_all_rows(int flag) {
129 switch ( _selectmode ) {
130 case SELECT_NONE:
131 return;
133 case SELECT_SINGLE:
134 if ( flag != 0 ) return;
135 //FALLTHROUGH
137 case SELECT_MULTI: {
138 char changed = 0;
139 if ( flag == 2 ) {
140 for ( int row=0; row<(int)_rowselect.size(); row++ ) {
141 _rowselect[row] ^= 1;
143 changed = 1;
144 } else {
145 for ( int row=0; row<(int)_rowselect.size(); row++ ) {
146 changed |= (_rowselect[row] != flag)?1:0;
147 _rowselect[row] = flag;
150 if ( changed ) {
151 redraw();
157 // Set number of rows
158 void Fl_Table_Row::rows(int val) {
159 Fl_Table::rows(val);
160 while ( val > (int)_rowselect.size() ) { _rowselect.push_back(0); } // enlarge
161 while ( val < (int)_rowselect.size() ) { _rowselect.pop_back(); } // shrink
164 // #include "eventnames.h" // debugging
165 // #include <stdio.h>
167 // Handle events
168 int Fl_Table_Row::handle(int event) {
170 // fprintf(stderr, "** EVENT: %s: EVENT XY=%d,%d\n",
171 // eventnames[event], Fl::event_x(), Fl::event_y()); // debugging
173 // Let base class handle event
174 int ret = Fl_Table::handle(event);
176 // The following code disables cell selection.. why was it added? -erco 05/18/03
177 // if ( ret ) { _last_y = Fl::event_y(); return(1); } // base class 'handled' it (eg. column resize)
179 int shiftstate = (Fl::event_state() & FL_CTRL) ? FL_CTRL :
180 (Fl::event_state() & FL_SHIFT) ? FL_SHIFT : 0;
182 // Which row/column are we over?
183 int R, C; // row/column being worked on
184 ResizeFlag resizeflag; // which resizing area are we over? (0=none)
185 TableContext context = cursor2rowcol(R, C, resizeflag);
186 switch ( event ) {
187 case FL_PUSH:
188 if ( Fl::event_button() == 1 ) {
189 _last_push_x = Fl::event_x(); // save regardless of context
190 _last_push_y = Fl::event_y(); // " "
192 // Handle selection in table.
193 // Select cell under cursor, and enable drag selection mode.
195 if ( context == CONTEXT_CELL ) {
196 // Ctrl key? Toggle selection state
197 switch ( shiftstate ) {
198 case FL_CTRL:
199 select_row(R, 2); // toggle
200 break;
202 case FL_SHIFT: {
203 select_row(R, 1);
204 if ( _last_row > -1 ) {
205 int srow = R, erow = _last_row;
206 if ( srow > erow ) {
207 srow = _last_row;
208 erow = R;
210 for ( int row = srow; row <= erow; row++ ) {
211 select_row(row, 1);
214 break;
217 default:
218 select_all_rows(0); // clear all previous selections
219 select_row(R, 1);
220 break;
223 _last_row = R;
224 _dragging_select = 1;
225 ret = 1; // FL_PUSH handled (ensures FL_DRAG will be sent)
226 // redraw(); // redraw() handled by select_row()
229 break;
231 case FL_DRAG: {
232 if ( _dragging_select ) {
233 // Dragged off table edges? Handle scrolling
234 int offtop = toy - _last_y; // >0 if off top of table
235 int offbot = _last_y - (toy + toh); // >0 if off bottom of table
237 if ( offtop > 0 && row_position() > 0 ) {
238 // Only scroll in upward direction
239 int diff = _last_y - Fl::event_y();
240 if ( diff < 1 ) {
241 ret = 1;
242 break;
244 row_position(row_position() - diff);
245 context = CONTEXT_CELL; C = 0; R = row_position(); // HACK: fake it
246 if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly
248 else if ( offbot > 0 && botrow < rows() ) {
249 // Only scroll in downward direction
250 int diff = Fl::event_y() - _last_y;
251 if ( diff < 1 ) {
252 ret = 1;
253 break;
255 row_position(row_position() + diff);
256 context = CONTEXT_CELL; C = 0; R = botrow; // HACK: fake it
257 if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly
259 if ( context == CONTEXT_CELL ) {
260 switch ( shiftstate ) {
261 case FL_CTRL:
262 if ( R != _last_row ) { // toggle if dragged to new row
263 select_row(R, 2); // 2=toggle
265 break;
267 case FL_SHIFT:
268 default:
269 select_row(R, 1);
270 if ( _last_row > -1 ) {
271 int srow = R, erow = _last_row;
272 if ( srow > erow ) {
273 srow = _last_row;
274 erow = R;
276 for ( int row = srow; row <= erow; row++ ) {
277 select_row(row, 1);
280 break;
282 ret = 1; // drag handled
283 _last_row = R;
286 break;
289 case FL_RELEASE:
290 if ( Fl::event_button() == 1 ) {
291 _dragging_select = 0;
292 ret = 1; // release handled
293 // Clicked off edges of data table?
294 // A way for user to clear the current selection.
296 int databot = tiy + table_h,
297 dataright = tix + table_w;
298 if (
299 ( _last_push_x > dataright && Fl::event_x() > dataright ) ||
300 ( _last_push_y > databot && Fl::event_y() > databot )
302 select_all_rows(0); // clear previous selections
305 break;
307 default:
308 break;
310 _last_y = Fl::event_y();
311 return(ret);
315 // End of "$Id: Fl_Table_Row.cxx 7950 2010-12-05 01:22:53Z greg.ercolano $".