Debug assertion failed! include\xtree line 256 expression map/set iterator not incrementable
I am trying to modify the TabControl widget in order to support dragging tabs out into their own separate windows and vice versa. The programme is:
1. Mouse down event on the TabButton widget sets drag_tab to point to the widget, and registers a mouse move event on it
2. If the mouse moves outside the drag threshold we start the drag:
3. This involves creating a new frame window, detaching the Content of the TabButton and attaching it to the window
4. We now want to drag the window, not the tab. So I try to release the mouse events from the TabButton and register them to the Window
5. I would then remove the TabButton and let the drag finish with the Window
I get a crash in step 4 as above. If I don't bother releasing the events and don't delete the TabButton the idea seems to work
Code: Select all
class DragTab : public TabControl
{
/* stuff */
public:
static const String WidgetTypeName; //!< Window factory name
DragTab(const String &type, const String &name) : TabControl(type,name)
/* stuff */
};
It's set up in an initialisation in the main program like this:
Code: Select all
const String DragTab::WidgetTypeName("CEGUI/DragTab");
CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<CEGUI::DragTab>>();
CEGUI::WindowFactoryManager::getSingleton().addFalagardWindowMapping("TaharezLook/DragTab","CEGUI/DragTab","TaharezLook/TabControl","Falagard/TabControl");
CEGUI::DragTab *tc = static_cast<CEGUI::DragTab *>(winMgr.createWindow("TaharezLook/DragTab","Overview/TabControl"));
The crash seems to be caused by releasing events, although I can't get my debugger to look into the CEGUI internals so I'm going by commenting out sections:
Code: Select all
bool DragTab::hdl_drag(const CEGUI::EventArgs &args) // registered to EventMouseMove on the tab button
{
/* stuff */
if ((m_args.position.d_x - mouse_clicked_at_x) > drag_threshold
|| (m_args.position.d_x - mouse_clicked_at_x) < -drag_threshold
|| (m_args.position.d_y - mouse_clicked_at_y) > drag_threshold
|| (m_args.position.d_y - mouse_clicked_at_y) < -drag_threshold)
{
drag_started=true;
// need to convert the tab to a freestanding window
Window *content=drag_tab->getTargetWindow(); // drag_tab is the TabButton we are dragging
DragTab *tc = static_cast<DragTab*>(WindowManager::getSingleton().getWindow("Overview/TabControl"));
drag_conn->disconnect();
drag_tab->releaseInput();
// release events
drag_tab->removeAllEvents(); // commenting out this line prevents a crash
float xpos=CEGUI::CoordConverter::windowToScreenX(*drag_tab,drag_tab->getPosition().d_x);
float ypos=CEGUI::CoordConverter::windowToScreenY(*drag_tab,drag_tab->getPosition().d_y);
//tc->removeTab(content->getName());
//drag_tab=0;
CEGUI::WindowManager &winMgr = WindowManager::getSingleton();
drag_window = winMgr.createWindow("TaharezLook/FrameWindow","Overview2");
winMgr.getWindow("root")->addChildWindow("Overview2");
/* set up window properties here */
xpos += m_args.position.d_x - mouse_clicked_at_x;
ypos += m_args.position.d_y - mouse_clicked_at_y;
mouse_clicked_at_x = m_args.position.d_x;
mouse_clicked_at_y = m_args.position.d_y;
drag_window->setPosition(CEGUI::UVector2(CEGUI::UDim(0,xpos),CEGUI::UDim(0,ypos)));
drag_window->addChildWindow(content);
drag_conn=drag_window->subscribeEvent(CEGUI::Window::EventMouseMove , CEGUI::Event::Subscriber(&DragTab::hdl_drag, this));
drag_window->subscribeEvent(CEGUI::Window::EventMouseButtonUp, CEGUI::Event::Subscriber(&DragTab::hdl_mup, this));
drag_window->captureInput();
}
The workaround I have in mind is to use my game event manager to schedule an event for next tick to deregister and remove the tab so it doesn't happen in a CEGUI event handler. But that seems very messy.
Is there a way to fix this? Maybe I'm doing something fundamentally wrong since this is my first attempt at extending CEGUI in this way?
Alternatively, is there a generally better way to make a drag-out tab?