1 /* 2 * slider.h 3 * DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath 4 * For more information, please visit http://dinisnoise.org/ 5 */ 6 7 8 #ifndef __slider 9 #define __slider 10 11 #include "widget.h" 12 #include "viewwin.h" 13 #include "utils.h" 14 #include "filled_button.h" 15 16 #include <algorithm> 17 #include <vector> 18 19 extern int mousex; 20 extern viewport view; 21 extern int lmb; 22 23 template <typename S> struct after_slide_lis { 24 virtual void slided (S& s) = 0; 25 }; 26 27 template <typename S> struct start_slide_lis { 28 virtual void start_slide (S& s) = 0; 29 }; 30 31 template <typename T> struct values { 32 33 T low, high, delta, val; 34 float amount; 35 36 values (T l = 0, T h = 1, T v = 0) { 37 set_limits (l, h); 38 *this = v; 39 } 40 Tvalues41 operator T() { 42 return ((T) val); 43 } 44 set_limitsvalues45 void set_limits (T l, T h) { 46 low = l; 47 high = h; 48 delta = high - low; 49 } 50 get_limitsvalues51 void get_limits (T& l, T& h) { 52 l = low; 53 h = high; 54 } 55 operatorvalues56 T operator() () const { return val; } 57 values& operator= (const T& v) { 58 val = v; 59 clamp<T> (low, val, high); 60 if (delta) amount = (val - low) * 1.0f / delta; else amount = 0; 61 return *this; 62 } 63 set_amountvalues64 void set_amount (float a) { 65 amount = a; 66 clamp<float> (0.0f, amount, 1.0f); 67 val = (T) (low + delta * amount); 68 } 69 get_amountvalues70 float get_amount () const { return amount; } 71 72 }; 73 74 template <typename T> struct slider : widget, move_listener { 75 76 values<T> vx; 77 int dx; 78 79 int sliding; 80 int lmb_clicked; 81 82 change_listener<slider> *chgl; 83 after_slide_lis<slider> *asl; 84 start_slide_lis<slider> *ssl; 85 86 filled_button sizer; 87 static const int spc = 10; 88 89 slider (int sv = 0, int w = 64, int h = 16) : widget (0, 0, w, h), vx (0, 0, 0), sliding(0), lmb_clicked(0) { 90 chgl = 0; 91 asl = 0; 92 set_sizer_visible (sv); 93 } 94 set_sizer_visibleslider95 void set_sizer_visible (int sv) { 96 sizer.visible = sv; 97 if (sizer.visible) { 98 sizer.set_moveable (1); 99 sizer.movlis = this; 100 } else { 101 sizer.set_moveable (0); 102 sizer.movlis = 0; 103 } 104 } 105 set_posslider106 void set_pos (int x, int y) { 107 widget::set_pos (x, y); 108 sizer.set_pos (extents.right + spc, extents.bottom); 109 } 110 set_rightslider111 void set_right (int r) { 112 set_extents (extents.left, extents.bottom, r, extents.top); 113 dx = vx.get_amount () * extents.width; 114 } 115 movedslider116 void moved () { 117 int mpx = mousex - movr.prevx; 118 if (mpx) { 119 sizer.set_pos (mousex, extents.bottom); 120 int msx = mousex - spc; 121 if (msx > extents.left) set_right (msx); 122 } 123 } 124 handle_inputslider125 int handle_input () { 126 127 widget::handle_input (); 128 129 if (sizer.visible && sizer.handle_input ()) return 1; 130 131 int ret = 0; 132 133 if (lmb) { 134 if (lmb_clicked == 0) { 135 if (sliding) { 136 sliding = 0; 137 if (asl) asl->slided (*this); 138 defocus (this); 139 ret = 1; 140 } else { 141 if (hover) { 142 sliding = 1; 143 if (ssl) ssl->start_slide (*this); 144 widget::focus = this; 145 ret = 1; 146 } 147 } 148 lmb_clicked = 1; 149 } 150 } else { 151 if (sliding) { 152 int nu_dx = mousex - extents.left; 153 clamp (0, nu_dx, extents.width); 154 if (nu_dx != dx) { 155 dx = nu_dx; 156 vx.set_amount (dx * extents.width_1); 157 if (chgl) chgl->changed (*this); 158 } 159 } else ret = 0; 160 lmb_clicked = 0; 161 } 162 163 return ret; 164 165 } 166 drawslider167 void draw () { 168 169 widget::draw (); 170 171 glEnable (GL_BLEND); 172 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 173 174 const color& c = clr; 175 176 glColor4f (c.r, c.g, c.b, (GLfloat) 0.15f); 177 178 const box<int>& e = extents; 179 glRecti (e.left, e.bottom, e.right, e.top); 180 181 glColor4f (c.r, c.g, c.b, 1); 182 glRecti (e.left, e.bottom, e.left + dx, e.top); 183 184 glDisable (GL_BLEND); 185 186 if (sizer.visible) sizer.draw (); 187 188 } 189 updateslider190 void update () { 191 float amount = vx.get_amount (); 192 const box<int>& e = extents; 193 dx = (int) (amount * e.width); 194 } 195 196 void set_listener (change_listener<slider>* _chgl, start_slide_lis<slider>* _ssl = 0, after_slide_lis<slider>* _asl = 0) { 197 chgl = _chgl; 198 ssl = _ssl; 199 asl = _asl; 200 } 201 operatorslider202 T operator() () const {return vx (); } 203 set_valslider204 void set_val (const T& t) { 205 vx = t; 206 update (); 207 } 208 set_limitsslider209 void set_limits (T l, T h) { 210 vx = values<T> (l, h, vx()); 211 update (); 212 } 213 get_limitsslider214 void get_limits (T& l, T& h) { 215 vx.get_limits (l, h); 216 } 217 }; 218 219 #define MAKE_SLIDER_LISTENER(name,var) struct name : change_listener< slider<float> > { void changed (slider<float>& s); }; name var; 220 #define SLIDER_CHANGED(scope,name) void scope::name::changed (slider<float>& s) 221 #define MAKE_AFTER_SLIDE_LISTENER(name,type,var) struct name : after_slide_lis< type > { void slided (type& s); }; name var; 222 #define SLIDED(scope,name,type) void scope::name::slided (type& s) 223 #define MAKE_START_SLIDE_LISTENER(name,type,var) struct name : start_slide_lis< type > { void start_slide (type& s); }; name var; 224 #define START_SLIDE(scope,name,type) void scope::name::start_slide (type& s) 225 226 #endif 227