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
6 #ifdef _IRR_COMPILE_WITH_GUI_
\r
8 #include "CGUIButton.h"
\r
9 #include "IGUISkin.h"
\r
10 #include "IGUIEnvironment.h"
\r
11 #include "IGUIFont.h"
\r
12 #include "IVideoDriver.h"
\r
21 // ------------------------------------------------------------------
\r
23 // ------------------------------------------------------------------
\r
26 CGUITab::CGUITab(IGUIEnvironment* environment,
\r
27 IGUIElement* parent, const core::rect<s32>& rectangle,
\r
29 : IGUITab(environment, parent, id, rectangle),
\r
30 BackColor(0,0,0,0), OverrideTextColorEnabled(false), TextColor(255,0,0,0),
\r
31 DrawBackground(false)
\r
34 setDebugName("CGUITab");
\r
37 const IGUISkin* const skin = environment->getSkin();
\r
39 TextColor = skin->getColor(EGDC_BUTTON_TEXT);
\r
42 //! draws the element and its children
\r
43 void CGUITab::draw()
\r
48 IGUISkin *skin = Environment->getSkin();
\r
50 if (skin && DrawBackground)
\r
51 skin->draw2DRectangle(this, BackColor, AbsoluteRect, &AbsoluteClippingRect);
\r
53 IGUIElement::draw();
\r
57 //! sets if the tab should draw its background
\r
58 void CGUITab::setDrawBackground(bool draw)
\r
60 DrawBackground = draw;
\r
64 //! sets the color of the background, if it should be drawn.
\r
65 void CGUITab::setBackgroundColor(video::SColor c)
\r
71 //! sets the color of the text
\r
72 void CGUITab::setTextColor(video::SColor c)
\r
74 OverrideTextColorEnabled = true;
\r
79 video::SColor CGUITab::getTextColor() const
\r
81 if ( OverrideTextColorEnabled )
\r
84 return Environment->getSkin()->getColor(EGDC_BUTTON_TEXT);
\r
87 //! returns true if the tab is drawing its background, false if not
\r
88 bool CGUITab::isDrawingBackground() const
\r
90 return DrawBackground;
\r
94 //! returns the color of the background
\r
95 video::SColor CGUITab::getBackgroundColor() const
\r
101 // ------------------------------------------------------------------
\r
103 // ------------------------------------------------------------------
\r
106 CGUITabControl::CGUITabControl(IGUIEnvironment* environment,
\r
107 IGUIElement* parent, const core::rect<s32>& rectangle,
\r
108 bool fillbackground, bool border, s32 id)
\r
109 : IGUITabControl(environment, parent, id, rectangle), ActiveTabIndex(-1),
\r
110 Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT),
\r
111 UpButton(0), DownButton(0), TabMaxWidth(0), CurrentScrollTabIndex(0), TabExtraWidth(20)
\r
114 setDebugName("CGUITabControl");
\r
117 IGUISkin* skin = Environment->getSkin();
\r
118 IGUISpriteBank* sprites = 0;
\r
124 sprites = skin->getSpriteBank();
\r
125 TabHeight = skin->getSize(gui::EGDS_BUTTON_HEIGHT) + 2;
\r
128 UpButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
\r
132 UpButton->setSpriteBank(sprites);
\r
133 UpButton->setVisible(false);
\r
134 UpButton->setSubElement(true);
\r
135 UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
136 UpButton->setOverrideFont(Environment->getBuiltInFont());
\r
140 DownButton = Environment->addButton(core::rect<s32>(0,0,10,10), this);
\r
144 DownButton->setSpriteBank(sprites);
\r
145 DownButton->setVisible(false);
\r
146 DownButton->setSubElement(true);
\r
147 DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
148 DownButton->setOverrideFont(Environment->getBuiltInFont());
\r
149 DownButton->grab();
\r
152 setTabVerticalAlignment(EGUIA_UPPERLEFT);
\r
157 CGUITabControl::~CGUITabControl()
\r
159 for (u32 i=0; i<Tabs.size(); ++i)
\r
169 DownButton->drop();
\r
172 void CGUITabControl::refreshSprites()
\r
174 video::SColor color(255,255,255,255);
\r
175 IGUISkin* skin = Environment->getSkin();
\r
178 color = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
\r
182 UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), color);
\r
183 UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), color);
\r
188 DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), color);
\r
189 DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), color);
\r
195 IGUITab* CGUITabControl::addTab(const wchar_t* caption, s32 id)
\r
197 CGUITab* tab = new CGUITab(Environment, this, calcTabPos(), id);
\r
199 tab->setText(caption);
\r
200 tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
\r
201 tab->setVisible(false);
\r
202 Tabs.push_back(tab); // no grab as new already creates a reference
\r
204 if (ActiveTabIndex == -1)
\r
206 ActiveTabIndex = Tabs.size()-1;
\r
207 tab->setVisible(true);
\r
210 recalculateScrollBar();
\r
216 //! adds a tab which has been created elsewhere
\r
217 s32 CGUITabControl::addTab(IGUITab* tab)
\r
219 return insertTab( Tabs.size(), tab, false);
\r
222 //! Insert the tab at the given index
\r
223 IGUITab* CGUITabControl::insertTab(s32 idx, const wchar_t* caption, s32 id)
\r
225 if ( idx < 0 || idx > (s32)Tabs.size() ) // idx == Tabs.size() is indeed OK here as core::array can handle that
\r
228 CGUITab* tab = new CGUITab(Environment, this, calcTabPos(), id);
\r
230 tab->setText(caption);
\r
231 tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
\r
232 tab->setVisible(false);
\r
233 Tabs.insert(tab, (u32)idx);
\r
235 if (ActiveTabIndex == -1)
\r
237 ActiveTabIndex = (u32)idx;
\r
238 tab->setVisible(true);
\r
240 else if ( idx <= ActiveTabIndex )
\r
243 setVisibleTab(ActiveTabIndex);
\r
246 recalculateScrollBar();
\r
251 s32 CGUITabControl::insertTab(s32 idx, IGUITab* tab, bool serializationMode)
\r
255 if ( idx > (s32)Tabs.size() && !serializationMode ) // idx == Tabs.size() is indeed OK here as core::array can handle that
\r
257 // Not allowing to add same tab twice as it would make things complicated (serialization or setting active visible)
\r
258 if ( getTabIndex(tab) >= 0 )
\r
262 idx = (s32)Tabs.size();
\r
264 if ( tab->getParent() != this )
\r
265 this->addChildToEnd(tab);
\r
267 tab->setVisible(false);
\r
271 if ( serializationMode)
\r
273 while ( idx >= (s32)Tabs.size() )
\r
279 if ( idx == ActiveTabIndex) // in serialization that can happen for any index
\r
281 setVisibleTab(ActiveTabIndex);
\r
282 tab->setVisible(true);
\r
287 Tabs.insert(tab, (u32)idx);
\r
289 if (ActiveTabIndex == -1)
\r
291 ActiveTabIndex = idx;
\r
292 setVisibleTab(ActiveTabIndex);
\r
294 else if ( idx <= ActiveTabIndex)
\r
297 setVisibleTab(ActiveTabIndex);
\r
301 recalculateScrollBar();
\r
306 //! Removes a child.
\r
307 void CGUITabControl::removeChild(IGUIElement* child)
\r
309 s32 idx = getTabIndex(child);
\r
311 removeTabButNotChild(idx);
\r
313 // remove real element
\r
314 IGUIElement::removeChild(child);
\r
316 recalculateScrollBar();
\r
320 //! Removes a tab from the tabcontrol
\r
321 void CGUITabControl::removeTab(s32 idx)
\r
323 if ( idx < 0 || idx >= (s32)Tabs.size() )
\r
326 removeChild(Tabs[(u32)idx]);
\r
329 void CGUITabControl::removeTabButNotChild(s32 idx)
\r
331 if ( idx < 0 || idx >= (s32)Tabs.size() )
\r
334 Tabs[(u32)idx]->drop();
\r
335 Tabs.erase((u32)idx);
\r
337 if ( idx < ActiveTabIndex )
\r
340 setVisibleTab(ActiveTabIndex);
\r
342 else if ( idx == ActiveTabIndex )
\r
344 if ( (u32)idx == Tabs.size() )
\r
346 setVisibleTab(ActiveTabIndex);
\r
350 //! Clears the tabcontrol removing all tabs
\r
351 void CGUITabControl::clear()
\r
353 for (u32 i=0; i<Tabs.size(); ++i)
\r
357 IGUIElement::removeChild(Tabs[i]);
\r
363 recalculateScrollBar();
\r
366 //! Returns amount of tabs in the tabcontrol
\r
367 s32 CGUITabControl::getTabCount() const
\r
369 return Tabs.size();
\r
373 //! Returns a tab based on zero based index
\r
374 IGUITab* CGUITabControl::getTab(s32 idx) const
\r
376 if (idx < 0 || (u32)idx >= Tabs.size())
\r
383 //! called if an event happened.
\r
384 bool CGUITabControl::OnEvent(const SEvent& event)
\r
388 switch(event.EventType)
\r
390 case EET_GUI_EVENT:
\r
391 switch(event.GUIEvent.EventType)
\r
393 case EGET_BUTTON_CLICKED:
\r
394 if (event.GUIEvent.Caller == UpButton)
\r
399 else if (event.GUIEvent.Caller == DownButton)
\r
410 case EET_MOUSE_INPUT_EVENT:
\r
411 switch(event.MouseInput.Event)
\r
413 //case EMIE_LMOUSE_PRESSED_DOWN:
\r
414 // // todo: dragging tabs around
\r
416 case EMIE_LMOUSE_LEFT_UP:
\r
418 s32 idx = getTabAt(event.MouseInput.X, event.MouseInput.Y);
\r
435 return IGUIElement::OnEvent(event);
\r
439 void CGUITabControl::scrollLeft()
\r
441 if ( CurrentScrollTabIndex > 0 )
\r
442 --CurrentScrollTabIndex;
\r
443 recalculateScrollBar();
\r
447 void CGUITabControl::scrollRight()
\r
449 if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 )
\r
451 if ( needScrollControl(CurrentScrollTabIndex, true) )
\r
452 ++CurrentScrollTabIndex;
\r
454 recalculateScrollBar();
\r
457 s32 CGUITabControl::calcTabWidth(IGUIFont* font, const wchar_t* text) const
\r
462 s32 len = font->getDimension(text).Width + TabExtraWidth;
\r
463 if ( TabMaxWidth > 0 && len > TabMaxWidth )
\r
469 bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl, s32 *pos_rightmost)
\r
471 if ( startIndex < 0 )
\r
474 IGUISkin* skin = Environment->getSkin();
\r
478 IGUIFont* font = skin->getFont();
\r
486 s32 pos = AbsoluteRect.UpperLeftCorner.X + 2;
\r
487 const s32 pos_right = withScrollControl ?
\r
488 UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 :
\r
489 AbsoluteRect.LowerRightCorner.X;
\r
491 for (s32 i = startIndex; i < (s32)Tabs.size(); ++i)
\r
494 const wchar_t* text = 0;
\r
497 text = Tabs[i]->getText();
\r
500 s32 len = calcTabWidth(font, text); // always without withScrollControl here or len would be shortened
\r
504 if (pos > pos_right)
\r
509 *pos_rightmost = pos;
\r
514 s32 CGUITabControl::calculateScrollIndexFromActive()
\r
516 if (!ScrollControl || Tabs.empty())
\r
519 IGUISkin *skin = Environment->getSkin();
\r
523 IGUIFont *font = skin->getFont();
\r
527 const s32 pos_left = AbsoluteRect.UpperLeftCorner.X + 2;
\r
528 const s32 pos_right = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2;
\r
530 // Move from center to the left border left until it is reached
\r
531 s32 pos_cl = (pos_left + pos_right) / 2;
\r
532 s32 i = ActiveTabIndex;
\r
533 for (; i > 0; --i) {
\r
537 s32 len = calcTabWidth(font, Tabs[i]->getText());
\r
538 if (i == ActiveTabIndex)
\r
540 if (pos_cl - len < pos_left)
\r
548 // Is scrolling to right still possible?
\r
550 if (needScrollControl(i, true, &pos_rr))
\r
551 return i; // Yes? -> OK
\r
553 // No? -> Decrease "i" more. Append tabs until scrolling becomes necessary
\r
554 for (--i; i > 0; --i) {
\r
558 pos_rr += calcTabWidth(font, Tabs[i]->getText());
\r
559 if (pos_rr > pos_right)
\r
565 core::rect<s32> CGUITabControl::calcTabPos()
\r
568 r.UpperLeftCorner.X = 0;
\r
569 r.LowerRightCorner.X = AbsoluteRect.getWidth();
\r
572 ++r.UpperLeftCorner.X;
\r
573 --r.LowerRightCorner.X;
\r
576 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
578 r.UpperLeftCorner.Y = TabHeight+2;
\r
579 r.LowerRightCorner.Y = AbsoluteRect.getHeight()-1;
\r
582 --r.LowerRightCorner.Y;
\r
587 r.UpperLeftCorner.Y = 0;
\r
588 r.LowerRightCorner.Y = AbsoluteRect.getHeight()-(TabHeight+2);
\r
591 ++r.UpperLeftCorner.Y;
\r
599 //! draws the element and its children
\r
600 void CGUITabControl::draw()
\r
605 IGUISkin* skin = Environment->getSkin();
\r
609 IGUIFont* font = skin->getFont();
\r
610 video::IVideoDriver* driver = Environment->getVideoDriver();
\r
612 core::rect<s32> frameRect(AbsoluteRect);
\r
614 // some empty background as placeholder when there are no tabs
\r
616 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect);
\r
621 // tab button bar can be above or below the tabs
\r
622 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
624 frameRect.UpperLeftCorner.Y += 2;
\r
625 frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
\r
629 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight - 1;
\r
630 frameRect.LowerRightCorner.Y -= 2;
\r
633 core::rect<s32> tr;
\r
634 s32 pos = frameRect.UpperLeftCorner.X + 2;
\r
636 bool needLeftScroll = CurrentScrollTabIndex > 0;
\r
637 bool needRightScroll = false;
\r
639 // left and right pos of the active tab
\r
643 //const wchar_t* activetext = 0;
\r
644 IGUITab *activeTab = 0;
\r
646 // Draw all tab-buttons except the active one
\r
647 for (u32 i = CurrentScrollTabIndex; i < Tabs.size() && !needRightScroll; ++i)
\r
650 const wchar_t* text = 0;
\r
652 text = Tabs[i]->getText();
\r
655 s32 len = calcTabWidth(font, text);
\r
656 if (ScrollControl) {
\r
657 s32 space = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos;
\r
659 needRightScroll = true;
\r
664 frameRect.LowerRightCorner.X += len;
\r
665 frameRect.UpperLeftCorner.X = pos;
\r
666 frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
\r
670 if ((s32)i == ActiveTabIndex)
\r
672 // for active button just remember values
\r
673 left = frameRect.UpperLeftCorner.X;
\r
674 right = frameRect.LowerRightCorner.X;
\r
675 //activetext = text;
\r
676 activeTab = Tabs[i];
\r
680 skin->draw3DTabButton(this, false, frameRect, &AbsoluteClippingRect, VerticalAlignment);
\r
683 core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
\r
684 textClipRect.clipAgainst(AbsoluteClippingRect);
\r
685 font->draw(text, frameRect, Tabs[i]->getTextColor(),
\r
686 true, true, &textClipRect);
\r
690 // Draw active tab button
\r
691 // Drawn later than other buttons because it draw over the buttons before/after it.
\r
692 if (left != 0 && right != 0 && activeTab != 0)
\r
694 // draw upper highlight frame
\r
695 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
697 frameRect.UpperLeftCorner.X = left-2;
\r
698 frameRect.LowerRightCorner.X = right+2;
\r
699 frameRect.UpperLeftCorner.Y -= 2;
\r
701 skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
\r
704 core::rect<s32> textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface
\r
705 textClipRect.clipAgainst(AbsoluteClippingRect);
\r
706 font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
\r
707 true, true, &textClipRect);
\r
709 tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
\r
710 tr.LowerRightCorner.X = left - 1;
\r
711 tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
\r
712 tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
\r
713 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
\r
715 tr.UpperLeftCorner.X = right;
\r
716 tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
\r
717 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
\r
721 frameRect.UpperLeftCorner.X = left-2;
\r
722 frameRect.LowerRightCorner.X = right+2;
\r
723 frameRect.LowerRightCorner.Y += 2;
\r
725 skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment);
\r
728 font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(),
\r
729 true, true, &frameRect);
\r
731 tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
\r
732 tr.LowerRightCorner.X = left - 1;
\r
733 tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
\r
734 tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
\r
735 driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
\r
737 tr.UpperLeftCorner.X = right;
\r
738 tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
\r
739 driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
\r
745 // Draw a line separating button bar from tab area
\r
746 tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X;
\r
747 tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X;
\r
748 tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1;
\r
749 tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y;
\r
751 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
753 driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect);
\r
757 tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1;
\r
758 tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y;
\r
759 driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect);
\r
763 // drawing some border and background for the tab-area.
\r
764 skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment);
\r
766 // enable scrollcontrols on need
\r
768 UpButton->setEnabled(needLeftScroll);
\r
770 DownButton->setEnabled(needRightScroll);
\r
773 IGUIElement::draw();
\r
777 //! Set the height of the tabs
\r
778 void CGUITabControl::setTabHeight( s32 height )
\r
783 TabHeight = height;
\r
785 recalculateScrollButtonPlacement();
\r
786 recalculateScrollBar();
\r
790 //! Get the height of the tabs
\r
791 s32 CGUITabControl::getTabHeight() const
\r
796 //! set the maximal width of a tab. Per default width is 0 which means "no width restriction".
\r
797 void CGUITabControl::setTabMaxWidth(s32 width )
\r
799 TabMaxWidth = width;
\r
802 //! get the maximal width of a tab
\r
803 s32 CGUITabControl::getTabMaxWidth() const
\r
805 return TabMaxWidth;
\r
809 //! Set the extra width added to tabs on each side of the text
\r
810 void CGUITabControl::setTabExtraWidth( s32 extraWidth )
\r
812 if ( extraWidth < 0 )
\r
815 TabExtraWidth = extraWidth;
\r
817 recalculateScrollBar();
\r
821 //! Get the extra width added to tabs on each side of the text
\r
822 s32 CGUITabControl::getTabExtraWidth() const
\r
824 return TabExtraWidth;
\r
828 void CGUITabControl::recalculateScrollBar()
\r
830 // Down: to right, Up: to left
\r
831 if (!UpButton || !DownButton)
\r
834 ScrollControl = needScrollControl() || CurrentScrollTabIndex > 0;
\r
838 UpButton->setVisible( true );
\r
839 DownButton->setVisible( true );
\r
843 UpButton->setVisible( false );
\r
844 DownButton->setVisible( false );
\r
847 bringToFront( UpButton );
\r
848 bringToFront( DownButton );
\r
851 //! Set the alignment of the tabs
\r
852 void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment )
\r
854 VerticalAlignment = alignment;
\r
856 recalculateScrollButtonPlacement();
\r
857 recalculateScrollBar();
\r
859 core::rect<s32> r(calcTabPos());
\r
860 for ( u32 i=0; i<Tabs.size(); ++i )
\r
862 Tabs[i]->setRelativePosition(r);
\r
866 void CGUITabControl::recalculateScrollButtonPlacement()
\r
868 IGUISkin* skin = Environment->getSkin();
\r
869 s32 ButtonSize = 16;
\r
870 s32 ButtonHeight = TabHeight - 2;
\r
871 if ( ButtonHeight < 0 )
\r
872 ButtonHeight = TabHeight;
\r
875 ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
\r
876 if (ButtonSize > TabHeight)
\r
877 ButtonSize = TabHeight;
\r
880 s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f*(f32)ButtonSize) - 1;
\r
883 if (VerticalAlignment == EGUIA_UPPERLEFT)
\r
885 ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2);
\r
886 UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
887 DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
\r
891 ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2;
\r
892 UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
\r
893 DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
\r
896 UpButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
\r
897 ButtonX += ButtonSize + 1;
\r
898 DownButton->setRelativePosition(core::rect<s32>(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight));
\r
901 //! Get the alignment of the tabs
\r
902 EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const
\r
904 return VerticalAlignment;
\r
908 s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const
\r
910 core::position2di p(xpos, ypos);
\r
911 IGUISkin* skin = Environment->getSkin();
\r
912 IGUIFont* font = skin->getFont();
\r
914 core::rect<s32> frameRect(AbsoluteRect);
\r
916 if ( VerticalAlignment == EGUIA_UPPERLEFT )
\r
918 frameRect.UpperLeftCorner.Y += 2;
\r
919 frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight;
\r
923 frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight;
\r
926 s32 pos = frameRect.UpperLeftCorner.X + 2;
\r
928 if (!frameRect.isPointInside(p))
\r
931 bool abort = false;
\r
932 for (s32 i = CurrentScrollTabIndex; i < (s32)Tabs.size() && !abort; ++i)
\r
935 const wchar_t* text = 0;
\r
937 text = Tabs[i]->getText();
\r
940 s32 len = calcTabWidth(font, text);
\r
941 if (ScrollControl) {
\r
942 // TODO: merge this with draw() ?
\r
943 s32 space = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos;
\r
950 frameRect.UpperLeftCorner.X = pos;
\r
951 frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len;
\r
955 if (frameRect.isPointInside(p))
\r
964 //! Returns which tab is currently active
\r
965 s32 CGUITabControl::getActiveTab() const
\r
967 return ActiveTabIndex;
\r
971 //! Brings a tab to front.
\r
972 bool CGUITabControl::setActiveTab(s32 idx)
\r
974 if ((u32)idx >= Tabs.size())
\r
977 bool changed = (ActiveTabIndex != idx);
\r
979 ActiveTabIndex = idx;
\r
981 setVisibleTab(ActiveTabIndex);
\r
983 if (changed && Parent)
\r
986 event.EventType = EET_GUI_EVENT;
\r
987 event.GUIEvent.Caller = this;
\r
988 event.GUIEvent.Element = 0;
\r
989 event.GUIEvent.EventType = EGET_TAB_CHANGED;
\r
990 Parent->OnEvent(event);
\r
993 if (ScrollControl) {
\r
994 CurrentScrollTabIndex = calculateScrollIndexFromActive();
\r
995 recalculateScrollBar();
\r
1001 void CGUITabControl::setVisibleTab(s32 idx)
\r
1003 for (u32 i=0; i<Tabs.size(); ++i)
\r
1005 Tabs[i]->setVisible( (s32)i == idx );
\r
1009 bool CGUITabControl::setActiveTab(IGUITab *tab)
\r
1011 return setActiveTab(getTabIndex(tab));
\r
1014 s32 CGUITabControl::getTabIndex(const IGUIElement *tab) const
\r
1016 for (u32 i=0; i<Tabs.size(); ++i)
\r
1017 if (Tabs[i] == tab)
\r
1023 //! Update the position of the element, decides scroll button status
\r
1024 void CGUITabControl::updateAbsolutePosition()
\r
1026 IGUIElement::updateAbsolutePosition();
\r
1027 recalculateScrollBar();
\r
1031 } // end namespace irr
\r
1032 } // end namespace gui
\r
1034 #endif // _IRR_COMPILE_WITH_GUI_
\r