~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CGUITabControl.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
// Copyright (C) 2002-2011 Nikolaus Gebhardt
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#include "CGUITabControl.h"
 
6
#ifdef _IRR_COMPILE_WITH_GUI_
 
7
 
 
8
#include "CGUIButton.h"
 
9
#include "IGUISkin.h"
 
10
#include "IGUIEnvironment.h"
 
11
#include "IGUIFont.h"
 
12
#include "IVideoDriver.h"
 
13
#include "rect.h"
 
14
#include "os.h"
 
15
 
 
16
namespace irr
 
17
{
 
18
namespace gui
 
19
{
 
20
 
 
21
// ------------------------------------------------------------------
 
22
// Tab
 
23
// ------------------------------------------------------------------
 
24
 
 
25
//! constructor
 
26
CGUITab::CGUITab(s32 number, IGUIEnvironment* environment,
 
27
        IGUIElement* parent, const core::rect<s32>& rectangle,
 
28
        s32 id)
 
29
        : IGUITab(environment, parent, id, rectangle), Number(number),
 
30
                BackColor(0,0,0,0), OverrideTextColorEnabled(false), TextColor(255,0,0,0),
 
31
                DrawBackground(false)
 
32
{
 
33
        #ifdef _DEBUG
 
34
        setDebugName("CGUITab");
 
35
        #endif
 
36
 
 
37
        const IGUISkin* const skin = environment->getSkin();
 
38
        if (skin)
 
39
                TextColor = skin->getColor(EGDC_BUTTON_TEXT);
 
40
}
 
41
 
 
42
 
 
43
//! Returns number of tab in tabcontrol. Can be accessed
 
44
//! later IGUITabControl::getTab() by this number.
 
45
s32 CGUITab::getNumber() const
 
46
{
 
47
        return Number;
 
48
}
 
49
 
 
50
 
 
51
//! Sets the number
 
52
void CGUITab::setNumber(s32 n)
 
53
{
 
54
        Number = n;
 
55
}
 
56
 
 
57
void CGUITab::refreshSkinColors()
 
58
{
 
59
        if ( !OverrideTextColorEnabled )
 
60
        {
 
61
                TextColor = Environment->getSkin()->getColor(EGDC_BUTTON_TEXT);
 
62
        }
 
63
}
 
64
 
 
65
//! draws the element and its children
 
66
void CGUITab::draw()
 
67
{
 
68
        if (!IsVisible)
 
69
                return;
 
70
 
 
71
        IGUISkin *skin = Environment->getSkin();
 
72
 
 
73
        if (skin && DrawBackground)
 
74
                skin->draw2DRectangle(this, BackColor, AbsoluteRect, &AbsoluteClippingRect);
 
75
 
 
76
        IGUIElement::draw();
 
77
}
 
78
 
 
79
 
 
80
//! sets if the tab should draw its background
 
81
void CGUITab::setDrawBackground(bool draw)
 
82
{
 
83
        DrawBackground = draw;
 
84
}
 
85
 
 
86
 
 
87
//! sets the color of the background, if it should be drawn.
 
88
void CGUITab::setBackgroundColor(video::SColor c)
 
89
{
 
90
        BackColor = c;
 
91
}
 
92
 
 
93
 
 
94
//! sets the color of the text
 
95
void CGUITab::setTextColor(video::SColor c)
 
96
{
 
97
        OverrideTextColorEnabled = true;
 
98
        TextColor = c;
 
99
}
 
100
 
 
101
 
 
102
video::SColor CGUITab::getTextColor() const
 
103
{
 
104
        return TextColor;
 
105
}
 
106
 
 
107
 
 
108
//! returns true if the tab is drawing its background, false if not
 
109
bool CGUITab::isDrawingBackground() const
 
110
{
 
111
        _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
 
112
        return DrawBackground;
 
113
}
 
114
 
 
115
 
 
116
//! returns the color of the background
 
117
video::SColor CGUITab::getBackgroundColor() const
 
118
{
 
119
        return BackColor;
 
120
}
 
121
 
 
122
 
 
123
//! Writes attributes of the element.
 
124
void CGUITab::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
 
125
{
 
126
        IGUITab::serializeAttributes(out,options);
 
127
 
 
128
        out->addInt             ("TabNumber",           Number);
 
129
        out->addBool    ("DrawBackground",      DrawBackground);
 
130
        out->addColor   ("BackColor",           BackColor);
 
131
        out->addBool    ("OverrideTextColorEnabled", OverrideTextColorEnabled);
 
132
        out->addColor   ("TextColor",           TextColor);
 
133
 
 
134
}
 
135
 
 
136
 
 
137
//! Reads attributes of the element
 
138
void CGUITab::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
 
139
{
 
140
        IGUITab::deserializeAttributes(in,options);
 
141
 
 
142
        setNumber(in->getAttributeAsInt("TabNumber"));
 
143
        setDrawBackground(in->getAttributeAsBool("DrawBackground"));
 
144
        setBackgroundColor(in->getAttributeAsColor("BackColor"));
 
145
        bool override = in->getAttributeAsBool("OverrideTextColorEnabled");
 
146
        setTextColor(in->getAttributeAsColor("TextColor"));
 
147
        if ( !override )
 
148
        {
 
149
                OverrideTextColorEnabled = false;
 
150
        }
 
151
 
 
152
        if (Parent && Parent->getType() == EGUIET_TAB_CONTROL)
 
153
        {
 
154
                ((CGUITabControl*)Parent)->addTab(this);
 
155
                if (isVisible())
 
156
                        ((CGUITabControl*)Parent)->setActiveTab(this);
 
157
        }
 
158
}
 
159
 
 
160
 
 
161
// ------------------------------------------------------------------
 
162
// Tabcontrol
 
163
// ------------------------------------------------------------------
 
164
 
 
165
//! constructor
 
166
CGUITabControl::CGUITabControl(IGUIEnvironment* environment,
 
167
        IGUIElement* parent, const core::rect<s32>& rectangle,
 
168
        bool fillbackground, bool border, s32 id)
 
169
        : IGUITabControl(environment, parent, id, rectangle), ActiveTab(-1),
 
170
        Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT),
 
171
        UpButton(0), DownButton(0), TabMaxWidth(0), CurrentScrollTabIndex(0), TabExtraWidth(20)
 
172
{
 
173
        #ifdef _DEBUG
 
174
        setDebugName("CGUITabControl");
 
175
        #endif
 
176
 
 
177
        IGUISkin* skin = Environment->getSkin();
 
178
        IGUISpriteBank* sprites = 0;
 
179
 
 
180
        TabHeight = 32;
 
181
 
 
182
        if (skin)
 
183
        {
 
184
                sprites = skin->getSpriteBank();
 
185
                TabHeight = skin->getSize(gui::EGDS_BUTTON_HEIGHT) + 2;
 
186
        }
 
187
 
 
188
        UpButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
 
189
 
 
190
        if (UpButton)
 
191
        {
 
192
                UpButton->setSpriteBank(sprites);
 
193
                UpButton->setVisible(false);
 
194
                UpButton->setSubElement(true);
 
195
                UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
 
196
                UpButton->setOverrideFont(Environment->getBuiltInFont());
 
197
                UpButton->grab();
 
198
        }
 
199
 
 
200
        DownButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
 
201
 
 
202
        if (DownButton)
 
203
        {
 
204
                DownButton->setSpriteBank(sprites);
 
205
                DownButton->setVisible(false);
 
206
                DownButton->setSubElement(true);
 
207
                DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
 
208
                DownButton->setOverrideFont(Environment->getBuiltInFont());
 
209
                DownButton->grab();
 
210
        }
 
211
 
 
212
        setTabVerticalAlignment(EGUIA_UPPERLEFT);
 
213
        refreshSprites();
 
214
}
 
215
 
 
216
//! destructor
 
217
CGUITabControl::~CGUITabControl()
 
218
{
 
219
        for (u32 i=0; i<Tabs.size(); ++i)
 
220
        {
 
221
                if (Tabs[i])
 
222
                        Tabs[i]->drop();
 
223
        }
 
224
 
 
225
        if (UpButton)
 
226
                UpButton->drop();
 
227
 
 
228
        if (DownButton)
 
229
                DownButton->drop();
 
230
}
 
231
 
 
232
void CGUITabControl::refreshSprites()
 
233
{
 
234
        video::SColor color(255,255,255,255);
 
235
        IGUISkin* skin = Environment->getSkin();
 
236
        if (skin)
 
237
        {
 
238
                color = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
 
239
        }
 
240
 
 
241
        if (UpButton)
 
242
        {
 
243
                UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), color);
 
244
                UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), color);
 
