Slider.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2012 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Context.h"
  25. #include "InputEvents.h"
  26. #include "Log.h"
  27. #include "Slider.h"
  28. #include "UIEvents.h"
  29. #include "DebugNew.h"
  30. namespace Urho3D
  31. {
  32. OBJECTTYPESTATIC(Slider);
  33. Slider::Slider(Context* context) :
  34. BorderImage(context),
  35. orientation_(O_HORIZONTAL),
  36. range_(1.0f),
  37. value_(0.0f),
  38. dragSlider_(false)
  39. {
  40. active_ = true;
  41. knob_ = CreateChild<BorderImage>();
  42. knob_->SetInternal(true);
  43. UpdateSlider();
  44. }
  45. Slider::~Slider()
  46. {
  47. }
  48. void Slider::RegisterObject(Context* context)
  49. {
  50. context->RegisterFactory<Slider>();
  51. }
  52. void Slider::SetStyle(const XMLElement& element)
  53. {
  54. BorderImage::SetStyle(element);
  55. if (element.HasChild("orientation"))
  56. {
  57. String orientation = element.GetChild("orientation").GetAttributeLower("value");
  58. if (orientation == "horizontal" || orientation == "h")
  59. SetOrientation(O_HORIZONTAL);
  60. if (orientation == "vertical" || orientation == "v")
  61. SetOrientation(O_VERTICAL);
  62. }
  63. if (element.HasChild("range"))
  64. {
  65. XMLElement rangeElem = element.GetChild("range");
  66. SetRange(rangeElem.GetFloat("max"));
  67. SetValue(rangeElem.GetFloat("value"));
  68. }
  69. XMLElement knobElem = element.GetChild("knob");
  70. if (knobElem)
  71. knob_->SetStyle(knobElem);
  72. }
  73. void Slider::Update(float timeStep)
  74. {
  75. if (dragSlider_)
  76. hovering_ = true;
  77. // Propagate hover and selection effect to the slider knob
  78. knob_->SetHovering(hovering_);
  79. knob_->SetSelected(selected_);
  80. }
  81. void Slider::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  82. {
  83. // Show hover effect if inside the slider knob
  84. hovering_ = knob_->IsInside(screenPosition, true);
  85. }
  86. void Slider::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  87. {
  88. dragBeginCursor_ = position;
  89. dragBeginPosition_ = knob_->GetPosition();
  90. dragSlider_ = knob_->IsInside(screenPosition, true);
  91. }
  92. void Slider::OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  93. {
  94. if (!dragSlider_ || GetSize() == knob_->GetSize())
  95. return;
  96. float newValue = value_;
  97. IntVector2 delta = position - dragBeginCursor_;
  98. if (orientation_ == O_HORIZONTAL)
  99. {
  100. int newX = Clamp(dragBeginPosition_.x_ + delta.x_, 0, GetWidth() - knob_->GetWidth());
  101. knob_->SetPosition(newX, 0);
  102. newValue = (float)newX * range_ / (float)(GetWidth() - knob_->GetWidth());
  103. }
  104. else
  105. {
  106. int newY = Clamp(dragBeginPosition_.y_ + delta.y_, 0, GetHeight() - knob_->GetHeight());
  107. knob_->SetPosition(0, newY);
  108. newValue = (float)newY * range_ / (float)(GetHeight() - knob_->GetHeight());
  109. }
  110. SetValue(newValue);
  111. }
  112. void Slider::OnDragEnd(const IntVector2& position, const IntVector2& screenPosition, Cursor* cursor)
  113. {
  114. dragSlider_ = false;
  115. }
  116. void Slider::OnResize()
  117. {
  118. UpdateSlider();
  119. }
  120. void Slider::SetOrientation(Orientation type)
  121. {
  122. orientation_ = type;
  123. UpdateSlider();
  124. }
  125. void Slider::SetRange(float range)
  126. {
  127. range = Max(range, 0.0f);
  128. if (range != range_)
  129. {
  130. range_ = range;
  131. UpdateSlider();
  132. }
  133. }
  134. void Slider::SetValue(float value)
  135. {
  136. value = Clamp(value, 0.0f, range_);
  137. if (value != value_)
  138. {
  139. value_ = value;
  140. UpdateSlider();
  141. using namespace SliderChanged;
  142. VariantMap eventData;
  143. eventData[P_ELEMENT] = (void*)this;
  144. eventData[P_VALUE] = value_;
  145. SendEvent(E_SLIDERCHANGED, eventData);
  146. }
  147. }
  148. void Slider::ChangeValue(float delta)
  149. {
  150. SetValue(value_ + delta);
  151. }
  152. void Slider::UpdateSlider()
  153. {
  154. const IntRect& border = knob_->GetBorder();
  155. if (range_ > 0.0f)
  156. {
  157. if (orientation_ == O_HORIZONTAL)
  158. {
  159. int sliderLength = (int)Max((float)GetWidth() / (range_ + 1.0f), (float)(border.left_ + border.right_));
  160. float sliderPos = (float)(GetWidth() - sliderLength) * value_ / range_;
  161. knob_->SetSize(sliderLength, GetHeight());
  162. knob_->SetPosition(Clamp((int)(sliderPos + 0.5f), 0, GetWidth() - knob_->GetWidth()), 0);
  163. }
  164. else
  165. {
  166. int sliderLength = (int)Max((float)GetHeight() / (range_ + 1.0f), (float)(border.top_ + border.bottom_));
  167. float sliderPos = (float)(GetHeight() - sliderLength) * value_ / range_;
  168. knob_->SetSize(GetWidth(), sliderLength);
  169. knob_->SetPosition(0, Clamp((int)(sliderPos + 0.5f), 0, GetHeight() - knob_->GetHeight()));
  170. }
  171. }
  172. else
  173. {
  174. knob_->SetSize(GetSize());
  175. knob_->SetPosition(0, 0);
  176. }
  177. }
  178. }