]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/gridsel.cpp
fix crash when the user code refuses to validate the new text when editing the item...
[wxWidgets.git] / src / generic / gridsel.cpp
index a4da89168510846132d567d3e7b9ba5ac9cea4f3..2781694fb5bd6d54549a6d7a7aa7017969e0ab72 100644 (file)
@@ -69,7 +69,7 @@ bool wxGridSelection::IsInSelection ( int row, int col )
         {
             wxGridCellCoords& coords = m_cellSelection[n];
             if ( row == coords.GetRow() && col == coords.GetCol() )
-                return true;
+                return TRUE;
         }
     }
 
@@ -83,7 +83,7 @@ bool wxGridSelection::IsInSelection ( int row, int col )
         if ( BlockContainsCell(coords1.GetRow(), coords1.GetCol(),
                                coords2.GetRow(), coords2.GetCol(),
                                row, col ) )
-            return true;
+            return TRUE;
     }
 
     // Now check whether the given cell is
@@ -95,7 +95,7 @@ bool wxGridSelection::IsInSelection ( int row, int col )
         for ( size_t n = 0; n < count; n++ )
         {
             if ( row == m_rowSelection[n] )
-              return true;
+              return TRUE;
         }
     }
 
@@ -108,10 +108,10 @@ bool wxGridSelection::IsInSelection ( int row, int col )
         for ( size_t n = 0; n < count; n++ )
         {
             if ( col == m_colSelection[n] )
-              return true;
+              return TRUE;
         }
     }
-    return false;
+    return FALSE;
 }
 
 // Change the selection mode
@@ -147,9 +147,10 @@ void wxGridSelection::SetSelectionMode(wxGrid::wxGridSelectionModes selmode)
             else // selmode == wxGridSelectColumns)
                 SelectCol( col );
         }
-        while( ( n = m_blockSelectionTopLeft.GetCount() ) > 0)
+
+        for (n = 0; n < m_blockSelectionTopLeft.GetCount(); n++)
+        // Note that m_blockSelectionTopLeft's size may be changing!
         {
-            n--;
             wxGridCellCoords& coords = m_blockSelectionTopLeft[n];
             int topRow = coords.GetRow();
             int leftCol = coords.GetCol();
@@ -163,7 +164,8 @@ void wxGridSelection::SetSelectionMode(wxGrid::wxGridSelectionModes selmode)
                     m_blockSelectionTopLeft.RemoveAt(n);
                     m_blockSelectionBottomRight.RemoveAt(n);
                     SelectBlock( topRow, 0,
-                                 bottomRow, m_grid->GetNumberCols() - 1 );
+                                 bottomRow, m_grid->GetNumberCols() - 1,
+                                 0, FALSE );
                 }
             }
             else // selmode == wxGridSelectColumns)
@@ -173,14 +175,18 @@ void wxGridSelection::SetSelectionMode(wxGrid::wxGridSelectionModes selmode)
                     m_blockSelectionTopLeft.RemoveAt(n);
                     m_blockSelectionBottomRight.RemoveAt(n);
                     SelectBlock( 0, leftCol,
-                                 m_grid->GetNumberRows() - 1, rightCol );
+                                 m_grid->GetNumberRows() - 1, rightCol,
+                                 0, FALSE );
                 }
             }
         }
+        m_selectionMode = selmode;
     }
 }
 
-void wxGridSelection::SelectRow( int row, bool addToSelected )
+void wxGridSelection::SelectRow( int row,
+                                 bool ControlDown,  bool ShiftDown,
+                                 bool AltDown, bool MetaDown )
 {
     if ( m_selectionMode == wxGrid::wxGridSelectColumns )
         return;
@@ -204,7 +210,7 @@ void wxGridSelection::SelectRow( int row, bool addToSelected )
 
     // Simplify list of selected blocks (if possible)
     count = m_blockSelectionTopLeft.GetCount();
-    bool done = false;
+    bool done = FALSE;
     for ( n = 0; n < count; n++ )
     {
         wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
@@ -227,12 +233,12 @@ void wxGridSelection::SelectRow( int row, bool addToSelected )
             else if ( coords1.GetRow() == row + 1)
             {
                 coords1.SetRow(row);
-                done = true;
+                done = TRUE;
             }
             else if ( coords2.GetRow() == row - 1)
             {
                 coords2.SetRow(row);
-                done = true;
+                done = TRUE;
             }           
         }
     }
@@ -258,11 +264,22 @@ void wxGridSelection::SelectRow( int row, bool addToSelected )
     if ( !m_grid->GetBatchCount() )
         ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
 
