1 module evael.graphics.gui.controls.Slider; 2 3 import std.algorithm : map; 4 import std.range : iota; 5 import std.array : array; 6 7 import evael.graphics.gui.controls.Container; 8 import evael.graphics.gui.controls.Button; 9 import evael.graphics.gui.controls.Panel; 10 11 import evael.utils.Math; 12 13 import evael.utils.Size; 14 import evael.utils.Color; 15 16 public class Slider : Container 17 { 18 private alias void delegate(Control sender, int value) OnValueChangeEvent; 19 private OnValueChangeEvent m_onValueChangeEvent; 20 21 /// Values 22 private int m_minimumValue, m_maximumValue; 23 24 /// Possible values' position 25 private int[] m_valuesPosition; 26 27 /// Current selected value 28 private int m_currentValueIndex; 29 30 /// Incrementation, formula is : controlWidth / maximumValue 31 private int m_incrementation; 32 33 private Button m_scrollButton; 34 35 public this(in float x, in float y, in int width) 36 { 37 this(vec2(x, y), Size!int(width + 20, 45)); 38 } 39 40 public this(in vec2 position, in Size!int size) 41 { 42 super(position, size); 43 44 this.m_opacity = 0; 45 46 Panel panel = new Panel(10, 20, size.width - 20, 5); 47 48 this.m_scrollButton = new Button(5, 16, 10, 16); 49 this.m_scrollButton.type = Button.Type.Icon; 50 51 this.addChild(panel); 52 this.addChild(this.m_scrollButton); 53 } 54 55 /** 56 * Renders the slider 57 */ 58 public override void draw(in float deltaTime) 59 { 60 super.draw(deltaTime); 61 } 62 63 64 65 /** 66 * Mouse enters in control's rect 67 * Params: 68 * mousePosition : mouse's position 69 */ 70 public override void onMouseMove(in ref vec2 mousePosition) 71 { 72 super.onMouseMove(mousePosition); 73 74 static vec2 lastMousePosition; 75 76 scope(exit) lastMousePosition = mousePosition; 77 78 if(this.m_scrollButton.isClicked && mousePosition.x != lastMousePosition.x) 79 { 80 bool change = false; 81 82 vec2 buttonPosition = this.m_scrollButton.realPosition; 83 84 // Slide to right 85 if(mousePosition.x > lastMousePosition.x && this.m_currentValueIndex < this.m_maximumValue + 1) 86 { 87 // We check if we reach half position for the next value 88 if(mousePosition.x > buttonPosition.x + (this.m_incrementation / 2)) 89 { 90 buttonPosition.x = (buttonPosition.x + this.m_incrementation); 91 this.m_currentValueIndex++; 92 93 change = true; 94 } 95 } 96 else if(mousePosition.x < lastMousePosition.x && this.m_currentValueIndex > 0) 97 { 98 if(mousePosition.x < buttonPosition.x - (this.m_incrementation / 2)) 99 { 100 buttonPosition.x = (buttonPosition.x - this.m_incrementation); 101 this.m_currentValueIndex--; 102 103 change = true; 104 } 105 } 106 107 // We update button's position and raise a new event if necessary 108 if(change) 109 { 110 this.m_scrollButton.realPosition = buttonPosition; 111 112 if(this.m_onValueChangeEvent !is null) 113 this.m_onValueChangeEvent(this, this.m_currentValueIndex); 114 } 115 } 116 } 117 118 /** 119 * Properties 120 */ 121 @property 122 public void onValueChangeEvent(OnValueChangeEvent callback) nothrow 123 { 124 this.m_onValueChangeEvent = callback; 125 } 126 127 @property 128 public void minimumValue(in int value) nothrow 129 { 130 this.m_minimumValue = value; 131 } 132 133 @property 134 public void maximumValue(in int value) nothrow 135 { 136 this.m_maximumValue = value; 137 138 this.m_incrementation = this.m_controls[0].size.width / value; 139 140 // this.m_values = iota(0, value + 1).map!(a => a * this.m_incrementation).array; 141 } 142 143 @property 144 public int value() const nothrow 145 { 146 return this.m_currentValueIndex; 147 } 148 }