Fix column reordering in wxHeaderCtrlSimple and related problems

Override required functions in wxHeaderCtrlSimple to avoid asserts if
its columns are reordered.

Also bring the code behaviour in agreement with the documentation by
calling UpdateColumn() after calling UpdateColumnVisibility().

Finally, only call UpdateColumnsOrder() if the corresponding event was
not processed as the application should use one xor the other mechanism
for reacting to columns reordering, but not both.

Closes #24108.

Closes #24172.
This commit is contained in:
Martin Corino 2023-12-29 10:59:39 +01:00 committed by Vadim Zeitlin
parent 927590fbcd
commit 6ee9056c16
5 changed files with 52 additions and 8 deletions

View file

@ -343,6 +343,9 @@ protected:
virtual const wxHeaderColumn& GetColumn(unsigned int idx) const override;
virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle) override;
virtual void UpdateColumnVisibility(unsigned int idx, bool show) override;
virtual void UpdateColumnsOrder(const wxArrayInt& order) override;
// and define another one to be overridden in the derived classes: it
// should return the best width for the given column contents or -1 if not
// implemented, we use it to implement UpdateColumnWidthToFit()

View file

@ -447,13 +447,15 @@ protected:
/**
Method called when the columns order is changed in the customization
dialog.
dialog @em or when the EVT_HEADER_END_REORDER event is not handled after
dragging a single column.
This method is only called from ShowCustomizeDialog() when the user
changes the order of columns. In particular it is @em not called if a
single column changes place because the user dragged it to the new
location, the EVT_HEADER_END_REORDER event handler should be used to
react to this.
This method is always called from ShowCustomizeDialog() when the user
changes the order of columns. In case a single column changes place
because the user dragged it to a new location, the EVT_HEADER_END_REORDER
event handler can be used to react to this. If this event
handler is not defined though UpdateColumnsOrder() will be called
instead.
A typical implementation in a derived class will update the display
order of the columns in the associated control, if any. Notice that

View file

@ -317,6 +317,7 @@ bool wxHeaderCtrlBase::ShowColumnsMenu(const wxPoint& pt, const wxString& title)
{
const int columnIndex = rc - wxID_COLUMNS_BASE;
UpdateColumnVisibility(columnIndex, !GetColumn(columnIndex).IsShown());
UpdateColumn(columnIndex);
}
return true;
@ -469,6 +470,19 @@ wxHeaderCtrlSimple::UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
return true;
}
void
wxHeaderCtrlSimple::UpdateColumnVisibility(unsigned int idx, bool show)
{
ShowColumn(idx, show);
}
void
wxHeaderCtrlSimple::UpdateColumnsOrder(const wxArrayInt& WXUNUSED(order))
{
// Nothing to do here, we only override this function to prevent the base
// class version from asserting that it should be implemented.
}
void wxHeaderCtrlSimple::OnHeaderResizing(wxHeaderCtrlEvent& evt)
{
m_cols[evt.GetColumn()].SetWidth(evt.GetWidth());

View file

@ -456,7 +456,22 @@ bool wxHeaderCtrl::EndReordering(int xPhysical)
const unsigned pos = GetColumnPos(colNew);
event.SetNewOrder(pos);
if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
const bool processed = GetEventHandler()->ProcessEvent(event);
if ( !processed )
{
// get the reordered columns
wxArrayInt order = GetColumnsOrder();
MoveColumnInOrderArray(order, colOld, pos);
// As the event wasn't processed, call the virtual function
// callback.
UpdateColumnsOrder(order);
// update columns order
SetColumnsOrder(order);
}
else if ( event.IsAllowed() )
{
// do reorder the columns
DoMoveCol(colOld, pos);

View file

@ -990,7 +990,17 @@ bool wxMSWHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
// internal column indices array if this is allowed to go ahead as
// the native control is going to reorder its columns now
if ( evtType == wxEVT_HEADER_END_REORDER )
m_header.MoveColumnInOrderArray(m_colIndices, idx, order);
{
// If the event handler didn't process the event, call the
// virtual function callback.
wxArrayInt colIndices = m_header.GetColumnsOrder();
m_header.MoveColumnInOrderArray(colIndices, idx, order);
if ( !processed )
m_header.UpdateColumnsOrder(colIndices);
// And update internally columns indices in any case.
m_colIndices = colIndices;
}
if ( processed )
{