~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CGUIEnvironment.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

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