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