-    // Possibly send event here? This would imply that no event is sent,
-    // if the row already was part of the selection.
+    // Send Event
+    wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                    wxEVT_GRID_RANGE_SELECT,
+                                    m_grid,
+                                    wxGridCellCoords( row, 0 ),
+                                    wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
+                                    TRUE,
+                                    ControlDown,  ShiftDown,
+                                    AltDown, MetaDown );
+
+    m_grid->GetEventHandler()->ProcessEvent(gridEvt);
 }
 
-void wxGridSelection::SelectCol( int col, bool addToSelected )
+void wxGridSelection::SelectCol( int col,
+                                 bool ControlDown,  bool ShiftDown,
+                                 bool AltDown, bool MetaDown )
 {
     if ( m_selectionMode == wxGrid::wxGridSelectRows )
         return;
@@ -286,7 +303,7 @@ void wxGridSelection::SelectCol( int col, bool addToSelected )
 
     // Simplify list of selected blocks (if possible)
     count = m_blockSelectionTopLeft.GetCount();
-    bool done = false;
+    bool done = FALSE;
     for ( n = 0; n < count; n++ )
     {
         wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n];
@@ -309,12 +326,12 @@ void wxGridSelection::SelectCol( int col, bool addToSelected )
             else if ( coords1.GetCol() == col + 1)
             {
                 coords1.SetCol(col);
-                done = true;
+                done = TRUE;
             }
             else if ( coords2.GetCol() == col - 1)
             {
                 coords2.SetCol(col);
-                done = true;
+                done = TRUE;
             }           
         }
     }
@@ -340,13 +357,26 @@ void wxGridSelection::SelectCol( int col, bool addToSelected )
     if ( !m_grid->GetBatchCount() )
         ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
 
-    // Possibly send event here? This would imply that no event is sent,
-    // if the row already was part of the selection.
+    // Send Event
+    wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                    wxEVT_GRID_RANGE_SELECT,
+                                    m_grid,
+                                    wxGridCellCoords( 0, col ),
+                                    wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
+                                    TRUE,
+                                    ControlDown,  ShiftDown,
+                                    AltDown, MetaDown );
+
+    m_grid->GetEventHandler()->ProcessEvent(gridEvt);
 }
 
-void wxGridSelection::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
+void wxGridSelection::SelectBlock( int topRow, int leftCol,
+                                   int bottomRow, int rightCol,
+                                   bool ControlDown, bool ShiftDown,
+                                   bool AltDown, bool MetaDown, 
+                                   bool sendEvent )
 {
-    // Fix the coordinates of the block if potentially needed
+    // Fix the coordinates of the block if needed.
     if ( m_selectionMode == wxGrid::wxGridSelectRows )
     {
         leftCol = 0;
@@ -357,10 +387,28 @@ void wxGridSelection::SelectBlock( int topRow, int leftCol, int bottomRow, int r
         topRow = 0;
         bottomRow = m_grid->GetNumberRows() - 1;
     }
+    if ( topRow > bottomRow )
+    {
+        int temp = topRow;
+        topRow = bottomRow;
+        bottomRow = temp;
+    }
+
+    if ( leftCol > rightCol )
+    {
+        int temp = leftCol;
+        leftCol = rightCol;
+        rightCol = temp;
+    }
 
     // Handle single cell selection in SelectCell.
-    if ( topRow == bottomRow && leftCol == rightCol )
-        SelectCell( topRow, leftCol );
+    // (MB: added check for selection mode here to prevent
+    //  crashes if, for example, we are select rows and the
+    //  grid only has 1 col)
+    if ( m_selectionMode == wxGrid::wxGridSelectCells &&
+         topRow == bottomRow && leftCol == rightCol )
+        SelectCell( topRow, leftCol, ControlDown,  ShiftDown,
+                    AltDown, MetaDown, sendEvent );
 
     size_t count, n;
     // Remove single cells contained in newly selected block.
@@ -451,15 +499,38 @@ void wxGridSelection::SelectBlock( int topRow, int leftCol, int bottomRow, int r
     if ( !m_grid->GetBatchCount() )
         ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
 
-    // Possibly send event?
+    // Send Event, if not disabled.
+    if ( sendEvent )
+    {
+        wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                        wxEVT_GRID_RANGE_SELECT,
+                                        m_grid,
+                                        wxGridCellCoords( topRow, leftCol ),
+                                        wxGridCellCoords( bottomRow, rightCol ),
+                                        TRUE,
+                                        ControlDown, ShiftDown,
+                                        AltDown, MetaDown );
+        m_grid->GetEventHandler()->ProcessEvent(gridEvt);
+    }
 }
 
-void wxGridSelection::SelectCell( int row, int col)
+void wxGridSelection::SelectCell( int row, int col,
+                                  bool ControlDown, bool ShiftDown,
+                                  bool AltDown, bool MetaDown,
+                                  bool sendEvent )
 {
     if ( m_selectionMode == wxGrid::wxGridSelectRows )
-        SelectBlock(row, 0, row, m_grid->GetNumberCols() - 1 );
+    {
+        SelectBlock(row, 0, row, m_grid->GetNumberCols() - 1,
+                    ControlDown, ShiftDown, AltDown, MetaDown);
+        return;
+    }
     else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
-        SelectBlock(0, col, m_grid->GetNumberRows() - 1, col );
+    {
+        SelectBlock(0, col, m_grid->GetNumberRows() - 1, col,
+                    ControlDown, ShiftDown, AltDown, MetaDown);
+        return;
+    }
     else if ( IsInSelection ( row, col ) )
         return;
     m_cellSelection.Add( wxGridCellCoords( row, col ) );
@@ -470,15 +541,30 @@ void wxGridSelection::SelectCell( int row, int col)
     if ( !m_grid->GetBatchCount() )
         ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
 
-    // Possibly send event?
+    // Send event
+    if (sendEvent)
+    {
+        wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                        wxEVT_GRID_RANGE_SELECT,
+                                        m_grid,
+                                        wxGridCellCoords( row, col ),
+                                        wxGridCellCoords( row, col ),
+                                        TRUE, 
+                                        ControlDown, ShiftDown,
+                                        AltDown, MetaDown);
+        m_grid->GetEventHandler()->ProcessEvent(gridEvt);
+    }
 }
 
