- 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,

File diff suppressed because it is too large Load Diff

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 )
{ {
leftCol = 0; default:
rightCol = m_grid->GetNumberCols() - 1; wxFAIL_MSG( "unknown selection mode" );
} // fall through
else if ( m_selectionMode == wxGrid::wxGridSelectColumns )
{ case wxGrid::wxGridSelectCells:
topRow = 0; // nothing to do -- in this mode arbitrary blocks can be selected
bottomRow = m_grid->GetNumberRows() - 1; break;
case wxGrid::wxGridSelectRows:
leftCol = 0;
rightCol = m_grid->GetNumberCols() - 1;
break;
case wxGrid::wxGridSelectColumns:
topRow = 0;
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 )