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.

790 lines
20KB

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