12. November 2010
I designed my sliders with scalable (length and height) bezier curves. The nob adapts and grows in length and width depending on the slider value. They also have a glowing mouse-over function. The checkbox is a actually a 'checkcircle'. it glows when rolled-over and fills with a color when pressed. optionally, one can get a boolean from the checkbox class to check if it has been activated. Doubleclick was done by checking a time difference (here max. 150ms). An impulse-like circle is shown at the last clicked mouse coordinates. It dissapears when re-clicked anywhere. In the doubleclick class, there is also a method which returns a boolean to check if it has been double-clicked or not. source code: codingSpace18 main class:/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * GUI - main class * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ //sliders Slider sliderR = null; Slider sliderG = null; Slider sliderB = null; //checkboxes Checkbox checkboxA = null; Checkbox checkboxB = null; //double click DoubleClick doubleClick = null; boolean checkDoubleClick = false; float mX, mY; //for doubleclick void setup() { size(400, 400); //parameter: [x, y, width, height, start value (0..1)] sliderR = new Slider(20,50,50,20,.5); sliderG = new Slider(150,50,100,80,.5); sliderB = new Slider(250,50,300,40,.5); //parameter: [x,y,diameter] checkboxA = new Checkbox(50, 300, 20); checkboxB = new Checkbox(150, 300, 50); doubleClick = new DoubleClick(); } void draw() { //background(sliderR.pos() * 255,sliderG.pos() * 255,sliderB.pos() * 255); background(240, 240, 240, 25); sliderR.draw(); sliderG.draw(); sliderB.draw(); checkboxA.draw(); checkboxB.draw(); //check if doubleclicked if(checkDoubleClick) doubleClick.ping(); //returns an impulse-like ellipse at the last mouse position. stops when clicked anywhere sliderR.fillColor(sliderR.pos() * 255, 0, 0, 255); //red and alpha sliderG.fillColor(0, sliderG.pos() * 255, 0, 255); //green and alpha sliderB.fillColor(0, 0, sliderB.pos() * 255, 255); //blue and alpha sliderR.mouseOver(mouseX, mouseY); sliderG.mouseOver(mouseX, mouseY); sliderB.mouseOver(mouseX, mouseY); //glow on mouse-over checkboxA.mouseOver(mouseX,mouseY); checkboxB.mouseOver(mouseX,mouseY); } void mousePressed() { sliderR.mousePos(mouseX,mouseY,true); sliderG.mousePos(mouseX,mouseY,true); sliderB.mousePos(mouseX,mouseY,true); //activate (fill) or deactivate( nofill) checkbox checkboxA.mousePos(mouseX,mouseY); checkboxB.mousePos(mouseX,mouseY); // send doubleclick request. returns a boolean checkDoubleClick = doubleClick.checkDoubleClick(millis()); if(checkDoubleClick) { mX = mouseX; mY = mouseY; } } void mouseDragged() { sliderR.mousePos(mouseX,mouseY,true); sliderG.mousePos(mouseX,mouseY,true); sliderB.mousePos(mouseX,mouseY,true); }slider class:
/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * GUI - Slider * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ class Slider { PVector _p1; PVector _p2; float[] _a = new float[4]; int _w; int _h; float _pos; Slider(int x,int y,int h,int w,float pos) { _p1 = new PVector(x + w * 0.5, y); _p2 = new PVector(x + w *.5, y + h); _w = w; _h = h; _pos = pos; if(_pos > 1.0) _pos = 1.0; else if(_pos < 0.0) _pos = 0.0; } float pos() { return _pos; } //fill color void fillColor(float c1, float c2, float c3, float a) { _a[0] = c1; _a[1] = c2; _a[2] = c3; _a[3] = a; } boolean isHit(int x,int y) { if(x > _p1.x - 20 && x < _p1.x + 20 && y > _p1.y && y < _p2.y) { return true; } else { return false; } } void draw() { pushStyle(); drawSlider(); drawKnob(); popStyle(); } void drawSlider() { noFill(); stroke(_a[0], _a[1], _a[2], _a[3]); smooth(); strokeWeight(2); bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/10.0), _p1.y + (_h/8.0), _p2.x-(_w/10.0), _p2.y-(_h/8.0), _p2.x-(_w/2.0), _p2.y); //left side bezier(_p1.x+(_w/2.0), _p1.y, _p1.x+(_w/10.0), _p1.y + (_h/8.0), _p2.x +(_w/10.0), _p2.y-(_h/8.0), _p2.x+(_w/2.0), _p2.y); //right side bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/2.0), _p1.y); //top bezier(_p2.x-(_w/2.0), _p2.y, _p2.x-(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/2.0), _p2.y); //bottom } void drawKnob() { stroke(0, 0,0,100); PVector dir = PVector.sub(_p2,_p1); PVector pos = PVector.add( _p1, PVector.mult(dir,_pos)); noFill(); float bezier1= pos.x-(_w/10.0); float bezier2= pos.x+(_w/10.0); float bezier3= pos.x-(_w/10.0); float bezier4= pos.x+(_w/10.0); float bezier5= pos.y+(_h/20.0); float bezier6= pos.y-(_h/20.0); if(_pos >= 0.6) { bezier1 = map(_pos, 0.5, 1.0, pos.x-(_w/10.0), pos.x-(_w/3.0) ); //change bottom left side bezier2 = map(_pos, 0.5, 1.0, pos.x+(_w/10.0), pos.x+(_w/3.0) ); //change bottom right side bezier6 = map(_pos, 0.6, 0.0, pos.y+(_h/10.0), pos.y+(_h/3.0) ); //expand top middle } else bezier6= pos.y-(_h/20.0); if(_pos <= 0.6) { bezier3 = map(_pos, 0.5, 0.0, pos.x-(_w/10.0), pos.x-(_w/3.0)); //top left side bezier4 = map(_pos, 0.5, 0.0, pos.x+(_w/10.0), pos.x+(_w/3.0)); ///top right side bezier5 = map(_pos, 0.6, 1.0, pos.y-(_h/50.0), pos.y-(_h/3.0) ); //expand bottom middle } else bezier5= pos.y+(_h/20.0); rect(pos.x-3, pos.y-2, 6, 4); bezier(bezier3, pos.y-4, pos.x-(_w/15.0), bezier6, pos.x+(_w/15.0), bezier6, bezier4, pos.y-4); //top arc bezier(bezier1, pos.y+4, pos.x-(_w/15.0), bezier5, pos.x+(_w/15.0),bezier5, bezier2, pos.y+4); //bottom arc bezier(bezier3, pos.y-4, pos.x-(_w/10.0), pos.y-2, pos.x-(_w/10.0), pos.y+2, bezier1, pos.y+4); //left side arc bezier(bezier4, pos.y-4, pos.x+(_w/10.0), pos.y-2, pos.x+(_w/10.0), pos.y+2, bezier2, pos.y+4); //right side arc } void mousePos(int x,int y,boolean pressed) { if(pressed) { if(isHit(x,y)) { // move knob PVector dir = PVector.sub(_p1, _p2); //laenge der 2 punkte bestimmen _pos = 1.0 / dir.mag() * (y-_p1.y); //mapping im zahlenbereich (laenge in scalar) . mag (magnitude) berechnet die laenge in scalar (eine zahl) } } else { // mouse over } } void mouseOver(int x, int y) { if(isHit(x,y)) { noFill(); int t = 10; strokeWeight(t ); //fade float al=100; al-= (millis()%1000/10.0); stroke(_a[0], _a[1], _a[2],al); //as drawn at the beginning (can be different) bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/10.0), _p1.y + (_h/8.0), _p2.x-(_w/10.0), _p2.y-(_h/8.0), _p2.x-(_w/2.0), _p2.y); //left side bezier(_p1.x+(_w/2.0), _p1.y, _p1.x+(_w/10.0), _p1.y + (_h/8.0), _p2.x +(_w/10.0), _p2.y-(_h/8.0), _p2.x+(_w/2.0), _p2.y); //right side bezier(_p1.x-(_w/2.0), _p1.y, _p1.x-(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/5.0), _p1.y-(_h/12), _p1.x+(_w/2.0), _p1.y); //top bezier(_p2.x-(_w/2.0), _p2.y, _p2.x-(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/5.0), _p2.y+(_h/12), _p2.x+(_w/2.0), _p2.y); //bottom } } }checkbox class:
/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * GUI - main class * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ class Checkbox { PVector _p1; float _r; float _pos; boolean _activateFlag = false; int _time1; boolean _pressedOnce=false; Checkbox(int x,int y,int d) { _p1 = new PVector(x, y); //center of circle _r = d*0.5; } float pos() { return _pos; } //for main class if feedback is needed boolean isChecked(){ return _activateFlag; } boolean isHit(int x,int y) { if(x > _p1.x-_r && x < _p1.x+_r && y > _p1.y-_r && y < _p1.y+_r) { return true; } else { return false; } } void draw() { //_time = System.currentTimeMillis(); pushStyle(); drawCheckbox(); activate(_activateFlag); popStyle(); } void drawCheckbox() { noFill(); smooth(); strokeWeight(2); stroke(50,50,40,255); ellipse(_p1.x, _p1.y, _r*2, _r*2); } void mousePos(int x,int y) { if(isHit(x,y)) { _activateFlag = !_activateFlag; } } void mouseOver(int x, int y) { if(isHit(x,y)) { noFill(); strokeWeight(5); stroke(50,50,40,90); ellipse(_p1.x, _p1.y, (_r*2)+2, (_r*2)+2); } } void activate(boolean a) { if(a) { strokeWeight(5); fill(50,50,40,100); stroke(50,50,40,100); ellipse(_p1.x, _p1.y, (_r*2)+2, (_r*2)+2); text("active!", _p1.x,_p1.y+(_r*2)); } } }doubleclick class:
/* ---------------------------------------------------------------------------- * codingSpace18 * ---------------------------------------------------------------------------- * GUI - main class * ---------------------------------------------------------------------------- * prog: eddi.lecesne@zhdk.ch * 13.11.2010 * ---------------------------------------------------------------------------- */ class DoubleClick { int _time1; boolean _pressedOnce=false; DoubleClick() { } boolean checkDoubleClick(int time) { boolean drawFlag=false; if(!_pressedOnce) { _time1 = time; _pressedOnce=true; drawFlag=false; println("time 1: "+_time1 +" " +_pressedOnce); return false; } if(_pressedOnce) { int time2 = time; int delta = time2-_time1; println("delta (max 150ms): " +time2 +"-"+_time1+"="+delta); if(delta<=150) { println("doubleclicked in " + delta +"ms"); drawFlag=true; _pressedOnce=false; return true; } else { _time1 = time; _pressedOnce=true; return false; } } return false; } void ping() { smooth(); float a= (millis()%1000)/10.0; float b= (millis()%1000)/50.0; fill(203, 49, 49, a); stroke(203, 49, 49, a); ellipse(mX, mY, b, b); } }