245
        }
 
246
 
 
247
        if (DownButton)
 
248
        {
 
249
                DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), color);
 
250
                DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), color);
 
251
        }
 
252
}
 
253
 
 
254
//! Adds a tab
 
255
IGUITab* CGUITabControl::addTab(const wchar_t* caption, s32 id)
 
256
{
 
257
        CGUITab* tab = new CGUITab(Tabs.size(), Environment, this, calcTabPos(), id);
 
258
 
 
259
        tab->setText(caption);
 
260
        tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
 
261
        tab->setVisible(false);
 
262
        Tabs.push_back(tab);
 
263
 
 
264
        if (ActiveTab == -1)
 
265
        {
 
266
                ActiveTab = 0;
 
267
                tab->setVisible(true);
 
268
        }
 
269
 
 
270
        recalculateScrollBar();
 
271
 
 
272
        return tab;
 
273
}
 
274
 
 
275
 
 
276
//! adds a tab which has been created elsewhere
 
277
void CGUITabControl::addTab(CGUITab* tab)
 
278
{
 
279
        if (!tab)
 
280
                return;
 
281
 
 
282
        // check if its already added
 
283
        for (u32 i=0; i < Tabs.size(); ++i)
 
284
        {
 
285
                if (Tabs[i] == tab)
 
286
                        return;
 
287
        }
 
288
 
 
289
        tab->grab();
 
290
 
 
291
        if (tab->getNumber() == -1)
 
292
                tab->setNumber((s32)Tabs.size());
 
293
 
 
294
        while (tab->getNumber() >= (s32)Tabs.size())
 
295
                Tabs.push_back(0);
 
296
 
 
297
        if (Tabs[tab->getNumber()])
 
298
        {
 
299
                Tabs.push_back(Tabs[tab->getNumber()]);
 
300
                Tabs[Tabs.size()-1]->setNumber(Tabs.size());
 
301
        }
 
302
        Tabs[tab->getNumber()] = tab;
 
303
 
 
304
        if (ActiveTab == -1)
 
305
                ActiveTab = tab->getNumber();
 
306
 
 
307
 
 
308
        if (tab->getNumber() == ActiveTab)
 
309
        {
 
310
                setActiveTab(ActiveTab);
 
311
        }
 
312
}
 
