]> git.saurik.com Git - wxWidgets.git/blob - src/generic/gridsel.cpp
Clear grid selection more consistently prior clear operations; improved Clear() tests...
[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 // remove a cell from a row, adding up to two new blocks
704 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
705 {
706 count = m_rowSelection.GetCount();
707 for ( n = 0; n < count; n++ )
708 {
709 if ( m_rowSelection[n] == row )
710 {
711 m_rowSelection.RemoveAt(n);
712 n--;
713 count--;
714
715 if (m_selectionMode == wxGrid::wxGridSelectCells)
716 {
717 if ( col > 0 )
718 SelectBlockNoEvent(row, 0, row, col - 1);
719 if ( col < m_grid->GetNumberCols() - 1 )
720 SelectBlockNoEvent( row, col + 1,
721 row, m_grid->GetNumberCols() - 1);
722 }
723 }
724 }
725 }
726
727 // remove a cell from a column, adding up to two new blocks
728 if ( m_selectionMode != wxGrid::wxGridSelectRows )
729 {
730 count = m_colSelection.GetCount();
731 for ( n = 0; n < count; n++ )
732 {
733 if ( m_colSelection[n] == col )
734 {
735 m_colSelection.RemoveAt(n);
736 n--;
737 count--;
738
739 if (m_selectionMode == wxGrid::wxGridSelectCells)
740 {
741 if ( row > 0 )
742 SelectBlockNoEvent(0, col, row - 1, col);
743 if ( row < m_grid->GetNumberRows() - 1 )
744 SelectBlockNoEvent(row + 1, col,
745 m_grid->GetNumberRows() - 1, col);
746 }
747 }
748 }
749 }
750
751 // Refresh the screen and send the event; according to m_selectionMode,
752 // we need to either update only the cell, or the whole row/column.
753 wxRect r;
754 switch (m_selectionMode)
755 {
756 case wxGrid::wxGridSelectCells:
757 {
758 if ( !m_grid->GetBatchCount() )
759 {
760 r = m_grid->BlockToDeviceRect(
761 wxGridCellCoords( row, col ),
762 wxGridCellCoords( row, col ) );
763 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
764 }
765
766 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
767 wxEVT_GRID_RANGE_SELECT,
768 m_grid,
769 wxGridCellCoords( row, col ),
770 wxGridCellCoords( row, col ),
771 false,
772 kbd );
773 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
774 }
775 break;
776
777 case wxGrid::wxGridSelectRows:
778 {
779 if ( !m_grid->GetBatchCount() )
780 {
781 r = m_grid->BlockToDeviceRect(
782 wxGridCellCoords( row, 0 ),
783 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
784 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
785 }
786
787 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
788 wxEVT_GRID_RANGE_SELECT,
789 m_grid,
790 wxGridCellCoords( row, 0 ),
791 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
792 false,
793 kbd );
794 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
795 }
796 break;
797
798 case wxGrid::wxGridSelectColumns:
799 {
800 if ( !m_grid->GetBatchCount() )
801 {
802 r = m_grid->BlockToDeviceRect(
803 wxGridCellCoords( 0, col ),
804 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
805 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
806 }
807
808 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
809 wxEVT_GRID_RANGE_SELECT,
810 m_grid,
811 wxGridCellCoords( 0, col ),
812 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
813 false,
814 kbd );
815 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
816 }
817 break;
818
819 default:
820 break;
821 }
822 }
823
824 void wxGridSelection::ClearSelection()
825 {
826 size_t n;
827 wxRect r;
828 wxGridCellCoords coords1, coords2;
829
830 // deselect all individual cells and update the screen
831 if ( m_selectionMode == wxGrid::wxGridSelectCells )
832 {
833 while ( ( n = m_cellSelection.GetCount() ) > 0)
834 {
835 n--;
836 coords1 = m_cellSelection[n];
837 m_cellSelection.RemoveAt(n);
838 if ( !m_grid->GetBatchCount() )
839 {
840 r = m_grid->BlockToDeviceRect( coords1, coords1 );
841 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
842
843 #ifdef __WXMAC__
844 ((wxWindow *)m_grid->m_gridWin)->Update();
845 #endif
846 }
847 }
848 }
849
850 // deselect all blocks and update the screen
851 while ( ( n = m_blockSelectionTopLeft.GetCount() ) > 0)
852 {
853 n--;
854 coords1 = m_blockSelectionTopLeft[n];
855 coords2 = m_blockSelectionBottomRight[n];
856 m_blockSelectionTopLeft.RemoveAt(n);
857 m_blockSelectionBottomRight.RemoveAt(n);
858 if ( !m_grid->GetBatchCount() )
859 {
860 r = m_grid->BlockToDeviceRect( coords1, coords2 );
861 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
862
863 #ifdef __WXMAC__
864 ((wxWindow *)m_grid->m_gridWin)->Update();
865 #endif
866 }
867 }
868
869 // deselect all rows and update the screen
870 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
871 {
872 while ( ( n = m_rowSelection.GetCount() ) > 0)
873 {
874 n--;
875 int row = m_rowSelection[n];
876 m_rowSelection.RemoveAt(n);
877 if ( !m_grid->GetBatchCount() )
878 {
879 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
880 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
881 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
882
883 #ifdef __WXMAC__
884 ((wxWindow *)m_grid->m_gridWin)->Update();
885 #endif
886 }
887 }
888 }
889
890 // deselect all columns and update the screen
891 if ( m_selectionMode != wxGrid::wxGridSelectRows )
892 {
893 while ( ( n = m_colSelection.GetCount() ) > 0)
894 {
895 n--;
896 int col = m_colSelection[n];
897 m_colSelection.RemoveAt(n);
898 if ( !m_grid->GetBatchCount() )
899 {
900 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
901 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
902 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
903
904 #ifdef __WXMAC__
905 ((wxWindow *)m_grid->m_gridWin)->Update();
906 #endif
907 }
908 }
909 }
910
911 // One deselection event, indicating deselection of _all_ cells.
912 // (No finer grained events for each of the smaller regions
913 // deselected above!)
914 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
915 wxEVT_GRID_RANGE_SELECT,
916 m_grid,
917 wxGridCellCoords( 0, 0 ),
918 wxGridCellCoords(
919 m_grid->GetNumberRows() - 1,
920 m_grid->GetNumberCols() - 1 ),
921 false );
922
923 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
924 }
925
926
927 void wxGridSelection::UpdateRows( size_t pos, int numRows )
928 {
929 size_t count = m_cellSelection.GetCount();
930 size_t n;
931 for ( n = 0; n < count; n++ )
932 {
933 wxGridCellCoords& coords = m_cellSelection[n];
934 wxCoord row = coords.GetRow();
935 if ((size_t)row >= pos)
936 {
937 if (numRows > 0)
938 {
939 // If rows inserted, increase row counter where necessary
940 coords.SetRow(row + numRows);
941 }
942 else if (numRows < 0)
943 {
944 // If rows deleted ...
945 if ((size_t)row >= pos - numRows)
946 {
947 // ...either decrement row counter (if row still exists)...
948 coords.SetRow(row + numRows);
949 }
950 else
951 {
952 // ...or remove the attribute
953 m_cellSelection.RemoveAt(n);
954 n--;
955 count--;
956 }
957 }
958 }
959 }
960
961 count = m_blockSelectionTopLeft.GetCount();
962 for ( n = 0; n < count; n++ )
963 {
964 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
965 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
966 wxCoord row1 = coords1.GetRow();
967 wxCoord row2 = coords2.GetRow();
968
969 if ((size_t)row2 >= pos)
970 {
971 if (numRows > 0)
972 {
973 // If rows inserted, increase row counter where necessary
974 coords2.SetRow( row2 + numRows );
975 if ((size_t)row1 >= pos)
976 coords1.SetRow( row1 + numRows );
977 }
978 else if (numRows < 0)
979 {
980 // If rows deleted ...
981 if ((size_t)row2 >= pos - numRows)
982 {
983 // ...either decrement row counter (if row still exists)...
984 coords2.SetRow( row2 + numRows );
985 if ((size_t)row1 >= pos)
986 coords1.SetRow( wxMax(row1 + numRows, (int)pos) );
987
988 }
989 else
990 {
991 if ((size_t)row1 >= pos)
992 {
993 // ...or remove the attribute
994 m_blockSelectionTopLeft.RemoveAt(n);
995 m_blockSelectionBottomRight.RemoveAt(n);
996 n--;
997 count--;
998 }
999 else
1000 coords2.SetRow( pos );
1001 }
1002 }
1003 }
1004 }
1005
1006 count = m_rowSelection.GetCount();
1007 for ( n = 0; n < count; n++ )
1008 {
1009 int rowOrCol_ = m_rowSelection[n];
1010
1011 if ((size_t) rowOrCol_ >= pos)
1012 {
1013 if ( numRows > 0 )
1014 {
1015 m_rowSelection[n] += numRows;
1016 }
1017 else if ( numRows < 0 )
1018 {
1019 if ((size_t)rowOrCol_ >= (pos - numRows))
1020 m_rowSelection[n] += numRows;
1021 else
1022 {
1023 m_rowSelection.RemoveAt( n );
1024 n--;
1025 count--;
1026 }
1027 }
1028 }
1029 }
1030 // No need to touch selected columns, unless we removed _all_
1031 // rows, in this case, we remove all columns from the selection.
1032
1033 if ( !m_grid->GetNumberRows() )
1034 m_colSelection.Clear();
1035 }
1036
1037
1038 void wxGridSelection::UpdateCols( size_t pos, int numCols )
1039 {
1040 size_t count = m_cellSelection.GetCount();
1041 size_t n;
1042
1043 for ( n = 0; n < count; n++ )
1044 {
1045 wxGridCellCoords& coords = m_cellSelection[n];
1046 wxCoord col = coords.GetCol();
1047 if ((size_t)col >= pos)
1048 {
1049 if (numCols > 0)
1050 {
1051 // If rows inserted, increase row counter where necessary
1052 coords.SetCol(col + numCols);
1053 }
1054 else if (numCols < 0)
1055 {
1056 // If rows deleted ...
1057 if ((size_t)col >= pos - numCols)
1058 {
1059 // ...either decrement row counter (if row still exists)...
1060 coords.SetCol(col + numCols);
1061 }
1062 else
1063 {
1064 // ...or remove the attribute
1065 m_cellSelection.RemoveAt(n);
1066 n--;
1067 count--;
1068 }
1069 }
1070 }
1071 }
1072
1073 count = m_blockSelectionTopLeft.GetCount();
1074 for ( n = 0; n < count; n++ )
1075 {
1076 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
1077 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
1078 wxCoord col1 = coords1.GetCol();
1079 wxCoord col2 = coords2.GetCol();
1080
1081 if ((size_t)col2 >= pos)
1082 {
1083 if (numCols > 0)
1084 {
1085 // If rows inserted, increase row counter where necessary
1086 coords2.SetCol(col2 + numCols);
1087 if ((size_t)col1 >= pos)
1088 coords1.SetCol(col1 + numCols);
1089 }
1090 else if (numCols < 0)
1091 {
1092 // If cols deleted ...
1093 if ((size_t)col2 >= pos - numCols)
1094 {
1095 // ...either decrement col counter (if col still exists)...
1096 coords2.SetCol(col2 + numCols);
1097 if ( (size_t) col1 >= pos)
1098 coords1.SetCol( wxMax(col1 + numCols, (int)pos) );
1099
1100 }
1101 else
1102 {
1103 if ((size_t)col1 >= pos)
1104 {
1105 // ...or remove the attribute
1106 m_blockSelectionTopLeft.RemoveAt(n);
1107 m_blockSelectionBottomRight.RemoveAt(n);
1108 n--;
1109 count--;
1110 }
1111 else
1112 coords2.SetCol(pos);
1113 }
1114 }
1115 }
1116 }
1117
1118 count = m_colSelection.GetCount();
1119 for ( n = 0; n < count; n++ )
1120 {
1121 int rowOrCol = m_colSelection[n];
1122
1123 if ((size_t)rowOrCol >= pos)
1124 {
1125 if ( numCols > 0 )
1126 m_colSelection[n] += numCols;
1127 else if ( numCols < 0 )
1128 {
1129 if ((size_t)rowOrCol >= (pos - numCols))
1130 m_colSelection[n] += numCols;
1131 else
1132 {
1133 m_colSelection.RemoveAt( n );
1134 n--;
1135 count--;
1136 }
1137 }
1138 }
1139 }
1140
1141 // No need to touch selected rows, unless we removed _all_
1142 // columns, in this case, we remove all rows from the selection.
1143 if ( !m_grid->GetNumberCols() )
1144 m_rowSelection.Clear();
1145 }
1146
1147 int wxGridSelection::BlockContain( int topRow1, int leftCol1,
1148 int bottomRow1, int rightCol1,
1149 int topRow2, int leftCol2,
1150 int bottomRow2, int rightCol2 )
1151 // returns 1, if Block1 contains Block2,
1152 // -1, if Block2 contains Block1,
1153 // 0, otherwise
1154 {
1155 if ( topRow1 <= topRow2 && bottomRow2 <= bottomRow1 &&
1156 leftCol1 <= leftCol2 && rightCol2 <= rightCol1 )
1157 return 1;
1158 else if ( topRow2 <= topRow1 && bottomRow1 <= bottomRow2 &&
1159 leftCol2 <= leftCol1 && rightCol1 <= rightCol2 )
1160 return -1;
1161
1162 return 0;
1163 }
1164
1165 #endif