BsGUIListBox.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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. UINT32 numElements = (UINT32)mElementStates.size();
  75. UINT32 min = std::min(numElements, (UINT32)states.size());
  76. bool anythingModified = min != numElements;
  77. if (!anythingModified)
  78. {
  79. for (UINT32 i = 0; i < numElements; i++)
  80. {
  81. if (mElementStates[i] != states[i])
  82. {
  83. anythingModified = true;
  84. break;
  85. }
  86. }
  87. }
  88. if (!anythingModified)
  89. return;
  90. bool wasOpen = mDropDownBox != nullptr;
  91. if (wasOpen)
  92. closeListBox();
  93. for (UINT32 i = 0; i < min; i++)
  94. {
  95. mElementStates[i] = states[i];
  96. if (mElementStates[i] && !mIsMultiselect)
  97. {
  98. for (UINT32 j = i + 1; j < numElements; j++)
  99. mElementStates[j] = false;
  100. break;
  101. }
  102. }
  103. updateContents();
  104. if (wasOpen)
  105. openListBox();
  106. }
  107. bool GUIListBox::_mouseEvent(const GUIMouseEvent& ev)
  108. {
  109. bool processed = GUIButtonBase::_mouseEvent(ev);
  110. if(ev.getType() == GUIMouseEventType::MouseDown)
  111. {
  112. if (!_isDisabled())
  113. {
  114. if (mDropDownBox == nullptr)
  115. openListBox();
  116. else
  117. closeListBox();
  118. }
  119. processed = true;
  120. }
  121. return processed;
  122. }
  123. void GUIListBox::elementSelected(UINT32 idx)
  124. {
  125. if (idx >= (UINT32)mElements.size())
  126. return;
  127. if (mIsMultiselect)
  128. {
  129. bool selected = mElementStates[idx];
  130. mElementStates[idx] = !selected;
  131. if (!onSelectionToggled.empty())
  132. onSelectionToggled(idx, !selected);
  133. }
  134. else
  135. {
  136. for (UINT32 i = 0; i < (UINT32)mElementStates.size(); i++)
  137. mElementStates[i] = false;
  138. mElementStates[idx] = true;
  139. if (!onSelectionToggled.empty())
  140. onSelectionToggled(idx, true);
  141. closeListBox();
  142. }
  143. updateContents();
  144. }
  145. void GUIListBox::openListBox()
  146. {
  147. closeListBox();
  148. DROP_DOWN_BOX_DESC desc;
  149. UINT32 i = 0;
  150. for(auto& elem : mElements)
  151. {
  152. WString identifier = toWString(i);
  153. desc.dropDownData.entries.push_back(GUIDropDownDataEntry::button(identifier, std::bind(&GUIListBox::elementSelected, this, i)));
  154. desc.dropDownData.localizedNames[identifier] = elem;
  155. i++;
  156. }
  157. CGUIWidget* widget = _getParentWidget();
  158. desc.camera = widget->getCamera();
  159. desc.skin = widget->getSkinResource();
  160. desc.placement = DropDownAreaPlacement::aroundBoundsHorz(mClippedBounds);
  161. desc.dropDownData.states = mElementStates;
  162. GUIDropDownType type;
  163. if (mIsMultiselect)
  164. type = GUIDropDownType::MultiListBox;
  165. else
  166. type = GUIDropDownType::ListBox;
  167. mDropDownBox = GUIDropDownBoxManager::instance().openDropDownBox(
  168. desc, type, std::bind(&GUIListBox::onListBoxClosed, this));
  169. _setOn(true);
  170. }
  171. void GUIListBox::closeListBox()
  172. {
  173. if (mDropDownBox != nullptr)
  174. {
  175. GUIDropDownBoxManager::instance().closeDropDownBox();
  176. _setOn(false);
  177. mDropDownBox = nullptr;
  178. }
  179. }
  180. void GUIListBox::updateContents()
  181. {
  182. UINT32 selectedIdx = 0;
  183. UINT32 numSelected = 0;
  184. for (UINT32 i = 0; i < (UINT32)mElementStates.size(); i++)
  185. {
  186. if (mElementStates[i])
  187. {
  188. selectedIdx = i;
  189. numSelected++;
  190. }
  191. }
  192. if (mIsMultiselect)
  193. {
  194. if (numSelected == 1)
  195. setContent(GUIContent(mElements[selectedIdx]));
  196. else if (numSelected == 0)
  197. setContent(GUIContent(HEString(L"None")));
  198. else
  199. setContent(GUIContent(HEString(L"Multiple")));
  200. }
  201. else
  202. {
  203. setContent(GUIContent(mElements[selectedIdx]));
  204. }
  205. }
  206. void GUIListBox::onListBoxClosed()
  207. {
  208. _setOn(false);
  209. mDropDownBox = nullptr;
  210. }
  211. }