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.

633 lines
16KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 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. if (orientation == Horizontal)
  336. {
  337. if (const double movX = ev.pos.getX() - lastX)
  338. {
  339. d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
  340. value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + (float(maximum - minimum) / d * float(movX));
  341. doVal = true;
  342. }
  343. }
  344. else if (orientation == Vertical)
  345. {
  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. }
  353. if (! doVal)
  354. return false;
  355. if (usingLog)
  356. value2 = logscale(value2);
  357. if (value2 < minimum)
  358. {
  359. valueTmp = value2 = minimum;
  360. }
  361. else if (value2 > maximum)
  362. {
  363. valueTmp = value2 = maximum;
  364. }
  365. else
  366. {
  367. valueTmp = value2;
  368. if (d_isNotZero(step))
  369. {
  370. const float rest = std::fmod(value2, step);
  371. value2 -= rest + (rest > step/2.0f ? step : 0.0f);
  372. }
  373. }
  374. setValue(value2, true);
  375. lastX = ev.pos.getX();
  376. lastY = ev.pos.getY();
  377. return true;
  378. }
  379. bool scrollEvent(const Widget::ScrollEvent& ev)
  380. {
  381. if (! widget->contains(ev.pos))
  382. return false;
  383. const float dir = (ev.delta.getY() > 0.f) ? 1.f : -1.f;
  384. const float d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
  385. float value2 = (usingLog ? invlogscale(valueTmp) : valueTmp)
  386. + ((maximum - minimum) / d * 10.f * dir);
  387. if (usingLog)
  388. value2 = logscale(value2);
  389. if (value2 < minimum)
  390. {
  391. valueTmp = value2 = minimum;
  392. }
  393. else if (value2 > maximum)
  394. {
  395. valueTmp = value2 = maximum;
  396. }
  397. else
  398. {
  399. valueTmp = value2;
  400. if (d_isNotZero(step))
  401. {
  402. const float rest = std::fmod(value2, step);
  403. value2 = value2 - rest + (rest > step/2.0f ? step : 0.0f);
  404. }
  405. }
  406. setValue(value2, true);
  407. return true;
  408. }
  409. float getNormalizedValue() const noexcept
  410. {
  411. const float diff = maximum - minimum;
  412. return ((usingLog ? invlogscale(value) : value) - minimum) / diff;
  413. }
  414. void setRange(const float min, const float max) noexcept
  415. {
  416. DISTRHO_SAFE_ASSERT_RETURN(max > min,);
  417. if (value < min)
  418. {
  419. valueTmp = value = min;
  420. widget->repaint();
  421. }
  422. else if (value > max)
  423. {
  424. valueTmp = value = max;
  425. widget->repaint();
  426. }
  427. minimum = min;
  428. maximum = max;
  429. }
  430. bool setValue(const float value2, const bool sendCallback)
  431. {
  432. if (d_isEqual(value, value2))
  433. return false;
  434. valueTmp = value = value2;
  435. widget->repaint();
  436. if (sendCallback && callback != nullptr)
  437. {
  438. try {
  439. callback->knobValueChanged(widget, value);
  440. } DISTRHO_SAFE_EXCEPTION("KnobEventHandler::setValue");
  441. }
  442. return true;
  443. }
  444. };
  445. // --------------------------------------------------------------------------------------------------------------------
  446. KnobEventHandler::KnobEventHandler(SubWidget* const self)
  447. : pData(new PrivateData(this, self)) {}
  448. KnobEventHandler::KnobEventHandler(SubWidget* const self, const KnobEventHandler& other)
  449. : pData(new PrivateData(this, self, other.pData)) {}
  450. KnobEventHandler& KnobEventHandler::operator=(const KnobEventHandler& other)
  451. {
  452. pData->assignFrom(other.pData);
  453. return *this;
  454. }
  455. KnobEventHandler::~KnobEventHandler()
  456. {
  457. delete pData;
  458. }
  459. float KnobEventHandler::getValue() const noexcept
  460. {
  461. return pData->value;
  462. }
  463. bool KnobEventHandler::setValue(const float value, const bool sendCallback) noexcept
  464. {
  465. return pData->setValue(value, sendCallback);
  466. }
  467. float KnobEventHandler::getNormalizedValue() const noexcept
  468. {
  469. return pData->getNormalizedValue();
  470. }
  471. void KnobEventHandler::setDefault(const float def) noexcept
  472. {
  473. pData->valueDef = def;
  474. pData->usingDefault = true;
  475. }
  476. void KnobEventHandler::setRange(const float min, const float max) noexcept
  477. {
  478. pData->setRange(min, max);
  479. }
  480. void KnobEventHandler::setStep(const float step) noexcept
  481. {
  482. pData->step = step;
  483. }
  484. void KnobEventHandler::setUsingLogScale(const bool yesNo) noexcept
  485. {
  486. pData->usingLog = yesNo;
  487. }
  488. KnobEventHandler::Orientation KnobEventHandler::getOrientation() const noexcept
  489. {
  490. return pData->orientation;
  491. }
  492. void KnobEventHandler::setOrientation(const Orientation orientation) noexcept
  493. {
  494. if (pData->orientation == orientation)
  495. return;
  496. pData->orientation = orientation;
  497. }
  498. void KnobEventHandler::setCallback(Callback* const callback) noexcept
  499. {
  500. pData->callback = callback;
  501. }
  502. bool KnobEventHandler::mouseEvent(const Widget::MouseEvent& ev)
  503. {
  504. return pData->mouseEvent(ev);
  505. }
  506. bool KnobEventHandler::motionEvent(const Widget::MotionEvent& ev)
  507. {
  508. return pData->motionEvent(ev);
  509. }
  510. bool KnobEventHandler::scrollEvent(const Widget::ScrollEvent& ev)
  511. {
  512. return pData->scrollEvent(ev);
  513. }
  514. KnobEventHandler::State KnobEventHandler::getState() const noexcept
  515. {
  516. return static_cast<State>(pData->state);
  517. }
  518. // --------------------------------------------------------------------------------------------------------------------
  519. END_NAMESPACE_DGL