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
)
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();
119 for ( n
= 0; n
< count
; n
++ )
121 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
122 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
123 if ( coords1
.GetRow() == row
&& row
== coords2
.GetRow() )
125 m_blockSelectionTopLeft
.RemoveAt(n
);
126 m_blockSelectionBottomRight
.RemoveAt(n
);
129 else if ( coords1
.GetCol() == 0 &&
130 coords2
.GetCol() == m_grid
->GetNumberCols() - 1 )
132 if ( coords1
.GetRow() <= row
&& row
<= coords2
.GetRow() )
134 else if ( coords1
.GetRow() == row
+ 1)
139 else if ( coords2
.GetRow() == row
- 1)
147 // Check whether row is already selected.
148 count
= m_rowSelection
.GetCount();
149 for ( n
= 0; n
< count
; n
++ )
151 if ( row
== m_rowSelection
[n
] )
155 // Add row to selection
156 m_rowSelection
.Add(row
);
159 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
160 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
161 if ( !m_grid
->GetBatchCount() )
162 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
165 void wxGridSelection::SelectCol( int col
, bool addToSelected
)
167 if ( m_selectionMode
== wxGrid::wxGridSelectRows
)
171 // Remove single cells contained in newly selected block.
172 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
173 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
175 count
= m_cellSelection
.GetCount();
176 for ( size_t n
= 0; n
< count
; n
++ )
178 wxGridCellCoords
& coords
= m_cellSelection
[n
];
179 if ( BlockContainsCell( 0, col
, m_grid
->GetNumberRows() - 1, col
,
180 coords
.GetRow(), coords
.GetCol() ) )
182 m_cellSelection
.RemoveAt(n
);
188 // If possible, merge col with existing selected block
189 count
= m_blockSelectionTopLeft
.GetCount();
191 for ( n
= 0; n
< count
; n
++ )
193 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
194 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
195 if ( coords1
.GetCol() == col
&& col
== coords2
.GetCol() )
197 m_blockSelectionTopLeft
.RemoveAt(n
);
198 m_blockSelectionBottomRight
.RemoveAt(n
);
201 else if ( coords1
.GetRow() == 0 &&
202 coords2
.GetRow() == m_grid
->GetNumberRows() - 1 )
204 if ( coords1
.GetCol() <= col
&& col
<= coords2
.GetCol() )
206 else if ( coords1
.GetCol() == col
+ 1)
211 else if ( coords2
.GetCol() == col
- 1)
219 // Check whether col is already selected.
220 count
= m_colSelection
.GetCount();
221 for ( n
= 0; n
< count
; n
++ )
223 if ( col
== m_colSelection
[n
] )
227 // Add col to selection
228 m_colSelection
.Add(col
);
231 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
232 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
233 if ( !m_grid
->GetBatchCount() )
234 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
237 void wxGridSelection::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
239 // Fix the coordinates of the block if potentially needed
240 if ( m_selectionMode
== wxGrid::wxGridSelectRows
)
243 rightCol
= m_grid
->GetNumberCols() - 1;
245 else if ( m_selectionMode
== wxGrid::wxGridSelectColumns
)
248 bottomRow
= m_grid
->GetNumberRows() - 1;
251 // Handle single cell selection in SelectCell.
252 if ( topRow
== bottomRow
&& leftCol
== rightCol
)
253 SelectCell( topRow
, leftCol
);
256 // Remove single cells contained in newly selected block.
257 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
258 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
260 count
= m_cellSelection
.GetCount();
261 for ( size_t n
= 0; n
< count
; n
++ )
263 wxGridCellCoords
& coords
= m_cellSelection
[n
];
264 if ( BlockContainsCell( topRow
, leftCol
, bottomRow
, rightCol
,
265 coords
.GetRow(), coords
.GetCol() ) )
267 m_cellSelection
.RemoveAt(n
);
273 // If a block containing the selection is already selected, return,
274 // if a block contained in the selection is found, remove it.
276 count
= m_blockSelectionTopLeft
.GetCount();
277 for ( size_t n
= 0; n
< count
; n
++ )
279 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
280 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
281 switch ( BlockContain( coords1
.GetRow(), coords1
.GetCol(),
282 coords2
.GetRow(), coords2
.GetCol(),
283 topRow
, leftCol
, bottomRow
, rightCol
) )
288 m_blockSelectionTopLeft
.RemoveAt(n
);
289 m_blockSelectionBottomRight
.RemoveAt(n
);
296 // If a row containing the selection is already selected, return,
297 // if a row contained in newly selected block is found, remove it.
298 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
300 size_t count
= m_rowSelection
.GetCount();
301 for ( size_t n
= 0; n
< count
; n
++ )
303 switch ( BlockContain( m_rowSelection
[n
], 0,
304 m_rowSelection
[n
], m_grid
->GetNumberCols()-1,
305 topRow
, leftCol
, bottomRow
, rightCol
) )
310 m_rowSelection
.RemoveAt(n
);
317 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
319 size_t count
= m_colSelection
.GetCount();
320 for ( size_t n
= 0; n
< count
; n
++ )
322 switch ( BlockContain( 0, m_colSelection
[n
],
323 m_grid
->GetNumberRows()-1, m_colSelection
[n
],
324 topRow
, leftCol
, bottomRow
, rightCol
) )
329 m_colSelection
.RemoveAt(n
);
336 m_blockSelectionTopLeft
.Add( wxGridCellCoords( topRow
, leftCol
) );
337 m_blockSelectionBottomRight
.Add( wxGridCellCoords( bottomRow
, rightCol
) );
340 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( topRow
, leftCol
),
341 wxGridCellCoords( bottomRow
, rightCol
) );
342 if ( !m_grid
->GetBatchCount() )
343 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
346 void wxGridSelection::SelectCell( int row
, int col
)
348 if ( m_selectionMode
== wxGrid::wxGridSelectRows
)
349 SelectBlock(row
, 0, row
, m_grid
->GetNumberCols() - 1 );
350 else if ( m_selectionMode
== wxGrid::wxGridSelectColumns
)
351 SelectBlock(0, col
, m_grid
->GetNumberRows() - 1, col
);
352 else if ( IsInSelection ( row
, col
) )
354 m_cellSelection
.Add( wxGridCellCoords( row
, col
) );
356 wxRect r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, col
),
357 wxGridCellCoords( row
, col
) );
358 if ( !m_grid
->GetBatchCount() )
359 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
362 void wxGridSelection::ToggleCellSelection( int row
, int col
)
364 if ( !IsInSelection ( row
, col
) )
366 SelectCell( row
, col
);
371 // Maybe we want to toggle a member of m_cellSelection.
372 // Then it can't be contained in rows/cols/block, and we
373 // just have to remove it from m_cellSelection.
375 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
376 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
378 count
= m_cellSelection
.GetCount();
379 for ( size_t n
= 0; n
< count
; n
++ )
381 wxGridCellCoords
& coords
= m_cellSelection
[n
];
382 if ( row
== coords
.GetRow() && col
== coords
.GetCol() )
385 r
= m_grid
->BlockToDeviceRect( m_cellSelection
[n
],
386 m_cellSelection
[n
] );
387 m_cellSelection
.RemoveAt(n
);
389 if ( !m_grid
->GetBatchCount() )
390 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
396 // remove a cell from the middle of a block (the really ugly case)
397 count
= m_blockSelectionTopLeft
.GetCount();
398 for ( size_t n
= 0; n
< count
; n
++ )
400 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
401 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
402 int topRow
= coords1
.GetRow();
403 int leftCol
= coords1
.GetCol();
404 int bottomRow
= coords2
.GetRow();
405 int rightCol
= coords2
.GetCol();
406 if ( BlockContainsCell( topRow
, leftCol
, bottomRow
, rightCol
,
410 m_blockSelectionTopLeft
.RemoveAt(n
);
411 m_blockSelectionBottomRight
.RemoveAt(n
);
413 // add up to 4 smaller blocks and set update region
414 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
417 SelectBlock( topRow
, leftCol
, row
- 1, rightCol
);
418 if ( bottomRow
> row
)
419 SelectBlock( row
+ 1, leftCol
, bottomRow
, rightCol
);
421 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
424 SelectBlock( row
, leftCol
, row
, col
- 1 );
425 if ( rightCol
> col
)
426 SelectBlock( row
, col
+ 1, row
, rightCol
);
431 // remove a cell from a row, adding up to two new blocks
432 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
434 size_t count
= m_rowSelection
.GetCount();
435 for ( size_t n
= 0; n
< count
; n
++ )
437 if ( m_rowSelection
[n
] == row
)
439 m_rowSelection
.RemoveAt(n
);
441 if (m_selectionMode
== wxGrid::wxGridSelectCells
)
444 SelectBlock( row
, 0, row
, col
- 1 );
445 if ( col
< m_grid
->GetNumberCols() - 1 )
446 SelectBlock( row
, col
+ 1, row
, m_grid
->GetNumberCols() - 1 );
452 // remove a cell from a column, adding up to two new blocks
453 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
455 size_t count
= m_colSelection
.GetCount();
456 for ( size_t n
= 0; n
< count
; n
++ )
458 if ( m_colSelection
[n
] == col
)
460 m_colSelection
.RemoveAt(n
);
462 if (m_selectionMode
== wxGrid::wxGridSelectCells
)
465 SelectBlock( 0, col
, row
- 1, col
);
466 if ( row
< m_grid
->GetNumberRows() - 1 )
467 SelectBlock( row
+ 1, col
, m_grid
->GetNumberRows() - 1, col
);
473 switch (m_selectionMode
)
475 case wxGrid::wxGridSelectCells
:
476 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, col
),
477 wxGridCellCoords( row
, col
) );
479 case wxGrid::wxGridSelectRows
:
480 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
481 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
483 case wxGrid::wxGridSelectColumns
:
484 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
485 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
488 if ( !m_grid
->GetBatchCount() )
489 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
492 void wxGridSelection::ClearSelection()
495 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
&&
496 m_selectionMode
!= wxGrid::wxGridSelectColumns
)
499 while( ( n
= m_cellSelection
.GetCount() ) > 0)
503 r
= m_grid
->BlockToDeviceRect( m_cellSelection
[n
],
504 m_cellSelection
[n
] );
505 m_cellSelection
.RemoveAt(n
);
506 if ( !m_grid
->GetBatchCount() )
507 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
510 while( ( n
= m_blockSelectionTopLeft
.GetCount() ) > 0)
514 r
= m_grid
->BlockToDeviceRect( m_blockSelectionTopLeft
[n
],
515 m_blockSelectionBottomRight
[n
] );
516 m_blockSelectionTopLeft
.RemoveAt(n
);
517 m_blockSelectionBottomRight
.RemoveAt(n
);
518 if ( !m_grid
->GetBatchCount() )
519 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
521 if ( m_selectionMode
!= wxGrid::wxGridSelectColumns
)
523 while( ( n
= m_rowSelection
.GetCount() ) > 0)
526 int & row
= m_rowSelection
[n
];
528 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
529 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
530 m_rowSelection
.RemoveAt(n
);
531 if ( !m_grid
->GetBatchCount() )
532 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
535 if ( m_selectionMode
!= wxGrid::wxGridSelectRows
)
537 while( ( n
= m_colSelection
.GetCount() ) > 0)
540 int & col
= m_colSelection
[n
];
542 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
543 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
544 m_colSelection
.RemoveAt(n
);
545 if ( !m_grid
->GetBatchCount() )
546 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
552 void wxGridSelection::UpdateRows( size_t pos
, int numRows
)
554 size_t count
= m_cellSelection
.GetCount();
556 for ( n
= 0; n
< count
; n
++ )
558 wxGridCellCoords
& coords
= m_cellSelection
[n
];
559 wxCoord row
= coords
.GetRow();
560 if ((size_t)row
>= pos
)
564 // If rows inserted, increase row counter where necessary
565 coords
.SetRow(row
+ numRows
);
567 else if (numRows
< 0)
569 // If rows deleted ...
570 if ((size_t)row
>= pos
- numRows
)
572 // ...either decrement row counter (if row still exists)...
573 coords
.SetRow(row
+ numRows
);
577 // ...or remove the attribute
578 m_cellSelection
.RemoveAt(n
);
585 count
= m_blockSelectionTopLeft
.GetCount();
586 for ( n
= 0; n
< count
; n
++ )
588 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
589 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
590 wxCoord row1
= coords1
.GetRow();
591 wxCoord row2
= coords2
.GetRow();
592 if ((size_t)row2
>= pos
)
596 // If rows inserted, increase row counter where necessary
597 coords2
.SetRow(row2
+ numRows
);
598 if ( (size_t)row1
>= pos
)
599 coords1
.SetRow(row1
+ numRows
);
601 else if (numRows
< 0)
603 // If rows deleted ...
604 if ((size_t)row2
>= pos
- numRows
)
606 // ...either decrement row counter (if row still exists)...
607 coords2
.SetRow(row2
+ numRows
);
608 if ( (size_t) row1
>= pos
)
609 coords1
.SetRow( wxMax(row1
+ numRows
, (int) pos
) );
614 if ( (size_t) row1
>= pos
)
616 // ...or remove the attribute
617 m_blockSelectionTopLeft
.RemoveAt(n
);
618 m_blockSelectionBottomRight
.RemoveAt(n
);
628 count
= m_rowSelection
.GetCount();
629 for ( n
= 0; n
< count
; n
++ )
631 int & rowOrCol
= m_rowSelection
[n
];
632 if ( (size_t)rowOrCol
>= pos
)
636 // If rows inserted, include row counter where necessary
639 else if ( numRows
< 0)
641 // If rows deleted, either decrement row counter (if row still exists)
642 if ((size_t)rowOrCol
>= pos
- numRows
)
646 m_rowSelection
.RemoveAt(n
);
654 void wxGridSelection::UpdateCols( size_t pos
, int numCols
)
656 size_t count
= m_cellSelection
.GetCount();
658 for ( n
= 0; n
< count
; n
++ )
660 wxGridCellCoords
& coords
= m_cellSelection
[n
];
661 wxCoord col
= coords
.GetCol();
662 if ((size_t)col
>= pos
)
666 // If rows inserted, increase row counter where necessary
667 coords
.SetCol(col
+ numCols
);
669 else if (numCols
< 0)
671 // If rows deleted ...
672 if ((size_t)col
>= pos
- numCols
)
674 // ...either decrement row counter (if row still exists)...
675 coords
.SetCol(col
+ numCols
);
679 // ...or remove the attribute
680 m_cellSelection
.RemoveAt(n
);
687 count
= m_blockSelectionTopLeft
.GetCount();
688 for ( n
= 0; n
< count
; n
++ )
690 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
691 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
692 wxCoord col1
= coords1
.GetCol();
693 wxCoord col2
= coords2
.GetCol();
694 if ((size_t)col2
>= pos
)
698 // If rows inserted, increase row counter where necessary
699 coords2
.SetCol(col2
+ numCols
);
700 if ( (size_t)col1
>= pos
)
701 coords1
.SetCol(col1
+ numCols
);
703 else if (numCols
< 0)
705 // If cols deleted ...
706 if ((size_t)col2
>= pos
- numCols
)
708 // ...either decrement col counter (if col still exists)...
709 coords2
.SetCol(col2
+ numCols
);
710 if ( (size_t) col1
>= pos
)
711 coords1
.SetCol( wxMax(col1
+ numCols
, (int) pos
) );
716 if ( (size_t) col1
>= pos
)
718 // ...or remove the attribute
719 m_blockSelectionTopLeft
.RemoveAt(n
);
720 m_blockSelectionBottomRight
.RemoveAt(n
);
730 count
= m_colSelection
.GetCount();
731 for ( n
= 0; n
< count
; n
++ )
733 int & rowOrCol
= m_colSelection
[n
];
734 if ( (size_t)rowOrCol
>= pos
)
738 // If cols inserted, include col counter where necessary
741 else if ( numCols
< 0)
743 // If cols deleted, either decrement col counter (if col still exists)
744 if ((size_t)rowOrCol
>= pos
- numCols
)
748 m_colSelection
.RemoveAt(n
);
756 int wxGridSelection::BlockContain( int topRow1
, int leftCol1
,
757 int bottomRow1
, int rightCol1
,
758 int topRow2
, int leftCol2
,
759 int bottomRow2
, int rightCol2
)
760 // returns 1, if Block1 contains Block2,
761 // -1, if Block2 contains Block1,
764 if ( topRow1
<= topRow2
&& bottomRow2
<= bottomRow1
&&
765 leftCol1
<= leftCol2
&& rightCol2
<= rightCol1
)
767 else if ( topRow2
<= topRow1
&& bottomRow1
<= bottomRow2
&&
768 leftCol2
<= leftCol1
&& rightCol1
<= rightCol2
)