313
 
 
314
//! Insert the tab at the given index
 
315
IGUITab* CGUITabControl::insertTab(s32 idx, const wchar_t* caption, s32 id)
 
316
{
 
317
        if ( idx < 0 || idx > (s32)Tabs.size() )        // idx == Tabs.size() is indeed ok here as core::array can handle that
 
318
                return NULL;
 
319
 
 
320
        CGUITab* tab = new CGUITab(idx, Environment, this, calcTabPos(), id);
 
321
 
 
322
        tab->setText(caption);
 
323
        tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
 
324
        tab->setVisible(false);
 
325
        Tabs.insert(tab, (u32)idx);
 
326
 
 
327
        if (ActiveTab == -1)
 
328
        {
 
329
                ActiveTab = 0;
 
330
                tab->setVisible(true);
 
331
        }
 
332
 
 
333
        for ( u32 i=(u32)idx+1; i < Tabs.size(); ++i )
 
334
        {
 
335
                Tabs[i]->setNumber(i);
 
336
        }
 
337
 
 
338
        recalculateScrollBar();
 
339
 
 
340
        return tab;
 
341
}
 
342
 
 
343
//! Removes a tab from the tabcontrol
 
344
void CGUITabControl::removeTab(s32 idx)
 
345
{
 
346
        if ( idx < 0 || idx >= (s32)Tabs.size() )
 
347
                return;
 
348
 
 
349
        Tabs[(u32)idx]->drop();
 
350
        Tabs.erase((u32)idx);
 
351
        for ( u32 i=(u32)idx; i < Tabs.size(); ++i )
 
352
        {
 
353
                Tabs[i]->setNumber(i);
 
354
        }
 
355
}
 
356
 
 
357
//! Clears the tabcontrol removing all tabs
 
358
void CGUITabControl::clear()
 
359
{
 
360
        for (u32 i=0; i<Tabs.size(); ++i)
 
361
        {
 
362
                if (Tabs[i])
 
363
                        Tabs[i]->drop();
 
364
        }
 
365
        Tabs.clear();
 
366
}
 
367
 
 
368
//! Returns amount of tabs in the tabcontrol
 
369
s32 CGUITabControl::getTabCount() const
 
370
{
 
371
        return Tabs.size();
 
372
}
 
373
 
 
374
 
 
375
//! Returns a tab based on zero based index
 
376
IGUITab* CGUITabControl::getTab(s32 idx) const
 
377
{
 
378
        if ((u32)idx >= Tabs.size())
 
379
                return 0;
 
380
 
 
381
        return Tabs[idx];
 
382
}
 
383
 
 
384
 
 
385
//! called if an event happened.
 
