ComboBox.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * ComboBox.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "ComboBox.h"
  12. #include "Slider.h"
  13. #include "Images.h"
  14. #include "TextControls.h"
  15. #include "../GameEngine.h"
  16. #include "../gui/WindowHandler.h"
  17. ComboBox::DropDown::Item::Item(const JsonNode & config, ComboBox::DropDown & _dropDown, Point position)
  18. : InterfaceObjectConfigurable(LCLICK | HOVER, position),
  19. dropDown(_dropDown)
  20. {
  21. build(config);
  22. if(auto w = widget<CIntObject>("hoverImage"))
  23. {
  24. pos.w = w->pos.w;
  25. pos.h = w->pos.h;
  26. w->disable();
  27. }
  28. setRedrawParent(true);
  29. }
  30. void ComboBox::DropDown::Item::updateItem(int idx, const void * _item)
  31. {
  32. item = _item;
  33. if(auto w = widget<CLabel>("labelName"))
  34. {
  35. if(dropDown.comboBox.getItemText)
  36. w->setText(dropDown.comboBox.getItemText(idx, item));
  37. }
  38. }
  39. void ComboBox::DropDown::Item::hover(bool on)
  40. {
  41. auto h = widget<CIntObject>("hoverImage");
  42. auto w = widget<CLabel>("labelName");
  43. if(h && w)
  44. {
  45. if(w->getText().empty() || on == false)
  46. h->disable();
  47. else
  48. h->enable();
  49. }
  50. redraw();
  51. }
  52. void ComboBox::DropDown::Item::clickPressed(const Point & cursorPosition)
  53. {
  54. if(isHovered())
  55. dropDown.setItem(item);
  56. }
  57. void ComboBox::DropDown::Item::clickReleased(const Point & cursorPosition)
  58. {
  59. dropDown.clickPressed(cursorPosition);
  60. dropDown.clickReleased(cursorPosition);
  61. }
  62. ComboBox::DropDown::DropDown(const JsonNode & config, ComboBox & _comboBox, Point dropDownPosition):
  63. InterfaceObjectConfigurable(LCLICK | HOVER),
  64. comboBox(_comboBox)
  65. {
  66. REGISTER_BUILDER("item", &ComboBox::DropDown::buildItem);
  67. if(comboBox.onConstructItems)
  68. comboBox.onConstructItems(curItems);
  69. addCallback("sliderMove", std::bind(&ComboBox::DropDown::sliderMove, this, std::placeholders::_1));
  70. pos = comboBox.pos + dropDownPosition;
  71. build(config);
  72. if(auto w = widget<CSlider>("slider"))
  73. {
  74. w->setAmount(curItems.size());
  75. }
  76. //FIXME: this should be done by InterfaceObjectConfigurable, but might have side-effects
  77. pos = children.front()->pos;
  78. for (auto const & child : children)
  79. pos = pos.include(child->pos);
  80. updateListItems();
  81. }
  82. std::shared_ptr<ComboBox::DropDown::Item> ComboBox::DropDown::buildItem(const JsonNode & config)
  83. {
  84. auto position = readPosition(config["position"]);
  85. items.push_back(std::make_shared<Item>(config, *this, position));
  86. return items.back();
  87. }
  88. void ComboBox::DropDown::sliderMove(int slidPos)
  89. {
  90. auto w = widget<CSlider>("slider");
  91. if(!w)
  92. return; // ignore spurious call when slider is being created
  93. updateListItems();
  94. redraw();
  95. }
  96. bool ComboBox::DropDown::receiveEvent(const Point & position, int eventType) const
  97. {
  98. if (eventType == LCLICK)
  99. return true; // we want drop box to close when clicking outside drop box borders
  100. return CIntObject::receiveEvent(position, eventType);
  101. }
  102. void ComboBox::DropDown::clickPressed(const Point & cursorPosition)
  103. {
  104. if (!pos.isInside(cursorPosition))
  105. {
  106. assert(ENGINE->windows().isTopWindow(this));
  107. ENGINE->windows().popWindows(1);
  108. }
  109. }
  110. void ComboBox::DropDown::updateListItems()
  111. {
  112. int elemIdx = 0;
  113. if(auto w = widget<CSlider>("slider"))
  114. elemIdx = w->getValue();
  115. for(auto item : items)
  116. {
  117. if(elemIdx < curItems.size())
  118. {
  119. item->updateItem(elemIdx, curItems[elemIdx]);
  120. elemIdx++;
  121. }
  122. else
  123. {
  124. item->updateItem(elemIdx);
  125. }
  126. }
  127. }
  128. void ComboBox::DropDown::setItem(const void * item)
  129. {
  130. comboBox.setItem(item);
  131. assert(ENGINE->windows().isTopWindow(this));
  132. ENGINE->windows().popWindows(1);
  133. }
  134. ComboBox::ComboBox(Point position, const AnimationPath & defName, const std::pair<std::string, std::string> & help, const JsonNode & dropDownDescriptor, Point dropDownPosition, EShortcut key, bool playerColoredButton):
  135. CButton(position, defName, help, 0, key, playerColoredButton)
  136. {
  137. addCallback([this, dropDownDescriptor, dropDownPosition]()
  138. {
  139. ENGINE->windows().createAndPushWindow<ComboBox::DropDown>(dropDownDescriptor, *this, dropDownPosition);
  140. });
  141. }
  142. void ComboBox::setItem(const void * item)
  143. {
  144. auto w = std::dynamic_pointer_cast<CLabel>(getOverlay());
  145. if( w && getItemText)
  146. setTextOverlay(getItemText(0, item), w->font, w->color);
  147. if(onSetItem)
  148. onSetItem(item);
  149. }
  150. void ComboBox::setItem(int id)
  151. {
  152. std::vector<const void *> tempItems;
  153. onConstructItems(tempItems);
  154. setItem(tempItems.at(id));
  155. }