1 ///////////////////////////////////////////////////////////////////////////
2 // Name: generic/gridsel.cpp
3 // Purpose: wxGridSelection
8 // Copyright: (c) Stefan Neis (Stefan.Neis@t-online.de)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "gridsel.h"
24 // For compilers that support precompilation, includes "wx/wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/generic/gridsel.h"
35 wxGridSelection::wxGridSelection( wxGrid
* grid
,
36 wxGrid::wxGridSelectionModes sel
)
39 m_selectionMode
= sel
;
42 bool wxGridSelection::IsSelection()
44 return ( m_cellSelection
.GetCount() || m_blockSelectionTopLeft
.GetCount() ||
45 m_rowSelection
.GetCount() || m_colSelection
.GetCount() );
48 bool wxGridSelection::IsInSelection ( int row
, int col
)
51 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
52 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
54 count
= m_cellSelection
.GetCount();
55 for ( size_t n
= 0; n
< count
; n
++ )
57 wxGridCellCoords
& coords
= m_cellSelection
[n
];
58 if ( row
== coords
.GetRow() && col
== coords
.GetCol() )
62 count
= m_blockSelectionTopLeft
.GetCount();
63 for ( size_t n
= 0; n
< count
; n
++ )
65 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
66 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
67 if ( BlockContainsCell(coords1
.GetRow(), coords1
.GetCol(),
68 coords2
.GetRow(), coords2
.GetCol(),
72 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
74 size_t count
= m_rowSelection
.GetCount();
75 for ( size_t n
= 0; n
< count
; n
++ )
77 if ( row
== m_rowSelection
[n
] )
81 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
83 size_t count
= m_colSelection
.GetCount();
84 for ( size_t n
= 0; n
< count
; n
++ )
86 if ( col
== m_colSelection
[n
] )
93 void wxGridSelection::SelectRow( int row
, bool addToSelected
= FALSE
)
95 if ( m_selectionMode
== wxGrid::wxGridSelectColumns
)
99 // Remove single cells contained in newly selected block.
100 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
101 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
103 count
= m_cellSelection
.GetCount();
104 for ( size_t n
= 0; n
< count
; n
++ )
106 wxGridCellCoords
& coords
= m_cellSelection
[n
];
107 if ( BlockContainsCell( row
, 0, row
, m_grid
->GetNumberCols() - 1,
108 coords
.GetRow(), coords
.GetCol() ) )
110 m_cellSelection
.RemoveAt(n
);
116 // If possible, merge row with existing selected block
117 count
= m_blockSelectionTopLeft
.GetCount();
118 for ( size_t n
= 0; n
< count
; n
++ )
120 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
121 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
122 if ( coords1
.GetRow() == row
&& row
== coords2
.GetRow() )
124 m_blockSelectionTopLeft
.RemoveAt(n
);
125 m_blockSelectionBottomRight
.RemoveAt(n
);
128 else if ( coords1
.GetCol() == 0 &&
129 coords2
.GetCol() == m_grid
->GetNumberCols() - 1 )
131 if ( coords1
.GetRow() <= row
&& row
<= coords2
.GetRow() )
133 else if ( coords1
.GetRow() == row
+ 1)
138 else if ( coords2
.GetRow() == row
- 1)
146 // Check whether row is already selected.
147 count
= m_rowSelection
.GetCount();
148 for ( size_t n
= 0; n
< count
; n
++ )
150 if ( row
== m_rowSelection
[n
] )
154 // Add row to selection
155 m_rowSelection
.Add(row
);
158 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
159 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
160 if ( !m_grid
->GetBatchCount() )
161 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
164 void wxGridSelection::SelectCol( int col
, bool addToSelected
= FALSE
)
166 if ( m_selectionMode
== wxGrid::wxGridSelectRows
)
170 // Remove single cells contained in newly selected block.
171 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
172 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
174 count
= m_cellSelection
.GetCount();
175 for ( size_t n
= 0; n
< count
; n
++ )
177 wxGridCellCoords
& coords
= m_cellSelection
[n
];
178 if ( BlockContainsCell( 0, col
, m_grid
->GetNumberRows() - 1, col
,
179 coords
.GetRow(), coords
.GetCol() ) )
181 m_cellSelection
.RemoveAt(n
);
187 // If possible, merge col with existing selected block
188 count
= m_blockSelectionTopLeft
.GetCount();
189 for ( size_t n
= 0; n
< count
; n
++ )
191 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
192 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
193 if ( coords1
.GetCol() == col
&& col
== coords2
.GetCol() )
195 m_blockSelectionTopLeft
.RemoveAt(n
);
196 m_blockSelectionBottomRight
.RemoveAt(n
);
199 else if ( coords1
.GetRow() == 0 &&
200 coords2
.GetRow() == m_grid
->GetNumberRows() - 1 )
202 if ( coords1
.GetCol() <= col
&& col
<= coords2
.GetCol() )
204 else if ( coords1
.GetCol() == col
+ 1)
209 else if ( coords2
.GetCol() == col
- 1)
217 // Check whether col is already selected.
218 count
= m_colSelection
.GetCount();
219 for ( size_t n
= 0; n
< count
; n
++ )
221 if ( col
== m_colSelection
[n
] )
225 // Add col to selection
226 m_colSelection
.Add(col
);
229 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
230 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
231 if ( !m_grid
->GetBatchCount() )
232 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
235 void wxGridSelection::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
237 // Fix the coordinates of the block if potentially needed
238 if ( m_selectionMode
== wxGrid::wxGridSelectRows
)
241 rightCol
= m_grid
->GetNumberCols() - 1;
243 else if ( m_selectionMode
== wxGrid::wxGridSelectColumns
)
246 bottomRow
= m_grid
->GetNumberRows() - 1;
249 // Handle single cell selection in SelectCell.
250 if ( topRow
== bottomRow
&& leftCol
== rightCol
)
251 SelectCell( topRow
, leftCol
);
254 // Remove single cells contained in newly selected block.
255 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
256 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
258 count
= m_cellSelection
.GetCount();
259 for ( size_t n
= 0; n
< count
; n
++ )
261 wxGridCellCoords
& coords
= m_cellSelection
[n
];
262 if ( BlockContainsCell( topRow
, leftCol
, bottomRow
, rightCol
,
263 coords
.GetRow(), coords
.GetCol() ) )
265 m_cellSelection
.RemoveAt(n
);
271 // If a block containing the selection is already selected, return,
272 // if a block contained in the selection is found, remove it.
274 count
= m_blockSelectionTopLeft
.GetCount();
275 for ( size_t n
= 0; n
< count
; n
++ )
277 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
278 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
279 switch ( BlockContain( coords1
.GetRow(), coords1
.GetCol(),
280 coords2
.GetRow(), coords2
.GetCol(),
281 topRow
, leftCol
, bottomRow
, rightCol
) )
286 m_blockSelectionTopLeft
.RemoveAt(n
);
287 m_blockSelectionBottomRight
.RemoveAt(n
);
294 // If a row containing the selection is already selected, return,
295 // if a row contained in newly selected block is found, remove it.
296 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
298 size_t count
= m_rowSelection
.GetCount();
299 for ( size_t n
= 0; n
< count
; n
++ )
301 switch ( BlockContain( m_rowSelection
[n
], 0,
302 m_rowSelection
[n
], m_grid
->GetNumberCols()-1,
303 topRow
, leftCol
, bottomRow
, rightCol
) )
308 m_rowSelection
.RemoveAt(n
);
315 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
317 size_t count
= m_colSelection
.GetCount();
318 for ( size_t n
= 0; n
< count
; n
++ )
320 switch ( BlockContain( 0, m_colSelection
[n
],
321 m_grid
->GetNumberRows()-1, m_colSelection
[n
],
322 topRow
, leftCol
, bottomRow
, rightCol
) )
327 m_colSelection
.RemoveAt(n
);
334 m_blockSelectionTopLeft
.Add( wxGridCellCoords( topRow
, leftCol
) );
335 m_blockSelectionBottomRight
.Add( wxGridCellCoords( bottomRow
, rightCol
) );
338 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( topRow
, leftCol
),
339 wxGridCellCoords( bottomRow
, rightCol
) );
340 if ( !m_grid
->GetBatchCount() )
341 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
344 void wxGridSelection::SelectCell( int row
, int col
)
346 if ( m_selectionMode
== wxGrid::wxGridSelectRows
)
347 SelectBlock(row
, 0, row
, m_grid
->GetNumberCols() - 1 );
348 else if ( m_selectionMode
== wxGrid::wxGridSelectColumns
)
349 SelectBlock(0, col
, m_grid
->GetNumberRows() - 1, col
);
350 else if ( IsInSelection ( row
, col
) )
352 m_cellSelection
.Add( wxGridCellCoords( row
, col
) );
354 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, col
),
355 wxGridCellCoords( row
, col
) );
356 if ( !m_grid
->GetBatchCount() )
357 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
360 void wxGridSelection::ToggleCellSelection( int row
, int col
)
362 if ( !IsInSelection ( row
, col
) )
364 SelectCell( row
, col
);
369 // Maybe we want to toggle a member of m_cellSelection.
370 // Then it can't be contained in rows/cols/block, and we
371 // just have to remove it from m_cellSelection.
373 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
374 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
376 count
= m_cellSelection
.GetCount();
377 for ( size_t n
= 0; n
< count
; n
++ )
379 wxGridCellCoords
& coords
= m_cellSelection
[n
];
380 if ( row
== coords
.GetRow() && col
== coords
.GetCol() )
383 r
= m_grid
->BlockToDeviceRect( m_cellSelection
[n
],
384 m_cellSelection
[n
] );
385 m_cellSelection
.RemoveAt(n
);
387 if ( !m_grid
->GetBatchCount() )
388 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
394 // remove a cell from the middle of a block (the really ugly case)
395 count
= m_blockSelectionTopLeft
.GetCount();
396 for ( size_t n
= 0; n
< count
; n
++ )
398 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
399 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
400 int topRow
= coords1
.GetRow();
401 int leftCol
= coords1
.GetCol();
402 int bottomRow
= coords2
.GetRow();
403 int rightCol
= coords2
.GetCol();
404 if ( BlockContainsCell( topRow
, leftCol
, bottomRow
, rightCol
,
408 m_blockSelectionTopLeft
.RemoveAt(n
);
409 m_blockSelectionBottomRight
.RemoveAt(n
);
411 // add up to 4 smaller blocks and set update region
412 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
415 SelectBlock( topRow
, leftCol
, row
- 1, rightCol
);
416 if ( bottomRow
> row
)
417 SelectBlock( row
+ 1, leftCol
, bottomRow
, rightCol
);
419 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
422 SelectBlock( row
, leftCol
, row
, col
- 1 );
423 if ( rightCol
> col
)
424 SelectBlock( row
, col
+ 1, row
, rightCol
);
429 // remove a cell from a row, adding up to two new blocks
430 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
432 size_t count
= m_rowSelection
.GetCount();
433 for ( size_t n
= 0; n
< count
; n
++ )
435 if ( m_rowSelection
[n
] == row
)
437 m_rowSelection
.RemoveAt(n
);
439 if (m_selectionMode
== wxGrid::wxGridSelectCells
)
442 SelectBlock( row
, 0, row
, col
- 1 );
443 if ( col
< m_grid
->GetNumberCols() - 1 )
444 SelectBlock( row
, col
+ 1, row
, m_grid
->GetNumberCols() - 1 );
450 // remove a cell from a column, adding up to two new blocks
451 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
453 size_t count
= m_colSelection
.GetCount();
454 for ( size_t n
= 0; n
< count
; n
++ )
456 if ( m_colSelection
[n
] == col
)
458 m_colSelection
.RemoveAt(n
);
460 if (m_selectionMode
== wxGrid::wxGridSelectCells
)
463 SelectBlock( 0, col
, row
- 1, col
);
464 if ( row
< m_grid
->GetNumberRows() - 1 )
465 SelectBlock( row
+ 1, col
, m_grid
->GetNumberRows() - 1, col
);
471 switch (m_selectionMode
)
473 case wxGrid::wxGridSelectCells
:
474 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, col
),
475 wxGridCellCoords( row
, col
) );
477 case wxGrid::wxGridSelectRows
:
478 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
479 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
481 case wxGrid::wxGridSelectColumns
:
482 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
483 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
486 if ( !m_grid
->GetBatchCount() )
487 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
490 void wxGridSelection::ClearSelection()
493 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
494 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
497 while( ( n
= m_cellSelection
.GetCount() ) > 0)
501 r
= m_grid
->BlockToDeviceRect( m_cellSelection
[n
],
502 m_cellSelection
[n
] );
503 m_cellSelection
.RemoveAt(n
);
504 if ( !m_grid
->GetBatchCount() )
505 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
508 while( ( n
= m_blockSelectionTopLeft
.GetCount() ) > 0)
512 r
= m_grid
->BlockToDeviceRect( m_blockSelectionTopLeft
[n
],
513 m_blockSelectionBottomRight
[n
] );
514 m_blockSelectionTopLeft
.RemoveAt(n
);
515 m_blockSelectionBottomRight
.RemoveAt(n
);
516 if ( !m_grid
->GetBatchCount() )
517 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
519 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
521 while( ( n
= m_rowSelection
.GetCount() ) > 0)
524 int & row
= m_rowSelection
[n
];
526 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
527 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
528 m_rowSelection
.RemoveAt(n
);
529 if ( !m_grid
->GetBatchCount() )
530 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
533 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
535 while( ( n
= m_colSelection
.GetCount() ) > 0)
538 int & col
= m_colSelection
[n
];
540 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
541 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
542 m_colSelection
.RemoveAt(n
);
543 if ( !m_grid
->GetBatchCount() )
544 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
550 void wxGridSelection::UpdateRows( size_t pos
, int numRows
)
552 size_t count
= m_cellSelection
.GetCount();
553 for ( size_t n
= 0; n
< count
; n
++ )
555 wxGridCellCoords
& coords
= m_cellSelection
[n
];
556 wxCoord row
= coords
.GetRow();
557 if ((size_t)row
>= pos
)
561 // If rows inserted, increase row counter where necessary
562 coords
.SetRow(row
+ numRows
);
564 else if (numRows
< 0)
566 // If rows deleted ...
567 if ((size_t)row
>= pos
- numRows
)
569 // ...either decrement row counter (if row still exists)...
570 coords
.SetRow(row
+ numRows
);
574 // ...or remove the attribute
575 m_cellSelection
.RemoveAt(n
);
582 count
= m_blockSelectionTopLeft
.GetCount();
583 for ( size_t n
= 0; n
< count
; n
++ )
585 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
586 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
587 wxCoord row1
= coords1
.GetRow();
588 wxCoord row2
= coords2
.GetRow();
589 if ((size_t)row2
>= pos
)
593 // If rows inserted, increase row counter where necessary
594 coords2
.SetRow(row2
+ numRows
);
595 if ( (size_t)row1
>= pos
)
596 coords1
.SetRow(row1
+ numRows
);
598 else if (numRows
< 0)
600 // If rows deleted ...
601 if ((size_t)row2
>= pos
- numRows
)
603 // ...either decrement row counter (if row still exists)...
604 coords2
.SetRow(row2
+ numRows
);
605 if ( (size_t) row1
>= pos
)
606 coords1
.SetRow( wxMax(row1
+ numRows
, (int) pos
) );
611 if ( (size_t) row1
>= pos
)
613 // ...or remove the attribute
614 m_blockSelectionTopLeft
.RemoveAt(n
);
615 m_blockSelectionBottomRight
.RemoveAt(n
);
625 count
= m_rowSelection
.GetCount();
626 for ( size_t n
= 0; n
< count
; n
++ )
628 int & rowOrCol
= m_rowSelection
[n
];
629 if ( (size_t)rowOrCol
>= pos
)
633 // If rows inserted, include row counter where necessary
636 else if ( numRows
< 0)
638 // If rows deleted, either decrement row counter (if row still exists)
639 if ((size_t)rowOrCol
>= pos
- numRows
)
643 m_rowSelection
.RemoveAt(n
);
651 void wxGridSelection::UpdateCols( size_t pos
, int numCols
)
653 size_t count
= m_cellSelection
.GetCount();
654 for ( size_t n
= 0; n
< count
; n
++ )
656 wxGridCellCoords
& coords
= m_cellSelection
[n
];
657 wxCoord col
= coords
.GetCol();
658 if ((size_t)col
>= pos
)
662 // If rows inserted, increase row counter where necessary
663 coords
.SetCol(col
+ numCols
);
665 else if (numCols
< 0)
667 // If rows deleted ...
668 if ((size_t)col
>= pos
- numCols
)
670 // ...either decrement row counter (if row still exists)...
671 coords
.SetCol(col
+ numCols
);
675 // ...or remove the attribute
676 m_cellSelection
.RemoveAt(n
);
683 count
= m_blockSelectionTopLeft
.GetCount();
684 for ( size_t n
= 0; n
< count
; n
++ )
686 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
687 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
688 wxCoord col1
= coords1
.GetCol();
689 wxCoord col2
= coords2
.GetCol();
690 if ((size_t)col2
>= pos
)
694 // If rows inserted, increase row counter where necessary
695 coords2
.SetCol(col2
+ numCols
);
696 if ( (size_t)col1
>= pos
)
697 coords1
.SetCol(col1
+ numCols
);
699 else if (numCols
< 0)
701 // If cols deleted ...
702 if ((size_t)col2
>= pos
- numCols
)
704 // ...either decrement col counter (if col still exists)...
705 coords2
.SetCol(col2
+ numCols
);
706 if ( (size_t) col1
>= pos
)
707 coords1
.SetCol( wxMax(col1
+ numCols
, (int) pos
) );
712 if ( (size_t) col1
>= pos
)
714 // ...or remove the attribute
715 m_blockSelectionTopLeft
.RemoveAt(n
);
716 m_blockSelectionBottomRight
.RemoveAt(n
);
726 count
= m_colSelection
.GetCount();
727 for ( size_t n
= 0; n
< count
; n
++ )
729 int & rowOrCol
= m_colSelection
[n
];
730 if ( (size_t)rowOrCol
>= pos
)
734 // If cols inserted, include col counter where necessary
737 else if ( numCols
< 0)
739 // If cols deleted, either decrement col counter (if col still exists)
740 if ((size_t)rowOrCol
>= pos
- numCols
)
744 m_colSelection
.RemoveAt(n
);
752 int wxGridSelection::BlockContain( int topRow1
, int leftCol1
,
753 int bottomRow1
, int rightCol1
,
754 int topRow2
, int leftCol2
,
755 int bottomRow2
, int rightCol2
)
756 // returns 1, if Block1 contains Block2,
757 // -1, if Block2 contains Block1,
760 if ( topRow1
<= topRow2
&& bottomRow2
<= bottomRow1
&&
761 leftCol1
<= leftCol2
&& rightCol2
<= rightCol1
)
763 else if ( topRow2
<= topRow1
&& bottomRow1
<= bottomRow2
&&
764 leftCol2
<= leftCol1
&& rightCol1
<= rightCol2
)