home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / generic / gridsel.cpp < prev    next >
C/C++ Source or Header  |  2002-09-21  |  40KB  |  1,086 lines

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