1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 2 3 #ifndef SPECTMORPH_SLIDER_HH 4 #define SPECTMORPH_SLIDER_HH 5 6 #include <math.h> 7 #include "smmath.hh" 8 9 namespace SpectMorph 10 { 11 12 class Slider : public Widget 13 { 14 double m_value; 15 bool highlight = false; 16 bool mouse_down = false; 17 int int_range_min = 0; 18 int int_range_max = 0; 19 20 public: 21 Signal<double> signal_value_changed; 22 Signal<int> signal_int_value_changed; 23 24 Slider (Widget *parent, double value) : 25 Widget (parent), 26 m_value (value) 27 { 28 } 29 void 30 set_int_range (int mn, int mx) 31 { 32 int_range_min = mn; 33 int_range_max = mx; 34 } 35 void 36 set_int_value (int ivalue) 37 { 38 m_value = double (ivalue - int_range_min) / (int_range_max - int_range_min); 39 update(); 40 } 41 void 42 draw (const DrawEvent& devent) override 43 { 44 cairo_t *cr = devent.cr; 45 DrawUtils du (cr); 46 47 double H = 6; // height of slider thing 48 double C = 6; 49 double value_pos = C + (width() - C * 2) * m_value; 50 51 Color slider_color_l = ThemeColor::SLIDER; 52 if (enabled()) 53 { 54 if (highlight) 55 slider_color_l = slider_color_l.lighter(); 56 } 57 else 58 slider_color_l.set_rgb (0.4, 0.4, 0.4); 59 du.round_box (0, height() / 2 - H / 2, value_pos, H, 1, 2, slider_color_l.darker(), slider_color_l); 60 61 Color slider_color_r (0.3, 0.3, 0.3); 62 if (highlight) 63 slider_color_r = slider_color_r.lighter(); 64 du.round_box (value_pos, height() / 2 - H / 2, (width() - value_pos), H, 1, 2, slider_color_r.darker(), slider_color_r); 65 66 if (enabled()) 67 { 68 if (highlight || mouse_down) 69 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); 70 else 71 cairo_set_source_rgb (cr, 0.8, 0.8, 0.8); 72 } 73 else 74 { 75 cairo_set_source_rgb (cr, 0.4, 0.4, 0.4); 76 } 77 cairo_arc (cr, value_pos, height() / 2, C, 0, 2 * M_PI); 78 cairo_fill (cr); 79 } 80 void 81 slider_value_from_x (double x) 82 { 83 double C = 6; 84 m_value = sm_bound (0.0, (x - C) / (width() - C * 2), 1.0); 85 86 /* optional: only allow discrete integer values */ 87 if (int_range_min != int_range_max) 88 { 89 int ivalue = int_range_min + sm_round_positive (m_value * (int_range_max - int_range_min)); 90 m_value = double (ivalue - int_range_min) / (int_range_max - int_range_min); 91 92 signal_int_value_changed (ivalue); 93 } 94 95 signal_value_changed (m_value); 96 } 97 void 98 mouse_move (const MouseEvent& event) override 99 { 100 if (mouse_down) 101 { 102 slider_value_from_x (event.x); 103 update(); 104 } 105 } 106 void 107 mouse_press (const MouseEvent& event) override 108 { 109 if (event.button == LEFT_BUTTON) 110 { 111 slider_value_from_x (event.x); 112 mouse_down = true; 113 update(); 114 } 115 } 116 void 117 mouse_release (const MouseEvent& event) override 118 { 119 if (event.button == LEFT_BUTTON) 120 { 121 mouse_down = false; 122 update(); 123 } 124 } 125 void 126 enter_event() override 127 { 128 highlight = true; 129 update(); 130 } 131 void 132 leave_event() override 133 { 134 highlight = false; 135 update(); 136 } 137 void 138 set_value (double v) 139 { 140 m_value = v; 141 update(); 142 } 143 double 144 value() const 145 { 146 return m_value; 147 } 148 }; 149 150 } 151 152 #endif 153