- Main change is the addition of wxGridSelectRowsOrColumns selection mode

(which is still probably buggy, wxGridSelection needs to be reviewed)
- Add XYToCell() overloads returning wxGridCellCoords (instead of modifying the
  argument passed by reference -- where did this come from?) and document them.
- Added GoToCell() which does make the new current cell visible unlike
  SetGridCursor() (which was documented as doing it, but wasn't)
- Changed SetCurrentCell() to only not change the cell if wxEVT_GRID_SELECT_CELL
  it generates is vetoed, not just processed as this seems to make more sense
- Split jumbo (~400 lines) ProcessGridCellMouseEvent() function into chunks
- Add many more comments to make reading this code seem less like puzzle
  solving for the next unfortunate soul to do it


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55746 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-09-19 23:33:04 +00:00
parent 0e0977894a
commit 8a3e536cd5
8 changed files with 717 additions and 502 deletions

View File

@@ -392,6 +392,7 @@ All (GUI):
- wxWindow::IsBeingDeleted() now returns true not only if the window itself is - wxWindow::IsBeingDeleted() now returns true not only if the window itself is
marked for destruction but also if any of its parent windows are. marked for destruction but also if any of its parent windows are.
- Improved drawing of the hint during column move in wxGrid. - Improved drawing of the hint during column move in wxGrid.
- Add wxGridSelectRowsOrColumns selection mode to wxGrid.
- Get/HasModifiers() of wxKeyEvent are now also available in wxMouseEvent. - Get/HasModifiers() of wxKeyEvent are now also available in wxMouseEvent.
wxGTK: wxGTK:

View File

@@ -320,7 +320,7 @@ public:
// Show or hide the edit control, use the specified attributes to set // Show or hide the edit control, use the specified attributes to set
// colours/fonts for it // colours/fonts for it
virtual void Show(bool show, wxGridCellAttr *attr = (wxGridCellAttr *)NULL); virtual void Show(bool show, wxGridCellAttr *attr = NULL);
// Draws the part of the cell not occupied by the control: the base class // Draws the part of the cell not occupied by the control: the base class
// version just fills it with background colour from the attribute // version just fills it with background colour from the attribute
@@ -1145,6 +1145,10 @@ public:
bool takeOwnership = false, bool takeOwnership = false,
wxGridSelectionModes selmode = wxGridSelectCells ); wxGridSelectionModes selmode = wxGridSelectCells );
bool ProcessTableMessage(wxGridTableMessage&);
wxGridTableBase *GetTable() const { return m_table; }
void SetSelectionMode(wxGridSelectionModes selmode); void SetSelectionMode(wxGridSelectionModes selmode);
wxGridSelectionModes GetSelectionMode() const; wxGridSelectionModes GetSelectionMode() const;
@@ -1163,20 +1167,6 @@ public:
wxGridCellCoordsArray CalcCellsExposed( const wxRegion& reg ) const; wxGridCellCoordsArray CalcCellsExposed( const wxRegion& reg ) const;
// ------ event handlers
//
void ProcessRowLabelMouseEvent( wxMouseEvent& event );
void ProcessColLabelMouseEvent( wxMouseEvent& event );
void ProcessCornerLabelMouseEvent( wxMouseEvent& event );
void ProcessGridCellMouseEvent( wxMouseEvent& event );
bool ProcessTableMessage( wxGridTableMessage& );
void DoEndDragResizeRow();
void DoEndDragResizeCol();
void DoEndDragMoveCol();
wxGridTableBase * GetTable() const { return m_table; }
void ClearGrid(); void ClearGrid();
bool InsertRows(int pos = 0, int numRows = 1, bool updateLabels = true) bool InsertRows(int pos = 0, int numRows = 1, bool updateLabels = true)
{ {
@@ -1261,8 +1251,7 @@ public:
int GetBatchCount() { return m_batchCount; } int GetBatchCount() { return m_batchCount; }
virtual void Refresh(bool eraseb = true, virtual void Refresh(bool eraseb = true, const wxRect* rect = NULL);
const wxRect* rect = (const wxRect *) NULL);
// Use this, rather than wxWindow::Refresh(), to force an // Use this, rather than wxWindow::Refresh(), to force an
// immediate repainting of the grid. Has no effect if you are // immediate repainting of the grid. Has no effect if you are
@@ -1297,7 +1286,12 @@ public:
// grid cells and labels so you will need to convert from device // grid cells and labels so you will need to convert from device
// coordinates for mouse events etc. // coordinates for mouse events etc.
// //
void XYToCell( int x, int y, wxGridCellCoords& ) const; wxGridCellCoords XYToCell(int x, int y) const;
void XYToCell(int x, int y, wxGridCellCoords& coords) const
{ coords = XYToCell(x, y); }
wxGridCellCoords XYToCell(const wxPoint& pos) const
{ return XYToCell(pos.x, pos.y); }
int YToRow( int y, bool clipToMinMax = false ) const; int YToRow( int y, bool clipToMinMax = false ) const;
int XToCol( int x, bool clipToMinMax = false ) const; int XToCol( int x, bool clipToMinMax = false ) const;
@@ -1324,8 +1318,20 @@ public:
// ------ grid cursor movement functions // ------ grid cursor movement functions
// //
void SetGridCursor( int row, int col ) void SetGridCursor(int row, int col) { SetCurrentCell(row, col); }
{ SetCurrentCell( wxGridCellCoords(row, col) ); } void SetGridCursor(const wxGridCellCoords& c) { SetCurrentCell(c); }
void GoToCell(int row, int col)
{
if ( SetCurrentCell(row, col) )
MakeCellVisible(row, col);
}
void GoToCell(const wxGridCellCoords& coords)
{
if ( SetCurrentCell(coords) )
MakeCellVisible(coords);
}
bool MoveCursorUp( bool expandSelection ); bool MoveCursorUp( bool expandSelection );
bool MoveCursorDown( bool expandSelection ); bool MoveCursorDown( bool expandSelection );
@@ -1867,10 +1873,22 @@ protected:
wxGridCellCoords m_currentCellCoords; wxGridCellCoords m_currentCellCoords;
wxGridCellCoords m_selectingTopLeft; // the corners of the block being currently selected or wxGridNoCellCoords
wxGridCellCoords m_selectingBottomRight; wxGridCellCoords m_selectedBlockTopLeft;
wxGridCellCoords m_selectingKeyboard; wxGridCellCoords m_selectedBlockBottomRight;
// when selecting blocks of cells (either from the keyboard using Shift
// with cursor keys, or by dragging the mouse), the selection is anchored
// at m_currentCellCoords which defines one of the corners of the rectangle
// being selected -- and this variable defines the other corner, i.e. it's
// either m_selectedBlockTopLeft or m_selectedBlockBottomRight depending on
// which of them is not m_currentCellCoords
//
// if no block selection is in process, it is set to wxGridNoCellCoords
wxGridCellCoords m_selectedBlockCorner;
wxGridSelection *m_selection; wxGridSelection *m_selection;
wxColour m_selectionBackground; wxColour m_selectionBackground;
wxColour m_selectionForeground; wxColour m_selectionForeground;
@@ -2007,12 +2025,22 @@ protected:
// for this to work, you should always use it and not set m_cursorMode // for this to work, you should always use it and not set m_cursorMode
// directly! // directly!
void ChangeCursorMode(CursorMode mode, void ChangeCursorMode(CursorMode mode,
wxWindow *win = (wxWindow *)NULL, wxWindow *win = NULL,
bool captureMouse = true); bool captureMouse = true);
wxWindow *m_winCapture; // the window which captured the mouse wxWindow *m_winCapture; // the window which captured the mouse
// this variable is used not for finding the correct current cursor but
// mainly for finding out what is going to happen if the mouse starts being
// dragged right now
//
// by default it is WXGRID_CURSOR_SELECT_CELL meaning that nothing else is
// going on, and it is set to one of RESIZE/SELECT/MOVE values while the
// corresponding operation will be started if the user starts dragging the
// mouse from the current position
CursorMode m_cursorMode; CursorMode m_cursorMode;
//Column positions //Column positions
wxArrayInt m_colAt; wxArrayInt m_colAt;
int m_moveToCol; int m_moveToCol;
@@ -2029,7 +2057,16 @@ protected:
int m_dragLastPos; int m_dragLastPos;
int m_dragRowOrCol; int m_dragRowOrCol;
// true if a drag operation is in progress; when this is true,
// m_startDragPos is valid, i.e. not wxDefaultPosition
bool m_isDragging; bool m_isDragging;
// the position (in physical coordinates) where the user started dragging
// the mouse or wxDefaultPosition if mouse isn't being dragged
//
// notice that this can be != wxDefaultPosition while m_isDragging is still
// false because we wait until the mouse is moved some distance away before
// setting m_isDragging to true
wxPoint m_startDragPos; wxPoint m_startDragPos;
bool m_waitForSlowClick; bool m_waitForSlowClick;
@@ -2053,14 +2090,20 @@ protected:
bool Redimension( wxGridTableMessage& ); bool Redimension( wxGridTableMessage& );
int SendEvent( const wxEventType, int row, int col, wxMouseEvent& ); // generate the appropriate grid event and return -1 if it was vetoed, 1 if
int SendEvent( const wxEventType, int row, int col ); // it was processed (but not vetoed) and 0 if it wasn't processed
int SendEvent( const wxEventType type) int SendEvent(const wxEventType evtType,
{ int row, int col,
return SendEvent(type, wxMouseEvent& e);
m_currentCellCoords.GetRow(), int SendEvent(const wxEventType evtType,
m_currentCellCoords.GetCol()); const wxGridCellCoords& coords,
} wxMouseEvent& e)
{ return SendEvent(evtType, coords.GetRow(), coords.GetCol(), e); }
int SendEvent(const wxEventType evtType, int row, int col);
int SendEvent(const wxEventType evtType, const wxGridCellCoords& coords)
{ return SendEvent(evtType, coords.GetRow(), coords.GetCol()); }
int SendEvent(const wxEventType evtType)
{ return SendEvent(evtType, m_currentCellCoords); }
void OnPaint( wxPaintEvent& ); void OnPaint( wxPaintEvent& );
void OnSize( wxSizeEvent& ); void OnSize( wxSizeEvent& );
@@ -2070,16 +2113,20 @@ protected:
void OnEraseBackground( wxEraseEvent& ); void OnEraseBackground( wxEraseEvent& );
void SetCurrentCell( const wxGridCellCoords& coords ); bool SetCurrentCell( const wxGridCellCoords& coords );
void SetCurrentCell( int row, int col ) bool SetCurrentCell( int row, int col )
{ SetCurrentCell( wxGridCellCoords(row, col) ); } { return SetCurrentCell( wxGridCellCoords(row, col) ); }
void HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCol );
void HighlightBlock( const wxGridCellCoords& topLeft, // this function is called to extend the block being currently selected
const wxGridCellCoords& bottomRight ) // from mouse and keyboard event handlers
{ HighlightBlock( topLeft.GetRow(), topLeft.GetCol(), void UpdateBlockBeingSelected(int topRow, int leftCol,
bottomRight.GetRow(), bottomRight.GetCol() ); } int bottomRow, int rightCol);
void UpdateBlockBeingSelected(const wxGridCellCoords& topLeft,
const wxGridCellCoords& bottomRight)
{ UpdateBlockBeingSelected(topLeft.GetRow(), topLeft.GetCol(),
bottomRight.GetRow(), bottomRight.GetCol()); }
// ------ functions to get/send data (see also public functions) // ------ functions to get/send data (see also public functions)
// //
@@ -2090,10 +2137,56 @@ protected:
friend class wxGridRowOperations; friend class wxGridRowOperations;
friend class wxGridColumnOperations; friend class wxGridColumnOperations;
// they call our private Process{{Corner,Col,Row}Label,GridCell}MouseEvent()
friend class wxGridCornerLabelWindow;
friend class wxGridColLabelWindow;
friend class wxGridRowLabelWindow;
friend class wxGridWindow;
private: private:
// implement wxScrolledWindow method to return m_gridWin size // implement wxScrolledWindow method to return m_gridWin size
virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size); virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size);
// event handlers and their helpers
// --------------------------------
// process mouse drag event in WXGRID_CURSOR_SELECT_CELL mode
void DoGridCellDrag(wxMouseEvent& event,
const wxGridCellCoords& coords,
bool isFirstDrag);
// process row/column resizing drag event
void DoGridLineDrag(wxMouseEvent& event, const wxGridOperations& oper);
// process mouse drag event in the grid window
void DoGridDragEvent(wxMouseEvent& event, const wxGridCellCoords& coords);
// process different clicks on grid cells
void DoGridCellLeftDown(wxMouseEvent& event,
const wxGridCellCoords& coords,
const wxPoint& pos);
void DoGridCellLeftDClick(wxMouseEvent& event,
const wxGridCellCoords& coords,
const wxPoint& pos);
void DoGridCellLeftUp(wxMouseEvent& event, const wxGridCellCoords& coords);
// process movement (but not dragging) event in the grid cell area
void DoGridMouseMoveEvent(wxMouseEvent& event,
const wxGridCellCoords& coords,
const wxPoint& pos);
// process mouse events in the grid window
void ProcessGridCellMouseEvent(wxMouseEvent& event);
// process mouse events in the row/column labels/corner windows
void ProcessRowLabelMouseEvent(wxMouseEvent& event);
void ProcessColLabelMouseEvent(wxMouseEvent& event);
void ProcessCornerLabelMouseEvent(wxMouseEvent& event);
void DoEndDragResizeRow();
void DoEndDragResizeCol();
void DoEndDragMoveCol();
// common implementations of methods defined for both rows and columns // common implementations of methods defined for both rows and columns
void DeselectLine(int line, const wxGridOperations& oper); void DeselectLine(int line, const wxGridOperations& oper);

