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