]> git.saurik.com Git - wxWidgets.git/blame - src/generic/gridsel.cpp
Added conversion of menu labels (&->~)
[wxWidgets.git] / src / generic / gridsel.cpp
CommitLineData
294f6bcb
SN
1///////////////////////////////////////////////////////////////////////////
2// Name: generic/gridsel.cpp
3// Purpose: wxGridSelection
4// Author: Stefan Neis
5// Modified by:
6// Created: 20/02/1999
7// RCS-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#ifdef __GNUG__
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
f1567cdd
SN
33#if defined(wxUSE_NEW_GRID) && (wxUSE_NEW_GRID)
34
294f6bcb
SN
35#include "wx/generic/gridsel.h"
36
f1567cdd
SN
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
294f6bcb 46wxGridSelection::wxGridSelection( wxGrid * grid,
b5808881 47 wxGrid::wxGridSelectionModes sel )
294f6bcb
SN
48{
49 m_grid = grid;
50 m_selectionMode = sel;
51}
52
53bool wxGridSelection::IsSelection()
54{
55 return ( m_cellSelection.GetCount() || m_blockSelectionTopLeft.GetCount() ||
b5808881 56 m_rowSelection.GetCount() || m_colSelection.GetCount() );
294f6bcb
SN
57}
58
59bool wxGridSelection::IsInSelection ( int row, int col )
60{
f1567cdd
SN
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 )
294f6bcb
SN
66 {
67 count = m_cellSelection.GetCount();
b5808881
SN
68 for ( size_t n = 0; n < count; n++ )
69 {
70 wxGridCellCoords& coords = m_cellSelection[n];
71 if ( row == coords.GetRow() && col == coords.GetCol() )
0912bee1 72 return TRUE;
b5808881 73 }
294f6bcb 74 }
f1567cdd
SN
75
76 // Now check whether the given cell is
77 // contained in one of the selected blocks.
294f6bcb
SN
78 count = m_blockSelectionTopLeft.GetCount();
79 for ( size_t n = 0; n < count; n++ )
80 {
b5808881
SN
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 ) )
0912bee1 86 return TRUE;
b5808881 87 }
f1567cdd
SN
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).
b5808881 92 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 93 {
b5808881
SN
94 size_t count = m_rowSelection.GetCount();
95 for ( size_t n = 0; n < count; n++ )
96 {
97 if ( row == m_rowSelection[n] )
0912bee1 98 return TRUE;
b5808881
SN
99 }
100 }
f1567cdd
SN
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).
b5808881 105 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 106 {
b5808881
SN
107 size_t count = m_colSelection.GetCount();
108 for ( size_t n = 0; n < count; n++ )
109 {
110 if ( col == m_colSelection[n] )
0912bee1 111 return TRUE;
b5808881 112 }
294f6bcb 113 }
0912bee1 114 return FALSE;
294f6bcb
SN
115}
116
f1567cdd
SN
117// Change the selection mode
118void 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 }
043d16b2
SN
150
151 for (n = 0; n < m_blockSelectionTopLeft.GetCount(); n++)
152 // Note that m_blockSelectionTopLeft's size may be changing!
f1567cdd 153 {
f1567cdd
SN
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,
5c8fc7c1
SN
167 bottomRow, m_grid->GetNumberCols() - 1,
168 0, FALSE );
f1567cdd
SN
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,
5c8fc7c1
SN
178 m_grid->GetNumberRows() - 1, rightCol,
179 0, FALSE );
f1567cdd
SN
180 }
181 }
182 }
043d16b2 183 m_selectionMode = selmode;
f1567cdd
SN
184 }
185}
186
723d1b1d 187void wxGridSelection::SelectRow( int row,
d95b0c2b
SN
188 bool ControlDown, bool ShiftDown,
189 bool AltDown, bool MetaDown )
294f6bcb 190{
b5808881 191 if ( m_selectionMode == wxGrid::wxGridSelectColumns )
294f6bcb 192 return;
f1567cdd 193 size_t count, n;
294f6bcb
SN
194
195 // Remove single cells contained in newly selected block.
f1567cdd 196 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
197 {
198 count = m_cellSelection.GetCount();
f1567cdd 199 for ( n = 0; n < count; n++ )
b5808881
SN
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 }
294f6bcb
SN
209 }
210
f1567cdd 211 // Simplify list of selected blocks (if possible)
294f6bcb 212 count = m_blockSelectionTopLeft.GetCount();
0912bee1 213 bool done = FALSE;
b14159f7 214 for ( n = 0; n < count; n++ )
294f6bcb 215 {
b5808881
SN
216 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
217 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
f1567cdd
SN
218
219 // Remove block if it is a subset of the row
b5808881
SN
220 if ( coords1.GetRow() == row && row == coords2.GetRow() )
221 {
222 m_blockSelectionTopLeft.RemoveAt(n);
223 m_blockSelectionBottomRight.RemoveAt(n);
224 n--; count--;
f1567cdd 225 }
b5808881
SN
226 else if ( coords1.GetCol() == 0 &&
227 coords2.GetCol() == m_grid->GetNumberCols() - 1 )
228 {
f1567cdd 229 // silently return, if row is contained in block
b5808881
SN
230 if ( coords1.GetRow() <= row && row <= coords2.GetRow() )
231 return;
f1567cdd 232 // expand block, if it touched row
b5808881
SN
233 else if ( coords1.GetRow() == row + 1)
234 {
235 coords1.SetRow(row);
0912bee1 236 done = TRUE;
b5808881
SN
237 }
238 else if ( coords2.GetRow() == row - 1)
239 {
240 coords2.SetRow(row);
0912bee1 241 done = TRUE;
b5808881
SN
242 }
243 }
294f6bcb
SN
244 }
245
f1567cdd
SN
246 // Unless we successfully handled the row,
247 // check whether row is already selected.
248 if ( !done )
294f6bcb 249 {
f1567cdd
SN
250 count = m_rowSelection.GetCount();
251 for ( n = 0; n < count; n++ )
252 {
253 if ( row == m_rowSelection[n] )
254 return;
255 }
294f6bcb 256
f1567cdd
SN
257 // Add row to selection
258 m_rowSelection.Add(row);
259 }
b5808881
SN
260
261 // Update View:
262 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
263 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
264 if ( !m_grid->GetBatchCount() )
265 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 266
5c8fc7c1
SN
267 // Send Event
268 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
269 wxEVT_GRID_RANGE_SELECT,
270 m_grid,
271 wxGridCellCoords( row, 0 ),
d95b0c2b
SN
272 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
273 TRUE,
274 ControlDown, ShiftDown,
275 AltDown, MetaDown );
5c8fc7c1
SN
276
277 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
294f6bcb
SN
278}
279
723d1b1d 280void wxGridSelection::SelectCol( int col,
d95b0c2b
SN
281 bool ControlDown, bool ShiftDown,
282 bool AltDown, bool MetaDown )
294f6bcb 283{
b5808881 284 if ( m_selectionMode == wxGrid::wxGridSelectRows )
294f6bcb 285 return;
f1567cdd 286 size_t count, n;
294f6bcb
SN
287
288 // Remove single cells contained in newly selected block.
f1567cdd 289 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
290 {
291 count = m_cellSelection.GetCount();
f1567cdd 292 for ( n = 0; n < count; n++ )
b5808881
SN
293 {
294 wxGridCellCoords& coords = m_cellSelection[n];
295 if ( BlockContainsCell( 0, col, m_grid->GetNumberRows() - 1, col,
296 coords.GetRow(), coords.GetCol() ) )
297 {
298 m_cellSelection.RemoveAt(n);
299 n--; count--;
300 }
301 }
294f6bcb
SN
302 }
303
f1567cdd 304 // Simplify list of selected blocks (if possible)
294f6bcb 305 count = m_blockSelectionTopLeft.GetCount();
0912bee1 306 bool done = FALSE;
b14159f7 307 for ( n = 0; n < count; n++ )
294f6bcb 308 {
b5808881
SN
309 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
310 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
f1567cdd
SN
311
312 // Remove block if it is a subset of the column
b5808881
SN
313 if ( coords1.GetCol() == col && col == coords2.GetCol() )
314 {
315 m_blockSelectionTopLeft.RemoveAt(n);
316 m_blockSelectionBottomRight.RemoveAt(n);
317 n--; count--;
318 }
319 else if ( coords1.GetRow() == 0 &&
320 coords2.GetRow() == m_grid->GetNumberRows() - 1 )
321 {
f1567cdd 322 // silently return, if row is contained in block
b5808881
SN
323 if ( coords1.GetCol() <= col && col <= coords2.GetCol() )
324 return;
f1567cdd 325 // expand block, if it touched col
b5808881
SN
326 else if ( coords1.GetCol() == col + 1)
327 {
328 coords1.SetCol(col);
0912bee1 329 done = TRUE;
b5808881
SN
330 }
331 else if ( coords2.GetCol() == col - 1)
332 {
333 coords2.SetCol(col);
0912bee1 334 done = TRUE;
b5808881
SN
335 }
336 }
294f6bcb
SN
337 }
338
f1567cdd 339 // Unless we successfully handled the column,
294f6bcb 340 // Check whether col is already selected.
f1567cdd 341 if ( !done )
294f6bcb 342 {
f1567cdd
SN
343 count = m_colSelection.GetCount();
344 for ( n = 0; n < count; n++ )
345 {
346 if ( col == m_colSelection[n] )
347 return;
348 }
294f6bcb 349
f1567cdd
SN
350 // Add col to selection
351 m_colSelection.Add(col);
352 }
b5808881
SN
353
354 // Update View:
355 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
356 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
357 if ( !m_grid->GetBatchCount() )
358 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 359
5c8fc7c1
SN
360 // Send Event
361 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
362 wxEVT_GRID_RANGE_SELECT,
363 m_grid,
364 wxGridCellCoords( 0, col ),
d95b0c2b
SN
365 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
366 TRUE,
367 ControlDown, ShiftDown,
368 AltDown, MetaDown );
5c8fc7c1
SN
369
370 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
294f6bcb
SN
371}
372
5c8fc7c1
SN
373void wxGridSelection::SelectBlock( int topRow, int leftCol,
374 int bottomRow, int rightCol,
d95b0c2b
SN
375 bool ControlDown, bool ShiftDown,
376 bool AltDown, bool MetaDown,
377 bool sendEvent )
294f6bcb 378{
5c8fc7c1 379 // Fix the coordinates of the block if needed.
b5808881 380 if ( m_selectionMode == wxGrid::wxGridSelectRows )
294f6bcb 381 {
b5808881
SN
382 leftCol = 0;
383 rightCol = m_grid->GetNumberCols() - 1;
294f6bcb 384 }
b5808881 385 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
294f6bcb 386 {
b5808881
SN
387 topRow = 0;
388 bottomRow = m_grid->GetNumberRows() - 1;
294f6bcb 389 }
5c8fc7c1
SN
390 if ( topRow > bottomRow )
391 {
392 int temp = topRow;
393 topRow = bottomRow;
394 bottomRow = temp;
395 }
396
397 if ( leftCol > rightCol )
398 {
399 int temp = leftCol;
400 leftCol = rightCol;
401 rightCol = temp;
402 }
294f6bcb
SN
403
404 // Handle single cell selection in SelectCell.
405 if ( topRow == bottomRow && leftCol == rightCol )
d95b0c2b
SN
406 SelectCell( topRow, leftCol, ControlDown, ShiftDown,
407 AltDown, MetaDown, sendEvent );
294f6bcb 408
f1567cdd 409 size_t count, n;
294f6bcb 410 // Remove single cells contained in newly selected block.
f1567cdd 411 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
412 {
413 count = m_cellSelection.GetCount();
f1567cdd 414 for ( n = 0; n < count; n++ )
b5808881
SN
415 {
416 wxGridCellCoords& coords = m_cellSelection[n];
417 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol,
418 coords.GetRow(), coords.GetCol() ) )
419 {
420 m_cellSelection.RemoveAt(n);
421 n--; count--;
422 }
423 }
294f6bcb
SN
424 }
425
426 // If a block containing the selection is already selected, return,
427 // if a block contained in the selection is found, remove it.
428
429 count = m_blockSelectionTopLeft.GetCount();
f1567cdd 430 for ( n = 0; n < count; n++ )
294f6bcb 431 {
b5808881
SN
432 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
433 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
434 switch ( BlockContain( coords1.GetRow(), coords1.GetCol(),
435 coords2.GetRow(), coords2.GetCol(),
436 topRow, leftCol, bottomRow, rightCol ) )
437 {
438 case 1:
439 return;
440 case -1:
441 m_blockSelectionTopLeft.RemoveAt(n);
442 m_blockSelectionBottomRight.RemoveAt(n);
443 n--; count--;
444 default:
445 ;
446 }
294f6bcb
SN
447 }
448
449 // If a row containing the selection is already selected, return,
450 // if a row contained in newly selected block is found, remove it.
b5808881 451 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 452 {
f1567cdd
SN
453 count = m_rowSelection.GetCount();
454 for ( n = 0; n < count; n++ )
b5808881
SN
455 {
456 switch ( BlockContain( m_rowSelection[n], 0,
457 m_rowSelection[n], m_grid->GetNumberCols()-1,
458 topRow, leftCol, bottomRow, rightCol ) )
459 {
460 case 1:
461 return;
462 case -1:
463 m_rowSelection.RemoveAt(n);
464 n--; count--;
465 default:
466 ;
467 }
468 }
469 }
470 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 471 {
f1567cdd
SN
472 count = m_colSelection.GetCount();
473 for ( n = 0; n < count; n++ )
b5808881
SN
474 {
475 switch ( BlockContain( 0, m_colSelection[n],
476 m_grid->GetNumberRows()-1, m_colSelection[n],
477 topRow, leftCol, bottomRow, rightCol ) )
478 {
479 case 1:
480 return;
481 case -1:
482 m_colSelection.RemoveAt(n);
483 n--; count--;
484 default:
485 ;
486 }
487 }
294f6bcb
SN
488 }
489 m_blockSelectionTopLeft.Add( wxGridCellCoords( topRow, leftCol ) );
490 m_blockSelectionBottomRight.Add( wxGridCellCoords( bottomRow, rightCol ) );
b5808881
SN
491
492 // Update View:
493 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( topRow, leftCol ),
494 wxGridCellCoords( bottomRow, rightCol ) );
495 if ( !m_grid->GetBatchCount() )
496 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 497
5c8fc7c1
SN
498 // Send Event, if not disabled.
499 if ( sendEvent )
500 {
d95b0c2b
SN
501 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
502 wxEVT_GRID_RANGE_SELECT,
503 m_grid,
504 wxGridCellCoords( topRow, leftCol ),
505 wxGridCellCoords( bottomRow, rightCol ),
506 TRUE,
507 ControlDown, ShiftDown,
508 AltDown, MetaDown );
509 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
5c8fc7c1 510 }
294f6bcb
SN
511}
512
d95b0c2b
SN
513void wxGridSelection::SelectCell( int row, int col,
514 bool ControlDown, bool ShiftDown,
515 bool AltDown, bool MetaDown,
516 bool sendEvent )
294f6bcb 517{
b5808881 518 if ( m_selectionMode == wxGrid::wxGridSelectRows )
043d16b2 519 {
294f6bcb 520 SelectBlock(row, 0, row, m_grid->GetNumberCols() - 1 );
043d16b2
SN
521 return;
522 }
b5808881 523 else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
043d16b2 524 {
294f6bcb 525 SelectBlock(0, col, m_grid->GetNumberRows() - 1, col );
043d16b2
SN
526 return;
527 }
294f6bcb
SN
528 else if ( IsInSelection ( row, col ) )
529 return;
530 m_cellSelection.Add( wxGridCellCoords( row, col ) );
b5808881 531
f1567cdd 532 // Update View:
b5808881
SN
533 wxRect r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, col ),
534 wxGridCellCoords( row, col ) );
535 if ( !m_grid->GetBatchCount() )
536 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
f1567cdd 537
5c8fc7c1 538 // Send event
d95b0c2b
SN
539 if (sendEvent)
540 {
541 wxGridEvent gridEvt( m_grid->GetId(),
542 wxEVT_GRID_SELECT_CELL,
543 m_grid,
544 row, col,
545 -1, -1,
546 TRUE,
547 ControlDown, ShiftDown,
548 AltDown, MetaDown);
549 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
550 }
294f6bcb
SN
551}
552
d95b0c2b
SN
553void wxGridSelection::ToggleCellSelection( int row, int col,
554 bool ControlDown, bool ShiftDown,
555 bool AltDown, bool MetaDown )
294f6bcb 556{
f1567cdd 557 // if the cell is not selected, select it
294f6bcb 558 if ( !IsInSelection ( row, col ) )
b5808881 559 {
d95b0c2b
SN
560 SelectCell( row, col, ControlDown, ShiftDown,
561 AltDown, MetaDown );
b5808881
SN
562 return;
563 }
294f6bcb 564
f1567cdd
SN
565 // otherwise deselect it. This can be simple or more or
566 // less difficult, depending on how the cell is selected.
567 size_t count, n;
568
569 // The simplest case: The cell is contained in m_cellSelection
570 // Then it can't be contained in rows/cols/block (since those
571 // would remove the cell from m_cellSelection on creation), so
572 // we just have to remove it from m_cellSelection.
294f6bcb 573
f1567cdd 574 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
575 {
576 count = m_cellSelection.GetCount();
f1567cdd 577 for ( n = 0; n < count; n++ )
b5808881
SN
578 {
579 wxGridCellCoords& coords = m_cellSelection[n];
580 if ( row == coords.GetRow() && col == coords.GetCol() )
581 {
582 wxRect r;
583 r = m_grid->BlockToDeviceRect( m_cellSelection[n],
584 m_cellSelection[n] );
585 m_cellSelection.RemoveAt(n);
586 n--; count--;
587 if ( !m_grid->GetBatchCount() )
588 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
5c8fc7c1
SN
589
590 // Send event
591 wxGridEvent gridEvt( m_grid->GetId(),
592 wxEVT_GRID_SELECT_CELL,
593 m_grid,
d95b0c2b
SN
594 row, col, -1, -1, FALSE,
595 ControlDown, ShiftDown,
596 AltDown, MetaDown );
5c8fc7c1 597 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
723d1b1d 598 return;
b5808881
SN
599 }
600 }
294f6bcb
SN
601 }
602
f1567cdd
SN
603 // The most difficult case: The cell is member of one or even several
604 // blocks. Split each such block in up to 4 new parts, that don't
605 // contain the cell to be selected, like this:
606 // |---------------------------|
607 // | |
608 // | part 1 |
609 // | |
610 // |---------------------------|
611 // | part 3 |x| part 4 |
612 // |---------------------------|
613 // | |
614 // | part 2 |
615 // | |
616 // |---------------------------|
617 // (The x marks the newly deselected cell).
618 // Note: in row selection mode, we only need part1 and part2;
619 // in column selection mode, we only need part 3 and part4,
620 // which are expanded to whole columns automatically!
621
294f6bcb 622 count = m_blockSelectionTopLeft.GetCount();
f1567cdd 623 for ( n = 0; n < count; n++ )
294f6bcb 624 {
b5808881
SN
625 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
626 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
627 int topRow = coords1.GetRow();
628 int leftCol = coords1.GetCol();
629 int bottomRow = coords2.GetRow();
630 int rightCol = coords2.GetCol();
631 if ( BlockContainsCell( topRow, leftCol, bottomRow, rightCol,
632 row, col ) )
633 {
634 // remove the block
635 m_blockSelectionTopLeft.RemoveAt(n);
636 m_blockSelectionBottomRight.RemoveAt(n);
637 n--; count--;
638 // add up to 4 smaller blocks and set update region
639 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
640 {
641 if ( topRow < row )
5c8fc7c1
SN
642 SelectBlock( topRow, leftCol,
643 row - 1, rightCol, 0, FALSE );
b5808881 644 if ( bottomRow > row )
5c8fc7c1
SN
645 SelectBlock( row + 1, leftCol,
646 bottomRow, rightCol, 0, FALSE );
b5808881
SN
647 }
648 if ( m_selectionMode != wxGrid::wxGridSelectRows )
649 {
650 if ( leftCol < col )
5c8fc7c1 651 SelectBlock( row, leftCol, row, col - 1, 0, FALSE );
b5808881 652 if ( rightCol > col )
5c8fc7c1 653 SelectBlock( row, col + 1, row, rightCol, 0, FALSE );
b5808881
SN
654 }
655 }
294f6bcb
SN
656 }
657
658 // remove a cell from a row, adding up to two new blocks
b5808881 659 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 660 {
f1567cdd
SN
661 count = m_rowSelection.GetCount();
662 for ( n = 0; n < count; n++ )
b5808881
SN
663 {
664 if ( m_rowSelection[n] == row )
665 {
666 m_rowSelection.RemoveAt(n);
667 n--; count--;
668 if (m_selectionMode == wxGrid::wxGridSelectCells)
669 {
670 if ( col > 0 )
5c8fc7c1 671 SelectBlock( row, 0, row, col - 1, 0, FALSE );
b5808881 672 if ( col < m_grid->GetNumberCols() - 1 )
5c8fc7c1
SN
673 SelectBlock( row, col + 1,
674 row, m_grid->GetNumberCols() - 1,
675 0, FALSE );
b5808881
SN
676 }
677 }
678 }
294f6bcb
SN
679 }
680
681 // remove a cell from a column, adding up to two new blocks
b5808881 682 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 683 {
f1567cdd
SN
684 count = m_colSelection.GetCount();
685 for ( n = 0; n < count; n++ )
b5808881
SN
686 {
687 if ( m_colSelection[n] == col )
688 {
689 m_colSelection.RemoveAt(n);
690 n--; count--;
691 if (m_selectionMode == wxGrid::wxGridSelectCells)
692 {
693 if ( row > 0 )
5c8fc7c1 694 SelectBlock( 0, col, row - 1, col, 0, FALSE );
b5808881 695 if ( row < m_grid->GetNumberRows() - 1 )
5c8fc7c1
SN
696 SelectBlock( row + 1, col,
697 m_grid->GetNumberRows() - 1, col,
698 0, FALSE );
b5808881
SN
699 }
700 }
701 }
294f6bcb 702 }
f1567cdd 703
5c8fc7c1
SN
704 // Refresh the screen and send the event; according to m_selectionMode,
705 // we need to either update only the cell, or the whole row/column.
294f6bcb
SN
706 wxRect r;
707 switch (m_selectionMode)
708 {
b5808881 709 case wxGrid::wxGridSelectCells:
5c8fc7c1
SN
710 {
711 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, col ),
712 wxGridCellCoords( row, col ) );
713 if ( !m_grid->GetBatchCount() )
714 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
715 wxGridEvent gridEvt( m_grid->GetId(),
716 wxEVT_GRID_SELECT_CELL,
717 m_grid,
d95b0c2b
SN
718 row, col, -1, -1, FALSE,
719 ControlDown, ShiftDown,
720 AltDown, MetaDown );
5c8fc7c1
SN
721 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
722 break;
723 }
b5808881 724 case wxGrid::wxGridSelectRows:
5c8fc7c1
SN
725 {
726 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
727 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
728 if ( !m_grid->GetBatchCount() )
729 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
730 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
731 wxEVT_GRID_RANGE_SELECT,
732 m_grid,
733 wxGridCellCoords( row, 0 ),
734 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
d95b0c2b
SN
735 FALSE,
736 ControlDown, ShiftDown,
737 AltDown, MetaDown );
5c8fc7c1
SN
738 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
739 break;
740 }
b5808881 741 case wxGrid::wxGridSelectColumns:
5c8fc7c1
SN
742 {
743 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
744 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
745 if ( !m_grid->GetBatchCount() )
746 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
747 wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
748 wxEVT_GRID_RANGE_SELECT,
749 m_grid,
750 wxGridCellCoords( 0, col ),
751 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
d95b0c2b
SN
752 FALSE,
753 ControlDown, ShiftDown,
754 AltDown, MetaDown );
5c8fc7c1
SN
755 m_grid->GetEventHandler()->ProcessEvent(gridEvt);
756 break;
757 }
294f6bcb 758 }
294f6bcb
SN
759}
760
761void wxGridSelection::ClearSelection()
762{
f1567cdd 763 // Should this send deselection events?
294f6bcb 764 size_t n;
f1567cdd
SN
765
766 // deselect all invidiual cells and update the screen
767 if ( m_selectionMode == wxGrid::wxGridSelectCells )
294f6bcb
SN
768 {
769
b5808881
SN
770 while( ( n = m_cellSelection.GetCount() ) > 0)
771 {
772 wxRect r;
773 n--;
774 r = m_grid->BlockToDeviceRect( m_cellSelection[n],
775 m_cellSelection[n] );
776 m_cellSelection.RemoveAt(n);
777 if ( !m_grid->GetBatchCount() )
778 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
779 }
294f6bcb 780 }
f1567cdd
SN
781
782 // deselect all blocks and update the screen
294f6bcb
SN
783 while( ( n = m_blockSelectionTopLeft.GetCount() ) > 0)
784 {
785 wxRect r;
b5808881
SN
786 n--;
787 r = m_grid->BlockToDeviceRect( m_blockSelectionTopLeft[n],
788 m_blockSelectionBottomRight[n] );
789 m_blockSelectionTopLeft.RemoveAt(n);
790 m_blockSelectionBottomRight.RemoveAt(n);
791 if ( !m_grid->GetBatchCount() )
792 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
793 }
f1567cdd
SN
794
795 // deselect all rows and update the screen
b5808881 796 if ( m_selectionMode != wxGrid::wxGridSelectColumns )
294f6bcb 797 {
b5808881
SN
798 while( ( n = m_rowSelection.GetCount() ) > 0)
799 {
800 n--;
801 int & row = m_rowSelection[n];
802 wxRect r;
803 r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
804 wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
805 m_rowSelection.RemoveAt(n);
806 if ( !m_grid->GetBatchCount() )
807 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
808 }
809 }
f1567cdd
SN
810
811 // deselect all columns and update the screen
b5808881 812 if ( m_selectionMode != wxGrid::wxGridSelectRows )
294f6bcb 813 {
b5808881
SN
814 while( ( n = m_colSelection.GetCount() ) > 0)
815 {
816 n--;
817 int & col = m_colSelection[n];
818 wxRect r;
819 r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
820 wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
821 m_colSelection.RemoveAt(n);
822 if ( !m_grid->GetBatchCount() )
823 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
824 }
294f6bcb
SN
825 }
826}
827
828
829void wxGridSelection::UpdateRows( size_t pos, int numRows )
830{
831 size_t count = m_cellSelection.GetCount();
b14159f7
JS
832 size_t n;
833 for ( n = 0; n < count; n++ )
294f6bcb
SN
834 {
835 wxGridCellCoords& coords = m_cellSelection[n];
836 wxCoord row = coords.GetRow();
837 if ((size_t)row >= pos)
838 {
839 if (numRows > 0)
840 {
841 // If rows inserted, increase row counter where necessary
842 coords.SetRow(row + numRows);
843 }
844 else if (numRows < 0)
845 {
846 // If rows deleted ...
847 if ((size_t)row >= pos - numRows)
848 {
849 // ...either decrement row counter (if row still exists)...
850 coords.SetRow(row + numRows);
851 }
852 else
853 {
854 // ...or remove the attribute
855 m_cellSelection.RemoveAt(n);
856 n--; count--;
857 }
858 }
859 }
860 }
861
862 count = m_blockSelectionTopLeft.GetCount();
b14159f7 863 for ( n = 0; n < count; n++ )
294f6bcb
SN
864 {
865 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
866 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
867 wxCoord row1 = coords1.GetRow();
868 wxCoord row2 = coords2.GetRow();
869 if ((size_t)row2 >= pos)
870 {
871 if (numRows > 0)
872 {
873 // If rows inserted, increase row counter where necessary
874 coords2.SetRow(row2 + numRows);
b5808881
SN
875 if ( (size_t)row1 >= pos )
876 coords1.SetRow(row1 + numRows);
294f6bcb
SN
877 }
878 else if (numRows < 0)
879 {
880 // If rows deleted ...
881 if ((size_t)row2 >= pos - numRows)
882 {
883 // ...either decrement row counter (if row still exists)...
884 coords2.SetRow(row2 + numRows);
b5808881
SN
885 if ( (size_t) row1 >= pos)
886 coords1.SetRow( wxMax(row1 + numRows, (int) pos) );
887
294f6bcb
SN
888 }
889 else
890 {
b5808881
SN
891 if ( (size_t) row1 >= pos)
892 {
893 // ...or remove the attribute
894 m_blockSelectionTopLeft.RemoveAt(n);
895 m_blockSelectionBottomRight.RemoveAt(n);
896 n--; count--;
897 }
898 else
899 coords2.SetRow(pos);
294f6bcb
SN
900 }
901 }
902 }
903 }
904
905 count = m_rowSelection.GetCount();
b14159f7 906 for ( n = 0; n < count; n++ )
294f6bcb
SN
907 {
908 int & rowOrCol = m_rowSelection[n];
909 if ( (size_t)rowOrCol >= pos )
910 {
911 if ( numRows > 0 )
912 {
913 // If rows inserted, include row counter where necessary
914 rowOrCol += numRows;
915 }
916 else if ( numRows < 0)
917 {
918 // If rows deleted, either decrement row counter (if row still exists)
919 if ((size_t)rowOrCol >= pos - numRows)
920 rowOrCol += numRows;
921 else
922 {
923 m_rowSelection.RemoveAt(n);
924 n--; count--;
925 }
926 }
927 }
928 }
929}
930
931void wxGridSelection::UpdateCols( size_t pos, int numCols )
932{
933 size_t count = m_cellSelection.GetCount();
b14159f7
JS
934 size_t n;
935 for ( n = 0; n < count; n++ )
294f6bcb
SN
936 {
937 wxGridCellCoords& coords = m_cellSelection[n];
938 wxCoord col = coords.GetCol();
939 if ((size_t)col >= pos)
940 {
941 if (numCols > 0)
942 {
943 // If rows inserted, increase row counter where necessary
944 coords.SetCol(col + numCols);
945 }
946 else if (numCols < 0)
947 {
948 // If rows deleted ...
949 if ((size_t)col >= pos - numCols)
950 {
951 // ...either decrement row counter (if row still exists)...
952 coords.SetCol(col + numCols);
953 }
954 else
955 {
956 // ...or remove the attribute
957 m_cellSelection.RemoveAt(n);
958 n--; count--;
959 }
960 }
961 }
962 }
963
964 count = m_blockSelectionTopLeft.GetCount();
b14159f7 965 for ( n = 0; n < count; n++ )
294f6bcb
SN
966 {
967 wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
968 wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n];
969 wxCoord col1 = coords1.GetCol();
970 wxCoord col2 = coords2.GetCol();
971 if ((size_t)col2 >= pos)
972 {
973 if (numCols > 0)
974 {
975 // If rows inserted, increase row counter where necessary
976 coords2.SetCol(col2 + numCols);
b5808881
SN
977 if ( (size_t)col1 >= pos )
978 coords1.SetCol(col1 + numCols);
294f6bcb
SN
979 }
980 else if (numCols < 0)
981 {
982 // If cols deleted ...
983 if ((size_t)col2 >= pos - numCols)
984 {
985 // ...either decrement col counter (if col still exists)...
986 coords2.SetCol(col2 + numCols);
b5808881
SN
987 if ( (size_t) col1 >= pos)
988 coords1.SetCol( wxMax(col1 + numCols, (int) pos) );
989
294f6bcb
SN
990 }
991 else
992 {
b5808881
SN
993 if ( (size_t) col1 >= pos)
994 {
995 // ...or remove the attribute
996 m_blockSelectionTopLeft.RemoveAt(n);
997 m_blockSelectionBottomRight.RemoveAt(n);
998 n--; count--;
999 }
1000 else
1001 coords2.SetCol(pos);
294f6bcb
SN
1002 }
1003 }
1004 }
1005 }
1006
1007 count = m_colSelection.GetCount();
b14159f7 1008 for ( n = 0; n < count; n++ )
294f6bcb
SN
1009 {
1010 int & rowOrCol = m_colSelection[n];
1011 if ( (size_t)rowOrCol >= pos )
1012 {
1013 if ( numCols > 0 )
1014 {
1015 // If cols inserted, include col counter where necessary
1016 rowOrCol += numCols;
1017 }
1018 else if ( numCols < 0)
1019 {
1020 // If cols deleted, either decrement col counter (if col still exists)
1021 if ((size_t)rowOrCol >= pos - numCols)
1022 rowOrCol += numCols;
1023 else
1024 {
1025 m_colSelection.RemoveAt(n);
1026 n--; count--;
1027 }
1028 }
1029 }
1030 }
1031}
1032
1033int wxGridSelection::BlockContain( int topRow1, int leftCol1,
b5808881
SN
1034 int bottomRow1, int rightCol1,
1035 int topRow2, int leftCol2,
1036 int bottomRow2, int rightCol2 )
294f6bcb
SN
1037// returns 1, if Block1 contains Block2,
1038// -1, if Block2 contains Block1,
1039// 0, otherwise
1040{
1041 if ( topRow1 <= topRow2 && bottomRow2 <= bottomRow1 &&
b5808881 1042 leftCol1 <= leftCol2 && rightCol2 <= rightCol1 )
294f6bcb
SN
1043 return 1;
1044 else if ( topRow2 <= topRow1 && bottomRow1 <= bottomRow2 &&
b5808881 1045 leftCol2 <= leftCol1 && rightCol1 <= rightCol2 )
294f6bcb
SN
1046 return -1;
1047 return 0;
1048}
f1567cdd
SN
1049
1050#endif