View File

@@ -44,10 +44,23 @@ public:
bool ControlDown = false, bool ShiftDown = false, bool ControlDown = false, bool ShiftDown = false,
bool AltDown = false, bool MetaDown = false, bool AltDown = false, bool MetaDown = false,
bool sendEvent = true ); bool sendEvent = true );
void SelectBlock( const wxGridCellCoords& topLeft,
const wxGridCellCoords& bottomRight,
bool ControlDown = false, bool ShiftDown = false,
bool AltDown = false, bool MetaDown = false,
bool sendEvent = true )
{
SelectBlock(topLeft.GetRow(), topLeft.GetCol(),
bottomRight.GetRow(), bottomRight.GetCol(),
ControlDown, ShiftDown, AltDown, MetaDown,
sendEvent);
}
void SelectCell( int row, int col, void SelectCell( int row, int col,
bool ControlDown = false, bool ShiftDown = false, bool ControlDown = false, bool ShiftDown = false,
bool AltDown = false, bool MetaDown = false, bool AltDown = false, bool MetaDown = false,
bool sendEvent = true ); bool sendEvent = true );
void ToggleCellSelection( int row, int col, void ToggleCellSelection( int row, int col,
bool ControlDown = false, bool ControlDown = false,
bool ShiftDown = false, bool ShiftDown = false,

View File

@@ -2130,6 +2130,19 @@ public:
*/ */
wxGridTableBase *GetTable() const; wxGridTableBase *GetTable() const;
//@{
/**
Make the given cell current and ensure it is visible.
This method is equivalent to calling MakeCellVisible() and
SetGridCursor() and so, as with the latter, a wxEVT_GRID_SELECT_CELL
event is generated by it and the selected cell doesn't change if the
event is vetoed.
*/
void GoToCell(int row, int col);
void GoToCell(const wxGridCellCoords& coords);
//@}
/** /**
Returns @true if drawing of grid lines is turned on, @false otherwise. Returns @true if drawing of grid lines is turned on, @false otherwise.
*/ */
@@ -2693,12 +2706,22 @@ public:
*/ */
void SetDefaultRowSize(int height, bool resizeExistingRows = false); void SetDefaultRowSize(int height, bool resizeExistingRows = false);
//@{
/** /**
Set the grid cursor to the specified cell. Set the grid cursor to the specified cell.
This function calls MakeCellVisible(). The grid cursor indicates the current cell and can be moved by the user
using the arrow keys or the mouse.
Calling this function generates a wxEVT_GRID_SELECT_CELL event and if
the event handler vetoes this event, the cursor is not moved.
This function doesn't make the target call visible, use GoToCell() to
do this.
*/ */
void SetGridCursor(int row, int col); void SetGridCursor(int row, int col);
void SetGridCursor(const wxGridCellCoords& coords);
//@}
/** /**
Sets the colour used to draw grid lines. Sets the colour used to draw grid lines.
@@ -2883,6 +2906,27 @@ public:
*/ */
int XToEdgeOfCol(int x) const; int XToEdgeOfCol(int x) const;
//@{
/**
Translates logical pixel coordinates to the grid cell coordinates.
Notice that this function expects logical coordinates on input so if
you use this function in a mouse event handler you need to translate
the mouse position, which is expressed in device coordinates, to
logical ones.
@see XToCol(), YToRow()
*/
// XYToCell(int, int, wxGridCellCoords&) overload is intentionally
// undocumented, using it is ugly and non-const reference parameters are
// not used in wxWidgets API
wxGridCellCoords XYToCell(int x, int y) const;
wxGridCellCoords XYToCell(const wxPoint& pos) const;
//@}
/** /**
Returns the row whose bottom edge is close to the given logical y Returns the row whose bottom edge is close to the given logical y
position. position.

View File

@@ -92,6 +92,7 @@ BEGIN_EVENT_TABLE( GridFrame, wxFrame )
EVT_MENU( ID_SELCELLS, GridFrame::SelectCells ) EVT_MENU( ID_SELCELLS, GridFrame::SelectCells )
EVT_MENU( ID_SELROWS, GridFrame::SelectRows ) EVT_MENU( ID_SELROWS, GridFrame::SelectRows )
EVT_MENU( ID_SELCOLS, GridFrame::SelectCols ) EVT_MENU( ID_SELCOLS, GridFrame::SelectCols )
EVT_MENU( ID_SELROWSORCOLS, GridFrame::SelectRowsOrCols )
EVT_MENU( ID_SET_CELL_FG_COLOUR, GridFrame::SetCellFgColour ) EVT_MENU( ID_SET_CELL_FG_COLOUR, GridFrame::SetCellFgColour )
EVT_MENU( ID_SET_CELL_BG_COLOUR, GridFrame::SetCellBgColour ) EVT_MENU( ID_SET_CELL_BG_COLOUR, GridFrame::SetCellBgColour )
@@ -223,9 +224,10 @@ GridFrame::GridFrame()
selectionMenu, selectionMenu,
_T("Change selection mode") ); _T("Change selection mode") );
selectionMenu->Append( ID_SELCELLS, _T("Select &Cells") ); selectionMenu->Append( ID_SELCELLS, _T("Select &cells") );
selectionMenu->Append( ID_SELROWS, _T("Select &Rows") ); selectionMenu->Append( ID_SELROWS, _T("Select &rows") );
selectionMenu->Append( ID_SELCOLS, _T("Select C&ols") ); selectionMenu->Append( ID_SELCOLS, _T("Select col&umns") );
selectionMenu->Append( ID_SELROWSORCOLS, _T("Select rows &or columns") );
wxMenu *autosizeMenu = new wxMenu; wxMenu *autosizeMenu = new wxMenu;
autosizeMenu->Append( ID_SIZE_ROW, _T("Selected &row data") ); autosizeMenu->Append( ID_SIZE_ROW, _T("Selected &row data") );
@@ -807,6 +809,11 @@ void GridFrame::SelectCols( wxCommandEvent& WXUNUSED(ev) )
grid->SetSelectionMode( wxGrid::wxGridSelectColumns ); grid->SetSelectionMode( wxGrid::wxGridSelectColumns );
} }
void GridFrame::SelectRowsOrCols( wxCommandEvent& WXUNUSED(ev) )
{
grid->SetSelectionMode( wxGrid::wxGridSelectRowsOrColumns );
}
void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) ) void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
{ {
wxColour col = wxGetColourFromUser(this); wxColour col = wxGetColourFromUser(this);

View File

@@ -64,6 +64,7 @@ class GridFrame : public wxFrame
void SelectCells( wxCommandEvent& ); void SelectCells( wxCommandEvent& );
void SelectRows( wxCommandEvent& ); void SelectRows( wxCommandEvent& );
void SelectCols( wxCommandEvent& ); void SelectCols( wxCommandEvent& );
void SelectRowsOrCols( wxCommandEvent& );
void DeselectCell(wxCommandEvent& event); void DeselectCell(wxCommandEvent& event);
void DeselectCol(wxCommandEvent& event); void DeselectCol(wxCommandEvent& event);
@@ -144,6 +145,7 @@ public:
ID_SELCELLS, ID_SELCELLS,
ID_SELROWS, ID_SELROWS,
ID_SELCOLS, ID_SELCOLS,
ID_SELROWSORCOLS,
ID_SET_CELL_FG_COLOUR, ID_SET_CELL_FG_COLOUR,
ID_SET_CELL_BG_COLOUR, ID_SET_CELL_BG_COLOUR,
ID_VTABLE, ID_VTABLE,

View File

@@ -471,11 +471,20 @@ public:
// Draws a line parallel to the row or column, i.e. horizontal or vertical: // Draws a line parallel to the row or column, i.e. horizontal or vertical:
// pos is the vertical or horizontal position of the line and start and end // pos is the horizontal or vertical position of the line and start and end
// are the coordinates of the line extremities in the other direction // are the coordinates of the line extremities in the other direction
virtual void virtual void
DrawParallelLine(wxDC& dc, int start, int end, int pos) const = 0; DrawParallelLine(wxDC& dc, int start, int end, int pos) const = 0;
// Draw a horizontal or vertical line across the given rectangle
// (this is implemented in terms of above and uses Select() to extract
// start and end from the given rectangle)
void DrawParallelLineInRect(wxDC& dc, const wxRect& rect, int pos) const
{
const int posStart = Select(rect.GetPosition());
DrawParallelLine(dc, posStart, posStart + Select(rect.GetSize()), pos);
}
// Return the row or column at the given pixel coordinate. // Return the row or column at the given pixel coordinate.
virtual int virtual int
@@ -785,13 +794,22 @@ private:
wxGridCellCoords wxGridNoCellCoords( -1, -1 ); wxGridCellCoords wxGridNoCellCoords( -1, -1 );
wxRect wxGridNoCellRect( -1, -1, -1, -1 ); wxRect wxGridNoCellRect( -1, -1, -1, -1 );
namespace
{
// scroll line size // scroll line size
static const size_t GRID_SCROLL_LINE_X = 15; const size_t GRID_SCROLL_LINE_X = 15;
static const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X; const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X;
// the size of hash tables used a bit everywhere (the max number of elements // the size of hash tables used a bit everywhere (the max number of elements
// in these hash tables is the number of rows/columns) // in these hash tables is the number of rows/columns)
static const int GRID_HASH_SIZE = 100; const int GRID_HASH_SIZE = 100;
// the minimal distance in pixels the mouse needs to move to start a drag
// operation
const int DRAG_SENSITIVITY = 3;
} // anonymous namespace
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// private helpers // private helpers
@@ -4708,22 +4726,22 @@ wxGrid::SetTable(wxGridTableBase *table,
// If the newly set table is smaller than the // If the newly set table is smaller than the
// original one current cell and selection regions // original one current cell and selection regions
// might be invalid, // might be invalid,
m_selectingKeyboard = wxGridNoCellCoords; m_selectedBlockCorner = wxGridNoCellCoords;
m_currentCellCoords = m_currentCellCoords =
wxGridCellCoords(wxMin(m_numRows, m_currentCellCoords.GetRow()), wxGridCellCoords(wxMin(m_numRows, m_currentCellCoords.GetRow()),
wxMin(m_numCols, m_currentCellCoords.GetCol())); wxMin(m_numCols, m_currentCellCoords.GetCol()));
if (m_selectingTopLeft.GetRow() >= m_numRows || if (m_selectedBlockTopLeft.GetRow() >= m_numRows ||
m_selectingTopLeft.GetCol() >= m_numCols) m_selectedBlockTopLeft.GetCol() >= m_numCols)
{ {
m_selectingTopLeft = wxGridNoCellCoords; m_selectedBlockTopLeft = wxGridNoCellCoords;
m_selectingBottomRight = wxGridNoCellCoords; m_selectedBlockBottomRight = wxGridNoCellCoords;
} }
else else
m_selectingBottomRight = m_selectedBlockBottomRight =
wxGridCellCoords(wxMin(m_numRows, wxGridCellCoords(wxMin(m_numRows,
m_selectingBottomRight.GetRow()), m_selectedBlockBottomRight.GetRow()),
wxMin(m_numCols, wxMin(m_numCols,
m_selectingBottomRight.GetCol())); m_selectedBlockBottomRight.GetCol()));
} }
CalcDimensions(); CalcDimensions();
@@ -6132,6 +6150,8 @@ void wxGrid::CancelMouseCapture()
if ( m_winCapture ) if ( m_winCapture )
{ {
m_isDragging = false; m_isDragging = false;
m_startDragPos = wxDefaultPosition;
m_cursorMode = WXGRID_CURSOR_SELECT_CELL; m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
m_winCapture->SetCursor( *wxSTANDARD_CURSOR ); m_winCapture->SetCursor( *wxSTANDARD_CURSOR );
m_winCapture = NULL; m_winCapture = NULL;
@@ -6214,186 +6234,155 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
} }
} }
void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) // ----------------------------------------------------------------------------
// grid mouse event processing
// ----------------------------------------------------------------------------
void
wxGrid::DoGridCellDrag(wxMouseEvent& event,
const wxGridCellCoords& coords,
bool isFirstDrag)
{ {
int x, y; if ( coords == wxGridNoCellCoords )
wxPoint pos( event.GetPosition() ); return; // we're outside any valid cell
CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
wxGridCellCoords coords; // Hide the edit control, so it won't interfere with drag-shrinking.
XYToCell( x, y, coords );
int cell_rows, cell_cols;
bool isFirstDrag = !m_isDragging;
GetCellSize( coords.GetRow(), coords.GetCol(), &cell_rows, &cell_cols );
if ((cell_rows < 0) || (cell_cols < 0))
{
coords.SetRow(coords.GetRow() + cell_rows);
coords.SetCol(coords.GetCol() + cell_cols);
}
if ( event.Dragging() )
{
//wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol());
// Don't start doing anything until the mouse has been dragged at
// least 3 pixels in any direction...
if (! m_isDragging)
{
if (m_startDragPos == wxDefaultPosition)
{
m_startDragPos = pos;
return;
}
if (abs(m_startDragPos.x - pos.x) < 4 && abs(m_startDragPos.y - pos.y) < 4)
return;
}
m_isDragging = true;
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
// Hide the edit control, so it
// won't interfere with drag-shrinking.
if ( IsCellEditControlShown() ) if ( IsCellEditControlShown() )
{ {
HideCellEditControl(); HideCellEditControl();
SaveEditControlValue(); SaveEditControlValue();
} }
if ( coords != wxGridNoCellCoords ) switch ( event.GetModifiers() )
{ {
if ( event.CmdDown() ) case wxMOD_CMD:
{ if ( m_selectedBlockCorner == wxGridNoCellCoords)
if ( m_selectingKeyboard == wxGridNoCellCoords) m_selectedBlockCorner = coords;
m_selectingKeyboard = coords; UpdateBlockBeingSelected(m_selectedBlockCorner, coords);
HighlightBlock( m_selectingKeyboard, coords ); break;
}
else if ( CanDragCell() ) case wxMOD_NONE:
if ( CanDragCell() )
{ {
if ( isFirstDrag ) if ( isFirstDrag )
{ {
if ( m_selectingKeyboard == wxGridNoCellCoords) if ( m_selectedBlockCorner == wxGridNoCellCoords)
m_selectingKeyboard = coords; m_selectedBlockCorner = coords;
SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG, SendEvent(wxEVT_GRID_CELL_BEGIN_DRAG, coords, event);
coords.GetRow(),
coords.GetCol(),
event );
return; return;
} }
} }
else
{ UpdateBlockBeingSelected(m_currentCellCoords, coords);
if ( !IsSelection() ) break;
{
HighlightBlock( coords, coords ); default:
// we don't handle the other key modifiers
event.Skip();
} }
else }
void wxGrid::DoGridLineDrag(wxMouseEvent& event, const wxGridOperations& oper)
{
wxClientDC dc(m_gridWin);
PrepareDC(dc);
dc.SetLogicalFunction(wxINVERT);
const wxRect rectWin(CalcUnscrolledPosition(wxPoint(0, 0)),
m_gridWin->GetClientSize());
// erase the previously drawn line, if any
if ( m_dragLastPos >= 0 )
oper.DrawParallelLineInRect(dc, rectWin, m_dragLastPos);
// we need the vertical position for rows and horizontal for columns here
m_dragLastPos = oper.Dual().Select(CalcUnscrolledPosition(event.GetPosition()));
// don't allow resizing beneath the minimal size
const int posMin = oper.GetLineStartPos(this, m_dragRowOrCol) +
oper.GetMinimalLineSize(this, m_dragRowOrCol);
if ( m_dragLastPos < posMin )
m_dragLastPos = posMin;
// and draw it at the new position
oper.DrawParallelLineInRect(dc, rectWin, m_dragLastPos);
}
void wxGrid::DoGridDragEvent(wxMouseEvent& event, const wxGridCellCoords& coords)
{
if ( !m_isDragging )
{ {
HighlightBlock( m_currentCellCoords, coords ); // Don't start doing anything until the mouse has been dragged far
} // enough
const wxPoint& pt = event.GetPosition();
if ( m_startDragPos == wxDefaultPosition )
{
m_startDragPos = pt;
return;
} }
if (! IsVisible(coords)) if ( abs(m_startDragPos.x - pt.x) <= DRAG_SENSITIVITY &&
abs(m_startDragPos.y - pt.y) <= DRAG_SENSITIVITY )
return;
}
const bool isFirstDrag = !m_isDragging;
m_isDragging = true;
switch ( m_cursorMode )
{ {
MakeCellVisible(coords); case WXGRID_CURSOR_SELECT_CELL:
// TODO: need to introduce a delay or something here. The DoGridCellDrag(event, coords, isFirstDrag);
// scrolling is way too fast, at least under MSW and GTK. break;
case WXGRID_CURSOR_RESIZE_ROW:
DoGridLineDrag(event, wxGridRowOperations());
break;
case WXGRID_CURSOR_RESIZE_COL:
DoGridLineDrag(event, wxGridColumnOperations());
break;
default:
event.Skip();
} }
}
// Have we captured the mouse yet? if ( isFirstDrag )
if (! m_winCapture)
{ {
m_winCapture = m_gridWin; m_winCapture = m_gridWin;
m_winCapture->CaptureMouse(); m_winCapture->CaptureMouse();
} }
}
void
} wxGrid::DoGridCellLeftDown(wxMouseEvent& event,
else if ( event.LeftIsDown() && const wxGridCellCoords& coords,
m_cursorMode == WXGRID_CURSOR_RESIZE_ROW ) const wxPoint& pos)
{
if ( SendEvent(wxEVT_GRID_CELL_LEFT_CLICK, coords, event) )
{ {
int cw, ch, left, dummy; // event handled by user code, no need to do anything here
m_gridWin->GetClientSize( &cw, &ch );
CalcUnscrolledPosition( 0, 0, &left, &dummy );
wxClientDC dc( m_gridWin );
PrepareDC( dc );
y = wxMax( y, GetRowTop(m_dragRowOrCol) +
GetRowMinimalHeight(m_dragRowOrCol) );
dc.SetLogicalFunction(wxINVERT);
if ( m_dragLastPos >= 0 )
{
dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos );
}
dc.DrawLine( left, y, left+cw, y );
m_dragLastPos = y;
}
else if ( event.LeftIsDown() &&
m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
{
int cw, ch, dummy, top;
m_gridWin->GetClientSize( &cw, &ch );
CalcUnscrolledPosition( 0, 0, &dummy, &top );
wxClientDC dc( m_gridWin );
PrepareDC( dc );
x = wxMax( x, GetColLeft(m_dragRowOrCol) +
GetColMinimalWidth(m_dragRowOrCol) );
dc.SetLogicalFunction(wxINVERT);
if ( m_dragLastPos >= 0 )
{
dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top + ch );
}
dc.DrawLine( x, top, x, top + ch );
m_dragLastPos = x;
}
return; return;
} }
m_isDragging = false;
m_startDragPos = wxDefaultPosition;
// VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
// immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
// wxGTK
#if 0
if ( event.Entering() || event.Leaving() )
{
ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
m_gridWin->SetCursor( *wxSTANDARD_CURSOR );
}
else
#endif // 0
// ------------ Left button pressed
//
if ( event.LeftDown() && coords != wxGridNoCellCoords )
{
if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK,
coords.GetRow(),
coords.GetCol(),
event ) )
{
if ( !event.CmdDown() ) if ( !event.CmdDown() )
ClearSelection(); ClearSelection();
if ( event.ShiftDown() ) if ( event.ShiftDown() )
{ {
if ( m_selection ) if ( m_selection )
{ {
m_selection->SelectBlock( m_currentCellCoords.GetRow(), m_selection->SelectBlock( m_currentCellCoords,
m_currentCellCoords.GetCol(), coords,
coords.GetRow(),
coords.GetCol(),
event.ControlDown(), event.ControlDown(),
event.ShiftDown(), event.ShiftDown(),
event.AltDown(), event.AltDown(),
event.MetaDown() ); event.MetaDown() );
m_selectedBlockCorner = coords;
} }
} }
else if ( XToEdgeOfCol(x) < 0 && else if ( XToEdgeOfCol(pos.x) < 0 && YToEdgeOfRow(pos.y) < 0 )
YToEdgeOfRow(y) < 0 )
{ {
DisableCellEditControl(); DisableCellEditControl();
MakeCellVisible( coords ); MakeCellVisible( coords );
@@ -6402,16 +6391,15 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
{ {
if ( m_selection ) if ( m_selection )
{ {
m_selection->ToggleCellSelection( coords.GetRow(), m_selection->ToggleCellSelection( coords,
coords.GetCol(),
event.ControlDown(), event.ControlDown(),
event.ShiftDown(), event.ShiftDown(),
event.AltDown(), event.AltDown(),
event.MetaDown() ); event.MetaDown() );
} }
m_selectingTopLeft = wxGridNoCellCoords; m_selectedBlockTopLeft = wxGridNoCellCoords;
m_selectingBottomRight = wxGridNoCellCoords; m_selectedBlockBottomRight = wxGridNoCellCoords;
m_selectingKeyboard = coords; m_selectedBlockCorner = coords;
} }
else else
{ {
@@ -6420,33 +6408,27 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
SetCurrentCell( coords ); SetCurrentCell( coords );
} }
} }
} }
}
// ------------ Left double click void
// wxGrid::DoGridCellLeftDClick(wxMouseEvent& event,
else if ( event.LeftDClick() && coords != wxGridNoCellCoords ) const wxGridCellCoords& coords,
const wxPoint& pos)
{
if ( XToEdgeOfCol(pos.x) < 0 && YToEdgeOfRow(pos.y) < 0 )
{ {
DisableCellEditControl(); if ( !SendEvent(wxEVT_GRID_CELL_LEFT_DCLICK, coords, event) )
if ( XToEdgeOfCol(x) < 0 && YToEdgeOfRow(y) < 0 )
{
if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK,
coords.GetRow(),
coords.GetCol(),
event ) )
{ {
// we want double click to select a cell and start editing // we want double click to select a cell and start editing
// (i.e. to behave in same way as sequence of two slow clicks): // (i.e. to behave in same way as sequence of two slow clicks):
m_waitForSlowClick = true; m_waitForSlowClick = true;
} }
} }
} }
// ------------ Left button released void
// wxGrid::DoGridCellLeftUp(wxMouseEvent& event, const wxGridCellCoords& coords)
else if ( event.LeftUp() ) {
{
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{ {
if (m_winCapture) if (m_winCapture)
@@ -6469,23 +6451,21 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
m_waitForSlowClick = false; m_waitForSlowClick = false;
} }
else if ( m_selectingTopLeft != wxGridNoCellCoords && else if ( m_selectedBlockTopLeft != wxGridNoCellCoords &&
m_selectingBottomRight != wxGridNoCellCoords ) m_selectedBlockBottomRight != wxGridNoCellCoords )
{ {
if ( m_selection ) if ( m_selection )
{ {
m_selection->SelectBlock( m_selectingTopLeft.GetRow(), m_selection->SelectBlock( m_selectedBlockTopLeft,
m_selectingTopLeft.GetCol(), m_selectedBlockBottomRight,
m_selectingBottomRight.GetRow(),
m_selectingBottomRight.GetCol(),
event.ControlDown(), event.ControlDown(),
event.ShiftDown(), event.ShiftDown(),
event.AltDown(), event.AltDown(),
event.MetaDown() ); event.MetaDown() );
} }
m_selectingTopLeft = wxGridNoCellCoords; m_selectedBlockTopLeft = wxGridNoCellCoords;
m_selectingBottomRight = wxGridNoCellCoords; m_selectedBlockBottomRight = wxGridNoCellCoords;
// Show the edit control, if it has been hidden for // Show the edit control, if it has been hidden for
// drag-shrinking. // drag-shrinking.
@@ -6514,40 +6494,13 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
} }
m_dragLastPos = -1; m_dragLastPos = -1;
} }
// ------------ Right button down void
// wxGrid::DoGridMouseMoveEvent(wxMouseEvent& WXUNUSED(event),
else if ( event.RightDown() && coords != wxGridNoCellCoords ) const wxGridCellCoords& coords,
{ const wxPoint& pos)
DisableCellEditControl(); {
if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK,
coords.GetRow(),
coords.GetCol(),
event ) )
{
// no default action at the moment
}
}
// ------------ Right double click
//
else if ( event.RightDClick() && coords != wxGridNoCellCoords )
{
DisableCellEditControl();
if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK,
coords.GetRow(),
coords.GetCol(),
event ) )
{
// no default action at the moment
}
}
// ------------ Moving and no button action
//
else if ( event.Moving() && !event.IsButton() )
{
if ( coords.GetRow() < 0 || coords.GetCol() < 0 ) if ( coords.GetRow() < 0 || coords.GetCol() < 0 )
{ {
// out of grid cell area // out of grid cell area
@@ -6555,8 +6508,8 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
return; return;
} }
int dragRow = YToEdgeOfRow( y ); int dragRow = YToEdgeOfRow( pos.y );
int dragCol = XToEdgeOfCol( x ); int dragCol = XToEdgeOfCol( pos.x );
// Dragging on the corner of a cell to resize in both // Dragging on the corner of a cell to resize in both
// directions is not implemented yet... // directions is not implemented yet...
@@ -6594,6 +6547,76 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL); ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
} }
} }
}
void wxGrid::ProcessGridCellMouseEvent(wxMouseEvent& event)
{
const wxPoint pos = CalcUnscrolledPosition(event.GetPosition());
// coordinates of the cell under mouse
wxGridCellCoords coords = XYToCell(pos);
int cell_rows, cell_cols;
GetCellSize( coords.GetRow(), coords.GetCol(), &cell_rows, &cell_cols );
if ( (cell_rows < 0) || (cell_cols < 0) )
{
coords.SetRow(coords.GetRow() + cell_rows);
coords.SetCol(coords.GetCol() + cell_cols);
}
if ( event.Dragging() )
{
if ( event.LeftIsDown() )
DoGridDragEvent(event, coords);
else
event.Skip();
return;
}
m_isDragging = false;
m_startDragPos = wxDefaultPosition;
// VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
// immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
// wxGTK
#if 0
if ( event.Entering() || event.Leaving() )
{
ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
m_gridWin->SetCursor( *wxSTANDARD_CURSOR );
}
#endif // 0
// deal with various button presses
if ( event.IsButton() )
{
if ( coords != wxGridNoCellCoords )
{
DisableCellEditControl();
if ( event.LeftDown() )
DoGridCellLeftDown(event, coords, pos);
else if ( event.LeftDClick() )
DoGridCellLeftDClick(event, coords, pos);
else if ( event.RightDown() )
SendEvent(wxEVT_GRID_CELL_RIGHT_CLICK, coords, event);
else if ( event.RightDClick() )
SendEvent(wxEVT_GRID_CELL_RIGHT_DCLICK, coords, event);
}
// this one should be called even if we're not over any cell
if ( event.LeftUp() )
{
DoGridCellLeftUp(event, coords);
}
}
else if ( event.Moving() )
{
DoGridMouseMoveEvent(event, coords, pos);
}
else // unknown mouse event?
{
event.Skip();
} }
} }
@@ -6883,12 +6906,14 @@ wxGrid::DoAppendLines(bool (wxGridTableBase::*funcAppend)(size_t),
// ----- event handlers // ----- event handlers
// //
// Generate a grid event based on a mouse event and // Generate a grid event based on a mouse event and return:
// return the result of ProcessEvent() // -1 if the event was vetoed
// // +1 if the event was processed (but not vetoed)
int wxGrid::SendEvent( const wxEventType type, // 0 if the event wasn't handled
int
wxGrid::SendEvent(const wxEventType type,
int row, int col, int row, int col,
wxMouseEvent& mouseEv ) wxMouseEvent& mouseEv)
{ {
bool claimed, vetoed; bool claimed, vetoed;
@@ -6916,8 +6941,8 @@ int wxGrid::SendEvent( const wxEventType type,
wxGridRangeSelectEvent gridEvt( GetId(), wxGridRangeSelectEvent gridEvt( GetId(),
type, type,
this, this,
m_selectingTopLeft, m_selectedBlockTopLeft,
m_selectingBottomRight, m_selectedBlockBottomRight,
true, true,
mouseEv.ControlDown(), mouseEv.ControlDown(),
mouseEv.ShiftDown(), mouseEv.ShiftDown(),
@@ -6977,11 +7002,9 @@ int wxGrid::SendEvent( const wxEventType type,
return claimed ? 1 : 0; return claimed ? 1 : 0;
} }
// Generate a grid event of specified type and return the result // Generate a grid event of specified type, return value same as above
// of ProcessEvent().
// //
int wxGrid::SendEvent( const wxEventType type, int wxGrid::SendEvent(const wxEventType type, int row, int col)
int row, int col )
{ {
bool claimed, vetoed; bool claimed, vetoed;
@@ -7224,8 +7247,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
case WXK_HOME: case WXK_HOME:
if ( event.ControlDown() ) if ( event.ControlDown() )
{ {
MakeCellVisible( 0, 0 ); GoToCell(0, 0);
SetCurrentCell( 0, 0 );
} }
else else
{ {
@@ -7236,8 +7258,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
case WXK_END: case WXK_END:
if ( event.ControlDown() ) if ( event.ControlDown() )
{ {
MakeCellVisible( m_numRows - 1, m_numCols - 1 ); GoToCell(m_numRows - 1, m_numCols - 1);
SetCurrentCell( m_numRows - 1, m_numCols - 1 );
} }
else else
{ {
@@ -7299,16 +7320,14 @@ void wxGrid::OnKeyUp( wxKeyEvent& event )
// //
if ( event.GetKeyCode() == WXK_SHIFT ) if ( event.GetKeyCode() == WXK_SHIFT )
{ {
if ( m_selectingTopLeft != wxGridNoCellCoords && if ( m_selectedBlockTopLeft != wxGridNoCellCoords &&
m_selectingBottomRight != wxGridNoCellCoords ) m_selectedBlockBottomRight != wxGridNoCellCoords )
{ {
if ( m_selection ) if ( m_selection )
{ {
m_selection->SelectBlock( m_selection->SelectBlock(
m_selectingTopLeft.GetRow(), m_selectedBlockTopLeft,
m_selectingTopLeft.GetCol(), m_selectedBlockBottomRight,
m_selectingBottomRight.GetRow(),
m_selectingBottomRight.GetCol(),
event.ControlDown(), event.ControlDown(),
true, true,
event.AltDown(), event.AltDown(),
@@ -7316,9 +7335,9 @@ void wxGrid::OnKeyUp( wxKeyEvent& event )
} }
} }
m_selectingTopLeft = wxGridNoCellCoords; m_selectedBlockTopLeft = wxGridNoCellCoords;
m_selectingBottomRight = wxGridNoCellCoords; m_selectedBlockBottomRight = wxGridNoCellCoords;
m_selectingKeyboard = wxGridNoCellCoords; m_selectedBlockCorner = wxGridNoCellCoords;
} }
} }
@@ -7367,12 +7386,12 @@ void wxGrid::OnEraseBackground(wxEraseEvent&)
{ {
} }
void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) bool wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
{ {
if ( SendEvent( wxEVT_GRID_SELECT_CELL, coords.GetRow(), coords.GetCol() ) ) if ( SendEvent(wxEVT_GRID_SELECT_CELL, coords) == -1 )
{ {
// the event has been intercepted - do nothing // the event has been vetoed - do nothing
return; return false;
} }
#if !defined(__WXMAC__) #if !defined(__WXMAC__)
@@ -7417,35 +7436,62 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
DrawCellHighlight( dc, attr ); DrawCellHighlight( dc, attr );
#endif #endif
attr->DecRef(); attr->DecRef();
return true;
} }
void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol) void
wxGrid::UpdateBlockBeingSelected(int topRow, int leftCol,
int bottomRow, int rightCol)
{ {
wxGridCellCoords updateTopLeft, updateBottomRight;
if ( m_selection ) if ( m_selection )
{ {
if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows ) switch ( m_selection->GetSelectionMode() )
{ {
default:
wxFAIL_MSG( "unknown selection mode" );
// fall through
case wxGridSelectCells:
// arbitrary blocks selection allowed so just use the cell
// coordinates as is
break;
case wxGridSelectRows:
// only full rows selection allowd, ensure that we do select
// full rows
leftCol = 0; leftCol = 0;
rightCol = GetNumberCols() - 1; rightCol = GetNumberCols() - 1;
} break;
else if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns )
{ case wxGridSelectColumns:
// same as above but for columns
topRow = 0; topRow = 0;
bottomRow = GetNumberRows() - 1; bottomRow = GetNumberRows() - 1;
break;
case wxGridSelectRowsOrColumns:
// in this mode we can select only full rows or full columns so
// it doesn't make sense to select blocks at all (and we can't
// extend the block because there is no preferred direction, we
// could only extend it to cover the entire grid but this is
// not useful)
return;
} }
} }
m_selectedBlockCorner = wxGridCellCoords(bottomRow, rightCol);
MakeCellVisible(m_selectedBlockCorner);
EnsureFirstLessThanSecond(topRow, bottomRow); EnsureFirstLessThanSecond(topRow, bottomRow);
EnsureFirstLessThanSecond(leftCol, rightCol); EnsureFirstLessThanSecond(leftCol, rightCol);
updateTopLeft = wxGridCellCoords( topRow, leftCol ); wxGridCellCoords updateTopLeft = wxGridCellCoords(topRow, leftCol),
updateBottomRight = wxGridCellCoords( bottomRow, rightCol ); updateBottomRight = wxGridCellCoords(bottomRow, rightCol);
// First the case that we selected a completely new area // First the case that we selected a completely new area
if ( m_selectingTopLeft == wxGridNoCellCoords || if ( m_selectedBlockTopLeft == wxGridNoCellCoords ||
m_selectingBottomRight == wxGridNoCellCoords ) m_selectedBlockBottomRight == wxGridNoCellCoords )
{ {
wxRect rect; wxRect rect;
rect = BlockToDeviceRect( wxGridCellCoords ( topRow, leftCol ), rect = BlockToDeviceRect( wxGridCellCoords ( topRow, leftCol ),
@@ -7454,8 +7500,8 @@ void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol
} }
// Now handle changing an existing selection area. // Now handle changing an existing selection area.
else if ( m_selectingTopLeft != updateTopLeft || else if ( m_selectedBlockTopLeft != updateTopLeft ||
m_selectingBottomRight != updateBottomRight ) m_selectedBlockBottomRight != updateBottomRight )
{ {
// Compute two optimal update rectangles: // Compute two optimal update rectangles:
// Either one rectangle is a real subset of the // Either one rectangle is a real subset of the
@@ -7469,10 +7515,10 @@ void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol
int i; int i;
// Store intermediate values // Store intermediate values
wxCoord oldLeft = m_selectingTopLeft.GetCol(); wxCoord oldLeft = m_selectedBlockTopLeft.GetCol();
wxCoord oldTop = m_selectingTopLeft.GetRow(); wxCoord oldTop = m_selectedBlockTopLeft.GetRow();
wxCoord oldRight = m_selectingBottomRight.GetCol(); wxCoord oldRight = m_selectedBlockBottomRight.GetCol();
wxCoord oldBottom = m_selectingBottomRight.GetRow(); wxCoord oldBottom = m_selectedBlockBottomRight.GetRow();
// Determine the outer/inner coordinates. // Determine the outer/inner coordinates.
EnsureFirstLessThanSecond(oldLeft, leftCol); EnsureFirstLessThanSecond(oldLeft, leftCol);
@@ -7531,8 +7577,8 @@ void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol
} }
// change selection // change selection
m_selectingTopLeft = updateTopLeft; m_selectedBlockTopLeft = updateTopLeft;
m_selectingBottomRight = updateBottomRight; m_selectedBlockBottomRight = updateBottomRight;
} }
// //
@@ -8371,7 +8417,7 @@ void wxGrid::EnableCellEditControl( bool enable )
{ {
if ( enable ) if ( enable )
{ {
if (SendEvent( wxEVT_GRID_EDITOR_SHOWN) <0) if ( SendEvent(wxEVT_GRID_EDITOR_SHOWN) == -1 )
return; return;
// this should be checked by the caller! // this should be checked by the caller!
@@ -8385,7 +8431,7 @@ void wxGrid::EnableCellEditControl( bool enable )
else else
{ {
//FIXME:add veto support //FIXME:add veto support
SendEvent( wxEVT_GRID_EDITOR_HIDDEN ); SendEvent(wxEVT_GRID_EDITOR_HIDDEN);
HideCellEditControl(); HideCellEditControl();
SaveEditControlValue(); SaveEditControlValue();
@@ -8624,9 +8670,7 @@ void wxGrid::SaveEditControlValue()
if (changed) if (changed)
{ {
if ( SendEvent( wxEVT_GRID_CELL_CHANGE, if ( SendEvent(wxEVT_GRID_CELL_CHANGE) == -1 )
m_currentCellCoords.GetRow(),
m_currentCellCoords.GetCol() ) < 0 )
{ {
// Event has been vetoed, set the data back. // Event has been vetoed, set the data back.
SetCellValue(row, col, oldval); SetCellValue(row, col, oldval);
@@ -8642,19 +8686,13 @@ void wxGrid::SaveEditControlValue()
// coordinates for mouse events etc. // coordinates for mouse events etc.
// //
void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords ) const wxGridCellCoords wxGrid::XYToCell(int x, int y) const
{ {
int row = YToRow(y); int row = YToRow(y);
int col = XToCol(x); int col = XToCol(x);
if ( row == -1 || col == -1 ) return row == -1 || col == -1 ? wxGridNoCellCoords
{ : wxGridCellCoords(row, col);
coords = wxGridNoCellCoords;
}
else
{
coords.Set( row, col );
}
} }
// compute row or column from some (unscrolled) coordinate value, using either // compute row or column from some (unscrolled) coordinate value, using either
@@ -8957,28 +8995,28 @@ wxGrid::DoMoveCursor(bool expandSelection,
if ( expandSelection ) if ( expandSelection )
{ {
if ( m_selectingKeyboard == wxGridNoCellCoords ) wxGridCellCoords coords = m_selectedBlockCorner;
m_selectingKeyboard = m_currentCellCoords; if ( coords == wxGridNoCellCoords )
coords = m_currentCellCoords;
if ( diroper.IsAtBoundary(m_selectingKeyboard) ) if ( diroper.IsAtBoundary(coords) )
return false; return false;
diroper.Advance(m_selectingKeyboard); diroper.Advance(coords);
MakeCellVisible(m_selectingKeyboard); UpdateBlockBeingSelected(m_currentCellCoords, coords);
HighlightBlock(m_currentCellCoords, m_selectingKeyboard);
} }
else else // don't expand selection
{ {
ClearSelection();
if ( diroper.IsAtBoundary(m_currentCellCoords) ) if ( diroper.IsAtBoundary(m_currentCellCoords) )
return false; return false;
ClearSelection();
wxGridCellCoords coords = m_currentCellCoords; wxGridCellCoords coords = m_currentCellCoords;
diroper.Advance(coords); diroper.Advance(coords);
MakeCellVisible(coords);
SetCurrentCell(coords); GoToCell(coords);
} }
return true; return true;
@@ -9025,8 +9063,7 @@ bool wxGrid::DoMoveCursorByPage(const wxGridDirectionOperations& diroper)
newRow = coords.GetRow(); newRow = coords.GetRow();
} }
MakeCellVisible(newRow, m_currentCellCoords.GetCol()); GoToCell(newRow, m_currentCellCoords.GetCol());
SetCurrentCell(newRow, m_currentCellCoords.GetCol());
return true; return true;
} }
@@ -9097,16 +9134,14 @@ wxGrid::DoMoveCursorByBlock(bool expandSelection,
} }
} }
MakeCellVisible(coords);
if ( expandSelection ) if ( expandSelection )
{ {
m_selectingKeyboard = coords; UpdateBlockBeingSelected(m_currentCellCoords, coords);
HighlightBlock(m_currentCellCoords, m_selectingKeyboard);
} }
else else
{ {
ClearSelection(); ClearSelection();
SetCurrentCell(coords); GoToCell(coords);
} }
return true; return true;
@@ -10718,17 +10753,17 @@ void wxGrid::DeselectCell( int row, int col )
bool wxGrid::IsSelection() const bool wxGrid::IsSelection() const
{ {
return ( m_selection && (m_selection->IsSelection() || return ( m_selection && (m_selection->IsSelection() ||
( m_selectingTopLeft != wxGridNoCellCoords && ( m_selectedBlockTopLeft != wxGridNoCellCoords &&
m_selectingBottomRight != wxGridNoCellCoords) ) ); m_selectedBlockBottomRight != wxGridNoCellCoords) ) );
} }
bool wxGrid::IsInSelection( int row, int col ) const bool wxGrid::IsInSelection( int row, int col ) const
{ {
return ( m_selection && (m_selection->IsInSelection( row, col ) || return ( m_selection && (m_selection->IsInSelection( row, col ) ||
( row >= m_selectingTopLeft.GetRow() && ( row >= m_selectedBlockTopLeft.GetRow() &&
col >= m_selectingTopLeft.GetCol() && col >= m_selectedBlockTopLeft.GetCol() &&
row <= m_selectingBottomRight.GetRow() && row <= m_selectedBlockBottomRight.GetRow() &&
col <= m_selectingBottomRight.GetCol() )) ); col <= m_selectedBlockBottomRight.GetCol() )) );
} }
wxGridCellCoordsArray wxGrid::GetSelectedCells() const wxGridCellCoordsArray wxGrid::GetSelectedCells() const
@@ -10788,13 +10823,18 @@ wxArrayInt wxGrid::GetSelectedCols() const
void wxGrid::ClearSelection() void wxGrid::ClearSelection()
{ {
wxRect r1 = BlockToDeviceRect( m_selectingTopLeft, m_selectingBottomRight); wxRect r1 = BlockToDeviceRect(m_selectedBlockTopLeft,
wxRect r2 = BlockToDeviceRect( m_currentCellCoords, m_selectingKeyboard ); m_selectedBlockBottomRight);
m_selectingTopLeft = wxRect r2 = BlockToDeviceRect(m_currentCellCoords,
m_selectingBottomRight = m_selectedBlockCorner);
m_selectingKeyboard = wxGridNoCellCoords;
m_selectedBlockTopLeft =
m_selectedBlockBottomRight =
m_selectedBlockCorner = wxGridNoCellCoords;
Refresh( false, &r1 ); Refresh( false, &r1 );
Refresh( false, &r2 ); Refresh( false, &r2 );
if ( m_selection ) if ( m_selection )
m_selection->ClearSelection(); m_selection->ClearSelection();
} }

View File

@@ -385,15 +385,30 @@ void wxGridSelection::SelectBlock( int topRow, int leftCol,
bool sendEvent ) bool sendEvent )
{ {
// Fix the coordinates of the block if needed. // Fix the coordinates of the block if needed.
if ( m_selectionMode == wxGrid::wxGridSelectRows ) switch ( m_selectionMode )
{ {
default:
wxFAIL_MSG( "unknown selection mode" );
// fall through
case wxGrid::wxGridSelectCells:
// nothing to do -- in this mode arbitrary blocks can be selected
break;
case wxGrid::wxGridSelectRows:
leftCol = 0; leftCol = 0;
rightCol = m_grid->GetNumberCols() - 1; rightCol = m_grid->GetNumberCols() - 1;
} break;
else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
{ case wxGrid::wxGridSelectColumns:
topRow = 0; topRow = 0;
bottomRow = m_grid->GetNumberRows() - 1; bottomRow = m_grid->GetNumberRows() - 1;
break;
case wxGrid::wxGridSelectRowsOrColumns:
// block selection doesn't make sense for this mode, we could only
// select the entire grid but this wouldn't be useful
return;
} }
if ( topRow > bottomRow ) if ( topRow > bottomRow )