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.

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