git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6000 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			290 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2002-2012 Nikolaus Gebhardt
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in irrlicht.h
 | |
| 
 | |
| #include "CGUIMenu.h"
 | |
| #ifdef _IRR_COMPILE_WITH_GUI_
 | |
| 
 | |
| #include "IGUISkin.h"
 | |
| #include "IGUIEnvironment.h"
 | |
| #include "IVideoDriver.h"
 | |
| #include "IGUIFont.h"
 | |
| #include "IGUIWindow.h"
 | |
| 
 | |
| #include "os.h"
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace gui
 | |
| {
 | |
| 
 | |
| //! constructor
 | |
| CGUIMenu::CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent,
 | |
| 		s32 id, core::rect<s32> rectangle)
 | |
| 	: CGUIContextMenu(environment, parent, id, rectangle, false, true)
 | |
| {
 | |
| 	#ifdef _DEBUG
 | |
| 	setDebugName("CGUIMenu");
 | |
| 	#endif
 | |
| 
 | |
| 	Type = EGUIET_MENU;
 | |
| 
 | |
| 	setNotClipped(false);
 | |
| 
 | |
| 	recalculateSize();
 | |
| }
 | |
| 
 | |
| 
 | |
| //! draws the element and its children
 | |
| void CGUIMenu::draw()
 | |
| {
 | |
| 	if (!IsVisible)
 | |
| 		return;
 | |
| 
 | |
| 	IGUISkin* skin = Environment->getSkin();
 | |
| 	IGUIFont* font = skin->getFont(EGDF_MENU);
 | |
| 
 | |
| 	if (font != LastFont)
 | |
| 	{
 | |
| 		if (LastFont)
 | |
| 			LastFont->drop();
 | |
| 		LastFont = font;
 | |
| 		if (LastFont)
 | |
| 			LastFont->grab();
 | |
| 
 | |
| 		recalculateSize();
 | |
| 	}
 | |
| 
 | |
| 	core::rect<s32> rect = AbsoluteRect;
 | |
| 
 | |
| 	// draw frame
 | |
| 
 | |
| 	skin->draw3DToolBar(this, rect, &AbsoluteClippingRect);
 | |
| 
 | |
| 	// loop through all menu items
 | |
| 
 | |
| 	rect = AbsoluteRect;
 | |
| 
 | |
| 	for (s32 i=0; i<(s32)Items.size(); ++i)
 | |
| 	{
 | |
| 		if (!Items[i].IsSeparator)
 | |
| 		{
 | |
| 			rect = getRect(Items[i], AbsoluteRect);
 | |
| 
 | |
| 			// draw highlighted
 | |
| 			if (i == HighLighted && Items[i].Enabled)
 | |
| 			{
 | |
| 				skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_DARK_SHADOW),
 | |
| 					true, true, rect, &AbsoluteClippingRect);
 | |
| 			}
 | |
| 			// draw text
 | |
| 
 | |
| 			EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT;
 | |
| 
 | |
| 			if (i == HighLighted)
 | |
| 				c = EGDC_HIGH_LIGHT_TEXT;
 | |
| 
 | |
| 			if (!Items[i].Enabled)
 | |
| 				c = EGDC_GRAY_TEXT;
 | |
| 
 | |
| 			if (font)
 | |
| 				font->draw(Items[i].Text.c_str(), rect,
 | |
| 					skin->getColor(c), true, true, &AbsoluteClippingRect);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	IGUIElement::draw();
 | |
| }
 | |
| 
 | |
| 
 | |
| //! called if an event happened.
 | |
| bool CGUIMenu::OnEvent(const SEvent& event)
 | |
| {
 | |
| 	if (isEnabled())
 | |
| 	{
 | |
| 
 | |
| 		switch(event.EventType)
 | |
| 		{
 | |
| 		case EET_GUI_EVENT:
 | |
| 			switch(event.GUIEvent.EventType)
 | |
| 			{
 | |
| 			case gui::EGET_ELEMENT_FOCUS_LOST:
 | |
| 				if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element))
 | |
| 				{
 | |
| 					closeAllSubMenus();
 | |
| 					HighLighted = -1;
 | |
| 				}
 | |
| 				break;
 | |
| 			case gui::EGET_ELEMENT_FOCUSED:
 | |
| 				if (event.GUIEvent.Caller == this && Parent)
 | |
| 				{
 | |
| 					Parent->bringToFront(this);
 | |
| 				}
 | |
| 				break;
 | |
| 			default:
 | |
| 				break;
 | |
| 			}
 | |
| 			break;
 | |
| 		case EET_MOUSE_INPUT_EVENT:
 | |
| 			switch(event.MouseInput.Event)
 | |
| 			{
 | |
| 			case EMIE_LMOUSE_PRESSED_DOWN:
 | |
| 			{
 | |
| 				if (Parent)
 | |
| 					Parent->bringToFront(this);
 | |
| 
 | |
| 				core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
 | |
| 				bool shouldCloseSubMenu = hasOpenSubMenu();
 | |
| 				if (!AbsoluteClippingRect.isPointInside(p))
 | |
| 				{
 | |
| 					shouldCloseSubMenu = false;
 | |
| 				}
 | |
| 				highlight(core::position2d<s32>(event.MouseInput.X,	event.MouseInput.Y), true);
 | |
| 				if ( shouldCloseSubMenu )
 | |
| 				{
 | |
|                     Environment->removeFocus(this);
 | |
| 				}
 | |
| 
 | |
| 				return true;
 | |
| 			}
 | |
| 			case EMIE_LMOUSE_LEFT_UP:
 | |
| 			{
 | |
|                 core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
 | |
| 				if (!AbsoluteClippingRect.isPointInside(p))
 | |
| 				{
 | |
| 					s32 t = sendClick(p);
 | |
| 					if ((t==0 || t==1) && Environment->hasFocus(this))
 | |
| 						Environment->removeFocus(this);
 | |
| 				}
 | |
| 
 | |
| 			    return true;
 | |
| 			}
 | |
| 			case EMIE_MOUSE_MOVED:
 | |
| 				if (Environment->hasFocus(this) && HighLighted >= 0)
 | |
| 				{
 | |
| 				    s32 oldHighLighted = HighLighted;
 | |
| 					highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
 | |
| 					if ( HighLighted < 0 )
 | |
|                         HighLighted = oldHighLighted;   // keep last hightlight active when moving outside the area
 | |
| 				}
 | |
| 				return true;
 | |
| 			default:
 | |
| 				break;
 | |
| 			}
 | |
| 			break;
 | |
| 		default:
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return IGUIElement::OnEvent(event);
 | |
| }
 | |
