Audio plugin host https://kx.studio/carla
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.

359 lines
8.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. fInverted(false),
  30. fStartedX(0),
  31. fStartedY(0),
  32. fCallback(nullptr)
  33. {
  34. setSize(fImage.getSize());
  35. }
  36. ImageSlider::ImageSlider(Widget* widget, const Image& image)
  37. : Widget(widget->getParentWindow()),
  38. fImage(image),
  39. fMinimum(0.0f),
  40. fMaximum(1.0f),
  41. fStep(0.0f),
  42. fValue(0.5f),
  43. fValueTmp(fValue),
  44. fDragging(false),
  45. fInverted(false),
  46. fStartedX(0),
  47. fStartedY(0),
  48. fCallback(nullptr)
  49. {
  50. setSize(fImage.getSize());
  51. }
  52. ImageSlider::ImageSlider(const ImageSlider& imageSlider)
  53. : Widget(imageSlider.getParentWindow()),
  54. fImage(imageSlider.fImage),
  55. fMinimum(imageSlider.fMinimum),
  56. fMaximum(imageSlider.fMaximum),
  57. fStep(imageSlider.fStep),
  58. fValue(imageSlider.fValue),
  59. fValueTmp(fValue),
  60. fDragging(false),
  61. fInverted(imageSlider.fInverted),
  62. fStartedX(0),
  63. fStartedY(0),
  64. fCallback(imageSlider.fCallback),
  65. fStartPos(imageSlider.fStartPos),
  66. fEndPos(imageSlider.fEndPos),
  67. fSliderArea(imageSlider.fSliderArea)
  68. {
  69. setSize(fImage.getSize());
  70. }
  71. float ImageSlider::getValue() const
  72. {
  73. return fValue;
  74. }
  75. void ImageSlider::setStartPos(const Point<int>& startPos)
  76. {
  77. fStartPos = startPos;
  78. _recheckArea();
  79. }
  80. void ImageSlider::setStartPos(int x, int y)
  81. {
  82. setStartPos(Point<int>(x, y));
  83. }
  84. void ImageSlider::setEndPos(const Point<int>& endPos)
  85. {
  86. fEndPos = endPos;
  87. _recheckArea();
  88. }
  89. void ImageSlider::setEndPos(int x, int y)
  90. {
  91. setEndPos(Point<int>(x, y));
  92. }
  93. void ImageSlider::setInverted(bool inverted)
  94. {
  95. if (fInverted == inverted)
  96. return;
  97. fInverted = inverted;
  98. repaint();
  99. }
  100. void ImageSlider::setRange(float min, float max)
  101. {
  102. if (fValue < min)
  103. {
  104. fValue = min;
  105. repaint();
  106. if (fCallback != nullptr)
  107. fCallback->imageSliderValueChanged(this, fValue);
  108. }
  109. else if (fValue > max)
  110. {
  111. fValue = max;
  112. repaint();
  113. if (fCallback != nullptr)
  114. fCallback->imageSliderValueChanged(this, fValue);
  115. }
  116. fMinimum = min;
  117. fMaximum = max;
  118. }
  119. void ImageSlider::setStep(float step)
  120. {
  121. fStep = step;
  122. }
  123. void ImageSlider::setValue(float value, bool sendCallback)
  124. {
  125. if (fValue == value)
  126. return;
  127. fValue = value;
  128. if (fStep == 0.0f)
  129. fValueTmp = value;
  130. repaint();
  131. if (sendCallback && fCallback != nullptr)
  132. fCallback->imageSliderValueChanged(this, fValue);
  133. }
  134. void ImageSlider::setCallback(Callback* callback)
  135. {
  136. fCallback = callback;
  137. }
  138. void ImageSlider::onDisplay()
  139. {
  140. #if 0 // DEBUG, paints slider area
  141. glColor3f(0.4f, 0.5f, 0.1f);
  142. glRecti(fSliderArea.getX(), fSliderArea.getY(), fSliderArea.getX()+fSliderArea.getWidth(), fSliderArea.getY()+fSliderArea.getHeight());
  143. glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  144. #endif
  145. float normValue = (fValue - fMinimum) / (fMaximum - fMinimum);
  146. int x, y;
  147. if (fStartPos.getY() == fEndPos.getY())
  148. {
  149. // horizontal
  150. if (fInverted)
  151. x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
  152. else
  153. x = fStartPos.getX() + static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
  154. y = fStartPos.getY();
  155. }
  156. else
  157. {
  158. // vertical
  159. x = fStartPos.getX();
  160. if (fInverted)
  161. y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
  162. else
  163. y = fStartPos.getY() + static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
  164. }
  165. fImage.draw(x, y);
  166. }
  167. bool ImageSlider::onMouse(int button, bool press, int x, int y)
  168. {
  169. if (button != 1)
  170. return false;
  171. if (press)
  172. {
  173. if (! fSliderArea.contains(x, y))
  174. return false;
  175. float vper;
  176. if (fStartPos.getY() == fEndPos.getY())
  177. {
  178. // horizontal
  179. vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
  180. }
  181. else
  182. {
  183. // vertical
  184. vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
  185. }
  186. float value;
  187. if (fInverted)
  188. value = fMaximum - vper * (fMaximum - fMinimum);
  189. else
  190. value = fMinimum + vper * (fMaximum - fMinimum);
  191. if (value < fMinimum)
  192. {
  193. value = fMinimum;
  194. fValueTmp = value;
  195. }
  196. else if (value > fMaximum)
  197. {
  198. value = fMaximum;
  199. fValueTmp = value;
  200. }
  201. else if (fStep != 0.0f)
  202. {
  203. fValueTmp = value;
  204. const float rest = std::fmod(value, fStep);
  205. value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
  206. }
  207. fDragging = true;
  208. fStartedX = x;
  209. fStartedY = y;
  210. if (fCallback != nullptr)
  211. fCallback->imageSliderDragStarted(this);
  212. setValue(value, true);
  213. return true;
  214. }
  215. else if (fDragging)
  216. {
  217. if (fCallback != nullptr)
  218. fCallback->imageSliderDragFinished(this);
  219. fDragging = false;
  220. return true;
  221. }
  222. return false;
  223. }
  224. bool ImageSlider::onMotion(int x, int y)
  225. {
  226. if (! fDragging)
  227. return false;
  228. const bool horizontal = fStartPos.getY() == fEndPos.getY();
  229. if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal))
  230. {
  231. float vper;
  232. if (horizontal)
  233. {
  234. // horizontal
  235. vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
  236. }
  237. else
  238. {
  239. // vertical
  240. vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
  241. }
  242. float value;
  243. if (fInverted)
  244. value = fMaximum - vper * (fMaximum - fMinimum);
  245. else
  246. value = fMinimum + vper * (fMaximum - fMinimum);
  247. if (value < fMinimum)
  248. {
  249. value = fMinimum;
  250. fValueTmp = value;
  251. }
  252. else if (value > fMaximum)
  253. {
  254. value = fMaximum;
  255. fValueTmp = value;
  256. }
  257. else if (fStep != 0.0f)
  258. {
  259. fValueTmp = value;
  260. const float rest = std::fmod(value, fStep);
  261. value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
  262. }
  263. setValue(value, true);
  264. }
  265. else if (horizontal)
  266. {
  267. if (x < fSliderArea.getX())
  268. setValue(fInverted ? fMaximum : fMinimum, true);
  269. else
  270. setValue(fInverted ? fMinimum : fMaximum, true);
  271. }
  272. else
  273. {
  274. if (y < fSliderArea.getY())
  275. setValue(fInverted ? fMaximum : fMinimum, true);
  276. else
  277. setValue(fInverted ? fMinimum : fMaximum, true);
  278. }
  279. return true;
  280. }
  281. void ImageSlider::_recheckArea()
  282. {
  283. if (fStartPos.getY() == fEndPos.getY())
  284. {
  285. // horizontal
  286. fSliderArea = Rectangle<int>(fStartPos.getX(),
  287. fStartPos.getY(),
  288. fEndPos.getX() + fImage.getWidth() - fStartPos.getX(),
  289. fImage.getHeight());
  290. }
  291. else
  292. {
  293. // vertical
  294. fSliderArea = Rectangle<int>(fStartPos.getX(),
  295. fStartPos.getY(),
  296. fImage.getWidth(),
  297. fEndPos.getY() + fImage.getHeight() - fStartPos.getY());
  298. }
  299. }
  300. // -----------------------------------------------------------------------
  301. END_NAMESPACE_DGL