386
bool CGUITabControl::OnEvent(const SEvent& event)
 
387
{
 
388
        if (isEnabled())
 
389
        {
 
390
 
 
391
                switch(event.EventType)
 
392
                {
 
393
                case EET_GUI_EVENT:
 
394
                        switch(event.GUIEvent.EventType)
 
395
                        {
 
396
                        case EGET_BUTTON_CLICKED:
 
397
                                if (event.GUIEvent.Caller == UpButton)
 
398
                                {
 
399
                                        scrollLeft();
 
400
                                        return true;
 
401
                                }
 
402
                                else if (event.GUIEvent.Caller == DownButton)
 
403
                                {
 
404
                                        scrollRight();
 
405
                                        return true;
 
406
                                }
 
407
 
 
408
                        break;
 
409
                        default:
 
410
                        break;
 
411
                        }
 
412
                        break;
 
413
                case EET_MOUSE_INPUT_EVENT:
 
414
                        switch(event.MouseInput.Event)
 
415
                        {
 
416
                        case EMIE_LMOUSE_PRESSED_DOWN:
 
417
                                // todo: dragging tabs around
 
418
                                return true;
 
419
                        case EMIE_LMOUSE_LEFT_UP:
 
420
                        {
 
421
                                s32 idx = getTabAt(event.MouseInput.X, event.MouseInput.Y);
 
422
                                if ( idx >= 0 )
 
423
                                {
 
424
                                        setActiveTab(idx);
 
425
                                        return true;
 
426
                                }
 
427
                                break;
 
428
                        }
 
429
                        default:
 
430
                                break;
 
431
                        }
 
432
                        break;
 
433
                default:
 
434
                        break;
 
435
                }
 
436
        }
 
437
 
 
438
        return IGUIElement::OnEvent(event);
 
439
}
 
440
 
 
441
 
 
442
void CGUITabControl::scrollLeft()
 
443
{
 
444
        if ( CurrentScrollTabIndex > 0 )
 
445
                --CurrentScrollTabIndex;
 
446
        recalculateScrollBar();
 
447
}
 
448
 
 
449
 
 
450
void CGUITabControl::scrollRight()
 
451
{
 
452
        if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 )
 
453
        {
 
454
                if ( needScrollControl(CurrentScrollTabIndex, true) )
 
455
                        ++CurrentScrollTabIndex;
 
456
        }
 
457
        recalculateScrollBar();
 
458
}
 
459
 
 
460
s32 CGUITabControl::calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl) const
 
461
{
 
462
        if ( !font )
 
463
                return 0;
 
464
 
 
465
        s32 len = font->getDimension(text).Width + TabExtraWidth;
 
466
        if ( TabMaxWidth > 0 && len > TabMaxWidth )
 
467
                len = TabMaxWidth;
 
468
 
 
469
        // check if we miss the place to draw the tab-button
 
470
        if ( withScrollControl && ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 )
 
471
        {
 
472
                s32 tabMinWidth = font->getDimension(L"A").Width;
 
473
                if ( TabExtraWidth > 0 && TabExtraWidth > tabMinWidth )
 
474
                        tabMinWidth = TabExtraWidth;
 
475
 
 
476
                if ( ScrollControl && pos+tabMinWidth <= UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 )
 
477
                {
 
478
                        len = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos;
 
479
                }
 
480
        }
 
481
        return len;
 
482
}
 
483
 
 
484
bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl)
 
485
{
 
486
        if ( startIndex >= (s32)Tabs.size() )
 
487
                startIndex -= 1;
 
488
 
 
489
        if ( startIndex < 0 )
 
490
                startIndex = 0;
 
491
 
 
492
        IGUISkin* skin = Environment->getSkin();
 
493
        if (!skin)
 
494
                return false;
 
495
 
 
496
        IGUIFont* font = skin->getFont();
 
497
 
 
498
        core::rect<s32> frameRect(AbsoluteRect);
 
499
 
 
500
        if (Tabs.empty())
 
501
                return false;
 
502
 
 
503
        if (!font)
 
504
                return false;
 
505
 
 
506
        s32 pos = frameRect.UpperLeftCorner.X + 2;
 
507
 
 
508
        for (s32 i=startIndex; i<(s32)Tabs.size(); ++i)
 
509
        {
 
510
                // get Text
 
511
                const wchar_t* text = 0;
 
512
                if (Tabs[i])
 
513
                        text = Tabs[i]->getText();
 
514
 
 
515
                // get text length
 
516
                s32 len = calcTabWidth(pos, font, text, false); // always without withScrollControl here or len would be shortened
 
517
 
 
518
                frameRect.LowerRightCorner.X += len;
 
519
 
 
520
                frameRect.UpperLeftCorner.X = pos;
 
521
                frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
 
522
                pos += len;
 
523
 
 
524
                if ( withScrollControl && pos > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2)
 
525
                        return true;
 
526
 
 
527
                if ( !withScrollControl && pos > AbsoluteRect.LowerRightCorner.X )
 
528
                        return true;
 
529
        }
 
530
 
 
531
        return false;
 
532
}
 
