]> git.saurik.com Git - wxWidgets.git/blob - src/generic/gridsel.cpp
d5ba76cbbb5da898ccc53e574ba6a7f936840c7c
[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 switch ( m_selectionMode )
389 {
390 default:
391 wxFAIL_MSG( "unknown selection mode" );
392 // fall through
393
394 case wxGrid::wxGridSelectCells:
395 // nothing to do -- in this mode arbitrary blocks can be selected
396 break;
397
398 case wxGrid::wxGridSelectRows:
399 leftCol = 0;
400 rightCol = m_grid->GetNumberCols() - 1;
401 break;
402
403 case wxGrid::wxGridSelectColumns:
404 topRow = 0;
405 bottomRow = m_grid->GetNumberRows() - 1;
406 break;
407
408 case wxGrid::wxGridSelectRowsOrColumns:
409 // block selection doesn't make sense for this mode, we could only
410 // select the entire grid but this wouldn't be useful
411 return;
412 }
413
414 if ( topRow > bottomRow )
415 {
416 int temp = topRow;
417 topRow = bottomRow;
418 bottomRow = temp;
419 }
420
421 if ( leftCol > rightCol )
422 {
423 int temp = leftCol;
424 leftCol = rightCol;
425 rightCol = temp;
426 }
427
428 // Handle single cell selection in SelectCell.
429 // (MB: added check for selection mode here to prevent
430 // crashes if, for example, we are select rows and the
431 // grid only has 1 col)
432 if ( m_selectionMode == wxGrid::wxGridSelectCells &&
433 topRow == bottomRow && leftCol == rightCol )
434 {
435 SelectCell( topRow, leftCol, ControlDown, ShiftDown,
436 AltDown, MetaDown, sendEvent );
437 }
438
439 size_t count, n;
440
441 // Remove single cells contained in newly selected block.
442 if ( m_selectionMode == wxGrid::wxGridSelectCells )
443 {
444 count = m_cellSelection.GetCount();
445 for ( n = 0; n < count; n++ )
446 {
447 wxGridCellCoords& coords = m_cellSelection[n];
448 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol,
449 coords.GetRow(), coords.GetCol() ) )
450 {
451 m_cellSelection.RemoveAt(n);
452 n--;
453 count--;
454 }
455 }
456 }
457
458 // If a block containing the selection is already selected, return,
459 // if a block contained in the selection is found, remove it.
460
461 count = m_blockSelectionTopLeft.GetCount();
462 for ( n = 0; n < count; n++ )
463 {
464 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
465 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
466
467 switch ( BlockContain( coords1.GetRow(), coords1.GetCol(),
468 coords2.GetRow(), coords2.GetCol(),
469 topRow, leftCol, bottomRow, rightCol ) )
470 {
471 case 1:
472 return;
473
474 case -1:
475 m_blockSelectionTopLeft.RemoveAt(n);
476 m_blockSelectionBottomRight.RemoveAt(n);
477 n--;
478 count--;
479 break;
480
481 default:
482 break;
483 }
484 }
485
486 // If a row containing the selection is already selected, return,
487 // if a row contained in newly selected block is found, remove it.
488 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
489 {
490 count = m_rowSelection.GetCount();
491 for ( n = 0; n < count; n++ )
492 {
493 switch ( BlockContain( m_rowSelection[n], 0,
494 m_rowSelection[n], m_grid->GetNumberCols() - 1,
495 topRow, leftCol, bottomRow, rightCol ) )
496 {
497 case 1:
498 return;
499
500 case -1:
501 m_rowSelection.RemoveAt(n);
502 n--;
503 count--;
504 break;
505
506 default:
507 break;
508 }
509 }
510 }
511
512 if ( m_selectionMode != wxGrid::wxGridSelectRows )
513 {
514 count = m_colSelection.GetCount();
515 for ( n = 0; n < count; n++ )
516 {
517 switch ( BlockContain( 0, m_colSelection[n],
518 m_grid->GetNumberRows() - 1, m_colSelection[n],
519 topRow, leftCol, bottomRow, rightCol ) )
520 {
521 case 1:
522 return;
523
524 case -1:
525 m_colSelection.RemoveAt(n);
526 n--;
527 count--;
528 break;
529
530 default:
531 break;
532 }
533 }
534 }
535
536 m_blockSelectionTopLeft.Add( wxGridCellCoords( topRow, leftCol ) );
537 m_blockSelectionBottomRight.Add( wxGridCellCoords( bottomRow, rightCol ) );
538
539 // Update View:
540 if ( !m_grid->GetBatchCount() )
541 {
542 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( topRow, leftCol ),
543 wxGridCellCoords( bottomRow, rightCol ) );
544 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
545 }
546
547 // Send Event, if not disabled.
548 if ( sendEvent )
549 {
550 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
551 wxEVT_GRID_RANGE_SELECT,
552 m_grid,
553 wxGridCellCoords( topRow, leftCol ),
554 wxGridCellCoords( bottomRow, rightCol ),
555 true,
556 ControlDown, ShiftDown,
557 AltDown, MetaDown );
558 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
559 }
560 }
561
562 void wxGridSelection::SelectCell( int row, int col,
563 bool ControlDown, bool ShiftDown,
564 bool AltDown, bool MetaDown,
565 bool sendEvent )
566 {
567 if ( m_selectionMode == wxGrid::wxGridSelectRows )
568 {
569 SelectBlock(row, 0, row, m_grid->GetNumberCols() - 1,
570 ControlDown, ShiftDown, AltDown, MetaDown, sendEvent);
571
572 return;
573 }
574 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
575 {
576 SelectBlock(0, col, m_grid->GetNumberRows() - 1, col,
577 ControlDown, ShiftDown, AltDown, MetaDown, sendEvent);
578
579 return;
580 }
581 else if ( IsInSelection ( row, col ) )
582 return;
583
584 m_cellSelection.Add( wxGridCellCoords( row, col ) );
585
586 // Update View:
587 if ( !m_grid->GetBatchCount() )
588 {
589 wxRect r = m_grid->BlockToDeviceRect(
590 wxGridCellCoords( row, col ),
591 wxGridCellCoords( row, col ) );
592 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
593 }
594
595 // Send event
596 if (sendEvent)
597 {
598 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
599 wxEVT_GRID_RANGE_SELECT,
600 m_grid,
601 wxGridCellCoords( row, col ),
602 wxGridCellCoords( row, col ),
603 true,
604 ControlDown, ShiftDown,
605 AltDown, MetaDown );
606 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
607 }
608 }
609
610 void wxGridSelection::ToggleCellSelection( int row, int col,
611 bool ControlDown, bool ShiftDown,
612 bool AltDown, bool MetaDown )
613 {
614 // if the cell is not selected, select it
615 if ( !IsInSelection ( row, col ) )
616 {
617 SelectCell( row, col, ControlDown, ShiftDown, AltDown, MetaDown );
618
619 return;
620 }
621
622 // otherwise deselect it. This can be simple or more or
623 // less difficult, depending on how the cell is selected.
624 size_t count, n;
625
626 // The simplest case: The cell is contained in m_cellSelection
627 // Then it can't be contained in rows/cols/block (since those
628 // would remove the cell from m_cellSelection on creation), so
629 // we just have to remove it from m_cellSelection.
630
631 if ( m_selectionMode == wxGrid::wxGridSelectCells )
632 {
633 count = m_cellSelection.GetCount();
634 for ( n = 0; n < count; n++ )
635 {
636 const wxGridCellCoords& sel = m_cellSelection[n];
637 if ( row == sel.GetRow() && col == sel.GetCol() )
638 {
639 wxGridCellCoords coords = m_cellSelection[n];
640 m_cellSelection.RemoveAt(n);
641 if ( !m_grid->GetBatchCount() )
642 {
643 wxRect r = m_grid->BlockToDeviceRect( coords, coords );
644 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
645 }
646
647 // Send event
648 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
649 wxEVT_GRID_RANGE_SELECT,
650 m_grid,
651 wxGridCellCoords( row, col ),
652 wxGridCellCoords( row, col ),
653 false,
654 ControlDown, ShiftDown,
655 AltDown, MetaDown );
656 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
657
658 return;
659 }
660 }
661 }
662
663 // The most difficult case: The cell is member of one or even several
664 // blocks. Split each such block in up to 4 new parts, that don't
665 // contain the cell to be selected, like this:
666 // |---------------------------|
667 // | |
668 // | part 1 |
669 // | |
670 // |---------------------------|
671 // | part 3 |x| part 4 |
672 // |---------------------------|
673 // | |
674 // | part 2 |
675 // | |
676 // |---------------------------|
677 // (The x marks the newly deselected cell).
678 // Note: in row selection mode, we only need part1 and part2;
679 // in column selection mode, we only need part 3 and part4,
680 // which are expanded to whole columns automatically!
681
682 count = m_blockSelectionTopLeft.GetCount();
683 for ( n = 0; n < count; n++ )
684 {
685 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
686 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
687 int topRow = coords1.GetRow();
688 int leftCol = coords1.GetCol();
689 int bottomRow = coords2.GetRow();
690 int rightCol = coords2.GetCol();
691
692 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol, row, col ) )
693 {
694 // remove the block
695 m_blockSelectionTopLeft.RemoveAt(n);
696 m_blockSelectionBottomRight.RemoveAt(n);
697 n--;
698 count--;
699
700 // add up to 4 smaller blocks and set update region
701 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
702 {
703 if ( topRow < row )
704 SelectBlock( topRow, leftCol, row - 1, rightCol,
705 false, false, false, false, false );
706 if ( bottomRow > row )
707 SelectBlock( row + 1, leftCol, bottomRow, rightCol,
708 false, false, false, false, false );
709 }
710
711 if ( m_selectionMode != wxGrid::wxGridSelectRows )
712 {
713 if ( leftCol < col )
714 SelectBlock( row, leftCol, row, col - 1,
715 false, false, false, false, false );
716 if ( rightCol > col )
717 SelectBlock( row, col + 1, row, rightCol,
718 false, false, false, false, false );
719 }
720 }
721 }
722
723 // remove a cell from a row, adding up to two new blocks
724 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
725 {
726 count = m_rowSelection.GetCount();
727 for ( n = 0; n < count; n++ )
728 {
729 if ( m_rowSelection[n] == row )
730 {
731 m_rowSelection.RemoveAt(n);
732 n--;
733 count--;
734
735 if (m_selectionMode == wxGrid::wxGridSelectCells)
736 {
737 if ( col > 0 )
738 SelectBlock( row, 0, row, col - 1,
739 false, false, false, false, false );
740 if ( col < m_grid->GetNumberCols() - 1 )
741 SelectBlock( row, col + 1,
742 row, m_grid->GetNumberCols() - 1,
743 false, false, false, false, false );
744 }
745 }
746 }
747 }
748
749 // remove a cell from a column, adding up to two new blocks
750 if ( m_selectionMode != wxGrid::wxGridSelectRows )
751 {
752 count = m_colSelection.GetCount();
753 for ( n = 0; n < count; n++ )
754 {
755 if ( m_colSelection[n] == col )
756 {
757 m_colSelection.RemoveAt(n);
758 n--;
759 count--;
760
761 if (m_selectionMode == wxGrid::wxGridSelectCells)
762 {
763 if ( row > 0 )
764 SelectBlock( 0, col, row - 1, col,
765 false, false, false, false, false );
766 if ( row < m_grid->GetNumberRows() - 1 )
767 SelectBlock( row + 1, col,
768 m_grid->GetNumberRows() - 1, col,
769 false, false, false, false, false );
770 }
771 }
772 }
773 }
774
775 // Refresh the screen and send the event; according to m_selectionMode,
776 // we need to either update only the cell, or the whole row/column.
777 wxRect r;
778 switch (m_selectionMode)
779 {
780 case wxGrid::wxGridSelectCells:
781 {
782 if ( !m_grid->GetBatchCount() )
783 {
784 r = m_grid->BlockToDeviceRect(
785 wxGridCellCoords( row, col ),
786 wxGridCellCoords( row, col ) );
787 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
788 }
789
790 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
791 wxEVT_GRID_RANGE_SELECT,
792 m_grid,
793 wxGridCellCoords( row, col ),
794 wxGridCellCoords( row, col ),
795 false,
796 ControlDown, ShiftDown,
797 AltDown, MetaDown );
798 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
799 }
800 break;
801
802 case wxGrid::wxGridSelectRows:
803 {
804 if ( !m_grid->GetBatchCount() )
805 {
806 r = m_grid->BlockToDeviceRect(
807 wxGridCellCoords( row, 0 ),
808 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
809 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
810 }
811
812 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
813 wxEVT_GRID_RANGE_SELECT,
814 m_grid,
815 wxGridCellCoords( row, 0 ),
816 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
817 false,
818 ControlDown, ShiftDown,
819 AltDown, MetaDown );
820 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
821 }
822 break;
823
824 case wxGrid::wxGridSelectColumns:
825 {
826 if ( !m_grid->GetBatchCount() )
827 {
828 r = m_grid->BlockToDeviceRect(
829 wxGridCellCoords( 0, col ),
830 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
831 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
832 }
833
834 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
835 wxEVT_GRID_RANGE_SELECT,
836 m_grid,
837 wxGridCellCoords( 0, col ),
838 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
839 false,
840 ControlDown, ShiftDown,
841 AltDown, MetaDown );
842 m_grid->GetEventHandler()->ProcessEvent( gridEvt );
843 }
844 break;
845
846 default:
847 break;
848 }
849 }
850
851 void wxGridSelection::ClearSelection()
852 {
853 size_t n;
854 wxRect r;
855 wxGridCellCoords coords1, coords2;
856
857 // deselect all individual cells and update the screen
858 if ( m_selectionMode == wxGrid::wxGridSelectCells )
859 {
860 while ( ( n = m_cellSelection.GetCount() ) > 0)
861 {
862 n--;
863 coords1 = m_cellSelection[n];
864 m_cellSelection.RemoveAt(n);
865 if ( !m_grid->GetBatchCount() )
866 {
867 r = m_grid->BlockToDeviceRect( coords1, coords1 );
868 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
869
870 #ifdef __WXMAC__
871 ((wxWindow *)m_grid->m_gridWin)->Update();
872 #endif
873 }
874 }
875 }
876
877 // deselect all blocks and update the screen
878 while ( ( n = m_blockSelectionTopLeft.GetCount() ) > 0)
879 {
880 n--;
881 coords1 = m_blockSelectionTopLeft[n];
882 coords2 = m_blockSelectionBottomRight[n];
883 m_blockSelectionTopLeft.RemoveAt(n);
884 m_blockSelectionBottomRight.RemoveAt(n);
885 if ( !m_grid->GetBatchCount() )
886 {
887 r = m_grid->BlockToDeviceRect( coords1, coords2 );
888 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
889
890 #ifdef __WXMAC__
891 ((wxWindow *)m_grid->m_gridWin)->Update();
892 #endif
893 }
894 }
895
896 // deselect all rows and update the screen
897 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
898 {
899 while ( ( n = m_rowSelection.GetCount() ) > 0)
900 {
901 n--;
902 int row = m_rowSelection[n];
903 m_rowSelection.RemoveAt(n);
904 if ( !m_grid->GetBatchCount() )
905 {
906 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
907 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
908 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
909
910 #ifdef __WXMAC__
911 ((wxWindow *)m_grid->m_gridWin)->Update();
912 #endif
913 }
914 }
915 }
916
917 // deselect all columns and update the screen
918 if ( m_selectionMode != wxGrid::wxGridSelectRows )
919 {
920 while ( ( n = m_colSelection.GetCount() ) > 0)
921 {
922 n--;
923 int col = m_colSelection[n];
924 m_colSelection.RemoveAt(n);
925 if ( !m_grid->GetBatchCount() )
926 {
927 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
928 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
929 ((wxWindow *)m_grid->m_gridWin)->Refresh( false, &r );
930
931 #ifdef __WXMAC__
932 ((wxWindow *)m_grid->m_gridWin)->Update();
933 #endif
934 }
935 }
936 }
937
938 // One deselection event, indicating deselection of _all_ cells.
939 // (No finer grained events for each of the smaller regions
940 // deselected above!)
941 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
942 wxEVT_GRID_RANGE_SELECT,
943 m_grid,
944 wxGridCellCoords( 0, 0 ),
945 wxGridCellCoords(
946 m_grid->GetNumberRows() - 1,
947 m_grid->GetNumberCols() - 1 ),
948 false );
949
950 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
951 }
952
953
954 void wxGridSelection::UpdateRows( size_t pos, int numRows )
955 {
956 size_t count = m_cellSelection.GetCount();
957 size_t n;
958 for ( n = 0; n < count; n++ )
959 {
960 wxGridCellCoords& coords = m_cellSelection[n];
961 wxCoord row = coords.GetRow();
962 if ((size_t)row >= pos)
963 {
964 if (numRows > 0)
965 {
966 // If rows inserted, increase row counter where necessary
967 coords.SetRow(row + numRows);
968 }
969 else if (numRows < 0)
970 {
971 // If rows deleted ...
972 if ((size_t)row >= pos - numRows)
973 {
974 // ...either decrement row counter (if row still exists)...
975 coords.SetRow(row + numRows);
976 }
977 else
978 {
979 // ...or remove the attribute
980 m_cellSelection.RemoveAt(n);
981 n--;
982 count--;
983 }
984 }
985 }
986 }
987
988 count = m_blockSelectionTopLeft.GetCount();
989 for ( n = 0; n < count; n++ )
990 {
991 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
992 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
993 wxCoord row1 = coords1.GetRow();
994 wxCoord row2 = coords2.GetRow();
995
996 if ((size_t)row2 >= pos)
997 {
998 if (numRows > 0)
999 {
1000 // If rows inserted, increase row counter where necessary
1001 coords2.SetRow( row2 + numRows );
1002 if ((size_t)row1 >= pos)
1003 coords1.SetRow( row1 + numRows );
1004 }
1005 else if (numRows < 0)
1006 {
1007 // If rows deleted ...
1008 if ((size_t)row2 >= pos - numRows)
1009 {
1010 // ...either decrement row counter (if row still exists)...
1011 coords2.SetRow( row2 + numRows );
1012 if ((size_t)row1 >= pos)
1013 coords1.SetRow( wxMax(row1 + numRows, (int)pos) );
1014
1015 }
1016 else
1017 {
1018 if ((size_t)row1 >= pos)
1019 {
1020 // ...or remove the attribute
1021 m_blockSelectionTopLeft.RemoveAt(n);
1022 m_blockSelectionBottomRight.RemoveAt(n);
1023 n--;
1024 count--;
1025 }
1026 else
1027 coords2.SetRow( pos );
1028 }
1029 }
1030 }
1031 }
1032
1033 count = m_rowSelection.GetCount();
1034 for ( n = 0; n < count; n++ )
1035 {
1036 int rowOrCol_ = m_rowSelection[n];
1037
1038 if ((size_t) rowOrCol_ >= pos)
1039 {
1040 if ( numRows > 0 )
1041 {
1042 m_rowSelection[n] += numRows;
1043 }
1044 else if ( numRows < 0 )
1045 {
1046 if ((size_t)rowOrCol_ >= (pos - numRows))
1047 m_rowSelection[n] += numRows;
1048 else
1049 {
1050 m_rowSelection.RemoveAt( n );
1051 n--;
1052 count--;
1053 }
1054 }
1055 }
1056 }
1057 // No need to touch selected columns, unless we removed _all_
1058 // rows, in this case, we remove all columns from the selection.
1059
1060 if ( !m_grid->GetNumberRows() )
1061 m_colSelection.Clear();
1062 }
1063
1064
1065 void wxGridSelection::UpdateCols( size_t pos, int numCols )
1066 {
1067 size_t count = m_cellSelection.GetCount();
1068 size_t n;
1069
1070 for ( n = 0; n < count; n++ )
1071 {
1072 wxGridCellCoords& coords = m_cellSelection[n];
1073 wxCoord col = coords.GetCol();
1074 if ((size_t)col >= pos)
1075 {
1076 if (numCols > 0)
1077 {
1078 // If rows inserted, increase row counter where necessary
1079 coords.SetCol(col + numCols);
1080 }
1081 else if (numCols < 0)
1082 {
1083 // If rows deleted ...
1084 if ((size_t)col >= pos - numCols)
1085 {
1086 // ...either decrement row counter (if row still exists)...
1087 coords.SetCol(col + numCols);
1088 }
1089 else
1090 {
1091 // ...or remove the attribute
1092 m_cellSelection.RemoveAt(n);
1093 n--;
1094 count--;
1095 }
1096 }
1097 }
1098 }
1099
1100 count = m_blockSelectionTopLeft.GetCount();
1101 for ( n = 0; n < count; n++ )
1102 {
1103 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
1104 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
1105 wxCoord col1 = coords1.GetCol();
1106 wxCoord col2 = coords2.GetCol();
1107
1108 if ((size_t)col2 >= pos)
1109 {
1110 if (numCols > 0)
1111 {
1112 // If rows inserted, increase row counter where necessary
1113 coords2.SetCol(col2 + numCols);
1114 if ((size_t)col1 >= pos)
1115 coords1.SetCol(col1 + numCols);
1116 }
1117 else if (numCols < 0)
1118 {
1119 // If cols deleted ...
1120 if ((size_t)col2 >= pos - numCols)
1121 {
1122 // ...either decrement col counter (if col still exists)...
1123 coords2.SetCol(col2 + numCols);
1124 if ( (size_t) col1 >= pos)
1125 coords1.SetCol( wxMax(col1 + numCols, (int)pos) );
1126
1127 }
1128 else
1129 {
1130 if ((size_t)col1 >= pos)
1131 {
1132 // ...or remove the attribute
1133 m_blockSelectionTopLeft.RemoveAt(n);
1134 m_blockSelectionBottomRight.RemoveAt(n);
1135 n--;
1136 count--;
1137 }
1138 else
1139 coords2.SetCol(pos);
1140 }
1141 }
1142 }
1143 }
1144
1145 count = m_colSelection.GetCount();
1146 for ( n = 0; n < count; n++ )
1147 {
1148 int rowOrCol = m_colSelection[n];
1149
1150 if ((size_t)rowOrCol >= pos)
1151 {
1152 if ( numCols > 0 )
1153 m_colSelection[n] += numCols;
1154 else if ( numCols < 0 )
1155 {
1156 if ((size_t)rowOrCol >= (pos - numCols))
1157 m_colSelection[n] += numCols;
1158 else
1159 {
1160 m_colSelection.RemoveAt( n );
1161 n--;
1162 count--;
1163 }
1164 }
1165 }
1166 }
1167
1168 // No need to touch selected rows, unless we removed _all_
1169 // columns, in this case, we remove all rows from the selection.
1170 if ( !m_grid->GetNumberCols() )
1171 m_rowSelection.Clear();
1172 }
1173
1174 int wxGridSelection::BlockContain( int topRow1, int leftCol1,
1175 int bottomRow1, int rightCol1,
1176 int topRow2, int leftCol2,
1177 int bottomRow2, int rightCol2 )
1178 // returns 1, if Block1 contains Block2,
1179 // -1, if Block2 contains Block1,
1180 // 0, otherwise
1181 {
1182 if ( topRow1 <= topRow2 && bottomRow2 <= bottomRow1 &&
1183 leftCol1 <= leftCol2 && rightCol2 <= rightCol1 )
1184 return 1;
1185 else if ( topRow2 <= topRow1 && bottomRow1 <= bottomRow2 &&
1186 leftCol2 <= leftCol1 && rightCol1 <= rightCol2 )
1187 return -1;
1188
1189 return 0;
1190 }
1191
1192 #endif