You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

326 lines
7.7KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "../ImageSlider.hpp"
  17. #include <cmath>
  18. START_NAMESPACE_DGL
  19. // -----------------------------------------------------------------------
  20. ImageSlider::ImageSlider(Window& parent, const Image& image)
  21. : Widget(parent),
  22. fImage(image),
  23. fMinimum(0.0f),
  24. fMaximum(1.0f),
  25. fStep(0.0f),
  26. fValue(0.5f),
  27. fValueTmp(fValue),
  28. fDragging(false),
  29. fStartedX(0),
  30. fStartedY(0),
  31. fCallback(nullptr)
  32. {
  33. setSize(fImage.getSize());
  34. }
  35. ImageSlider::ImageSlider(Widget* widget, const Image& image)
  36. : Widget(widget->getParentWindow()),
  37. fImage(image),
  38. fMinimum(0.0f),
  39. fMaximum(1.0f),
  40. fStep(0.0f),
  41. fValue(0.5f),
  42. fValueTmp(fValue),
  43. fDragging(false),
  44. fStartedX(0),
  45. fStartedY(0),
  46. fCallback(nullptr)
  47. {
  48. setSize(fImage.getSize());
  49. }
  50. ImageSlider::ImageSlider(const ImageSlider& imageSlider)
  51. : Widget(imageSlider.getParentWindow()),
  52. fImage(imageSlider.fImage),
  53. fMinimum(imageSlider.fMinimum),
  54. fMaximum(imageSlider.fMaximum),
  55. fStep(imageSlider.fStep),
  56. fValue(imageSlider.fValue),
  57. fValueTmp(fValue),
  58. fDragging(false),
  59. fStartedX(0),
  60. fStartedY(0),
  61. fCallback(imageSlider.fCallback),
  62. fStartPos(imageSlider.fStartPos),
  63. fEndPos(imageSlider.fEndPos),
  64. fSliderArea(imageSlider.fSliderArea)
  65. {
  66. setSize(fImage.getSize());
  67. }
  68. float ImageSlider::getValue() const
  69. {
  70. return fValue;
  71. }
  72. void ImageSlider::setStartPos(const Point<int>& startPos)
  73. {
  74. fStartPos = startPos;
  75. _recheckArea();
  76. }
  77. void ImageSlider::setStartPos(int x, int y)
  78. {
  79. setStartPos(Point<int>(x, y));
  80. }
  81. void ImageSlider::setEndPos(const Point<int>& endPos)
  82. {
  83. fEndPos = endPos;
  84. _recheckArea();
  85. }
  86. void ImageSlider::setEndPos(int x, int y)
  87. {
  88. setEndPos(Point<int>(x, y));
  89. }
  90. void ImageSlider::setRange(float min, float max)
  91. {
  92. if (fValue < min)
  93. {
  94. fValue = min;
  95. repaint();
  96. if (fCallback != nullptr)
  97. fCallback->imageSliderValueChanged(this, fValue);
  98. }
  99. else if (fValue > max)
  100. {
  101. fValue = max;
  102. repaint();
  103. if (fCallback != nullptr)
  104. fCallback->imageSliderValueChanged(this, fValue);
  105. }
  106. fMinimum = min;
  107. fMaximum = max;
  108. }
  109. void ImageSlider::setStep(float step)
  110. {
  111. fStep = step;
  112. }
  113. void ImageSlider::setValue(float value, bool sendCallback)
  114. {
  115. if (fValue == value)
  116. return;
  117. fValue = value;
  118. if (fStep == 0.0f)
  119. fValueTmp = value;
  120. repaint();
  121. if (sendCallback && fCallback != nullptr)
  122. fCallback->imageSliderValueChanged(this, fValue);
  123. }
  124. void ImageSlider::setCallback(Callback* callback)
  125. {
  126. fCallback = callback;
  127. }
  128. void ImageSlider::onDisplay()
  129. {
  130. #if 0 // DEBUG, paints slider area
  131. glColor3f(0.4f, 0.5f, 0.1f);
  132. glRecti(fSliderArea.getX(), fSliderArea.getY(), fSliderArea.getX()+fSliderArea.getWidth(), fSliderArea.getY()+fSliderArea.getHeight());
  133. #endif
  134. float normValue = (fValue - fMinimum) / (fMaximum - fMinimum);
  135. int x, y;
  136. if (fStartPos.getX() == fEndPos.getX())
  137. {
  138. x = fStartPos.getX();
  139. y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
  140. }
  141. else if (fStartPos.getY() == fEndPos.getY())
  142. {
  143. x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
  144. y = fStartPos.getY();
  145. }
  146. else
  147. return;
  148. fImage.draw(x, y);
  149. }
  150. bool ImageSlider::onMouse(int button, bool press, int x, int y)
  151. {
  152. if (button != 1)
  153. return false;
  154. if (press)
  155. {
  156. if (! fSliderArea.contains(x, y))
  157. return false;
  158. float vper;
  159. if (fStartPos.getX() == fEndPos.getX())
  160. {
  161. // vertical
  162. vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
  163. }
  164. else if (fStartPos.getY() == fEndPos.getY())
  165. {
  166. // horizontal
  167. vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
  168. }
  169. else
  170. return false;
  171. float value;
  172. value = fMaximum - vper * (fMaximum - fMinimum);
  173. if (value < fMinimum)
  174. {
  175. value = fMinimum;
  176. fValueTmp = value;
  177. }
  178. else if (value > fMaximum)
  179. {
  180. value = fMaximum;
  181. fValueTmp = value;
  182. }
  183. else if (fStep != 0.0f)
  184. {
  185. fValueTmp = value;
  186. const float rest = std::fmod(value, fStep);
  187. value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
  188. }
  189. fDragging = true;
  190. fStartedX = x;
  191. fStartedY = y;
  192. if (fCallback != nullptr)
  193. fCallback->imageSliderDragStarted(this);
  194. setValue(value, true);
  195. return true;
  196. }
  197. else if (fDragging)
  198. {
  199. if (fCallback != nullptr)
  200. fCallback->imageSliderDragFinished(this);
  201. fDragging = false;
  202. return true;
  203. }
  204. return false;
  205. }
  206. bool ImageSlider::onMotion(int x, int y)
  207. {
  208. if (! fDragging)
  209. return false;
  210. bool horizontal = fStartPos.getY() == fEndPos.getY();
  211. if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal))
  212. {
  213. float vper;
  214. if (horizontal)
  215. {
  216. // horizontal
  217. vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
  218. }
  219. else
  220. {
  221. // vertical
  222. vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
  223. }
  224. float value;
  225. value = fMaximum - vper * (fMaximum - fMinimum);
  226. if (value < fMinimum)
  227. {
  228. value = fMinimum;
  229. fValueTmp = value;
  230. }
  231. else if (value > fMaximum)
  232. {
  233. value = fMaximum;
  234. fValueTmp = value;
  235. }
  236. else if (fStep != 0.0f)
  237. {
  238. fValueTmp = value;
  239. const float rest = std::fmod(value, fStep);
  240. value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
  241. }
  242. setValue(value, true);
  243. }
  244. else if (y < fSliderArea.getY())
  245. {
  246. setValue(fMaximum, true);
  247. }
  248. else
  249. {
  250. setValue(fMinimum, true);
  251. }
  252. return true;
  253. }
  254. void ImageSlider::_recheckArea()
  255. {
  256. if (fStartPos.getX() == fEndPos.getX())
  257. {
  258. fSliderArea = Rectangle<int>(fStartPos.getX(),
  259. fStartPos.getY(),
  260. fImage.getWidth(),
  261. fEndPos.getY() + fImage.getHeight() - fStartPos.getY());
  262. }
  263. else if (fStartPos.getY() == fEndPos.getY())
  264. {
  265. fSliderArea = Rectangle<int>(fStartPos.getX(),
  266. fStartPos.getY(),
  267. fEndPos.getX() + fImage.getWidth() - fStartPos.getX(),
  268. fImage.getHeight());
  269. }
  270. }
  271. // -----------------------------------------------------------------------
  272. END_NAMESPACE_DGL