533
 
 
534
 
 
535
core::rect<s32> CGUITabControl::calcTabPos()
 
536
{
 
537
        core::rect<s32> r;
 
538
        r.UpperLeftCorner.X = 0;
 
539
        r.LowerRightCorner.X = AbsoluteRect.getWidth();
 
540
        if ( Border )
 
541
        {
 
542
                ++r.UpperLeftCorner.X;
 
543
                --r.LowerRightCorner.X;
 
544
        }
 
545
 
 
546
        if ( VerticalAlignment == EGUIA_UPPERLEFT )
 
547
        {
 
548
                r.UpperLeftCorner.Y = TabHeight+2;
 
549
                r.LowerRightCorner.Y = AbsoluteRect.getHeight()-1;
 
550
                if ( Border )
 
551
                {
 
552
                        --r.LowerRightCorner.Y;
 
553
                }
 
554
        }
 
555
        else
 
556
        {
 
557
                r.UpperLeftCorner.Y = 0;
 
558
                r.LowerRightCorner.Y = AbsoluteRect.getHeight()-(TabHeight+2);
 
559
                if ( Border )
 
560
                {
 
561
                        ++r.UpperLeftCorner.Y;
 
562
                }
 
563
        }
 
564
 
 
565
        return r;
 
566
}
 
567
 
 
568
 
 
569
//! draws the element and its children
 
570
void CGUITabControl::draw()
 
571
{
 
572
        if (!IsVisible)
 
573
                return;
 
574
 
 
575
        IGUISkin* skin = Environment->getSkin();
 
576
        if (!skin)
 
577
                return;
 
578
 
 
579
        IGUIFont* font = skin->getFont();
 
580
        video::IVideoDriver* driver = Environment->getVideoDriver();
 
581
 
 
582
        core::rect<s32> frameRect(AbsoluteRect);
 
583
 
 
584
        if (Tabs.empty())
 
585
                driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
 
586
 
 
587
        if (!font)
 
588
                return;
 
589
 
 
590
        if ( VerticalAlignment == EGUIA_UPPERLEFT )
 
591
        {
 
592
                frameRect.UpperLeftCorner.Y += 2;
 
593
                frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
 
594
        }
 
595
        else
 
596
        {
 
597
                frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight - 1;
 
598
                frameRect.LowerRightCorner.Y -= 2;
 
599
        }
 
600
 
 
601
        core::rect<s32> tr;
 
602
        s32 pos = frameRect.UpperLeftCorner.X + 2;
 
603
 
 
604
        bool needLeftScroll = CurrentScrollTabIndex > 0;
 
605
        bool needRightScroll = false;
 
606
 
 
607
        // left and right pos of the active tab
 
608
        s32 left = 0;
 
609
        s32 right = 0;
 
610
 
 
611
        //const wchar_t* activetext = 0;
 
612
        CGUITab *activeTab = 0;
 
613
 
 
614
        for (u32 i=CurrentScrollTabIndex; i<Tabs.size(); ++i)
 
615
        {
 
616
                // get Text
 
617
                const wchar_t* text = 0;
 
618
                if (Tabs[i])
 
619
                        text = Tabs[i]->getText();
 
620
 
 
621
                // get text length
 
622
                s32 len = calcTabWidth(pos, font, text, true);
 
623
                if ( ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 )
 
624
                {
 
625
                        needRightScroll = true;
 
626
                        break;
 
627
                }
 
628
 
 
629
                frameRect.LowerRightCorner.X += len;
 
630
                frameRect.UpperLeftCorner.X = pos;
 
631
                frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
 
632
 
 
633
                pos += len;
 
634
 
 
635
                if ( text )
 
636
                        Tabs[i]->refreshSkinColors();
 
637
 
 
638
                if ((s32)i == ActiveTab)
 
639
                {
 
640
                        left = frameRect.UpperLeftCorner.X;
 
641
                        right = frameRect.LowerRightCorner.X;
 
642
                        //activetext = text;
 
643
                        activeTab = Tabs[i];
 
644
                }
 
645
                else
 
646
                {
 
647
                        skin->draw3DTabButton(this, false, frameRect, &AbsoluteClippingRect, VerticalAlignment);
 
648
 
 
649
                        // draw text
 
650
                        core::rect<s32> textClipRect(frameRect);        // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
 
651
                        textClipRect.clipAgainst(AbsoluteClippingRect);
 
652
                        font->draw(text, frameRect, Tabs[i]->getTextColor(),
 
653
                                true, true, &textClipRect);
 
654
                }
 
655
        }
 
656
 
 
657
        // draw active tab
 
658
        if (left != 0 && right != 0 && activeTab != 0)
 
659
        {
 
660
                // draw upper highlight frame
 
661
                if ( VerticalAlignment == EGUIA_UPPERLEFT )
 
662
                {
 
663
                        frameRect.UpperLeftCorner.X = left-2;
 
664
                        frameRect.LowerRightCorner.X = right+2;
 
665
                        frameRect.UpperLeftCorner.Y -= 2;
 
666
 
 
667
                        skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
 
668
 
 
669
                        // draw text
 
670
                        core::rect<s32> textClipRect(frameRect);        // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
 
671
                        textClipRect.clipAgainst(AbsoluteClippingRect);
 
672
                        font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
 
673
                                true, true, &textClipRect);
 
674
 
 
675
                        tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
 
676
                        tr.LowerRightCorner.X = left - 1;
 
677
                        tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
 
678
                        tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
 
679
                        driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
 
680
 
 
681
                        tr.UpperLeftCorner.X = right;
 
682
                        tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
 
683
                        driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
 
684
                }
 
685
                else
 
686
                {
 
687
 
 
688
                        frameRect.UpperLeftCorner.X = left-2;
 
689
                        frameRect.LowerRightCorner.X = right+2;
 
690
                        frameRect.LowerRightCorner.Y += 2;
 
691
 
 
692
                        skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
 
693
 
 
694
                        // draw text
 
695
                        font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
 
696
                                true, true, &frameRect);
 
697
 
 
698
                        tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
 
699
                        tr.LowerRightCorner.X = left - 1;
 
700
                        tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
 
701
                        tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
 
702
                        driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
 
703
 
 
704
                        tr.UpperLeftCorner.X = right;
 
705
                        tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
 
706
                        driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
 
707
                }
 