-void wxGridSelection::ToggleCellSelection( int row, int col)
+void wxGridSelection::ToggleCellSelection( int row, int col,
+                                           bool ControlDown, bool ShiftDown,
+                                           bool AltDown, bool MetaDown )
 {
     // if the cell is not selected, select it
     if ( !IsInSelection ( row, col ) )
     {
-        SelectCell( row, col );
+        SelectCell( row, col, ControlDown, ShiftDown,
+                    AltDown, MetaDown );
         return;
     }
 
@@ -506,6 +592,17 @@ void wxGridSelection::ToggleCellSelection( int row, int col)
                 n--; count--;
                 if ( !m_grid->GetBatchCount() )
                     ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
+
+                // Send event
+                wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                                wxEVT_GRID_RANGE_SELECT,
+                                                m_grid,
+                                                wxGridCellCoords( row, col ),
+                                                wxGridCellCoords( row, col ),
+                                                FALSE,
+                                                ControlDown, ShiftDown,
+                                                AltDown, MetaDown );
+                m_grid->GetEventHandler()->ProcessEvent(gridEvt);
                 return;
             }
         }
@@ -550,16 +647,18 @@ void wxGridSelection::ToggleCellSelection( int row, int col)
             if ( m_selectionMode != wxGrid::wxGridSelectColumns )
             {
                 if ( topRow < row )
-                    SelectBlock( topRow, leftCol, row - 1, rightCol );
+                    SelectBlock( topRow, leftCol,
+                                 row - 1, rightCol, 0, FALSE );
                 if ( bottomRow > row )
-                    SelectBlock( row + 1, leftCol, bottomRow, rightCol );
+                    SelectBlock( row + 1, leftCol,
+                                 bottomRow, rightCol, 0, FALSE );
             }
             if ( m_selectionMode != wxGrid::wxGridSelectRows )
             {
                 if ( leftCol < col )
-                    SelectBlock( row, leftCol, row, col - 1 );
+                    SelectBlock( row, leftCol, row, col - 1, 0, FALSE );
                 if ( rightCol > col )
-                    SelectBlock( row, col + 1, row, rightCol );
+                    SelectBlock( row, col + 1, row, rightCol, 0, FALSE );
             }
         }
     }
@@ -577,9 +676,11 @@ void wxGridSelection::ToggleCellSelection( int row, int col)
                 if (m_selectionMode == wxGrid::wxGridSelectCells)
                 {
                     if ( col > 0 )
-                        SelectBlock( row, 0, row, col - 1 );
+                        SelectBlock( row, 0, row, col - 1, 0, FALSE );
                     if ( col < m_grid->GetNumberCols() - 1 )
-                        SelectBlock( row, col + 1, row, m_grid->GetNumberCols() - 1 );
+                        SelectBlock( row, col + 1,
+                                     row, m_grid->GetNumberCols() - 1,
+                                     0, FALSE );
                 }
             }
         }
@@ -598,39 +699,77 @@ void wxGridSelection::ToggleCellSelection( int row, int col)
                 if (m_selectionMode == wxGrid::wxGridSelectCells)
                 {
                     if ( row > 0 )
-                        SelectBlock( 0, col, row - 1, col );
+                        SelectBlock( 0, col, row - 1, col, 0, FALSE );
                     if ( row < m_grid->GetNumberRows() - 1 )
-                        SelectBlock( row + 1, col, m_grid->GetNumberRows() - 1, col );
+                        SelectBlock( row + 1, col,
+                                     m_grid->GetNumberRows() - 1, col,
+                                     0, FALSE );
                 }
             }
         }
     }
 
