CGUIMenu.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. #include "CGUIMenu.h"
  5. #ifdef _IRR_COMPILE_WITH_GUI_
  6. #include "IGUISkin.h"
  7. #include "IGUIEnvironment.h"
  8. #include "IVideoDriver.h"
  9. #include "IGUIFont.h"
  10. #include "IGUIWindow.h"
  11. #include "os.h"
  12. namespace irr
  13. {
  14. namespace gui
  15. {
  16. //! constructor
  17. CGUIMenu::CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent,
  18. s32 id, core::rect<s32> rectangle)
  19. : CGUIContextMenu(environment, parent, id, rectangle, false, true)
  20. {
  21. #ifdef _DEBUG
  22. setDebugName("CGUIMenu");
  23. #endif
  24. Type = EGUIET_MENU;
  25. setNotClipped(false);
  26. recalculateSize();
  27. }
  28. //! draws the element and its children
  29. void CGUIMenu::draw()
  30. {
  31. if (!IsVisible)
  32. return;
  33. IGUISkin* skin = Environment->getSkin();
  34. IGUIFont* font = skin->getFont(EGDF_MENU);
  35. if (font != LastFont)
  36. {
  37. if (LastFont)
  38. LastFont->drop();
  39. LastFont = font;
  40. if (LastFont)
  41. LastFont->grab();
  42. recalculateSize();
  43. }
  44. core::rect<s32> rect = AbsoluteRect;
  45. // draw frame
  46. skin->draw3DToolBar(this, rect, &AbsoluteClippingRect);
  47. // loop through all menu items
  48. rect = AbsoluteRect;
  49. for (s32 i=0; i<(s32)Items.size(); ++i)
  50. {
  51. if (!Items[i].IsSeparator)
  52. {
  53. rect = getRect(Items[i], AbsoluteRect);
  54. // draw highlighted
  55. if (i == HighLighted && Items[i].Enabled)
  56. {
  57. skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_DARK_SHADOW),
  58. true, true, rect, &AbsoluteClippingRect);
  59. }
  60. // draw text
  61. EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT;
  62. if (i == HighLighted)
  63. c = EGDC_HIGH_LIGHT_TEXT;
  64. if (!Items[i].Enabled)
  65. c = EGDC_GRAY_TEXT;
  66. if (font)
  67. font->draw(Items[i].Text.c_str(), rect,
  68. skin->getColor(c), true, true, &AbsoluteClippingRect);
  69. }
  70. }
  71. IGUIElement::draw();
  72. }
  73. //! called if an event happened.
  74. bool CGUIMenu::OnEvent(const SEvent& event)
  75. {
  76. if (isEnabled())
  77. {
  78. switch(event.EventType)
  79. {
  80. case EET_GUI_EVENT:
  81. switch(event.GUIEvent.EventType)
  82. {
  83. case gui::EGET_ELEMENT_FOCUS_LOST:
  84. if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element))
  85. {
  86. closeAllSubMenus();
  87. HighLighted = -1;
  88. }
  89. break;
  90. case gui::EGET_ELEMENT_FOCUSED:
  91. if (event.GUIEvent.Caller == this && Parent)
  92. {
  93. Parent->bringToFront(this);
  94. }
  95. break;
  96. default:
  97. break;
  98. }
  99. break;
  100. case EET_MOUSE_INPUT_EVENT:
  101. switch(event.MouseInput.Event)
  102. {
  103. case EMIE_LMOUSE_PRESSED_DOWN:
  104. {
  105. if (!Environment->hasFocus(this))
  106. {
  107. Environment->setFocus(this);
  108. }
  109. if (Parent)
  110. Parent->bringToFront(this);
  111. core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
  112. bool shouldCloseSubMenu = hasOpenSubMenu();
  113. if (!AbsoluteClippingRect.isPointInside(p))
  114. {
  115. shouldCloseSubMenu = false;
  116. }
  117. highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
  118. if ( shouldCloseSubMenu )
  119. {
  120. Environment->removeFocus(this);
  121. }
  122. return true;
  123. }
  124. case EMIE_LMOUSE_LEFT_UP:
  125. {
  126. core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
  127. if (!AbsoluteClippingRect.isPointInside(p))
  128. {
  129. s32 t = sendClick(p);
  130. if ((t==0 || t==1) && Environment->hasFocus(this))
  131. Environment->removeFocus(this);
  132. }
  133. return true;
  134. }
  135. case EMIE_MOUSE_MOVED:
  136. if (Environment->hasFocus(this) && HighLighted >= 0)
  137. {
  138. s32 oldHighLighted = HighLighted;
  139. highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
  140. if ( HighLighted < 0 )
  141. HighLighted = oldHighLighted; // keep last hightlight active when moving outside the area
  142. }
  143. return true;
  144. default:
  145. break;
  146. }
  147. break;
  148. default:
  149. break;
  150. }
  151. }
  152. return IGUIElement::OnEvent(event);
  153. }
  154. void CGUIMenu::recalculateSize()
  155. {
  156. core::rect<s32> clientRect; // client rect of parent
  157. if ( Parent && Parent->hasType(EGUIET_WINDOW) )
  158. {
  159. clientRect = static_cast<IGUIWindow*>(Parent)->getClientRect();
  160. }
  161. else if ( Parent )
  162. {
  163. clientRect = core::rect<s32>(0,0, Parent->getAbsolutePosition().getWidth(),
  164. Parent->getAbsolutePosition().getHeight());
  165. }
  166. else
  167. {
  168. clientRect = RelativeRect;
  169. }
  170. IGUISkin* skin = Environment->getSkin();
  171. IGUIFont* font = skin->getFont(EGDF_MENU);
  172. if (!font)
  173. {
  174. if (Parent && skin)
  175. RelativeRect = core::rect<s32>(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y,
  176. clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT));
  177. return;
  178. }
  179. core::rect<s32> rect;
  180. rect.UpperLeftCorner = clientRect.UpperLeftCorner;
  181. s32 height = font->getDimension(L"A").Height + 5;
  182. //if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT ))
  183. // height = skin->getSize(EGDS_MENU_HEIGHT);
  184. s32 width = rect.UpperLeftCorner.X;
  185. s32 i;
  186. for (i=0; i<(s32)Items.size(); ++i)
  187. {
  188. if (Items[i].IsSeparator)
  189. {
  190. Items[i].Dim.Width = 0;
  191. Items[i].Dim.Height = height;
  192. }
  193. else
  194. {
  195. Items[i].Dim = font->getDimension(Items[i].Text.c_str());
  196. Items[i].Dim.Width += 20;
  197. }
  198. Items[i].PosY = width;
  199. width += Items[i].Dim.Width;
  200. }
  201. width = clientRect.getWidth();
  202. rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width;
  203. rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height;
  204. setRelativePosition(rect);
  205. // recalculate submenus
  206. for (i=0; i<(s32)Items.size(); ++i)
  207. if (Items[i].SubMenu)
  208. {
  209. // move submenu
  210. s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth();
  211. s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight();
  212. Items[i].SubMenu->setRelativePosition(
  213. core::rect<s32>(Items[i].PosY, height ,
  214. Items[i].PosY+w-5, height+h));
  215. }
  216. }
  217. //! returns the item highlight-area
  218. core::rect<s32> CGUIMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const
  219. {
  220. core::rect<s32> r = absolute;
  221. r.UpperLeftCorner.X += i.PosY;
  222. r.LowerRightCorner.X = r.UpperLeftCorner.X + i.Dim.Width;
  223. return r;
  224. }
  225. //! Gets drawing rect of Item
  226. core::rect<s32> CGUIMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const
  227. {
  228. return getHRect(i, absolute);
  229. }
  230. void CGUIMenu::updateAbsolutePosition()
  231. {
  232. if (Parent)
  233. DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth();
  234. IGUIElement::updateAbsolutePosition();
  235. }
  236. } // end namespace
  237. } // end namespace
  238. #endif // _IRR_COMPILE_WITH_GUI_