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