BsGUIMenu.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "GUI/BsGUIMenu.h"
  4. #include "GUI/BsGUIDropDownMenu.h"
  5. namespace bs
  6. {
  7. bool GUIMenuItemComparer::operator() (const GUIMenuItem* const& a, const GUIMenuItem* const& b)
  8. {
  9. return a->mPriority > b->mPriority || (a->mPriority == b->mPriority && a->mSeqIdx < b->mSeqIdx);
  10. }
  11. GUIMenuItem::GUIMenuItem(GUIMenuItem* parent, const WString& name, std::function<void()> callback,
  12. INT32 priority, UINT32 seqIdx, const ShortcutKey& key)
  13. :mParent(parent), mIsSeparator(false), mName(name), mCallback(callback), mPriority(priority),
  14. mShortcut(key), mSeqIdx(seqIdx)
  15. {
  16. }
  17. GUIMenuItem::GUIMenuItem(GUIMenuItem* parent, INT32 priority, UINT32 seqIdx)
  18. : mParent(parent), mIsSeparator(true), mCallback(nullptr), mPriority(priority), mSeqIdx(seqIdx)
  19. {
  20. }
  21. GUIMenuItem::~GUIMenuItem()
  22. {
  23. for(auto& child : mChildren)
  24. bs_delete(child);
  25. }
  26. const GUIMenuItem* GUIMenuItem::findChild(const WString& name) const
  27. {
  28. auto iterFind = std::find_if(begin(mChildren), end(mChildren), [&] (GUIMenuItem* x) { return x->getName() == name; });
  29. if(iterFind != mChildren.end())
  30. return *iterFind;
  31. return nullptr;
  32. }
  33. GUIMenuItem* GUIMenuItem::findChild(const WString& name)
  34. {
  35. auto iterFind = std::find_if(begin(mChildren), end(mChildren), [&] (GUIMenuItem* x) { return x->getName() == name; });
  36. if(iterFind != mChildren.end())
  37. return *iterFind;
  38. return nullptr;
  39. }
  40. void GUIMenuItem::removeChild(const WString& name)
  41. {
  42. auto iterFind = std::find_if(begin(mChildren), end(mChildren), [&] (GUIMenuItem* x) { return x->getName() == name; });
  43. if(iterFind != mChildren.end())
  44. {
  45. bs_delete(*iterFind);
  46. mChildren.erase(iterFind);
  47. }
  48. }
  49. void GUIMenuItem::removeChild(const GUIMenuItem* item)
  50. {
  51. auto iterFind = std::find(begin(mChildren), end(mChildren), item);
  52. if (iterFind != mChildren.end())
  53. {
  54. bs_delete(*iterFind);
  55. mChildren.erase(iterFind);
  56. }
  57. }
  58. GUIMenu::GUIMenu()
  59. :mRootElement(nullptr, L"", nullptr, 0, 0, ShortcutKey::NONE), mNextIdx(0)
  60. {
  61. }
  62. GUIMenu::~GUIMenu()
  63. {
  64. }
  65. GUIMenuItem* GUIMenu::addMenuItem(const WString& path, std::function<void()> callback, INT32 priority, const ShortcutKey& key)
  66. {
  67. return addMenuItemInternal(path, callback, false, priority, key);
  68. }
  69. GUIMenuItem* GUIMenu::addSeparator(const WString& path, INT32 priority)
  70. {
  71. return addMenuItemInternal(path, nullptr, true, priority, ShortcutKey::NONE);
  72. }
  73. GUIMenuItem* GUIMenu::addMenuItemInternal(const WString& path, std::function<void()> callback, bool isSeparator,
  74. INT32 priority, const ShortcutKey& key)
  75. {
  76. Vector<WString> pathElements = StringUtil::split(path, L"/");
  77. GUIMenuItem* curSubMenu = &mRootElement;
  78. for(UINT32 i = 0; i < (UINT32)pathElements.size(); i++)
  79. {
  80. if(pathElements[i] == L"")
  81. continue;
  82. const WString& pathElem = *(pathElements.begin() + i);
  83. GUIMenuItem* existingItem = curSubMenu->findChild(pathElem);
  84. if(existingItem == nullptr)
  85. {
  86. bool isLastElem = i == (UINT32)(pathElements.size() - 1);
  87. if(isLastElem)
  88. existingItem = bs_new<GUIMenuItem>(curSubMenu, pathElem, callback, priority, mNextIdx++, key);
  89. else
  90. {
  91. existingItem = bs_alloc<GUIMenuItem>();
  92. existingItem = new (existingItem) GUIMenuItem(curSubMenu, pathElem, nullptr, priority, mNextIdx++, ShortcutKey::NONE);
  93. }
  94. curSubMenu->addChild(existingItem);
  95. }
  96. curSubMenu = existingItem;
  97. }
  98. if(isSeparator)
  99. {
  100. GUIMenuItem* separatorItem = bs_new<GUIMenuItem>(curSubMenu, priority, mNextIdx++);
  101. curSubMenu->addChild(separatorItem);
  102. return separatorItem;
  103. }
  104. return curSubMenu;
  105. }
  106. GUIMenuItem* GUIMenu::getMenuItem(const WString& path)
  107. {
  108. Vector<WString> pathElements = StringUtil::split(path, L"/");
  109. GUIMenuItem* curSubMenu = &mRootElement;
  110. for(UINT32 i = 0; i < (UINT32)pathElements.size(); i++)
  111. {
  112. const WString& pathElem = *(pathElements.begin() + i);
  113. GUIMenuItem* existingItem = curSubMenu->findChild(pathElem);
  114. if(existingItem == nullptr || existingItem->isSeparator())
  115. return nullptr;
  116. curSubMenu = existingItem;
  117. }
  118. return curSubMenu;
  119. }
  120. void GUIMenu::removeMenuItem(const GUIMenuItem* item)
  121. {
  122. GUIMenuItem* parent = item->mParent;
  123. assert(parent != nullptr);
  124. parent->removeChild(item->getName());
  125. }
  126. GUIDropDownData GUIMenu::getDropDownData() const
  127. {
  128. return getDropDownDataInternal(mRootElement);
  129. }
  130. void GUIMenu::setLocalizedName(const WString& menuItemLabel, const HString& localizedName)
  131. {
  132. mLocalizedEntryNames[menuItemLabel] = localizedName;
  133. }
  134. GUIDropDownData GUIMenu::getDropDownDataInternal(const GUIMenuItem& menu) const
  135. {
  136. GUIDropDownData dropDownData;
  137. for(auto& menuItem : menu.mChildren)
  138. {
  139. if(menuItem->isSeparator())
  140. {
  141. dropDownData.entries.push_back(GUIDropDownDataEntry::separator());
  142. }
  143. else
  144. {
  145. if(menuItem->getNumChildren() == 0)
  146. {
  147. dropDownData.entries.push_back(GUIDropDownDataEntry::button(menuItem->getName(), menuItem->getCallback(), menuItem->getShortcut().getName()));
  148. }
  149. else
  150. {
  151. dropDownData.entries.push_back(GUIDropDownDataEntry::subMenu(menuItem->getName(), getDropDownDataInternal(*menuItem)));
  152. }
  153. }
  154. }
  155. dropDownData.localizedNames = mLocalizedEntryNames;
  156. return dropDownData;
  157. }
  158. }