diff options
Diffstat (limited to 'libraries/irrlicht-1.8.1/source/Irrlicht/CGUIEnvironment.cpp')
-rw-r--r-- | libraries/irrlicht-1.8.1/source/Irrlicht/CGUIEnvironment.cpp | 1658 |
1 files changed, 0 insertions, 1658 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIEnvironment.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIEnvironment.cpp deleted file mode 100644 index bf3fa86..0000000 --- a/libraries/irrlicht-1.8.1/source/Irrlicht/CGUIEnvironment.cpp +++ /dev/null | |||
@@ -1,1658 +0,0 @@ | |||
1 | |||
2 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
3 | // This file is part of the "Irrlicht Engine". | ||
4 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
5 | |||
6 | #include "CGUIEnvironment.h" | ||
7 | |||
8 | #ifdef _IRR_COMPILE_WITH_GUI_ | ||
9 | |||
10 | #include "IVideoDriver.h" | ||
11 | |||
12 | #include "CGUISkin.h" | ||
13 | #include "CGUIButton.h" | ||
14 | #include "CGUIWindow.h" | ||
15 | #include "CGUIScrollBar.h" | ||
16 | #include "CGUIFont.h" | ||
17 | #include "CGUISpriteBank.h" | ||
18 | #include "CGUIImage.h" | ||
19 | #include "CGUIMeshViewer.h" | ||
20 | #include "CGUICheckBox.h" | ||
21 | #include "CGUIListBox.h" | ||
22 | #include "CGUITreeView.h" | ||
23 | #include "CGUIImageList.h" | ||
24 | #include "CGUIFileOpenDialog.h" | ||
25 | #include "CGUIColorSelectDialog.h" | ||
26 | #include "CGUIStaticText.h" | ||
27 | #include "CGUIEditBox.h" | ||
28 | #include "CGUISpinBox.h" | ||
29 | #include "CGUIInOutFader.h" | ||
30 | #include "CGUIMessageBox.h" | ||
31 | #include "CGUIModalScreen.h" | ||
32 | #include "CGUITabControl.h" | ||
33 | #include "CGUIContextMenu.h" | ||
34 | #include "CGUIComboBox.h" | ||
35 | #include "CGUIMenu.h" | ||
36 | #include "CGUIToolBar.h" | ||
37 | #include "CGUITable.h" | ||
38 | |||
39 | #include "CDefaultGUIElementFactory.h" | ||
40 | #include "IWriteFile.h" | ||
41 | #include "IXMLWriter.h" | ||
42 | |||
43 | #include "BuiltInFont.h" | ||
44 | #include "os.h" | ||
45 | |||
46 | namespace irr | ||
47 | { | ||
48 | namespace gui | ||
49 | { | ||
50 | |||
51 | const wchar_t* IRR_XML_FORMAT_GUI_ENV = L"irr_gui"; | ||
52 | const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT = L"element"; | ||
53 | const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE = L"type"; | ||
54 | |||
55 | const io::path CGUIEnvironment::DefaultFontName = "#DefaultFont"; | ||
56 | |||
57 | //! constructor | ||
58 | CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op) | ||
59 | : IGUIElement(EGUIET_ROOT, 0, 0, 0, core::rect<s32>(core::position2d<s32>(0,0), driver ? core::dimension2d<s32>(driver->getScreenSize()) : core::dimension2d<s32>(0,0))), | ||
60 | Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0), | ||
61 | FileSystem(fs), UserReceiver(0), Operator(op) | ||
62 | { | ||
63 | if (Driver) | ||
64 | Driver->grab(); | ||
65 | |||
66 | if (FileSystem) | ||
67 | FileSystem->grab(); | ||
68 | |||
69 | if (Operator) | ||
70 | Operator->grab(); | ||
71 | |||
72 | #ifdef _DEBUG | ||
73 | IGUIEnvironment::setDebugName("CGUIEnvironment"); | ||
74 | #endif | ||
75 | |||
76 | // gui factory | ||
77 | IGUIElementFactory* factory = new CDefaultGUIElementFactory(this); | ||
78 | registerGUIElementFactory(factory); | ||
79 | factory->drop(); | ||
80 | |||
81 | loadBuiltInFont(); | ||
82 | |||
83 | IGUISkin* skin = createSkin( gui::EGST_WINDOWS_METALLIC ); | ||
84 | setSkin(skin); | ||
85 | skin->drop(); | ||
86 | |||
87 | //set tooltip default | ||
88 | ToolTip.LastTime = 0; | ||
89 | ToolTip.EnterTime = 0; | ||
90 | ToolTip.LaunchTime = 1000; | ||
91 | ToolTip.RelaunchTime = 500; | ||
92 | ToolTip.Element = 0; | ||
93 | |||
94 | // environment is root tab group | ||
95 | Environment = this; | ||
96 | setTabGroup(true); | ||
97 | } | ||
98 | |||
99 | |||
100 | //! destructor | ||
101 | CGUIEnvironment::~CGUIEnvironment() | ||
102 | { | ||
103 | if ( HoveredNoSubelement && HoveredNoSubelement != this ) | ||
104 | { | ||
105 | HoveredNoSubelement->drop(); | ||
106 | HoveredNoSubelement = 0; | ||
107 | } | ||
108 | |||
109 | if (Hovered && Hovered != this) | ||
110 | { | ||
111 | Hovered->drop(); | ||
112 | Hovered = 0; | ||
113 | } | ||
114 | |||
115 | if (Focus) | ||
116 | { | ||
117 | Focus->drop(); | ||
118 | Focus = 0; | ||
119 | } | ||
120 | |||
121 | if (ToolTip.Element) | ||
122 | { | ||
123 | ToolTip.Element->drop(); | ||
124 | ToolTip.Element = 0; | ||
125 | } | ||
126 | |||
127 | // drop skin | ||
128 | if (CurrentSkin) | ||
129 | { | ||
130 | CurrentSkin->drop(); | ||
131 | CurrentSkin = 0; | ||
132 | } | ||
133 | |||
134 | u32 i; | ||
135 | |||
136 | // delete all sprite banks | ||
137 | for (i=0; i<Banks.size(); ++i) | ||
138 | if (Banks[i].Bank) | ||
139 | Banks[i].Bank->drop(); | ||
140 | |||
141 | // delete all fonts | ||
142 | for (i=0; i<Fonts.size(); ++i) | ||
143 | Fonts[i].Font->drop(); | ||
144 | |||
145 | // remove all factories | ||
146 | for (i=0; i<GUIElementFactoryList.size(); ++i) | ||
147 | GUIElementFactoryList[i]->drop(); | ||
148 | |||
149 | if (Operator) | ||
150 | { | ||
151 | Operator->drop(); | ||
152 | Operator = 0; | ||
153 | } | ||
154 | |||
155 | if (FileSystem) | ||
156 | { | ||
157 | FileSystem->drop(); | ||
158 | FileSystem = 0; | ||
159 | } | ||
160 | |||
161 | if (Driver) | ||
162 | { | ||
163 | Driver->drop(); | ||
164 | Driver = 0; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | void CGUIEnvironment::loadBuiltInFont() | ||
170 | { | ||
171 | io::IReadFile* file = io::createMemoryReadFile(BuiltInFontData, BuiltInFontDataSize, DefaultFontName, false); | ||
172 | |||
173 | CGUIFont* font = new CGUIFont(this, DefaultFontName ); | ||
174 | if (!font->load(file)) | ||
175 | { | ||
176 | os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR); | ||
177 | font->drop(); | ||
178 | file->drop(); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | SFont f; | ||
183 | f.NamedPath.setPath(DefaultFontName); | ||
184 | f.Font = font; | ||
185 | Fonts.push_back(f); | ||
186 | |||
187 | file->drop(); | ||
188 | } | ||
189 | |||
190 | |||
191 | //! draws all gui elements | ||
192 | void CGUIEnvironment::drawAll() | ||
193 | { | ||
194 | if (Driver) | ||
195 | { | ||
196 | core::dimension2d<s32> dim(Driver->getScreenSize()); | ||
197 | if (AbsoluteRect.LowerRightCorner.X != dim.Width || | ||
198 | AbsoluteRect.LowerRightCorner.Y != dim.Height) | ||
199 | { | ||
200 | // resize gui environment | ||
201 | DesiredRect.LowerRightCorner = dim; | ||
202 | AbsoluteClippingRect = DesiredRect; | ||
203 | AbsoluteRect = DesiredRect; | ||
204 | updateAbsolutePosition(); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | // make sure tooltip is always on top | ||
209 | if (ToolTip.Element) | ||
210 | bringToFront(ToolTip.Element); | ||
211 | |||
212 | draw(); | ||
213 | OnPostRender ( os::Timer::getTime () ); | ||
214 | } | ||
215 | |||
216 | |||
217 | //! sets the focus to an element | ||
218 | bool CGUIEnvironment::setFocus(IGUIElement* element) | ||
219 | { | ||
220 | if (Focus == element) | ||
221 | { | ||
222 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
223 | return false; | ||
224 | } | ||
225 | |||
226 | // GUI Environment should not get the focus | ||
227 | if (element == this) | ||
228 | element = 0; | ||
229 | |||
230 | // stop element from being deleted | ||
231 | if (element) | ||
232 | element->grab(); | ||
233 | |||
234 | // focus may change or be removed in this call | ||
235 | IGUIElement *currentFocus = 0; | ||
236 | if (Focus) | ||
237 | { | ||
238 | currentFocus = Focus; | ||
239 | currentFocus->grab(); | ||
240 | SEvent e; | ||
241 | e.EventType = EET_GUI_EVENT; | ||
242 | e.GUIEvent.Caller = Focus; | ||
243 | e.GUIEvent.Element = element; | ||
244 | e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST; | ||
245 | if (Focus->OnEvent(e)) | ||
246 | { | ||
247 | if (element) | ||
248 | element->drop(); | ||
249 | currentFocus->drop(); | ||
250 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
251 | return false; | ||
252 | } | ||
253 | currentFocus->drop(); | ||
254 | currentFocus = 0; | ||
255 | } | ||
256 | |||
257 | if (element) | ||
258 | { | ||
259 | currentFocus = Focus; | ||
260 | if (currentFocus) | ||
261 | currentFocus->grab(); | ||
262 | |||
263 | // send focused event | ||
264 | SEvent e; | ||
265 | e.EventType = EET_GUI_EVENT; | ||
266 | e.GUIEvent.Caller = element; | ||
267 | e.GUIEvent.Element = Focus; | ||
268 | e.GUIEvent.EventType = EGET_ELEMENT_FOCUSED; | ||
269 | if (element->OnEvent(e)) | ||
270 | { | ||
271 | if (element) | ||
272 | element->drop(); | ||
273 | if (currentFocus) | ||
274 | currentFocus->drop(); | ||
275 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
276 | return false; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | if (currentFocus) | ||
281 | currentFocus->drop(); | ||
282 | |||
283 | if (Focus) | ||
284 | Focus->drop(); | ||
285 | |||
286 | // element is the new focus so it doesn't have to be dropped | ||
287 | Focus = element; | ||
288 | |||
289 | return true; | ||
290 | } | ||
291 | |||
292 | |||
293 | //! returns the element with the focus | ||
294 | IGUIElement* CGUIEnvironment::getFocus() const | ||
295 | { | ||
296 | return Focus; | ||
297 | } | ||
298 | |||
299 | //! returns the element last known to be under the mouse cursor | ||
300 | IGUIElement* CGUIEnvironment::getHovered() const | ||
301 | { | ||
302 | return Hovered; | ||
303 | } | ||
304 | |||
305 | |||
306 | //! removes the focus from an element | ||
307 | bool CGUIEnvironment::removeFocus(IGUIElement* element) | ||
308 | { | ||
309 | if (Focus && Focus==element) | ||
310 | { | ||
311 | SEvent e; | ||
312 | e.EventType = EET_GUI_EVENT; | ||
313 | e.GUIEvent.Caller = Focus; | ||
314 | e.GUIEvent.Element = 0; | ||
315 | e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST; | ||
316 | if (Focus->OnEvent(e)) | ||
317 | { | ||
318 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
319 | return false; | ||
320 | } | ||
321 | } | ||
322 | if (Focus) | ||
323 | { | ||
324 | Focus->drop(); | ||
325 | Focus = 0; | ||
326 | } | ||
327 | |||
328 | return true; | ||
329 | } | ||
330 | |||
331 | |||
332 | //! Returns if the element has focus | ||
333 | bool CGUIEnvironment::hasFocus(IGUIElement* element) const | ||
334 | { | ||
335 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
336 | return (element == Focus); | ||
337 | } | ||
338 | |||
339 | |||
340 | //! returns the current video driver | ||
341 | video::IVideoDriver* CGUIEnvironment::getVideoDriver() const | ||
342 | { | ||
343 | return Driver; | ||
344 | } | ||
345 | |||
346 | |||
347 | //! returns the current file system | ||
348 | io::IFileSystem* CGUIEnvironment::getFileSystem() const | ||
349 | { | ||
350 | return FileSystem; | ||
351 | } | ||
352 | |||
353 | |||
354 | //! returns a pointer to the OS operator | ||
355 | IOSOperator* CGUIEnvironment::getOSOperator() const | ||
356 | { | ||
357 | return Operator; | ||
358 | } | ||
359 | |||
360 | |||
361 | //! clear all GUI elements | ||
362 | void CGUIEnvironment::clear() | ||
363 | { | ||
364 | // Remove the focus | ||
365 | if (Focus) | ||
366 | { | ||
367 | Focus->drop(); | ||
368 | Focus = 0; | ||
369 | } | ||
370 | |||
371 | if (Hovered && Hovered != this) | ||
372 | { | ||
373 | Hovered->drop(); | ||
374 | Hovered = 0; | ||
375 | } | ||
376 | if ( HoveredNoSubelement && HoveredNoSubelement != this) | ||
377 | { | ||
378 | HoveredNoSubelement->drop(); | ||
379 | HoveredNoSubelement = 0; | ||
380 | } | ||
381 | |||
382 | // get the root's children in case the root changes in future | ||
383 | const core::list<IGUIElement*>& children = getRootGUIElement()->getChildren(); | ||
384 | |||
385 | while (!children.empty()) | ||
386 | (*children.getLast())->remove(); | ||
387 | } | ||
388 | |||
389 | |||
390 | //! called by ui if an event happened. | ||
391 | bool CGUIEnvironment::OnEvent(const SEvent& event) | ||
392 | { | ||
393 | bool ret = false; | ||
394 | if (UserReceiver | ||
395 | && (event.EventType != EET_MOUSE_INPUT_EVENT) | ||
396 | && (event.EventType != EET_KEY_INPUT_EVENT) | ||
397 | && (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this)) | ||
398 | { | ||
399 | ret = UserReceiver->OnEvent(event); | ||
400 | } | ||
401 | |||
402 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | // | ||
407 | void CGUIEnvironment::OnPostRender( u32 time ) | ||
408 | { | ||
409 | // launch tooltip | ||
410 | if ( ToolTip.Element == 0 && | ||
411 | HoveredNoSubelement && HoveredNoSubelement != this && | ||
412 | (time - ToolTip.EnterTime >= ToolTip.LaunchTime | ||
413 | || (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) && | ||
414 | HoveredNoSubelement->getToolTipText().size() && | ||
415 | getSkin() && | ||
416 | getSkin()->getFont(EGDF_TOOLTIP) | ||
417 | ) | ||
418 | { | ||
419 | core::rect<s32> pos; | ||
420 | |||
421 | pos.UpperLeftCorner = LastHoveredMousePos; | ||
422 | core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str()); | ||
423 | dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2; | ||
424 | dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2; | ||
425 | |||
426 | pos.UpperLeftCorner.Y -= dim.Height+1; | ||
427 | pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + dim.Height-1; | ||
428 | pos.LowerRightCorner.X = pos.UpperLeftCorner.X + dim.Width; | ||
429 | |||
430 | pos.constrainTo(getAbsolutePosition()); | ||
431 | |||
432 | ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true); | ||
433 | ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP)); | ||
434 | ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND)); | ||
435 | ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP)); | ||
436 | ToolTip.Element->setSubElement(true); | ||
437 | ToolTip.Element->grab(); | ||
438 | |||
439 | s32 textHeight = ToolTip.Element->getTextHeight(); | ||
440 | pos = ToolTip.Element->getRelativePosition(); | ||
441 | pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight; | ||
442 | ToolTip.Element->setRelativePosition(pos); | ||
443 | } | ||
444 | |||
445 | if (ToolTip.Element && ToolTip.Element->isVisible() ) // (isVisible() check only because we might use visibility for ToolTip one day) | ||
446 | { | ||
447 | ToolTip.LastTime = time; | ||
448 | |||
449 | // got invisible or removed in the meantime? | ||
450 | if ( !HoveredNoSubelement || | ||
451 | !HoveredNoSubelement->isVisible() || | ||
452 | !HoveredNoSubelement->getParent() | ||
453 | ) // got invisible or removed in the meantime? | ||
454 | { | ||
455 | ToolTip.Element->remove(); | ||
456 | ToolTip.Element->drop(); | ||
457 | ToolTip.Element = 0; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | IGUIElement::OnPostRender ( time ); | ||
462 | } | ||
463 | |||
464 | |||
465 | // | ||
466 | void CGUIEnvironment::updateHoveredElement(core::position2d<s32> mousePos) | ||
467 | { | ||
468 | IGUIElement* lastHovered = Hovered; | ||
469 | IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement; | ||
470 | LastHoveredMousePos = mousePos; | ||
471 | |||
472 | Hovered = getElementFromPoint(mousePos); | ||
473 | |||
474 | if ( ToolTip.Element && Hovered == ToolTip.Element ) | ||
475 | { | ||
476 | // When the mouse is over the ToolTip we remove that so it will be re-created at a new position. | ||
477 | // Note that ToolTip.EnterTime does not get changed here, so it will be re-created at once. | ||
478 | ToolTip.Element->remove(); | ||
479 | ToolTip.Element->drop(); | ||
480 | ToolTip.Element = 0; | ||
481 | |||
482 | // Get the real Hovered | ||
483 | Hovered = getElementFromPoint(mousePos); | ||
484 | } | ||
485 | |||
486 | // for tooltips we want the element itself and not some of it's subelements | ||
487 | HoveredNoSubelement = Hovered; | ||
488 | while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() ) | ||
489 | { | ||
490 | HoveredNoSubelement = HoveredNoSubelement->getParent(); | ||
491 | } | ||
492 | |||
493 | if (Hovered && Hovered != this) | ||
494 | Hovered->grab(); | ||
495 | if ( HoveredNoSubelement && HoveredNoSubelement != this) | ||
496 | HoveredNoSubelement->grab(); | ||
497 | |||
498 | if (Hovered != lastHovered) | ||
499 | { | ||
500 | SEvent event; | ||
501 | event.EventType = EET_GUI_EVENT; | ||
502 | |||
503 | if (lastHovered) | ||
504 | { | ||
505 | event.GUIEvent.Caller = lastHovered; | ||
506 | event.GUIEvent.Element = 0; | ||
507 | event.GUIEvent.EventType = EGET_ELEMENT_LEFT; | ||
508 | lastHovered->OnEvent(event); | ||
509 | } | ||
510 | |||
511 | if ( Hovered ) | ||
512 | { | ||
513 | event.GUIEvent.Caller = Hovered; | ||
514 | event.GUIEvent.Element = Hovered; | ||
515 | event.GUIEvent.EventType = EGET_ELEMENT_HOVERED; | ||
516 | Hovered->OnEvent(event); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | if ( lastHoveredNoSubelement != HoveredNoSubelement ) | ||
521 | { | ||
522 | if (ToolTip.Element) | ||
523 | { | ||
524 | ToolTip.Element->remove(); | ||
525 | ToolTip.Element->drop(); | ||
526 | ToolTip.Element = 0; | ||
527 | } | ||
528 | |||
529 | if ( HoveredNoSubelement ) | ||
530 | { | ||
531 | u32 now = os::Timer::getTime(); | ||
532 | ToolTip.EnterTime = now; | ||
533 | } | ||
534 | } | ||
535 | |||
536 | if (lastHovered && lastHovered != this) | ||
537 | lastHovered->drop(); | ||
538 | if (lastHoveredNoSubelement && lastHoveredNoSubelement != this) | ||
539 | lastHoveredNoSubelement->drop(); | ||
540 | } | ||
541 | |||
542 | |||
543 | //! This sets a new event receiver for gui events. Usually you do not have to | ||
544 | //! use this method, it is used by the internal engine. | ||
545 | void CGUIEnvironment::setUserEventReceiver(IEventReceiver* evr) | ||
546 | { | ||
547 | UserReceiver = evr; | ||
548 | } | ||
549 | |||
550 | |||
551 | //! posts an input event to the environment | ||
552 | bool CGUIEnvironment::postEventFromUser(const SEvent& event) | ||
553 | { | ||
554 | switch(event.EventType) | ||
555 | { | ||
556 | case EET_GUI_EVENT: | ||
557 | // hey, why is the user sending gui events..? | ||
558 | break; | ||
559 | case EET_MOUSE_INPUT_EVENT: | ||
560 | |||
561 | updateHoveredElement(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)); | ||
562 | |||
563 | if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) | ||
564 | if ( (Hovered && Hovered != Focus) || !Focus ) | ||
565 | { | ||
566 | setFocus(Hovered); | ||
567 | } | ||
568 | |||
569 | // sending input to focus | ||
570 | if (Focus && Focus->OnEvent(event)) | ||
571 | return true; | ||
572 | |||
573 | // focus could have died in last call | ||
574 | if (!Focus && Hovered) | ||
575 | { | ||
576 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
577 | return Hovered->OnEvent(event); | ||
578 | } | ||
579 | |||
580 | break; | ||
581 | case EET_KEY_INPUT_EVENT: | ||
582 | { | ||
583 | if (Focus && Focus->OnEvent(event)) | ||
584 | return true; | ||
585 | |||
586 | // For keys we handle the event before changing focus to give elements the chance for catching the TAB | ||
587 | // Send focus changing event | ||
588 | if (event.EventType == EET_KEY_INPUT_EVENT && | ||
589 | event.KeyInput.PressedDown && | ||
590 | event.KeyInput.Key == KEY_TAB) | ||
591 | { | ||
592 | IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control); | ||
593 | if (next && next != Focus) | ||
594 | { | ||
595 | if (setFocus(next)) | ||
596 | return true; | ||
597 | } | ||
598 | } | ||
599 | |||
600 | } | ||
601 | break; | ||
602 | default: | ||
603 | break; | ||
604 | } // end switch | ||
605 | |||
606 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
607 | return false; | ||
608 | } | ||
609 | |||
610 | |||
611 | //! returns the current gui skin | ||
612 | IGUISkin* CGUIEnvironment::getSkin() const | ||
613 | { | ||
614 | return CurrentSkin; | ||
615 | } | ||
616 | |||
617 | |||
618 | //! Sets a new GUI Skin | ||
619 | void CGUIEnvironment::setSkin(IGUISkin* skin) | ||
620 | { | ||
621 | if (CurrentSkin==skin) | ||
622 | return; | ||
623 | |||
624 | if (CurrentSkin) | ||
625 | CurrentSkin->drop(); | ||
626 | |||
627 | CurrentSkin = skin; | ||
628 | |||
629 | if (CurrentSkin) | ||
630 | CurrentSkin->grab(); | ||
631 | } | ||
632 | |||
633 | |||
634 | //! Creates a new GUI Skin based on a template. | ||
635 | /** \return Returns a pointer to the created skin. | ||
636 | If you no longer need the skin, you should call IGUISkin::drop(). | ||
637 | See IReferenceCounted::drop() for more information. */ | ||
638 | IGUISkin* CGUIEnvironment::createSkin(EGUI_SKIN_TYPE type) | ||
639 | { | ||
640 | IGUISkin* skin = new CGUISkin(type, Driver); | ||
641 | |||
642 | IGUIFont* builtinfont = getBuiltInFont(); | ||
643 | IGUIFontBitmap* bitfont = 0; | ||
644 | if (builtinfont && builtinfont->getType() == EGFT_BITMAP) | ||
645 | bitfont = (IGUIFontBitmap*)builtinfont; | ||
646 | |||
647 | IGUISpriteBank* bank = 0; | ||
648 | skin->setFont(builtinfont); | ||
649 | |||
650 | if (bitfont) | ||
651 | bank = bitfont->getSpriteBank(); | ||
652 | |||
653 | skin->setSpriteBank(bank); | ||
654 | |||
655 | return skin; | ||
656 | } | ||
657 | |||
658 | |||
659 | //! Returns the default element factory which can create all built in elements | ||
660 | IGUIElementFactory* CGUIEnvironment::getDefaultGUIElementFactory() const | ||
661 | { | ||
662 | return getGUIElementFactory(0); | ||
663 | } | ||
664 | |||
665 | |||
666 | //! Adds an element factory to the gui environment. | ||
667 | /** Use this to extend the gui environment with new element types which it should be | ||
668 | able to create automaticly, for example when loading data from xml files. */ | ||
669 | void CGUIEnvironment::registerGUIElementFactory(IGUIElementFactory* factoryToAdd) | ||
670 | { | ||
671 | if (factoryToAdd) | ||
672 | { | ||
673 | factoryToAdd->grab(); | ||
674 | GUIElementFactoryList.push_back(factoryToAdd); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | |||
679 | //! Returns amount of registered scene node factories. | ||
680 | u32 CGUIEnvironment::getRegisteredGUIElementFactoryCount() const | ||
681 | { | ||
682 | return GUIElementFactoryList.size(); | ||
683 | } | ||
684 | |||
685 | |||
686 | //! Returns a scene node factory by index | ||
687 | IGUIElementFactory* CGUIEnvironment::getGUIElementFactory(u32 index) const | ||
688 | { | ||
689 | if (index < GUIElementFactoryList.size()) | ||
690 | return GUIElementFactoryList[index]; | ||
691 | else | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | |||
696 | //! adds a GUI Element using its name | ||
697 | IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* parent) | ||
698 | { | ||
699 | IGUIElement* node=0; | ||
700 | |||
701 | if (!parent) | ||
702 | parent = this; | ||
703 | |||
704 | for (s32 i=GUIElementFactoryList.size()-1; i>=0 && !node; --i) | ||
705 | node = GUIElementFactoryList[i]->addGUIElement(elementName, parent); | ||
706 | |||
707 | |||
708 | return node; | ||
709 | } | ||
710 | |||
711 | |||
712 | //! Saves the current gui into a file. | ||
713 | //! \param filename: Name of the file . | ||
714 | bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start) | ||
715 | { | ||
716 | io::IWriteFile* file = FileSystem->createAndWriteFile(filename); | ||
717 | if (!file) | ||
718 | { | ||
719 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
720 | return false; | ||
721 | } | ||
722 | |||
723 | bool ret = saveGUI(file, start); | ||
724 | file->drop(); | ||
725 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
726 | return ret; | ||
727 | } | ||
728 | |||
729 | |||
730 | //! Saves the current gui into a file. | ||
731 | bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start) | ||
732 | { | ||
733 | if (!file) | ||
734 | { | ||
735 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
736 | return false; | ||
737 | } | ||
738 | |||
739 | io::IXMLWriter* writer = FileSystem->createXMLWriter(file); | ||
740 | if (!writer) | ||
741 | { | ||
742 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
743 | return false; | ||
744 | } | ||
745 | |||
746 | writer->writeXMLHeader(); | ||
747 | writeGUIElement(writer, start ? start : this); | ||
748 | writer->drop(); | ||
749 | |||
750 | return true; | ||
751 | } | ||
752 | |||
753 | |||
754 | //! Loads the gui. Note that the current gui is not cleared before. | ||
755 | //! \param filename: Name of the file. | ||
756 | bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent) | ||
757 | { | ||
758 | io::IReadFile* read = FileSystem->createAndOpenFile(filename); | ||
759 | if (!read) | ||
760 | { | ||
761 | os::Printer::log("Unable to open gui file", filename, ELL_ERROR); | ||
762 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
763 | return false; | ||
764 | } | ||
765 | |||
766 | bool ret = loadGUI(read, parent); | ||
767 | read->drop(); | ||
768 | |||
769 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | |||
774 | //! Loads the gui. Note that the current gui is not cleared before. | ||
775 | bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent) | ||
776 | { | ||
777 | if (!file) | ||
778 | { | ||
779 | os::Printer::log("Unable to open GUI file", ELL_ERROR); | ||
780 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
781 | return false; | ||
782 | } | ||
783 | |||
784 | io::IXMLReader* reader = FileSystem->createXMLReader(file); | ||
785 | if (!reader) | ||
786 | { | ||
787 | os::Printer::log("GUI is not a valid XML file", file->getFileName(), ELL_ERROR); | ||
788 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
789 | return false; | ||
790 | } | ||
791 | |||
792 | // read file | ||
793 | while(reader->read()) | ||
794 | { | ||
795 | readGUIElement(reader, parent); | ||
796 | } | ||
797 | |||
798 | // finish up | ||
799 | |||
800 | reader->drop(); | ||
801 | return true; | ||
802 | } | ||
803 | |||
804 | |||
805 | //! reads an element | ||
806 | void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* node) | ||
807 | { | ||
808 | if (!reader) | ||
809 | return; | ||
810 | |||
811 | io::EXML_NODE nodeType = reader->getNodeType(); | ||
812 | |||
813 | if (nodeType == io::EXN_NONE || nodeType == io::EXN_UNKNOWN || nodeType == io::EXN_ELEMENT_END) | ||
814 | return; | ||
815 | |||
816 | IGUIElement* deferedNode = 0; | ||
817 | if (!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) | ||
818 | { | ||
819 | // GuiEnvironment always must be this as it would serialize into a wrong element otherwise. | ||
820 | // So we use the given node next time | ||
821 | if ( node && node != this ) | ||
822 | deferedNode = node; | ||
823 | node = this; // root | ||
824 | } | ||
825 | else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName())) | ||
826 | { | ||
827 | // find node type and create it | ||
828 | const core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE); | ||
829 | |||
830 | node = addGUIElement(attrName.c_str(), node); | ||
831 | |||
832 | if (!node) | ||
833 | os::Printer::log("Could not create GUI element of unknown type", attrName.c_str()); | ||
834 | } | ||
835 | |||
836 | // read attributes | ||
837 | |||
838 | while(reader->read()) | ||
839 | { | ||
840 | bool endreached = false; | ||
841 | |||
842 | switch (reader->getNodeType()) | ||
843 | { | ||
844 | case io::EXN_ELEMENT_END: | ||
845 | if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) || | ||
846 | !wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) | ||
847 | { | ||
848 | endreached = true; | ||
849 | } | ||
850 | break; | ||
851 | case io::EXN_ELEMENT: | ||
852 | if (!wcscmp(L"attributes", reader->getNodeName())) | ||
853 | { | ||
854 | // read attributes | ||
855 | io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); | ||
856 | attr->read(reader, true); | ||
857 | |||
858 | if (node) | ||
859 | node->deserializeAttributes(attr); | ||
860 | |||
861 | attr->drop(); | ||
862 | } | ||
863 | else | ||
864 | if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) || | ||
865 | !wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) | ||
866 | { | ||
867 | if ( deferedNode ) | ||
868 | readGUIElement(reader, deferedNode); | ||
869 | else | ||
870 | readGUIElement(reader, node); | ||
871 | } | ||
872 | else | ||
873 | { | ||
874 | os::Printer::log("Found unknown element in irrlicht GUI file", | ||
875 | core::stringc(reader->getNodeName()).c_str()); | ||
876 | } | ||
877 | |||
878 | break; | ||
879 | default: | ||
880 | break; | ||
881 | } | ||
882 | |||
883 | if (endreached) | ||
884 | break; | ||
885 | } | ||
886 | } | ||
887 | |||
888 | |||
889 | //! writes an element | ||
890 | void CGUIEnvironment::writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) | ||
891 | { | ||
892 | if (!writer || !node ) | ||
893 | return; | ||
894 | |||
895 | const wchar_t* name = 0; | ||
896 | |||
897 | // write properties | ||
898 | |||
899 | io::IAttributes* attr = FileSystem->createEmptyAttributes(); | ||
900 | node->serializeAttributes(attr); | ||
901 | |||
902 | // all gui elements must have at least one attribute | ||
903 | // if they have nothing then we ignore them. | ||
904 | if (attr->getAttributeCount() != 0) | ||
905 | { | ||
906 | if (node == this) | ||
907 | { | ||
908 | name = IRR_XML_FORMAT_GUI_ENV; | ||
909 | writer->writeElement(name, false); | ||
910 | } | ||
911 | else | ||
912 | { | ||
913 | name = IRR_XML_FORMAT_GUI_ELEMENT; | ||
914 | writer->writeElement(name, false, IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE, | ||
915 | core::stringw(node->getTypeName()).c_str()); | ||
916 | } | ||
917 | |||
918 | writer->writeLineBreak(); | ||
919 | writer->writeLineBreak(); | ||
920 | |||
921 | attr->write(writer); | ||
922 | writer->writeLineBreak(); | ||
923 | } | ||
924 | |||
925 | // write children | ||
926 | |||
927 | core::list<IGUIElement*>::ConstIterator it = node->getChildren().begin(); | ||
928 | for (; it != node->getChildren().end(); ++it) | ||
929 | { | ||
930 | if (!(*it)->isSubElement()) | ||
931 | writeGUIElement(writer, (*it)); | ||
932 | } | ||
933 | |||
934 | // write closing brace if required | ||
935 | if (attr->getAttributeCount() != 0) | ||
936 | { | ||
937 | writer->writeClosingTag(name); | ||
938 | writer->writeLineBreak(); | ||
939 | writer->writeLineBreak(); | ||
940 | } | ||
941 | |||
942 | attr->drop(); | ||
943 | } | ||
944 | |||
945 | |||
946 | //! Writes attributes of the environment | ||
947 | void CGUIEnvironment::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const | ||
948 | { | ||
949 | IGUISkin* skin = getSkin(); | ||
950 | |||
951 | if (skin) | ||
952 | { | ||
953 | out->addEnum("Skin", getSkin()->getType(), GUISkinTypeNames); | ||
954 | skin->serializeAttributes(out, options); | ||
955 | } | ||
956 | } | ||
957 | |||
958 | |||
959 | //! Reads attributes of the environment | ||
960 | void CGUIEnvironment::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) | ||
961 | { | ||
962 | if (in->existsAttribute("Skin")) | ||
963 | { | ||
964 | IGUISkin *skin = getSkin(); | ||
965 | |||
966 | EGUI_SKIN_TYPE t = (EGUI_SKIN_TYPE) in->getAttributeAsEnumeration("Skin",GUISkinTypeNames); | ||
967 | if ( !skin || t != skin->getType()) | ||
968 | { | ||
969 | skin = createSkin(t); | ||
970 | setSkin(skin); | ||
971 | skin->drop(); | ||
972 | } | ||
973 | |||
974 | skin = getSkin(); | ||
975 | |||
976 | if (skin) | ||
977 | { | ||
978 | skin->deserializeAttributes(in, options); | ||
979 | } | ||
980 | |||
981 | } | ||
982 | |||
983 | RelativeRect = AbsoluteRect = | ||
984 | core::rect<s32>(core::position2d<s32>(0,0), | ||
985 | Driver ? core::dimension2di(Driver->getScreenSize()) : core::dimension2d<s32>(0,0)); | ||
986 | } | ||
987 | |||
988 | |||
989 | //! adds a button. The returned pointer must not be dropped. | ||
990 | IGUIButton* CGUIEnvironment::addButton(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext) | ||
991 | { | ||
992 | IGUIButton* button = new CGUIButton(this, parent ? parent : this, id, rectangle); | ||
993 | if (text) | ||
994 | button->setText(text); | ||
995 | |||
996 | if ( tooltiptext ) | ||
997 | button->setToolTipText ( tooltiptext ); | ||
998 | |||
999 | button->drop(); | ||
1000 | return button; | ||
1001 | } | ||
1002 | |||
1003 | |||
1004 | //! adds a window. The returned pointer must not be dropped. | ||
1005 | IGUIWindow* CGUIEnvironment::addWindow(const core::rect<s32>& rectangle, bool modal, | ||
1006 | const wchar_t* text, IGUIElement* parent, s32 id) | ||
1007 | { | ||
1008 | parent = parent ? parent : this; | ||
1009 | |||
1010 | IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle); | ||
1011 | if (text) | ||
1012 | win->setText(text); | ||
1013 | win->drop(); | ||
1014 | |||
1015 | if (modal) | ||
1016 | { | ||
1017 | // 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 | ||
1018 | // careful not to get virtual function call, like OnEvent, in the window. | ||
1019 | CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); | ||
1020 | modalScreen->drop(); | ||
1021 | modalScreen->addChild(win); | ||
1022 | } | ||
1023 | |||
1024 | return win; | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | //! adds a modal screen. The returned pointer must not be dropped. | ||
1029 | IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent) | ||
1030 | { | ||
1031 | parent = parent ? parent : this; | ||
1032 | |||
1033 | IGUIElement *win = new CGUIModalScreen(this, parent, -1); | ||
1034 | win->drop(); | ||
1035 | |||
1036 | return win; | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | //! Adds a message box. | ||
1041 | IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text, | ||
1042 | bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image) | ||
1043 | { | ||
1044 | if (!CurrentSkin) | ||
1045 | return 0; | ||
1046 | |||
1047 | parent = parent ? parent : this; | ||
1048 | |||
1049 | core::rect<s32> rect; | ||
1050 | core::dimension2d<u32> screenDim, msgBoxDim; | ||
1051 | |||
1052 | screenDim.Width = parent->getAbsolutePosition().getWidth(); | ||
1053 | screenDim.Height = parent->getAbsolutePosition().getHeight(); | ||
1054 | msgBoxDim.Width = 2; | ||
1055 | msgBoxDim.Height = 2; | ||
1056 | |||
1057 | rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2; | ||
1058 | rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2; | ||
1059 | rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width; | ||
1060 | rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height; | ||
1061 | |||
1062 | IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag, | ||
1063 | parent, id, rect, image); | ||
1064 | win->drop(); | ||
1065 | |||
1066 | if (modal) | ||
1067 | { | ||
1068 | // 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 | ||
1069 | // careful not to get virtual function call, like OnEvent, in the CGUIMessageBox. | ||
1070 | CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); | ||
1071 | modalScreen->drop(); | ||
1072 | modalScreen->addChild( win ); | ||
1073 | } | ||
1074 | |||
1075 | |||
1076 | return win; | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | //! adds a scrollbar. The returned pointer must not be dropped. | ||
1081 | IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id) | ||
1082 | { | ||
1083 | IGUIScrollBar* bar = new CGUIScrollBar(horizontal, this, parent ? parent : this, id, rectangle); | ||
1084 | bar->drop(); | ||
1085 | return bar; | ||
1086 | } | ||
1087 | |||
1088 | //! Adds a table to the environment | ||
1089 | IGUITable* CGUIEnvironment::addTable(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, bool drawBackground) | ||
1090 | { | ||
1091 | CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false); | ||
1092 | b->drop(); | ||
1093 | return b; | ||
1094 | } | ||
1095 | |||
1096 | |||
1097 | //! Adds an image element. | ||
1098 | IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d<s32> pos, | ||
1099 | bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text) | ||
1100 | { | ||
1101 | core::dimension2d<s32> sz(0,0); | ||
1102 | if (image) | ||
1103 | sz = core::dimension2d<s32>(image->getOriginalSize()); | ||
1104 | |||
1105 | IGUIImage* img = new CGUIImage(this, parent ? parent : this, | ||
1106 | id, core::rect<s32>(pos, sz)); | ||
1107 | |||
1108 | if (text) | ||
1109 | img->setText(text); | ||
1110 | |||
1111 | if (useAlphaChannel) | ||
1112 | img->setUseAlphaChannel(true); | ||
1113 | |||
1114 | if (image) | ||
1115 | img->setImage(image); | ||
1116 | |||
1117 | img->drop(); | ||
1118 | return img; | ||
1119 | } | ||
1120 | |||
1121 | |||
1122 | //! adds an image. The returned pointer must not be dropped. | ||
1123 | IGUIImage* CGUIEnvironment::addImage(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, bool useAlphaChannel) | ||
1124 | { | ||
1125 | IGUIImage* img = new CGUIImage(this, parent ? parent : this, | ||
1126 | id, rectangle); | ||
1127 | |||
1128 | if (text) | ||
1129 | img->setText(text); | ||
1130 | |||
1131 | if ( useAlphaChannel ) | ||
1132 | img->setUseAlphaChannel(true); | ||
1133 | |||
1134 | img->drop(); | ||
1135 | return img; | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | //! adds an mesh viewer. The returned pointer must not be dropped. | ||
1140 | IGUIMeshViewer* CGUIEnvironment::addMeshViewer(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text) | ||
1141 | { | ||
1142 | IGUIMeshViewer* v = new CGUIMeshViewer(this, parent ? parent : this, | ||
1143 | id, rectangle); | ||
1144 | |||
1145 | if (text) | ||
1146 | v->setText(text); | ||
1147 | |||
1148 | v->drop(); | ||
1149 | return v; | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | //! adds a checkbox | ||
1154 | IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent, s32 id, const wchar_t* text) | ||
1155 | { | ||
1156 | IGUICheckBox* b = new CGUICheckBox(checked, this, | ||
1157 | parent ? parent : this , id , rectangle); | ||
1158 | |||
1159 | if (text) | ||
1160 | b->setText(text); | ||
1161 | |||
1162 | b->drop(); | ||
1163 | return b; | ||
1164 | } | ||
1165 | |||
1166 | |||
1167 | //! adds a list box | ||
1168 | IGUIListBox* CGUIEnvironment::addListBox(const core::rect<s32>& rectangle, | ||
1169 | IGUIElement* parent, s32 id, bool drawBackground) | ||
1170 | { | ||
1171 | IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle, | ||
1172 | true, drawBackground, false); | ||
1173 | |||
1174 | if (CurrentSkin && CurrentSkin->getSpriteBank()) | ||
1175 | { | ||
1176 | b->setSpriteBank(CurrentSkin->getSpriteBank()); | ||
1177 | } | ||
1178 | else if (getBuiltInFont() && getBuiltInFont()->getType() == EGFT_BITMAP) | ||
1179 | { | ||
1180 | b->setSpriteBank( ((IGUIFontBitmap*)getBuiltInFont())->getSpriteBank()); | ||
1181 | } | ||
1182 | |||
1183 | b->drop(); | ||
1184 | return b; | ||
1185 | } | ||
1186 | |||
1187 | //! adds a tree view | ||
1188 | IGUITreeView* CGUIEnvironment::addTreeView(const core::rect<s32>& rectangle, | ||
1189 | IGUIElement* parent, s32 id, | ||
1190 | bool drawBackground, | ||
1191 | bool scrollBarVertical, bool scrollBarHorizontal) | ||
1192 | { | ||
1193 | IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle, | ||
1194 | true, drawBackground, scrollBarVertical, scrollBarHorizontal); | ||
1195 | |||
1196 | b->setIconFont ( getBuiltInFont () ); | ||
1197 | b->drop(); | ||
1198 | return b; | ||
1199 | } | ||
1200 | |||
1201 | //! adds a file open dialog. The returned pointer must not be dropped. | ||
1202 | IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, | ||
1203 | bool modal, IGUIElement* parent, s32 id, | ||
1204 | bool restoreCWD, io::path::char_type* startDir) | ||
1205 | { | ||
1206 | parent = parent ? parent : this; | ||
1207 | |||
1208 | IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id, | ||
1209 | restoreCWD, startDir); | ||
1210 | d->drop(); | ||
1211 | |||
1212 | if (modal) | ||
1213 | { | ||
1214 | // 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 | ||
1215 | // careful not to get virtual function call, like OnEvent, in the window. | ||
1216 | CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); | ||
1217 | modalScreen->drop(); | ||
1218 | modalScreen->addChild(d); | ||
1219 | } | ||
1220 | |||
1221 | return d; | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | //! adds a color select dialog. The returned pointer must not be dropped. | ||
1226 | IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title, | ||
1227 | bool modal, IGUIElement* parent, s32 id) | ||
1228 | { | ||
1229 | parent = parent ? parent : this; | ||
1230 | |||
1231 | IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title, | ||
1232 | this, parent, id); | ||
1233 | d->drop(); | ||
1234 | |||
1235 | if (modal) | ||
1236 | { | ||
1237 | // 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 | ||
1238 | // careful not to get virtual function call, like OnEvent, in the window. | ||
1239 | CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); | ||
1240 | modalScreen->drop(); | ||
1241 | modalScreen->addChild(d); | ||
1242 | } | ||
1243 | |||
1244 | return d; | ||
1245 | } | ||
1246 | |||
1247 | |||
1248 | //! adds a static text. The returned pointer must not be dropped. | ||
1249 | IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text, | ||
1250 | const core::rect<s32>& rectangle, | ||
1251 | bool border, bool wordWrap, | ||
1252 | IGUIElement* parent, s32 id, bool background) | ||
1253 | { | ||
1254 | IGUIStaticText* d = new CGUIStaticText(text, border, this, | ||
1255 | parent ? parent : this, id, rectangle, background); | ||
1256 | |||
1257 | d->setWordWrap(wordWrap); | ||
1258 | d->drop(); | ||
1259 | |||
1260 | return d; | ||
1261 | } | ||
1262 | |||
1263 | |||
1264 | //! Adds an edit box. The returned pointer must not be dropped. | ||
1265 | IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text, | ||
1266 | const core::rect<s32>& rectangle, bool border, | ||
1267 | IGUIElement* parent, s32 id) | ||
1268 | { | ||
1269 | IGUIEditBox* d = new CGUIEditBox(text, border, this, | ||
1270 | parent ? parent : this, id, rectangle); | ||
1271 | |||
1272 | d->drop(); | ||
1273 | return d; | ||
1274 | } | ||
1275 | |||
1276 | |||
1277 | //! Adds a spin box to the environment | ||
1278 | IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text, | ||
1279 | const core::rect<s32> &rectangle, | ||
1280 | bool border,IGUIElement* parent, s32 id) | ||
1281 | { | ||
1282 | IGUISpinBox* d = new CGUISpinBox(text, border,this, | ||
1283 | parent ? parent : this, id, rectangle); | ||
1284 | |||
1285 | d->drop(); | ||
1286 | return d; | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | //! Adds a tab control to the environment. | ||
1291 | IGUITabControl* CGUIEnvironment::addTabControl(const core::rect<s32>& rectangle, | ||
1292 | IGUIElement* parent, bool fillbackground, bool border, s32 id) | ||
1293 | { | ||
1294 | IGUITabControl* t = new CGUITabControl(this, parent ? parent : this, | ||
1295 | rectangle, fillbackground, border, id); | ||
1296 | t->drop(); | ||
1297 | return t; | ||
1298 | } | ||
1299 | |||
1300 | |||
1301 | //! Adds tab to the environment. | ||
1302 | IGUITab* CGUIEnvironment::addTab(const core::rect<s32>& rectangle, | ||
1303 | IGUIElement* parent, s32 id) | ||
1304 | { | ||
1305 | IGUITab* t = new CGUITab(-1, this, parent ? parent : this, | ||
1306 | rectangle, id); | ||
1307 | t->drop(); | ||
1308 | return t; | ||
1309 | } | ||
1310 | |||
1311 | |||
1312 | //! Adds a context menu to the environment. | ||
1313 | IGUIContextMenu* CGUIEnvironment::addContextMenu(const core::rect<s32>& rectangle, | ||
1314 | IGUIElement* parent, s32 id) | ||
1315 | { | ||
1316 | IGUIContextMenu* c = new CGUIContextMenu(this, | ||
1317 | parent ? parent : this, id, rectangle, true); | ||
1318 | c->drop(); | ||
1319 | return c; | ||
1320 | } | ||
1321 | |||
1322 | |||
1323 | //! Adds a menu to the environment. | ||
1324 | IGUIContextMenu* CGUIEnvironment::addMenu(IGUIElement* parent, s32 id) | ||
1325 | { | ||
1326 | if (!parent) | ||
1327 | parent = this; | ||
1328 | |||
1329 | IGUIContextMenu* c = new CGUIMenu(this, | ||
1330 | parent, id, core::rect<s32>(0,0, | ||
1331 | parent->getAbsolutePosition().getWidth(), | ||
1332 | parent->getAbsolutePosition().getHeight())); | ||
1333 | |||
1334 | c->drop(); | ||
1335 | return c; | ||
1336 | } | ||
1337 | |||
1338 | |||
1339 | //! Adds a toolbar to the environment. It is like a menu is always placed on top | ||
1340 | //! in its parent, and contains buttons. | ||
1341 | IGUIToolBar* CGUIEnvironment::addToolBar(IGUIElement* parent, s32 id) | ||
1342 | { | ||
1343 | if (!parent) | ||
1344 | parent = this; | ||
1345 | |||
1346 | IGUIToolBar* b = new CGUIToolBar(this, parent, id, core::rect<s32>(0,0,10,10)); | ||
1347 | b->drop(); | ||
1348 | return b; | ||
1349 | } | ||
1350 | |||
1351 | |||
1352 | //! Adds an element for fading in or out. | ||
1353 | IGUIInOutFader* CGUIEnvironment::addInOutFader(const core::rect<s32>* rectangle, IGUIElement* parent, s32 id) | ||
1354 | { | ||
1355 | core::rect<s32> rect; | ||
1356 | |||
1357 | if (rectangle) | ||
1358 | rect = *rectangle; | ||
1359 | else if (Driver) | ||
1360 | rect = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Driver->getScreenSize())); | ||
1361 | |||
1362 | if (!parent) | ||
1363 | parent = this; | ||
1364 | |||
1365 | IGUIInOutFader* fader = new CGUIInOutFader(this, parent, id, rect); | ||
1366 | fader->drop(); | ||
1367 | return fader; | ||
1368 | } | ||
1369 | |||
1370 | |||
1371 | //! Adds a combo box to the environment. | ||
1372 | IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect<s32>& rectangle, | ||
1373 | IGUIElement* parent, s32 id) | ||
1374 | { | ||
1375 | IGUIComboBox* t = new CGUIComboBox(this, parent ? parent : this, | ||
1376 | id, rectangle); | ||
1377 | t->drop(); | ||
1378 | return t; | ||
1379 | } | ||
1380 | |||
1381 | |||
1382 | //! returns the font | ||
1383 | IGUIFont* CGUIEnvironment::getFont(const io::path& filename) | ||
1384 | { | ||
1385 | // search existing font | ||
1386 | |||
1387 | SFont f; | ||
1388 | f.NamedPath.setPath(filename); | ||
1389 | |||
1390 | s32 index = Fonts.binary_search(f); | ||
1391 | if (index != -1) | ||
1392 | return Fonts[index].Font; | ||
1393 | |||
1394 | // font doesn't exist, attempt to load it | ||
1395 | |||
1396 | // does the file exist? | ||
1397 | |||
1398 | if (!FileSystem->existFile(filename)) | ||
1399 | { | ||
1400 | os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR); | ||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | IGUIFont* ifont=0; | ||
1405 | io::IXMLReader *xml = FileSystem->createXMLReader(filename ); | ||
1406 | if (xml) | ||
1407 | { | ||
1408 | // this is an XML font, but we need to know what type | ||
1409 | EGUI_FONT_TYPE t = EGFT_CUSTOM; | ||
1410 | |||
1411 | bool found=false; | ||
1412 | while(!found && xml->read()) | ||
1413 | { | ||
1414 | if (xml->getNodeType() == io::EXN_ELEMENT) | ||
1415 | { | ||
1416 | if (core::stringw(L"font") == xml->getNodeName()) | ||
1417 | { | ||
1418 | if (core::stringw(L"vector") == xml->getAttributeValue(L"type")) | ||
1419 | { | ||
1420 | t = EGFT_VECTOR; | ||
1421 | found=true; | ||
1422 | } | ||
1423 | else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type")) | ||
1424 | { | ||
1425 | t = EGFT_BITMAP; | ||
1426 | found=true; | ||
1427 | } | ||
1428 | else found=true; | ||
1429 | } | ||
1430 | } | ||
1431 | } | ||
1432 | |||
1433 | if (t==EGFT_BITMAP) | ||
1434 | { | ||
1435 | CGUIFont* font = new CGUIFont(this, filename); | ||
1436 | ifont = (IGUIFont*)font; | ||
1437 | // change working directory, for loading textures | ||
1438 | io::path workingDir = FileSystem->getWorkingDirectory(); | ||
1439 | FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.NamedPath.getPath())); | ||
1440 | |||
1441 | // load the font | ||
1442 | if (!font->load(xml)) | ||
1443 | { | ||
1444 | font->drop(); | ||
1445 | font = 0; | ||
1446 | ifont = 0; | ||
1447 | } | ||
1448 | // change working dir back again | ||
1449 | FileSystem->changeWorkingDirectoryTo( workingDir ); | ||
1450 | } | ||
1451 | else if (t==EGFT_VECTOR) | ||
1452 | { | ||
1453 | // todo: vector fonts | ||
1454 | os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR); | ||
1455 | |||
1456 | //CGUIFontVector* font = new CGUIFontVector(Driver); | ||
1457 | //ifont = (IGUIFont*)font; | ||
1458 | //if (!font->load(xml)) | ||
1459 | } | ||
1460 | xml->drop(); | ||
1461 | } | ||
1462 | |||
1463 | |||
1464 | if (!ifont) | ||
1465 | { | ||
1466 | |||
1467 | CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() ); | ||
1468 | ifont = (IGUIFont*)font; | ||
1469 | if (!font->load(f.NamedPath.getPath())) | ||
1470 | { | ||
1471 | font->drop(); | ||
1472 | return 0; | ||
1473 | } | ||
1474 | } | ||
1475 | |||
1476 | // add to fonts. | ||
1477 | |||
1478 | f.Font = ifont; | ||
1479 | Fonts.push_back(f); | ||
1480 | |||
1481 | return ifont; | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | //! add an externally loaded font | ||
1486 | IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font) | ||
1487 | { | ||
1488 | if (font) | ||
1489 | { | ||
1490 | SFont f; | ||
1491 | f.NamedPath.setPath(name); | ||
1492 | s32 index = Fonts.binary_search(f); | ||
1493 | if (index != -1) | ||
1494 | return Fonts[index].Font; | ||
1495 | f.Font = font; | ||
1496 | Fonts.push_back(f); | ||
1497 | font->grab(); | ||
1498 | } | ||
1499 | return font; | ||
1500 | } | ||
1501 | |||
1502 | //! remove loaded font | ||
1503 | void CGUIEnvironment::removeFont(IGUIFont* font) | ||
1504 | { | ||
1505 | if ( !font ) | ||
1506 | return; | ||
1507 | for ( u32 i=0; i<Fonts.size(); ++i ) | ||
1508 | { | ||
1509 | if ( Fonts[i].Font == font ) | ||
1510 | { | ||
1511 | Fonts[i].Font->drop(); | ||
1512 | Fonts.erase(i); | ||
1513 | return; | ||
1514 | } | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | //! returns default font | ||
1519 | IGUIFont* CGUIEnvironment::getBuiltInFont() const | ||
1520 | { | ||
1521 | if (Fonts.empty()) | ||
1522 | return 0; | ||
1523 | |||
1524 | return Fonts[0].Font; | ||
1525 | } | ||
1526 | |||
1527 | |||
1528 | IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename) | ||
1529 | { | ||
1530 | // search for the file name | ||
1531 | |||
1532 | SSpriteBank b; | ||
1533 | b.NamedPath.setPath(filename); | ||
1534 | |||
1535 | s32 index = Banks.binary_search(b); | ||
1536 | if (index != -1) | ||
1537 | return Banks[index].Bank; | ||
1538 | |||
1539 | // we don't have this sprite bank, we should load it | ||
1540 | if (!FileSystem->existFile(b.NamedPath.getPath())) | ||
1541 | { | ||
1542 | if ( filename != DefaultFontName ) | ||
1543 | { | ||
1544 | os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_DEBUG); | ||
1545 | } | ||
1546 | return 0; | ||
1547 | } | ||
1548 | |||
1549 | // todo: load it! | ||
1550 | |||
1551 | return 0; | ||
1552 | } | ||
1553 | |||
1554 | |||
1555 | IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name) | ||
1556 | { | ||
1557 | // no duplicate names allowed | ||
1558 | |||
1559 | SSpriteBank b; | ||
1560 | b.NamedPath.setPath(name); | ||
1561 | |||
1562 | const s32 index = Banks.binary_search(b); | ||
1563 | if (index != -1) | ||
1564 | return 0; | ||
1565 | |||
1566 | // create a new sprite bank | ||
1567 | |||
1568 | b.Bank = new CGUISpriteBank(this); | ||
1569 | Banks.push_back(b); | ||
1570 | |||
1571 | return b.Bank; | ||
1572 | } | ||
1573 | |||
1574 | |||
1575 | //! Creates the image list from the given texture. | ||
1576 | IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture, | ||
1577 | core::dimension2d<s32> imageSize, bool useAlphaChannel ) | ||
1578 | { | ||
1579 | CGUIImageList* imageList = new CGUIImageList( Driver ); | ||
1580 | if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) ) | ||
1581 | { | ||
1582 | imageList->drop(); | ||
1583 | return 0; | ||
1584 | } | ||
1585 | |||
1586 | return imageList; | ||
1587 | } | ||
1588 | |||
1589 | //! Returns the root gui element. | ||
1590 | IGUIElement* CGUIEnvironment::getRootGUIElement() | ||
1591 | { | ||
1592 | return this; | ||
1593 | } | ||
1594 | |||
1595 | |||
1596 | //! Returns the next element in the tab group starting at the focused element | ||
1597 | IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group) | ||
1598 | { | ||
1599 | // start the search at the root of the current tab group | ||
1600 | IGUIElement *startPos = Focus ? Focus->getTabGroup() : 0; | ||
1601 | s32 startOrder = -1; | ||
1602 | |||
1603 | // if we're searching for a group | ||
1604 | if (group && startPos) | ||
1605 | { | ||
1606 | startOrder = startPos->getTabOrder(); | ||
1607 | } | ||
1608 | else | ||
1609 | if (!group && Focus && !Focus->isTabGroup()) | ||
1610 | { | ||
1611 | startOrder = Focus->getTabOrder(); | ||
1612 | if (startOrder == -1) | ||
1613 | { | ||
1614 | // this element is not part of the tab cycle, | ||
1615 | // but its parent might be... | ||
1616 | IGUIElement *el = Focus; | ||
1617 | while (el && el->getParent() && startOrder == -1) | ||
1618 | { | ||
1619 | el = el->getParent(); | ||
1620 | startOrder = el->getTabOrder(); | ||
1621 | } | ||
1622 | |||
1623 | } | ||
1624 | } | ||
1625 | |||
1626 | if (group || !startPos) | ||
1627 | startPos = this; // start at the root | ||
1628 | |||
1629 | // find the element | ||
1630 | IGUIElement *closest = 0; | ||
1631 | IGUIElement *first = 0; | ||
1632 | startPos->getNextElement(startOrder, reverse, group, first, closest); | ||
1633 | |||
1634 | if (closest) | ||
1635 | return closest; // we found an element | ||
1636 | else if (first) | ||
1637 | return first; // go to the end or the start | ||
1638 | else if (group) | ||
1639 | return this; // no group found? root group | ||
1640 | else | ||
1641 | return 0; | ||
1642 | } | ||
1643 | |||
1644 | |||
1645 | //! creates an GUI Environment | ||
1646 | IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs, | ||
1647 | video::IVideoDriver* Driver, | ||
1648 | IOSOperator* op) | ||
1649 | { | ||
1650 | return new CGUIEnvironment(fs, Driver, op); | ||
1651 | } | ||
1652 | |||
1653 | |||
1654 | } // end namespace gui | ||
1655 | } // end namespace irr | ||
1656 | |||
1657 | #endif // _IRR_COMPILE_WITH_GUI_ | ||
1658 | |||