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