Add support for rearranging wxGrid rows order interactively
Add EnableDragRowMove() function and wxEVT_GRID_ROW_MOVE, similarly to the existing column function and event. Closes #22260.
This commit is contained in:
committed by
Vadim Zeitlin
parent
c39c392bbb
commit
3719ab3725
@@ -1899,6 +1899,11 @@ public:
|
||||
bool CanDragColSize(int col) const
|
||||
{ return m_canDragColSize && DoCanResizeLine(col, m_setFixedCols); }
|
||||
|
||||
// interactive row reordering (disabled by default)
|
||||
bool EnableDragRowMove( bool enable = true );
|
||||
void DisableDragRowMove() { EnableDragRowMove( false ); }
|
||||
bool CanDragRowMove() const { return m_canDragRowMove; }
|
||||
|
||||
// interactive column reordering (disabled by default)
|
||||
bool EnableDragColMove( bool enable = true );
|
||||
void DisableDragColMove() { EnableDragColMove( false ); }
|
||||
@@ -2053,33 +2058,60 @@ public:
|
||||
void SetRowSizes(const wxGridSizesInfo& sizeInfo);
|
||||
|
||||
|
||||
// ------- columns (only, for now) reordering
|
||||
// ------- rows and columns reordering
|
||||
|
||||
// columns index <-> positions mapping: by default, the position of the
|
||||
// column is the same as its index, but the columns can also be reordered
|
||||
// (either by calling SetColPos() explicitly or by the user dragging the
|
||||
// columns around) in which case their indices don't correspond to their
|
||||
// rows and columns index <-> positions mapping: by default, the position
|
||||
// is the same as its index, but they can also be reordered
|
||||
// (either by calling SetRowPos()/SetColPos() explicitly or by the user
|
||||
// dragging around) in which case their indices don't correspond to their
|
||||
// positions on display any longer
|
||||
//
|
||||
// internally we always work with indices except for the functions which
|
||||
// have "Pos" in their names (and which work with columns, not pixels) and
|
||||
// only the display and hit testing code really cares about display
|
||||
// positions at all
|
||||
// have "Pos" in their names (and which work with rows and columns, not
|
||||
// pixels) and only the display and hit testing code really cares about
|
||||
// display positions at all
|
||||
|
||||
// set the positions of all columns at once (this method uses the same
|
||||
// conventions as wxHeaderCtrl::SetColumnsOrder() for the order array)
|
||||
// set the positions of all rows or columns at once (this method uses the
|
||||
// same conventions as wxHeaderCtrl::SetColumnsOrder() for the order array)
|
||||
void SetRowsOrder(const wxArrayInt& order);
|
||||
void SetColumnsOrder(const wxArrayInt& order);
|
||||
|
||||
// return the row index corresponding to the given (valid) position
|
||||
int GetRowAt(int pos) const
|
||||
{
|
||||
return m_rowAt.empty() ? pos : m_rowAt[pos];
|
||||
}
|
||||
|
||||
// return the column index corresponding to the given (valid) position
|
||||
int GetColAt(int pos) const
|
||||
{
|
||||
return m_colAt.empty() ? pos : m_colAt[pos];
|
||||
}
|
||||
|
||||
// reorder the rows so that the row with the given index is now shown
|
||||
// as the position pos
|
||||
void SetRowPos(int idx, int pos);
|
||||
|
||||
// reorder the columns so that the column with the given index is now shown
|
||||
// as the position pos
|
||||
void SetColPos(int idx, int pos);
|
||||
|
||||
// return the position at which the row with the given index is
|
||||
// displayed: notice that this is a slow operation as we don't maintain the
|
||||
// reverse mapping currently
|
||||
int GetRowPos(int idx) const
|
||||
{
|
||||
wxASSERT_MSG( idx >= 0 && idx < m_numRows, "invalid row index" );
|
||||
|
||||
if ( m_rowAt.IsEmpty() )
|
||||
return idx;
|
||||
|
||||
int pos = m_rowAt.Index(idx);
|
||||
wxASSERT_MSG( pos != wxNOT_FOUND, "invalid row index" );
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// return the position at which the column with the given index is
|
||||
// displayed: notice that this is a slow operation as we don't maintain the
|
||||
// reverse mapping currently
|
||||
@@ -2096,7 +2128,8 @@ public:
|
||||
return pos;
|
||||
}
|
||||
|
||||
// reset the columns positions to the default order
|
||||
// reset the rows or columns positions to the default order
|
||||
void ResetRowPos();
|
||||
void ResetColPos();
|
||||
|
||||
|
||||
@@ -2718,6 +2751,7 @@ protected:
|
||||
WXGRID_CURSOR_RESIZE_COL,
|
||||
WXGRID_CURSOR_SELECT_ROW,
|
||||
WXGRID_CURSOR_SELECT_COL,
|
||||
WXGRID_CURSOR_MOVE_ROW,
|
||||
WXGRID_CURSOR_MOVE_COL
|
||||
};
|
||||
|
||||
@@ -2744,18 +2778,23 @@ protected:
|
||||
CursorMode m_cursorMode;
|
||||
|
||||
|
||||
//Row positions
|
||||
wxArrayInt m_rowAt;
|
||||
|
||||
//Column positions
|
||||
wxArrayInt m_colAt;
|
||||
|
||||
bool m_canDragRowSize;
|
||||
bool m_canDragColSize;
|
||||
bool m_canDragRowMove;
|
||||
bool m_canDragColMove;
|
||||
bool m_canHideColumns;
|
||||
bool m_canDragGridSize;
|
||||
bool m_canDragCell;
|
||||
|
||||
// Index of the column being drag-moved or -1 if there is no move operation
|
||||
// in progress.
|
||||
// Index of the row or column being drag-moved or -1 if there is no move
|
||||
// operation in progress.
|
||||
int m_dragMoveRow;
|
||||
int m_dragMoveCol;
|
||||
|
||||
// Last horizontal mouse position while drag-moving a column.
|
||||
@@ -2908,8 +2947,9 @@ private:
|
||||
// the sorting indicator to effectively show
|
||||
void UpdateColumnSortingIndicator(int col);
|
||||
|
||||
// update the grid after changing the columns order (common part of
|
||||
// SetColPos() and ResetColPos())
|
||||
// update the grid after changing the rows or columns order (common part
|
||||
// of Set{Row,Col}Pos() and Reset{Row,Col}Pos())
|
||||
void RefreshAfterRowPosChange();
|
||||
void RefreshAfterColPosChange();
|
||||
|
||||
// reset the variables used during dragging operations after it ended,
|
||||
@@ -2927,11 +2967,12 @@ private:
|
||||
}
|
||||
|
||||
|
||||
// return the position (not index) of the column at the given logical pixel
|
||||
// position
|
||||
// return the position (not index) of the row or column at the given logical
|
||||
// pixel position
|
||||
//
|
||||
// this always returns a valid position, even if the coordinate is out of
|
||||
// bounds (in which case first/last column is returned)
|
||||
// bounds (in which case first/last row/column is returned)
|
||||
int YToPos(int y, wxGridWindow *gridWindow) const;
|
||||
int XToPos(int x, wxGridWindow *gridWindow) const;
|
||||
|
||||
// event handlers and their helpers
|
||||
@@ -2989,12 +3030,14 @@ private:
|
||||
void DoColHeaderClick(int col);
|
||||
|
||||
void DoStartResizeRowOrCol(int col);
|
||||
void DoStartMoveRow(int col);
|
||||
void DoStartMoveCol(int col);
|
||||
|
||||
// These functions should only be called when actually resizing/moving,
|
||||
// i.e. m_dragRowOrCol and m_dragMoveCol, respectively, are valid.
|
||||
void DoEndDragResizeRow(const wxMouseEvent& event, wxGridWindow *gridWindow);
|
||||
void DoEndDragResizeCol(const wxMouseEvent& event, wxGridWindow *gridWindow);
|
||||
void DoEndMoveRow(int pos);
|
||||
void DoEndMoveCol(int pos);
|
||||
|
||||
// Helper function returning the position (only the horizontal component
|
||||
@@ -3426,6 +3469,7 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_EDITOR_SHOWN, wxGridEvent
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_EDITOR_HIDDEN, wxGridEvent );
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_EDITOR_CREATED, wxGridEditorCreatedEvent );
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_CELL_BEGIN_DRAG, wxGridEvent );
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_ROW_MOVE, wxGridEvent );
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_COL_MOVE, wxGridEvent );
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_COL_SORT, wxGridEvent );
|
||||
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_GRID_TABBING, wxGridEvent );
|
||||
@@ -3470,6 +3514,7 @@ typedef void (wxEvtHandler::*wxGridEditorCreatedEventFunction)(wxGridEditorCreat
|
||||
#define EVT_GRID_CMD_ROW_SIZE(id, fn) wx__DECLARE_GRIDSIZEEVT(ROW_SIZE, id, fn)
|
||||
#define EVT_GRID_CMD_COL_SIZE(id, fn) wx__DECLARE_GRIDSIZEEVT(COL_SIZE, id, fn)
|
||||
#define EVT_GRID_CMD_COL_AUTO_SIZE(id, fn) wx__DECLARE_GRIDSIZEEVT(COL_AUTO_SIZE, id, fn)
|
||||
#define EVT_GRID_CMD_ROW_MOVE(id, fn) wx__DECLARE_GRIDEVT(ROW_MOVE, id, fn)
|
||||
#define EVT_GRID_CMD_COL_MOVE(id, fn) wx__DECLARE_GRIDEVT(COL_MOVE, id, fn)
|
||||
#define EVT_GRID_CMD_COL_SORT(id, fn) wx__DECLARE_GRIDEVT(COL_SORT, id, fn)
|
||||
#define EVT_GRID_CMD_RANGE_SELECTING(id, fn) wx__DECLARE_GRIDRANGESELEVT(RANGE_SELECTING, id, fn)
|
||||
@@ -3496,6 +3541,7 @@ typedef void (wxEvtHandler::*wxGridEditorCreatedEventFunction)(wxGridEditorCreat
|
||||
#define EVT_GRID_ROW_SIZE(fn) EVT_GRID_CMD_ROW_SIZE(wxID_ANY, fn)
|
||||
#define EVT_GRID_COL_SIZE(fn) EVT_GRID_CMD_COL_SIZE(wxID_ANY, fn)
|
||||
#define EVT_GRID_COL_AUTO_SIZE(fn) EVT_GRID_CMD_COL_AUTO_SIZE(wxID_ANY, fn)
|
||||
#define EVT_GRID_ROW_MOVE(fn) EVT_GRID_CMD_ROW_MOVE(wxID_ANY, fn)
|
||||
#define EVT_GRID_COL_MOVE(fn) EVT_GRID_CMD_COL_MOVE(wxID_ANY, fn)
|
||||
#define EVT_GRID_COL_SORT(fn) EVT_GRID_CMD_COL_SORT(wxID_ANY, fn)
|
||||
#define EVT_GRID_RANGE_SELECTING(fn) EVT_GRID_CMD_RANGE_SELECTING(wxID_ANY, fn)
|
||||
|
||||
@@ -572,14 +572,9 @@ public:
|
||||
|
||||
|
||||
// Return the index of the line at the given position
|
||||
//
|
||||
// NB: currently this is always identity for the rows as reordering is only
|
||||
// implemented for the lines
|
||||
virtual int GetLineAt(const wxGrid *grid, int pos) const = 0;
|
||||
|
||||
// Return the display position of the line with the given index.
|
||||
//
|
||||
// NB: As GetLineAt(), currently this is always identity for rows.
|
||||
virtual int GetLinePos(const wxGrid *grid, int line) const = 0;
|
||||
|
||||
// Return the index of the line just before the given one or wxNOT_FOUND.
|
||||
@@ -663,13 +658,16 @@ public:
|
||||
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const wxOVERRIDE
|
||||
{ grid->SetDefaultRowSize(size, resizeExisting); }
|
||||
|
||||
virtual int GetLineAt(const wxGrid * WXUNUSED(grid), int pos) const wxOVERRIDE
|
||||
{ return pos; } // TODO: implement row reordering
|
||||
virtual int GetLinePos(const wxGrid * WXUNUSED(grid), int line) const wxOVERRIDE
|
||||
{ return line; } // TODO: implement row reordering
|
||||
virtual int GetLineAt(const wxGrid *grid, int pos) const wxOVERRIDE
|
||||
{ return grid->GetRowAt(pos); }
|
||||
virtual int GetLinePos(const wxGrid *grid, int line) const wxOVERRIDE
|
||||
{ return grid->GetRowPos(line); }
|
||||
|
||||
virtual int GetLineBefore(const wxGrid* WXUNUSED(grid), int line) const wxOVERRIDE
|
||||
{ return line - 1; }
|
||||
virtual int GetLineBefore(const wxGrid *grid, int line) const wxOVERRIDE
|
||||
{
|
||||
int posBefore = grid->GetRowPos(line) - 1;
|
||||
return posBefore >= 0 ? grid->GetRowAt(posBefore) : wxNOT_FOUND;
|
||||
}
|
||||
|
||||
virtual wxWindow *GetHeaderWindow(wxGrid *grid) const wxOVERRIDE
|
||||
{ return grid->GetGridRowLabelWindow(); }
|
||||
|
||||
@@ -4480,8 +4480,9 @@ public:
|
||||
EnableDragGridSize() they can also be resized by dragging the right or
|
||||
bottom edge of the grid cells.
|
||||
|
||||
Columns can also be moved to interactively change their order but this
|
||||
needs to be explicitly enabled with EnableDragColMove().
|
||||
Columns and rows can also be moved to interactively change their order
|
||||
but this needs to be explicitly enabled with EnableDragColMove() and
|
||||
EnableDragColMove().
|
||||
*/
|
||||
//@{
|
||||
|
||||
@@ -4534,6 +4535,15 @@ public:
|
||||
*/
|
||||
bool CanDragGridSize() const;
|
||||
|
||||
/**
|
||||
Returns @true if rows can be moved by dragging with the mouse.
|
||||
|
||||
Rows can be moved by dragging on their labels.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
bool CanDragRowMove() const;
|
||||
|
||||
/**
|
||||
Returns @true if the given row can be resized by dragging with the
|
||||
mouse.
|
||||
@@ -4586,6 +4596,15 @@ public:
|
||||
*/
|
||||
void DisableDragColMove();
|
||||
|
||||
/**
|
||||
Disables row moving by dragging with the mouse.
|
||||
|
||||
Equivalent to passing @false to EnableDragRowMove().
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
void DisableDragRowMove();
|
||||
|
||||
/**
|
||||
Disables column sizing by dragging with the mouse.
|
||||
|
||||
@@ -4632,6 +4651,19 @@ public:
|
||||
*/
|
||||
bool EnableDragColMove(bool enable = true);
|
||||
|
||||
/**
|
||||
Enables or disables row moving by dragging with the mouse.
|
||||
|
||||
Note that reordering rows by dragging them is currently not
|
||||
supported when the grid has any frozen columns (see FreezeTo()) and if
|
||||
this method is called with @a enable equal to @true in this situation,
|
||||
it returns @false without doing anything. Otherwise it returns @true to
|
||||
indicate that it was successful.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
bool EnableDragRowMove(bool enable = true);
|
||||
|
||||
/**
|
||||
Enables or disables column sizing by dragging with the mouse.
|
||||
|
||||
@@ -4703,6 +4735,44 @@ public:
|
||||
*/
|
||||
void ResetColPos();
|
||||
|
||||
/**
|
||||
Returns the row ID of the specified row position.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
int GetRowAt(int rowPos) const;
|
||||
|
||||
/**
|
||||
Returns the position of the specified row.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
int GetRowPos(int rowID) const;
|
||||
|
||||
/**
|
||||
Sets the position of the specified row.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
void SetRowPos(int rowID, int newPos);
|
||||
|
||||
/**
|
||||
Sets the positions of all rows at once.
|
||||
|
||||
This method takes an array containing the indices of the rows in
|
||||
their display order.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
void SetRowsOrder(const wxArrayInt& order);
|
||||
|
||||
/**
|
||||
Resets the position of the rows to the default.
|
||||
|
||||
@since 3.1.7
|
||||
*/
|
||||
void ResetRowPos();
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
@@ -6187,6 +6257,19 @@ public:
|
||||
The given cell was made current, either by user or by the program via a
|
||||
call to SetGridCursor() or GoToCell(). Processes a
|
||||
@c wxEVT_GRID_SELECT_CELL event type.
|
||||
@event{EVT_GRID_ROW_MOVE(func)}
|
||||
The user tries to change the order of the rows in the grid by
|
||||
dragging the row specified by GetRow(). This event can be vetoed to
|
||||
either prevent the user from reordering the row change completely
|
||||
(but notice that if you don't want to allow it at all, you simply
|
||||
shouldn't call wxGrid::EnableDragRowMove() in the first place), vetoed
|
||||
but handled in some way in the handler, e.g. by really moving the
|
||||
row to the new position at the associated table level, or allowed to
|
||||
proceed in which case wxGrid::SetRowPos() is used to reorder the
|
||||
rows display order without affecting the use of the row indices
|
||||
otherwise.
|
||||
This event macro corresponds to @c wxEVT_GRID_ROW_MOVE event type.
|
||||
It is only available since wxWidgets 3.1.7.
|
||||
@event{EVT_GRID_COL_MOVE(func)}
|
||||
The user tries to change the order of the columns in the grid by
|
||||
dragging the column specified by GetCol(). This event can be vetoed to
|
||||
@@ -6582,6 +6665,7 @@ wxEventType wxEVT_GRID_EDITOR_SHOWN;
|
||||
wxEventType wxEVT_GRID_EDITOR_HIDDEN;
|
||||
wxEventType wxEVT_GRID_EDITOR_CREATED;
|
||||
wxEventType wxEVT_GRID_CELL_BEGIN_DRAG;
|
||||
wxEventType wxEVT_GRID_ROW_MOVE;
|
||||
wxEventType wxEVT_GRID_COL_MOVE;
|
||||
wxEventType wxEVT_GRID_COL_SORT;
|
||||
wxEventType wxEVT_GRID_TABBING;
|
||||
|
||||
@@ -281,6 +281,7 @@ wxBEGIN_EVENT_TABLE( GridFrame, wxFrame )
|
||||
EVT_MENU( ID_TOGGLEEDIT, GridFrame::ToggleEditing )
|
||||
EVT_MENU( ID_TOGGLEROWSIZING, GridFrame::ToggleRowSizing )
|
||||
EVT_MENU( ID_TOGGLECOLSIZING, GridFrame::ToggleColSizing )
|
||||
EVT_MENU( ID_TOGGLEROWMOVING, GridFrame::ToggleRowMoving)
|
||||
EVT_MENU( ID_TOGGLECOLMOVING, GridFrame::ToggleColMoving )
|
||||
EVT_MENU( ID_TOGGLECOLHIDING, GridFrame::ToggleColHiding )
|
||||
EVT_MENU( ID_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
|
||||
@@ -437,6 +438,7 @@ GridFrame::GridFrame()
|
||||
viewMenu->AppendCheckItem(ID_TOGGLEEDIT,"&Editable");
|
||||
viewMenu->AppendCheckItem(ID_TOGGLEROWSIZING, "Ro&w drag-resize");
|
||||
viewMenu->AppendCheckItem(ID_TOGGLECOLSIZING, "C&ol drag-resize");
|
||||
viewMenu->AppendCheckItem(ID_TOGGLEROWMOVING, "Row drag-move");
|
||||
viewMenu->AppendCheckItem(ID_TOGGLECOLMOVING, "Col drag-&move");
|
||||
viewMenu->AppendCheckItem(ID_TOGGLECOLHIDING, "Col hiding popup menu");
|
||||
viewMenu->AppendCheckItem(ID_TOGGLEGRIDSIZING, "&Grid drag-resize");
|
||||
@@ -865,6 +867,12 @@ void GridFrame::ToggleColSizing( wxCommandEvent& WXUNUSED(ev) )
|
||||
GetMenuBar()->IsChecked( ID_TOGGLECOLSIZING ) );
|
||||
}
|
||||
|
||||
void GridFrame::ToggleRowMoving( wxCommandEvent& WXUNUSED(ev) )
|
||||
{
|
||||
grid->EnableDragRowMove(
|
||||
GetMenuBar()->IsChecked( ID_TOGGLEROWMOVING ) );
|
||||
}
|
||||
|
||||
void GridFrame::ToggleColMoving( wxCommandEvent& WXUNUSED(ev) )
|
||||
{
|
||||
grid->EnableDragColMove(
|
||||
@@ -1717,9 +1725,12 @@ void GridFrame::OnSelectCell( wxGridEvent& ev )
|
||||
<< ", AltDown: "<< (ev.AltDown() ? 'T':'F')
|
||||
<< ", MetaDown: "<< (ev.MetaDown() ? 'T':'F') << " )";
|
||||
|
||||
//Indicate whether this row was moved
|
||||
if ( grid->GetRowPos( ev.GetRow() ) != ev.GetRow() )
|
||||
logBuf << " *** Row moved, current position: " << grid->GetRowPos( ev.GetRow() );
|
||||
//Indicate whether this column was moved
|
||||
if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
|
||||
logBuf << " *** Column moved, current position: " << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
|
||||
if ( grid->GetColPos( ev.GetCol() ) != ev.GetCol() )
|
||||
logBuf << " *** Column moved, current position: " << grid->GetColPos( ev.GetCol() );
|
||||
|
||||
wxLogMessage( "%s", logBuf );
|
||||
|
||||
@@ -2432,6 +2443,7 @@ private:
|
||||
Id_Check_UseNativeHeader,
|
||||
Id_Check_DrawNativeLabels,
|
||||
Id_Check_ShowRowLabels,
|
||||
Id_Check_EnableRowMove,
|
||||
Id_Check_EnableColMove
|
||||
};
|
||||
|
||||
@@ -2461,6 +2473,11 @@ private:
|
||||
: 0);
|
||||
}
|
||||
|
||||
void OnToggleRowMove(wxCommandEvent&)
|
||||
{
|
||||
m_grid->EnableDragRowMove(m_chkEnableRowMove->IsChecked());
|
||||
}
|
||||
|
||||
void OnToggleColMove(wxCommandEvent&)
|
||||
{
|
||||
m_grid->EnableDragColMove(m_chkEnableColMove->IsChecked());
|
||||
@@ -2474,7 +2491,7 @@ private:
|
||||
m_grid->SetColSize(col,
|
||||
event.GetId() == wxID_ADD ? wxGRID_AUTOSIZE : 0);
|
||||
|
||||
UpdateOrderAndVisibility();
|
||||
UpdateColOrderAndVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2487,14 +2504,14 @@ private:
|
||||
|
||||
m_grid->SetColPos(col, pos);
|
||||
|
||||
UpdateOrderAndVisibility();
|
||||
UpdateColOrderAndVisibility();
|
||||
}
|
||||
|
||||
void OnResetColumnOrder(wxCommandEvent&)
|
||||
{
|
||||
m_grid->ResetColPos();
|
||||
|
||||
UpdateOrderAndVisibility();
|
||||
UpdateColOrderAndVisibility();
|
||||
}
|
||||
|
||||
void OnGridColSort(wxGridEvent& event)
|
||||
@@ -2504,11 +2521,20 @@ private:
|
||||
m_grid->IsSortOrderAscending()));
|
||||
}
|
||||
|
||||
void OnGridRowMove(wxGridEvent& event)
|
||||
{
|
||||
// can't update it yet as the order hasn't been changed, so do it a bit
|
||||
// later
|
||||
m_shouldUpdateRowOrder = true;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void OnGridColMove(wxGridEvent& event)
|
||||
{
|
||||
// can't update it yet as the order hasn't been changed, so do it a bit
|
||||
// later
|
||||
m_shouldUpdateOrder = true;
|
||||
m_shouldUpdateColOrder = true;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
@@ -2518,23 +2544,29 @@ private:
|
||||
// we only catch this event to react to the user showing or hiding this
|
||||
// column using the header control menu and not because we're
|
||||
// interested in column resizing
|
||||
UpdateOrderAndVisibility();
|
||||
UpdateColOrderAndVisibility();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void OnIdle(wxIdleEvent& event)
|
||||
{
|
||||
if ( m_shouldUpdateOrder )
|
||||
if ( m_shouldUpdateColOrder )
|
||||
{
|
||||
m_shouldUpdateOrder = false;
|
||||
UpdateOrderAndVisibility();
|
||||
m_shouldUpdateColOrder = false;
|
||||
UpdateColOrderAndVisibility();
|
||||
}
|
||||
|
||||
if ( m_shouldUpdateRowOrder )
|
||||
{
|
||||
m_shouldUpdateRowOrder = false;
|
||||
UpdateRowOrderAndVisibility();
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void UpdateOrderAndVisibility()
|
||||
void UpdateColOrderAndVisibility()
|
||||
{
|
||||
wxString s;
|
||||
for ( int pos = 0; pos < TabularGridTable::COL_MAX; pos++ )
|
||||
@@ -2554,12 +2586,33 @@ private:
|
||||
m_statOrder->SetLabel(s);
|
||||
}
|
||||
|
||||
void UpdateRowOrderAndVisibility()
|
||||
{
|
||||
wxString s;
|
||||
for ( int pos = 0; pos < TabularGridTable::ROW_MAX; pos++ )
|
||||
{
|
||||
const int row = m_grid->GetRowAt(pos);
|
||||
const bool isHidden = m_grid->GetRowSize(row) == 0;
|
||||
|
||||
if ( isHidden )
|
||||
s << '[';
|
||||
s << row;
|
||||
if ( isHidden )
|
||||
s << ']';
|
||||
|
||||
s << ' ';
|
||||
}
|
||||
|
||||
m_statOrder->SetLabel(s);
|
||||
}
|
||||
|
||||
// controls
|
||||
wxGrid *m_grid;
|
||||
TabularGridTable *m_table;
|
||||
wxCheckBox *m_chkUseNative,
|
||||
*m_chkDrawNative,
|
||||
*m_chkShowRowLabels,
|
||||
*m_chkEnableRowMove,
|
||||
*m_chkEnableColMove;
|
||||
|
||||
ColIndexEntry *m_txtColIndex,
|
||||
@@ -2569,7 +2622,8 @@ private:
|
||||
wxStaticText *m_statOrder;
|
||||
|
||||
// fla for EVT_IDLE handler
|
||||
bool m_shouldUpdateOrder;
|
||||
bool m_shouldUpdateRowOrder,
|
||||
m_shouldUpdateColOrder;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TabularGridFrame);
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
@@ -2594,6 +2648,7 @@ wxBEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
|
||||
EVT_BUTTON(wxID_DELETE, TabularGridFrame::OnShowHideColumn)
|
||||
|
||||
EVT_GRID_COL_SORT(TabularGridFrame::OnGridColSort)
|
||||
EVT_GRID_ROW_MOVE(TabularGridFrame::OnGridRowMove)
|
||||
EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
|
||||
EVT_GRID_COL_SIZE(TabularGridFrame::OnGridColSize)
|
||||
|
||||
@@ -2603,7 +2658,7 @@ wxEND_EVENT_TABLE()
|
||||
TabularGridFrame::TabularGridFrame()
|
||||
: wxFrame(NULL, wxID_ANY, "Tabular table")
|
||||
{
|
||||
m_shouldUpdateOrder = false;
|
||||
m_shouldUpdateColOrder = false;
|
||||
|
||||
wxPanel * const panel = new wxPanel(this);
|
||||
|
||||
@@ -2614,6 +2669,7 @@ TabularGridFrame::TabularGridFrame()
|
||||
wxBORDER_STATIC | wxWANTS_CHARS);
|
||||
m_grid->AssignTable(m_table, wxGrid::wxGridSelectRows);
|
||||
|
||||
m_grid->EnableDragRowMove();
|
||||
m_grid->EnableDragColMove();
|
||||
m_grid->UseNativeColHeader();
|
||||
m_grid->HideRowLabels();
|
||||
@@ -2638,6 +2694,12 @@ TabularGridFrame::TabularGridFrame()
|
||||
"Show &row labels");
|
||||
sizerStyles->Add(m_chkShowRowLabels, wxSizerFlags().Border());
|
||||
|
||||
m_chkEnableRowMove = new wxCheckBox(panel, Id_Check_EnableRowMove,
|
||||
"Allow row reordering");
|
||||
m_chkEnableRowMove->SetValue(true);
|
||||
sizerStyles->Add(m_chkEnableRowMove, wxSizerFlags().Border());
|
||||
sizerControls->Add(sizerStyles);
|
||||
|
||||
m_chkEnableColMove = new wxCheckBox(panel, Id_Check_EnableColMove,
|
||||
"Allow column re&ordering");
|
||||
m_chkEnableColMove->SetValue(true);
|
||||
|
||||
@@ -35,6 +35,7 @@ class GridFrame : public wxFrame
|
||||
void ToggleEditing( wxCommandEvent& );
|
||||
void ToggleRowSizing( wxCommandEvent& );
|
||||
void ToggleColSizing( wxCommandEvent& );
|
||||
void ToggleRowMoving( wxCommandEvent& );
|
||||
void ToggleColMoving( wxCommandEvent& );
|
||||
void ToggleColHiding( wxCommandEvent& );
|
||||
void ToggleGridSizing( wxCommandEvent& );
|
||||
@@ -148,6 +149,7 @@ public:
|
||||
ID_TOGGLEEDIT,
|
||||
ID_TOGGLEROWSIZING,
|
||||
ID_TOGGLECOLSIZING,
|
||||
ID_TOGGLEROWMOVING,
|
||||
ID_TOGGLECOLMOVING,
|
||||
ID_TOGGLECOLHIDING,
|
||||
ID_TOGGLEGRIDSIZING,
|
||||
|
||||
@@ -141,6 +141,7 @@ wxDEFINE_EVENT( wxEVT_GRID_LABEL_RIGHT_DCLICK, wxGridEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_ROW_SIZE, wxGridSizeEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_COL_SIZE, wxGridSizeEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_COL_AUTO_SIZE, wxGridSizeEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_ROW_MOVE, wxGridEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_COL_MOVE, wxGridEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_COL_SORT, wxGridEvent );
|
||||
wxDEFINE_EVENT( wxEVT_GRID_RANGE_SELECTING, wxGridRangeSelectEvent );
|
||||
@@ -3019,6 +3020,7 @@ void wxGrid::Init()
|
||||
|
||||
m_gridFrozenBorderPenWidth = 2;
|
||||
|
||||
m_canDragRowMove = false;
|
||||
m_canDragColMove = false;
|
||||
m_canHideColumns = true;
|
||||
|
||||
@@ -3028,6 +3030,7 @@ void wxGrid::Init()
|
||||
m_canDragColSize = true;
|
||||
m_canDragGridSize = true;
|
||||
m_canDragCell = false;
|
||||
m_dragMoveRow = -1;
|
||||
m_dragMoveCol = -1;
|
||||
m_dragLastPos = -1;
|
||||
m_dragRowOrCol = -1;
|
||||
@@ -3087,10 +3090,9 @@ void wxGrid::InitRowHeights()
|
||||
|
||||
m_rowHeights.Add( m_defaultRowHeight, m_numRows );
|
||||
|
||||
int rowBottom = 0;
|
||||
for ( int i = 0; i < m_numRows; i++ )
|
||||
{
|
||||
rowBottom += m_defaultRowHeight;
|
||||
int rowBottom = ( GetRowPos( i ) + 1 ) * m_defaultRowHeight;;
|
||||
m_rowBottoms.Add( rowBottom );
|
||||
}
|
||||
}
|
||||
@@ -3148,14 +3150,14 @@ int wxGrid::GetRowHeight(int row) const
|
||||
int wxGrid::GetRowTop(int row) const
|
||||
{
|
||||
if ( m_rowBottoms.IsEmpty() )
|
||||
return row * m_defaultRowHeight;
|
||||
return GetRowPos( row ) * m_defaultRowHeight;
|
||||
|
||||
return m_rowBottoms[row] - GetRowHeight(row);
|
||||
}
|
||||
|
||||
int wxGrid::GetRowBottom(int row) const
|
||||
{
|
||||
return m_rowBottoms.IsEmpty() ? (row + 1) * m_defaultRowHeight
|
||||
return m_rowBottoms.IsEmpty() ? (GetRowPos( row ) + 1) * m_defaultRowHeight
|
||||
: m_rowBottoms[row];
|
||||
}
|
||||
|
||||
@@ -3297,9 +3299,27 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
{
|
||||
size_t pos = msg.GetCommandInt();
|
||||
int numRows = msg.GetCommandInt2();
|
||||
|
||||
m_numRows += numRows;
|
||||
|
||||
if ( !m_rowAt.IsEmpty() )
|
||||
{
|
||||
//Shift the row IDs
|
||||
for ( i = 0; i < m_numRows - numRows; i++ )
|
||||
{
|
||||
if ( m_rowAt[i] >= (int)pos )
|
||||
m_rowAt[i] += numRows;
|
||||
}
|
||||
|
||||
m_rowAt.Insert( pos, pos, numRows );
|
||||
|
||||
//Set the new rows' positions
|
||||
for ( i = pos + 1; i < (int)pos + numRows; i++ )
|
||||
{
|
||||
m_rowAt[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( !m_rowHeights.IsEmpty() )
|
||||
{
|
||||
m_rowHeights.Insert( m_defaultRowHeight, pos, numRows );
|
||||
@@ -3307,10 +3327,13 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
|
||||
int bottom = 0;
|
||||
if ( pos > 0 )
|
||||
bottom = m_rowBottoms[pos - 1];
|
||||
bottom = m_rowBottoms[GetRowAt( pos - 1 )];
|
||||
|
||||
for ( i = pos; i < m_numRows; i++ )
|
||||
int rowPos;
|
||||
for ( rowPos = pos; rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
i = GetRowAt( rowPos );
|
||||
|
||||
bottom += GetRowHeight(i);
|
||||
m_rowBottoms[i] = bottom;
|
||||
}
|
||||
@@ -3338,6 +3361,17 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
int oldNumRows = m_numRows;
|
||||
m_numRows += numRows;
|
||||
|
||||
if ( !m_rowAt.IsEmpty() )
|
||||
{
|
||||
m_rowAt.Add( 0, numRows );
|
||||
|
||||
//Set the new rows' positions
|
||||
for ( i = oldNumRows; i < m_numRows; i++ )
|
||||
{
|
||||
m_rowAt[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_rowHeights.IsEmpty() )
|
||||
{
|
||||
m_rowHeights.Add( m_defaultRowHeight, numRows );
|
||||
@@ -3347,8 +3381,11 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
if ( oldNumRows > 0 )
|
||||
bottom = m_rowBottoms[oldNumRows - 1];
|
||||
|
||||
for ( i = oldNumRows; i < m_numRows; i++ )
|
||||
int rowPos;
|
||||
for ( rowPos = oldNumRows; rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
i = GetRowAt( rowPos );
|
||||
|
||||
bottom += GetRowHeight(i);
|
||||
m_rowBottoms[i] = bottom;
|
||||
}
|
||||
@@ -3370,14 +3407,32 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
int numRows = msg.GetCommandInt2();
|
||||
m_numRows -= numRows;
|
||||
|
||||
if ( !m_rowAt.IsEmpty() )
|
||||
{
|
||||
int rowID = GetRowAt( pos );
|
||||
|
||||
m_rowAt.RemoveAt( pos, numRows );
|
||||
|
||||
//Shift the row IDs
|
||||
int rowPos;
|
||||
for ( rowPos = 0; rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
if ( m_rowAt[rowPos] > rowID )
|
||||
m_rowAt[rowPos] -= numRows;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_rowHeights.IsEmpty() )
|
||||
{
|
||||
m_rowHeights.RemoveAt( pos, numRows );
|
||||
m_rowBottoms.RemoveAt( pos, numRows );
|
||||
|
||||
int h = 0;
|
||||
for ( i = 0; i < m_numRows; i++ )
|
||||
int rowPos;
|
||||
for ( rowPos = 0; rowPos < m_numCols; rowPos++ )
|
||||
{
|
||||
i = GetRowAt( rowPos );
|
||||
|
||||
h += GetRowHeight(i);
|
||||
m_rowBottoms[i] = h;
|
||||
}
|
||||
@@ -3637,9 +3692,12 @@ wxArrayInt wxGrid::CalcRowLabelsExposed( const wxRegion& reg, wxGridWindow *grid
|
||||
|
||||
// find the row labels within these bounds
|
||||
//
|
||||
int row;
|
||||
for ( row = internalYToRow(top, gridWindow); row < m_numRows; row++ )
|
||||
int rowPos = GetRowPos( internalYToRow(top, gridWindow) );
|
||||
for ( ; rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
int row;
|
||||
row = GetRowAt( rowPos );
|
||||
|
||||
if ( GetRowBottom(row) < top )
|
||||
continue;
|
||||
|
||||
@@ -3751,9 +3809,13 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg,
|
||||
CalcGridWindowUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom, gridWindow );
|
||||
|
||||
// find the cells within these bounds
|
||||
//
|
||||
wxArrayInt cols;
|
||||
for ( int row = internalYToRow(top, gridWindow); row < m_numRows; row++ )
|
||||
int rowPos = GetRowPos( internalYToRow(top, gridWindow) );
|
||||
for ( ; rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
const int row = GetRowAt( rowPos );
|
||||
|
||||
if ( GetRowBottom(row) <= top )
|
||||
continue;
|
||||
|
||||
@@ -3799,6 +3861,7 @@ void wxGrid::PrepareDCFor(wxDC &dc, wxGridWindow *gridWindow)
|
||||
|
||||
void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindow* rowLabelWin )
|
||||
{
|
||||
int y;
|
||||
wxGridWindow *gridWindow = rowLabelWin->IsFrozen() ? m_frozenRowGridWin : m_gridWin;
|
||||
|
||||
event.SetPosition(event.GetPosition() + GetGridWindowOffset(gridWindow));
|
||||
@@ -3807,14 +3870,19 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
if ( rowLabelWin->IsFrozen() && event.GetPosition().y > rowLabelWin->GetClientSize().y )
|
||||
gridWindow = m_gridWin;
|
||||
|
||||
wxPoint pos = CalcGridWindowUnscrolledPosition(event.GetPosition(), gridWindow);
|
||||
int row;
|
||||
CalcGridWindowUnscrolledPosition(0, event.GetPosition().y, NULL, &y, gridWindow);
|
||||
int row = YToRow( y );
|
||||
|
||||
if ( event.Dragging() )
|
||||
{
|
||||
if (!m_isDragging)
|
||||
{
|
||||
m_isDragging = true;
|
||||
|
||||
if ( m_cursorMode == WXGRID_CURSOR_MOVE_ROW && row != -1 )
|
||||
DoStartMoveRow(row);
|
||||
}
|
||||
|
||||
if ( event.LeftIsDown() )
|
||||
{
|
||||
switch ( m_cursorMode )
|
||||
@@ -3832,7 +3900,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
if ( !m_selection->IsInSelection(m_currentCellCoords) )
|
||||
break;
|
||||
|
||||
if ( (row = YToRow( pos.y )) >= 0 )
|
||||
if ( row >= 0 )
|
||||
{
|
||||
m_selection->ExtendCurrentBlock(
|
||||
wxGridCellCoords(m_currentCellCoords.GetRow(), 0),
|
||||
@@ -3842,6 +3910,60 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
}
|
||||
break;
|
||||
|
||||
case WXGRID_CURSOR_MOVE_ROW:
|
||||
{
|
||||
int posNew = YToPos(y, NULL);
|
||||
int rowNew = GetRowAt(posNew);
|
||||
|
||||
// determine the position of the drop marker
|
||||
int markerY;
|
||||
if ( y >= GetRowTop(rowNew) + (GetRowHeight(rowNew) / 2) )
|
||||
markerY = GetRowBottom(rowNew);
|
||||
else
|
||||
markerY = GetRowTop(rowNew);
|
||||
|
||||
if ( markerY != m_dragLastPos )
|
||||
{
|
||||
wxClientDC dc( m_rowLabelWin );
|
||||
DoPrepareDC(dc);
|
||||
|
||||
int cw, ch;
|
||||
m_rowLabelWin->GetClientSize( &cw, &ch );
|
||||
|
||||
markerY++;
|
||||
|
||||
//Clean up the last indicator
|
||||
if ( m_dragLastPos >= 0 )
|
||||
{
|
||||
wxPen pen( m_rowLabelWin->GetBackgroundColour(), 2 );
|
||||
dc.SetPen(pen);
|
||||
dc.DrawLine( 0, m_dragLastPos + 1, cw, m_dragLastPos + 1 );
|
||||
dc.SetPen(wxNullPen);
|
||||
|
||||
if ( YToRow( m_dragLastPos ) != -1 )
|
||||
DrawRowLabel( dc, YToRow( m_dragLastPos ) );
|
||||
}
|
||||
|
||||
const wxColour *color;
|
||||
//Moving to the same place? Don't draw a marker
|
||||
if ( rowNew == m_dragMoveRow )
|
||||
color = wxLIGHT_GREY;
|
||||
else
|
||||
color = wxBLUE;
|
||||
|
||||
//Draw the marker
|
||||
wxPen pen( *color, 2 );
|
||||
dc.SetPen(pen);
|
||||
|
||||
dc.DrawLine( 0, markerY, cw, markerY );
|
||||
|
||||
dc.SetPen(wxNullPen);
|
||||
|
||||
m_dragLastPos = markerY - 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// default label to suppress warnings about "enumeration value
|
||||
// 'xxx' not handled in switch
|
||||
default:
|
||||
@@ -3865,7 +3987,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
//
|
||||
else if ( event.LeftDown() )
|
||||
{
|
||||
row = YToEdgeOfRow(pos.y);
|
||||
row = YToEdgeOfRow(y);
|
||||
if ( row != wxNOT_FOUND && CanDragRowSize(row) )
|
||||
{
|
||||
DoStartResizeRowOrCol(row);
|
||||
@@ -3873,9 +3995,23 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
}
|
||||
else // not a request to start resizing
|
||||
{
|
||||
row = YToRow(pos.y);
|
||||
row = YToRow(y);
|
||||
if ( row >= 0 &&
|
||||
SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, row, -1, event ) == Event_Unhandled )
|
||||
{
|
||||
if ( m_canDragRowMove )
|
||||
{
|
||||
//Show button as pressed
|
||||
wxClientDC dc( m_rowLabelWin );
|
||||
int rowTop = GetRowTop( row );
|
||||
int rowBottom = GetRowBottom( row ) - 1;
|
||||
dc.SetPen( wxPen( m_rowLabelWin->GetBackgroundColour(), 1 ) );
|
||||
dc.DrawLine( 1, rowTop, m_rowLabelWidth-1, rowTop );
|
||||
dc.DrawLine( 1, rowTop, 1, rowBottom );
|
||||
|
||||
ChangeCursorMode(WXGRID_CURSOR_MOVE_ROW, m_rowLabelWin);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if row selection is possible and allowed, before doing
|
||||
// anything else, including changing the cursor mode to "select
|
||||
@@ -3929,12 +4065,13 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------ Left double click
|
||||
//
|
||||
else if (event.LeftDClick() )
|
||||
{
|
||||
row = YToEdgeOfRow(pos.y);
|
||||
row = YToEdgeOfRow(y);
|
||||
if ( row != wxNOT_FOUND && CanDragRowSize(row) )
|
||||
{
|
||||
// adjust row height depending on label text
|
||||
@@ -3949,7 +4086,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
}
|
||||
else // not on row separator or it's not resizable
|
||||
{
|
||||
row = YToRow(pos.y);
|
||||
row = YToRow(y);
|
||||
if ( row >=0 &&
|
||||
SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, row, -1, event ) == Event_Unhandled )
|
||||
{
|
||||
@@ -3962,8 +4099,56 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
//
|
||||
else if ( event.LeftUp() )
|
||||
{
|
||||
if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
|
||||
switch ( m_cursorMode )
|
||||
{
|
||||
case WXGRID_CURSOR_RESIZE_ROW:
|
||||
DoEndDragResizeRow(event, gridWindow);
|
||||
break;
|
||||
|
||||
case WXGRID_CURSOR_MOVE_ROW:
|
||||
if ( m_dragLastPos == -1 || row == m_dragMoveRow )
|
||||
{
|
||||
// the row didn't actually move anywhere
|
||||
m_rowLabelWin->Refresh(); // "unpress" the row
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the position of the row we're over
|
||||
int pos = YToPos(y, NULL);
|
||||
|
||||
// insert the row being dragged either before or after
|
||||
// it, depending on where exactly it was dropped, so
|
||||
// find the index of the row we're over: notice
|
||||
// that the existing "row" variable may be invalid but
|
||||
// we need a valid one here
|
||||
const int rowValid = GetRowAt(pos);
|
||||
|
||||
// and check if we're on the "near" (left) part of the row
|
||||
const int middle = GetRowTop(rowValid) +
|
||||
GetRowHeight(rowValid)/2;
|
||||
const bool onNearPart = (y <= middle);
|
||||
|
||||
// adjust for the row being dragged itself
|
||||
if ( pos < GetRowPos(m_dragMoveRow) )
|
||||
pos++;
|
||||
|
||||
// and if it's on the near part of the target row,
|
||||
// insert it before it, not after
|
||||
if ( onNearPart )
|
||||
pos--;
|
||||
|
||||
DoEndMoveRow(pos);
|
||||
}
|
||||
break;
|
||||
|
||||
case WXGRID_CURSOR_SELECT_ROW:
|
||||
case WXGRID_CURSOR_SELECT_CELL:
|
||||
case WXGRID_CURSOR_RESIZE_COL:
|
||||
case WXGRID_CURSOR_SELECT_COL:
|
||||
case WXGRID_CURSOR_MOVE_COL:
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, rowLabelWin);
|
||||
m_dragLastPos = -1;
|
||||
@@ -3974,7 +4159,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
//
|
||||
else if ( event.RightDown() )
|
||||
{
|
||||
row = YToRow(pos.y);
|
||||
row = YToRow(y);
|
||||
if ( row < 0 ||
|
||||
SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, row, -1, event ) == Event_Unhandled )
|
||||
{
|
||||
@@ -3987,7 +4172,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
//
|
||||
else if ( event.RightDClick() )
|
||||
{
|
||||
row = YToRow(pos.y);
|
||||
row = YToRow(y);
|
||||
if ( row < 0 ||
|
||||
SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, row, -1, event ) == Event_Unhandled )
|
||||
{
|
||||
@@ -4000,7 +4185,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
//
|
||||
else if ( event.Moving() )
|
||||
{
|
||||
const int dragRowOrCol = YToEdgeOfRow( pos.y );
|
||||
const int dragRowOrCol = YToEdgeOfRow( y );
|
||||
if ( dragRowOrCol != wxNOT_FOUND )
|
||||
{
|
||||
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
|
||||
@@ -4408,11 +4593,15 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event, wxGridColLabelWindo
|
||||
|
||||
case WXGRID_CURSOR_SELECT_COL:
|
||||
case WXGRID_CURSOR_SELECT_CELL:
|
||||
case WXGRID_CURSOR_RESIZE_ROW:
|
||||
case WXGRID_CURSOR_SELECT_ROW:
|
||||
if ( col != -1 )
|
||||
DoColHeaderClick(col);
|
||||
break;
|
||||
|
||||
case WXGRID_CURSOR_RESIZE_ROW:
|
||||
case WXGRID_CURSOR_SELECT_ROW:
|
||||
case WXGRID_CURSOR_MOVE_ROW:
|
||||
// nothing to do, will not happen anyway
|
||||
break;
|
||||
}
|
||||
|
||||
ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
|
||||
@@ -4570,6 +4759,7 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
|
||||
wxT("RESIZE_COL"),
|
||||
wxT("SELECT_ROW"),
|
||||
wxT("SELECT_COL"),
|
||||
wxT("MOVE_ROW"),
|
||||
wxT("MOVE_COL"),
|
||||
};
|
||||
|
||||
@@ -4606,6 +4796,7 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
|
||||
win->SetCursor( m_colResizeCursor );
|
||||
break;
|
||||
|
||||
case WXGRID_CURSOR_MOVE_ROW:
|
||||
case WXGRID_CURSOR_MOVE_COL:
|
||||
// Currently we don't capture mouse when moving columns, which is
|
||||
// almost certainly wrong.
|
||||
@@ -4816,6 +5007,7 @@ wxGrid::DoGridCellLeftDown(wxMouseEvent& event,
|
||||
}
|
||||
break;
|
||||
|
||||
case WXGRID_CURSOR_MOVE_ROW:
|
||||
case WXGRID_CURSOR_MOVE_COL:
|
||||
// Nothing to do here for this case.
|
||||
break;
|
||||
@@ -5130,6 +5322,99 @@ void wxGrid::DoHeaderEndDragResizeCol(int width)
|
||||
DoEndDragResizeCol(e, m_gridWin);
|
||||
}
|
||||
|
||||
void wxGrid::DoStartMoveRow(int row)
|
||||
{
|
||||
m_dragMoveRow = row;
|
||||
}
|
||||
|
||||
void wxGrid::DoEndMoveRow(int pos)
|
||||
{
|
||||
wxASSERT_MSG( m_dragMoveRow != -1, "no matching DoStartMoveRow?" );
|
||||
|
||||
if ( SendEvent(wxEVT_GRID_ROW_MOVE, -1, m_dragMoveRow) != Event_Vetoed )
|
||||
SetRowPos(m_dragMoveRow, pos);
|
||||
|
||||
m_dragMoveRow = -1;
|
||||
}
|
||||
|
||||
void wxGrid::RefreshAfterRowPosChange()
|
||||
{
|
||||
// recalculate the row bottoms as the row positions have changed,
|
||||
// unless we calculate them dynamically because all rows heights are the
|
||||
// same and it's easy to do
|
||||
if ( !m_rowHeights.empty() )
|
||||
{
|
||||
int rowBottom = 0;
|
||||
for ( int rowPos = 0; rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
int rowID = GetRowAt( rowPos );
|
||||
|
||||
// Ignore the currently hidden rows.
|
||||
const int height = m_rowHeights[rowID];
|
||||
if ( height > 0 )
|
||||
rowBottom += height;
|
||||
|
||||
m_rowBottoms[rowID] = rowBottom;
|
||||
}
|
||||
}
|
||||
|
||||
// and make the changes visible
|
||||
m_rowLabelWin->Refresh();
|
||||
m_gridWin->Refresh();
|
||||
}
|
||||
|
||||
void wxGrid::SetRowsOrder(const wxArrayInt& order)
|
||||
{
|
||||
m_rowAt = order;
|
||||
|
||||
RefreshAfterRowPosChange();
|
||||
}
|
||||
|
||||
void wxGrid::SetRowPos(int idx, int pos)
|
||||
{
|
||||
// we're going to need m_rowAt now, initialize it if needed
|
||||
if ( m_rowAt.empty() )
|
||||
{
|
||||
m_rowAt.reserve(m_numRows);
|
||||
for ( int i = 0; i < m_numRows; i++ )
|
||||
m_rowAt.push_back(i);
|
||||
}
|
||||
|
||||
// from wxHeaderCtrl::MoveRowInOrderArray:
|
||||
int posOld = m_rowAt.Index(idx);
|
||||
wxASSERT_MSG( posOld != wxNOT_FOUND, "invalid index" );
|
||||
|
||||
if ( pos != posOld )
|
||||
{
|
||||
m_rowAt.RemoveAt(posOld);
|
||||
m_rowAt.Insert(idx, pos);
|
||||
}
|
||||
|
||||
RefreshAfterRowPosChange();
|
||||
}
|
||||
|
||||
void wxGrid::ResetRowPos()
|
||||
{
|
||||
m_rowAt.clear();
|
||||
|
||||
RefreshAfterRowPosChange();
|
||||
}
|
||||
|
||||
bool wxGrid::EnableDragRowMove( bool enable )
|
||||
{
|
||||
if ( m_canDragRowMove == enable ||
|
||||
(enable && m_rowFrozenLabelWin) )
|
||||
return false;
|
||||
|
||||
m_canDragRowMove = enable;
|
||||
|
||||
// we use to call ResetRowPos() from here if !enable but this doesn't seem
|
||||
// right as it would mean there would be no way to "freeze" the current
|
||||
// rows order by disabling moving them after putting them in the desired
|
||||
// order, whereas now you can always call ResetRowPos() manually if needed
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxGrid::DoStartMoveCol(int col)
|
||||
{
|
||||
m_dragMoveCol = col;
|
||||
@@ -5306,6 +5591,7 @@ bool wxGrid::FreezeTo(int row, int col)
|
||||
"Number of rows or cols can't be negative!");
|
||||
|
||||
if ( row >= m_numRows || col >= m_numCols ||
|
||||
!m_rowAt.empty() || m_canDragRowMove ||
|
||||
!m_colAt.empty() || m_canDragColMove || m_useNativeHeader )
|
||||
return false;
|
||||
|
||||
@@ -5330,7 +5616,7 @@ bool wxGrid::FreezeTo(int row, int col)
|
||||
{
|
||||
for ( int j = 0; j < m_numCols; j++ )
|
||||
{
|
||||
GetCellSize(i, GetColAt(j), &cell_rows, &cell_cols );
|
||||
GetCellSize(GetRowAt(i), GetColAt(j), &cell_rows, &cell_cols );
|
||||
|
||||
if (( cell_rows > 1 ) || ( cell_cols > 1 ))
|
||||
return false;
|
||||
@@ -5341,7 +5627,7 @@ bool wxGrid::FreezeTo(int row, int col)
|
||||
{
|
||||
for ( int j = 0; j < m_numRows; j++ )
|
||||
{
|
||||
GetCellSize(j, GetColAt(i), &cell_rows, &cell_cols );
|
||||
GetCellSize(GetRowAt(j), GetColAt(i), &cell_rows, &cell_cols );
|
||||
|
||||
if (( cell_rows > 1 ) || ( cell_cols > 1 ))
|
||||
return false;
|
||||
@@ -5699,7 +5985,7 @@ void wxGrid::RefreshBlock(int topRow, int leftCol,
|
||||
int col = leftCol;
|
||||
|
||||
// corner grid
|
||||
if ( topRow < m_numFrozenRows && GetColPos(leftCol) < m_numFrozenCols && m_frozenCornerGridWin )
|
||||
if ( GetRowPos(topRow) < m_numFrozenRows && GetColPos(leftCol) < m_numFrozenCols && m_frozenCornerGridWin )
|
||||
{
|
||||
row = wxMin(bottomRow, m_numFrozenRows - 1);
|
||||
col = wxMin(rightCol, m_numFrozenCols - 1);
|
||||
@@ -5712,7 +5998,7 @@ void wxGrid::RefreshBlock(int topRow, int leftCol,
|
||||
}
|
||||
|
||||
// frozen cols grid
|
||||
if ( GetColPos(leftCol) < m_numFrozenCols && bottomRow >= m_numFrozenRows && m_frozenColGridWin )
|
||||
if ( GetColPos(leftCol) < m_numFrozenCols && GetRowPos(bottomRow) >= m_numFrozenRows && m_frozenColGridWin )
|
||||
{
|
||||
col = wxMin(rightCol, m_numFrozenCols - 1);
|
||||
|
||||
@@ -5724,7 +6010,7 @@ void wxGrid::RefreshBlock(int topRow, int leftCol,
|
||||
}
|
||||
|
||||
// frozen rows grid
|
||||
if ( topRow < m_numFrozenRows && GetColPos(rightCol) >= m_numFrozenCols && m_frozenRowGridWin )
|
||||
if ( GetRowPos(topRow) < m_numFrozenRows && GetColPos(rightCol) >= m_numFrozenCols && m_frozenRowGridWin )
|
||||
{
|
||||
row = wxMin(bottomRow, m_numFrozenRows - 1);
|
||||
|
||||
@@ -5736,7 +6022,7 @@ void wxGrid::RefreshBlock(int topRow, int leftCol,
|
||||
}
|
||||
|
||||
// main grid
|
||||
if ( bottomRow >= m_numFrozenRows && GetColPos(rightCol) >= m_numFrozenCols )
|
||||
if ( GetRowPos(bottomRow) >= m_numFrozenRows && GetColPos(rightCol) >= m_numFrozenCols )
|
||||
{
|
||||
const wxRect rect = BlockToDeviceRect(wxGridCellCoords(row, col),
|
||||
wxGridCellCoords(bottomRow, rightCol),
|
||||
@@ -6441,7 +6727,7 @@ void wxGrid::DrawGridSpace( wxDC& dc, wxGridWindow *gridWindow )
|
||||
CalcGridWindowUnscrolledPosition(cw + offset.x, ch + offset.y, &right, &bottom, gridWindow);
|
||||
|
||||
int rightCol = m_numCols > 0 ? GetColRight(GetColAt( m_numCols - 1 )) : 0;
|
||||
int bottomRow = m_numRows > 0 ? GetRowBottom(m_numRows - 1) : 0;
|
||||
int bottomRow = m_numRows > 0 ? GetRowBottom(GetRowAt( m_numRows - 1 )) : 0;
|
||||
|
||||
if ( right > rightCol || bottom > bottomRow )
|
||||
{
|
||||
@@ -6771,16 +7057,16 @@ void wxGrid::DrawAllGridWindowLines(wxDC& dc, const wxRegion & WXUNUSED(reg), wx
|
||||
if ( !m_numRows )
|
||||
return;
|
||||
|
||||
const int lastRowBottom = GetRowBottom(m_numRows - 1);
|
||||
const int lastRowBottom = GetRowBottom(GetRowAt(m_numRows - 1));
|
||||
if ( bottom > lastRowBottom )
|
||||
bottom = lastRowBottom;
|
||||
}
|
||||
|
||||
// no gridlines inside multicells, clip them out
|
||||
int leftCol = GetColPos( internalXToCol(left, gridWindow) );
|
||||
int topRow = internalYToRow(top, gridWindow);
|
||||
int topRow = GetRowPos( internalYToRow(top, gridWindow) );
|
||||
int rightCol = GetColPos( internalXToCol(right, gridWindow) );
|
||||
int bottomRow = internalYToRow(bottom, gridWindow);
|
||||
int bottomRow = GetRowPos( internalYToRow(bottom, gridWindow) );
|
||||
|
||||
if ( gridWindow == m_gridWin )
|
||||
{
|
||||
@@ -6871,8 +7157,9 @@ wxGrid::DoDrawGridLines(wxDC& dc,
|
||||
int bottomRow, int rightCol)
|
||||
{
|
||||
// horizontal grid lines
|
||||
for ( int i = topRow; i < bottomRow; i++ )
|
||||
for ( int rowPos = topRow; rowPos < bottomRow; rowPos++ )
|
||||
{
|
||||
int i = GetRowAt( rowPos );
|
||||
int bot = GetRowBottom(i) - 1;
|
||||
|
||||
if ( bot > bottom )
|
||||
@@ -7848,6 +8135,11 @@ int wxGrid::XToCol(int x, bool clipToMinMax, wxGridWindow *gridWindow) const
|
||||
return PosToLine(x, clipToMinMax, wxGridColumnOperations(), gridWindow);
|
||||
}
|
||||
|
||||
int wxGrid::YToPos(int y, wxGridWindow *gridWindow) const
|
||||
{
|
||||
return PosToLinePos(y, true /* clip */, wxGridRowOperations(), gridWindow);
|
||||
}
|
||||
|
||||
int wxGrid::XToPos(int x, wxGridWindow *gridWindow) const
|
||||
{
|
||||
return PosToLinePos(x, true /* clip */, wxGridColumnOperations(), gridWindow);
|
||||
@@ -7947,9 +8239,9 @@ wxGridWindow* wxGrid::CellToGridWindow( int row, int col ) const
|
||||
// frozen corner window in this case.
|
||||
if ( row == -1 && col == -1 )
|
||||
return m_gridWin;
|
||||
else if ( row < m_numFrozenRows && GetColPos(col) < m_numFrozenCols )
|
||||
else if ( GetRowPos(row) < m_numFrozenRows && GetColPos(col) < m_numFrozenCols )
|
||||
return m_frozenCornerGridWin;
|
||||
else if ( row < m_numFrozenRows )
|
||||
else if ( GetRowPos(row) < m_numFrozenRows )
|
||||
return m_frozenRowGridWin;
|
||||
else if ( GetColPos(col) < m_numFrozenCols )
|
||||
return m_frozenColGridWin;
|
||||
@@ -9834,9 +10126,10 @@ void wxGrid::DoSetRowSize( int row, int height )
|
||||
if ( !diff )
|
||||
return;
|
||||
|
||||
for ( int i = row; i < m_numRows; i++ )
|
||||
|
||||
for ( int rowPos = GetRowPos(row); rowPos < m_numRows; rowPos++ )
|
||||
{
|
||||
m_rowBottoms[i] += diff;
|
||||
m_rowBottoms[GetRowAt(rowPos)] += diff;
|
||||
}
|
||||
|
||||
InvalidateBestSize();
|
||||
@@ -10045,10 +10338,12 @@ void wxGrid::DoSetColSize( int col, int width )
|
||||
CalcUnscrolledPosition(0, rect.GetTop(), NULL, &top);
|
||||
CalcUnscrolledPosition(0, rect.GetBottom(), NULL, &bottom);
|
||||
|
||||
const int rowTop = internalYToRow(top, m_gridWin);
|
||||
const int rowBottom = internalYToRow(bottom, m_gridWin);
|
||||
for ( int row = rowTop; row <= rowBottom; ++row )
|
||||
const int posTop = YToPos(top, m_gridWin);
|
||||
const int posBottom = YToPos(bottom, m_gridWin);
|
||||
for ( int pos = posTop; pos <= posBottom; ++pos )
|
||||
{
|
||||
int row = GetRowAt(pos);
|
||||
|
||||
int numRows, numCols;
|
||||
if ( GetCellSize(row, col, &numRows, &numCols) == CellSpan_Inside )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user