diff options
Diffstat (limited to 'libraries/irrlicht-1.8.1/source/Irrlicht/CGUIMessageBox.cpp')
-rw-r--r-- | libraries/irrlicht-1.8.1/source/Irrlicht/CGUIMessageBox.cpp | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIMessageBox.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIMessageBox.cpp new file mode 100644 index 0000000..57b383d --- /dev/null +++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIMessageBox.cpp | |||
@@ -0,0 +1,463 @@ | |||
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 "CGUIMessageBox.h" | ||
6 | #ifdef _IRR_COMPILE_WITH_GUI_ | ||
7 | |||
8 | #include "IGUISkin.h" | ||
9 | #include "IGUIEnvironment.h" | ||
10 | #include "IGUIButton.h" | ||
11 | #include "IGUIFont.h" | ||
12 | #include "ITexture.h" | ||
13 | |||
14 | namespace irr | ||
15 | { | ||
16 | namespace gui | ||
17 | { | ||
18 | |||
19 | //! constructor | ||
20 | CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption, | ||
21 | const wchar_t* text, s32 flags, | ||
22 | IGUIElement* parent, s32 id, core::rect<s32> rectangle, video::ITexture* image) | ||
23 | : CGUIWindow(environment, parent, id, rectangle), | ||
24 | OkButton(0), CancelButton(0), YesButton(0), NoButton(0), StaticText(0), | ||
25 | Icon(0), IconTexture(image), | ||
26 | Flags(flags), MessageText(text), Pressed(false) | ||
27 | { | ||
28 | #ifdef _DEBUG | ||
29 | setDebugName("CGUIMessageBox"); | ||
30 | #endif | ||
31 | |||
32 | // set element type | ||
33 | Type = EGUIET_MESSAGE_BOX; | ||
34 | |||
35 | // remove focus | ||
36 | Environment->setFocus(0); | ||
37 | |||
38 | // remove buttons | ||
39 | |||
40 | getMaximizeButton()->remove(); | ||
41 | getMinimizeButton()->remove(); | ||
42 | |||
43 | if (caption) | ||
44 | setText(caption); | ||
45 | |||
46 | Environment->setFocus(this); | ||
47 | |||
48 | if ( IconTexture ) | ||
49 | IconTexture->grab(); | ||
50 | |||
51 | refreshControls(); | ||
52 | } | ||
53 | |||
54 | |||
55 | //! destructor | ||
56 | CGUIMessageBox::~CGUIMessageBox() | ||
57 | { | ||
58 | if (StaticText) | ||
59 | StaticText->drop(); | ||
60 | |||
61 | if (OkButton) | ||
62 | OkButton->drop(); | ||
63 | |||
64 | if (CancelButton) | ||
65 | CancelButton->drop(); | ||
66 | |||
67 | if (YesButton) | ||
68 | YesButton->drop(); | ||
69 | |||
70 | if (NoButton) | ||
71 | NoButton->drop(); | ||
72 | |||
73 | if (Icon) | ||
74 | Icon->drop(); | ||
75 | |||
76 | if ( IconTexture ) | ||
77 | IconTexture->drop(); | ||
78 | } | ||
79 | |||
80 | void CGUIMessageBox::setButton(IGUIButton*& button, bool isAvailable, const core::rect<s32> & btnRect, const wchar_t * text, IGUIElement*& focusMe) | ||
81 | { | ||
82 | // add/remove ok button | ||
83 | if (isAvailable) | ||
84 | { | ||
85 | if (!button) | ||
86 | { | ||
87 | button = Environment->addButton(btnRect, this); | ||
88 | button->setSubElement(true); | ||
89 | button->grab(); | ||
90 | } | ||
91 | else | ||
92 | button->setRelativePosition(btnRect); | ||
93 | |||
94 | button->setText(text); | ||
95 | |||
96 | focusMe = button; | ||
97 | } | ||
98 | else if (button) | ||
99 | { | ||
100 | button->drop(); | ||
101 | button->remove(); | ||
102 | button =0; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void CGUIMessageBox::refreshControls() | ||
107 | { | ||
108 | // Layout can be seen as 4 boxes (a layoutmanager would be nice) | ||
109 | // One box at top over the whole width for title | ||
110 | // Two boxes with same height at the middle beside each other for icon and for text | ||
111 | // One box at the bottom for the buttons | ||
112 | |||
113 | const IGUISkin* skin = Environment->getSkin(); | ||
114 | |||
115 | const s32 buttonHeight = skin->getSize(EGDS_BUTTON_HEIGHT); | ||
116 | const s32 buttonWidth = skin->getSize(EGDS_BUTTON_WIDTH); | ||
117 | const s32 titleHeight = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2; // titlebar has no own constant | ||
118 | const s32 buttonDistance = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); | ||
119 | const s32 borderWidth = skin->getSize(EGDS_MESSAGE_BOX_GAP_SPACE); | ||
120 | |||
121 | // add the static text for the message | ||
122 | core::rect<s32> staticRect; | ||
123 | staticRect.UpperLeftCorner.X = borderWidth; | ||
124 | staticRect.UpperLeftCorner.Y = titleHeight + borderWidth; | ||
125 | staticRect.LowerRightCorner.X = staticRect.UpperLeftCorner.X + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH); | ||
126 | staticRect.LowerRightCorner.Y = staticRect.UpperLeftCorner.Y + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT); | ||
127 | if (!StaticText) | ||
128 | { | ||
129 | StaticText = Environment->addStaticText(MessageText.c_str(), staticRect, false, false, this); | ||
130 | |||
131 | StaticText->setWordWrap(true); | ||
132 | StaticText->setSubElement(true); | ||
133 | StaticText->grab(); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | StaticText->setRelativePosition(staticRect); | ||
138 | StaticText->setText(MessageText.c_str()); | ||
139 | } | ||
140 | |||
141 | s32 textHeight = StaticText->getTextHeight(); | ||
142 | s32 textWidth = StaticText->getTextWidth() + 6; // +6 because the static itself needs that | ||
143 | const s32 iconHeight = IconTexture ? IconTexture->getOriginalSize().Height : 0; | ||
144 | |||
145 | if ( textWidth < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) ) | ||
146 | textWidth = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) + 6; | ||
147 | // no neeed to check for max because it couldn't get larger due to statictextbox. | ||
148 | if ( textHeight < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT) ) | ||
149 | textHeight = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT); | ||
150 | if ( textHeight > skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT) ) | ||
151 | textHeight = skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT); | ||
152 | |||
153 | // content is text + icons + borders (but not titlebar) | ||
154 | s32 contentHeight = textHeight > iconHeight ? textHeight : iconHeight; | ||
155 | contentHeight += borderWidth; | ||
156 | s32 contentWidth = 0; | ||
157 | |||
158 | // add icon | ||
159 | if ( IconTexture ) | ||
160 | { | ||
161 | core::position2d<s32> iconPos; | ||
162 | iconPos.Y = titleHeight + borderWidth; | ||
163 | if ( iconHeight < textHeight ) | ||
164 | iconPos.Y += (textHeight-iconHeight) / 2; | ||
165 | iconPos.X = borderWidth; | ||
166 | |||
167 | if (!Icon) | ||
168 | { | ||
169 | Icon = Environment->addImage(IconTexture, iconPos, true, this); | ||
170 | Icon->setSubElement(true); | ||
171 | Icon->grab(); | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | core::rect<s32> iconRect( iconPos.X, iconPos.Y, iconPos.X + IconTexture->getOriginalSize().Width, iconPos.Y + IconTexture->getOriginalSize().Height ); | ||
176 | Icon->setRelativePosition(iconRect); | ||
177 | } | ||
178 | |||
179 | contentWidth += borderWidth + IconTexture->getOriginalSize().Width; | ||
180 | } | ||
181 | else if ( Icon ) | ||
182 | { | ||
183 | Icon->drop(); | ||
184 | Icon->remove(); | ||
185 | Icon = 0; | ||
186 | } | ||
187 | |||
188 | // position text | ||
189 | core::rect<s32> textRect; | ||
190 | textRect.UpperLeftCorner.X = contentWidth + borderWidth; | ||
191 | textRect.UpperLeftCorner.Y = titleHeight + borderWidth; | ||
192 | if ( textHeight < iconHeight ) | ||
193 | textRect.UpperLeftCorner.Y += (iconHeight-textHeight) / 2; | ||
194 | textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X + textWidth; | ||
195 | textRect.LowerRightCorner.Y = textRect.UpperLeftCorner.Y + textHeight; | ||
196 | contentWidth += 2*borderWidth + textWidth; | ||
197 | StaticText->setRelativePosition( textRect ); | ||
198 | |||
199 | // find out button size needs | ||
200 | s32 countButtons = 0; | ||
201 | if (Flags & EMBF_OK) | ||
202 | ++countButtons; | ||
203 | if (Flags & EMBF_CANCEL) | ||
204 | ++countButtons; | ||
205 | if (Flags & EMBF_YES) | ||
206 | ++countButtons; | ||
207 | if (Flags & EMBF_NO) | ||
208 | ++countButtons; | ||
209 | |||
210 | s32 buttonBoxWidth = countButtons * buttonWidth + 2 * borderWidth; | ||
211 | if ( countButtons > 1 ) | ||
212 | buttonBoxWidth += (countButtons-1) * buttonDistance; | ||
213 | s32 buttonBoxHeight = buttonHeight + 2 * borderWidth; | ||
214 | |||
215 | // calc new message box sizes | ||
216 | core::rect<s32> tmp = getRelativePosition(); | ||
217 | s32 msgBoxHeight = titleHeight + contentHeight + buttonBoxHeight; | ||
218 | s32 msgBoxWidth = contentWidth > buttonBoxWidth ? contentWidth : buttonBoxWidth; | ||
219 | |||
220 | // adjust message box position | ||
221 | tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2; | ||
222 | tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight; | ||
223 | tmp.UpperLeftCorner.X = (Parent->getAbsolutePosition().getWidth() - msgBoxWidth) / 2; | ||
224 | tmp.LowerRightCorner.X = tmp.UpperLeftCorner.X + msgBoxWidth; | ||
225 | setRelativePosition(tmp); | ||
226 | |||
227 | // add buttons | ||
228 | |||
229 | core::rect<s32> btnRect; | ||
230 | btnRect.UpperLeftCorner.Y = titleHeight + contentHeight + borderWidth; | ||
231 | btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight; | ||
232 | btnRect.UpperLeftCorner.X = borderWidth; | ||
233 | if ( contentWidth > buttonBoxWidth ) | ||
234 | btnRect.UpperLeftCorner.X += (contentWidth - buttonBoxWidth) / 2; // center buttons | ||
235 | btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth; | ||
236 | |||
237 | IGUIElement* focusMe = 0; | ||
238 | setButton(OkButton, (Flags & EMBF_OK) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_OK), focusMe); | ||
239 | if ( Flags & EMBF_OK ) | ||
240 | btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0); | ||
241 | setButton(CancelButton, (Flags & EMBF_CANCEL) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_CANCEL), focusMe); | ||
242 | if ( Flags & EMBF_CANCEL ) | ||
243 | btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0); | ||
244 | setButton(YesButton, (Flags & EMBF_YES) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_YES), focusMe); | ||
245 | if ( Flags & EMBF_YES ) | ||
246 | btnRect += core::position2d<s32>(buttonWidth + buttonDistance, 0); | ||
247 | setButton(NoButton, (Flags & EMBF_NO) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_NO), focusMe); | ||
248 | |||
249 | if (Environment->hasFocus(this) && focusMe) | ||
250 | Environment->setFocus(focusMe); | ||
251 | } | ||
252 | |||
253 | |||
254 | //! called if an event happened. | ||
255 | bool CGUIMessageBox::OnEvent(const SEvent& event) | ||
256 | { | ||
257 | if (isEnabled()) | ||
258 | { | ||
259 | SEvent outevent; | ||
260 | outevent.EventType = EET_GUI_EVENT; | ||
261 | outevent.GUIEvent.Caller = this; | ||
262 | outevent.GUIEvent.Element = 0; | ||
263 | |||
264 | switch(event.EventType) | ||
265 | { | ||
266 | case EET_KEY_INPUT_EVENT: | ||
267 | |||
268 | if (event.KeyInput.PressedDown) | ||
269 | { | ||
270 | switch (event.KeyInput.Key) | ||
271 | { | ||
272 | case KEY_RETURN: | ||
273 | if (OkButton) | ||
274 | { | ||
275 | OkButton->setPressed(true); | ||
276 | Pressed = true; | ||
277 | } | ||
278 | break; | ||
279 | case KEY_KEY_Y: | ||
280 | if (YesButton) | ||
281 | { | ||
282 | YesButton->setPressed(true); | ||
283 | Pressed = true; | ||
284 | } | ||
285 | break; | ||
286 | case KEY_KEY_N: | ||
287 | if (NoButton) | ||
288 | { | ||
289 | NoButton->setPressed(true); | ||
290 | Pressed = true; | ||
291 | } | ||
292 | break; | ||
293 | case KEY_ESCAPE: | ||
294 | if (Pressed) | ||
295 | { | ||
296 | // cancel press | ||
297 | if (OkButton) OkButton->setPressed(false); | ||
298 | if (YesButton) YesButton->setPressed(false); | ||
299 | if (NoButton) NoButton->setPressed(false); | ||
300 | Pressed = false; | ||
301 | } | ||
302 | else | ||
303 | if (CancelButton) | ||
304 | { | ||
305 | CancelButton->setPressed(true); | ||
306 | Pressed = true; | ||
307 | } | ||
308 | else | ||
309 | if (CloseButton && CloseButton->isVisible()) | ||
310 | { | ||
311 | CloseButton->setPressed(true); | ||
312 | Pressed = true; | ||
313 | } | ||
314 | break; | ||
315 | default: // no other key is handled here | ||
316 | break; | ||
317 | } | ||
318 | } | ||
319 | else | ||
320 | if (Pressed) | ||
321 | { | ||
322 | if (OkButton && event.KeyInput.Key == KEY_RETURN) | ||
323 | { | ||
324 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
325 | Environment->setFocus(0); | ||
326 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK; | ||
327 | Parent->OnEvent(outevent); | ||
328 | remove(); | ||
329 | return true; | ||
330 | } | ||
331 | else | ||
332 | if ((CancelButton || CloseButton) && event.KeyInput.Key == KEY_ESCAPE) | ||
333 | { | ||
334 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
335 | Environment->setFocus(0); | ||
336 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL; | ||
337 | Parent->OnEvent(outevent); | ||
338 | remove(); | ||
339 | return true; | ||
340 | } | ||
341 | else | ||
342 | if (YesButton && event.KeyInput.Key == KEY_KEY_Y) | ||
343 | { | ||
344 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
345 | Environment->setFocus(0); | ||
346 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES; | ||
347 | Parent->OnEvent(outevent); | ||
348 | remove(); | ||
349 | return true; | ||
350 | } | ||
351 | else | ||
352 | if (NoButton && event.KeyInput.Key == KEY_KEY_N) | ||
353 | { | ||
354 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
355 | Environment->setFocus(0); | ||
356 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO; | ||
357 | Parent->OnEvent(outevent); | ||
358 | remove(); | ||
359 | return true; | ||
360 | } | ||
361 | } | ||
362 | break; | ||
363 | case EET_GUI_EVENT: | ||
364 | if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) | ||
365 | { | ||
366 | if (event.GUIEvent.Caller == OkButton) | ||
367 | { | ||
368 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
369 | Environment->setFocus(0); | ||
370 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK; | ||
371 | Parent->OnEvent(outevent); | ||
372 | remove(); | ||
373 | return true; | ||
374 | } | ||
375 | else | ||
376 | if (event.GUIEvent.Caller == CancelButton || | ||
377 | event.GUIEvent.Caller == CloseButton) | ||
378 | { | ||
379 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
380 | Environment->setFocus(0); | ||
381 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL; | ||
382 | Parent->OnEvent(outevent); | ||
383 | remove(); | ||
384 | return true; | ||
385 | } | ||
386 | else | ||
387 | if (event.GUIEvent.Caller == YesButton) | ||
388 | { | ||
389 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
390 | Environment->setFocus(0); | ||
391 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES; | ||
392 | Parent->OnEvent(outevent); | ||
393 | remove(); | ||
394 | return true; | ||
395 | } | ||
396 | else | ||
397 | if (event.GUIEvent.Caller == NoButton) | ||
398 | { | ||
399 | setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC | ||
400 | Environment->setFocus(0); | ||
401 | outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO; | ||
402 | Parent->OnEvent(outevent); | ||
403 | remove(); | ||
404 | return true; | ||
405 | } | ||
406 | } | ||
407 | break; | ||
408 | default: | ||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | return CGUIWindow::OnEvent(event); | ||
414 | } | ||
415 | |||
416 | |||
417 | //! Writes attributes of the element. | ||
418 | void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const | ||
419 | { | ||
420 | CGUIWindow::serializeAttributes(out,options); | ||
421 | |||
422 | out->addBool ("OkayButton", (Flags & EMBF_OK) != 0 ); | ||
423 | out->addBool ("CancelButton", (Flags & EMBF_CANCEL) != 0 ); | ||
424 | out->addBool ("YesButton", (Flags & EMBF_YES) != 0 ); | ||
425 | out->addBool ("NoButton", (Flags & EMBF_NO) != 0 ); | ||
426 | out->addTexture ("Texture", IconTexture); | ||
427 | |||
428 | out->addString ("MessageText", MessageText.c_str()); | ||
429 | } | ||
430 | |||
431 | |||
432 | //! Reads attributes of the element | ||
433 | void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) | ||
434 | { | ||
435 | Flags = 0; | ||
436 | |||
437 | Flags = in->getAttributeAsBool("OkayButton") ? EMBF_OK : 0; | ||
438 | Flags |= in->getAttributeAsBool("CancelButton")? EMBF_CANCEL : 0; | ||
439 | Flags |= in->getAttributeAsBool("YesButton") ? EMBF_YES : 0; | ||
440 | Flags |= in->getAttributeAsBool("NoButton") ? EMBF_NO : 0; | ||
441 | |||
442 | if ( IconTexture ) | ||
443 | { | ||
444 | IconTexture->drop(); | ||
445 | IconTexture = NULL; | ||
446 | } | ||
447 | IconTexture = in->getAttributeAsTexture("Texture"); | ||
448 | if ( IconTexture ) | ||
449 | IconTexture->grab(); | ||
450 | |||
451 | MessageText = in->getAttributeAsStringW("MessageText").c_str(); | ||
452 | |||
453 | CGUIWindow::deserializeAttributes(in,options); | ||
454 | |||
455 | refreshControls(); | ||
456 | } | ||
457 | |||
458 | |||
459 | } // end namespace gui | ||
460 | } // end namespace irr | ||
461 | |||
462 | #endif // _IRR_COMPILE_WITH_GUI_ | ||
463 | |||