3

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.

Community
  • 1
  • 1
Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
  • How about `EVT_HEADER_BEGIN_REORDER(id, func)` and `EVT_HEADER_END_REORDER(id, func)` – macroland Feb 13 '17 at 09:24
  • @macroland I tried them but the [wxHeaderCtrl](http://docs.wxwidgets.org/3.1.0/classwx_header_ctrl.html) events are not fired. I tried binding+catching them in my wxGrid code (similar to the wxEVT_GRID_COL_MOVE) and also inside a custom wxGrid implementation. – Gino Mempin Feb 14 '17 at 00:59

1 Answers1

4

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);
          ...
     });
}
VZ.
  • 21,740
  • 3
  • 39
  • 42
  • This will capture by copy the whole `wxGridEvent` object; is that wise? It's not that small a class... – bogdan Feb 14 '17 at 01:54
  • Personally I think clarity is more important, especially in a quick example, but you can, of course, extract just the column from the `event` object and capture just it if you prefer. – VZ. Feb 14 '17 at 02:17
  • This seems to be the best workaround for now. A minor edit to the answer is to move `event.GetCol()` outside of `CallAfter` to fix the compile error. Otherwise, good. Thanks. – Gino Mempin Feb 16 '17 at 23:57
  • Applied, also addressing the previous comment, thanks. – VZ. Feb 17 '17 at 00:58