-    // Refresh the screen; according to m_selectionMode, we
-    // need to either update only the cell, or the whole row/column.
+    // Refresh the screen and send the event; according to m_selectionMode,
+    // we need to either update only the cell, or the whole row/column.
     wxRect r;
     switch (m_selectionMode)
     {
       case wxGrid::wxGridSelectCells:
-        r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, col ),
-                                       wxGridCellCoords( row, col ) );
-        break;
+      {
+          r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, col ),
+                                         wxGridCellCoords( row, col ) );
+          if ( !m_grid->GetBatchCount() )
+              ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
+          wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                          wxEVT_GRID_RANGE_SELECT,
+                                          m_grid,
+                                          wxGridCellCoords( row, col ),
+                                          wxGridCellCoords( row, col ),
+                                          FALSE,
+                                          ControlDown, ShiftDown,
+                                          AltDown, MetaDown );
+          m_grid->GetEventHandler()->ProcessEvent(gridEvt);
+          break;
+      }
       case wxGrid::wxGridSelectRows:
-        r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
-                                       wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
-        break;
+      {
+          r = m_grid->BlockToDeviceRect( wxGridCellCoords( row, 0 ),
+                                         wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ) );
+          if ( !m_grid->GetBatchCount() )
+              ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
+          wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                          wxEVT_GRID_RANGE_SELECT,
+                                          m_grid,
+                                          wxGridCellCoords( row, 0 ),
+                                          wxGridCellCoords( row, m_grid->GetNumberCols() - 1 ),
+                                          FALSE,
+                                          ControlDown, ShiftDown,
+                                          AltDown, MetaDown );
+          m_grid->GetEventHandler()->ProcessEvent(gridEvt);
+          break;
+      }
       case wxGrid::wxGridSelectColumns:
-        r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
-                                       wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
-        break;
+      {
+          r = m_grid->BlockToDeviceRect( wxGridCellCoords( 0, col ),
+                                         wxGridCellCoords( m_grid->GetNumberRows() - 1, col ) );
+          if ( !m_grid->GetBatchCount() )
+              ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
+          wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                          wxEVT_GRID_RANGE_SELECT,
+                                          m_grid,
+                                          wxGridCellCoords( 0, col ),
+                                          wxGridCellCoords( m_grid->GetNumberRows() - 1, col ),
+                                          FALSE,
+                                          ControlDown, ShiftDown,
+                                          AltDown, MetaDown );
+          m_grid->GetEventHandler()->ProcessEvent(gridEvt);
+          break;
+      }
     }
-    if ( !m_grid->GetBatchCount() )
-        ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );
 }
 
 void wxGridSelection::ClearSelection()
 {
-    // Should this send deselection events?
     size_t n;
 
     // deselect all invidiual cells and update the screen
@@ -693,6 +832,19 @@ void wxGridSelection::ClearSelection()
                 ((wxWindow *)m_grid->m_gridWin)->Refresh( FALSE, &r );   
         }
     }
+
+    // One deselection event, indicating deselection of _all_ cells.
+    // (No finer grained events for each of the smaller regions
+    //  deselected above!)
+    wxGridRangeSelectEvent gridEvt( m_grid->GetId(),
+                                    wxEVT_GRID_RANGE_SELECT,
+                                    m_grid,
+                                    wxGridCellCoords( 0, 0 ),
+                                    wxGridCellCoords( m_grid->GetNumberRows() - 1,
+                                                      m_grid->GetNumberCols() - 1 ),
+                                    FALSE );
+
+    m_grid->GetEventHandler()->ProcessEvent(gridEvt);
 }
 
 
@@ -796,6 +948,10 @@ void wxGridSelection::UpdateRows( size_t pos, int numRows )
             }
         }
     }
+    // No need to touch selected columns, unless we removed _all_
+    // rows, in this case, we remove all columns from the selection.
+    if ( !m_grid->GetNumberRows() )
+        m_colSelection.Clear();
 }
 
 void wxGridSelection::UpdateCols( size_t pos, int numCols )
@@ -898,6 +1054,11 @@ void wxGridSelection::UpdateCols( size_t pos, int numCols )
             }
         }
     }
+
+    // No need to touch selected rows, unless we removed _all_
+    // columns, in this case, we remove all rows from the selection.
+    if ( !m_grid->GetNumberCols() )
+        m_rowSelection.Clear();
 }
 
 int wxGridSelection::BlockContain( int topRow1, int leftCol1,