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