708
        }
 
709
        else
 
710
        {
 
711
                if ( VerticalAlignment == EGUIA_UPPERLEFT )
 
712
                {
 
713
                        tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
 
714
                        tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
 
715
                        tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
 
716
                        tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
 
717
                        driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
 
718
                }
 
719
                else
 
720
                {
 
721
                        tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
 
722
                        tr.LowerRightCorner.X = 1000;
 
723
                        tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
 
724
                        tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
 
725
                        driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
 
726
                }
 
727
        }
 
728
 
 
729
        skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment);
 
730
 
 
731
        // enable scrollcontrols on need
 
732
        if ( UpButton )
 
733
                UpButton->setEnabled(needLeftScroll);
 
734
        if ( DownButton )
 
735
                DownButton->setEnabled(needRightScroll);
 
736
        refreshSprites();
 
737
 
 
738
        IGUIElement::draw();
 
739
}
 
740
 
 
741
 
 
742
//! Set the height of the tabs
 
743
void CGUITabControl::setTabHeight( s32 height )
 
744
{
 
745
        if ( height < 0 )
 
746
                height = 0;
 
747
 
 
748
        TabHeight = height;
 
749
 
 
750
        recalculateScrollButtonPlacement();
 
751
        recalculateScrollBar();
 
752
}
 
753
 
 
754
 
 
755
//! Get the height of the tabs
 
756
s32 CGUITabControl::getTabHeight() const
 
757
{
 
758
        return TabHeight;
 
759
}
 
760
 
 
761
//! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
 
762
void CGUITabControl::setTabMaxWidth(s32 width )
 
763
{
 
764
        TabMaxWidth = width;
 
765
}
 
766
 
 
767
//! get the maximal width of a tab
 
768
s32 CGUITabControl::getTabMaxWidth() const
 
769
{
 
770
        return TabMaxWidth;
 
771
}
 
772
 
 
773
 
 
774
//! Set the extra width added to tabs on each side of the text
 
775
void CGUITabControl::setTabExtraWidth( s32 extraWidth )
 
776
{
 
777
        if ( extraWidth < 0 )
 
778
                extraWidth = 0;
 
779
 
 
780
        TabExtraWidth = extraWidth;
 
781
 
 
782
        recalculateScrollBar();
 
783
}
 