| 
 | |
| void CGUIMenu::recalculateSize()
 | |
| {
 | |
| 	core::rect<s32> clientRect; // client rect of parent
 | |
| 	if ( Parent && Parent->hasType(EGUIET_WINDOW) )
 | |
| 	{
 | |
| 		clientRect = static_cast<IGUIWindow*>(Parent)->getClientRect();
 | |
| 	}
 | |
| 	else if ( Parent )
 | |
| 	{
 | |
| 		clientRect = core::rect<s32>(0,0, Parent->getAbsolutePosition().getWidth(),
 | |
| 					Parent->getAbsolutePosition().getHeight());
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		clientRect = RelativeRect;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	IGUISkin* skin = Environment->getSkin();
 | |
| 	IGUIFont* font = skin->getFont(EGDF_MENU);
 | |
| 
 | |
| 	if (!font)
 | |
| 	{
 | |
| 		if (Parent && skin)
 | |
| 			RelativeRect = core::rect<s32>(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y,
 | |
| 					clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT));
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	core::rect<s32> rect;
 | |
| 	rect.UpperLeftCorner = clientRect.UpperLeftCorner;
 | |
| 	s32 height = font->getDimension(L"A").Height + 5;
 | |
| 	//if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT ))
 | |
| 	//	height = skin->getSize(EGDS_MENU_HEIGHT);
 | |
| 	s32 width = rect.UpperLeftCorner.X;
 | |
| 	s32 i;
 | |
| 
 | |
| 	for (i=0; i<(s32)Items.size(); ++i)
 | |
| 	{
 | |
| 		if (Items[i].IsSeparator)
 | |
| 		{
 | |
| 			Items[i].Dim.Width = 0;
 | |
| 			Items[i].Dim.Height = height;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			Items[i].Dim = font->getDimension(Items[i].Text.c_str());
 | |
| 			Items[i].Dim.Width += 20;
 | |
| 		}
 | |
| 
 | |
| 		Items[i].PosY = width;
 | |
| 		width += Items[i].Dim.Width;
 | |
| 	}
 | |
| 
 | |
| 	width = clientRect.getWidth();
 | |
| 
 | |
| 	rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width;
 | |
| 	rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height;
 | |
| 
 | |
| 	setRelativePosition(rect);
 | |
| 
 | |
| 	// recalculate submenus
 | |
| 	for (i=0; i<(s32)Items.size(); ++i)
 | |
| 		if (Items[i].SubMenu)
 | |
| 		{
 | |
| 			// move submenu
 | |
| 			s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth();
 | |
| 			s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight();
 | |
| 
 | |
| 			Items[i].SubMenu->setRelativePosition(
 | |
| 				core::rect<s32>(Items[i].PosY, height ,
 | |
| 					Items[i].PosY+w-5, height+h));
 | |
| 		}
 | |
| }
 | |
| 
 | |
| 
 | |
| //! returns the item highlight-area
 | |
| core::rect<s32> CGUIMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const
 | |
| {
 | |
| 	core::rect<s32> r = absolute;
 | |
| 	r.UpperLeftCorner.X += i.PosY;
 | |
| 	r.LowerRightCorner.X = r.UpperLeftCorner.X + i.Dim.Width;
 | |
| 	return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Gets drawing rect of Item
 | |
| core::rect<s32> CGUIMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const
 | |
| {
 | |
| 	return getHRect(i, absolute);
 | |
| }
 | |
| 
 | |
| 
 | |
| void CGUIMenu::updateAbsolutePosition()
 | |
| {
 | |
| 	if (Parent)
 | |
| 		DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth();
 | |
| 
 | |
| 	IGUIElement::updateAbsolutePosition();
 | |
| }
 | |
| 
 | |
| 
 | |
| } // end namespace
 | |
| } // end namespace
 | |
| 
 | |
| #endif // _IRR_COMPILE_WITH_GUI_
 | |
| 
 |