1 /***********************************************************************
2 created: 13/4/2004
3 author: Paul D Turner
4
5 purpose: Implementation of Slider widget base class
6 *************************************************************************/
7 /***************************************************************************
8 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 ***************************************************************************/
29 #include "CEGUI/widgets/Slider.h"
30 #include "CEGUI/widgets/Thumb.h"
31 #include "CEGUI/WindowManager.h"
32 #include "CEGUI/Exceptions.h"
33
34 // Start of CEGUI namespace section
35 namespace CEGUI
36 {
37 const String Slider::EventNamespace("Slider");
38 const String Slider::WidgetTypeName("CEGUI/Slider");
39
40 /*************************************************************************
41 SliderWindowRenderer
42 *************************************************************************/
SliderWindowRenderer(const String & name)43 SliderWindowRenderer::SliderWindowRenderer(const String& name) :
44 WindowRenderer(name, Slider::EventNamespace)
45 {
46 }
47
48 /*************************************************************************
49 Event name constants
50 *************************************************************************/
51 const String Slider::EventValueChanged( "ValueChanged" );
52 const String Slider::EventThumbTrackStarted( "ThumbTrackStarted" );
53 const String Slider::EventThumbTrackEnded( "ThumbTrackEnded" );
54
55 /*************************************************************************
56 Child Widget name constants
57 *************************************************************************/
58 const String Slider::ThumbName( "__auto_thumb__" );
59
60 /*************************************************************************
61 Slider base class constructor
62 *************************************************************************/
Slider(const String & type,const String & name)63 Slider::Slider(const String& type, const String& name) :
64 Window(type, name),
65 d_value(0.0f),
66 d_maxValue(1.0f),
67 d_step(0.01f)
68 {
69 addSliderProperties();
70 }
71
72
73 /*************************************************************************
74 Slider base class destructor
75 *************************************************************************/
~Slider(void)76 Slider::~Slider(void)
77 {
78 }
79
80
81 /*************************************************************************
82 Initialises the Window based object ready for use.
83 *************************************************************************/
initialiseComponents(void)84 void Slider::initialiseComponents(void)
85 {
86 // get thumb
87 Thumb* thumb = getThumb();
88
89 // bind handler to thumb events
90 thumb->subscribeEvent(Thumb::EventThumbPositionChanged, Event::Subscriber(&CEGUI::Slider::handleThumbMoved, this));
91 thumb->subscribeEvent(Thumb::EventThumbTrackStarted, Event::Subscriber(&CEGUI::Slider::handleThumbTrackStarted, this));
92 thumb->subscribeEvent(Thumb::EventThumbTrackEnded, Event::Subscriber(&CEGUI::Slider::handleThumbTrackEnded, this));
93
94 performChildWindowLayout();
95 }
96
97
98 /*************************************************************************
99 set the maximum value for the slider.
100 Note that the minimum value is fixed at 0.
101 *************************************************************************/
setMaxValue(float maxVal)102 void Slider::setMaxValue(float maxVal)
103 {
104 d_maxValue = maxVal;
105
106 float oldval = d_value;
107
108 // limit current value to be within new max
109 if (d_value > d_maxValue) {
110 d_value = d_maxValue;
111 }
112
113 updateThumb();
114
115 // send notification if slider value changed.
116 if (d_value != oldval)
117 {
118 WindowEventArgs args(this);
119 onValueChanged(args);
120 }
121
122 }
123
124
125 /*************************************************************************
126 set the current slider value.
127 *************************************************************************/
setCurrentValue(float value)128 void Slider::setCurrentValue(float value)
129 {
130 float oldval = d_value;
131
132 // range for value: 0 <= value <= maxValue
133 d_value = (value >= 0.0f) ? ((value <= d_maxValue) ? value : d_maxValue) : 0.0f;
134
135 updateThumb();
136
137 // send notification if slider value changed.
138 if (d_value != oldval)
139 {
140 WindowEventArgs args(this);
141 onValueChanged(args);
142 }
143
144 }
145
validateWindowRenderer(const WindowRenderer * renderer) const146 bool Slider::validateWindowRenderer(const WindowRenderer* renderer) const
147 {
148 return dynamic_cast<const SliderWindowRenderer*>(renderer) != 0;
149 }
150
151 /*************************************************************************
152 Handler triggered when the slider value changes
153 *************************************************************************/
onValueChanged(WindowEventArgs & e)154 void Slider::onValueChanged(WindowEventArgs& e)
155 {
156 fireEvent(EventValueChanged, e, EventNamespace);
157 }
158
159
160 /*************************************************************************
161 Handler triggered when the user begins to drag the slider thumb.
162 *************************************************************************/
onThumbTrackStarted(WindowEventArgs & e)163 void Slider::onThumbTrackStarted(WindowEventArgs& e)
164 {
165 fireEvent(EventThumbTrackStarted, e, EventNamespace);
166 }
167
168
169 /*************************************************************************
170 Handler triggered when the slider thumb is released
171 *************************************************************************/
onThumbTrackEnded(WindowEventArgs & e)172 void Slider::onThumbTrackEnded(WindowEventArgs& e)
173 {
174 fireEvent(EventThumbTrackEnded, e, EventNamespace);
175 }
176
177
178 /*************************************************************************
179 Handler for when a mouse button is pressed
180 *************************************************************************/
onMouseButtonDown(MouseEventArgs & e)181 void Slider::onMouseButtonDown(MouseEventArgs& e)
182 {
183 // base class processing
184 Window::onMouseButtonDown(e);
185
186 if (e.button == LeftButton)
187 {
188 float adj = getAdjustDirectionFromPoint(e.position);
189
190 // adjust slider position in whichever direction as required.
191 if (adj != 0)
192 {
193 setCurrentValue(d_value + (adj * d_step));
194 }
195
196 ++e.handled;
197 }
198
199 }
200
201
202 /*************************************************************************
203 Handler for scroll wheel changes
204 *************************************************************************/
onMouseWheel(MouseEventArgs & e)205 void Slider::onMouseWheel(MouseEventArgs& e)
206 {
207 // base class processing
208 Window::onMouseWheel(e);
209
210 // scroll by e.wheelChange * stepSize
211 setCurrentValue(d_value + d_step * e.wheelChange);
212
213 // ensure the message does not go to our parent.
214 ++e.handled;
215 }
216
217
218 /*************************************************************************
219 handler function for when thumb moves.
220 *************************************************************************/
handleThumbMoved(const EventArgs &)221 bool Slider::handleThumbMoved(const EventArgs&)
222 {
223 setCurrentValue(getValueFromThumb());
224
225 return true;
226 }
227
228
229 /*************************************************************************
230 handler function for when thumb tracking begins
231 *************************************************************************/
handleThumbTrackStarted(const EventArgs &)232 bool Slider::handleThumbTrackStarted(const EventArgs&)
233 {
234 // simply trigger our own version of this event
235 WindowEventArgs args(this);
236 onThumbTrackStarted(args);
237
238 return true;
239 }
240
241
242 /*************************************************************************
243 handler function for when thumb tracking begins
244 *************************************************************************/
handleThumbTrackEnded(const EventArgs &)245 bool Slider::handleThumbTrackEnded(const EventArgs&)
246 {
247 // simply trigger our own version of this event
248 WindowEventArgs args(this);
249 onThumbTrackEnded(args);
250
251 return true;
252 }
253
254
255 /*************************************************************************
256 Add properties for the slider
257 *************************************************************************/
addSliderProperties(void)258 void Slider::addSliderProperties(void)
259 {
260 const String& propertyOrigin = WidgetTypeName;
261
262 CEGUI_DEFINE_PROPERTY(Slider, float,
263 "CurrentValue", "Property to get/set the current value of the slider. Value is a float.",
264 &Slider::setCurrentValue, &Slider::getCurrentValue, 0.0f
265 );
266
267 CEGUI_DEFINE_PROPERTY(Slider, float,
268 "MaximumValue", "Property to get/set the maximum value of the slider. Value is a float.",
269 &Slider::setMaxValue, &Slider::getMaxValue, 1.0f /* TODO: Inconsistency */
270 );
271
272 CEGUI_DEFINE_PROPERTY(Slider, float,
273 "ClickStepSize", "Property to get/set the click-step size for the slider. Value is a float.",
274 &Slider::setClickStep, &Slider::getClickStep, 0.01f /* TODO: Inconsistency */
275 );
276 }
277
278 /*************************************************************************
279 Return a pointer to the Thumb component widget..
280 *************************************************************************/
getThumb() const281 Thumb* Slider::getThumb() const
282 {
283 return static_cast<Thumb*>(getChild(ThumbName));
284 }
285
286 /*************************************************************************
287 update the size and location of the thumb to properly represent the
288 current state of the scroll bar
289 *************************************************************************/
updateThumb(void)290 void Slider::updateThumb(void)
291 {
292 if (d_windowRenderer != 0)
293 {
294 SliderWindowRenderer* wr = (SliderWindowRenderer*)d_windowRenderer;
295 wr->updateThumb();
296 }
297 else
298 {
299 //updateThumb_impl();
300 CEGUI_THROW(InvalidRequestException(
301 "This function must be implemented by the window renderer module"));
302 }
303 }
304
305 /*************************************************************************
306 return value that best represents current scroll bar position given
307 the current location of the thumb.
308 *************************************************************************/
getValueFromThumb(void) const309 float Slider::getValueFromThumb(void) const
310 {
311 if (d_windowRenderer != 0)
312 {
313 SliderWindowRenderer* wr = (SliderWindowRenderer*)d_windowRenderer;
314 return wr->getValueFromThumb();
315 }
316 else
317 {
318 //return getValueFromThumb_impl();
319 CEGUI_THROW(InvalidRequestException(
320 "This function must be implemented by the window renderer module"));
321 }
322 }
323
324 /*************************************************************************
325 Given window location 'pt', return a value indicating what change
326 should be made to the scroll bar.
327 *************************************************************************/
getAdjustDirectionFromPoint(const Vector2f & pt) const328 float Slider::getAdjustDirectionFromPoint(const Vector2f& pt) const
329 {
330 if (d_windowRenderer != 0)
331 {
332 SliderWindowRenderer* wr = (SliderWindowRenderer*)d_windowRenderer;
333 return wr->getAdjustDirectionFromPoint(pt);
334 }
335 else
336 {
337 //return getAdjustDirectionFromPoint_impl(pt);
338 CEGUI_THROW(InvalidRequestException(
339 "This function must be implemented by the window renderer module"));
340 }
341 }
342
343 } // End of CEGUI namespace section
344