DISTRHO Plugin Framework
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.

652 lines
17KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2022 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 "../EventHandlers.hpp"
  17. #include "../SubWidget.hpp"
  18. START_NAMESPACE_DGL
  19. // --------------------------------------------------------------------------------------------------------------------
  20. struct ButtonEventHandler::PrivateData {
  21. ButtonEventHandler* const self;
  22. SubWidget* const widget;
  23. ButtonEventHandler::Callback* internalCallback;
  24. ButtonEventHandler::Callback* userCallback;
  25. int button;
  26. int state;
  27. bool checkable;
  28. bool checked;
  29. Point<double> lastClickPos;
  30. Point<double> lastMotionPos;
  31. PrivateData(ButtonEventHandler* const s, SubWidget* const w)
  32. : self(s),
  33. widget(w),
  34. internalCallback(nullptr),
  35. userCallback(nullptr),
  36. button(-1),
  37. state(kButtonStateDefault),
  38. checkable(false),
  39. checked(false),
  40. lastClickPos(0, 0),
  41. lastMotionPos(0, 0) {}
  42. bool mouseEvent(const Widget::MouseEvent& ev)
  43. {
  44. lastClickPos = ev.pos;
  45. // button was released, handle it now
  46. if (button != -1 && ! ev.press)
  47. {
  48. DISTRHO_SAFE_ASSERT(state & kButtonStateActive);
  49. // release button
  50. const int button2 = button;
  51. button = -1;
  52. const int state2 = state;
  53. state &= ~kButtonStateActive;
  54. self->stateChanged(static_cast<State>(state), static_cast<State>(state2));
  55. widget->repaint();
  56. // cursor was moved outside the button bounds, ignore click
  57. if (! widget->contains(ev.pos))
  58. return true;
  59. // still on bounds, register click
  60. if (checkable)
  61. checked = !checked;
  62. if (internalCallback != nullptr)
  63. internalCallback->buttonClicked(widget, button2);
  64. else if (userCallback != nullptr)
  65. userCallback->buttonClicked(widget, button2);
  66. return true;
  67. }
  68. // button was pressed, wait for release
  69. if (ev.press && widget->contains(ev.pos))
  70. {
  71. const int state2 = state;
  72. button = static_cast<int>(ev.button);
  73. state |= kButtonStateActive;
  74. self->stateChanged(static_cast<State>(state), static_cast<State>(state2));
  75. widget->repaint();
  76. return true;
  77. }
  78. return false;
  79. }
  80. bool motionEvent(const Widget::MotionEvent& ev)
  81. {
  82. // keep pressed
  83. if (button != -1)
  84. {
  85. lastMotionPos = ev.pos;
  86. return true;
  87. }
  88. bool ret = false;
  89. if (widget->contains(ev.pos))
  90. {
  91. // check if entering hover
  92. if ((state & kButtonStateHover) == 0x0)
  93. {
  94. const int state2 = state;
  95. state |= kButtonStateHover;
  96. ret = widget->contains(lastMotionPos);
  97. self->stateChanged(static_cast<State>(state), static_cast<State>(state2));
  98. widget->repaint();
  99. }
  100. }
  101. else
  102. {
  103. // check if exiting hover
  104. if (state & kButtonStateHover)
  105. {
  106. const int state2 = state;
  107. state &= ~kButtonStateHover;
  108. ret = widget->contains(lastMotionPos);
  109. self->stateChanged(static_cast<State>(state), static_cast<State>(state2));
  110. widget->repaint();
  111. }
  112. }
  113. lastMotionPos = ev.pos;
  114. return ret;
  115. }
  116. void setActive(const bool active2, const bool sendCallback) noexcept
  117. {
  118. const bool active = state & kButtonStateActive;
  119. if (active == active2)
  120. return;
  121. state |= kButtonStateActive;
  122. widget->repaint();
  123. if (sendCallback)
  124. {
  125. if (internalCallback != nullptr)
  126. internalCallback->buttonClicked(widget, -1);
  127. else if (userCallback != nullptr)
  128. userCallback->buttonClicked(widget, -1);
  129. }
  130. }
  131. void setChecked(const bool checked2, const bool sendCallback) noexcept
  132. {
  133. if (checked == checked2)
  134. return;
  135. checked = checked2;
  136. widget->repaint();
  137. if (sendCallback)
  138. {
  139. if (internalCallback != nullptr)
  140. internalCallback->buttonClicked(widget, -1);
  141. else if (userCallback != nullptr)
  142. userCallback->buttonClicked(widget, -1);
  143. }
  144. }
  145. DISTRHO_DECLARE_NON_COPYABLE(PrivateData)
  146. };
  147. // --------------------------------------------------------------------------------------------------------------------
  148. ButtonEventHandler::ButtonEventHandler(SubWidget* const self)
  149. : pData(new PrivateData(this, self)) {}
  150. ButtonEventHandler::~ButtonEventHandler()
  151. {
  152. delete pData;
  153. }
  154. bool ButtonEventHandler::isActive() noexcept
  155. {
  156. return pData->state & kButtonStateActive;
  157. }
  158. void ButtonEventHandler::setActive(const bool active, const bool sendCallback) noexcept
  159. {
  160. pData->setActive(active, sendCallback);
  161. }
  162. bool ButtonEventHandler::isChecked() const noexcept
  163. {
  164. return pData->checked;
  165. }
  166. void ButtonEventHandler::setChecked(const bool checked, const bool sendCallback) noexcept
  167. {
  168. pData->setChecked(checked, sendCallback);
  169. }
  170. bool ButtonEventHandler::isCheckable() const noexcept
  171. {
  172. return pData->checkable;
  173. }
  174. void ButtonEventHandler::setCheckable(const bool checkable) noexcept
  175. {
  176. if (pData->checkable == checkable)
  177. return;
  178. pData->checkable = checkable;
  179. }
  180. Point<double> ButtonEventHandler::getLastClickPosition() const noexcept
  181. {
  182. return pData->lastClickPos;
  183. }
  184. Point<double> ButtonEventHandler::getLastMotionPosition() const noexcept
  185. {
  186. return pData->lastMotionPos;
  187. }
  188. void ButtonEventHandler::setCallback(Callback* const callback) noexcept
  189. {
  190. pData->userCallback = callback;
  191. }
  192. bool ButtonEventHandler::mouseEvent(const Widget::MouseEvent& ev)
  193. {
  194. return pData->mouseEvent(ev);
  195. }
  196. bool ButtonEventHandler::motionEvent(const Widget::MotionEvent& ev)
  197. {
  198. return pData->motionEvent(ev);
  199. }
  200. ButtonEventHandler::State ButtonEventHandler::getState() const noexcept
  201. {
  202. return static_cast<State>(pData->state);
  203. }
  204. void ButtonEventHandler::clearState() noexcept
  205. {
  206. pData->state = kButtonStateDefault;
  207. }
  208. void ButtonEventHandler::stateChanged(State, State)
  209. {
  210. }
  211. void ButtonEventHandler::setInternalCallback(Callback* const callback) noexcept
  212. {
  213. pData->internalCallback = callback;
  214. }
  215. void ButtonEventHandler::triggerUserCallback(SubWidget* const widget, const int button)
  216. {
  217. if (pData->userCallback != nullptr)
  218. pData->userCallback->buttonClicked(widget, button);
  219. }
  220. // --------------------------------------------------------------------------------------------------------------------
  221. struct KnobEventHandler::PrivateData {
  222. KnobEventHandler* const self;
  223. SubWidget* const widget;
  224. KnobEventHandler::Callback* callback;
  225. float minimum;
  226. float maximum;
  227. float step;
  228. float value;
  229. float valueDef;
  230. float valueTmp;
  231. bool usingDefault;
  232. bool usingLog;
  233. Orientation orientation;
  234. int state;
  235. double lastX;
  236. double lastY;
  237. PrivateData(KnobEventHandler* const s, SubWidget* const w)
  238. : self(s),
  239. widget(w),
  240. callback(nullptr),
  241. minimum(0.0f),
  242. maximum(1.0f),
  243. step(0.0f),
  244. value(0.5f),
  245. valueDef(value),
  246. valueTmp(value),
  247. usingDefault(false),
  248. usingLog(false),
  249. orientation(Vertical),
  250. state(kKnobStateDefault),
  251. lastX(0.0),
  252. lastY(0.0) {}
  253. PrivateData(KnobEventHandler* const s, SubWidget* const w, PrivateData* const other)
  254. : self(s),
  255. widget(w),
  256. callback(other->callback),
  257. minimum(other->minimum),
  258. maximum(other->maximum),
  259. step(other->step),
  260. value(other->value),
  261. valueDef(other->valueDef),
  262. valueTmp(value),
  263. usingDefault(other->usingDefault),
  264. usingLog(other->usingLog),
  265. orientation(other->orientation),
  266. state(kKnobStateDefault),
  267. lastX(0.0),
  268. lastY(0.0) {}
  269. void assignFrom(PrivateData* const other)
  270. {
  271. callback = other->callback;
  272. minimum = other->minimum;
  273. maximum = other->maximum;
  274. step = other->step;
  275. value = other->value;
  276. valueDef = other->valueDef;
  277. valueTmp = value;
  278. usingDefault = other->usingDefault;
  279. usingLog = other->usingLog;
  280. orientation = other->orientation;
  281. state = kKnobStateDefault;
  282. lastX = 0.0;
  283. lastY = 0.0;
  284. }
  285. inline float logscale(const float v) const
  286. {
  287. const float b = std::log(maximum/minimum)/(maximum-minimum);
  288. const float a = maximum/std::exp(maximum*b);
  289. return a * std::exp(b*v);
  290. }
  291. inline float invlogscale(const float v) const
  292. {
  293. const float b = std::log(maximum/minimum)/(maximum-minimum);
  294. const float a = maximum/std::exp(maximum*b);
  295. return std::log(v/a)/b;
  296. }
  297. bool mouseEvent(const Widget::MouseEvent& ev)
  298. {
  299. if (ev.button != 1)
  300. return false;
  301. if (ev.press)
  302. {
  303. if (! widget->contains(ev.pos))
  304. return false;
  305. if ((ev.mod & kModifierShift) != 0 && usingDefault)
  306. {
  307. setValue(valueDef, true);
  308. valueTmp = value;
  309. return true;
  310. }
  311. state |= kKnobStateDragging;
  312. lastX = ev.pos.getX();
  313. lastY = ev.pos.getY();
  314. widget->repaint();
  315. if (callback != nullptr)
  316. callback->knobDragStarted(widget);
  317. return true;
  318. }
  319. else if (state & kKnobStateDragging)
  320. {
  321. state &= ~kKnobStateDragging;
  322. widget->repaint();
  323. if (callback != nullptr)
  324. callback->knobDragFinished(widget);
  325. return true;
  326. }
  327. return false;
  328. }
  329. bool motionEvent(const Widget::MotionEvent& ev)
  330. {
  331. if ((state & kKnobStateDragging) == 0x0)
  332. return false;
  333. bool doVal = false;
  334. float d, value2 = 0.0f;
  335. switch (orientation)
  336. {
  337. case Horizontal:
  338. if (const double movX = ev.pos.getX() - lastX)
  339. {
  340. d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
  341. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(movX));
  342. doVal = true;
  343. }
  344. break;
  345. case Vertical:
  346. if (const double movY = lastY - ev.pos.getY())
  347. {
  348. d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
  349. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(movY));
  350. doVal = true;
  351. }
  352. break;
  353. case Both:
  354. const double movX = ev.pos.getX() - lastX;
  355. const double movY = lastY - ev.pos.getY();
  356. if (const double mov = movX + movY)
  357. {
  358. d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
  359. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(mov));
  360. doVal = true;
  361. }
  362. break;
  363. }
  364. if (! doVal)
  365. return false;
  366. if (usingLog)
  367. value2 = logscale(value2);
  368. if (value2 < minimum)
  369. {
  370. valueTmp = value2 = minimum;
  371. }
  372. else if (value2 > maximum)
  373. {
  374. valueTmp = value2 = maximum;
  375. }
  376. else
  377. {
  378. valueTmp = value2;
  379. if (d_isNotZero(step))
  380. {
  381. const float rest = std::fmod(value2, step);
  382. value2 -= rest + (rest > step/2.0f ? step : 0.0f);
  383. if (value2 < minimum)
  384. valueTmp = value2 = minimum;
  385. else if (value2 > maximum)
  386. valueTmp = value2 = maximum;
  387. }
  388. }
  389. setValue(value2, true);
  390. lastX = ev.pos.getX();
  391. lastY = ev.pos.getY();
  392. return true;
  393. }
  394. bool scrollEvent(const Widget::ScrollEvent& ev)
  395. {
  396. if (! widget->contains(ev.pos))
  397. return false;
  398. const float dir = (ev.delta.getY() > 0.f) ? 1.f : -1.f;
  399. const float d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
  400. float value2 = (usingLog ? invlogscale(valueTmp) : valueTmp)
  401. + ((maximum - minimum) / d * 10.f * dir);
  402. if (usingLog)
  403. value2 = logscale(value2);
  404. if (value2 < minimum)
  405. {
  406. valueTmp = value2 = minimum;
  407. }
  408. else if (value2 > maximum)
  409. {
  410. valueTmp = value2 = maximum;
  411. }
  412. else
  413. {
  414. valueTmp = value2;
  415. if (d_isNotZero(step))
  416. {
  417. const float rest = std::fmod(value2, step);
  418. value2 = value2 - rest + (rest > step/2.0f ? step : 0.0f);
  419. }
  420. }
  421. setValue(value2, true);
  422. return true;
  423. }
  424. float getNormalizedValue() const noexcept
  425. {
  426. const float diff = maximum - minimum;
  427. return ((usingLog ? invlogscale(value) : value) - minimum) / diff;
  428. }
  429. void setRange(const float min, const float max) noexcept
  430. {
  431. DISTRHO_SAFE_ASSERT_RETURN(max > min,);
  432. if (value < min)
  433. {
  434. valueTmp = value = min;
  435. widget->repaint();
  436. }
  437. else if (value > max)
  438. {
  439. valueTmp = value = max;
  440. widget->repaint();
  441. }
  442. minimum = min;
  443. maximum = max;
  444. }
  445. bool setValue(const float value2, const bool sendCallback)
  446. {
  447. if (d_isEqual(value, value2))
  448. return false;
  449. valueTmp = value = value2;
  450. widget->repaint();
  451. if (sendCallback && callback != nullptr)
  452. {
  453. try {
  454. callback->knobValueChanged(widget, value);
  455. } DISTRHO_SAFE_EXCEPTION("KnobEventHandler::setValue");
  456. }
  457. return true;
  458. }
  459. };
  460. // --------------------------------------------------------------------------------------------------------------------
  461. KnobEventHandler::KnobEventHandler(SubWidget* const self)
  462. : pData(new PrivateData(this, self)) {}
  463. KnobEventHandler::KnobEventHandler(SubWidget* const self, const KnobEventHandler& other)
  464. : pData(new PrivateData(this, self, other.pData)) {}
  465. KnobEventHandler& KnobEventHandler::operator=(const KnobEventHandler& other)
  466. {
  467. pData->assignFrom(other.pData);
  468. return *this;
  469. }
  470. KnobEventHandler::~KnobEventHandler()
  471. {
  472. delete pData;
  473. }
  474. bool KnobEventHandler::isInteger() const noexcept
  475. {
  476. return d_isEqual(pData->step, 1.f);
  477. }
  478. float KnobEventHandler::getValue() const noexcept
  479. {
  480. return pData->value;
  481. }
  482. bool KnobEventHandler::setValue(const float value, const bool sendCallback) noexcept
  483. {
  484. return pData->setValue(value, sendCallback);
  485. }
  486. float KnobEventHandler::getNormalizedValue() const noexcept
  487. {
  488. return pData->getNormalizedValue();
  489. }
  490. void KnobEventHandler::setDefault(const float def) noexcept
  491. {
  492. pData->valueDef = def;
  493. pData->usingDefault = true;
  494. }
  495. void KnobEventHandler::setRange(const float min, const float max) noexcept
  496. {
  497. pData->setRange(min, max);
  498. }
  499. void KnobEventHandler::setStep(const float step) noexcept
  500. {
  501. pData->step = step;
  502. }
  503. void KnobEventHandler::setUsingLogScale(const bool yesNo) noexcept
  504. {
  505. pData->usingLog = yesNo;
  506. }
  507. KnobEventHandler::Orientation KnobEventHandler::getOrientation() const noexcept
  508. {
  509. return pData->orientation;
  510. }
  511. void KnobEventHandler::setOrientation(const Orientation orientation) noexcept
  512. {
  513. pData->orientation = orientation;
  514. }
  515. void KnobEventHandler::setCallback(Callback* const callback) noexcept
  516. {
  517. pData->callback = callback;
  518. }
  519. bool KnobEventHandler::mouseEvent(const Widget::MouseEvent& ev)
  520. {
  521. return pData->mouseEvent(ev);
  522. }
  523. bool KnobEventHandler::motionEvent(const Widget::MotionEvent& ev)
  524. {
  525. return pData->motionEvent(ev);
  526. }
  527. bool KnobEventHandler::scrollEvent(const Widget::ScrollEvent& ev)
  528. {
  529. return pData->scrollEvent(ev);
  530. }
  531. KnobEventHandler::State KnobEventHandler::getState() const noexcept
  532. {
  533. return static_cast<State>(pData->state);
  534. }
  535. // --------------------------------------------------------------------------------------------------------------------
  536. END_NAMESPACE_DGL