RadialMenu.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * RadialMenu.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 "RadialMenu.h"
  12. #include "Images.h"
  13. #include "TextControls.h"
  14. #include "../gui/CGuiHandler.h"
  15. #include "../gui/WindowHandler.h"
  16. #include "../render/IImage.h"
  17. RadialMenuItem::RadialMenuItem(const std::string & imageName, const std::string & hoverText, const std::function<void()> & callback)
  18. : callback(callback)
  19. , hoverText(hoverText)
  20. {
  21. OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
  22. image = IImage::createFromFile("radialMenu/" + imageName, EImageBlitMode::COLORKEY);
  23. picture = std::make_shared<CPicture>(image, Point(0, 0));
  24. pos = picture->pos;
  25. }
  26. RadialMenu::RadialMenu(const Point & positionToCenter, const std::vector<RadialMenuConfig> & menuConfig)
  27. {
  28. OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
  29. pos += positionToCenter;
  30. addItem(Point(0,0), "itemEmpty", "", [](){});
  31. Point itemSize = items.back()->pos.dimensions();
  32. moveBy(-itemSize / 2);
  33. for (auto const & item : menuConfig)
  34. addItem(item.itemPosition, item.imageName, item.hoverText, item.callback);
  35. statusBar = CGStatusBar::create(-80, -100, "radialMenu/statusBar");
  36. for(const auto & item : items)
  37. pos = pos.include(item->pos);
  38. fitToScreen(10);
  39. addUsedEvents(GESTURE);
  40. }
  41. void RadialMenu::addItem(const Point & offset, const std::string & path, const std::string & hoverText, const std::function<void()>& callback )
  42. {
  43. auto item = std::make_shared<RadialMenuItem>(path, hoverText, callback);
  44. item->moveBy(offset);
  45. items.push_back(item);
  46. }
  47. std::shared_ptr<RadialMenuItem> RadialMenu::findNearestItem(const Point & cursorPosition) const
  48. {
  49. int bestDistance = std::numeric_limits<int>::max();
  50. std::shared_ptr<RadialMenuItem> bestItem;
  51. for(const auto & item : items)
  52. {
  53. Point vector = item->pos.center() - cursorPosition;
  54. if (vector.length() < bestDistance)
  55. {
  56. bestDistance = vector.length();
  57. bestItem = item;
  58. }
  59. }
  60. assert(bestItem);
  61. return bestItem;
  62. }
  63. void RadialMenu::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
  64. {
  65. auto item = findNearestItem(currentPosition);
  66. GH.statusbar()->write(item->hoverText);
  67. }
  68. void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
  69. {
  70. if (on)
  71. return;
  72. auto item = findNearestItem(finalPosition);
  73. // we need to close this window first so if action spawns a new window it won't be closed instead
  74. GH.windows().popWindows(1);
  75. item->callback();
  76. }