support column reordering using drag and drop when using wxHeaderCtrl

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57301 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-12-13 00:24:39 +00:00
parent baa4a96705
commit cd68daf58a
4 changed files with 135 additions and 62 deletions

View File

@@ -2133,7 +2133,6 @@ protected:
//Column positions
wxArrayInt m_colAt;
int m_moveToCol;
bool m_canDragRowSize;
bool m_canDragColSize;
@@ -2293,10 +2292,11 @@ private:
void DoStartResizeCol(int col);
void DoUpdateResizeCol(int x);
void DoUpdateResizeColWidth(int w);
void DoStartMoveCol(int col);
void DoEndDragResizeRow();
void DoEndDragResizeCol(wxMouseEvent *event = NULL);
void DoEndDragMoveCol();
void DoEndMoveCol(int pos);
// common implementations of methods defined for both rows and columns

View File

@@ -3161,6 +3161,18 @@ public:
@event{EVT_GRID_SELECT_CELL(func)}
The user moved to, and selected a cell. Processes a
@c wxEVT_GRID_SELECT_CELL event type.
@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
either prevent the user from reordering the column change completely
(but notice that if you don't want to allow it at all, you simply
shouldn't call wxGrid::EnableDragColMove() in the first place), vetoed
but handled in some way in the handler, e.g. by really moving the
column to the new position at the associated table level, or allowed to
proceed in which case wxGrid::SetColPos() is used to reorder the
columns display order without affecting the use of the column indices
otherwise.
This event macro corresponds to @c wxEVT_GRID_COL_MOVE event type.
@event{EVT_GRID_CMD_CELL_CHANGE(id, func)}
The user changed the data in a cell; variant taking a window
identifier. Processes a @c wxEVT_GRID_CELL_CHANGE event type.

View File

@@ -1641,7 +1641,9 @@ public:
private:
enum // control ids
{
Id_Check_UseNative,
Id_Check_UseNativeHeader,
Id_Check_DrawNativeLabels,
Id_Check_ShowRowLabels,
Id_Check_EnableColMove
};
@@ -1649,7 +1651,26 @@ private:
void OnToggleUseNativeHeader(wxCommandEvent&)
{
m_grid->SetUseNativeColLabels(m_chkUseNative->IsChecked());
m_grid->UseNativeColHeader(m_chkUseNative->IsChecked());
}
void OnUpdateDrawNativeLabelsUI(wxUpdateUIEvent& event)
{
// we don't draw labels at all, native or otherwise, if we use the
// native header control
event.Enable( !m_chkUseNative->GetValue() );
}
void OnToggleDrawNativeLabels(wxCommandEvent&)
{
m_grid->SetUseNativeColLabels(m_chkDrawNative->IsChecked());
}
void OnToggleShowRowLabels(wxCommandEvent&)
{
m_grid->SetRowLabelSize(m_chkShowRowLabels->IsChecked()
? wxGRID_AUTOSIZE
: 0);
}
void OnToggleColMove(wxCommandEvent&)
@@ -1671,7 +1692,20 @@ private:
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;
event.Skip();
}
void OnIdle(wxIdleEvent& event)
{
if ( m_shouldUpdateOrder )
{
m_shouldUpdateOrder = false;
UpdateOrder();
}
event.Skip();
}
@@ -1688,6 +1722,8 @@ private:
// controls
wxGrid *m_grid;
wxCheckBox *m_chkUseNative,
*m_chkDrawNative,
*m_chkShowRowLabels,
*m_chkEnableColMove;
ColIndexEntry *m_txtColIndex,
@@ -1695,28 +1731,49 @@ private:
wxStaticText *m_statOrder;
// fla for EVT_IDLE handler
bool m_shouldUpdateOrder;
DECLARE_NO_COPY_CLASS(TabularGridFrame)
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
EVT_CHECKBOX(Id_Check_UseNative, TabularGridFrame::OnToggleUseNativeHeader)
EVT_CHECKBOX(Id_Check_EnableColMove, TabularGridFrame::OnToggleColMove)
EVT_CHECKBOX(Id_Check_UseNativeHeader,
TabularGridFrame::OnToggleUseNativeHeader)
EVT_CHECKBOX(Id_Check_DrawNativeLabels,
TabularGridFrame::OnToggleDrawNativeLabels)
EVT_CHECKBOX(Id_Check_ShowRowLabels,
TabularGridFrame::OnToggleShowRowLabels)
EVT_CHECKBOX(Id_Check_EnableColMove,
TabularGridFrame::OnToggleColMove)
EVT_UPDATE_UI(Id_Check_DrawNativeLabels,
TabularGridFrame::OnUpdateDrawNativeLabelsUI)
EVT_BUTTON(wxID_APPLY, TabularGridFrame::OnMoveColumn)
EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
EVT_IDLE(TabularGridFrame::OnIdle)
END_EVENT_TABLE()
TabularGridFrame::TabularGridFrame()
: wxFrame(NULL, wxID_ANY, "Tabular table")
{
m_shouldUpdateOrder = false;
wxPanel * const panel = new wxPanel(this);
// create and initialize the grid with the specified data
m_grid = new wxGrid(this, wxID_ANY);
m_grid = new wxGrid(panel, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxBORDER_STATIC | wxWANTS_CHARS);
m_grid->SetTable(new TabularGridTable, true, wxGrid::wxGridSelectRows);
m_grid->SetUseNativeColLabels();
m_grid->EnableDragColMove();
m_grid->UseNativeColHeader();
m_grid->HideRowLabels();
// add it and the other controls to the frame
wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
@@ -1725,12 +1782,20 @@ TabularGridFrame::TabularGridFrame()
wxSizer * const sizerControls = new wxBoxSizer(wxHORIZONTAL);
wxSizer * const sizerStyles = new wxBoxSizer(wxVERTICAL);
m_chkUseNative = new wxCheckBox(this, Id_Check_UseNative,
m_chkUseNative = new wxCheckBox(panel, Id_Check_UseNativeHeader,
"&Use native header");
m_chkUseNative->SetValue(true);
sizerStyles->Add(m_chkUseNative, wxSizerFlags().Border());
m_chkEnableColMove = new wxCheckBox(this, Id_Check_EnableColMove,
m_chkDrawNative = new wxCheckBox(panel, Id_Check_DrawNativeLabels,
"&Draw native column labels");
sizerStyles->Add(m_chkDrawNative, wxSizerFlags().Border());
m_chkShowRowLabels = new wxCheckBox(panel, Id_Check_ShowRowLabels,
"Show &row labels");
sizerStyles->Add(m_chkShowRowLabels, wxSizerFlags().Border());
m_chkEnableColMove = new wxCheckBox(panel, Id_Check_EnableColMove,
"Allow column re&ordering");
m_chkEnableColMove->SetValue(true);
sizerStyles->Add(m_chkEnableColMove, wxSizerFlags().Border());
@@ -1742,21 +1807,21 @@ TabularGridFrame::TabularGridFrame()
wxSizer * const sizerMoveCols = new wxBoxSizer(wxHORIZONTAL);
const wxSizerFlags
flagsHorz(wxSizerFlags().Border(wxLEFT | wxRIGHT).Centre());
sizerMoveCols->Add(new wxStaticText(this, wxID_ANY, "&Move column"),
sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&Move column"),
flagsHorz);
m_txtColIndex = new ColIndexEntry(this);
m_txtColIndex = new ColIndexEntry(panel);
sizerMoveCols->Add(m_txtColIndex, flagsHorz);
sizerMoveCols->Add(new wxStaticText(this, wxID_ANY, "&to"), flagsHorz);
m_txtColPos = new ColIndexEntry(this);
sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&to"), flagsHorz);
m_txtColPos = new ColIndexEntry(panel);
sizerMoveCols->Add(m_txtColPos, flagsHorz);
sizerMoveCols->Add(new wxButton(this, wxID_APPLY), flagsHorz);
sizerMoveCols->Add(new wxButton(panel, wxID_APPLY), flagsHorz);
sizerColumns->Add(sizerMoveCols, wxSizerFlags().Expand().Border(wxBOTTOM));
wxSizer * const sizerShowCols = new wxBoxSizer(wxHORIZONTAL);
sizerShowCols->Add(new wxStaticText(this, wxID_ANY, "Current order:"),
sizerShowCols->Add(new wxStaticText(panel, wxID_ANY, "Current order:"),
flagsHorz);
m_statOrder = new wxStaticText(this, wxID_ANY, "<default>");
m_statOrder = new wxStaticText(panel, wxID_ANY, "<default>");
sizerShowCols->Add(m_statOrder, flagsHorz);
sizerColumns->Add(sizerShowCols, wxSizerFlags().Expand().Border(wxTOP));
@@ -1764,8 +1829,11 @@ TabularGridFrame::TabularGridFrame()
sizerTop->Add(sizerControls, wxSizerFlags().Expand().Border());
SetSizerAndFit(sizerTop);
SetBackgroundColour(*wxWHITE);
panel->SetSizer(sizerTop);
SetClientSize(panel->GetBestSize());
SetSizeHints(GetSize());
Show();
}
@@ -1773,4 +1841,3 @@ void GridFrame::OnTabularTable(wxCommandEvent&)
{
new TabularGridFrame;
}

View File

@@ -275,9 +275,14 @@ private:
event.Skip();
}
void OnBeginReorder(wxHeaderCtrlEvent& event)
{
GetOwner()->DoStartMoveCol(event.GetColumn());
}
void OnEndReorder(wxHeaderCtrlEvent& event)
{
event.Skip(); // TODO: position it at event.GetNewOrder()
GetOwner()->DoEndMoveCol(event.GetNewOrder());
}
wxVector<wxGridHeaderColumn> m_columns;
@@ -291,6 +296,7 @@ BEGIN_EVENT_TABLE(wxGridHeaderCtrl, wxHeaderCtrl)
EVT_HEADER_RESIZING(wxID_ANY, wxGridHeaderCtrl::OnResizing)
EVT_HEADER_END_RESIZE(wxID_ANY, wxGridHeaderCtrl::OnEndResize)
EVT_HEADER_BEGIN_REORDER(wxID_ANY, wxGridHeaderCtrl::OnBeginReorder)
EVT_HEADER_END_REORDER(wxID_ANY, wxGridHeaderCtrl::OnEndReorder)
END_EVENT_TABLE()
@@ -5888,7 +5894,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
GetColLabelWindow()->CaptureMouse();
if ( m_cursorMode == WXGRID_CURSOR_MOVE_COL )
m_dragRowOrCol = XToCol( x );
DoStartMoveCol(XToCol(x));
}
if ( event.LeftIsDown() )
@@ -5911,25 +5917,15 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
case WXGRID_CURSOR_MOVE_COL:
{
if ( x < 0 )
m_moveToCol = GetColAt( 0 );
else
m_moveToCol = XToCol( x );
int posNew = XToPos(x);
int colNew = GetColAt(posNew);
// determine the position of the drop marker
int markerX;
if ( m_moveToCol < 0 )
markerX = GetColRight( GetColAt( m_numCols - 1 ) );
else if ( x >= (GetColLeft( m_moveToCol ) + (GetColWidth(m_moveToCol) / 2)) )
{
m_moveToCol = GetColAt( GetColPos( m_moveToCol ) + 1 );
if ( m_moveToCol < 0 )
markerX = GetColRight( GetColAt( m_numCols - 1 ) );
if ( x >= GetColLeft(colNew) + (GetColWidth(colNew) / 2) )
markerX = GetColRight(colNew);
else
markerX = GetColLeft( m_moveToCol );
}
else
markerX = GetColLeft( m_moveToCol );
markerX = GetColLeft(colNew);
if ( markerX != m_dragLastPos )
{
@@ -5955,9 +5951,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
const wxColour *color;
//Moving to the same place? Don't draw a marker
if ( (m_moveToCol == m_dragRowOrCol)
|| (GetColPos( m_moveToCol ) == GetColPos( m_dragRowOrCol ) + 1)
|| (m_moveToCol < 0 && m_dragRowOrCol == GetColAt( m_numCols - 1 )))
if ( colNew == m_dragRowOrCol )
color = wxLIGHT_GREY;
else
color = wxBLUE;
@@ -6096,9 +6090,15 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
break;
case WXGRID_CURSOR_MOVE_COL:
DoEndDragMoveCol();
SendEvent( wxEVT_GRID_COL_MOVE, -1, m_dragRowOrCol, event );
if ( m_dragLastPos == -1 )
{
// The user clicked on the column but didn't actually drag
m_colWindow->Refresh(); // "unpress" the column
}
else
{
DoEndMoveCol(XToPos(x));
}
break;
case WXGRID_CURSOR_SELECT_COL:
@@ -6763,26 +6763,20 @@ void wxGrid::DoEndDragResizeCol(wxMouseEvent *event)
SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol );
}
void wxGrid::DoEndDragMoveCol()
void wxGrid::DoStartMoveCol(int col)
{
//The user clicked on the column but didn't actually drag
if ( m_dragLastPos < 0 )
{
m_colWindow->Refresh(); //Do this to "unpress" the column
return;
}
m_dragRowOrCol = col;
}
int newPos;
if ( m_moveToCol == -1 )
newPos = m_numCols - 1;
else
{
newPos = GetColPos( m_moveToCol );
if ( newPos > GetColPos( m_dragRowOrCol ) )
newPos--;
}
void wxGrid::DoEndMoveCol(int pos)
{
wxASSERT_MSG( m_dragRowOrCol != -1, "no matching DoStartMoveCol?" );
SetColPos( m_dragRowOrCol, newPos );
if ( SendEvent(wxEVT_GRID_COL_MOVE, -1, m_dragRowOrCol) != -1 )
SetColPos(m_dragRowOrCol, pos);
//else: vetoed by user
m_dragRowOrCol = -1;
}
void wxGrid::SetColPos(int idx, int pos)