784
 
 
785
 
 
786
//! Get the extra width added to tabs on each side of the text
 
787
s32 CGUITabControl::getTabExtraWidth() const
 
788
{
 
789
        return TabExtraWidth;
 
790
}
 
791
 
 
792
 
 
793
void CGUITabControl::recalculateScrollBar()
 
794
{
 
795
        if (!UpButton || !DownButton)
 
796
                return;
 
797
 
 
798
        ScrollControl = needScrollControl() || CurrentScrollTabIndex > 0;
 
799
 
 
800
        if (ScrollControl)
 
801
        {
 
802
                UpButton->setVisible( true );
 
803
                DownButton->setVisible( true );
 
804
        }
 
805
        else
 
806
        {
 
807
                UpButton->setVisible( false );
 
808
                DownButton->setVisible( false );
 
809
        }
 
810
 
 
811
        bringToFront( UpButton );
 
812
        bringToFront( DownButton );
 
813
}
 
814
 
 
815
//! Set the alignment of the tabs
 
816
void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment )
 
817
{
 
818
        VerticalAlignment = alignment;
 
819
 
 
820
        recalculateScrollButtonPlacement();
 
821
        recalculateScrollBar();
 
822
 
 
823
        core::rect<s32> r(calcTabPos());
 
824
        for ( u32 i=0; i<Tabs.size(); ++i )
 
825
        {
 
826
                Tabs[i]->setRelativePosition(r);
 
827
        }
 
828
}
 
829
 
 
830
void CGUITabControl::recalculateScrollButtonPlacement()
 
831
{
 
832
        IGUISkin* skin = Environment->getSkin();
 
833
        s32 ButtonSize = 16;
 
834
        s32 ButtonHeight = TabHeight - 2;
 
835
        if ( ButtonHeight < 0 )
 
836
                ButtonHeight = TabHeight;
 
837
        if (skin)
 
838
        {
 
839
                ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
 
840
                if (ButtonSize > TabHeight)
 
841
                        ButtonSize = TabHeight;
 
842
        }
 
843
 
 
844
        s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f*(f32)ButtonSize) - 1;
 
845
        s32 ButtonY = 0;
 
846
 
 
847
        if (VerticalAlignment == EGUIA_UPPERLEFT)
 
848
        {
 
849
                ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2);
 
850
                UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
 
851
                DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
 
852
        }
 
853
        else
 
854
        {
 
855
                ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2;
 
856
                UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
 
857
                DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
 
858
        }
 
859
 
 
860
        UpButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
 
861
        ButtonX += ButtonSize + 1;
 
862
        DownButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
 
863
}
 
864
 
 
865
//! Get the alignment of the tabs
 
866
EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const
 
867
{
 
868
        return VerticalAlignment;
 
869
}
 
870
 
 
871
 
 
872
s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const
 
873
{
 
874
        core::position2di p(xpos, ypos);
 
875
        IGUISkin* skin = Environment->getSkin();
 
876
        IGUIFont* font = skin->getFont();
 
877
 
 
878
        core::rect<s32> frameRect(AbsoluteRect);
 
879
 
 
880
        if ( VerticalAlignment == EGUIA_UPPERLEFT )
 
881
        {
 
882
                frameRect.UpperLeftCorner.Y += 2;
 
883
                frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
 
884
        }
 
885
        else
 
886
        {
 
887
                frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight;
 
888
        }
 
889
 
 
890
        s32 pos = frameRect.UpperLeftCorner.X + 2;
 
891
 
 
892
        if (!frameRect.isPointInside(p))
 
893
                return -1;
 
894
 
 
895
        for (s32 i=CurrentScrollTabIndex; i<(s32)Tabs.size(); ++i)
 
896
        {
 
897
                // get Text
 
898
                const wchar_t* text = 0;
 
899
                if (Tabs[i])
 
900
                        text = Tabs[i]->getText();
 
901
 
 
902
                // get text length
 
903
                s32 len = calcTabWidth(pos, font, text, true);
 
904
                if ( ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 )
 
905
                        return -1;
 
906
 
 
907
                frameRect.UpperLeftCorner.X = pos;
 
908
                frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
 
909
 
 
910
                pos += len;
 
911
 
 
912
                if (frameRect.isPointInside(p))
 
913
                {
 
914
                        return i;
 
915
                }
 
916
        }
 
917
        return -1;
 
918
}
 
919
 
 
920
//! Returns which tab is currently active
 
921
s32 CGUITabControl::getActiveTab() const
 
