/* * * Slider.as * Keith Peters * version 0.9.10 * * Abstract base slider class for HSlider and VSlider. * * Copyright (c) 2011 Keith Peters * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * version 1.0 * By. xiaotie@geblab.com * Changes: [2012-02-11] make it skinable */ package geb.controls
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import geb.common.BaseComponent;
[Event(name="change", type="flash.events.Event")]
public class Slider
extends BaseComponent
{
[Bindable]
public var thumb:Sprite;
[Bindable]
public var track:Sprite;
[Bindable]
public var trackHighlight:Sprite;
[Bindable]
public var orientation:
String = "horizontal";
public var trackClickable:
Boolean =
true;
[Bindable]
public var ignoreThumbSize:
Boolean =
false;
protected
var _value:
Number = 0;
protected
var _max:
Number = 100;
protected
var _min:
Number = 0;
protected
var _tick:
Number = 0.01;
public static const HORIZONTAL:
String = "horizontal";
public static const VERTICAL:
String = "vertical";
/* * * Initializes the component. */ override protected
function init():void
{
super.init();
if(orientation == HORIZONTAL)
{
setSize(width, height);
}
else {
setSize(width, height);
}
}
/* * * Creates and adds the child display objects of this component. */ override protected
function addChildren():void
{
super.addChildren();
}
/* * * Adjusts value to be within minimum and maximum. */ protected
function correctValue():void
{
if(_max > _min)
{
_value = Math.min(_value, _max);
_value = Math.max(_value, _min);
}
else {
_value = Math.max(_value, _max);
_value = Math.min(_value, _min);
}
}
private function get thumbSize():
Number {
if(thumb ==
null || ignoreThumbSize ==
true)
return 0;
else if(orientation == HORIZONTAL)
{
return thumb.width;
}
else {
return thumb.height;
}
}
/* * * Adjusts position of handle when value, maximum or minimum have changed. * TODO: Should also be called when slider is resized. */ protected
function updateDislpay():void
{
var range:
Number;
var highlightRange:
Number;
var pos:
Number;
var ts:
Number = thumbSize;
if(orientation == HORIZONTAL)
{
range = _width - ts;
pos = (_value - _min) / (_max - _min) * range;
highlightRange = pos + ts * 0.5;
if(thumb!=
null)
{
thumb.x = pos - (ignoreThumbSize ? thumb.width * 0.5 : 0);
thumb.y = 0.5 * (this.height - thumb.height);
}
if(trackHighlight !=
null)
{
trackHighlight.width = pos + 0.5 * ts;
trackHighlight.height = Math.min(height,trackHighlight.height);
trackHighlight.y = Math.max(0, 0.5 * (height - trackHighlight.height));
if(trackHighlight is BaseComponent)
{
BaseComponent(trackHighlight).invalidate(
false);
}
}
if(track !=
null)
{
track.width = width;
track.height = Math.min(height,track.height);
track.y = Math.max(0, 0.5 * (height - track.height));
if(track is BaseComponent)
{
BaseComponent(track).invalidate(
false);
}
}
}
else {
range = _height - ts;
pos = height - ts - (_value - _min) / (_max - _min) * range;
highlightRange = pos + ts * 0.5;
if(thumb !=
null)
{
thumb.x = 0.5 * (this.width - thumb.width);
thumb.y = pos - (ignoreThumbSize ? thumb.height * 0.5 : 0);
}
if(trackHighlight !=
null)
{
trackHighlight.width = Math.min(width,trackHighlight.width);
trackHighlight.y = pos + 0.5 * ts;
trackHighlight.height = height - trackHighlight.y;
trackHighlight.x = Math.max(0, 0.5 * (width - trackHighlight.width));
if(trackHighlight is BaseComponent)
{
BaseComponent(trackHighlight).invalidate(
false);
}
}
if(track !=
null)
{
track.height = height;
track.width = Math.min(width,track.width);
track.x = Math.max(0, 0.5 * (width - track.width));
if(track is BaseComponent)
{
BaseComponent(track).invalidate(
false);
}
}
}
if(track !=
null && this.contains(track) ==
false)
{
addChild(track);
if(trackClickable)
{
track.useHandCursor =
true;
track.buttonMode =
true;
track.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
}
else {
track.removeEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
}
}
if(trackHighlight !=
null && this.contains(trackHighlight) ==
false)
{
addChild(trackHighlight);
if(trackClickable)
{
trackHighlight.useHandCursor =
true;
trackHighlight.buttonMode =
true;
trackHighlight.addEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
}
else {
trackHighlight.removeEventListener(MouseEvent.MOUSE_DOWN, onBackClick);
}
}
if(thumb !=
null && this.contains(thumb) ==
false)
{
thumb.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
thumb.buttonMode =
true;
thumb.useHandCursor =
true;
addChild(thumb);
}
}
// / // public methods // / /* * * Draws the visual ui of the component. */ override
public function draw():void
{
super.draw();
updateDislpay();
}
/* * * Convenience method to set the three main parameters in one shot. * @param min The minimum value of the slider. * @param max The maximum value of the slider. * @param value The value of the slider. */ public function setSliderParams(min:
Number, max:
Number, value:
Number):void
{
this.minimum = min;
this.maximum = max;
this.value = value;
}
// / // event handlers // / /* * * Handler called when user clicks the background of the slider, causing the handle to move to that point. Only active if backClick is true. * @param event The MouseEvent passed by the system. */ protected
function onBackClick(event:MouseEvent):void
{
var ts:
Number = thumbSize;
var pos:
Number;
if(orientation == HORIZONTAL)
{
pos = mouseX - ( ignoreThumbSize ? 0 : thumb.width * 0.5);
pos = Math.max(pos, 0);
pos = Math.min(pos, _width - ts);
value = pos / (width - ts) * (_max - _min) + _min;
}
else {
pos = mouseY - ( ignoreThumbSize ? 0 : thumb.height * 0.5);
pos = Math.max(pos, 0);
pos = Math.min(pos, _height - ts);
value = (_height - ts - pos) / (height - ts) * (_max - _min) + _min;
}
dispatchEvent(new Event(Event.CHANGE));
}
/* * * Internal mouseDown handler. Starts dragging the handle. * @param event The MouseEvent passed by the system. */ protected
function onDrag(event:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onSlide);
if(orientation == HORIZONTAL)
{
var xStart:
Number = ignoreThumbSize? - thumb.width * 0.5 : 0;
thumb.startDrag(
false, new Rectangle(xStart, thumb.y, _width - thumbSize, 0));
}
else {
var yStart:
Number = ignoreThumbSize? - thumb.height * 0.5 : 0;
thumb.startDrag(
false, new Rectangle(thumb.x, yStart, 0, _height - thumbSize));
}
}
/* * * Internal mouseUp handler. Stops dragging the handle. * @param event The MouseEvent passed by the system. */ protected
function onDrop(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onSlide);
stopDrag();
}
/* * * Internal mouseMove handler for when the handle is being moved. * @param event The MouseEvent passed by the system. */ protected
function onSlide(event:MouseEvent):void
{
var oldValue:
Number = _value;
var pos:
Number;
if(orientation == HORIZONTAL)
{
pos = ignoreThumbSize ? (thumb.x + thumb.width * 0.5) : thumb.x;
value = pos / (width - thumbSize) * (_max - _min) + _min;
}
else {
pos = ignoreThumbSize ? (thumb.y + thumb.height * 0.5) : thumb.y;
value = (height - thumbSize - pos) / (height - thumbSize) * (_max - _min) + _min;
}
if(value != oldValue)
{
dispatchEvent(new Event(Event.CHANGE));
}
}
// / // getter/setters // / /* * * Sets / gets whether or not a click on the background of the slider will move the handler to that position. */ public function set backClick(b:
Boolean):void
{
trackClickable = b;
invalidate();
}
public function get backClick():
Boolean {
return trackClickable;
}
/* * * Sets / gets the current value of this slider. */ [Bindable]
public function set value(v:
Number):void
{
_value = v;
correctValue();
updateDislpay();
}
[Bindable]
public function get value():
Number {
return Math.round(_value / _tick) * _tick;
}
/* * * Gets the value of the slider without rounding it per the tick value. */ public function get rawValue():
Number {
return _value;
}
[Bindable]
/* * * Gets / sets the maximum value of this slider. */ public function set maximum(m:
Number):void
{
_max = m;
correctValue();
updateDislpay();
}
public function get maximum():
Number {
return _max;
}
[Bindable]
/* * * Gets / sets the minimum value of this slider. */ public function set minimum(m:
Number):void
{
_min = m;
correctValue();
updateDislpay();
}
public function get minimum():
Number {
return _min;
}
/* * * Gets / sets the tick value of this slider. This round the value to the nearest multiple of this number. */ public function set tick(t:
Number):void
{
_tick = t;
}
public function get tick():
Number {
return _tick;
}
}
}