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