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.

677 lines
18KB

  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 accel;
  226. float minimum;
  227. float maximum;
  228. float step;
  229. float value;
  230. float valueDef;
  231. float valueTmp;
  232. bool usingDefault;
  233. bool usingLog;
  234. Orientation orientation;
  235. int state;
  236. double lastX;
  237. double lastY;
  238. uint lastClickTime;
  239. PrivateData(KnobEventHandler* const s, SubWidget* const w)
  240. : self(s),
  241. widget(w),
  242. callback(nullptr),
  243. accel(200.f),
  244. minimum(0.f),
  245. maximum(1.f),
  246. step(0.0f),
  247. value(0.5f),
  248. valueDef(value),
  249. valueTmp(value),
  250. usingDefault(false),
  251. usingLog(false),
  252. orientation(Vertical),
  253. state(kKnobStateDefault),
  254. lastX(0.0),
  255. lastY(0.0),
  256. lastClickTime(0) {}
  257. PrivateData(KnobEventHandler* const s, SubWidget* const w, PrivateData* const other)
  258. : self(s),
  259. widget(w),
  260. callback(other->callback),
  261. accel(other->accel),
  262. minimum(other->minimum),
  263. maximum(other->maximum),
  264. step(other->step),
  265. value(other->value),
  266. valueDef(other->valueDef),
  267. valueTmp(value),
  268. usingDefault(other->usingDefault),
  269. usingLog(other->usingLog),
  270. orientation(other->orientation),
  271. state(kKnobStateDefault),
  272. lastX(0.0),
  273. lastY(0.0),
  274. lastClickTime(0) {}
  275. void assignFrom(PrivateData* const other)
  276. {
  277. callback = other->callback;
  278. accel = other->accel;
  279. minimum = other->minimum;
  280. maximum = other->maximum;
  281. step = other->step;
  282. value = other->value;
  283. valueDef = other->valueDef;
  284. valueTmp = value;
  285. usingDefault = other->usingDefault;
  286. usingLog = other->usingLog;
  287. orientation = other->orientation;
  288. state = kKnobStateDefault;
  289. lastX = 0.0;
  290. lastY = 0.0;
  291. lastClickTime = 0;
  292. }
  293. inline float logscale(const float v) const
  294. {
  295. const float b = std::log(maximum/minimum)/(maximum-minimum);
  296. const float a = maximum/std::exp(maximum*b);
  297. return a * std::exp(b*v);
  298. }
  299. inline float invlogscale(const float v) const
  300. {
  301. const float b = std::log(maximum/minimum)/(maximum-minimum);
  302. const float a = maximum/std::exp(maximum*b);
  303. return std::log(v/a)/b;
  304. }
  305. bool mouseEvent(const Widget::MouseEvent& ev)
  306. {
  307. if (ev.button != 1)
  308. return false;
  309. if (ev.press)
  310. {
  311. if (! widget->contains(ev.pos))
  312. return false;
  313. if ((ev.mod & kModifierShift) != 0 && usingDefault)
  314. {
  315. setValue(valueDef, true);
  316. valueTmp = value;
  317. return true;
  318. }
  319. lastX = ev.pos.getX();
  320. lastY = ev.pos.getY();
  321. if (lastClickTime > 0 && ev.time > lastClickTime && ev.time - lastClickTime <= 300)
  322. {
  323. lastClickTime = 0;
  324. if (callback != nullptr)
  325. callback->knobDoubleClicked(widget);
  326. return true;
  327. }
  328. lastClickTime = ev.time;
  329. state |= kKnobStateDragging;
  330. widget->repaint();
  331. if (callback != nullptr)
  332. callback->knobDragStarted(widget);
  333. return true;
  334. }
  335. else if (state & kKnobStateDragging)
  336. {
  337. state &= ~kKnobStateDragging;
  338. widget->repaint();
  339. if (callback != nullptr)
  340. callback->knobDragFinished(widget);
  341. return true;
  342. }
  343. return false;
  344. }
  345. bool motionEvent(const Widget::MotionEvent& ev)
  346. {
  347. if ((state & kKnobStateDragging) == 0x0)
  348. return false;
  349. bool doVal = false;
  350. float d, value2 = 0.0f;
  351. switch (orientation)
  352. {
  353. case Horizontal:
  354. if (const double movX = ev.pos.getX() - lastX)
  355. {
  356. d = (ev.mod & kModifierControl) ? accel * 10.f : accel;
  357. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(movX));
  358. doVal = true;
  359. }
  360. break;
  361. case Vertical:
  362. if (const double movY = lastY - ev.pos.getY())
  363. {
  364. d = (ev.mod & kModifierControl) ? accel * 10.f : accel;
  365. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(movY));
  366. doVal = true;
  367. }
  368. break;
  369. case Both:
  370. const double movX = ev.pos.getX() - lastX;
  371. const double movY = lastY - ev.pos.getY();
  372. if (const double mov = movX + movY)
  373. {
  374. d = (ev.mod & kModifierControl) ? accel * 10.f : accel;
  375. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(mov));
  376. doVal = true;
  377. }
  378. break;
  379. }
  380. if (! doVal)
  381. return false;
  382. if (usingLog)
  383. value2 = logscale(value2);
  384. if (value2 < minimum)
  385. {
  386. valueTmp = value2 = minimum;
  387. }
  388. else if (value2 > maximum)
  389. {
  390. valueTmp = value2 = maximum;
  391. }
  392. else
  393. {
  394. valueTmp = value2;
  395. if (d_isNotZero(step))
  396. {
  397. const float rest = std::fmod(value2, step);
  398. value2 -= rest + (rest > step/2.0f ? step : 0.0f);
  399. if (value2 < minimum)
  400. valueTmp = value2 = minimum;
  401. else if (value2 > maximum)
  402. valueTmp = value2 = maximum;
  403. }
  404. }
  405. setValue(value2, true);
  406. lastX = ev.pos.getX();
  407. lastY = ev.pos.getY();
  408. return true;
  409. }
  410. bool scrollEvent(const Widget::ScrollEvent& ev)
  411. {
  412. if (! widget->contains(ev.pos))
  413. return false;
  414. const float dir = (ev.delta.getY() > 0.f) ? 1.f : -1.f;
  415. const float d = (ev.mod & kModifierControl) ? accel * 10.f : accel;
  416. float value2 = (usingLog ? invlogscale(valueTmp) : valueTmp)
  417. + ((maximum - minimum) / d * 10.f * dir);
  418. if (usingLog)
  419. value2 = logscale(value2);
  420. if (value2 < minimum)
  421. {
  422. valueTmp = value2 = minimum;
  423. }
  424. else if (value2 > maximum)
  425. {
  426. valueTmp = value2 = maximum;
  427. }
  428. else
  429. {
  430. valueTmp = value2;
  431. if (d_isNotZero(step))
  432. {
  433. const float rest = std::fmod(value2, step);
  434. value2 = value2 - rest + (rest > step/2.0f ? step : 0.0f);
  435. }
  436. }
  437. setValue(value2, true);
  438. return true;
  439. }
  440. float getNormalizedValue() const noexcept
  441. {
  442. const float diff = maximum - minimum;
  443. return ((usingLog ? invlogscale(value) : value) - minimum) / diff;
  444. }
  445. void setRange(const float min, const float max) noexcept
  446. {
  447. DISTRHO_SAFE_ASSERT_RETURN(max > min,);
  448. if (value < min)
  449. {
  450. valueTmp = value = min;
  451. widget->repaint();
  452. }
  453. else if (value > max)
  454. {
  455. valueTmp = value = max;
  456. widget->repaint();
  457. }
  458. minimum = min;
  459. maximum = max;
  460. }
  461. bool setValue(const float value2, const bool sendCallback)
  462. {
  463. if (d_isEqual(value, value2))
  464. return false;
  465. valueTmp = value = value2;
  466. widget->repaint();
  467. if (sendCallback && callback != nullptr)
  468. {
  469. try {
  470. callback->knobValueChanged(widget, value);
  471. } DISTRHO_SAFE_EXCEPTION("KnobEventHandler::setValue");
  472. }
  473. return true;
  474. }
  475. };
  476. // --------------------------------------------------------------------------------------------------------------------
  477. KnobEventHandler::KnobEventHandler(SubWidget* const self)
  478. : pData(new PrivateData(this, self)) {}
  479. KnobEventHandler::KnobEventHandler(SubWidget* const self, const KnobEventHandler& other)
  480. : pData(new PrivateData(this, self, other.pData)) {}
  481. KnobEventHandler& KnobEventHandler::operator=(const KnobEventHandler& other)
  482. {
  483. pData->assignFrom(other.pData);
  484. return *this;
  485. }
  486. KnobEventHandler::~KnobEventHandler()
  487. {
  488. delete pData;
  489. }
  490. bool KnobEventHandler::isInteger() const noexcept
  491. {
  492. return d_isEqual(pData->step, 1.f);
  493. }
  494. float KnobEventHandler::getValue() const noexcept
  495. {
  496. return pData->value;
  497. }
  498. bool KnobEventHandler::setValue(const float value, const bool sendCallback) noexcept
  499. {
  500. return pData->setValue(value, sendCallback);
  501. }
  502. float KnobEventHandler::getNormalizedValue() const noexcept
  503. {
  504. return pData->getNormalizedValue();
  505. }
  506. void KnobEventHandler::setDefault(const float def) noexcept
  507. {
  508. pData->valueDef = def;
  509. pData->usingDefault = true;
  510. }
  511. void KnobEventHandler::setRange(const float min, const float max) noexcept
  512. {
  513. pData->setRange(min, max);
  514. }
  515. void KnobEventHandler::setStep(const float step) noexcept
  516. {
  517. pData->step = step;
  518. }
  519. void KnobEventHandler::setUsingLogScale(const bool yesNo) noexcept
  520. {
  521. pData->usingLog = yesNo;
  522. }
  523. KnobEventHandler::Orientation KnobEventHandler::getOrientation() const noexcept
  524. {
  525. return pData->orientation;
  526. }
  527. void KnobEventHandler::setOrientation(const Orientation orientation) noexcept
  528. {
  529. pData->orientation = orientation;
  530. }
  531. void KnobEventHandler::setCallback(Callback* const callback) noexcept
  532. {
  533. pData->callback = callback;
  534. }
  535. void KnobEventHandler::setMouseDeceleration(float accel) noexcept
  536. {
  537. pData->accel = accel;
  538. }
  539. bool KnobEventHandler::mouseEvent(const Widget::MouseEvent& ev)
  540. {
  541. return pData->mouseEvent(ev);
  542. }
  543. bool KnobEventHandler::motionEvent(const Widget::MotionEvent& ev)
  544. {
  545. return pData->motionEvent(ev);
  546. }
  547. bool KnobEventHandler::scrollEvent(const Widget::ScrollEvent& ev)
  548. {
  549. return pData->scrollEvent(ev);
  550. }
  551. KnobEventHandler::State KnobEventHandler::getState() const noexcept
  552. {
  553. return static_cast<State>(pData->state);
  554. }
  555. // --------------------------------------------------------------------------------------------------------------------
  556. END_NAMESPACE_DGL