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 wxGridSelection::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
!= wxGridSelection::wxGridSelectRows
&&
52 m_selectionMode
!= wxGridSelection::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
!= wxGridSelection::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
!= wxGridSelection::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
== wxGridSelection::wxGridSelectColumns
)
99 // Remove single cells contained in newly selected block.
100 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
&&
101 m_selectionMode
!= wxGridSelection::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 void wxGridSelection::SelectCol( int col
, bool addToSelected
= FALSE
)
160 if ( m_selectionMode
== wxGridSelection::wxGridSelectRows
)
164 // Remove single cells contained in newly selected block.
165 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
&&
166 m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
168 count
= m_cellSelection
.GetCount();
169 for ( size_t n
= 0; n
< count
; n
++ )
171 wxGridCellCoords
& coords
= m_cellSelection
[n
];
172 if ( BlockContainsCell( 0, col
, m_grid
->GetNumberRows() - 1, col
,
173 coords
.GetRow(), coords
.GetCol() ) )
175 m_cellSelection
.RemoveAt(n
);
181 // If possible, merge col with existing selected block
182 count
= m_blockSelectionTopLeft
.GetCount();
183 for ( size_t n
= 0; n
< count
; n
++ )
185 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
186 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
187 if ( coords1
.GetCol() == col
&& col
== coords2
.GetCol() )
189 m_blockSelectionTopLeft
.RemoveAt(n
);
190 m_blockSelectionBottomRight
.RemoveAt(n
);
193 else if ( coords1
.GetRow() == 0 &&
194 coords2
.GetRow() == m_grid
->GetNumberRows() - 1 )
196 if ( coords1
.GetCol() <= col
&& col
<= coords2
.GetCol() )
198 else if ( coords1
.GetCol() == col
+ 1)
203 else if ( coords2
.GetCol() == col
- 1)
211 // Check whether col is already selected.
212 count
= m_colSelection
.GetCount();
213 for ( size_t n
= 0; n
< count
; n
++ )
215 if ( col
== m_colSelection
[n
] )
219 // Add col to selection
220 m_colSelection
.Add(col
);
223 void wxGridSelection::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
225 // Fix the coordinates of the block if potentially needed
226 if ( m_selectionMode
== wxGridSelection::wxGridSelectRows
)
229 rightCol
= m_grid
->GetNumberCols() - 1;
231 else if ( m_selectionMode
== wxGridSelection::wxGridSelectColumns
)
234 bottomRow
= m_grid
->GetNumberRows() - 1;
237 // Handle single cell selection in SelectCell.
238 if ( topRow
== bottomRow
&& leftCol
== rightCol
)
239 SelectCell( topRow
, leftCol
);
242 // Remove single cells contained in newly selected block.
243 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
&&
244 m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
246 count
= m_cellSelection
.GetCount();
247 for ( size_t n
= 0; n
< count
; n
++ )
249 wxGridCellCoords
& coords
= m_cellSelection
[n
];
250 if ( BlockContainsCell( topRow
, leftCol
, bottomRow
, rightCol
,
251 coords
.GetRow(), coords
.GetCol() ) )
253 m_cellSelection
.RemoveAt(n
);
259 // If a block containing the selection is already selected, return,
260 // if a block contained in the selection is found, remove it.
262 count
= m_blockSelectionTopLeft
.GetCount();
263 for ( size_t n
= 0; n
< count
; n
++ )
265 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
266 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
267 switch ( BlockContain( coords1
.GetRow(), coords1
.GetCol(),
268 coords2
.GetRow(), coords2
.GetCol(),
269 topRow
, leftCol
, bottomRow
, rightCol
) )
274 m_blockSelectionTopLeft
.RemoveAt(n
);
275 m_blockSelectionBottomRight
.RemoveAt(n
);
282 // If a row containing the selection is already selected, return,
283 // if a row contained in newly selected block is found, remove it.
284 if ( m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
286 size_t count
= m_rowSelection
.GetCount();
287 for ( size_t n
= 0; n
< count
; n
++ )
289 switch ( BlockContain( m_rowSelection
[n
], 0,
290 m_rowSelection
[n
], m_grid
->GetNumberCols()-1,
291 topRow
, leftCol
, bottomRow
, rightCol
) )
296 m_rowSelection
.RemoveAt(n
);
303 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
)
305 size_t count
= m_colSelection
.GetCount();
306 for ( size_t n
= 0; n
< count
; n
++ )
308 switch ( BlockContain( 0, m_colSelection
[n
],
309 m_grid
->GetNumberRows()-1, m_colSelection
[n
],
310 topRow
, leftCol
, bottomRow
, rightCol
) )
315 m_colSelection
.RemoveAt(n
);
322 m_blockSelectionTopLeft
.Add( wxGridCellCoords( topRow
, leftCol
) );
323 m_blockSelectionBottomRight
.Add( wxGridCellCoords( bottomRow
, rightCol
) );
326 void wxGridSelection::SelectCell( int row
, int col
)
328 if ( m_selectionMode
== wxGridSelection::wxGridSelectRows
)
329 SelectBlock(row
, 0, row
, m_grid
->GetNumberCols() - 1 );
330 else if ( m_selectionMode
== wxGridSelection::wxGridSelectColumns
)
331 SelectBlock(0, col
, m_grid
->GetNumberRows() - 1, col
);
332 else if ( IsInSelection ( row
, col
) )
334 m_cellSelection
.Add( wxGridCellCoords( row
, col
) );
337 void wxGridSelection::ToggleCellSelection( int row
, int col
)
339 if ( !IsInSelection ( row
, col
) )
340 SelectCell( row
, col
);
343 // Maybe we want to toggle a member of m_cellSelection.
344 // Then it can't be contained in rows/cols/block, and we
345 // just have to remove it from m_cellSelection.
347 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
&&
348 m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
350 count
= m_cellSelection
.GetCount();
351 for ( size_t n
= 0; n
< count
; n
++ )
353 wxGridCellCoords
& coords
= m_cellSelection
[n
];
354 if ( row
== coords
.GetRow() && col
== coords
.GetCol() )
356 m_cellSelection
.RemoveAt(n
);
359 r
= m_grid
->BlockToDeviceRect( m_cellSelection
[n
],
360 m_cellSelection
[n
] );
361 if ( !m_grid
->GetBatchCount() )
362 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
368 // remove a cell from the middle of a block (the really ugly case)
369 count
= m_blockSelectionTopLeft
.GetCount();
370 for ( size_t n
= 0; n
< count
; n
++ )
372 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
373 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
374 int topRow
= coords1
.GetRow();
375 int leftCol
= coords1
.GetCol();
376 int bottomRow
= coords2
.GetRow();
377 int rightCol
= coords2
.GetCol();
378 if ( BlockContainsCell( topRow
, leftCol
, bottomRow
, rightCol
,
382 m_blockSelectionTopLeft
.RemoveAt(n
);
383 m_blockSelectionBottomRight
.RemoveAt(n
);
385 // add up to 4 smaller blocks and set update region
386 if ( m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
389 SelectBlock( topRow
, leftCol
, row
- 1, rightCol
);
390 if ( bottomRow
> row
)
391 SelectBlock( row
+ 1, leftCol
, bottomRow
, rightCol
);
393 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
)
396 SelectBlock( row
, leftCol
, row
, col
- 1 );
397 if ( rightCol
> col
)
398 SelectBlock( row
, col
+ 1, row
, rightCol
);
403 // remove a cell from a row, adding up to two new blocks
404 if ( m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
406 size_t count
= m_rowSelection
.GetCount();
407 for ( size_t n
= 0; n
< count
; n
++ )
409 if ( m_rowSelection
[n
] == row
)
411 m_rowSelection
.RemoveAt(n
);
413 if (m_selectionMode
== wxGridSelection::wxGridSelectCells
)
416 SelectBlock( row
, 0, row
, col
- 1 );
417 if ( col
< m_grid
->GetNumberCols() - 1 )
418 SelectBlock( row
, col
+ 1, row
, m_grid
->GetNumberCols() - 1 );
424 // remove a cell from a column, adding up to two new blocks
425 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
)
427 size_t count
= m_colSelection
.GetCount();
428 for ( size_t n
= 0; n
< count
; n
++ )
430 if ( m_colSelection
[n
] == col
)
432 m_colSelection
.RemoveAt(n
);
434 if (m_selectionMode
== wxGridSelection::wxGridSelectCells
)
437 SelectBlock( 0, col
, row
- 1, col
);
438 if ( row
< m_grid
->GetNumberRows() - 1 )
439 SelectBlock( row
+ 1, col
, m_grid
->GetNumberRows() - 1, col
);
445 switch (m_selectionMode
)
447 case wxGridSelection::wxGridSelectCells
:
448 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, col
),
449 wxGridCellCoords( row
, col
) );
451 case wxGridSelection::wxGridSelectRows
:
452 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
453 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
455 case wxGridSelection::wxGridSelectColumns
:
456 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
457 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
460 if ( !m_grid
->GetBatchCount() )
461 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
464 void wxGridSelection::ClearSelection()
467 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
&&
468 m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
471 while( ( n
= m_cellSelection
.GetCount() ) > 0)
474 r
= m_grid
->BlockToDeviceRect( m_cellSelection
[n
],
475 m_cellSelection
[n
] );
476 m_cellSelection
.RemoveAt(n
);
477 if ( !m_grid
->GetBatchCount() )
478 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
481 while( ( n
= m_blockSelectionTopLeft
.GetCount() ) > 0)
484 r
= m_grid
->BlockToDeviceRect( m_blockSelectionTopLeft
[n
],
485 m_blockSelectionBottomRight
[n
] );
486 m_blockSelectionTopLeft
.RemoveAt(n
);
487 m_blockSelectionBottomRight
.RemoveAt(n
);
488 if ( !m_grid
->GetBatchCount() )
489 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
491 if ( m_selectionMode
!= wxGridSelection::wxGridSelectColumns
)
493 while( ( n
= m_rowSelection
.GetCount() ) > 0)
495 int & row
= m_rowSelection
[n
];
497 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( row
, 0 ),
498 wxGridCellCoords( row
, m_grid
->GetNumberCols() - 1 ) );
499 m_rowSelection
.RemoveAt(n
);
500 if ( !m_grid
->GetBatchCount() )
501 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
504 if ( m_selectionMode
!= wxGridSelection::wxGridSelectRows
)
506 while( ( n
= m_colSelection
.GetCount() ) > 0)
508 int & col
= m_colSelection
[n
];
510 r
= m_grid
->BlockToDeviceRect( wxGridCellCoords( 0, col
),
511 wxGridCellCoords( m_grid
->GetNumberRows() - 1, col
) );
512 m_colSelection
.RemoveAt(n
);
513 if ( !m_grid
->GetBatchCount() )
514 ((wxWindow
*)m_grid
->m_gridWin
)->Refresh( FALSE
, &r
);
520 void wxGridSelection::UpdateRows( size_t pos
, int numRows
)
522 size_t count
= m_cellSelection
.GetCount();
523 for ( size_t n
= 0; n
< count
; n
++ )
525 wxGridCellCoords
& coords
= m_cellSelection
[n
];
526 wxCoord row
= coords
.GetRow();
527 if ((size_t)row
>= pos
)
531 // If rows inserted, increase row counter where necessary
532 coords
.SetRow(row
+ numRows
);
534 else if (numRows
< 0)
536 // If rows deleted ...
537 if ((size_t)row
>= pos
- numRows
)
539 // ...either decrement row counter (if row still exists)...
540 coords
.SetRow(row
+ numRows
);
544 // ...or remove the attribute
545 m_cellSelection
.RemoveAt(n
);
552 count
= m_blockSelectionTopLeft
.GetCount();
553 for ( size_t n
= 0; n
< count
; n
++ )
555 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
556 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
557 wxCoord row1
= coords1
.GetRow();
558 wxCoord row2
= coords2
.GetRow();
559 if ((size_t)row2
>= pos
)
563 // If rows inserted, increase row counter where necessary
564 coords2
.SetRow(row2
+ numRows
);
565 if ( (size_t)row1
>= pos
)
566 coords1
.SetRow(row1
+ numRows
);
568 else if (numRows
< 0)
570 // If rows deleted ...
571 if ((size_t)row2
>= pos
- numRows
)
573 // ...either decrement row counter (if row still exists)...
574 coords2
.SetRow(row2
+ numRows
);
575 if ( (size_t) row1
>= pos
)
576 coords1
.SetRow( wxMax(row1
+ numRows
, (int) pos
) );
581 if ( (size_t) row1
>= pos
)
583 // ...or remove the attribute
584 m_blockSelectionTopLeft
.RemoveAt(n
);
585 m_blockSelectionBottomRight
.RemoveAt(n
);
595 count
= m_rowSelection
.GetCount();
596 for ( size_t n
= 0; n
< count
; n
++ )
598 int & rowOrCol
= m_rowSelection
[n
];
599 if ( (size_t)rowOrCol
>= pos
)
603 // If rows inserted, include row counter where necessary
606 else if ( numRows
< 0)
608 // If rows deleted, either decrement row counter (if row still exists)
609 if ((size_t)rowOrCol
>= pos
- numRows
)
613 m_rowSelection
.RemoveAt(n
);
621 void wxGridSelection::UpdateCols( size_t pos
, int numCols
)
623 size_t count
= m_cellSelection
.GetCount();
624 for ( size_t n
= 0; n
< count
; n
++ )
626 wxGridCellCoords
& coords
= m_cellSelection
[n
];
627 wxCoord col
= coords
.GetCol();
628 if ((size_t)col
>= pos
)
632 // If rows inserted, increase row counter where necessary
633 coords
.SetCol(col
+ numCols
);
635 else if (numCols
< 0)
637 // If rows deleted ...
638 if ((size_t)col
>= pos
- numCols
)
640 // ...either decrement row counter (if row still exists)...
641 coords
.SetCol(col
+ numCols
);
645 // ...or remove the attribute
646 m_cellSelection
.RemoveAt(n
);
653 count
= m_blockSelectionTopLeft
.GetCount();
654 for ( size_t n
= 0; n
< count
; n
++ )
656 wxGridCellCoords
& coords1
= m_blockSelectionTopLeft
[n
];
657 wxGridCellCoords
& coords2
= m_blockSelectionBottomRight
[n
];
658 wxCoord col1
= coords1
.GetCol();
659 wxCoord col2
= coords2
.GetCol();
660 if ((size_t)col2
>= pos
)
664 // If rows inserted, increase row counter where necessary
665 coords2
.SetCol(col2
+ numCols
);
666 if ( (size_t)col1
>= pos
)
667 coords1
.SetCol(col1
+ numCols
);
669 else if (numCols
< 0)
671 // If cols deleted ...
672 if ((size_t)col2
>= pos
- numCols
)
674 // ...either decrement col counter (if col still exists)...
675 coords2
.SetCol(col2
+ numCols
);
676 if ( (size_t) col1
>= pos
)
677 coords1
.SetCol( wxMax(col1
+ numCols
, (int) pos
) );
682 if ( (size_t) col1
>= pos
)
684 // ...or remove the attribute
685 m_blockSelectionTopLeft
.RemoveAt(n
);
686 m_blockSelectionBottomRight
.RemoveAt(n
);
696 count
= m_colSelection
.GetCount();
697 for ( size_t n
= 0; n
< count
; n
++ )
699 int & rowOrCol
= m_colSelection
[n
];
700 if ( (size_t)rowOrCol
>= pos
)
704 // If cols inserted, include col counter where necessary
707 else if ( numCols
< 0)
709 // If cols deleted, either decrement col counter (if col still exists)
710 if ((size_t)rowOrCol
>= pos
- numCols
)
714 m_colSelection
.RemoveAt(n
);
722 int wxGridSelection::BlockContain( int topRow1
, int leftCol1
,
723 int bottomRow1
, int rightCol1
,
724 int topRow2
, int leftCol2
,
725 int bottomRow2
, int rightCol2
)
726 // returns 1, if Block1 contains Block2,
727 // -1, if Block2 contains Block1,
730 if ( topRow1
<= topRow2
&& bottomRow2
<= bottomRow1
&&
731 leftCol1
<= leftCol2
&& rightCol2
<= rightCol1
)
733 else if ( topRow2
<= topRow1
&& bottomRow1
<= bottomRow2
&&
734 leftCol2
<= leftCol1
&& rightCol1
<= rightCol2
)