diff --git a/include/wx/generic/gridsel.h b/include/wx/generic/gridsel.h index 1a64387c84..aeed559ecc 100644 --- a/include/wx/generic/gridsel.h +++ b/include/wx/generic/gridsel.h @@ -67,17 +67,19 @@ public: void UpdateRows( size_t pos, int numRows ); void UpdateCols( size_t pos, int numCols ); - // Extend (or shrink) the current selection block or create a new one. - // blockStart and blockEnd specifies the opposite corners of the currently - // edited selection block. In almost all cases blockStart equals to - // wxGrid::m_currentCellCoords (the exception is when we scrolled out from + // Extend (or shrink) the current selection block to the one specified by + // the start and end coordinates of its opposite corners (which don't have + // to be in top/bottom left/right order). + // + // Note that blockStart is equal to wxGrid::m_currentCellCoords almost + // always, but not always (the exception is when we scrolled out from // the top of the grid and select a column or scrolled right and select // a row: in this case the lowest visible row/column will be set as // current, not the first one). // // Both components of both blockStart and blockEnd must be valid. // - // Return true if the current block was actually changed or created. + // Return true if the current block was actually changed. bool ExtendOrCreateCurrentBlock(const wxGridCellCoords& blockStart, const wxGridCellCoords& blockEnd, const wxKeyboardState& kbd); diff --git a/src/generic/gridsel.cpp b/src/generic/gridsel.cpp index 963717aac0..6c67f263a9 100644 --- a/src/generic/gridsel.cpp +++ b/src/generic/gridsel.cpp @@ -498,8 +498,6 @@ bool wxGridSelection::ExtendOrCreateCurrentBlock(const wxGridCellCoords& blockSt const wxGridBlockCoords& block = *m_selection.rbegin(); wxGridBlockCoords newBlock = block; - bool editBlock = false; - // If the new block starts at the same top row as the current one, the // end block coordinates must correspond to the new bottom row -- and // vice versa, if the new block starts at the bottom, its other end @@ -507,63 +505,84 @@ bool wxGridSelection::ExtendOrCreateCurrentBlock(const wxGridCellCoords& blockSt if ( blockStart.GetRow() == block.GetTopRow() ) { newBlock.SetBottomRow(blockEnd.GetRow()); - editBlock = true; } else if ( blockStart.GetRow() == block.GetBottomRow() ) { newBlock.SetTopRow(blockEnd.GetRow()); - editBlock = true; + } + else // current and new block don't have common row boundary + { + // This can happen when mixing entire column and cell selection, e.g. + // by Shift-clicking on the column header. In this case, the right + // thing to do is to just expand the current block to the new one + // boundaries, extending the selection to the entire column height when + // a column is selected. However notice that we should not shrink the + // current block here, in order to allow Shift-Left/Right (which don't + // know anything about the column selection and so just use single row + // blocks) to keep the full column selection. + int top = blockStart.GetRow(), + bottom = blockEnd.GetRow(); + if ( top > bottom ) + wxSwap(top, bottom); + + if ( top < newBlock.GetTopRow() ) + newBlock.SetTopRow(top); + if ( bottom > newBlock.GetBottomRow() ) + newBlock.SetBottomRow(bottom); } + // Same as above but mirrored for columns. if ( blockStart.GetCol() == block.GetLeftCol() ) { newBlock.SetRightCol(blockEnd.GetCol()); - editBlock = true; } else if ( blockStart.GetCol() == block.GetRightCol() ) { newBlock.SetLeftCol(blockEnd.GetCol()); - editBlock = true; + } + else + { + int left = blockStart.GetCol(), + right = blockEnd.GetCol(); + if ( left > right ) + wxSwap(left, right); + + if ( left < newBlock.GetLeftCol() ) + newBlock.SetLeftCol(left); + if ( right > newBlock.GetRightCol() ) + newBlock.SetRightCol(right); } newBlock = newBlock.Canonicalize(); - if ( editBlock ) - { - if ( newBlock == block ) - return false; + if ( newBlock == block ) + return false; - // Update View. - if ( !m_grid->GetBatchCount() ) + // Update View. + if ( !m_grid->GetBatchCount() ) + { + wxGridBlockDiffResult refreshBlocks = block.SymDifference(newBlock); + for ( int i = 0; i < 4; ++i ) { - wxGridBlockDiffResult refreshBlocks = block.SymDifference(newBlock); - for ( int i = 0; i < 4; ++i ) - { - const wxGridBlockCoords& refreshBlock = refreshBlocks.m_parts[i]; - m_grid->RefreshBlock(refreshBlock.GetTopLeft(), - refreshBlock.GetBottomRight()); - } + const wxGridBlockCoords& refreshBlock = refreshBlocks.m_parts[i]; + m_grid->RefreshBlock(refreshBlock.GetTopLeft(), + refreshBlock.GetBottomRight()); } - - // Update the current block in place. - *m_selection.rbegin() = newBlock; - - // Send Event. - wxGridRangeSelectEvent gridEvt(m_grid->GetId(), - wxEVT_GRID_RANGE_SELECT, - m_grid, - newBlock.GetTopLeft(), - newBlock.GetBottomRight(), - true, - kbd); - m_grid->GetEventHandler()->ProcessEvent(gridEvt); - } - else - { - // Select the new one. - SelectBlock(newBlock.GetTopLeft(), newBlock.GetBottomRight(), kbd); } + // Update the current block in place. + *m_selection.rbegin() = newBlock; + + // Send Event. + wxGridRangeSelectEvent gridEvt(m_grid->GetId(), + wxEVT_GRID_RANGE_SELECT, + m_grid, + newBlock.GetTopLeft(), + newBlock.GetBottomRight(), + true, + kbd); + m_grid->GetEventHandler()->ProcessEvent(gridEvt); + return true; }