]> git.saurik.com Git - wxWidgets.git/blob - src/generic/gridsel.cpp
forward port from 2.8
[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 SelectBlock( topRow, 0,
164 bottomRow, m_grid->GetNumberCols() - 1,
165 false, false, false, false, false );
166 }
167 }
168 else // selmode == wxGridSelectColumns)
169 {
170 if (topRow != 0 || bottomRow != m_grid->GetNumberRows() - 1 )
171 {
172 m_blockSelectionTopLeft.RemoveAt(n);
173 m_blockSelectionBottomRight.RemoveAt(n);
174 SelectBlock( 0, leftCol,
175 m_grid->GetNumberRows() - 1, rightCol,
176 false, false, false, false, false );
177 }
178 }
179 }
180
181 m_selectionMode = selmode;
182 }
183 }
184
185 void wxGridSelection::SelectRow( int row,
186 bool ControlDown, bool ShiftDown,
187 bool AltDown, bool MetaDown )
188 {
189 if ( m_selectionMode == wxGrid::wxGridSelectColumns )
190 return;
191
192 size_t count, n;
193
194 // Remove single cells contained in newly selected block.
195 if ( m_selectionMode == wxGrid::wxGridSelectCells )
196 {
197 count = m_cellSelection.GetCount();
198 for ( n = 0; n < count; n++ )
199 {
200 wxGridCellCoords& coords = m_cellSelection[n];
201 if ( BlockContainsCell( row, 0, row, m_grid->GetNumberCols() - 1,
202 coords.GetRow(), coords.GetCol() ) )
203 {
204 m_cellSelection.RemoveAt(n);
205 n--;
206 count--;
207 }
208 }
209 }
210
211 // Simplify list of selected blocks (if possible)
212 count = m_blockSelectionTopLeft.GetCount();
213 bool done = false;
214
215 for ( n = 0; n < count; n++ )
216 {
217 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
218 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
219
220 // Remove block if it is a subset of the row
221 if ( coords1.GetRow() == row && row == coords2.GetRow() )
222 {
223 m_blockSelectionTopLeft.RemoveAt(n);
224 m_blockSelectionBottomRight.RemoveAt(n);
225 n--;
226 count--;
227 }
228 else if ( coords1.GetCol() == 0 &&
229 coords2.GetCol() == m_grid->GetNumberCols() - 1 )
230 {
231 // silently return, if row is contained in block
232 if ( coords1.GetRow() <= row && row <= coords2.GetRow() )
233 return;
234 // expand block, if it touched row
235 else if ( coords1.GetRow() == row + 1)
236 {
237 coords1.SetRow(row);
238 done = true;
239 }
240 else if ( coords2.GetRow() == row - 1)
241 {
242 coords2.SetRow(row);
243 done = true;
244 }
245 }
246 }
247
248 // Unless we successfully handled the row,
249 // check whether row is already selected.
250 if ( !done )
251 {
252 count = m_rowSelection.GetCount();
253 for ( n = 0; n < count; n++ )
254 {
255 if ( row == m_rowSelection[n] )
256 return;
257 }
258
259 // Add row to selection
260 m_rowSelection.Add(row);
261 }
262
263 // Update View:
264 if ( !m_grid->GetBatchCount() )
265 {
266 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
267 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
268 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
269 }
270
271 // Send Event
272 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
273 wxEVT_GRID_RANGE_SELECT,
274 m_grid,
275 wxGridCellCoords( row, 0 ),
276 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
277 true,
278 ControlDown, ShiftDown,
279 AltDown, MetaDown );
280
281 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
282 }
283
284 void wxGridSelection::SelectCol( int col,
285 bool ControlDown, bool ShiftDown,
286 bool AltDown, bool MetaDown )
287 {
288 if ( m_selectionMode == wxGrid::wxGridSelectRows )
289 return;
290 size_t count, n;
291
292 // Remove single cells contained in newly selected block.
293 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294 {
295 count = m_cellSelection.GetCount();
296 for ( n = 0; n < count; n++ )
297 {
298 wxGridCellCoords& coords = m_cellSelection[n];
299 if ( BlockContainsCell( 0, col, m_grid->GetNumberRows() - 1, col,
300 coords.GetRow(), coords.GetCol() ) )
301 {
302 m_cellSelection.RemoveAt(n);
303 n--;
304 count--;
305 }
306 }
307 }
308
309 // Simplify list of selected blocks (if possible)
310 count = m_blockSelectionTopLeft.GetCount();
311 bool done = false;
312 for ( n = 0; n < count; n++ )
313 {
314 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
315 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
316
317 // Remove block if it is a subset of the column
318 if ( coords1.GetCol() == col && col == coords2.GetCol() )
319 {
320 m_blockSelectionTopLeft.RemoveAt(n);
321 m_blockSelectionBottomRight.RemoveAt(n);
322 n--;
323 count--;
324 }
325 else if ( coords1.GetRow() == 0 &&
326 coords2.GetRow() == m_grid->GetNumberRows() - 1 )
327 {
328 // silently return, if row is contained in block
329 if ( coords1.GetCol() <= col && col <= coords2.GetCol() )
330 return;
331 // expand block, if it touched col
332 else if ( coords1.GetCol() == col + 1)
333 {
334 coords1.SetCol(col);
335 done = true;
336 }
337 else if ( coords2.GetCol() == col - 1)
338 {
339 coords2.SetCol(col);
340 done = true;
341 }
342 }
343 }
344
345 // Unless we successfully handled the column,
346 // Check whether col is already selected.
347 if ( !done )
348 {
349 count = m_colSelection.GetCount();
350 for ( n = 0; n < count; n++ )
351 {
352 if ( col == m_colSelection[n] )
353 return;
354 }
355
356 // Add col to selection
357 m_colSelection.Add(col);
358 }
359
360 // Update View:
361 if ( !m_grid->GetBatchCount() )
362 {
363 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
364 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
365 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
366 }
367
368 // Send Event
369 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
370 wxEVT_GRID_RANGE_SELECT,
371 m_grid,
372 wxGridCellCoords( 0, col ),
373 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
374 true,
375 ControlDown, ShiftDown,
376 AltDown, MetaDown );
377
378 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
379 }
380
381 void wxGridSelection::SelectBlock( int topRow, int leftCol,
382 int bottomRow, int rightCol,
383 bool ControlDown, bool ShiftDown,
384 bool AltDown, bool MetaDown,
385 bool sendEvent )
386 {
387 // Fix the coordinates of the block if needed.
388 if ( m_selectionMode == wxGrid::wxGridSelectRows )
389 {
390 leftCol = 0;
391 rightCol = m_grid->GetNumberCols() - 1;
392 }
393 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
394 {
395 topRow = 0;
396 bottomRow = m_grid->GetNumberRows() - 1;
397 }
398
399 if ( topRow > bottomRow )
400 {
401 int temp = topRow;
402 topRow = bottomRow;
403 bottomRow = temp;
404 }
405
406 if ( leftCol > rightCol )
407 {
408 int temp = leftCol;
409 leftCol = rightCol;
410 rightCol = temp;
411 }
412
413 // Handle single cell selection in SelectCell.
414 // (MB: added check for selection mode here to prevent
415 // crashes if, for example, we are select rows and the
416 // grid only has 1 col)
417 if ( m_selectionMode == wxGrid::wxGridSelectCells &&
418 topRow == bottomRow && leftCol == rightCol )
419 {
420 SelectCell( topRow, leftCol, ControlDown, ShiftDown,
421 AltDown, MetaDown, sendEvent );
422 }
423
424 size_t count, n;
425
426 // Remove single cells contained in newly selected block.
427 if ( m_selectionMode == wxGrid::wxGridSelectCells )
428 {
429 count = m_cellSelection.GetCount();
430 for ( n = 0; n < count; n++ )
431 {
432 wxGridCellCoords& coords = m_cellSelection[n];
433 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol,
434 coords.GetRow(), coords.GetCol() ) )
435 {
436 m_cellSelection.RemoveAt(n);
437 n--;
438 count--;
439 }
440 }
441 }
442
443 // If a block containing the selection is already selected, return,
444 // if a block contained in the selection is found, remove it.
445
446 count = m_blockSelectionTopLeft.GetCount();
447 for ( n = 0; n < count; n++ )
448 {
449 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
450 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
451
452 switch ( BlockContain( coords1.GetRow(), coords1.GetCol(),
453 coords2.GetRow(), coords2.GetCol(),
454 topRow, leftCol, bottomRow, rightCol ) )
455 {
456 case 1:
457 return;
458
459 case -1:
460 m_blockSelectionTopLeft.RemoveAt(n);
461 m_blockSelectionBottomRight.RemoveAt(n);
462 n--;
463 count--;
464 break;
465
466 default:
467 break;
468 }
469 }
470
471 // If a row containing the selection is already selected, return,
472 // if a row contained in newly selected block is found, remove it.
473 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
474 {
475 count = m_rowSelection.GetCount();
476 for ( n = 0; n < count; n++ )
477 {
478 switch ( BlockContain( m_rowSelection[n], 0,
479 m_rowSelection[n], m_grid->GetNumberCols() - 1,
480 topRow, leftCol, bottomRow, rightCol ) )
481 {
482 case 1:
483 return;
484
485 case -1:
486 m_rowSelection.RemoveAt(n);
487 n--;
488 count--;
489 break;
490
491 default:
492 break;
493 }
494 }
495 }
496
497 if ( m_selectionMode != wxGrid::wxGridSelectRows )
498 {
499 count = m_colSelection.GetCount();
500 for ( n = 0; n < count; n++ )
501 {
502 switch ( BlockContain( 0, m_colSelection[n],
503 m_grid->GetNumberRows() - 1, m_colSelection[n],
504 topRow, leftCol, bottomRow, rightCol ) )
505 {
506 case 1:
507 return;
508
509 case -1:
510 m_colSelection.RemoveAt(n);
511 n--;
512 count--;
513 break;
514
515 default:
516 break;
517 }
518 }
519 }
520
521 m_blockSelectionTopLeft.Add( wxGridCellCoords( topRow, leftCol ) );
522 m_blockSelectionBottomRight.Add( wxGridCellCoords( bottomRow, rightCol ) );
523
524 // Update View:
525 if ( !m_grid->GetBatchCount() )
526 {
527 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( topRow, leftCol ),
528 wxGridCellCoords( bottomRow, rightCol ) );
529 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
530 }
531
532 // Send Event, if not disabled.
533 if ( sendEvent )
534 {
535 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
536 wxEVT_GRID_RANGE_SELECT,
537 m_grid,
538 wxGridCellCoords( topRow, leftCol ),
539 wxGridCellCoords( bottomRow, rightCol ),
540 true,
541 ControlDown, ShiftDown,
542 AltDown, MetaDown );
543 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
544 }
545 }
546
547 void wxGridSelection::SelectCell( int row, int col,
548 bool ControlDown, bool ShiftDown,
549 bool AltDown, bool MetaDown,
550 bool sendEvent )
551 {
552 if ( m_selectionMode == wxGrid::wxGridSelectRows )
553 {
554 SelectBlock(row, 0, row, m_grid->GetNumberCols() - 1,
555 ControlDown, ShiftDown, AltDown, MetaDown, sendEvent);
556
557 return;
558 }
559 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
560 {
561 SelectBlock(0, col, m_grid->GetNumberRows() - 1, col,
562 ControlDown, ShiftDown, AltDown, MetaDown, sendEvent);
563
564 return;
565 }
566 else if ( IsInSelection ( row, col ) )
567 return;
568
569 m_cellSelection.Add( wxGridCellCoords( row, col ) );
570
571 // Update View:
572 if ( !m_grid->GetBatchCount() )
573 {
574 wxRect r = m_grid->BlockToDeviceRect(
575 wxGridCellCoords( row, col ),
576 wxGridCellCoords( row, col ) );
577 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
578 }
579
580 // Send event
581 if (sendEvent)
582 {
583 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
584 wxEVT_GRID_RANGE_SELECT,
585 m_grid,
586 wxGridCellCoords( row, col ),
587 wxGridCellCoords( row, col ),
588 true,
589 ControlDown, ShiftDown,
590 AltDown, MetaDown );
591 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
592 }
593 }
594
595 void wxGridSelection::ToggleCellSelection( int row, int col,
596 bool ControlDown, bool ShiftDown,
597 bool AltDown, bool MetaDown )
598 {
599 // if the cell is not selected, select it
600 if ( !IsInSelection ( row, col ) )
601 {
602 SelectCell( row, col, ControlDown, ShiftDown, AltDown, MetaDown );
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 ControlDown, ShiftDown,
640 AltDown, MetaDown );
641 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
642
643 return;
644 }
645 }
646 }
647
648 // The most difficult case: The cell is member of one or even several
649 // blocks. Split each such block in up to 4 new parts, that don't
650 // contain the cell to be selected, like this:
651 // |---------------------------|
652 // | |
653 // | part 1 |
654 // | |
655 // |---------------------------|
656 // | part 3 |x| part 4 |
657 // |---------------------------|
658 // | |
659 // | part 2 |
660 // | |
661 // |---------------------------|
662 // (The x marks the newly deselected cell).
663 // Note: in row selection mode, we only need part1 and part2;
664 // in column selection mode, we only need part 3 and part4,
665 // which are expanded to whole columns automatically!
666
667 count = m_blockSelectionTopLeft.GetCount();
668 for ( n = 0; n < count; n++ )
669 {
670 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
671 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
672 int topRow = coords1.GetRow();
673 int leftCol = coords1.GetCol();
674 int bottomRow = coords2.GetRow();
675 int rightCol = coords2.GetCol();
676
677 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol, row, col ) )
678 {
679 // remove the block
680 m_blockSelectionTopLeft.RemoveAt(n);
681 m_blockSelectionBottomRight.RemoveAt(n);
682 n--;
683 count--;
684
685 // add up to 4 smaller blocks and set update region
686 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
687 {
688 if ( topRow < row )
689 SelectBlock( topRow, leftCol, row - 1, rightCol,
690 false, false, false, false, false );
691 if ( bottomRow > row )
692 SelectBlock( row + 1, leftCol, bottomRow, rightCol,
693 false, false, false, false, false );
694 }
695
696 if ( m_selectionMode != wxGrid::wxGridSelectRows )
697 {
698 if ( leftCol < col )
699 SelectBlock( row, leftCol, row, col - 1,
700 false, false, false, false, false );
701 if ( rightCol > col )
702 SelectBlock( row, col + 1, row, rightCol,
703 false, false, false, false, false );
704 }
705 }
706 }
707
708 // remove a cell from a row, adding up to two new blocks
709 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
710 {
711 count = m_rowSelection.GetCount();
712 for ( n = 0; n < count; n++ )
713 {
714 if ( m_rowSelection[n] == row )
715 {
716 m_rowSelection.RemoveAt(n);
717 n--;
718 count--;
719
720 if (m_selectionMode == wxGrid::wxGridSelectCells)
721 {
722 if ( col > 0 )
723 SelectBlock( row, 0, row, col - 1,
724 false, false, false, false, false );
725 if ( col < m_grid->GetNumberCols() - 1 )
726 SelectBlock( row, col + 1,
727 row, m_grid->GetNumberCols() - 1,
728 false, false, false, false, false );
729 }
730 }
731 }
732 }
733
734 // remove a cell from a column, adding up to two new blocks
735 if ( m_selectionMode != wxGrid::wxGridSelectRows )
736 {
737 count = m_colSelection.GetCount();
738 for ( n = 0; n < count; n++ )
739 {
740 if ( m_colSelection[n] == col )
741 {
742 m_colSelection.RemoveAt(n);
743 n--;
744 count--;
745
746 if (m_selectionMode == wxGrid::wxGridSelectCells)
747 {
748 if ( row > 0 )
749 SelectBlock( 0, col, row - 1, col,
750 false, false, false, false, false );
751 if ( row < m_grid->GetNumberRows() - 1 )
752 SelectBlock( row + 1, col,
753 m_grid->GetNumberRows() - 1, col,
754 false, false, false, false, false );
755 }
756 }
757 }
758 }
759
760 // Refresh the screen and send the event; according to m_selectionMode,
761 // we need to either update only the cell, or the whole row/column.
762 wxRect r;
763 switch (m_selectionMode)
764 {
765 case wxGrid::wxGridSelectCells:
766 {
767 if ( !m_grid->GetBatchCount() )
768 {
769 r = m_grid->BlockToDeviceRect(
770 wxGridCellCoords( row, col ),
771 wxGridCellCoords( row, col ) );
772 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
773 }
774
775 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
776 wxEVT_GRID_RANGE_SELECT,
777 m_grid,
778 wxGridCellCoords( row, col ),
779 wxGridCellCoords( row, col ),
780 false,
781 ControlDown, ShiftDown,
782 AltDown, MetaDown );
783 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
784 }
785 break;
786
787 case wxGrid::wxGridSelectRows:
788 {
789 if ( !m_grid->GetBatchCount() )
790 {
791 r = m_grid->BlockToDeviceRect(
792 wxGridCellCoords( row, 0 ),
793 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
794 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
795 }
796
797 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
798 wxEVT_GRID_RANGE_SELECT,
799 m_grid,
800 wxGridCellCoords( row, 0 ),
801 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
802 false,
803 ControlDown, ShiftDown,
804 AltDown, MetaDown );
805 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
806 }
807 break;
808
809 case wxGrid::wxGridSelectColumns:
810 {
811 if ( !m_grid->GetBatchCount() )
812 {
813 r = m_grid->BlockToDeviceRect(
814 wxGridCellCoords( 0, col ),
815 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
816 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
817 }
818
819 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
820 wxEVT_GRID_RANGE_SELECT,
821 m_grid,
822 wxGridCellCoords( 0, col ),
823 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
824 false,
825 ControlDown, ShiftDown,
826 AltDown, MetaDown );
827 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
828 }
829 break;
830
831 default:
832 break;
833 }
834 }
835
836 void wxGridSelection::ClearSelection()
837 {
838 size_t n;
839 wxRect r;
840 wxGridCellCoords coords1, coords2;
841
842 // deselect all individual cells and update the screen
843 if ( m_selectionMode == wxGrid::wxGridSelectCells )
844 {
845 while ( ( n = m_cellSelection.GetCount() ) > 0)
846 {
847 n--;
848 coords1 = m_cellSelection[n];
849 m_cellSelection.RemoveAt(n);
850 if ( !m_grid->GetBatchCount() )
851 {
852 r = m_grid->BlockToDeviceRect( coords1, coords1 );
853 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
854
855 #ifdef __WXMAC__
856 ((wxWindow *)m_grid->m_gridWin)->Update();
857 #endif
858 }
859 }
860 }
861
862 // deselect all blocks and update the screen
863 while ( ( n = m_blockSelectionTopLeft.GetCount() ) > 0)
864 {
865 n--;
866 coords1 = m_blockSelectionTopLeft[n];
867 coords2 = m_blockSelectionBottomRight[n];
868 m_blockSelectionTopLeft.RemoveAt(n);
869 m_blockSelectionBottomRight.RemoveAt(n);
870 if ( !m_grid->GetBatchCount() )
871 {
872 r = m_grid->BlockToDeviceRect( coords1, coords2 );
873 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
874
875 #ifdef __WXMAC__
876 ((wxWindow *)m_grid->m_gridWin)->Update();
877 #endif
878 }
879 }
880
881 // deselect all rows and update the screen
882 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
883 {
884 while ( ( n = m_rowSelection.GetCount() ) > 0)
885 {
886 n--;
887 int row = m_rowSelection[n];
888 m_rowSelection.RemoveAt(n);
889 if ( !m_grid->GetBatchCount() )
890 {
891 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
892 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
893 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
894
895 #ifdef __WXMAC__
896 ((wxWindow *)m_grid->m_gridWin)->Update();
897 #endif
898 }
899 }
900 }
901
902 // deselect all columns and update the screen
903 if ( m_selectionMode != wxGrid::wxGridSelectRows )
904 {
905 while ( ( n = m_colSelection.GetCount() ) > 0)
906 {
907 n--;
908 int col = m_colSelection[n];
909 m_colSelection.RemoveAt(n);
910 if ( !m_grid->GetBatchCount() )
911 {
912 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
913 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
914 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
915
916 #ifdef __WXMAC__
917 ((wxWindow *)m_grid->m_gridWin)->Update();
918 #endif
919 }
920 }
921 }
922
923 // One deselection event, indicating deselection of _all_ cells.
924 // (No finer grained events for each of the smaller regions
925 // deselected above!)
926 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
927 wxEVT_GRID_RANGE_SELECT,
928 m_grid,
929 wxGridCellCoords( 0, 0 ),
930 wxGridCellCoords(
931 m_grid->GetNumberRows() - 1,
932 m_grid->GetNumberCols() - 1 ),
933 false );
934
935 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
936 }
937
938
939 void wxGridSelection::UpdateRows( size_t pos, int numRows )
940 {
941 size_t count = m_cellSelection.GetCount();
942 size_t n;
943 for ( n = 0; n < count; n++ )
944 {
945 wxGridCellCoords& coords = m_cellSelection[n];
946 wxCoord row = coords.GetRow();
947 if ((size_t)row >= pos)
948 {
949 if (numRows > 0)
950 {
951 // If rows inserted, increase row counter where necessary
952 coords.SetRow(row + numRows);
953 }
954 else if (numRows < 0)
955 {
956 // If rows deleted ...
957 if ((size_t)row >= pos - numRows)
958 {
959 // ...either decrement row counter (if row still exists)...
960 coords.SetRow(row + numRows);
961 }
962 else
963 {
964 // ...or remove the attribute
965 m_cellSelection.RemoveAt(n);
966 n--;
967 count--;
968 }
969 }
970 }
971 }
972
973 count = m_blockSelectionTopLeft.GetCount();
974 for ( n = 0; n < count; n++ )
975 {
976 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
977 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
978 wxCoord row1 = coords1.GetRow();
979 wxCoord row2 = coords2.GetRow();
980
981 if ((size_t)row2 >= pos)
982 {
983 if (numRows > 0)
984 {
985 // If rows inserted, increase row counter where necessary
986 coords2.SetRow( row2 + numRows );
987 if ((size_t)row1 >= pos)
988 coords1.SetRow( row1 + numRows );
989 }
990 else if (numRows < 0)
991 {
992 // If rows deleted ...
993 if ((size_t)row2 >= pos - numRows)
994 {
995 // ...either decrement row counter (if row still exists)...
996 coords2.SetRow( row2 + numRows );
997 if ((size_t)row1 >= pos)
998 coords1.SetRow( wxMax(row1 + numRows, (int)pos) );
999
1000 }
1001 else
1002 {
1003 if ((size_t)row1 >= pos)
1004 {
1005 // ...or remove the attribute
1006 m_blockSelectionTopLeft.RemoveAt(n);
1007 m_blockSelectionBottomRight.RemoveAt(n);
1008 n--;
1009 count--;
1010 }
1011 else
1012 coords2.SetRow( pos );
1013 }
1014 }
1015 }
1016 }
1017
1018 count = m_rowSelection.GetCount();
1019 for ( n = 0; n < count; n++ )
1020 {
1021 int rowOrCol_ = m_rowSelection[n];
1022
1023 if ((size_t) rowOrCol_ >= pos)
1024 {
1025 if ( numRows > 0 )
1026 {
1027 m_rowSelection[n] += numRows;
1028 }
1029 else if ( numRows < 0 )
1030 {
1031 if ((size_t)rowOrCol_ >= (pos - numRows))
1032 m_rowSelection[n] += numRows;
1033 else
1034 {
1035 m_rowSelection.RemoveAt( n );
1036 n--;
1037 count--;
1038 }
1039 }
1040 }
1041 }
1042 // No need to touch selected columns, unless we removed _all_
1043 // rows, in this case, we remove all columns from the selection.
1044
1045 if ( !m_grid->GetNumberRows() )
1046 m_colSelection.Clear();
1047 }
1048
1049
1050 void wxGridSelection::UpdateCols( size_t pos, int numCols )
1051 {
1052 size_t count = m_cellSelection.GetCount();
1053 size_t n;
1054
1055 for ( n = 0; n < count; n++ )
1056 {
1057 wxGridCellCoords& coords = m_cellSelection[n];
1058 wxCoord col = coords.GetCol();
1059 if ((size_t)col >= pos)
1060 {
1061 if (numCols > 0)
1062 {
1063 // If rows inserted, increase row counter where necessary
1064 coords.SetCol(col + numCols);
1065 }
1066 else if (numCols < 0)
1067 {
1068 // If rows deleted ...
1069 if ((size_t)col >= pos - numCols)
1070 {
1071 // ...either decrement row counter (if row still exists)...
1072 coords.SetCol(col + numCols);
1073 }
1074 else
1075 {
1076 // ...or remove the attribute
1077 m_cellSelection.RemoveAt(n);
1078 n--;
1079 count--;
1080 }
1081 }
1082 }
1083 }
1084
1085 count = m_blockSelectionTopLeft.GetCount();
1086 for ( n = 0; n < count; n++ )
1087 {
1088 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
1089 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
1090 wxCoord col1 = coords1.GetCol();
1091 wxCoord col2 = coords2.GetCol();
1092
1093 if ((size_t)col2 >= pos)
1094 {
1095 if (numCols > 0)
1096 {
1097 // If rows inserted, increase row counter where necessary
1098 coords2.SetCol(col2 + numCols);
1099 if ((size_t)col1 >= pos)
1100 coords1.SetCol(col1 + numCols);
1101 }
1102 else if (numCols < 0)
1103 {
1104 // If cols deleted ...
1105 if ((size_t)col2 >= pos - numCols)
1106 {
1107 // ...either decrement col counter (if col still exists)...
1108 coords2.SetCol(col2 + numCols);
1109 if ( (size_t) col1 >= pos)
1110 coords1.SetCol( wxMax(col1 + numCols, (int)pos) );
1111
1112 }
1113 else
1114 {
1115 if ((size_t)col1 >= pos)
1116 {
1117 // ...or remove the attribute
1118 m_blockSelectionTopLeft.RemoveAt(n);
1119 m_blockSelectionBottomRight.RemoveAt(n);
1120 n--;
1121 count--;
1122 }
1123 else
1124 coords2.SetCol(pos);
1125 }
1126 }
1127 }
1128 }
1129
1130 count = m_colSelection.GetCount();
1131 for ( n = 0; n < count; n++ )
1132 {
1133 int rowOrCol = m_colSelection[n];
1134
1135 if ((size_t)rowOrCol >= pos)
1136 {
1137 if ( numCols > 0 )
1138 m_colSelection[n] += numCols;
1139 else if ( numCols < 0 )
1140 {
1141 if ((size_t)rowOrCol >= (pos - numCols))
1142 m_colSelection[n] += numCols;
1143 else
1144 {
1145 m_colSelection.RemoveAt( n );
1146 n--;
1147 count--;
1148 }
1149 }
1150 }
1151 }
1152
1153 // No need to touch selected rows, unless we removed _all_
1154 // columns, in this case, we remove all rows from the selection.
1155 if ( !m_grid->GetNumberCols() )
1156 m_rowSelection.Clear();
1157 }
1158
1159 int wxGridSelection::BlockContain( int topRow1, int leftCol1,
1160 int bottomRow1, int rightCol1,
1161 int topRow2, int leftCol2,
1162 int bottomRow2, int rightCol2 )
1163 // returns 1, if Block1 contains Block2,
1164 // -1, if Block2 contains Block1,
1165 // 0, otherwise
1166 {
1167 if ( topRow1 <= topRow2 && bottomRow2 <= bottomRow1 &&
1168 leftCol1 <= leftCol2 && rightCol2 <= rightCol1 )
1169 return 1;
1170 else if ( topRow2 <= topRow1 && bottomRow1 <= bottomRow2 &&
1171 leftCol2 <= leftCol1 && rightCol1 <= rightCol2 )
1172 return -1;
1173
1174 return 0;
1175 }
1176
1177 #endif