From b2907798f28b4acce5b024f025e7b96079f53338 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Mon, 9 Apr 2012 12:40:30 +0100 Subject: [PATCH] Fix issue where unborn children were slaughtered when removing a component from an event --- src/dialogues/ConfirmPrompt.cpp | 2 +- src/dialogues/ErrorMessage.cpp | 2 +- src/interface/Component.cpp | 3 +- src/interface/Window.cpp | 67 +++++++++++++++++++++++++++------ src/interface/Window.h | 8 ++++ 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/dialogues/ConfirmPrompt.cpp b/src/dialogues/ConfirmPrompt.cpp index d97e8c8d2..e3c8e3afb 100644 --- a/src/dialogues/ConfirmPrompt.cpp +++ b/src/dialogues/ConfirmPrompt.cpp @@ -32,7 +32,7 @@ ConfirmPrompt::ConfirmPrompt(std::string title, std::string message, ConfirmDial { ui::Engine::Ref().CloseWindow(); prompt->callback->ConfirmCallback(result); - //delete prompt; TODO: Fix component disposal + prompt->SelfDestruct(); //TODO: Fix component disposal } }; diff --git a/src/dialogues/ErrorMessage.cpp b/src/dialogues/ErrorMessage.cpp index 76039939e..3b9fc1841 100644 --- a/src/dialogues/ErrorMessage.cpp +++ b/src/dialogues/ErrorMessage.cpp @@ -29,7 +29,7 @@ ErrorMessage::ErrorMessage(std::string title, std::string message): void ActionCallback(ui::Button * sender) { ui::Engine::Ref().CloseWindow(); - //delete message; TODO: Fix component disposal + message->SelfDestruct(); //TODO: Fix component disposal } }; diff --git a/src/interface/Component.cpp b/src/interface/Component.cpp index b2769cc0b..0efc2b1a0 100644 --- a/src/interface/Component.cpp +++ b/src/interface/Component.cpp @@ -148,6 +148,5 @@ void Component::OnMouseWheelInside(int localx, int localy, int d) Component::~Component() { - if(GetParentWindow()->IsFocused(this)) - GetParentWindow()->FocusComponent(NULL); + } diff --git a/src/interface/Window.cpp b/src/interface/Window.cpp index 5b603b9a4..5d93587a7 100644 --- a/src/interface/Window.cpp +++ b/src/interface/Window.cpp @@ -8,7 +8,9 @@ Window::Window(Point _position, Point _size): Position(_position), Size(_size), focusedComponent_(NULL), - AllowExclusiveDrawing(true) + AllowExclusiveDrawing(true), + halt(false), + destruct(false) { } @@ -16,7 +18,11 @@ Window::~Window() { for(unsigned i = 0, sz = Components.size(); i < sz; ++i) if( Components[i] ) + { delete Components[i]; + if(Components[i]==focusedComponent_) + focusedComponent_ = NULL; + } } void Window::AddComponent(Component* c) @@ -51,6 +57,11 @@ void Window::RemoveComponent(Component* c) // find the appropriate component index if(Components[i] == c) { + //Make sure any events don't continue + halt = true; + if(Components[i]==focusedComponent_) + focusedComponent_ = NULL; + Components.erase(Components.begin() + i); // we're done @@ -61,7 +72,10 @@ void Window::RemoveComponent(Component* c) void Window::RemoveComponent(unsigned idx) { + halt = true; // free component and remove it. + if(Components[idx]==focusedComponent_) + focusedComponent_ = NULL; delete Components[idx]; Components.erase(Components.begin() + idx); } @@ -118,7 +132,7 @@ void Window::DoDraw() void Window::DoTick(float dt) { //on mouse hover - for(int i = Components.size() - 1; i >= 0; --i) + for(int i = Components.size() - 1; i >= 0 && !halt; --i) { if(!Components[i]->Locked && ui::Engine::Ref().GetMouseX() >= Components[i]->Position.X+Position.X && @@ -132,12 +146,17 @@ void Window::DoTick(float dt) } //tick - for(int i = 0, sz = Components.size(); i < sz; ++i) + for(int i = 0, sz = Components.size(); i < sz && !halt; ++i) { Components[i]->Tick(dt); } + halt = false; + OnTick(dt); + + if(destruct) + finalise(); } void Window::DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) @@ -150,6 +169,8 @@ void Window::DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool a } OnKeyPress(key, character, shift, ctrl, alt); + if(destruct) + finalise(); } void Window::DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt) @@ -162,6 +183,8 @@ void Window::DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool } OnKeyRelease(key, character, shift, ctrl, alt); + if(destruct) + finalise(); } void Window::DoMouseDown(int x_, int y_, unsigned button) @@ -170,7 +193,7 @@ void Window::DoMouseDown(int x_, int y_, unsigned button) int x = x_ - Position.X; int y = y_ - Position.Y; bool clickState = false; - for(int i = Components.size() - 1; i > -1 ; --i) + for(int i = Components.size() - 1; i > -1 && !halt; --i) { if(!Components[i]->Locked) { @@ -188,13 +211,15 @@ void Window::DoMouseDown(int x_, int y_, unsigned button) FocusComponent(NULL); //on mouse down - for(int i = Components.size() - 1; i > -1 ; --i) + for(int i = Components.size() - 1; i > -1 && !halt; --i) { if(!Components[i]->Locked) Components[i]->OnMouseDown(x, y, button); } OnMouseDown(x_, y_, button); + if(destruct) + finalise(); } void Window::DoMouseMove(int x_, int y_, int dx, int dy) @@ -202,7 +227,7 @@ void Window::DoMouseMove(int x_, int y_, int dx, int dy) //on mouse move (if true, and inside) int x = x_ - Position.X; int y = y_ - Position.Y; - for(int i = Components.size() - 1; i > -1 ; --i) + for(int i = Components.size() - 1; i > -1 && !halt; --i) { if(!Components[i]->Locked) { @@ -214,7 +239,7 @@ void Window::DoMouseMove(int x_, int y_, int dx, int dy) if(local.X >= 0 && local.Y >= 0 && local.X < Components[i]->Size.X && - local.Y < Components[i]->Size.Y ) + local.Y < Components[i]->Size.Y && !halt) { Components[i]->OnMouseMovedInside(local.X, local.Y, dx, dy); @@ -228,7 +253,7 @@ void Window::DoMouseMove(int x_, int y_, int dx, int dy) Components[i]->OnMouseEnter(local.X, local.Y); } } - else + else if(!halt) { // leaving? if( a.X >= 0 && @@ -244,6 +269,8 @@ void Window::DoMouseMove(int x_, int y_, int dx, int dy) } OnMouseMove(x_, y_, dx, dy); + if(destruct) + finalise(); } void Window::DoMouseUp(int x_, int y_, unsigned button) @@ -251,7 +278,7 @@ void Window::DoMouseUp(int x_, int y_, unsigned button) int x = x_ - Position.X; int y = y_ - Position.Y; //on mouse unclick - for(int i = Components.size() - 1; i >= 0 ; --i) + for(int i = Components.size() - 1; i >= 0 && !halt; --i) { if(!Components[i]->Locked) { @@ -264,13 +291,15 @@ void Window::DoMouseUp(int x_, int y_, unsigned button) } //on mouse up - for(int i = Components.size() - 1; i >= 0 ; --i) + for(int i = Components.size() - 1; i >= 0 && !halt; --i) { if(!Components[i]->Locked) Components[i]->OnMouseUp(x, y, button); } OnMouseUp(x_, y_, button); + if(destruct) + finalise(); } void Window::DoMouseWheel(int x_, int y_, int d) @@ -278,7 +307,7 @@ void Window::DoMouseWheel(int x_, int y_, int d) int x = x_ - Position.X; int y = y_ - Position.Y; //on mouse wheel focused - for(int i = Components.size() - 1; i >= 0 ; --i) + for(int i = Components.size() - 1; i >= 0 && !halt; --i) { if(x >= Components[i]->Position.X && y >= Components[i]->Position.Y && x < Components[i]->Position.X + Components[i]->Size.X && y < Components[i]->Position.Y + Components[i]->Size.Y) { @@ -289,12 +318,26 @@ void Window::DoMouseWheel(int x_, int y_, int d) } //on mouse wheel - for(int i = Components.size() - 1; i >= 0 ; --i) + for(int i = Components.size() - 1; i >= 0 && !halt; --i) { if(!Components[i]->Locked) Components[i]->OnMouseWheel(x - Components[i]->Position.X, y - Components[i]->Position.Y, d); } OnMouseWheel(x_, y_, d); + + if(destruct) + finalise(); +} + +void Window::finalise() +{ + delete this; +} + +void Window::SelfDestruct() +{ + destruct = true; + halt = true; } diff --git a/src/interface/Window.h b/src/interface/Window.h index 5fb5eec6a..4e705f088 100644 --- a/src/interface/Window.h +++ b/src/interface/Window.h @@ -58,6 +58,9 @@ enum ChromeStyle virtual void DoKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); virtual void DoKeyRelease(int key, Uint16 character, bool shift, bool ctrl, bool alt); + //Sets halt and destroy, this causes the Windows to stop sending events and remove itself. + void SelfDestruct(); + bool IsFocused(const Component* c) const; void FocusComponent(Component* c); @@ -79,6 +82,11 @@ enum ChromeStyle Component* focusedComponent_; ChromeStyle chrome; + //These controls allow a component to call the destruction of the Window inside an event (called by the Window) + void finalise(); + bool halt; + bool destruct; + };