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