1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CGUITabControl.h"
\r
7 #include "CGUIButton.h"
\r
8 #include "IGUISkin.h"
\r
9 #include "IGUIEnvironment.h"
\r
10 #include "IGUIFont.h"
\r
11 #include "IVideoDriver.h"
\r
20 // ------------------------------------------------------------------
\r
22 // ------------------------------------------------------------------
\r
25 CGUITab::CGUITab(IGUIEnvironment* environment,
\r
26 IGUIElement* parent, const core::rect<s32>& rectangle,
\r
28 : IGUITab(environment, parent, id, rectangle),
\r
29 BackColor(0,0,0,0), OverrideTextColorEnabled(false), TextColor(255,0,0,0),
\r
30 DrawBackground(false)
\r
33 setDebugName("CGUITab");
\r
36 const IGUISkin* const skin = environment->getSkin();
\r
38 TextColor = skin->getColor(EGDC_BUTTON_TEXT);
\r
41 //! draws the element and its children
\r
42 void CGUITab::draw()
\r
47 IGUISkin *skin = Environment->getSkin();
\r
49 if (skin && DrawBackground)
\r
50 skin->draw2DRectangle(this, BackColor, AbsoluteRect, &AbsoluteClippingRect);
\r
52 IGUIElement::draw();
\r
56 //! sets if the tab should draw its background
\r
57 void CGUITab::setDrawBackground(bool draw)
\r
59 DrawBackground = draw;
\r
63 //! sets the color of the background, if it should be drawn.
\r
64 void CGUITab::setBackgroundColor(video::SColor c)
\r
70 //! sets the color of the text
\r
71 void CGUITab::setTextColor(video::SColor c)
\r
73 OverrideTextColorEnabled = true;
\r
78 video::SColor CGUITab::getTextColor() const
\r
80 if ( OverrideTextColorEnabled )
\r
83 return Environment->getSkin()->getColor(EGDC_BUTTON_TEXT);
\r
86 //! returns true if the tab is drawing its background, false if not
\r
87 bool CGUITab::isDrawingBackground() const
\r
89 return DrawBackground;
\r
93 //! returns the color of the background
\r
94 video::SColor CGUITab::getBackgroundColor() const
\r
100 // ------------------------------------------------------------------
\r
102 // ------------------------------------------------------------------
\r
105 CGUITabControl::CGUITabControl(IGUIEnvironment* environment,
\r
106 IGUIElement* parent, const core::rect<s32>& rectangle,
\r
107 bool fillbackground, bool border, s32 id)
\r
108 : IGUITabControl(environment, parent, id, rectangle), ActiveTabIndex(-1),
\r
109 Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT),
\r
110 UpButton(0), DownButton(0), TabMaxWidth(0), CurrentScrollTabIndex(0), TabExtraWidth(20)
\r
113 setDebugName("CGUITabControl");
\r
116 IGUISkin* skin = Environment->getSkin();
\r
117 IGUISpriteBank* sprites = 0;
\r
123 sprites = skin->getSpriteBank();
\r
124 TabHeight = skin->getSize(gui::EGDS_BUTTON_HEIGHT) + 2;
\r
127 UpButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
\r
131 UpButton->setSpriteBank(sprites);
\r
132 UpButton->setVisible(false);
\r
133 UpButton->setSubElement(true);
\r
134 UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
135 UpButton->setOverrideFont(Environment->getBuiltInFont());
\r
139 DownButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
\r
143 DownButton->setSpriteBank(sprites);
\r
144 DownButton->setVisible(false);
\r
145 DownButton->setSubElement(true);
\r
146 DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
147 DownButton->setOverrideFont(Environment->getBuiltInFont());
\r
148 DownButton->grab();
\r
151 setTabVerticalAlignment(EGUIA_UPPERLEFT);
\r
156 CGUITabControl::~CGUITabControl()
\r
158 for (u32 i=0; i<Tabs.size(); ++i)
\r
168 DownButton->drop();
\r
171 void CGUITabControl::refreshSprites()
\r
173 video::SColor color(255,255,255,255);
\r
174 IGUISkin* skin = Environment->getSkin();
\r
177 color = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
\r
181 UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), color);
\r
182 UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), color);
\r
187 DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), color);
\r
188 DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), color);
\r
194 IGUITab* CGUITabControl::addTab(const wchar_t* caption, s32 id)
\r
196 CGUITab* tab = new CGUITab(Environment, this, calcTabPos(), id);
\r
198 tab->setText(caption);
\r
199 tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
\r
200 tab->setVisible(false);
\r
201 Tabs.push_back(tab); // no grab as new already creates a reference
\r
203 if (ActiveTabIndex == -1)
\r
205 ActiveTabIndex = Tabs.size()-1;
\r
206 tab->setVisible(true);
\r
209 recalculateScrollBar();
\r
215 //! adds a tab which has been created elsewhere
\r
216 s32 CGUITabControl::addTab(IGUITab* tab)
\r
218 return insertTab( Tabs.size(), tab, false);
\r
221 //! Insert the tab at the given index
\r
222 IGUITab* CGUITabControl::insertTab(s32 idx, const wchar_t* caption, s32 id)
\r
224 if ( idx < 0 || idx > (s32)Tabs.size() ) // idx == Tabs.size() is indeed OK here as core::array can handle that
\r
227 CGUITab* tab = new CGUITab(Environment, this, calcTabPos(), id);
\r
229 tab->setText(caption);
\r
230 tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
\r
231 tab->setVisible(false);
\r
232 Tabs.insert(tab, (u32)idx);
\r
234 if (ActiveTabIndex == -1)
\r
236 ActiveTabIndex = (u32)idx;
\r
237 tab->setVisible(true);
\r
239 else if ( idx <= ActiveTabIndex )
\r
242 setVisibleTab(ActiveTabIndex);
\r
245 recalculateScrollBar();
\r
250 s32 CGUITabControl::insertTab(s32 idx, IGUITab* tab, bool serializationMode)
\r
254 if ( idx > (s32)Tabs.size() && !serializationMode ) // idx == Tabs.size() is indeed OK here as core::array can handle that
\r
256 // Not allowing to add same tab twice as it would make things complicated (serialization or setting active visible)
\r
257 if ( getTabIndex(tab) >= 0 )
\r
261 idx = (s32)Tabs.size();
\r
263 if ( tab->getParent() != this )
\r
264 this->addChildToEnd(tab);
\r
266 tab->setVisible(false);
\r
270 if ( serializationMode)
\r
272 while ( idx >= (s32)Tabs.size() )
\r
278 if ( idx == ActiveTabIndex) // in serialization that can happen for any index
\r
280 setVisibleTab(ActiveTabIndex);
\r
281 tab->setVisible(true);
\r
286 Tabs.insert(tab, (u32)idx);
\r
288 if (ActiveTabIndex == -1)
\r
290 ActiveTabIndex = idx;
\r
291 setVisibleTab(ActiveTabIndex);
\r
293 else if ( idx <= ActiveTabIndex)
\r
296 setVisibleTab(ActiveTabIndex);
\r
300 recalculateScrollBar();
\r
305 //! Removes a child.
\r
306 void CGUITabControl::removeChild(IGUIElement* child)
\r
308 s32 idx = getTabIndex(child);
\r
310 removeTabButNotChild(idx);
\r
312 // remove real element
\r
313 IGUIElement::removeChild(child);
\r
315 recalculateScrollBar();
\r
319 //! Removes a tab from the tabcontrol
\r
320 void CGUITabControl::removeTab(s32 idx)
\r
322 if ( idx < 0 || idx >= (s32)Tabs.size() )
\r
325 removeChild(Tabs[(u32)idx]);
\r
328 void CGUITabControl::removeTabButNotChild(s32 idx)
\r
330 if ( idx < 0 || idx >= (s32)Tabs.size() )
\r
333 Tabs[(u32)idx]->drop();
\r
334 Tabs.erase((u32)idx);
\r
336 if ( idx < ActiveTabIndex )
\r
339 setVisibleTab(ActiveTabIndex);
\r
341 else if ( idx == ActiveTabIndex )
\r
343 if ( (u32)idx == Tabs.size() )
\r
345 setVisibleTab(ActiveTabIndex);
\r
349 //! Clears the tabcontrol removing all tabs
\r
350 void CGUITabControl::clear()
\r
352 for (u32 i=0; i<Tabs.size(); ++i)
\r
356 IGUIElement::removeChild(Tabs[i]);
\r
362 recalculateScrollBar();
\r
365 //! Returns amount of tabs in the tabcontrol
\r
366 s32 CGUITabControl::getTabCount() const
\r
368 return Tabs.size();
\r
372 //! Returns a tab based on zero based index
\r
373 IGUITab* CGUITabControl::getTab(s32 idx) const
\r
375 if (idx < 0 || (u32)idx >= Tabs.size())
\r
382 //! called if an event happened.
\r
383 bool CGUITabControl::OnEvent(const SEvent& event)
\r
387 switch(event.EventType)
\r
389 case EET_GUI_EVENT:
\r
390 switch(event.GUIEvent.EventType)
\r
392 case EGET_BUTTON_CLICKED:
\r
393 if (event.GUIEvent.Caller == UpButton)
\r
398 else if (event.GUIEvent.Caller == DownButton)
\r
409 case EET_MOUSE_INPUT_EVENT:
\r
410 switch(event.MouseInput.Event)
\r
412 //case EMIE_LMOUSE_PRESSED_DOWN:
\r
413 // // todo: dragging tabs around
\r
415 case EMIE_LMOUSE_LEFT_UP:
\r
417 s32 idx = getTabAt(event.MouseInput.X, event.MouseInput.Y);
\r
434 return IGUIElement::OnEvent(event);
\r
438 void CGUITabControl::scrollLeft()
\r
440 if ( CurrentScrollTabIndex > 0 )
\r
441 --CurrentScrollTabIndex;
\r
442 recalculateScrollBar();
\r
446 void CGUITabControl::scrollRight()
\r
448 if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 )
\r
450 if ( needScrollControl(CurrentScrollTabIndex, true) )
\r
451 ++CurrentScrollTabIndex;
\r
453 recalculateScrollBar();
\r
456 s32 CGUITabControl::calcTabWidth(IGUIFont* font, const wchar_t* text) const
\r
461 s32 len = font->getDimension(text).Width + TabExtraWidth;
\r
462 if ( TabMaxWidth > 0 && len > TabMaxWidth )
\r
468 bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl, s32 *pos_rightmost)
\r
470 if ( startIndex < 0 )
\r
473 IGUISkin* skin = Environment->getSkin();
\r
477 IGUIFont* font = skin->getFont();
\r
485 s32 pos = AbsoluteRect.UpperLeftCorner.X + 2;
\r
486 const s32 pos_right = withScrollControl ?
\r
487 UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 :
\r
488 AbsoluteRect.LowerRightCorner.X;
\r
490 for (s32 i = startIndex; i < (s32)Tabs.size(); ++i)
\r
493 const wchar_t* text = 0;
\r
496 text = Tabs[i]->getText();
\r
499 s32 len = calcTabWidth(font, text); // always without withScrollControl here or len would be shortened
\r
503 if (pos > pos_right)
\r
508 *pos_rightmost = pos;
\r
513 s32 CGUITabControl::calculateScrollIndexFromActive()
\r
515 if (!ScrollControl || Tabs.empty())
\r
518 IGUISkin *skin = Environment->getSkin();
\r
522 IGUIFont *font = skin->getFont();
\r
526 const s32 pos_left = AbsoluteRect.UpperLeftCorner.X + 2;
\r
527 const s32 pos_right = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2;
\r
529 // Move from center to the left border left until it is reached
\r
530 s32 pos_cl = (pos_left + pos_right) / 2;
\r
531 s32 i = ActiveTabIndex;
\r
532 for (; i > 0; --i) {
\r
536 s32 len = calcTabWidth(font, Tabs[i]->getText());
\r
537 if (i == ActiveTabIndex)
\r
539 if (pos_cl - len < pos_left)
\r
547 // Is scrolling to right still possible?
\r
549 if (needScrollControl(i, true, &pos_rr))
\r
550 return i; // Yes? -> OK
\r
552 // No? -> Decrease "i" more. Append tabs until scrolling becomes necessary
\r
553 for (--i; i > 0; --i) {
\r
557 pos_rr += calcTabWidth(font, Tabs[i]->getText());
\r
558 if (pos_rr > pos_right)
\r
564 core::rect<s32> CGUITabControl::calcTabPos()
\r
567 r.UpperLeftCorner.X = 0;
\r
568 r.LowerRightCorner.X = AbsoluteRect.getWidth();
\r
571 ++r.UpperLeftCorner.X;
\r
572 --r.LowerRightCorner.X;
\r
575 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
577 r.UpperLeftCorner.Y = TabHeight+2;
\r
578 r.LowerRightCorner.Y = AbsoluteRect.getHeight()-1;
\r
581 --r.LowerRightCorner.Y;
\r
586 r.UpperLeftCorner.Y = 0;
\r
587 r.LowerRightCorner.Y = AbsoluteRect.getHeight()-(TabHeight+2);
\r
590 ++r.UpperLeftCorner.Y;
\r
598 //! draws the element and its children
\r
599 void CGUITabControl::draw()
\r
604 IGUISkin* skin = Environment->getSkin();
\r
608 IGUIFont* font = skin->getFont();
\r
609 video::IVideoDriver* driver = Environment->getVideoDriver();
\r
611 core::rect<s32> frameRect(AbsoluteRect);
\r
613 // some empty background as placeholder when there are no tabs
\r
615 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
\r
620 // tab button bar can be above or below the tabs
\r
621 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
623 frameRect.UpperLeftCorner.Y += 2;
\r
624 frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
\r
628 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight - 1;
\r
629 frameRect.LowerRightCorner.Y -= 2;
\r
632 core::rect<s32> tr;
\r
633 s32 pos = frameRect.UpperLeftCorner.X + 2;
\r
635 bool needLeftScroll = CurrentScrollTabIndex > 0;
\r
636 bool needRightScroll = false;
\r
638 // left and right pos of the active tab
\r
642 //const wchar_t* activetext = 0;
\r
643 IGUITab *activeTab = 0;
\r
645 // Draw all tab-buttons except the active one
\r
646 for (u32 i = CurrentScrollTabIndex; i < Tabs.size() && !needRightScroll; ++i)
\r
649 const wchar_t* text = 0;
\r
651 text = Tabs[i]->getText();
\r
654 s32 len = calcTabWidth(font, text);
\r
655 if (ScrollControl) {
\r
656 s32 space = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos;
\r
658 needRightScroll = true;
\r
663 frameRect.LowerRightCorner.X += len;
\r
664 frameRect.UpperLeftCorner.X = pos;
\r
665 frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
\r
669 if ((s32)i == ActiveTabIndex)
\r
671 // for active button just remember values
\r
672 left = frameRect.UpperLeftCorner.X;
\r
673 right = frameRect.LowerRightCorner.X;
\r
674 //activetext = text;
\r
675 activeTab = Tabs[i];
\r
679 skin->draw3DTabButton(this, false, frameRect, &AbsoluteClippingRect, VerticalAlignment);
\r
682 core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
\r
683 textClipRect.clipAgainst(AbsoluteClippingRect);
\r
684 font->draw(text, frameRect, Tabs[i]->getTextColor(),
\r
685 true, true, &textClipRect);
\r
689 // Draw active tab button
\r
690 // Drawn later than other buttons because it draw over the buttons before/after it.
\r
691 if (left != 0 && right != 0 && activeTab != 0)
\r
693 // draw upper highlight frame
\r
694 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
696 frameRect.UpperLeftCorner.X = left-2;
\r
697 frameRect.LowerRightCorner.X = right+2;
\r
698 frameRect.UpperLeftCorner.Y -= 2;
\r
700 skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
\r
703 core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
\r
704 textClipRect.clipAgainst(AbsoluteClippingRect);
\r
705 font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
\r
706 true, true, &textClipRect);
\r
708 tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
\r
709 tr.LowerRightCorner.X = left - 1;
\r
710 tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
\r
711 tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
\r
712 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
\r
714 tr.UpperLeftCorner.X = right;
\r
715 tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
\r
716 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
\r
720 frameRect.UpperLeftCorner.X = left-2;
\r
721 frameRect.LowerRightCorner.X = right+2;
\r
722 frameRect.LowerRightCorner.Y += 2;
\r
724 skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
\r
727 font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
\r
728 true, true, &frameRect);
\r
730 tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
\r
731 tr.LowerRightCorner.X = left - 1;
\r
732 tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
\r
733 tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
\r
734 driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
\r
736 tr.UpperLeftCorner.X = right;
\r
737 tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
\r
738 driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
\r
744 // Draw a line separating button bar from tab area
\r
745 tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
\r
746 tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
\r
747 tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
\r
748 tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
\r
750 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
752 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
\r
756 tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
\r
757 tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
\r
758 driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
\r
762 // drawing some border and background for the tab-area.
\r
763 skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment);
\r
765 // enable scrollcontrols on need
\r
767 UpButton->setEnabled(needLeftScroll);
\r
769 DownButton->setEnabled(needRightScroll);
\r
772 IGUIElement::draw();
\r
776 //! Set the height of the tabs
\r
777 void CGUITabControl::setTabHeight( s32 height )
\r
782 TabHeight = height;
\r
784 recalculateScrollButtonPlacement();
\r
785 recalculateScrollBar();
\r
789 //! Get the height of the tabs
\r
790 s32 CGUITabControl::getTabHeight() const
\r
795 //! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
\r
796 void CGUITabControl::setTabMaxWidth(s32 width )
\r
798 TabMaxWidth = width;
\r
801 //! get the maximal width of a tab
\r
802 s32 CGUITabControl::getTabMaxWidth() const
\r
804 return TabMaxWidth;
\r
808 //! Set the extra width added to tabs on each side of the text
\r
809 void CGUITabControl::setTabExtraWidth( s32 extraWidth )
\r
811 if ( extraWidth < 0 )
\r
814 TabExtraWidth = extraWidth;
\r
816 recalculateScrollBar();
\r
820 //! Get the extra width added to tabs on each side of the text
\r
821 s32 CGUITabControl::getTabExtraWidth() const
\r
823 return TabExtraWidth;
\r
827 void CGUITabControl::recalculateScrollBar()
\r
829 // Down: to right, Up: to left
\r
830 if (!UpButton || !DownButton)
\r
833 ScrollControl = needScrollControl() || CurrentScrollTabIndex > 0;
\r
837 UpButton->setVisible( true );
\r
838 DownButton->setVisible( true );
\r
842 UpButton->setVisible( false );
\r
843 DownButton->setVisible( false );
\r
846 bringToFront( UpButton );
\r
847 bringToFront( DownButton );
\r
850 //! Set the alignment of the tabs
\r
851 void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment )
\r
853 VerticalAlignment = alignment;
\r
855 recalculateScrollButtonPlacement();
\r
856 recalculateScrollBar();
\r
858 core::rect<s32> r(calcTabPos());
\r
859 for ( u32 i=0; i<Tabs.size(); ++i )
\r
861 Tabs[i]->setRelativePosition(r);
\r
865 void CGUITabControl::recalculateScrollButtonPlacement()
\r
867 IGUISkin* skin = Environment->getSkin();
\r
868 s32 ButtonSize = 16;
\r
869 s32 ButtonHeight = TabHeight - 2;
\r
870 if ( ButtonHeight < 0 )
\r
871 ButtonHeight = TabHeight;
\r
874 ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
\r
875 if (ButtonSize > TabHeight)
\r
876 ButtonSize = TabHeight;
\r
879 s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f*(f32)ButtonSize) - 1;
\r
882 if (VerticalAlignment == EGUIA_UPPERLEFT)
\r
884 ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2);
\r
885 UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
886 DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
890 ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2;
\r
891 UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
\r
892 DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
\r
895 UpButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
\r
896 ButtonX += ButtonSize + 1;
\r
897 DownButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
\r
900 //! Get the alignment of the tabs
\r
901 EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const
\r
903 return VerticalAlignment;
\r
907 s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const
\r
909 core::position2di p(xpos, ypos);
\r
910 IGUISkin* skin = Environment->getSkin();
\r
911 IGUIFont* font = skin->getFont();
\r
913 core::rect<s32> frameRect(AbsoluteRect);
\r
915 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
917 frameRect.UpperLeftCorner.Y += 2;
\r
918 frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
\r
922 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight;
\r
925 s32 pos = frameRect.UpperLeftCorner.X + 2;
\r
927 if (!frameRect.isPointInside(p))
\r
930 bool abort = false;
\r
931 for (s32 i = CurrentScrollTabIndex; i < (s32)Tabs.size() && !abort; ++i)
\r
934 const wchar_t* text = 0;
\r
936 text = Tabs[i]->getText();
\r
939 s32 len = calcTabWidth(font, text);
\r
940 if (ScrollControl) {
\r
941 // TODO: merge this with draw() ?
\r
942 s32 space = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos;
\r
949 frameRect.UpperLeftCorner.X = pos;
\r
950 frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
\r
954 if (frameRect.isPointInside(p))
\r
963 //! Returns which tab is currently active
\r
964 s32 CGUITabControl::getActiveTab() const
\r
966 return ActiveTabIndex;
\r
970 //! Brings a tab to front.
\r
971 bool CGUITabControl::setActiveTab(s32 idx)
\r
973 if ((u32)idx >= Tabs.size())
\r
976 bool changed = (ActiveTabIndex != idx);
\r
978 ActiveTabIndex = idx;
\r
980 setVisibleTab(ActiveTabIndex);
\r
982 if (changed && Parent)
\r
985 event.EventType = EET_GUI_EVENT;
\r
986 event.GUIEvent.Caller = this;
\r
987 event.GUIEvent.Element = 0;
\r
988 event.GUIEvent.EventType = EGET_TAB_CHANGED;
\r
989 Parent->OnEvent(event);
\r
992 if (ScrollControl) {
\r
993 CurrentScrollTabIndex = calculateScrollIndexFromActive();
\r
994 recalculateScrollBar();
\r
1000 void CGUITabControl::setVisibleTab(s32 idx)
\r
1002 for (u32 i=0; i<Tabs.size(); ++i)
\r
1004 Tabs[i]->setVisible( (s32)i == idx );
\r
1008 bool CGUITabControl::setActiveTab(IGUITab *tab)
\r
1010 return setActiveTab(getTabIndex(tab));
\r
1013 s32 CGUITabControl::getTabIndex(const IGUIElement *tab) const
\r
1015 for (u32 i=0; i<Tabs.size(); ++i)
\r
1016 if (Tabs[i] == tab)
\r
1022 //! Update the position of the element, decides scroll button status
\r
1023 void CGUITabControl::updateAbsolutePosition()
\r
1025 IGUIElement::updateAbsolutePosition();
\r
1026 recalculateScrollBar();
\r
1030 } // end namespace irr
\r
1031 } // end namespace gui
\r