aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CGUITabControl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CGUITabControl.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CGUITabControl.cpp1042
1 files changed, 1042 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CGUITabControl.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CGUITabControl.cpp
new file mode 100644
index 0000000..a931d92
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CGUITabControl.cpp
@@ -0,0 +1,1042 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "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
16namespace irr
17{
18namespace gui
19{
20
21// ------------------------------------------------------------------
22// Tab
23// ------------------------------------------------------------------
24
25//! constructor
26CGUITab::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.
45s32 CGUITab::getNumber() const
46{
47 return Number;
48}
49
50
51//! Sets the number
52void CGUITab::setNumber(s32 n)
53{
54 Number = n;
55}
56
57void 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
66void 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
81void CGUITab::setDrawBackground(bool draw)
82{
83 DrawBackground = draw;
84}
85
86
87//! sets the color of the background, if it should be drawn.
88void CGUITab::setBackgroundColor(video::SColor c)
89{
90 BackColor = c;
91}
92
93
94//! sets the color of the text
95void CGUITab::setTextColor(video::SColor c)
96{
97 OverrideTextColorEnabled = true;
98 TextColor = c;
99}
100
101
102video::SColor CGUITab::getTextColor() const
103{
104 return TextColor;
105}
106
107
108//! returns true if the tab is drawing its background, false if not
109bool CGUITab::isDrawingBackground() const
110{
111 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
112 return DrawBackground;
113}
114
115
116//! returns the color of the background
117video::SColor CGUITab::getBackgroundColor() const
118{
119 return BackColor;
120}
121
122
123//! Writes attributes of the element.
124void 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
138void 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
166CGUITabControl::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
217CGUITabControl::~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
232void 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
255IGUITab* 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
277void 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
315IGUITab* 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
344void 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
358void 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
369s32 CGUITabControl::getTabCount() const
370{
371 return Tabs.size();
372}
373
374
375//! Returns a tab based on zero based index
376IGUITab* 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.
386bool 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
442void CGUITabControl::scrollLeft()
443{
444 if ( CurrentScrollTabIndex > 0 )
445 --CurrentScrollTabIndex;
446 recalculateScrollBar();
447}
448
449
450void CGUITabControl::scrollRight()
451{
452 if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 )
453 {
454 if ( needScrollControl(CurrentScrollTabIndex, true) )
455 ++CurrentScrollTabIndex;
456 }
457 recalculateScrollBar();
458}
459
460s32 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
484bool 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
535core::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
570void 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
743void 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
756s32 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".
762void CGUITabControl::setTabMaxWidth(s32 width )
763{
764 TabMaxWidth = width;
765}
766
767//! get the maximal width of a tab
768s32 CGUITabControl::getTabMaxWidth() const
769{
770 return TabMaxWidth;
771}
772
773
774//! Set the extra width added to tabs on each side of the text
775void 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
787s32 CGUITabControl::getTabExtraWidth() const
788{
789 return TabExtraWidth;
790}
791
792
793void 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
816void 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
830void 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
866EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const
867{
868 return VerticalAlignment;
869}
870
871
872s32 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
921s32 CGUITabControl::getActiveTab() const
922{
923 return ActiveTab;
924}
925
926
927//! Brings a tab to front.
928bool 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
955bool 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.
965void 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
999void CGUITabControl::updateAbsolutePosition()
1000{
1001 IGUIElement::updateAbsolutePosition();
1002 recalculateScrollBar();
1003}
1004
1005
1006//! Writes attributes of the element.
1007void 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
1021void 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