Fix Shift-click/arrow behaviour for column/row selection
Extend the current block to the entire line when the corresponding header is Shift-clicked and, importantly, keep the full-line selection when using Shift-arrows later to make the selection behave in the expected way.
This commit is contained in:
@@ -67,17 +67,19 @@ public:
|
|||||||
void UpdateRows( size_t pos, int numRows );
|
void UpdateRows( size_t pos, int numRows );
|
||||||
void UpdateCols( size_t pos, int numCols );
|
void UpdateCols( size_t pos, int numCols );
|
||||||
|
|
||||||
// Extend (or shrink) the current selection block or create a new one.
|
// Extend (or shrink) the current selection block to the one specified by
|
||||||
// blockStart and blockEnd specifies the opposite corners of the currently
|
// the start and end coordinates of its opposite corners (which don't have
|
||||||
// edited selection block. In almost all cases blockStart equals to
|
// to be in top/bottom left/right order).
|
||||||
// wxGrid::m_currentCellCoords (the exception is when we scrolled out from
|
//
|
||||||
|
// 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
|
// 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
|
// a row: in this case the lowest visible row/column will be set as
|
||||||
// current, not the first one).
|
// current, not the first one).
|
||||||
//
|
//
|
||||||
// Both components of both blockStart and blockEnd must be valid.
|
// 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,
|
bool ExtendOrCreateCurrentBlock(const wxGridCellCoords& blockStart,
|
||||||
const wxGridCellCoords& blockEnd,
|
const wxGridCellCoords& blockEnd,
|
||||||
const wxKeyboardState& kbd);
|
const wxKeyboardState& kbd);
|
||||||
|
@@ -498,8 +498,6 @@ bool wxGridSelection::ExtendOrCreateCurrentBlock(const wxGridCellCoords& blockSt
|
|||||||
const wxGridBlockCoords& block = *m_selection.rbegin();
|
const wxGridBlockCoords& block = *m_selection.rbegin();
|
||||||
wxGridBlockCoords newBlock = block;
|
wxGridBlockCoords newBlock = block;
|
||||||
|
|
||||||
bool editBlock = false;
|
|
||||||
|
|
||||||
// If the new block starts at the same top row as the current one, the
|
// 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
|
// end block coordinates must correspond to the new bottom row -- and
|
||||||
// vice versa, if the new block starts at the bottom, its other end
|
// 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() )
|
if ( blockStart.GetRow() == block.GetTopRow() )
|
||||||
{
|
{
|
||||||
newBlock.SetBottomRow(blockEnd.GetRow());
|
newBlock.SetBottomRow(blockEnd.GetRow());
|
||||||
editBlock = true;
|
|
||||||
}
|
}
|
||||||
else if ( blockStart.GetRow() == block.GetBottomRow() )
|
else if ( blockStart.GetRow() == block.GetBottomRow() )
|
||||||
{
|
{
|
||||||
newBlock.SetTopRow(blockEnd.GetRow());
|
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() )
|
if ( blockStart.GetCol() == block.GetLeftCol() )
|
||||||
{
|
{
|
||||||
newBlock.SetRightCol(blockEnd.GetCol());
|
newBlock.SetRightCol(blockEnd.GetCol());
|
||||||
editBlock = true;
|
|
||||||
}
|
}
|
||||||
else if ( blockStart.GetCol() == block.GetRightCol() )
|
else if ( blockStart.GetCol() == block.GetRightCol() )
|
||||||
{
|
{
|
||||||
newBlock.SetLeftCol(blockEnd.GetCol());
|
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();
|
newBlock = newBlock.Canonicalize();
|
||||||
|
|
||||||
if ( editBlock )
|
if ( newBlock == block )
|
||||||
{
|
return false;
|
||||||
if ( newBlock == block )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Update View.
|
// Update View.
|
||||||
if ( !m_grid->GetBatchCount() )
|
if ( !m_grid->GetBatchCount() )
|
||||||
|
{
|
||||||
|
wxGridBlockDiffResult refreshBlocks = block.SymDifference(newBlock);
|
||||||
|
for ( int i = 0; i < 4; ++i )
|
||||||
{
|
{
|
||||||
wxGridBlockDiffResult refreshBlocks = block.SymDifference(newBlock);
|
const wxGridBlockCoords& refreshBlock = refreshBlocks.m_parts[i];
|
||||||
for ( int i = 0; i < 4; ++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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user