1 /*      _______   __   __   __   ______   __   __   _______   __   __
2  *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
3  *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
4  *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
5  *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
6  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
7  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
8  *
9  * Copyright (c) 2004 - 2008 Olof Naess�n and Per Larsson
10  *
11  *
12  * Per Larsson a.k.a finalman
13  * Olof Naess�n a.k.a jansem/yakslem
14  *
15  * Visit: http://guichan.sourceforge.net
16  *
17  * License: (BSD)
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  * 2. Redistributions in binary form must reproduce the above copyright
24  *    notice, this list of conditions and the following disclaimer in
25  *    the documentation and/or other materials provided with the
26  *    distribution.
27  * 3. Neither the name of Guichan nor the names of its contributors may
28  *    be used to endorse or promote products derived from this software
29  *    without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  */
43 
44 /*
45  * For comments regarding functions please see the header file.
46  */
47 
48 #include "guichan/widgets/slider.hpp"
49 
50 #include "guichan/graphics.hpp"
51 #include "guichan/key.hpp"
52 #include "guichan/mouseinput.hpp"
53 
54 namespace gcn
55 {
Slider(double scaleEnd)56     Slider::Slider(double scaleEnd)
57     {
58         mDragged = false;
59 
60         mScaleStart = 0;
61         mScaleEnd = scaleEnd;
62 
63         setFocusable(true);
64         setFrameSize(1);
65         setOrientation(HORIZONTAL);
66         setValue(0);
67         setStepLength(scaleEnd / 10);
68         setMarkerLength(10);
69 
70         addMouseListener(this);
71         addKeyListener(this);
72     }
73 
Slider(double scaleStart,double scaleEnd)74     Slider::Slider(double scaleStart, double scaleEnd)
75     {
76         mDragged = false;
77 
78         mScaleStart = scaleStart;
79         mScaleEnd = scaleEnd;
80 
81         setFocusable(true);
82         setFrameSize(1);
83         setOrientation(HORIZONTAL);
84         setValue(scaleStart);
85         setStepLength((scaleEnd  - scaleStart)/ 10);
86         setMarkerLength(10);
87 
88         addMouseListener(this);
89         addKeyListener(this);
90     }
91 
setScale(double scaleStart,double scaleEnd)92     void Slider::setScale(double scaleStart, double scaleEnd)
93     {
94         mScaleStart = scaleStart;
95         mScaleEnd = scaleEnd;
96     }
97 
getScaleStart() const98     double Slider::getScaleStart() const
99     {
100         return mScaleStart;
101     }
102 
setScaleStart(double scaleStart)103     void Slider::setScaleStart(double scaleStart)
104     {
105         mScaleStart = scaleStart;
106     }
107 
getScaleEnd() const108     double Slider::getScaleEnd() const
109     {
110         return mScaleEnd;
111     }
112 
setScaleEnd(double scaleEnd)113     void Slider::setScaleEnd(double scaleEnd)
114     {
115         mScaleEnd = scaleEnd;
116     }
117 
draw(gcn::Graphics * graphics)118     void Slider::draw(gcn::Graphics* graphics)
119     {
120         Color shadowColor = getBaseColor() - 0x101010;
121         int alpha = getBaseColor().a;
122          shadowColor.a = alpha;
123 
124         graphics->setColor(shadowColor);
125         graphics->fillRectangle(gcn::Rectangle(0,0,getWidth(),getHeight()));
126 
127         drawMarker(graphics);
128     }
129 
drawMarker(gcn::Graphics * graphics)130     void Slider::drawMarker(gcn::Graphics* graphics)
131     {
132         gcn::Color faceColor = getBaseColor();
133         Color highlightColor, shadowColor;
134         int alpha = getBaseColor().a;
135         highlightColor = faceColor + 0x303030;
136         highlightColor.a = alpha;
137         shadowColor = faceColor - 0x303030;
138         shadowColor.a = alpha;
139 
140         graphics->setColor(faceColor);
141 
142         if (getOrientation() == HORIZONTAL)
143         {
144             int v = getMarkerPosition();
145             graphics->fillRectangle(gcn::Rectangle(v + 1, 1, getMarkerLength() - 2, getHeight() - 2));
146             graphics->setColor(highlightColor);
147             graphics->drawLine(v, 0, v + getMarkerLength() - 1,0);
148             graphics->drawLine(v, 0, v, getHeight() - 1);
149             graphics->setColor(shadowColor);
150             graphics->drawLine(v + getMarkerLength() - 1, 1, v + getMarkerLength() - 1, getHeight() - 1);
151             graphics->drawLine(v + 1, getHeight() - 1, v + getMarkerLength() - 1, getHeight() - 1);
152 
153             if (isFocused())
154             {
155                 graphics->setColor(getForegroundColor());
156                 graphics->drawRectangle(Rectangle(v + 2, 2, getMarkerLength() - 4, getHeight() - 4));
157             }
158         }
159         else
160         {
161             int v = (getHeight() - getMarkerLength()) - getMarkerPosition();
162             graphics->fillRectangle(gcn::Rectangle(1, v + 1, getWidth() - 2, getMarkerLength() - 2));
163             graphics->setColor(highlightColor);
164             graphics->drawLine(0, v, 0, v + getMarkerLength() - 1);
165             graphics->drawLine(0, v, getWidth() - 1, v);
166             graphics->setColor(shadowColor);
167             graphics->drawLine(1, v + getMarkerLength() - 1, getWidth() - 1, v + getMarkerLength() - 1);
168             graphics->drawLine(getWidth() - 1, v + 1, getWidth() - 1, v + getMarkerLength() - 1);
169 
170             if (isFocused())
171             {
172                 graphics->setColor(getForegroundColor());
173                 graphics->drawRectangle(Rectangle(2, v + 2, getWidth() - 4, getMarkerLength() - 4));
174             }
175         }
176     }
177 
mousePressed(MouseEvent & mouseEvent)178     void Slider::mousePressed(MouseEvent& mouseEvent)
179     {
180         if (mouseEvent.getButton() == gcn::MouseEvent::LEFT
181             && mouseEvent.getX() >= 0
182             && mouseEvent.getX() <= getWidth()
183             && mouseEvent.getY() >= 0
184             && mouseEvent.getY() <= getHeight())
185         {
186             if (getOrientation() == HORIZONTAL)
187             {
188                 setValue(markerPositionToValue(mouseEvent.getX() - getMarkerLength() / 2));
189             }
190             else
191             {
192                 setValue(markerPositionToValue(getHeight() - mouseEvent.getY() - getMarkerLength() / 2));
193             }
194 
195             distributeActionEvent();
196         }
197     }
198 
mouseDragged(MouseEvent & mouseEvent)199     void Slider::mouseDragged(MouseEvent& mouseEvent)
200     {
201         if (getOrientation() == HORIZONTAL)
202         {
203             setValue(markerPositionToValue(mouseEvent.getX() - getMarkerLength() / 2));
204         }
205         else
206         {
207             setValue(markerPositionToValue(getHeight() - mouseEvent.getY() - getMarkerLength() / 2));
208         }
209 
210         distributeActionEvent();
211 
212         mouseEvent.consume();
213     }
214 
setValue(double value)215     void Slider::setValue(double value)
216     {
217         if (value > getScaleEnd())
218         {
219             mValue = getScaleEnd();
220             return;
221         }
222 
223         if (value < getScaleStart())
224         {
225             mValue = getScaleStart();
226             return;
227         }
228 
229         mValue = value;
230     }
231 
getValue() const232     double Slider::getValue() const
233     {
234         return mValue;
235     }
236 
getMarkerLength() const237     int Slider::getMarkerLength() const
238     {
239         return mMarkerLength;
240     }
241 
setMarkerLength(int length)242     void Slider::setMarkerLength(int length)
243     {
244         mMarkerLength = length;
245     }
246 
keyPressed(KeyEvent & keyEvent)247     void Slider::keyPressed(KeyEvent& keyEvent)
248     {
249         Key key = keyEvent.getKey();
250 
251         if (getOrientation() == HORIZONTAL)
252         {
253             if (key.getValue() == Key::RIGHT)
254             {
255                 setValue(getValue() + getStepLength());
256                 distributeActionEvent();
257                 keyEvent.consume();
258             }
259             else if (key.getValue() == Key::LEFT)
260             {
261                 setValue(getValue() - getStepLength());
262                 distributeActionEvent();
263                 keyEvent.consume();
264             }
265         }
266         else
267         {
268             if (key.getValue() == Key::UP)
269             {
270                 setValue(getValue() + getStepLength());
271                 distributeActionEvent();
272                 keyEvent.consume();
273             }
274             else if (key.getValue() == Key::DOWN)
275             {
276                 setValue(getValue() - getStepLength());
277                 distributeActionEvent();
278                 keyEvent.consume();
279             }
280         }
281     }
282 
setOrientation(Slider::Orientation orientation)283     void Slider::setOrientation(Slider::Orientation orientation)
284     {
285         mOrientation = orientation;
286     }
287 
getOrientation() const288     Slider::Orientation Slider::getOrientation() const
289     {
290         return mOrientation;
291     }
292 
markerPositionToValue(int v) const293     double Slider::markerPositionToValue(int v) const
294     {
295         int w;
296         if (getOrientation() == HORIZONTAL)
297         {
298             w = getWidth();
299         }
300         else
301         {
302             w = getHeight();
303         }
304 
305         double pos = v / ((double)w - getMarkerLength());
306         return (1.0 - pos) * getScaleStart() + pos * getScaleEnd();
307 
308     }
309 
valueToMarkerPosition(double value) const310     int Slider::valueToMarkerPosition(double value) const
311     {
312         int v;
313         if (getOrientation() == HORIZONTAL)
314         {
315             v = getWidth();
316         }
317         else
318         {
319             v = getHeight();
320         }
321 
322         int w =  (int)((v - getMarkerLength())
323                        * (value  - getScaleStart())
324                        / (getScaleEnd() - getScaleStart()));
325 
326         if (w < 0)
327         {
328             return 0;
329         }
330 
331         if (w > v - getMarkerLength())
332         {
333             return v - getMarkerLength();
334         }
335 
336         return w;
337     }
338 
setStepLength(double length)339     void Slider::setStepLength(double length)
340     {
341         mStepLength = length;
342     }
343 
getStepLength() const344     double Slider::getStepLength() const
345     {
346         return mStepLength;
347     }
348 
getMarkerPosition() const349     int Slider::getMarkerPosition() const
350     {
351         return valueToMarkerPosition(getValue());
352     }
353 
mouseWheelMovedUp(MouseEvent & mouseEvent)354     void Slider::mouseWheelMovedUp(MouseEvent& mouseEvent)
355     {
356         setValue(getValue() + getStepLength());
357         distributeActionEvent();
358 
359         mouseEvent.consume();
360     }
361 
mouseWheelMovedDown(MouseEvent & mouseEvent)362     void Slider::mouseWheelMovedDown(MouseEvent& mouseEvent)
363     {
364         setValue(getValue() - getStepLength());
365         distributeActionEvent();
366 
367         mouseEvent.consume();
368     }
369 }
370