//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package spark.components { import flash.display.DisplayObject; import flash.display.InteractiveObject; import flash.events.Event; import flash.events.FocusEvent; import flash.events.KeyboardEvent; import flash.globalization.LocaleID; import flash.globalization.NumberFormatter; import mx.core.IIMESupport; import mx.core.mx_internal; import mx.events.FlexEvent; import mx.managers.IFocusManagerComponent; use namespace mx_internal; //-------------------------------------- // Styles //-------------------------------------- include "../styles/metadata/BasicInheritingTextStyles.as" include "../styles/metadata/AdvancedInheritingTextStyles.as" include "../styles/metadata/SelectionFormatTextStyles.as" /** * The alpha of the border for this component. * * @default 0.5 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ [Style(name="borderAlpha", type="Number", inherit="no", theme="spark")] /** * The color of the border for this component. * * @default 0x000000 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ [Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")] /** * Controls the visibility of the border for this component. * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ [Style(name="borderVisible", type="Boolean", inherit="no", theme="spark")] /** * The alpha of the content background for this component. * * @default 1 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ [Style(name="contentBackgroundAlpha", type="Number", inherit="yes", theme="spark")] /** * @copy spark.components.supportClasses.GroupBase#style:contentBackgroundColor * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ [Style(name="contentBackgroundColor", type="uint", format="Color", inherit="yes", theme="spark")] //-------------------------------------- // Other metadata //-------------------------------------- [AccessibilityClass(implementation="spark.accessibility.NumericStepperAccImpl")] [DefaultTriggerEvent("change")] [IconFile("NumericStepper.png")] /** * Because this component does not define a skin for the mobile theme, Adobe * recommends that you not use it in a mobile application. Alternatively, you * can define your own mobile skin for the component. For more information, * see Basics of mobile skinning. */ [DiscouragedForProfile("mobileDevice")] /** * The NumericStepper control lets you select * a number from an ordered set. * The NumericStepper provides the same functionality as * the Spinner component, but adds a TextInput control * so that you can directly edit the value of the component, * rather than modifying it by using the control's arrow buttons. * *
The NumericStepper control consists of a single-line
* input text field and a pair of arrow buttons
* for stepping through the possible values.
* The Up Arrow and Down Arrow keys and the mouse wheel also cycle through
* the values.
* An input value is committed when
* the user presses the Enter key, removes focus from the
* component, or steps the NumericStepper by pressing an arrow button
* or by calling the changeValueByStep()
method.
To use this component in a list-based component, such as a List or DataGrid, * create an item renderer. * For information about creating an item renderer, see * * Custom Spark item renderers.
* *The NumericStepper control has the following default characteristics:
*Characteristic | *Description | *
---|---|
Default size | *53 pixels wide by 23 pixels high | *
Minimum size | *40 pixels wide and 40 pixels high | *
Maximum size | *10000 pixels wide and 10000 pixels high | *
Default skin classes | *spark.skins.spark.NumericStepperSkin
* spark.skins.spark.NumericStepperTextInputSkin |
*
The <s:NumericStepper>
tag inherits all of the tag
* attributes of its superclass and adds the following tag attributes:
* <s:NumericStepper * * Properties * imeMode="null" * maxChars="0" * maximum="10" * valueFormatFunction="" * valueParseFunction="" * * Styles * * alignmentBaseline="USE_DOMINANT_BASELINE" * baselineShift="0.0" * blockProgression="TB" * borderAlpha="0.5" * borderColor="0x000000" * borderVisible="true" * breakOpportunity="AUTO" * cffHinting="HORIZONTAL_STEM" * color="0" * contentBackgroundAlpha="1.0" * contentBackgroundColor="0xFFFFFF" * clearFloats="none" * digitCase="DEFAULT" * digitWidth="DEFAULT" * direction="LTR" * dominantBaseline="AUTO" * firstBaselineOffset="AUTO" * focusedTextSelectionColor="" * fontFamily="Arial" * fontLookup="DEVICE" * fontSize="12" * fontStyle="NORMAL" * fontWeight="NORMAL" * inactiveTextSelection="" * justificationRule="AUTO" * justificationStyle="AUTO" * kerning="AUTO" * leadingModel="AUTO" * ligatureLevel="COMMON" * lineHeight="120%" * lineThrough="false" * listAutoPadding="40" * listStylePosition="outside" * listStyleType="disc" * locale="en" * paragraphEndIndent="0" * paragraphSpaceAfter="0" * paragraphSpaceBefore="0" * paragraphStartIndent="0" * renderingMode="CFF" * tabStops="null" * textAlign="START" * textAlignLast="START" * textAlpha="1" * textDecoration="NONE" * textIndent="0" * textJustify="INTER_WORD" * textRotation="AUTO" * trackingLeft="0" * trackingRight="0" * typographicCase="DEFAULT" * unfocusedTextSelectionColor="" * whiteSpaceCollapse="COLLAPSE" * wordSpacing="100%,50%,150%" * /> ** * @see spark.components.Spinner * @see spark.skins.spark.NumericStepperSkin * @see spark.skins.spark.NumericStepperTextInputSkin * * @includeExample examples/NumericStepperExample.mxml * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public class NumericStepper extends Spinner implements IFocusManagerComponent, IIMESupport { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Class mixins // //-------------------------------------------------------------------------- /** * @private * Placeholder for mixin by SpinnerAccImpl. */ mx_internal static var createAccessibilityImplementation:Function; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function NumericStepper() { super(); maximum = 10; } //-------------------------------------------------------------------------- // // Skin parts // //-------------------------------------------------------------------------- [SkinPart(required="true")] /** * A skin part that defines a TextInput control * which allows a user to edit the value of * the NumericStepper component. * The value is rounded and committed * when the user presses enter, focuses out of * the NumericStepper, or steps the NumericStepper. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public var textDisplay:TextInput; //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private */ private var dataFormatter:NumberFormatter; //-------------------------------------------------------------------------- // // Overridden properties: UIComponent // //-------------------------------------------------------------------------- //---------------------------------- // baselinePosition //---------------------------------- /** * @private */ override public function get baselinePosition():Number { return getBaselinePositionForPart(textDisplay); } //-------------------------------------------------------------------------- // // Overridden Properties: Range // //-------------------------------------------------------------------------- //--------------------------------- // maximum //--------------------------------- /** * @private */ private var maxChanged:Boolean = false; [Inspectable(category="General", defaultValue="10.0")] /** * Number which represents the maximum value possible for *
value
. If the values for either
* minimum
or value
are greater
* than maximum
, they will be changed to
* reflect the new maximum
*
* @default 10
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
override public function set maximum(value:Number):void
{
maxChanged = true;
super.maximum = value;
}
//---------------------------------
// stepSize
//---------------------------------
/**
* @private
*/
private var stepSizeChanged:Boolean = false;
[Inspectable(category="General", defaultValue="1.0", minValue="0.0")]
/**
* @private
*/
override public function set stepSize(value:Number):void
{
stepSizeChanged = true;
super.stepSize = value;
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// enableIME
//----------------------------------
/**
* A flag that indicates whether the IME should
* be enabled when the component receives focus.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get enableIME():Boolean
{
if (textDisplay && textDisplay.textDisplay)
return textDisplay.textDisplay.editable;
// most numeric steppers will be editable
return true;
}
//----------------------------------
// maxChars
//----------------------------------
/**
* @private
* Storage for the maxChars property.
*/
private var _maxChars:int = 0;
/**
* @private
*/
private var maxCharsChanged:Boolean = false;
[Inspectable(category="General", defaultValue="0")]
/**
* The maximum number of characters that can be entered in the field.
* A value of 0 means that any number of characters can be entered.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get maxChars():int
{
return _maxChars;
}
/**
* @private
*/
public function set maxChars(value:int):void
{
if (value == _maxChars)
return;
_maxChars = value;
maxCharsChanged = true;
invalidateProperties();
}
//---------------------------------
// valueFormatFunction
//---------------------------------
/**
* @private
*/
private var _valueFormatFunction:Function;
/**
* @private
*/
private var valueFormatFunctionChanged:Boolean;
/**
* Callback function that formats the value displayed
* in the skin's textDisplay
property.
* The function takes a single Number as an argument
* and returns a formatted String.
*
* The function has the following signature:
** funcName(value:Number):String ** @default undefined * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get valueFormatFunction():Function { return _valueFormatFunction; } /** * @private */ public function set valueFormatFunction(value:Function):void { _valueFormatFunction = value; valueFormatFunctionChanged = true; invalidateProperties(); } //--------------------------------- // valueParseFunction //--------------------------------- /** * @private */ private var _valueParseFunction:Function; /** * @private */ private var valueParseFunctionChanged:Boolean; /** * Callback function that extracts the numeric * value from the displayed value in the * skin's
textDisplay
field.
*
* The function takes a single String as an argument
* and returns a Number.
*
* The function has the following signature:
** funcName(value:String):Number ** @default undefined * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get valueParseFunction():Function { return _valueParseFunction; } /** * @private */ public function set valueParseFunction(value:Function):void { _valueParseFunction = value; valueParseFunctionChanged = true; invalidateProperties(); } //---------------------------------- // imeMode //---------------------------------- /** * @private */ private var _imeMode:String = null; /** * @private */ private var imeModeChanged:Boolean = false; /** * Specifies the IME (Input Method Editor) mode. * The IME enables users to enter text in Chinese, Japanese, and Korean. * Flex sets the specified IME mode when the control gets the focus * and sets it back to previous value when the control loses the focus. * *
The flash.system.IMEConversionMode class defines constants for the
* valid values for this property.
* You can also specify null
to specify no IME.
textDisplay
* to the value
property.
* This method uses the nearestValidValue()
method
* to round the input value to the closest valid value.
* Valid values are defined by the sum of the minimum
* with integer multiples of the snapInterval. It is also
* constrained by and includes the maximum
property.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
private function commitTextInput(dispatchChange:Boolean = false):void
{
var inputValue:Number;
var prevValue:Number = value;
if (valueParseFunction != null)
{
inputValue = valueParseFunction(textDisplay.text);
}
else
{
if (dataFormatter == null)
dataFormatter = new NumberFormatter(LocaleID.DEFAULT);
inputValue = dataFormatter.parseNumber(textDisplay.text);
}
if ((textDisplay.text && textDisplay.text.length != value.toString().length)
|| textDisplay.text == "" || (inputValue != value &&
(Math.abs(inputValue - value) >= 0.000001 || isNaN(inputValue))))
{
setValue(nearestValidValue(inputValue, snapInterval));
// Dispatch valueCommit if the display needs to change.
if (value == prevValue && inputValue != prevValue)
dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
}
if (dispatchChange)
{
if (value != prevValue)
dispatchEvent(new Event(Event.CHANGE));
}
}
/**
* @private
* Helper method that returns a number corresponding
* to the length of the maximum value displayable in
* the textDisplay.
*/
private function calculateWidestValue():Number
{
var widestNumber:Number = minimum.toString().length >
maximum.toString().length ?
minimum :
maximum;
widestNumber += stepSize;
if (valueFormatFunction != null)
return valueFormatFunction(widestNumber).length;
else
return widestNumber.toString().length;
}
/**
* @private
* Helper method that applies the valueFormatFunction
*/
private function applyDisplayFormatFunction():void
{
if (valueFormatFunction != null)
textDisplay.text = valueFormatFunction(value);
else
textDisplay.text = value.toString();
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function focusInHandler(event:FocusEvent):void
{
super.focusInHandler(event);
addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
}
/**
* @private
*/
override protected function focusOutHandler(event:FocusEvent):void
{
super.focusOutHandler(event);
removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
}
/**
* @private
* When the enter key is pressed, NumericStepper commits the
* text currently displayed.
*/
private function textDisplay_enterHandler(event:Event):void
{
commitTextInput(true);
}
/**
* @private
* When the enter key is pressed, NumericStepper commits the
* text currently displayed.
*/
private function textDisplay_focusOutHandler(event:Event):void
{
commitTextInput(true);
}
}
}