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.

279 lines
7.6KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. WidgetPDial.cpp - Fl_Dial With Custom Behavior
  4. Copyright (C) 2016 Mark McCurry
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. // generated by Fast Light User Interface Designer (fluid) version 1.0107f
  11. #include <cmath>
  12. #include <FL/fl_draw.H>
  13. #include "../Misc/Util.h"
  14. #include "WidgetPDial.h"
  15. //Copyright (c) 2003-2005 Nasca Octavian Paul
  16. //License: GNU GPL version 2 or later
  17. //static int numobj = 0;
  18. static float identity(float value)
  19. {
  20. return value;
  21. }
  22. WidgetPDial::WidgetPDial(int x, int y, int w, int h, const char *label)
  23. :Fl_Dial(x, y, w, h, label), reset_value(0), integer_step(true),
  24. use_rounding(false), oldvalue(0.0f), pos(false), textset(false),
  25. transform(identity)
  26. {
  27. //cout << "[" << label << "] There are now " << ++numobj << endl;
  28. Fl_Group *save = Fl_Group::current();
  29. tipwin = new TipWin();
  30. tipwin->hide();
  31. Fl_Group::current(save);
  32. }
  33. WidgetPDial::~WidgetPDial()
  34. {
  35. //cout << "There are now " << --numobj << endl;
  36. delete tipwin;
  37. }
  38. void WidgetPDial::set_rounding(unsigned int digits)
  39. {
  40. tipwin->set_rounding(digits);
  41. }
  42. #define MOD_MASK (FL_CTRL | FL_SHIFT)
  43. int WidgetPDial::handle(int event)
  44. {
  45. double dragsize, min = minimum(), max = maximum(), result;
  46. int dy;
  47. if (event == FL_RELEASE && Fl::event_clicks() == 1) {
  48. Fl::event_clicks(0);
  49. value(reset_value);
  50. tipwin->hide();
  51. value_damage();
  52. if (this->when() != 0)
  53. do_callback();
  54. return 1;
  55. }
  56. int old_mod_state;
  57. switch(event) {
  58. case FL_PUSH:
  59. mod_state = Fl::event_state() & MOD_MASK;
  60. if (!use_rounding) {
  61. if (integer_step)
  62. set_rounding(0);
  63. else if (mod_state == MOD_MASK)
  64. set_rounding(5);
  65. else if (mod_state == FL_SHIFT)
  66. set_rounding(4);
  67. else
  68. set_rounding((Fl::event_button3() || mod_state & FL_CTRL)
  69. ? 3 : 2);
  70. }
  71. oldvalue = value();
  72. old_y = Fl::event_y();
  73. case FL_DRAG:
  74. getPos();
  75. old_mod_state = mod_state;
  76. mod_state = Fl::event_state() & MOD_MASK;
  77. if (old_mod_state != mod_state) {
  78. oldvalue = value();
  79. old_y = Fl::event_y();
  80. if (!use_rounding) {
  81. if (integer_step)
  82. set_rounding(0);
  83. else if (mod_state == MOD_MASK)
  84. set_rounding(5);
  85. else if (mod_state == FL_SHIFT)
  86. set_rounding(4);
  87. else
  88. set_rounding((Fl::event_button3() ||
  89. mod_state & FL_CTRL)
  90. ? 3 : 2);
  91. }
  92. break;
  93. }
  94. dy = old_y - Fl::event_y();
  95. if (dy < -1 || dy > 1)
  96. Fl::event_clicks(0);
  97. if (!integer_step && mod_state == MOD_MASK)
  98. dragsize = 200000.0f;
  99. else if (!integer_step && mod_state == FL_SHIFT)
  100. dragsize = 20000.0f;
  101. else
  102. dragsize = (Fl::event_button3() || mod_state & MOD_MASK)
  103. ? 1000.0f : 200.0f;
  104. value(clamp(oldvalue + dy / dragsize * (max - min)));
  105. tipwin->showValue(transform(value()));
  106. value_damage();
  107. if(this->when() != 0)
  108. do_callback();
  109. return 1;
  110. case FL_MOUSEWHEEL:
  111. if (Fl::event_buttons() || Fl::belowmouse() != this)
  112. return 1;
  113. mod_state = Fl::event_state() & MOD_MASK;
  114. dy = - Fl::event_dy();
  115. if (integer_step) {
  116. if (!use_rounding) set_rounding(0);
  117. result = (int)(value() +
  118. dy * ((Fl::event_ctrl() ||
  119. Fl::event_shift()) ? 1 : 8));
  120. } else {
  121. float dragsize;
  122. if (mod_state == MOD_MASK) {
  123. dragsize = 100000.0;
  124. if (!use_rounding) set_rounding(5);
  125. } else if (mod_state == FL_SHIFT) {
  126. dragsize = 10000.0;
  127. if (!use_rounding) set_rounding(4);
  128. } else if (mod_state == FL_CTRL) {
  129. dragsize = 1000.0;
  130. if (!use_rounding) set_rounding(3);
  131. } else {
  132. dragsize = 100.0;
  133. if (!use_rounding) set_rounding(2);
  134. }
  135. result = value() + dy / dragsize * (max - min);
  136. }
  137. value(clamp(result));
  138. tipwin->showValue(transform(value()));
  139. value_damage();
  140. if(this->when() != 0)
  141. do_callback();
  142. return 1;
  143. case FL_ENTER:
  144. getPos();
  145. tipwin->showText();
  146. return 1;
  147. case FL_HIDE:
  148. case FL_LEAVE:
  149. tipwin->hide();
  150. resetPos();
  151. break;
  152. case FL_RELEASE:
  153. if (integer_step) {
  154. float rounded = floorf(value() + 0.5);
  155. value(clamp(rounded));
  156. }
  157. tipwin->hide();
  158. resetPos();
  159. if(this->when() == 0)
  160. do_callback();
  161. return 1;
  162. }
  163. return 0;
  164. //#endif
  165. }
  166. void WidgetPDial::draw()
  167. {
  168. #ifdef NTK_GUI
  169. box( FL_NO_BOX );
  170. Fl_Dial::draw();
  171. return;
  172. #else
  173. const int cx = x(), cy = y(), sx = w(), sy = h();
  174. const double a1 = angle1(), a2 = angle2();
  175. const double val = (value() - minimum()) / (maximum() - minimum());
  176. // even radius produces less artifacts if no antialiasing is avail
  177. const int rad = (sx > sy ? sy : sx) &~1;
  178. /* clears the button background */
  179. pdialcolor(160, 160, 160);
  180. fl_pie(cx - 2, cy - 2, rad + 4, rad + 4, 0, 360);
  181. /* dark outline */
  182. fl_color(60, 60, 60);
  183. fl_pie(cx - 1, cy - 1, rad + 2, rad + 2, 0, 360);
  184. /* Draws the button faceplate, min/max */
  185. pdialcolor(110, 110, 115);
  186. fl_pie(cx, cy, rad, rad, 270 - a2, 270 - a1);
  187. /* knob center */
  188. if (rad > 8) {
  189. pdialcolor(140, 140, 145);
  190. fl_pie(cx + 4, cy + 4, rad - 8, rad - 8, 0, 360);
  191. }
  192. /* value circle */
  193. double a = -(a2 - a1) * val - a1;
  194. fl_line_style(0, 2, 0);
  195. pdialcolor(0, 200, 0);
  196. fl_arc(cx + 1, cy + 1, rad - 2, rad - 2, a - 90, a1 - 180);
  197. fl_line_style(0);
  198. /* draw value line */
  199. int ll = rad/4;
  200. if (ll < 2) ll = 2;
  201. fl_push_matrix();
  202. fl_translate(cx + rad / 2, cy + rad / 2);
  203. fl_rotate(a - 90.0f);
  204. fl_translate(rad / 2, 0);
  205. fl_begin_polygon();
  206. pdialcolor(0, 0, 0);
  207. fl_vertex(-ll, 0);
  208. fl_vertex(0, 0);
  209. fl_end_polygon();
  210. fl_pop_matrix();
  211. #endif
  212. }
  213. void WidgetPDial::pdialcolor(int r, int g, int b)
  214. {
  215. if(active_r())
  216. fl_color(r, g, b);
  217. else
  218. fl_color(160 - (160 - r) / 3, 160 - (160 - b) / 3, 160 - (160 - b) / 3);
  219. }
  220. void WidgetPDial::tooltip(const char *c)
  221. {
  222. tipwin->setText(c);
  223. textset = true;
  224. }
  225. void WidgetPDial::getPos()
  226. {
  227. if(!pos) {
  228. tipwin->position(Fl::event_x_root(), Fl::event_y_root() + 20);
  229. pos = true;
  230. }
  231. }
  232. void WidgetPDial::resetPos()
  233. {
  234. pos = false;
  235. }
  236. void WidgetPDial::set_transform(float (*transformer)(float))
  237. {
  238. transform = transformer;
  239. use_rounding = true;
  240. }