922
{
 
923
        return ActiveTab;
 
924
}
 
925
 
 
926
 
 
927
//! Brings a tab to front.
 
928
bool CGUITabControl::setActiveTab(s32 idx)
 
929
{
 
930
        if ((u32)idx >= Tabs.size())
 
931
                return false;
 
932
 
 
933
        bool changed = (ActiveTab != idx);
 
934
 
 
935
        ActiveTab = idx;
 
936
 
 
937
        for (s32 i=0; i<(s32)Tabs.size(); ++i)
 
938
                if (Tabs[i])
 
939
                        Tabs[i]->setVisible( i == ActiveTab );
 
940
 
 
941
        if (changed)
 
942
        {
 
943
                SEvent event;
 
944
                event.EventType = EET_GUI_EVENT;
 
945
                event.GUIEvent.Caller = this;
 
946
                event.GUIEvent.Element = 0;
 
947
                event.GUIEvent.EventType = EGET_TAB_CHANGED;
 
948
                Parent->OnEvent(event);
 
949
        }
 
950
 
 
951
        return true;
 
952
}
 
953
 
 
954
 
 
955
bool CGUITabControl::setActiveTab(IGUITab *tab)
 
956
{
 
957
        for (s32 i=0; i<(s32)Tabs.size(); ++i)
 
958
                if (Tabs[i] == tab)
 
959
                        return setActiveTab(i);
 
960
        return false;
 
961
}
 
962
 
 
963
 
 
964
//! Removes a child.
 
965
void CGUITabControl::removeChild(IGUIElement* child)
 
966
{
 
967
        bool isTab = false;
 
968
 
 
969
        u32 i=0;
 
970
        // check if it is a tab
 
971
        while (i<Tabs.size())
 
972
        {
 
973
                if (Tabs[i] == child)
 
974
                {
 
975
                        Tabs[i]->drop();
 
976
                        Tabs.erase(i);
 
977
                        isTab = true;
 
978
                }
 
979
                else
 
980
                        ++i;
 
981
        }
 
982
 
 
983
        // reassign numbers
 
984
        if (isTab)
 
985
        {
 
986
                for (i=0; i<Tabs.size(); ++i)
 
987
                        if (Tabs[i])
 
988
                                Tabs[i]->setNumber(i);
 
989
        }
 
990
 
 
991
        // remove real element
 
992
        IGUIElement::removeChild(child);
 
993
 
 
994
        recalculateScrollBar();
 
995
}
 
996
 
 
997
 
 
998
//! Update the position of the element, decides scroll button status
 
999
void CGUITabControl::updateAbsolutePosition()
 
1000
{
 
1001
        IGUIElement::updateAbsolutePosition();
 
1002
        recalculateScrollBar();
 
1003
}
 
1004
 
 
1005
 
 
1006
//! Writes attributes of the element.
 
1007
void CGUITabControl::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
 
1008
{
 
1009
        IGUITabControl::serializeAttributes(out,options);
 
1010
 
 
1011
        out->addInt ("ActiveTab",       ActiveTab);
 
1012
        out->addBool("Border",          Border);
 
1013
        out->addBool("FillBackground",  FillBackground);
 
1014
        out->addInt ("TabHeight",       TabHeight);
 
1015
        out->addInt ("TabMaxWidth", TabMaxWidth);
 
1016
        out->addEnum("TabVerticalAlignment", s32(VerticalAlignment), GUIAlignmentNames);
 
1017
}
 
1018
 
 
1019
 
 
1020
//! Reads attributes of the element
 
1021
void CGUITabControl::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
 
1022
{
 
1023
        Border          = in->getAttributeAsBool("Border");
 
1024
        FillBackground  = in->getAttributeAsBool("FillBackground");
 
1025
 
 
1026
        ActiveTab = -1;
 
1027
 
 
1028
        setTabHeight(in->getAttributeAsInt("TabHeight"));
 
1029
        TabMaxWidth     = in->getAttributeAsInt("TabMaxWidth");
 
1030
 
 
1031
        IGUITabControl::deserializeAttributes(in,options);
 
1032
 
 
1033
        setActiveTab(in->getAttributeAsInt("ActiveTab"));
 
1034
        setTabVerticalAlignment( static_cast<EGUI_ALIGNMENT>(in->getAttributeAsEnumeration("TabVerticalAlignment" , GUIAlignmentNames)) );
 
1035
}
 
1036
 
 
1037
 
 
1038
} // end namespace irr
 
1039
} // end namespace gui
 
1040
 
 
1041
#endif // _IRR_COMPILE_WITH_GUI_
 
1042