Slider.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. OBJECTTYPESTATIC(Slider);
  31. Slider::Slider(Context* context) :
  32. BorderImage(context),
  33. orientation_(O_HORIZONTAL),
  34. range_(1.0f),
  35. value_(0.0f),
  36. dragSlider_(false)
  37. {
  38. active_ = true;
  39. knob_ = new BorderImage(context_);
  40. AddChild(knob_);
  41. UpdateSlider();
  42. }
  43. Slider::~Slider()
  44. {
  45. }
  46. void Slider::RegisterObject(Context* context)
  47. {
  48. context->RegisterFactory<Slider>();
  49. }
  50. void Slider::SetStyle(const XMLElement& element)
  51. {
  52. BorderImage::SetStyle(element);
  53. if (element.HasChild("orientation"))
  54. {
  55. String orientation = element.GetChild("orientation").GetAttributeLower("value");
  56. if (orientation == "horizontal" || orientation == "h")
  57. SetOrientation(O_HORIZONTAL);
  58. if (orientation == "vertical" || orientation == "v")
  59. SetOrientation(O_VERTICAL);
  60. }
  61. if (element.HasChild("range"))
  62. {
  63. XMLElement rangeElem = element.GetChild("range");
  64. SetRange(rangeElem.GetFloat("max"));
  65. SetValue(rangeElem.GetFloat("value"));
  66. }
  67. XMLElement knobElem = element.GetChild("knob");
  68. if (knobElem)
  69. knob_->SetStyle(knobElem);
  70. }
  71. void Slider::Update(float timeStep)
  72. {
  73. if (dragSlider_)
  74. hovering_ = true;
  75. // Propagate hover and selection effect to the slider knob
  76. knob_->SetHovering(hovering_);
  77. knob_->SetSelected(selected_);
  78. }
  79. void Slider::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  80. {
  81. // Show hover effect if inside the slider knob
  82. hovering_ = knob_->IsInside(screenPosition, true);
  83. }
  84. void Slider::OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  85. {
  86. dragStartCursor_ = position;
  87. dragStartPosition_ = knob_->GetPosition();
  88. dragSlider_ = knob_->IsInside(screenPosition, true);
  89. }
  90. void Slider::OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
  91. {
  92. if (!dragSlider_ || GetSize() == knob_->GetSize())
  93. return;
  94. float newValue = value_;
  95. IntVector2 delta = position - dragStartCursor_;
  96. if (orientation_ == O_HORIZONTAL)
  97. {
  98. int newX = Clamp(dragStartPosition_.x_ + delta.x_, 0, GetWidth() - knob_->GetWidth());
  99. knob_->SetPosition(newX, 0);
  100. newValue = (float)newX * range_ / (float)(GetWidth() - knob_->GetWidth());
  101. }
  102. else
  103. {
  104. int newY = Clamp(dragStartPosition_.y_ + delta.y_, 0, GetHeight() - knob_->GetHeight());
  105. knob_->SetPosition(0, newY);
  106. newValue = (float)newY * range_ / (float)(GetHeight() - knob_->GetHeight());
  107. }
  108. SetValue(newValue);
  109. }
  110. void Slider::OnDragEnd(const IntVector2& position, const IntVector2& screenPosition, Cursor* cursor)
  111. {
  112. dragSlider_ = false;
  113. }
  114. void Slider::OnResize()
  115. {
  116. UpdateSlider();
  117. }
  118. void Slider::SetOrientation(Orientation type)
  119. {
  120. orientation_ = type;
  121. UpdateSlider();
  122. }
  123. void Slider::SetRange(float range)
  124. {
  125. range = Max(range, 0.0f);
  126. if (range != range_)
  127. {
  128. range_ = range;
  129. UpdateSlider();
  130. }
  131. }
  132. void Slider::SetValue(float value)
  133. {
  134. value = Clamp(value, 0.0f, range_);
  135. if (value != value_)
  136. {
  137. value_ = value;
  138. UpdateSlider();
  139. using namespace SliderChanged;
  140. VariantMap eventData;
  141. eventData[P_ELEMENT] = (void*)this;
  142. eventData[P_VALUE] = value_;
  143. SendEvent(E_SLIDERCHANGED, eventData);
  144. }
  145. }
  146. void Slider::ChangeValue(float delta)
  147. {
  148. SetValue(value_ + delta);
  149. }
  150. void Slider::UpdateSlider()
  151. {
  152. const IntRect& border = knob_->GetBorder();
  153. if (range_ > 0.0f)
  154. {
  155. if (orientation_ == O_HORIZONTAL)
  156. {
  157. int sliderLength = (int)Max((float)GetWidth() / (range_ + 1.0f), (float)(border.left_ + border.right_));
  158. float sliderPos = (float)(GetWidth() - sliderLength) * value_ / range_;
  159. knob_->SetSize(sliderLength, GetHeight());
  160. knob_->SetPosition(Clamp((int)(sliderPos + 0.5f), 0, GetWidth() - knob_->GetWidth()), 0);
  161. }
  162. else
  163. {
  164. int sliderLength = (int)Max((float)GetHeight() / (range_ + 1.0f), (float)(border.top_ + border.bottom_));
  165. float sliderPos = (float)(GetHeight() - sliderLength) * value_ / range_;
  166. knob_->SetSize(GetWidth(), sliderLength);
  167. knob_->SetPosition(0, Clamp((int)(sliderPos + 0.5f), 0, GetHeight() - knob_->GetHeight()));
  168. }
  169. }
  170. else
  171. {
  172. knob_->SetSize(GetSize());
  173. knob_->SetPosition(0, 0);
  174. }
  175. }