BsGUIMenu.cpp 5.3 KB

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