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