1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CGUIModalScreen.h"
\r
6 #ifdef _IRR_COMPILE_WITH_GUI_
\r
8 #include "IGUIEnvironment.h"
\r
10 #include "IVideoDriver.h"
\r
11 #include "IGUISkin.h"
\r
19 CGUIModalScreen::CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id)
\r
20 : IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, core::recti(0, 0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight()) ),
\r
25 setDebugName("CGUIModalScreen");
\r
27 setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
\r
29 // this element is a tab group
\r
33 bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const
\r
35 return (target && ((const IGUIElement*)target == this // this element can take it
\r
36 || isMyChild(target) // own children also
\r
37 || (target->getType() == EGUIET_MODAL_SCREEN ) // other modals also fine (is now on top or explicitely requested)
\r
38 || (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN ))) // children of other modals will do
\r
42 bool CGUIModalScreen::isVisible() const
\r
44 // any parent invisible?
\r
45 IGUIElement * parentElement = getParent();
\r
46 while ( parentElement )
\r
48 if ( !parentElement->isVisible() )
\r
50 parentElement = parentElement->getParent();
\r
53 // if we have no children then the modal is probably abused as a way to block input
\r
54 if ( Children.empty() )
\r
56 return IGUIElement::isVisible();
\r
59 // any child visible?
\r
60 bool visible = false;
\r
61 core::list<IGUIElement*>::ConstIterator it = Children.begin();
\r
62 for (; it != Children.end(); ++it)
\r
64 if ( (*it)->isVisible() )
\r
73 bool CGUIModalScreen::isPointInside(const core::position2d<s32>& point) const
\r
78 //! called if an event happened.
\r
79 bool CGUIModalScreen::OnEvent(const SEvent& event)
\r
81 if (!isEnabled() || !isVisible() )
\r
82 return IGUIElement::OnEvent(event);
\r
84 switch(event.EventType)
\r
87 switch(event.GUIEvent.EventType)
\r
89 case EGET_ELEMENT_FOCUSED:
\r
90 if ( event.GUIEvent.Caller == this && isMyChild(event.GUIEvent.Element) )
\r
92 Environment->removeFocus(0); // can't setFocus otherwise at it still has focus here
\r
93 Environment->setFocus(event.GUIEvent.Element);
\r
95 MouseDownTime = os::Timer::getTime();
\r
98 if ( !canTakeFocus(event.GUIEvent.Caller))
\r
100 if ( !Children.empty() )
\r
101 Environment->setFocus(*(Children.begin()));
\r
103 Environment->setFocus(this);
\r
105 IGUIElement::OnEvent(event);
\r
107 case EGET_ELEMENT_FOCUS_LOST:
\r
108 if ( !canTakeFocus(event.GUIEvent.Element))
\r
110 if ( isMyChild(event.GUIEvent.Caller) )
\r
112 if ( !Children.empty() )
\r
113 Environment->setFocus(*(Children.begin()));
\r
115 Environment->setFocus(this);
\r
117 else if ( BlinkMode&1 )
\r
119 MouseDownTime = os::Timer::getTime();
\r
125 return IGUIElement::OnEvent(event);
\r
127 case EGET_ELEMENT_CLOSED:
\r
128 // do not interfere with children being removed
\r
129 return IGUIElement::OnEvent(event);
\r
134 case EET_MOUSE_INPUT_EVENT:
\r
135 if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN && (BlinkMode & 2))
\r
137 MouseDownTime = os::Timer::getTime();
\r
140 case EET_KEY_INPUT_EVENT:
\r
141 // CAREFUL when changing - there's an identical check in CGUIEnvironment::postEventFromUser
\r
142 if (Environment->getFocusBehavior() & EFF_SET_ON_TAB &&
\r
143 event.KeyInput.PressedDown &&
\r
144 event.KeyInput.Key == KEY_TAB)
\r
146 IGUIElement* next = Environment->getNextElement(event.KeyInput.Shift, event.KeyInput.Control);
\r
147 if ( next && isMyChild(next) )
\r
149 // Pass on the TAB-key, otherwise focus-tabbing inside modal screens breaks
\r
157 IGUIElement::OnEvent(event); // anyone knows why events are passed on here? Causes p.e. problems when this is child of a CGUIWindow.
\r
159 return true; // absorb everything else
\r
163 //! draws the element and its children
\r
164 void CGUIModalScreen::draw()
\r
166 IGUISkin *skin = Environment->getSkin();
\r
171 u32 now = os::Timer::getTime();
\r
172 if (BlinkMode && now - MouseDownTime < 300 && (now / 70)%2)
\r
174 core::list<IGUIElement*>::Iterator it = Children.begin();
\r
176 video::SColor c = Environment->getSkin()->getColor(gui::EGDC_3D_HIGH_LIGHT);
\r
178 for (; it != Children.end(); ++it)
\r
180 if ((*it)->isVisible())
\r
182 r = (*it)->getAbsolutePosition();
\r
183 r.LowerRightCorner.X += 1;
\r
184 r.LowerRightCorner.Y += 1;
\r
185 r.UpperLeftCorner.X -= 1;
\r
186 r.UpperLeftCorner.Y -= 1;
\r
188 skin->draw2DRectangle(this, c, r, &AbsoluteClippingRect);
\r
193 IGUIElement::draw();
\r
197 //! Removes a child.
\r
198 void CGUIModalScreen::removeChild(IGUIElement* child)
\r
200 IGUIElement::removeChild(child);
\r
202 if (Children.empty())
\r
210 void CGUIModalScreen::addChild(IGUIElement* child)
\r
212 IGUIElement::addChild(child);
\r
213 Environment->setFocus(child);
\r
217 void CGUIModalScreen::updateAbsolutePosition()
\r
219 core::rect<s32> parentRect(0,0,0,0);
\r
223 parentRect = Parent->getAbsolutePosition();
\r
224 RelativeRect.UpperLeftCorner.X = 0;
\r
225 RelativeRect.UpperLeftCorner.Y = 0;
\r
226 RelativeRect.LowerRightCorner.X = parentRect.getWidth();
\r
227 RelativeRect.LowerRightCorner.Y = parentRect.getHeight();
\r
230 IGUIElement::updateAbsolutePosition();
\r
234 //! Writes attributes of the element.
\r
235 void CGUIModalScreen::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
\r
237 IGUIElement::serializeAttributes(out,options);
\r
239 out->addInt("BlinkMode", BlinkMode );
\r
242 //! Reads attributes of the element
\r
243 void CGUIModalScreen::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
\r
245 IGUIElement::deserializeAttributes(in, options);
\r
247 BlinkMode = in->getAttributeAsInt("BlinkMode", BlinkMode);
\r
251 } // end namespace gui
\r
252 } // end namespace irr
\r
254 #endif // _IRR_COMPILE_WITH_GUI_
\r