implementaion.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include "implementaion.h"
  2. movable_bounds::movable_bounds(range2D bounds) : bounds(bounds) { }
  3. int2 movable_bounds::lower() const
  4. {
  5. return bounds.lower();
  6. }
  7. int2 movable_bounds::upper() const
  8. {
  9. return bounds.upper();
  10. }
  11. movable_bounds& movable_bounds::operator+=(const int2& offset)
  12. {
  13. bounds += offset;
  14. return *this;
  15. }
  16. ui_element::ui_element(const i_bounds<int2>& bounds) :
  17. current(state::idle),
  18. bounds_proxy(bounds),
  19. _focus(false)
  20. { }
  21. bool contains(const i_bounds<int2>& bounds, int2 point)
  22. {
  23. return bounds.lower() < point && point < bounds.upper();
  24. };
  25. void ui_element::update(const interactive::event& event) noexcept
  26. {
  27. if(state::disabled == current)
  28. return;
  29. std::visit(support::overload{
  30. [this](const interactive::mouse_down& mouse)
  31. {
  32. if(contains(bounds_proxy, mouse.data.position))
  33. {
  34. current = state::pressed;
  35. for(auto&& callback : on_press)
  36. callback(*this);
  37. }
  38. },
  39. [this](const interactive::mouse_up& mouse)
  40. {
  41. if(state::pressed == current)
  42. {
  43. current = state::idle;
  44. for(auto&& callback : on_release)
  45. callback(*this);
  46. if(contains(bounds_proxy, mouse.data.position))
  47. {
  48. current = state::hover;
  49. for(auto&& callback : on_click)
  50. callback(*this);
  51. }
  52. }
  53. },
  54. [this](const interactive::mouse_motion& mouse)
  55. {
  56. if(contains(bounds_proxy, mouse.data.position))
  57. {
  58. if(state::idle == current )
  59. current = state::hover;
  60. }
  61. else
  62. {
  63. if(state::hover == current )
  64. current = state::idle;
  65. }
  66. },
  67. [](auto) { }
  68. }, event);
  69. }
  70. auto ui_element::current_state() const noexcept -> state
  71. {
  72. return current;
  73. }
  74. void ui_element::disable(bool value) noexcept
  75. {
  76. if(value && current != state::disabled)
  77. current = state::disabled;
  78. else
  79. if(!value && current == state::disabled)
  80. current = state::idle;
  81. }
  82. void ui_element::enable(bool value) noexcept
  83. {
  84. disable(!value);
  85. }
  86. void ui_element::focus(bool value) noexcept
  87. {
  88. _focus = value;
  89. }
  90. bool ui_element::focus() const noexcept
  91. {
  92. return _focus;
  93. }
  94. void focus_group::focus()
  95. {
  96. if(focused_element)
  97. focused_element->focus(true);
  98. }
  99. void focus_group::drop_focus()
  100. {
  101. if(focused_element)
  102. focused_element->focus(false);
  103. }
  104. void focus_group::focus(size_t index)
  105. {
  106. auto new_element = elements.at(index);
  107. if(focused_element)
  108. focused_element->focus(false);
  109. focused_element = new_element;
  110. focused_element->focus(true);
  111. }
  112. void focus_group::focus(i_focusable* element)
  113. {
  114. expecting_focus = false;
  115. focus(find(elements.begin(), elements.end(), element) - elements.begin());
  116. }
  117. void focus_group::pre_update(const interactive::event& event)
  118. {
  119. std::visit(support::overload{
  120. [this](const interactive::mouse_down&)
  121. {
  122. expecting_focus = true;
  123. },
  124. [](auto&&){}
  125. }, event);
  126. }
  127. void focus_group::post_update(const interactive::event& event)
  128. {
  129. if(expecting_focus)
  130. {
  131. expecting_focus = false;
  132. drop_focus();
  133. }
  134. std::visit(support::overload{
  135. [this](const interactive::key_pressed& event)
  136. {
  137. using namespace interactive;
  138. if(event.data.keycode == interactive::keycode::tab)
  139. {
  140. int direction;
  141. if(pressed(scancode::rshift) || pressed(scancode::lshift))
  142. {
  143. direction = !focused_element
  144. ? elements.size()-1
  145. : !focused_element->focus() ? 0 : -1;
  146. }
  147. else
  148. {
  149. direction = !focused_element || !focused_element->focus() ? 0 : 1;
  150. }
  151. focus(support::wrap(
  152. std::find(elements.begin(), elements.end(), focused_element) - elements.begin() +
  153. direction,
  154. elements.end() - elements.begin()
  155. ));
  156. }
  157. },
  158. [](auto&&){}
  159. }, event);
  160. }