Commit a08f3e25 authored by cutealien's avatar cutealien

- Fix problem that modal windows do not get activated on setFocus (noticed by Yoran).

- Kick virtual function calls out of IGUIElement constructor.
- Actually those fixes could maybe go into 1.6 (only non-virtual protected interfaces added).

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3067 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 538d1a1e
...@@ -42,8 +42,10 @@ public: ...@@ -42,8 +42,10 @@ public:
// if we were given a parent to attach to // if we were given a parent to attach to
if (parent) if (parent)
parent->addChild(this); {
parent->addChildToEnd(this);
recalculateAbsolutePosition(true);
}
} }
...@@ -213,120 +215,7 @@ public: ...@@ -213,120 +215,7 @@ public:
//! Updates the absolute position. //! Updates the absolute position.
virtual void updateAbsolutePosition() virtual void updateAbsolutePosition()
{ {
core::rect<s32> parentAbsolute(0,0,0,0); recalculateAbsolutePosition(false);
core::rect<s32> parentAbsoluteClip;
f32 fw=0.f, fh=0.f;
if (Parent)
{
parentAbsolute = Parent->AbsoluteRect;
if (NoClip)
{
IGUIElement* p=this;
while (p && p->Parent)
p = p->Parent;
parentAbsoluteClip = p->AbsoluteClippingRect;
}
else
parentAbsoluteClip = Parent->AbsoluteClippingRect;
}
const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth();
const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight();
if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE)
fw = (f32)parentAbsolute.getWidth();
if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE)
fh = (f32)parentAbsolute.getHeight();
switch (AlignLeft)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.UpperLeftCorner.X += diffx;
break;
case EGUIA_CENTER:
DesiredRect.UpperLeftCorner.X += diffx/2;
break;
case EGUIA_SCALE:
DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw);
break;
}
switch (AlignRight)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.LowerRightCorner.X += diffx;
break;
case EGUIA_CENTER:
DesiredRect.LowerRightCorner.X += diffx/2;
break;
case EGUIA_SCALE:
DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw);
break;
}
switch (AlignTop)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.UpperLeftCorner.Y += diffy;
break;
case EGUIA_CENTER:
DesiredRect.UpperLeftCorner.Y += diffy/2;
break;
case EGUIA_SCALE:
DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh);
break;
}
switch (AlignBottom)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.LowerRightCorner.Y += diffy;
break;
case EGUIA_CENTER:
DesiredRect.LowerRightCorner.Y += diffy/2;
break;
case EGUIA_SCALE:
DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh);
break;
}
RelativeRect = DesiredRect;
const s32 w = RelativeRect.getWidth();
const s32 h = RelativeRect.getHeight();
// make sure the desired rectangle is allowed
if (w < (s32)MinSize.Width)
RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width;
if (h < (s32)MinSize.Height)
RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height;
if (MaxSize.Width && w > (s32)MaxSize.Width)
RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width;
if (MaxSize.Height && h > (s32)MaxSize.Height)
RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height;
RelativeRect.repair();
AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner;
if (!Parent)
parentAbsoluteClip = AbsoluteRect;
AbsoluteClippingRect = AbsoluteRect;
AbsoluteClippingRect.clipAgainst(parentAbsoluteClip);
LastParentRect = parentAbsolute;
// update all children // update all children
core::list<IGUIElement*>::Iterator it = Children.begin(); core::list<IGUIElement*>::Iterator it = Children.begin();
...@@ -388,13 +277,9 @@ public: ...@@ -388,13 +277,9 @@ public:
//! Adds a GUI element as new child of this element. //! Adds a GUI element as new child of this element.
virtual void addChild(IGUIElement* child) virtual void addChild(IGUIElement* child)
{ {
addChildToEnd(child);
if (child) if (child)
{ {
child->grab(); // prevent destruction when removed
child->remove(); // remove from old parent
child->LastParentRect = getAbsolutePosition();
child->Parent = this;
Children.push_back(child);
child->updateAbsolutePosition(); child->updateAbsolutePosition();
} }
} }
...@@ -860,6 +745,149 @@ public: ...@@ -860,6 +745,149 @@ public:
setNotClipped(in->getAttributeAsBool("NoClip")); setNotClipped(in->getAttributeAsBool("NoClip"));
} }
protected:
// not virtual because needed in constructor
void addChildToEnd(IGUIElement* child)
{
if (child)
{
child->grab(); // prevent destruction when removed
child->remove(); // remove from old parent
child->LastParentRect = getAbsolutePosition();
child->Parent = this;
Children.push_back(child);
}
}
// not virtual because needed in constructor
void recalculateAbsolutePosition(bool recursive)
{
core::rect<s32> parentAbsolute(0,0,0,0);
core::rect<s32> parentAbsoluteClip;
f32 fw=0.f, fh=0.f;
if (Parent)
{
parentAbsolute = Parent->AbsoluteRect;
if (NoClip)
{
IGUIElement* p=this;
while (p && p->Parent)
p = p->Parent;
parentAbsoluteClip = p->AbsoluteClippingRect;
}
else
parentAbsoluteClip = Parent->AbsoluteClippingRect;
}
const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth();
const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight();
if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE)
fw = (f32)parentAbsolute.getWidth();
if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE)
fh = (f32)parentAbsolute.getHeight();
switch (AlignLeft)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.UpperLeftCorner.X += diffx;
break;
case EGUIA_CENTER:
DesiredRect.UpperLeftCorner.X += diffx/2;
break;
case EGUIA_SCALE:
DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw);
break;
}
switch (AlignRight)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.LowerRightCorner.X += diffx;
break;
case EGUIA_CENTER:
DesiredRect.LowerRightCorner.X += diffx/2;
break;
case EGUIA_SCALE:
DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw);
break;
}
switch (AlignTop)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.UpperLeftCorner.Y += diffy;
break;
case EGUIA_CENTER:
DesiredRect.UpperLeftCorner.Y += diffy/2;
break;
case EGUIA_SCALE:
DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh);
break;
}
switch (AlignBottom)
{
case EGUIA_UPPERLEFT:
break;
case EGUIA_LOWERRIGHT:
DesiredRect.LowerRightCorner.Y += diffy;
break;
case EGUIA_CENTER:
DesiredRect.LowerRightCorner.Y += diffy/2;
break;
case EGUIA_SCALE:
DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh);
break;
}
RelativeRect = DesiredRect;
const s32 w = RelativeRect.getWidth();
const s32 h = RelativeRect.getHeight();
// make sure the desired rectangle is allowed
if (w < (s32)MinSize.Width)
RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width;
if (h < (s32)MinSize.Height)
RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height;
if (MaxSize.Width && w > (s32)MaxSize.Width)
RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width;
if (MaxSize.Height && h > (s32)MaxSize.Height)
RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height;
RelativeRect.repair();
AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner;
if (!Parent)
parentAbsoluteClip = AbsoluteRect;
AbsoluteClippingRect = AbsoluteRect;
AbsoluteClippingRect.clipAgainst(parentAbsoluteClip);
LastParentRect = parentAbsolute;
if ( recursive )
{
// update all children
core::list<IGUIElement*>::Iterator it = Children.begin();
for (; it != Children.end(); ++it)
{
(*it)->recalculateAbsolutePosition(recursive);
}
}
}
protected: protected:
//! List of all children of this element //! List of all children of this element
......
...@@ -949,17 +949,20 @@ IGUIWindow* CGUIEnvironment::addWindow(const core::rect<s32>& rectangle, bool mo ...@@ -949,17 +949,20 @@ IGUIWindow* CGUIEnvironment::addWindow(const core::rect<s32>& rectangle, bool mo
{ {
parent = parent ? parent : this; parent = parent ? parent : this;
if (modal)
{
parent = new CGUIModalScreen(this, parent, -1);
parent->drop();
}
IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle); IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle);
if (text) if (text)
win->setText(text); win->setText(text);
win->drop(); win->drop();
if (modal)
{
// Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very
// careful not to get virtual function call, like OnEvent, in the window.
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild(win);
}
return win; return win;
} }
...@@ -998,16 +1001,20 @@ IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t ...@@ -998,16 +1001,20 @@ IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t
rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height;
IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag,
parent, id, rect, image);
win->drop();
if (modal) if (modal)
{ {
parent = new CGUIModalScreen(this, parent, -1); // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very
parent->drop(); // careful not to get virtual function call, like OnEvent, in the CGUIMessageBox.
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild( win );
} }
IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag,
parent, id, rect, image);
win->drop();
return win; return win;
} }
...@@ -1136,15 +1143,18 @@ IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, ...@@ -1136,15 +1143,18 @@ IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title,
{ {
parent = parent ? parent : this; parent = parent ? parent : this;
IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id);
d->drop();
if (modal) if (modal)
{ {
parent = new CGUIModalScreen(this, parent, -1); // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very
parent->drop(); // careful not to get virtual function call, like OnEvent, in the window.
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild(d);
} }
IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id);
d->drop();
return d; return d;
} }
...@@ -1155,16 +1165,19 @@ IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* titl ...@@ -1155,16 +1165,19 @@ IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* titl
{ {
parent = parent ? parent : this; parent = parent ? parent : this;
IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title,
this, parent, id);
d->drop();
if (modal) if (modal)
{ {
parent = new CGUIModalScreen(this, parent, -1); // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very
parent->drop(); // careful not to get virtual function call, like OnEvent, in the window.
CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1);
modalScreen->drop();
modalScreen->addChild(d);
} }
IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title,
this, parent, id);
d->drop();
return d; return d;
} }
......
...@@ -90,6 +90,7 @@ bool CGUIModalScreen::OnEvent(const SEvent& event) ...@@ -90,6 +90,7 @@ bool CGUIModalScreen::OnEvent(const SEvent& event)
{ {
Environment->setFocus(this); Environment->setFocus(this);
} }
IGUIElement::OnEvent(event);
return false; return false;
case EGET_ELEMENT_FOCUS_LOST: case EGET_ELEMENT_FOCUS_LOST:
if ( !canTakeFocus(event.GUIEvent.Element)) if ( !canTakeFocus(event.GUIEvent.Element))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment