1 module evael.graphics.gui.controls.ProgressBar;
2 
3 import std.conv : to;
4 import std.math;
5 
6 import evael.graphics.gui.controls.Control;
7 
8 import evael.utils.Math;
9 
10 import evael.utils.Size;
11 import evael.utils.Color;
12 
13 class ProgressBar : Control
14 {
15 	/// Max value
16 	private float m_maxValue;
17 
18 	/// Current value
19 	private float m_currentValue;
20 
21 	/// Bar position
22 	private vec2 m_barPosition;
23 
24 	/// Bar data in vbo
25 	private uint m_barVerticesPtr, m_barColorsPtr;
26 
27 	/// Value of 1 bar pixel
28 	private float m_indentation;
29 
30 	/// Draw progressbar background ?
31 	private bool m_drawBackground;
32 
33 	/// Draw animation bar ?
34 	private bool m_drawAnimationBar;
35 
36 	/// Filled bar
37 	private int m_barWidth;
38 
39 	/// Bar color
40 	private Color m_color;
41 
42 	public this(in float x, in float y, in int width, in int height = 22)
43 	{
44 		super(vec2(x, y), Size!int(width ,height));
45 
46 		this.m_name = "progressBar";
47 
48 		this.m_barPosition = vec2(2.0f, 2.0f);
49 
50 		this.m_maxValue = 100.0f;
51 		this.m_currentValue = 1.0f;
52 
53 		this.m_drawAnimationBar = false;
54 	}
55 
56 	/**
57 	 * Renders the ProgressBar
58 	 */
59 	public override void draw(in float deltaTime)
60 	{
61 		super.draw(deltaTime);
62 
63 		immutable x = this.m_realPosition.x;
64 		immutable y = this.m_realPosition.y;
65 		immutable w = this.m_size.width;
66 		immutable h = this.m_size.height;
67 
68 		immutable cornerRadius = this.m_theme.cornerRadius;
69 
70 		auto vg = this.m_nvg;
71 		
72 		// Filled part
73 		nvgBeginPath(vg);
74 		nvgRoundedRect(vg, x, y, this.m_barWidth, h, cornerRadius);
75 		nvgFillColor(vg, this.m_color.asNvg);
76 		nvgFill(vg);
77 	}
78 
79 	/**
80 	 * Initializes control
81 	 */
82 	public override void initialize()
83 	{
84 		super.initialize();
85 
86 		// Formula : (36000 / 70) / 70 = 514 / 70 = 7,xx, one pixel is ~7
87 		this.m_indentation = this.m_size.width / this.m_maxValue;
88 
89 		this.m_barWidth = cast(int)ceil(this.m_currentValue * this.m_indentation);
90 
91 		if(this.m_barWidth > this.m_size.width)
92 		{
93 			this.m_barWidth = this.m_size.width;
94 		}
95 
96 		this.m_tooltipText = this.m_currentValue.to!wstring() ~ " / " ~ this.m_maxValue.to!wstring();
97 	}
98 
99 	public void opUnary(string op)()
100 	{
101         mixin("this.value = this.m_currentValue " ~ op[0] ~ " 1;");
102     }
103 
104 	@property
105 	{
106 		public void maxValue(in float value)
107 		{
108 			this.m_maxValue = value;
109 
110 			// If control is already initialized, we have to update the bar manually
111 			if(this.m_initialized)
112 			{
113 				this.m_tooltipText = this.m_currentValue.to!wstring() ~ " / " ~ this.m_maxValue.to!wstring();
114 			}
115 		}
116 		
117 		public float maxValue() const nothrow @nogc
118 		{
119 			return this.m_maxValue;
120 		}
121 
122 		public void value(in float cvalue) nothrow @nogc
123 		{
124 			this.m_currentValue = cvalue;
125 
126 			if(this.m_initialized)
127 			{
128 				this.m_barWidth = cast(int)ceil(this.m_currentValue * this.m_indentation);
129 
130 				if(this.m_barWidth > this.m_size.width)
131 				{
132 					this.m_barWidth = this.m_size.width;
133 				}
134 			}
135 		}
136 
137 		public float value() const nothrow @nogc
138 		{
139 			return this.m_currentValue;
140 		}
141 		public void color()(in auto ref Color value)
142 		{
143 			this.m_color = value;
144 		}
145 	}
146 }