BsGUIDropDownMenu.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisites.h"
  5. #include "GUI/BsCGUIWidget.h"
  6. #include "Math/BsRect2I.h"
  7. #include "GUI/BsDropDownAreaPlacement.h"
  8. namespace bs
  9. {
  10. /** @addtogroup GUI-Internal
  11. * @{
  12. */
  13. /** Contains items used for initializing one level in a drop down box hierarchy. */
  14. struct BS_EXPORT GUIDropDownData
  15. {
  16. Vector<GUIDropDownDataEntry> entries;
  17. Vector<bool> states;
  18. UnorderedMap<WString, HString> localizedNames;
  19. };
  20. /** A set of parameters used for initializing a drop down box. */
  21. struct DROP_DOWN_BOX_DESC
  22. {
  23. SPtr<Camera> camera; /**< Camera on which to open the drop down box. */
  24. DropDownAreaPlacement placement; /**< Determines how is the drop down box positioned in the visible area. */
  25. GUIDropDownData dropDownData; /**< Data to use for initializing menu items of the drop down box. */
  26. HGUISkin skin; /**< Skin to use for drop down box GUI elements. */
  27. /** Additional bounds that control what is considered the inside or the outside of the drop down box. */
  28. Vector<Rect2I> additionalBounds;
  29. };
  30. /** Represents a single entry in a drop down box. */
  31. class BS_EXPORT GUIDropDownDataEntry
  32. {
  33. enum class Type
  34. {
  35. Separator,
  36. Entry,
  37. SubMenu
  38. };
  39. public:
  40. /** Creates a new separator entry. */
  41. static GUIDropDownDataEntry separator();
  42. /** Creates a new button entry with the specified callback that is triggered when button is selected. */
  43. static GUIDropDownDataEntry button(const WString& label, std::function<void()> callback,
  44. const WString& shortcutTag = StringUtil::WBLANK);
  45. /** Creates a new sub-menu entry that will open the provided drop down data sub-menu when activated. */
  46. static GUIDropDownDataEntry subMenu(const WString& label, const GUIDropDownData& data);
  47. /** Check is the entry a separator. */
  48. bool isSeparator() const { return mType == Type::Separator; }
  49. /** Check is the entry a sub menu. */
  50. bool isSubMenu() const { return mType == Type::SubMenu; }
  51. /** Returns display label of the entry (if an entry is a button or a sub-menu). */
  52. const WString& getLabel() const { return mLabel; }
  53. /** Returns the shortcut key combination string that is to be displayed along the entry label. */
  54. const WString& getShortcutTag() const { return mShortcutTag; }
  55. /** Returns a button callback if the entry (if an entry is a button). */
  56. std::function<void()> getCallback() const { return mCallback; }
  57. /** Returns sub-menu data that is used for creating a sub-menu (if an entry is a sub-menu). */
  58. const GUIDropDownData& getSubMenuData() const { return mChildData; }
  59. private:
  60. GUIDropDownDataEntry() { }
  61. std::function<void()> mCallback;
  62. GUIDropDownData mChildData;
  63. WString mLabel;
  64. WString mShortcutTag;
  65. Type mType;
  66. };
  67. /** Type of drop down box types. */
  68. enum class GUIDropDownType
  69. {
  70. ListBox,
  71. MultiListBox,
  72. ContextMenu,
  73. MenuBar
  74. };
  75. /** This is a generic GUI drop down box class that can be used for: list boxes, menu bars or context menus. */
  76. class BS_EXPORT GUIDropDownMenu : public CGUIWidget
  77. {
  78. public:
  79. /**
  80. * Creates a new drop down box widget.
  81. *
  82. * @param[in] parent Parent scene object to attach the drop down box to.
  83. * @param[in] desc Various parameters that control the drop down menu features and content.
  84. * @param[in] type Specific type of drop down box to display.
  85. */
  86. GUIDropDownMenu(const HSceneObject& parent, const DROP_DOWN_BOX_DESC& desc, GUIDropDownType type);
  87. ~GUIDropDownMenu();
  88. private:
  89. /** Contains data about a single drop down box sub-menu. */
  90. struct DropDownSubMenu
  91. {
  92. /** Represents a single sub-menu page. */
  93. struct PageInfo
  94. {
  95. UINT32 idx;
  96. UINT32 start;
  97. UINT32 end;
  98. UINT32 height;
  99. };
  100. public:
  101. /**
  102. * Creates a new drop down box sub-menu.
  103. *
  104. * @param[in] owner Owner drop down box this sub menu belongs to.
  105. * @param[in] parent Parent sub-menu. Can be null.
  106. * @param[in] placement Determines how is the sub-menu positioned in the visible area.
  107. * @param[in] availableBounds Available bounds (in pixels) in which the sub-menu may be opened.
  108. * @param[in] dropDownData Data to use for initializing menu items of the sub-menu.
  109. * @param[in] skin Skin to use for sub-menu GUI elements.
  110. * @param[in] depthOffset How much to offset the sub-menu depth. We want deeper levels of the sub-menu
  111. * hierarchy to be in front of lower levels, so you should increase this value for
  112. * each level of the sub-menu hierarchy.
  113. */
  114. DropDownSubMenu(GUIDropDownMenu* owner, DropDownSubMenu* parent, const DropDownAreaPlacement& placement,
  115. const Rect2I& availableBounds, const GUIDropDownData& dropDownData, GUIDropDownType type, UINT32 depthOffset);
  116. ~DropDownSubMenu();
  117. /** Recreates all internal GUI elements for the entries of the current sub-menu page. */
  118. void updateGUIElements();
  119. /** Moves the sub-menu to the previous page and displays its elements, if available. */
  120. void scrollDown();
  121. /** Moves the sub-menu to the next page and displays its elements, if available. */
  122. void scrollUp();
  123. /** Moves the sub-menu to the first page and displays its elements. */
  124. void scrollToTop();
  125. /** Moves the sub-menu to the last page and displays its elements. */
  126. void scrollToBottom();
  127. /** Calculates ranges for all the pages of the sub-menu. */
  128. Vector<PageInfo> getPageInfos() const;
  129. /**
  130. * Called when the user activates an element with the specified index.
  131. *
  132. * @param[in] bounds Bounds of the GUI element that is used as a visual representation of this drop down
  133. * element.
  134. */
  135. void elementActivated(UINT32 idx, const Rect2I& bounds);
  136. /**
  137. * Called when the user selects an element with the specified index.
  138. *
  139. * @param[in] idx Index of the element that was selected.
  140. */
  141. void elementSelected(UINT32 idx);
  142. /** Called when the user wants to close the currently open sub-menu. */
  143. void closeSubMenu();
  144. /** Closes this sub-menu. */
  145. void close();
  146. /** Returns the type of the displayed drop down menu. */
  147. GUIDropDownType getType() const { return mType; }
  148. /** Returns actual visible bounds of the sub-menu. */
  149. Rect2I getVisibleBounds() const { return mVisibleBounds; }
  150. /** Returns the drop box object that owns this sub-menu. */
  151. GUIDropDownMenu* getOwner() const { return mOwner; }
  152. public:
  153. GUIDropDownMenu* mOwner;
  154. GUIDropDownType mType;
  155. GUIDropDownData mData;
  156. UINT32 mPage;
  157. INT32 x, y;
  158. UINT32 width, height;
  159. Rect2I mVisibleBounds;
  160. Rect2I mAvailableBounds;
  161. UINT32 mDepthOffset;
  162. bool mOpenedUpward;
  163. GUIDropDownContent* mContent;
  164. GUITexture* mBackgroundFrame;
  165. GUIButton* mScrollUpBtn;
  166. GUIButton* mScrollDownBtn;
  167. GUITexture* mHandle;
  168. GUIPanel* mBackgroundPanel;
  169. GUIPanel* mContentPanel;
  170. GUILayout* mContentLayout;
  171. GUIPanel* mSidebarPanel;
  172. DropDownSubMenu* mParent;
  173. DropDownSubMenu* mSubMenu;
  174. };
  175. private:
  176. friend class GUIDropDownContent;
  177. /** Called when the specified sub-menu is opened. */
  178. void notifySubMenuOpened(DropDownSubMenu* subMenu);
  179. /** Called when the specified sub-menu is opened. */
  180. void notifySubMenuClosed(DropDownSubMenu* subMenu);
  181. /** Called when the drop down box loses focus (and should be closed). */
  182. void dropDownFocusLost();
  183. /** @copydoc GUIWidget::onDestroyed */
  184. void onDestroyed() override;
  185. private:
  186. static const UINT32 DROP_DOWN_BOX_WIDTH;
  187. String mScrollUpStyle;
  188. String mScrollDownStyle;
  189. String mBackgroundStyle;
  190. String mContentStyle;
  191. String mSideBackgroundStyle;
  192. String mHandleStyle;
  193. DropDownSubMenu* mRootMenu;
  194. GUIDropDownHitBox* mFrontHitBox;
  195. GUIDropDownHitBox* mBackHitBox;
  196. // Captures mouse clicks so that we don't trigger elements outside the drop down box when we just want to close it.
  197. // (Particular example is clicking on the button that opened the drop down box in the first place. Clicking will cause
  198. // the drop down to lose focus and close, but if the button still processes the mouse click it will be immediately opened again)
  199. GUIDropDownHitBox* mCaptureHitBox;
  200. Vector<Rect2I> mAdditionalCaptureBounds;
  201. };
  202. /** @} */
  203. }