BsGUIListBox.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #include "BsGUIListBox.h"
  2. #include "BsImageSprite.h"
  3. #include "BsCGUIWidget.h"
  4. #include "BsGUISkin.h"
  5. #include "BsSpriteTexture.h"
  6. #include "BsTextSprite.h"
  7. #include "BsGUIDimensions.h"
  8. #include "BsGUIMouseEvent.h"
  9. #include "BsGUIManager.h"
  10. #include "BsGUIHelper.h"
  11. #include "BsGUIDropDownBoxManager.h"
  12. #include "BsTexture.h"
  13. namespace BansheeEngine
  14. {
  15. const String& GUIListBox::getGUITypeName()
  16. {
  17. static String name = "ListBox";
  18. return name;
  19. }
  20. GUIListBox::GUIListBox(const String& styleName, const Vector<HString>& elements, bool isMultiselect, const GUIDimensions& dimensions)
  21. :GUIButtonBase(styleName, GUIContent(HString(L"")), dimensions), mElements(elements), mIsMultiselect(isMultiselect)
  22. {
  23. mElementStates.resize(elements.size(), false);
  24. if (!mIsMultiselect && mElementStates.size() > 0)
  25. mElementStates[0] = true;
  26. updateContents();
  27. }
  28. GUIListBox::~GUIListBox()
  29. {
  30. closeListBox();
  31. }
  32. GUIListBox* GUIListBox::create(const Vector<HString>& elements, bool isMultiselect, const String& styleName)
  33. {
  34. return new (bs_alloc<GUIListBox>()) GUIListBox(getStyleName<GUIListBox>(styleName), elements, isMultiselect, GUIDimensions::create());
  35. }
  36. GUIListBox* GUIListBox::create(const Vector<HString>& elements, bool isMultiselect, const GUIOptions& options, const String& styleName)
  37. {
  38. return new (bs_alloc<GUIListBox>()) GUIListBox(getStyleName<GUIListBox>(styleName), elements, isMultiselect, GUIDimensions::create(options));
  39. }
  40. GUIListBox* GUIListBox::create(const Vector<HString>& elements, const GUIOptions& options, const String& styleName)
  41. {
  42. return new (bs_alloc<GUIListBox>()) GUIListBox(getStyleName<GUIListBox>(styleName), elements, false, GUIDimensions::create(options));
  43. }
  44. void GUIListBox::setElements(const Vector<HString>& elements)
  45. {
  46. bool wasOpen = mDropDownBox != nullptr;
  47. if(wasOpen)
  48. closeListBox();
  49. mElements = elements;
  50. mElementStates.clear();
  51. mElementStates.resize(mElements.size(), false);
  52. if (!mIsMultiselect && mElementStates.size() > 0)
  53. mElementStates[0] = true;
  54. updateContents();
  55. if(wasOpen)
  56. openListBox();
  57. }
  58. void GUIListBox::selectElement(UINT32 idx)
  59. {
  60. if (idx >= (UINT32)mElements.size())
  61. return;
  62. if (mElementStates[idx] != true)
  63. elementSelected(idx);
  64. }
  65. void GUIListBox::deselectElement(UINT32 idx)
  66. {
  67. if (!mIsMultiselect || idx >= (UINT32)mElements.size())
  68. return;
  69. if (mElementStates[idx] != false)
  70. elementSelected(idx);
  71. }
  72. void GUIListBox::setElementStates(const Vector<bool>& states)
  73. {
  74. bool wasOpen = mDropDownBox != nullptr;
  75. if (wasOpen)
  76. closeListBox();
  77. UINT32 numElements = (UINT32)mElementStates.size();
  78. UINT32 min = std::min(numElements, (UINT32)states.size());
  79. for (UINT32 i = 0; i < min; i++)
  80. {
  81. mElementStates[i] = states[i];
  82. if (mElementStates[i] && !mIsMultiselect)
  83. {
  84. for (UINT32 j = i + 1; j < numElements; j++)
  85. mElementStates[j] = false;
  86. break;
  87. }
  88. }
  89. updateContents();
  90. if (wasOpen)
  91. openListBox();
  92. }
  93. bool GUIListBox::_mouseEvent(const GUIMouseEvent& ev)
  94. {
  95. bool processed = GUIButtonBase::_mouseEvent(ev);
  96. if(ev.getType() == GUIMouseEventType::MouseDown)
  97. {
  98. if (mDropDownBox == nullptr)
  99. openListBox();
  100. else
  101. closeListBox();
  102. processed = true;
  103. }
  104. return processed;
  105. }
  106. void GUIListBox::elementSelected(UINT32 idx)
  107. {
  108. if (idx >= (UINT32)mElements.size())
  109. return;
  110. if (mIsMultiselect)
  111. {
  112. bool selected = mElementStates[idx];
  113. mElementStates[idx] = !selected;
  114. if (!onSelectionToggled.empty())
  115. onSelectionToggled(idx, !selected);
  116. }
  117. else
  118. {
  119. for (UINT32 i = 0; i < (UINT32)mElementStates.size(); i++)
  120. mElementStates[i] = false;
  121. mElementStates[idx] = true;
  122. if (!onSelectionToggled.empty())
  123. onSelectionToggled(idx, true);
  124. closeListBox();
  125. }
  126. updateContents();
  127. }
  128. void GUIListBox::openListBox()
  129. {
  130. closeListBox();
  131. DROP_DOWN_BOX_DESC desc;
  132. UINT32 i = 0;
  133. for(auto& elem : mElements)
  134. {
  135. WString identifier = toWString(i);
  136. desc.dropDownData.entries.push_back(GUIDropDownDataEntry::button(identifier, std::bind(&GUIListBox::elementSelected, this, i)));
  137. desc.dropDownData.localizedNames[identifier] = elem;
  138. i++;
  139. }
  140. CGUIWidget* widget = _getParentWidget();
  141. desc.camera = widget->getCamera();
  142. desc.skin = widget->getSkinResource();
  143. desc.placement = DropDownAreaPlacement::aroundBoundsHorz(mClippedBounds);
  144. desc.dropDownData.states = mElementStates;
  145. GUIDropDownType type;
  146. if (mIsMultiselect)
  147. type = GUIDropDownType::MultiListBox;
  148. else
  149. type = GUIDropDownType::ListBox;
  150. mDropDownBox = GUIDropDownBoxManager::instance().openDropDownBox(
  151. desc, type, std::bind(&GUIListBox::onListBoxClosed, this));
  152. _setOn(true);
  153. }
  154. void GUIListBox::closeListBox()
  155. {
  156. if (mDropDownBox != nullptr)
  157. {
  158. GUIDropDownBoxManager::instance().closeDropDownBox();
  159. _setOn(false);
  160. mDropDownBox = nullptr;
  161. }
  162. }
  163. void GUIListBox::updateContents()
  164. {
  165. UINT32 selectedIdx = 0;
  166. UINT32 numSelected = 0;
  167. for (UINT32 i = 0; i < (UINT32)mElementStates.size(); i++)
  168. {
  169. if (mElementStates[i])
  170. {
  171. selectedIdx = i;
  172. numSelected++;
  173. }
  174. }
  175. if (mIsMultiselect)
  176. {
  177. if (numSelected == 1)
  178. setContent(GUIContent(mElements[selectedIdx]));
  179. else if (numSelected == 0)
  180. setContent(GUIContent(HEString(L"None")));
  181. else
  182. setContent(GUIContent(HEString(L"Multiple")));
  183. }
  184. else
  185. {
  186. setContent(GUIContent(mElements[selectedIdx]));
  187. }
  188. }
  189. void GUIListBox::onListBoxClosed()
  190. {
  191. _setOn(false);
  192. mDropDownBox = nullptr;
  193. }
  194. }