Search code examples
c++windowswxwidgetswxgrid

How do I get the new index of a moved column in a wxGrid?


I'm using wxWidgets 3.1.0 and I'm developing a Windows app in C++.

I'm using the base wxGrid and I've enabled column re-ordering via dragging them with the mouse (EnableDragColMove(true)). My problem now is that I need to get the moved column's new position/index after the column has been dragged to its new position.

Unfortunately, I could not find a way to do that from the available APIs.

I've tried catching the wxGridEvent wxEVT_GRID_COL_MOVE then using GetCol() and GetColPos() to check the column's new index:

gridDataList->Bind(wxEVT_GRID_COL_MOVE, &FormData::OnList_ColumnMove, this);

...

void FormData::OnList_ColumnMove(wxGridEvent& event)
{
    int movedCol = event.GetCol();
    int movedColPos = gridDataList->GetColPos(movedCol );

    ...
}

But it seems the event is triggered BEFORE the column is actually moved, so GetColPos() will still return the current column index, NOT the new index.

There seems to be no event to catch AFTER the column is moved.

My current solutions/workarounds are to:

  1. Manually handle the column movement after catching the wxEVT_GRID_COL_MOVE event (as suggested in the wxWidgets docs) so that I can properly track the before and after index of the moved column.

  2. Manually trigger a callback or a timer event after the column moves to its new position, similar to a wxPython workaround suggested in another SO post.

Though, I would like to know if there is a cleaner, less complicated way without resorting to the workarounds above.

Any suggestions are appreciated.


Solution

  • Yes, this wxEVT_GRID_COL_MOVE is generated before moving the column because it can be vetoed, preventing the move from happening. And it's true that it would be convenient if it carried the new column position, but unfortunately currently it doesn't (it would be simple to fix this and any patches doing this would be welcome!).

    The standard workaround of using CallAfter() to execute your code at later time should work just fine without changing wxWidgets however. I.e., assuming you use C++11, you should be able to just write

    void FormData::OnList_ColumnMove(wxGridEvent& event)
    {
         const int movedCol = event.GetCol();
         CallAfter([movedCol]() {
              int movedColPos = gridDataList->GetColPos(movedCol);
              ...
         });
    }