Or, for example, I have a material panel that creates windows (not inside and thus not clipped by the material panel), and these windows allow the user to edit color or do blah blah blah, which ultimately effect things in the material panel. The solution, and in short...
tl;dr - Please give CGUIWindow an event handler.
By this, I mean a pointer to an IEventReceiver which is defaulted to 0 but can be set by the programmer to handle events from the window, including window close events.
I've named by IEventReceiver as EventParent (following our ISO), and with that assumption, very little changes about CGUIWindow. Aside from the pointer member, it needs only a setter function ( setEventParent(IEventReceiver* pEventReceiver) ) and a slight modification of OnEvent(), a well-tested working version is below:
Code: Select all
bool GUIWindow::OnEvent(const SEvent& event)
{
if (isEnabled())
{
switch(event.EventType)
{
case EET_GUI_EVENT:
/* Note that this only handles GUI events. Mouse events for child elements
are not handled because focus is determined by the environment. */
if ( event.GUIEvent.Caller != this )
if ( EventParent )
if ( EventParent->OnEvent(event) )
return true;
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
{
Dragging = false;
IsActive = false;
if ( EventParent )
EventParent->OnEvent(event);
}
else
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
{
if (Parent && ((event.GUIEvent.Caller == this) || isMyChild(event.GUIEvent.Caller)))
{
Parent->bringToFront(this);
IsActive = true;
if ( EventParent )
EventParent->OnEvent(event);
}
else
{
IsActive = false;
}
}
else
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
{
if (event.GUIEvent.Caller == CloseButton)
{
if ( EventParent )
{
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
// event parent may catch this event
if ( EventParent->OnEvent(e) )
return true;
}
if (Parent)
{
// send close event to parent
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
// if the event was not absorbed
if (!Parent->OnEvent(e))
remove();
return true;
}
else
{
remove();
return true;
}
}
}
break;
case EET_MOUSE_INPUT_EVENT:
switch(event.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN:
DragStart.X = event.MouseInput.X;
DragStart.Y = event.MouseInput.Y;
Dragging = IsDraggable;
if (Parent)
Parent->bringToFront(this);
return true;
case EMIE_LMOUSE_LEFT_UP:
Dragging = false;
return true;
case EMIE_MOUSE_MOVED:
if (!event.MouseInput.isLeftPressed())
Dragging = false;
if (Dragging)
{
// gui window should not be dragged outside its parent
if (Parent &&
(event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1))
return true;
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
DragStart.X = event.MouseInput.X;
DragStart.Y = event.MouseInput.Y;
return true;
}
break;
default:
break;
}
default:
break;
}
}
if ( EventParent )
if ( EventParent->OnEvent(event) )
return true;
return IGUIElement::OnEvent(event);
}
Code: Select all
void GUIWindow::setEventParent( IEventReceiver* pEventParent )
{
EventParent = pEventParent;
}