1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #include "CGUIModalScreen.h"
6 #ifdef _IRR_COMPILE_WITH_GUI_
7 
8 #include "IGUIEnvironment.h"
9 #include "os.h"
10 #include "IVideoDriver.h"
11 #include "IGUISkin.h"
12 
13 namespace irr
14 {
15 namespace gui
16 {
17 
18 //! constructor
CGUIModalScreen(IGUIEnvironment * environment,IGUIElement * parent,s32 id)19 CGUIModalScreen::CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id)
20 : IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, core::recti(0, 0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight()) ),
21 	MouseDownTime(0)
22 {
23 	#ifdef _DEBUG
24 	setDebugName("CGUIModalScreen");
25 	#endif
26 	setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
27 
28 	// this element is a tab group
29 	setTabGroup(true);
30 }
31 
canTakeFocus(IGUIElement * target) const32 bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const
33 {
34     return (target && ((const IGUIElement*)target == this // this element can take it
35                         || isMyChild(target)    // own children also
36                         || (target->getType() == EGUIET_MODAL_SCREEN )	// other modals also fine (is now on top or explicitely requested)
37                         || (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN )))   // children of other modals will do
38             ;
39 }
40 
isVisible() const41 bool CGUIModalScreen::isVisible() const
42 {
43     // any parent invisible?
44     IGUIElement * parentElement = getParent();
45     while ( parentElement )
46     {
47         if ( !parentElement->isVisible() )
48             return false;
49         parentElement = parentElement->getParent();
50     }
51 
52     // if we have no children then the modal is probably abused as a way to block input
53     if ( Children.empty() )
54     {
55         return IGUIElement::isVisible();
56     }
57 
58     // any child visible?
59     bool visible = false;
60     core::list<IGUIElement*>::ConstIterator it = Children.begin();
61     for (; it != Children.end(); ++it)
62     {
63         if ( (*it)->isVisible() )
64         {
65             visible = true;
66             break;
67         }
68     }
69     return visible;
70 }
71 
isPointInside(const core::position2d<s32> & point) const72 bool CGUIModalScreen::isPointInside(const core::position2d<s32>& point) const
73 {
74     return true;
75 }
76 
77 //! called if an event happened.
OnEvent(const SEvent & event)78 bool CGUIModalScreen::OnEvent(const SEvent& event)
79 {
80     if (!isEnabled() || !isVisible() )
81         return IGUIElement::OnEvent(event);
82 
83     switch(event.EventType)
84 	{
85 	case EET_GUI_EVENT:
86 		switch(event.GUIEvent.EventType)
87 		{
88 		case EGET_ELEMENT_FOCUSED:
89 			if ( event.GUIEvent.Caller == this && isMyChild(event.GUIEvent.Element) )
90 			{
91 				Environment->removeFocus(0);	// can't setFocus otherwise at it still has focus here
92 				Environment->setFocus(event.GUIEvent.Element);
93 				MouseDownTime = os::Timer::getTime();
94 				return true;
95 			}
96 			if ( !canTakeFocus(event.GUIEvent.Caller))
97 			{
98 				if ( !Children.empty() )
99 					Environment->setFocus(*(Children.begin()));
100 				else
101 					Environment->setFocus(this);
102 			}
103 			IGUIElement::OnEvent(event);
104 			return false;
105 		case EGET_ELEMENT_FOCUS_LOST:
106 			if ( !canTakeFocus(event.GUIEvent.Element))
107             {
108             	if ( isMyChild(event.GUIEvent.Caller) )
109 				{
110 					if ( !Children.empty() )
111 						Environment->setFocus(*(Children.begin()));
112 					else
113 						Environment->setFocus(this);
114 				}
115 				else
116 				{
117 					MouseDownTime = os::Timer::getTime();
118 				}
119 				return true;
120 			}
121 			else
122 			{
123 				return IGUIElement::OnEvent(event);
124 			}
125 		case EGET_ELEMENT_CLOSED:
126 			// do not interfere with children being removed
127 			return IGUIElement::OnEvent(event);
128 		default:
129 			break;
130 		}
131 		break;
132 	case EET_MOUSE_INPUT_EVENT:
133 		if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
134 		{
135 			MouseDownTime = os::Timer::getTime();
136         }
137 	default:
138 		break;
139 	}
140 
141 	IGUIElement::OnEvent(event);	// anyone knows why events are passed on here? Causes p.e. problems when this is child of a CGUIWindow.
142 
143 	return true; // absorb everything else
144 }
145 
146 
147 //! draws the element and its children
draw()148 void CGUIModalScreen::draw()
149 {
150 	IGUISkin *skin = Environment->getSkin();
151 
152 	if (!skin)
153 		return;
154 
155 	u32 now = os::Timer::getTime();
156 	if (now - MouseDownTime < 300 && (now / 70)%2)
157 	{
158 		core::list<IGUIElement*>::Iterator it = Children.begin();
159 		core::rect<s32> r;
160 		video::SColor c = Environment->getSkin()->getColor(gui::EGDC_3D_HIGH_LIGHT);
161 
162 		for (; it != Children.end(); ++it)
163 		{
164 			if ((*it)->isVisible())
165 			{
166 				r = (*it)->getAbsolutePosition();
167 				r.LowerRightCorner.X += 1;
168 				r.LowerRightCorner.Y += 1;
169 				r.UpperLeftCorner.X -= 1;
170 				r.UpperLeftCorner.Y -= 1;
171 
172 				skin->draw2DRectangle(this, c, r, &AbsoluteClippingRect);
173 			}
174 		}
175 	}
176 
177 	IGUIElement::draw();
178 }
179 
180 
181 //! Removes a child.
removeChild(IGUIElement * child)182 void CGUIModalScreen::removeChild(IGUIElement* child)
183 {
184 	IGUIElement::removeChild(child);
185 
186 	if (Children.empty())
187 	{
188 		remove();
189 	}
190 }
191 
192 
193 //! adds a child
addChild(IGUIElement * child)194 void CGUIModalScreen::addChild(IGUIElement* child)
195 {
196 	IGUIElement::addChild(child);
197 	Environment->setFocus(child);
198 }
199 
200 
updateAbsolutePosition()201 void CGUIModalScreen::updateAbsolutePosition()
202 {
203 	core::rect<s32> parentRect(0,0,0,0);
204 
205 	if (Parent)
206 	{
207 		parentRect = Parent->getAbsolutePosition();
208 		RelativeRect.UpperLeftCorner.X = 0;
209 		RelativeRect.UpperLeftCorner.Y = 0;
210 		RelativeRect.LowerRightCorner.X = parentRect.getWidth();
211 		RelativeRect.LowerRightCorner.Y = parentRect.getHeight();
212 	}
213 
214 	IGUIElement::updateAbsolutePosition();
215 }
216 
217 
218 //! Writes attributes of the element.
serializeAttributes(io::IAttributes * out,io::SAttributeReadWriteOptions * options=0) const219 void CGUIModalScreen::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
220 {
221 	IGUIElement::serializeAttributes(out,options);
222 }
223 
224 //! Reads attributes of the element
deserializeAttributes(io::IAttributes * in,io::SAttributeReadWriteOptions * options=0)225 void CGUIModalScreen::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
226 {
227 	IGUIElement::deserializeAttributes(in, options);
228 }
229 
230 
231 } // end namespace gui
232 } // end namespace irr
233 
234 #endif // _IRR_COMPILE_WITH_GUI_
235 
236