1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "GUI/BsGUISlider.h" |
4 | #include "GUI/BsGUISliderHandle.h" |
5 | #include "GUI/BsGUITexture.h" |
6 | #include "GUI/BsGUIDimensions.h" |
7 | #include "GUI/BsGUICommandEvent.h" |
8 | #include "GUI/BsGUIElementStyle.h" |
9 | |
10 | using namespace std::placeholders; |
11 | |
12 | namespace bs |
13 | { |
14 | GUISlider::GUISlider(bool horizontal, const String& styleName, const GUIDimensions& dimensions) |
15 | :GUIElementContainer(dimensions, styleName, GUIElementOption::AcceptsKeyFocus), mHorizontal(horizontal) |
16 | { |
17 | GUISliderHandleFlags flags = horizontal ? GUISliderHandleFlag::Horizontal : GUISliderHandleFlag::Vertical; |
18 | flags |= GUISliderHandleFlag::JumpOnClick; |
19 | |
20 | mSliderHandle = GUISliderHandle::create(flags, getSubStyleName(getHandleStyleType())); |
21 | mBackground = GUITexture::create(getSubStyleName(getBackgroundStyleType())); |
22 | mFillBackground = GUITexture::create(getSubStyleName(getFillStyleType())); |
23 | |
24 | mBackground->_setElementDepth(mSliderHandle->_getRenderElementDepthRange() + mFillBackground->_getRenderElementDepthRange()); |
25 | mFillBackground->_setElementDepth(mSliderHandle->_getRenderElementDepthRange()); |
26 | |
27 | _registerChildElement(mSliderHandle); |
28 | _registerChildElement(mBackground); |
29 | _registerChildElement(mFillBackground); |
30 | |
31 | mHandleMovedConn = mSliderHandle->onHandleMovedOrResized.connect(std::bind(&GUISlider::onHandleMoved, this, _1, _2)); |
32 | } |
33 | |
34 | GUISlider::~GUISlider() |
35 | { |
36 | mHandleMovedConn.disconnect(); |
37 | } |
38 | |
39 | const String& GUISlider::getHandleStyleType() |
40 | { |
41 | static String HANDLE_STYLE_TYPE = "SliderHandle" ; |
42 | return HANDLE_STYLE_TYPE; |
43 | } |
44 | |
45 | const String& GUISlider::getBackgroundStyleType() |
46 | { |
47 | static String BACKGROUND_STYLE_TYPE = "SliderBackground" ; |
48 | return BACKGROUND_STYLE_TYPE; |
49 | } |
50 | |
51 | const String& GUISlider::getFillStyleType() |
52 | { |
53 | static String FILL_STYLE_TYPE = "SliderFill" ; |
54 | return FILL_STYLE_TYPE; |
55 | } |
56 | |
57 | Vector2I GUISlider::_getOptimalSize() const |
58 | { |
59 | Vector2I optimalSize = mSliderHandle->_getOptimalSize(); |
60 | |
61 | Vector2I backgroundSize = mBackground->_getOptimalSize(); |
62 | optimalSize.x = std::max(optimalSize.x, backgroundSize.x); |
63 | optimalSize.y = std::max(optimalSize.y, backgroundSize.y); |
64 | |
65 | return optimalSize; |
66 | } |
67 | |
68 | void GUISlider::_updateLayoutInternal(const GUILayoutData& data) |
69 | { |
70 | GUILayoutData childData = data; |
71 | |
72 | if (mHorizontal) |
73 | { |
74 | Vector2I optimalSize = mBackground->_getOptimalSize(); |
75 | childData.area.height = optimalSize.y; |
76 | childData.area.y = data.area.y + (INT32)((data.area.height - childData.area.height) * 0.5f); |
77 | |
78 | childData.clipRect = data.area; |
79 | childData.clipRect.clip(data.clipRect); |
80 | |
81 | mBackground->_setLayoutData(childData); |
82 | |
83 | optimalSize = mSliderHandle->_getOptimalSize(); |
84 | childData.area.height = optimalSize.y; |
85 | childData.area.y = data.area.y + (INT32)((data.area.height - childData.area.height) * 0.5f); |
86 | |
87 | childData.clipRect = data.area; |
88 | childData.clipRect.clip(data.clipRect); |
89 | |
90 | mSliderHandle->_setLayoutData(childData); |
91 | UINT32 handleWidth = optimalSize.x; |
92 | |
93 | optimalSize = mFillBackground->_getOptimalSize(); |
94 | childData.area.height = optimalSize.y; |
95 | childData.area.y = data.area.y + (INT32)((data.area.height - childData.area.height) * 0.5f); |
96 | childData.area.width = mSliderHandle->getHandlePosPx() + handleWidth / 2; |
97 | |
98 | childData.clipRect = data.area; |
99 | childData.clipRect.clip(data.clipRect); |
100 | |
101 | mFillBackground->_setLayoutData(childData); |
102 | } |
103 | else |
104 | { |
105 | Vector2I optimalSize = mBackground->_getOptimalSize(); |
106 | childData.area.width = optimalSize.x; |
107 | childData.area.x = data.area.x + (INT32)((data.area.width - childData.area.width) * 0.5f); |
108 | |
109 | childData.clipRect = data.area; |
110 | childData.clipRect.clip(data.clipRect); |
111 | |
112 | mBackground->_setLayoutData(childData); |
113 | |
114 | optimalSize = mSliderHandle->_getOptimalSize(); |
115 | childData.area.width = optimalSize.x; |
116 | childData.area.x = data.area.x + (INT32)((data.area.width - childData.area.width) * 0.5f); |
117 | |
118 | childData.clipRect = data.area; |
119 | childData.clipRect.clip(data.clipRect); |
120 | |
121 | mSliderHandle->_setLayoutData(childData); |
122 | UINT32 handleHeight = optimalSize.y; |
123 | |
124 | optimalSize = mFillBackground->_getOptimalSize(); |
125 | childData.area.width = optimalSize.x; |
126 | childData.area.x = data.area.x + (INT32)((data.area.width - childData.area.width) * 0.5f); |
127 | childData.area.height = mSliderHandle->getHandlePosPx() + handleHeight / 2; |
128 | |
129 | childData.clipRect = data.area; |
130 | childData.clipRect.clip(data.clipRect); |
131 | |
132 | mFillBackground->_setLayoutData(childData); |
133 | } |
134 | } |
135 | |
136 | void GUISlider::styleUpdated() |
137 | { |
138 | mBackground->setStyle(getSubStyleName(getBackgroundStyleType())); |
139 | mFillBackground->setStyle(getSubStyleName(getFillStyleType())); |
140 | mSliderHandle->setStyle(getSubStyleName(getHandleStyleType())); |
141 | |
142 | const GUIElementStyle* bgStyle = mBackground->_getStyle(); |
143 | if(mHasFocus) |
144 | mBackground->setTexture(bgStyle->focused.texture); |
145 | else |
146 | mBackground->setTexture(bgStyle->normal.texture); |
147 | } |
148 | |
149 | void GUISlider::setPercent(float pct) |
150 | { |
151 | float oldHandlePos = mSliderHandle->getHandlePos(); |
152 | mSliderHandle->_setHandlePos(pct); |
153 | |
154 | if (oldHandlePos != mSliderHandle->getHandlePos()) |
155 | mSliderHandle->_markLayoutAsDirty(); |
156 | } |
157 | |
158 | float GUISlider::getPercent() const |
159 | { |
160 | return mSliderHandle->getHandlePos(); |
161 | } |
162 | |
163 | float GUISlider::getValue() const |
164 | { |
165 | float diff = mMaxRange - mMinRange; |
166 | return mMinRange + diff * mSliderHandle->getHandlePos(); |
167 | } |
168 | |
169 | void GUISlider::setValue(float value) |
170 | { |
171 | float diff = mMaxRange - mMinRange; |
172 | float pct = (value - mMinRange) / diff; |
173 | |
174 | setPercent(pct); |
175 | } |
176 | |
177 | void GUISlider::setRange(float min, float max) |
178 | { |
179 | mMinRange = min; |
180 | mMaxRange = max; |
181 | } |
182 | |
183 | float GUISlider::getRangeMaximum() const |
184 | { |
185 | return mMaxRange; |
186 | } |
187 | |
188 | float GUISlider::getRangeMinimum() const |
189 | { |
190 | return mMinRange; |
191 | } |
192 | |
193 | void GUISlider::setStep(float step) |
194 | { |
195 | float range = mMaxRange - mMinRange; |
196 | if(range > 0.0f) |
197 | step = step / range; |
198 | else |
199 | step = 0.0f; |
200 | |
201 | mSliderHandle->setStep(step); |
202 | } |
203 | |
204 | float GUISlider::getStep() const |
205 | { |
206 | return mSliderHandle->getStep(); |
207 | } |
208 | |
209 | void GUISlider::setTint(const Color& color) |
210 | { |
211 | mBackground->setTint(color); |
212 | mSliderHandle->setTint(color); |
213 | } |
214 | |
215 | void GUISlider::onHandleMoved(float newPosition, float newSize) |
216 | { |
217 | onChanged(getValue()); |
218 | } |
219 | |
220 | bool GUISlider::_commandEvent(const GUICommandEvent& ev) |
221 | { |
222 | const bool baseReturnValue = GUIElement::_commandEvent(ev); |
223 | |
224 | const GUIElementStyle* bgStyle = mBackground->_getStyle(); |
225 | if(ev.getType() == GUICommandEventType::FocusGained) |
226 | { |
227 | mHasFocus = true; |
228 | |
229 | if(!_isDisabled()) |
230 | mBackground->setTexture(bgStyle->focused.texture); |
231 | |
232 | return true; |
233 | } |
234 | else if(ev.getType() == GUICommandEventType::FocusLost) |
235 | { |
236 | mHasFocus = false; |
237 | mBackground->setTexture(bgStyle->normal.texture); |
238 | |
239 | return true; |
240 | } |
241 | else if(ev.getType() == GUICommandEventType::MoveLeft) |
242 | { |
243 | mSliderHandle->moveOneStep(false); |
244 | return true; |
245 | } |
246 | else if(ev.getType() == GUICommandEventType::MoveRight) |
247 | { |
248 | mSliderHandle->moveOneStep(true); |
249 | return true; |
250 | } |
251 | |
252 | return baseReturnValue; |
253 | } |
254 | |
255 | GUISliderHorz::GUISliderHorz(const String& styleName, const GUIDimensions& dimensions) |
256 | :GUISlider(true, styleName, dimensions) |
257 | { |
258 | |
259 | } |
260 | |
261 | GUISliderHorz* GUISliderHorz::create(const String& styleName) |
262 | { |
263 | return new (bs_alloc<GUISliderHorz>()) GUISliderHorz(getStyleName<GUISliderHorz>(styleName), GUIDimensions::create()); |
264 | } |
265 | |
266 | GUISliderHorz* GUISliderHorz::create(const GUIOptions& options, const String& styleName) |
267 | { |
268 | return new (bs_alloc<GUISliderHorz>()) GUISliderHorz(getStyleName<GUISliderHorz>(styleName), GUIDimensions::create(options)); |
269 | } |
270 | |
271 | const String& GUISliderHorz::getGUITypeName() |
272 | { |
273 | static String typeName = "SliderHorz" ; |
274 | return typeName; |
275 | } |
276 | |
277 | GUISliderVert::GUISliderVert(const String& styleName, const GUIDimensions& dimensions) |
278 | :GUISlider(false, styleName, dimensions) |
279 | { |
280 | |
281 | } |
282 | |
283 | GUISliderVert* GUISliderVert::create(const String& styleName) |
284 | { |
285 | return new (bs_alloc<GUISliderVert>()) GUISliderVert(getStyleName<GUISliderVert>(styleName), GUIDimensions::create()); |
286 | } |
287 | |
288 | GUISliderVert* GUISliderVert::create(const GUIOptions& options, const String& styleName) |
289 | { |
290 | return new (bs_alloc<GUISliderVert>()) GUISliderVert(getStyleName<GUISliderVert>(styleName), GUIDimensions::create(options)); |
291 | } |
292 | |
293 | const String& GUISliderVert::getGUITypeName() |
294 | { |
295 | static String typeName = "SliderVert" ; |
296 | return typeName; |
297 | } |
298 | } |