]> git.saurik.com Git - wxWidgets.git/blame - src/generic/gridsel.cpp
fix for infinite loop in wxFileConfig when reading from input stream fails (patch...
[wxWidgets.git] / src / generic / gridsel.cpp
CommitLineData
294f6bcb
SN
1///////////////////////////////////////////////////////////////////////////
2// Name: generic/gridsel.cpp
3// Purpose: wxGridSelection
4// Author: Stefan Neis
5// Modified by:
6// Created: 20/02/1999
2b5f62a0 7// RCS-ID: $Id$
294f6bcb
SN
8// Copyright: (c) Stefan Neis (Stefan.Neis@t-online.de)
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
294f6bcb
SN
21 #pragma implementation "gridsel.h"
22#endif
23
24// For compilers that support precompilation, includes "wx/wx.h".
25#include "wx/wxprec.h"
26
27#include "wx/defs.h"
28
29#ifdef __BORLANDC__
30 #pragma hdrstop
31#endif
32
f7556ff0 33#if wxUSE_GRID
f1567cdd 34
294f6bcb
SN
35#include "wx/generic/gridsel.h"
36
f1567cdd
SN
37// Some explanation for the members of the class:
38// m_cellSelection stores individual selected cells
39// -- this is only used if m_selectionMode == wxGridSelectCells
40// m_blockSelectionTopLeft and m_blockSelectionBottomRight
41// store the upper left and lower right corner of selected Blocks
42// m_rowSelection and m_colSelection store individual selected
43// rows and columns; maybe those are superfluous and should be
44// treated as blocks?
45
294f6bcb 46wxGridSelection::wxGridSelection( wxGrid * grid,
b5808881 47 wxGrid::wxGridSelectionModes sel )
294f6bcb
SN
48{
49 m_grid = grid;
50 m_selectionMode = sel;
51}
52
53bool wxGridSelection::IsSelection()
54{
55 return ( m_cellSelection.GetCount() || m_blockSelectionTopLeft.GetCount() ||
b5808881 56 m_rowSelection.GetCount() || m_colSelection.GetCount() );
294f6bcb
SN
57}
58
59bool wxGridSelection::IsInSelection ( int row, int col )
60{
f1567cdd
SN
61 size_t count;
62
63 // First check whether the given cell is individually selected
64 // (if m_selectionMode is wxGridSelectCells).
65 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
66 {
67 count = m_cellSelection.GetCount();
b5808881
SN
68 for ( size_t n = 0; n < count; n++ )
69 {
70 wxGridCellCoords& coords = m_cellSelection[n];
71 if ( row == coords.GetRow() && col == coords.GetCol() )
0912bee1 72 return TRUE;
b5808881 73 }
294f6bcb 74 }
f1567cdd
SN
75
76 // Now check whether the given cell is
77 // contained in one of the selected blocks.
294f6bcb
SN
78 count = m_blockSelectionTopLeft.GetCount();
79 for ( size_t n = 0; n < count; n++ )
80 {
b5808881
SN
81 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
82 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
83 if ( BlockContainsCell(coords1.GetRow(), coords1.GetCol(),
84 coords2.GetRow(), coords2.GetCol(),
85 row, col ) )
0912bee1 86 return TRUE;
b5808881 87 }
f1567cdd
SN
88
89 // Now check whether the given cell is
90 // contained in one of the selected rows
91 // (unless we are in column selection mode).
b5808881 92 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 93 {
b5808881
SN
94 size_t count = m_rowSelection.GetCount();
95 for ( size_t n = 0; n < count; n++ )
96 {
97 if ( row == m_rowSelection[n] )
0912bee1 98 return TRUE;
b5808881
SN
99 }
100 }
f1567cdd
SN
101
102 // Now check whether the given cell is
103 // contained in one of the selected columns
104 // (unless we are in row selection mode).
b5808881 105 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 106 {
b5808881
SN
107 size_t count = m_colSelection.GetCount();
108 for ( size_t n = 0; n < count; n++ )
109 {
110 if ( col == m_colSelection[n] )
0912bee1 111 return TRUE;
b5808881 112 }
294f6bcb 113 }
0912bee1 114 return FALSE;
294f6bcb
SN
115}
116
f1567cdd
SN
117// Change the selection mode
118void wxGridSelection::SetSelectionMode(wxGrid::wxGridSelectionModes selmode)
119{
120 // if selection mode is unchanged return immediately
121 if (selmode == m_selectionMode)
122 return;
123
124 if ( m_selectionMode != wxGrid::wxGridSelectCells )
125 {
126 // if changing form row to column selection
127 // or vice versa, clear the selection.
128 if ( selmode != wxGrid::wxGridSelectCells )
129 ClearSelection();
130
131 m_selectionMode = selmode;
132 }
133 else
134 {
135 // if changing from cell selection to something else,
136 // promote selected cells/blocks to whole rows/columns.
137 size_t n;
138 while ( ( n = m_cellSelection.GetCount() ) > 0 )
139 {
140 n--;
141 wxGridCellCoords& coords = m_cellSelection[n];
142 int row = coords.GetRow();
143 int col = coords.GetCol();
144 m_cellSelection.RemoveAt(n);
145 if (selmode == wxGrid::wxGridSelectRows)
146 SelectRow( row );
147 else // selmode == wxGridSelectColumns)
148 SelectCol( col );
149 }
043d16b2
SN
150
151 for (n = 0; n < m_blockSelectionTopLeft.GetCount(); n++)
152 // Note that m_blockSelectionTopLeft's size may be changing!
f1567cdd 153 {
f1567cdd
SN
154 wxGridCellCoords& coords = m_blockSelectionTopLeft[n];
155 int topRow = coords.GetRow();
156 int leftCol = coords.GetCol();
157 coords = m_blockSelectionBottomRight[n];
158 int bottomRow = coords.GetRow();
159 int rightCol = coords.GetCol();
160 if (selmode == wxGrid::wxGridSelectRows)
161 {
162 if (leftCol != 0 || rightCol != m_grid->GetNumberCols() - 1 )
163 {
164 m_blockSelectionTopLeft.RemoveAt(n);
165 m_blockSelectionBottomRight.RemoveAt(n);
166 SelectBlock( topRow, 0,
5c8fc7c1 167 bottomRow, m_grid->GetNumberCols() - 1,
2b5f62a0 168 FALSE, FALSE, FALSE, FALSE, FALSE );
f1567cdd
SN
169 }
170 }
171 else // selmode == wxGridSelectColumns)
172 {
173 if (topRow != 0 || bottomRow != m_grid->GetNumberRows() - 1 )
174 {
175 m_blockSelectionTopLeft.RemoveAt(n);
176 m_blockSelectionBottomRight.RemoveAt(n);
177 SelectBlock( 0, leftCol,
5c8fc7c1 178 m_grid->GetNumberRows() - 1, rightCol,
2b5f62a0 179 FALSE, FALSE, FALSE, FALSE, FALSE );
f1567cdd
SN
180 }
181 }
182 }
043d16b2 183 m_selectionMode = selmode;
f1567cdd
SN
184 }
185}
186
723d1b1d 187void wxGridSelection::SelectRow( int row,
d95b0c2b
SN
188 bool ControlDown, bool ShiftDown,
189 bool AltDown, bool MetaDown )
294f6bcb 190{
b5808881 191 if ( m_selectionMode == wxGrid::wxGridSelectColumns )
294f6bcb 192 return;
f1567cdd 193 size_t count, n;
294f6bcb
SN
194
195 // Remove single cells contained in newly selected block.
f1567cdd 196 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
197 {
198 count = m_cellSelection.GetCount();
f1567cdd 199 for ( n = 0; n < count; n++ )
b5808881
SN
200 {
201 wxGridCellCoords& coords = m_cellSelection[n];
202 if ( BlockContainsCell( row, 0, row, m_grid->GetNumberCols() - 1,
203 coords.GetRow(), coords.GetCol() ) )
204 {
205 m_cellSelection.RemoveAt(n);
206 n--; count--;
207 }
208 }
294f6bcb
SN
209 }
210
f1567cdd 211 // Simplify list of selected blocks (if possible)
294f6bcb 212 count = m_blockSelectionTopLeft.GetCount();
0912bee1 213 bool done = FALSE;
b14159f7 214 for ( n = 0; n < count; n++ )
294f6bcb 215 {
b5808881
SN
216 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
217 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
f1567cdd
SN
218
219 // Remove block if it is a subset of the row
b5808881
SN
220 if ( coords1.GetRow() == row && row == coords2.GetRow() )
221 {
222 m_blockSelectionTopLeft.RemoveAt(n);
223 m_blockSelectionBottomRight.RemoveAt(n);
224 n--; count--;
f1e26920 225 }
b5808881
SN
226 else if ( coords1.GetCol() == 0 &&
227 coords2.GetCol() == m_grid->GetNumberCols() - 1 )
228 {
f1567cdd 229 // silently return, if row is contained in block
b5808881
SN
230 if ( coords1.GetRow() <= row && row <= coords2.GetRow() )
231 return;
f1567cdd 232 // expand block, if it touched row
b5808881
SN
233 else if ( coords1.GetRow() == row + 1)
234 {
235 coords1.SetRow(row);
0912bee1 236 done = TRUE;
b5808881
SN
237 }
238 else if ( coords2.GetRow() == row - 1)
239 {
240 coords2.SetRow(row);
0912bee1 241 done = TRUE;
f1e26920 242 }
b5808881 243 }
294f6bcb
SN
244 }
245
f1567cdd
SN
246 // Unless we successfully handled the row,
247 // check whether row is already selected.
248 if ( !done )
294f6bcb 249 {
f1567cdd
SN
250 count = m_rowSelection.GetCount();
251 for ( n = 0; n < count; n++ )
252 {
253 if ( row == m_rowSelection[n] )
254 return;
255 }
294f6bcb 256
f1567cdd
SN
257 // Add row to selection
258 m_rowSelection.Add(row);
259 }
b5808881
SN
260
261 // Update View:
262 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
263 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
264 if ( !m_grid->GetBatchCount() )
265 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 266
5c8fc7c1
SN
267 // Send Event
268 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
269 wxEVT_GRID_RANGE_SELECT,
270 m_grid,
271 wxGridCellCoords( row, 0 ),
d95b0c2b
SN
272 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
273 TRUE,
274 ControlDown, ShiftDown,
275 AltDown, MetaDown );
5c8fc7c1
SN
276
277 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
294f6bcb
SN
278}
279
723d1b1d 280void wxGridSelection::SelectCol( int col,
d95b0c2b
SN
281 bool ControlDown, bool ShiftDown,
282 bool AltDown, bool MetaDown )
294f6bcb 283{
b5808881 284 if ( m_selectionMode == wxGrid::wxGridSelectRows )
294f6bcb 285 return;
f1567cdd 286 size_t count, n;
294f6bcb
SN
287
288 // Remove single cells contained in newly selected block.
f1567cdd 289 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
290 {
291 count = m_cellSelection.GetCount();
f1567cdd 292 for ( n = 0; n < count; n++ )
b5808881
SN
293 {
294 wxGridCellCoords& coords = m_cellSelection[n];
295 if ( BlockContainsCell( 0, col, m_grid->GetNumberRows() - 1, col,
296 coords.GetRow(), coords.GetCol() ) )
297 {
298 m_cellSelection.RemoveAt(n);
299 n--; count--;
300 }
301 }
294f6bcb
SN
302 }
303
f1567cdd 304 // Simplify list of selected blocks (if possible)
294f6bcb 305 count = m_blockSelectionTopLeft.GetCount();
0912bee1 306 bool done = FALSE;
b14159f7 307 for ( n = 0; n < count; n++ )
294f6bcb 308 {
b5808881
SN
309 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
310 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
f1567cdd
SN
311
312 // Remove block if it is a subset of the column
b5808881
SN
313 if ( coords1.GetCol() == col && col == coords2.GetCol() )
314 {
315 m_blockSelectionTopLeft.RemoveAt(n);
316 m_blockSelectionBottomRight.RemoveAt(n);
317 n--; count--;
318 }
319 else if ( coords1.GetRow() == 0 &&
320 coords2.GetRow() == m_grid->GetNumberRows() - 1 )
321 {
f1567cdd 322 // silently return, if row is contained in block
b5808881
SN
323 if ( coords1.GetCol() <= col && col <= coords2.GetCol() )
324 return;
f1567cdd 325 // expand block, if it touched col
b5808881
SN
326 else if ( coords1.GetCol() == col + 1)
327 {
328 coords1.SetCol(col);
0912bee1 329 done = TRUE;
b5808881
SN
330 }
331 else if ( coords2.GetCol() == col - 1)
332 {
333 coords2.SetCol(col);
0912bee1 334 done = TRUE;
f1e26920 335 }
b5808881 336 }
294f6bcb
SN
337 }
338
f1567cdd 339 // Unless we successfully handled the column,
294f6bcb 340 // Check whether col is already selected.
f1567cdd 341 if ( !done )
294f6bcb 342 {
f1567cdd
SN
343 count = m_colSelection.GetCount();
344 for ( n = 0; n < count; n++ )
345 {
346 if ( col == m_colSelection[n] )
347 return;
348 }
294f6bcb 349
f1567cdd
SN
350 // Add col to selection
351 m_colSelection.Add(col);
352 }
b5808881
SN
353
354 // Update View:
355 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
356 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
357 if ( !m_grid->GetBatchCount() )
358 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 359
5c8fc7c1
SN
360 // Send Event
361 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
362 wxEVT_GRID_RANGE_SELECT,
363 m_grid,
364 wxGridCellCoords( 0, col ),
d95b0c2b
SN
365 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
366 TRUE,
367 ControlDown, ShiftDown,
368 AltDown, MetaDown );
5c8fc7c1
SN
369
370 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
294f6bcb
SN
371}
372
5c8fc7c1
SN
373void wxGridSelection::SelectBlock( int topRow, int leftCol,
374 int bottomRow, int rightCol,
d95b0c2b 375 bool ControlDown, bool ShiftDown,
f1e26920 376 bool AltDown, bool MetaDown,
d95b0c2b 377 bool sendEvent )
294f6bcb 378{
5c8fc7c1 379 // Fix the coordinates of the block if needed.
b5808881 380 if ( m_selectionMode == wxGrid::wxGridSelectRows )
294f6bcb 381 {
b5808881
SN
382 leftCol = 0;
383 rightCol = m_grid->GetNumberCols() - 1;
294f6bcb 384 }
b5808881 385 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
294f6bcb 386 {
b5808881
SN
387 topRow = 0;
388 bottomRow = m_grid->GetNumberRows() - 1;
294f6bcb 389 }
5c8fc7c1
SN
390 if ( topRow > bottomRow )
391 {
392 int temp = topRow;
393 topRow = bottomRow;
394 bottomRow = temp;
395 }
396
397 if ( leftCol > rightCol )
398 {
399 int temp = leftCol;
400 leftCol = rightCol;
401 rightCol = temp;
402 }
294f6bcb
SN
403
404 // Handle single cell selection in SelectCell.
695a3263
MB
405 // (MB: added check for selection mode here to prevent
406 // crashes if, for example, we are select rows and the
407 // grid only has 1 col)
408 if ( m_selectionMode == wxGrid::wxGridSelectCells &&
409 topRow == bottomRow && leftCol == rightCol )
d95b0c2b
SN
410 SelectCell( topRow, leftCol, ControlDown, ShiftDown,
411 AltDown, MetaDown, sendEvent );
294f6bcb 412
f1567cdd 413 size_t count, n;
294f6bcb 414 // Remove single cells contained in newly selected block.
f1567cdd 415 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
416 {
417 count = m_cellSelection.GetCount();
f1567cdd 418 for ( n = 0; n < count; n++ )
b5808881
SN
419 {
420 wxGridCellCoords& coords = m_cellSelection[n];
421 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol,
422 coords.GetRow(), coords.GetCol() ) )
423 {
424 m_cellSelection.RemoveAt(n);
425 n--; count--;
426 }
427 }
294f6bcb
SN
428 }
429
430 // If a block containing the selection is already selected, return,
431 // if a block contained in the selection is found, remove it.
432
433 count = m_blockSelectionTopLeft.GetCount();
f1567cdd 434 for ( n = 0; n < count; n++ )
294f6bcb 435 {
b5808881
SN
436 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
437 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
438 switch ( BlockContain( coords1.GetRow(), coords1.GetCol(),
439 coords2.GetRow(), coords2.GetCol(),
440 topRow, leftCol, bottomRow, rightCol ) )
441 {
442 case 1:
443 return;
444 case -1:
445 m_blockSelectionTopLeft.RemoveAt(n);
446 m_blockSelectionBottomRight.RemoveAt(n);
447 n--; count--;
448 default:
449 ;
450 }
294f6bcb
SN
451 }
452
453 // If a row containing the selection is already selected, return,
454 // if a row contained in newly selected block is found, remove it.
b5808881 455 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 456 {
f1567cdd
SN
457 count = m_rowSelection.GetCount();
458 for ( n = 0; n < count; n++ )
b5808881
SN
459 {
460 switch ( BlockContain( m_rowSelection[n], 0,
461 m_rowSelection[n], m_grid->GetNumberCols()-1,
462 topRow, leftCol, bottomRow, rightCol ) )
463 {
464 case 1:
465 return;
466 case -1:
467 m_rowSelection.RemoveAt(n);
468 n--; count--;
469 default:
470 ;
471 }
472 }
473 }
474 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 475 {
f1567cdd
SN
476 count = m_colSelection.GetCount();
477 for ( n = 0; n < count; n++ )
b5808881
SN
478 {
479 switch ( BlockContain( 0, m_colSelection[n],
f1e26920 480 m_grid->GetNumberRows()-1, m_colSelection[n],
b5808881
SN
481 topRow, leftCol, bottomRow, rightCol ) )
482 {
483 case 1:
484 return;
485 case -1:
486 m_colSelection.RemoveAt(n);
487 n--; count--;
488 default:
489 ;
490 }
491 }
294f6bcb
SN
492 }
493 m_blockSelectionTopLeft.Add( wxGridCellCoords( topRow, leftCol ) );
494 m_blockSelectionBottomRight.Add( wxGridCellCoords( bottomRow, rightCol ) );
b5808881
SN
495
496 // Update View:
497 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( topRow, leftCol ),
498 wxGridCellCoords( bottomRow, rightCol ) );
499 if ( !m_grid->GetBatchCount() )
500 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 501
5c8fc7c1
SN
502 // Send Event, if not disabled.
503 if ( sendEvent )
504 {
d95b0c2b
SN
505 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
506 wxEVT_GRID_RANGE_SELECT,
507 m_grid,
508 wxGridCellCoords( topRow, leftCol ),
509 wxGridCellCoords( bottomRow, rightCol ),
510 TRUE,
511 ControlDown, ShiftDown,
512 AltDown, MetaDown );
513 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
5c8fc7c1 514 }
294f6bcb
SN
515}
516
d95b0c2b
SN
517void wxGridSelection::SelectCell( int row, int col,
518 bool ControlDown, bool ShiftDown,
519 bool AltDown, bool MetaDown,
520 bool sendEvent )
294f6bcb 521{
b5808881 522 if ( m_selectionMode == wxGrid::wxGridSelectRows )
043d16b2 523 {
f6bcfd97 524 SelectBlock(row, 0, row, m_grid->GetNumberCols() - 1,
2b5f62a0 525 ControlDown, ShiftDown, AltDown, MetaDown, sendEvent);
043d16b2
SN
526 return;
527 }
b5808881 528 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
043d16b2 529 {
f6bcfd97 530 SelectBlock(0, col, m_grid->GetNumberRows() - 1, col,
2b5f62a0 531 ControlDown, ShiftDown, AltDown, MetaDown, sendEvent);
043d16b2
SN
532 return;
533 }
294f6bcb
SN
534 else if ( IsInSelection ( row, col ) )
535 return;
536 m_cellSelection.Add( wxGridCellCoords( row, col ) );
b5808881 537
f1567cdd 538 // Update View:
b5808881
SN
539 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, col ),
540 wxGridCellCoords( row, col ) );
541 if ( !m_grid->GetBatchCount() )
542 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 543
5c8fc7c1 544 // Send event
d95b0c2b
SN
545 if (sendEvent)
546 {
f6bcfd97
BP
547 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
548 wxEVT_GRID_RANGE_SELECT,
549 m_grid,
550 wxGridCellCoords( row, col ),
551 wxGridCellCoords( row, col ),
f1e26920 552 TRUE,
f6bcfd97
BP
553 ControlDown, ShiftDown,
554 AltDown, MetaDown);
d95b0c2b
SN
555 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
556 }
294f6bcb
SN
557}
558
d95b0c2b
SN
559void wxGridSelection::ToggleCellSelection( int row, int col,
560 bool ControlDown, bool ShiftDown,
561 bool AltDown, bool MetaDown )
294f6bcb 562{
f1567cdd 563 // if the cell is not selected, select it
294f6bcb 564 if ( !IsInSelection ( row, col ) )
b5808881 565 {
d95b0c2b
SN
566 SelectCell( row, col, ControlDown, ShiftDown,
567 AltDown, MetaDown );
b5808881
SN
568 return;
569 }
294f6bcb 570
f1567cdd
SN
571 // otherwise deselect it. This can be simple or more or
572 // less difficult, depending on how the cell is selected.
573 size_t count, n;
574
575 // The simplest case: The cell is contained in m_cellSelection
576 // Then it can't be contained in rows/cols/block (since those
577 // would remove the cell from m_cellSelection on creation), so
578 // we just have to remove it from m_cellSelection.
294f6bcb 579
f1567cdd 580 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
581 {
582 count = m_cellSelection.GetCount();
f1567cdd 583 for ( n = 0; n < count; n++ )
b5808881
SN
584 {
585 wxGridCellCoords& coords = m_cellSelection[n];
586 if ( row == coords.GetRow() && col == coords.GetCol() )
587 {
588 wxRect r;
589 r = m_grid->BlockToDeviceRect( m_cellSelection[n],
590 m_cellSelection[n] );
591 m_cellSelection.RemoveAt(n);
b5808881
SN
592 if ( !m_grid->GetBatchCount() )
593 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
5c8fc7c1
SN
594
595 // Send event
f6bcfd97
BP
596 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
597 wxEVT_GRID_RANGE_SELECT,
598 m_grid,
599 wxGridCellCoords( row, col ),
600 wxGridCellCoords( row, col ),
601 FALSE,
602 ControlDown, ShiftDown,
603 AltDown, MetaDown );
5c8fc7c1 604 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
723d1b1d 605 return;
b5808881
SN
606 }
607 }
294f6bcb
SN
608 }
609
f1567cdd
SN
610 // The most difficult case: The cell is member of one or even several
611 // blocks. Split each such block in up to 4 new parts, that don't
612 // contain the cell to be selected, like this:
613 // |---------------------------|
614 // | |
615 // | part 1 |
616 // | |
617 // |---------------------------|
618 // | part 3 |x| part 4 |
619 // |---------------------------|
620 // | |
621 // | part 2 |
622 // | |
623 // |---------------------------|
624 // (The x marks the newly deselected cell).
625 // Note: in row selection mode, we only need part1 and part2;
626 // in column selection mode, we only need part 3 and part4,
627 // which are expanded to whole columns automatically!
628
294f6bcb 629 count = m_blockSelectionTopLeft.GetCount();
f1567cdd 630 for ( n = 0; n < count; n++ )
294f6bcb 631 {
b5808881
SN
632 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
633 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
634 int topRow = coords1.GetRow();
635 int leftCol = coords1.GetCol();
636 int bottomRow = coords2.GetRow();
637 int rightCol = coords2.GetCol();
638 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol,
639 row, col ) )
640 {
641 // remove the block
642 m_blockSelectionTopLeft.RemoveAt(n);
643 m_blockSelectionBottomRight.RemoveAt(n);
644 n--; count--;
645 // add up to 4 smaller blocks and set update region
646 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
647 {
648 if ( topRow < row )
2b5f62a0
VZ
649 SelectBlock( topRow, leftCol, row - 1, rightCol,
650 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881 651 if ( bottomRow > row )
2b5f62a0
VZ
652 SelectBlock( row + 1, leftCol, bottomRow, rightCol,
653 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881
SN
654 }
655 if ( m_selectionMode != wxGrid::wxGridSelectRows )
656 {
657 if ( leftCol < col )
2b5f62a0
VZ
658 SelectBlock( row, leftCol, row, col - 1,
659 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881 660 if ( rightCol > col )
2b5f62a0
VZ
661 SelectBlock( row, col + 1, row, rightCol,
662 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881
SN
663 }
664 }
294f6bcb
SN
665 }
666
667 // remove a cell from a row, adding up to two new blocks
b5808881 668 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 669 {
f1567cdd
SN
670 count = m_rowSelection.GetCount();
671 for ( n = 0; n < count; n++ )
b5808881
SN
672 {
673 if ( m_rowSelection[n] == row )
674 {
675 m_rowSelection.RemoveAt(n);
676 n--; count--;
677 if (m_selectionMode == wxGrid::wxGridSelectCells)
678 {
679 if ( col > 0 )
2b5f62a0
VZ
680 SelectBlock( row, 0, row, col - 1,
681 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881 682 if ( col < m_grid->GetNumberCols() - 1 )
5c8fc7c1
SN
683 SelectBlock( row, col + 1,
684 row, m_grid->GetNumberCols() - 1,
2b5f62a0 685 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881
SN
686 }
687 }
688 }
294f6bcb
SN
689 }
690
691 // remove a cell from a column, adding up to two new blocks
b5808881 692 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 693 {
f1567cdd
SN
694 count = m_colSelection.GetCount();
695 for ( n = 0; n < count; n++ )
b5808881
SN
696 {
697 if ( m_colSelection[n] == col )
698 {
699 m_colSelection.RemoveAt(n);
700 n--; count--;
701 if (m_selectionMode == wxGrid::wxGridSelectCells)
702 {
703 if ( row > 0 )
2b5f62a0
VZ
704 SelectBlock( 0, col, row - 1, col,
705 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881 706 if ( row < m_grid->GetNumberRows() - 1 )
5c8fc7c1
SN
707 SelectBlock( row + 1, col,
708 m_grid->GetNumberRows() - 1, col,
2b5f62a0 709 FALSE, FALSE, FALSE, FALSE, FALSE );
b5808881
SN
710 }
711 }
712 }
294f6bcb 713 }
f1567cdd 714
5c8fc7c1
SN
715 // Refresh the screen and send the event; according to m_selectionMode,
716 // we need to either update only the cell, or the whole row/column.
294f6bcb
SN
717 wxRect r;
718 switch (m_selectionMode)
719 {
b5808881 720 case wxGrid::wxGridSelectCells:
5c8fc7c1
SN
721 {
722 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, col ),
723 wxGridCellCoords( row, col ) );
724 if ( !m_grid->GetBatchCount() )
725 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f6bcfd97
BP
726 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
727 wxEVT_GRID_RANGE_SELECT,
728 m_grid,
729 wxGridCellCoords( row, col ),
730 wxGridCellCoords( row, col ),
731 FALSE,
732 ControlDown, ShiftDown,
733 AltDown, MetaDown );
5c8fc7c1
SN
734 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
735 break;
736 }
b5808881 737 case wxGrid::wxGridSelectRows:
5c8fc7c1
SN
738 {
739 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
740 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
741 if ( !m_grid->GetBatchCount() )
742 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
743 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
744 wxEVT_GRID_RANGE_SELECT,
745 m_grid,
746 wxGridCellCoords( row, 0 ),
747 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
d95b0c2b
SN
748 FALSE,
749 ControlDown, ShiftDown,
750 AltDown, MetaDown );
5c8fc7c1
SN
751 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
752 break;
753 }
b5808881 754 case wxGrid::wxGridSelectColumns:
5c8fc7c1
SN
755 {
756 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
757 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
758 if ( !m_grid->GetBatchCount() )
759 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
760 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
761 wxEVT_GRID_RANGE_SELECT,
762 m_grid,
763 wxGridCellCoords( 0, col ),
764 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
d95b0c2b
SN
765 FALSE,
766 ControlDown, ShiftDown,
767 AltDown, MetaDown );
5c8fc7c1
SN
768 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
769 break;
770 }
294f6bcb 771 }
294f6bcb
SN
772}
773
774void wxGridSelection::ClearSelection()
775{
776 size_t n;
f1567cdd
SN
777
778 // deselect all invidiual cells and update the screen
779 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb 780 {
f1e26920 781
b5808881
SN
782 while( ( n = m_cellSelection.GetCount() ) > 0)
783 {
784 wxRect r;
785 n--;
786 r = m_grid->BlockToDeviceRect( m_cellSelection[n],
787 m_cellSelection[n] );
788 m_cellSelection.RemoveAt(n);
789 if ( !m_grid->GetBatchCount() )
790 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
791 }
294f6bcb 792 }
f1567cdd
SN
793
794 // deselect all blocks and update the screen
294f6bcb
SN
795 while( ( n = m_blockSelectionTopLeft.GetCount() ) > 0)
796 {
797 wxRect r;
b5808881
SN
798 n--;
799 r = m_grid->BlockToDeviceRect( m_blockSelectionTopLeft[n],
800 m_blockSelectionBottomRight[n] );
801 m_blockSelectionTopLeft.RemoveAt(n);
802 m_blockSelectionBottomRight.RemoveAt(n);
803 if ( !m_grid->GetBatchCount() )
f1e26920 804 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
b5808881 805 }
f1567cdd
SN
806
807 // deselect all rows and update the screen
b5808881 808 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 809 {
b5808881
SN
810 while( ( n = m_rowSelection.GetCount() ) > 0)
811 {
812 n--;
813 int & row = m_rowSelection[n];
814 wxRect r;
815 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
816 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
817 m_rowSelection.RemoveAt(n);
818 if ( !m_grid->GetBatchCount() )
f1e26920 819 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
b5808881
SN
820 }
821 }
f1567cdd
SN
822
823 // deselect all columns and update the screen
b5808881 824 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 825 {
b5808881
SN
826 while( ( n = m_colSelection.GetCount() ) > 0)
827 {
828 n--;
829 int & col = m_colSelection[n];
830 wxRect r;
831 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
832 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
833 m_colSelection.RemoveAt(n);
834 if ( !m_grid->GetBatchCount() )
f1e26920 835 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
b5808881 836 }
294f6bcb 837 }
f6bcfd97
BP
838
839 // One deselection event, indicating deselection of _all_ cells.
840 // (No finer grained events for each of the smaller regions
841 // deselected above!)
842 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
843 wxEVT_GRID_RANGE_SELECT,
844 m_grid,
845 wxGridCellCoords( 0, 0 ),
846 wxGridCellCoords( m_grid->GetNumberRows() - 1,
847 m_grid->GetNumberCols() - 1 ),
848 FALSE );
849
850 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
294f6bcb
SN
851}
852
853
854void wxGridSelection::UpdateRows( size_t pos, int numRows )
855{
856 size_t count = m_cellSelection.GetCount();
b14159f7
JS
857 size_t n;
858 for ( n = 0; n < count; n++ )
294f6bcb
SN
859 {
860 wxGridCellCoords& coords = m_cellSelection[n];
861 wxCoord row = coords.GetRow();
862 if ((size_t)row >= pos)
863 {
864 if (numRows > 0)
865 {
866 // If rows inserted, increase row counter where necessary
867 coords.SetRow(row + numRows);
868 }
869 else if (numRows < 0)
870 {
871 // If rows deleted ...
872 if ((size_t)row >= pos - numRows)
873 {
874 // ...either decrement row counter (if row still exists)...
875 coords.SetRow(row + numRows);
876 }
877 else
878 {
879 // ...or remove the attribute
880 m_cellSelection.RemoveAt(n);
881 n--; count--;
882 }
883 }
884 }
885 }
886
887 count = m_blockSelectionTopLeft.GetCount();
b14159f7 888 for ( n = 0; n < count; n++ )
294f6bcb
SN
889 {
890 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
891 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
892 wxCoord row1 = coords1.GetRow();
893 wxCoord row2 = coords2.GetRow();
894 if ((size_t)row2 >= pos)
895 {
896 if (numRows > 0)
897 {
898 // If rows inserted, increase row counter where necessary
899 coords2.SetRow(row2 + numRows);
b5808881
SN
900 if ( (size_t)row1 >= pos )
901 coords1.SetRow(row1 + numRows);
294f6bcb
SN
902 }
903 else if (numRows < 0)
904 {
905 // If rows deleted ...
906 if ((size_t)row2 >= pos - numRows)
907 {
908 // ...either decrement row counter (if row still exists)...
909 coords2.SetRow(row2 + numRows);
b5808881
SN
910 if ( (size_t) row1 >= pos)
911 coords1.SetRow( wxMax(row1 + numRows, (int) pos) );
f1e26920 912
294f6bcb
SN
913 }
914 else
915 {
b5808881
SN
916 if ( (size_t) row1 >= pos)
917 {
918 // ...or remove the attribute
919 m_blockSelectionTopLeft.RemoveAt(n);
920 m_blockSelectionBottomRight.RemoveAt(n);
921 n--; count--;
922 }
923 else
924 coords2.SetRow(pos);
294f6bcb
SN
925 }
926 }
927 }
928 }
929
930 count = m_rowSelection.GetCount();
b14159f7 931 for ( n = 0; n < count; n++ )
294f6bcb 932 {
f1e26920
CE
933 int rowOrCol_ = m_rowSelection [ n ];
934
935 if ( ( size_t ) rowOrCol_ >= pos )
936 {
937 if ( numRows > 0 )
938 {
939 m_rowSelection [ n ] += numRows;
940 }
941 else if ( numRows < 0 )
942 {
943 if ( ( size_t ) rowOrCol_ >= ( pos - numRows ) )
944 m_rowSelection [ n ] += numRows;
945 else
946 {
947 m_rowSelection.RemoveAt ( n );
948 n--;
949 count--;
950 }
951 }
952 }
294f6bcb 953 }
f6bcfd97
BP
954 // No need to touch selected columns, unless we removed _all_
955 // rows, in this case, we remove all columns from the selection.
f1e26920 956
f6bcfd97
BP
957 if ( !m_grid->GetNumberRows() )
958 m_colSelection.Clear();
294f6bcb
SN
959}
960
f1e26920 961
294f6bcb
SN
962void wxGridSelection::UpdateCols( size_t pos, int numCols )
963{
964 size_t count = m_cellSelection.GetCount();
b14159f7
JS
965 size_t n;
966 for ( n = 0; n < count; n++ )
294f6bcb
SN
967 {
968 wxGridCellCoords& coords = m_cellSelection[n];
969 wxCoord col = coords.GetCol();
970 if ((size_t)col >= pos)
971 {
972 if (numCols > 0)
973 {
974 // If rows inserted, increase row counter where necessary
975 coords.SetCol(col + numCols);
976 }
977 else if (numCols < 0)
978 {
979 // If rows deleted ...
980 if ((size_t)col >= pos - numCols)
981 {
982 // ...either decrement row counter (if row still exists)...
983 coords.SetCol(col + numCols);
984 }
985 else
986 {
987 // ...or remove the attribute
988 m_cellSelection.RemoveAt(n);
989 n--; count--;
990 }
991 }
992 }
993 }
994
995 count = m_blockSelectionTopLeft.GetCount();
b14159f7 996 for ( n = 0; n < count; n++ )
294f6bcb
SN
997 {
998 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
999 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
1000 wxCoord col1 = coords1.GetCol();
1001 wxCoord col2 = coords2.GetCol();
1002 if ((size_t)col2 >= pos)
1003 {
1004 if (numCols > 0)
1005 {
1006 // If rows inserted, increase row counter where necessary
1007 coords2.SetCol(col2 + numCols);
b5808881
SN
1008 if ( (size_t)col1 >= pos )
1009 coords1.SetCol(col1 + numCols);
294f6bcb
SN
1010 }
1011 else if (numCols < 0)
1012 {
1013 // If cols deleted ...
1014 if ((size_t)col2 >= pos - numCols)
1015 {
1016 // ...either decrement col counter (if col still exists)...
1017 coords2.SetCol(col2 + numCols);
b5808881
SN
1018 if ( (size_t) col1 >= pos)
1019 coords1.SetCol( wxMax(col1 + numCols, (int) pos) );
f1e26920 1020
294f6bcb
SN
1021 }
1022 else
1023 {
b5808881
SN
1024 if ( (size_t) col1 >= pos)
1025 {
1026 // ...or remove the attribute
1027 m_blockSelectionTopLeft.RemoveAt(n);
1028 m_blockSelectionBottomRight.RemoveAt(n);
1029 n--; count--;
1030 }
1031 else
1032 coords2.SetCol(pos);
294f6bcb
SN
1033 }
1034 }
1035 }
1036 }
1037
1038 count = m_colSelection.GetCount();
b14159f7 1039 for ( n = 0; n < count; n++ )
294f6bcb 1040 {
f1e26920
CE
1041
1042 int rowOrCol = m_colSelection [ n ];
1043 if ( ( size_t ) rowOrCol >= pos )
294f6bcb
SN
1044 {
1045 if ( numCols > 0 )
f1e26920
CE
1046 m_colSelection [ n ] += numCols;
1047 else if ( numCols < 0 )
294f6bcb 1048 {
f1e26920
CE
1049 if ( ( size_t ) rowOrCol >= ( pos -numCols ) )
1050 m_colSelection [ n ] += numCols;
294f6bcb
SN
1051 else
1052 {
f1e26920
CE
1053 m_colSelection.RemoveAt ( n );
1054 n--;
1055 count--;
294f6bcb
SN
1056 }
1057 }
1058 }
f1e26920 1059
294f6bcb 1060 }
f6bcfd97
BP
1061
1062 // No need to touch selected rows, unless we removed _all_
1063 // columns, in this case, we remove all rows from the selection.
1064 if ( !m_grid->GetNumberCols() )
1065 m_rowSelection.Clear();
294f6bcb
SN
1066}
1067
f1e26920 1068
294f6bcb 1069int wxGridSelection::BlockContain( int topRow1, int leftCol1,
b5808881
SN
1070 int bottomRow1, int rightCol1,
1071 int topRow2, int leftCol2,
1072 int bottomRow2, int rightCol2 )
294f6bcb
SN
1073// returns 1, if Block1 contains Block2,
1074// -1, if Block2 contains Block1,
1075// 0, otherwise
1076{
1077 if ( topRow1 <= topRow2 && bottomRow2 <= bottomRow1 &&
b5808881 1078 leftCol1 <= leftCol2 && rightCol2 <= rightCol1 )
294f6bcb
SN
1079 return 1;
1080 else if ( topRow2 <= topRow1 && bottomRow1 <= bottomRow2 &&
b5808881 1081 leftCol2 <= leftCol1 && rightCol1 <= rightCol2 )
294f6bcb
SN
1082 return -1;
1083 return 0;
1084}
f1567cdd
SN
1085
1086#endif