| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 mx.formatters |
| { |
| |
| import mx.managers.ISystemManager; |
| import mx.managers.SystemManager; |
| |
| [ResourceBundle("formatters")] |
| [ResourceBundle("SharedResources")] |
| |
| [Alternative(replacement="spark.formatters.NumberFormatter", since="4.5")] |
| /** |
| * The NumberFormatter class formats a valid number |
| * by adjusting the decimal rounding and precision, |
| * the thousands separator, and the negative sign. |
| * |
| * <p>If you use both the <code>rounding</code> and <code>precision</code> |
| * properties, rounding is applied first, and then you set the decimal length |
| * by using the specified <code>precision</code> value. |
| * This lets you round a number and still have a trailing decimal; |
| * for example, 303.99 = 304.00.</p> |
| * |
| * <p>If an error occurs, an empty String is returned and a String |
| * describing the error is saved to the <code>error</code> property. |
| * The <code>error</code> property can have one of the following values:</p> |
| * |
| * <ul> |
| * <li><code>"Invalid value"</code> means an invalid numeric value is passed to |
| * the <code>format()</code> method. The value should be a valid number in the |
| * form of a Number or a String.</li> |
| * <li><code>"Invalid format"</code> means one of the parameters |
| * contain an unusable setting.</li> |
| * </ul> |
| * |
| * @mxml |
| * |
| * <p>The <code><mx:NumberFormatter></code> tag |
| * inherits all of the tag attributes of its superclass, |
| * and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <mx:NumberFormatter |
| * decimalSeparatorFrom="." |
| * decimalSeparatorTo="." |
| * precision="-1" |
| * rounding="none|up|down|nearest" |
| * thousandsSeparatorFrom="," |
| * thousandsSeparatorTo="," |
| * useNegativeSign="true|false" |
| * useThousandsSeparator="true|false"/> |
| * </pre> |
| * |
| * @includeExample examples/NumberFormatterExample.mxml |
| * |
| * @see mx.formatters.NumberBase |
| * @see mx.formatters.NumberBaseRoundType |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class NumberFormatter extends Formatter |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function NumberFormatter() |
| { |
| super(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // decimalSeparatorFrom |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the decimalSeparatorFrom property. |
| */ |
| private var _decimalSeparatorFrom:String; |
| |
| /** |
| * @private |
| */ |
| private var decimalSeparatorFromOverride:String; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Decimal separator character to use |
| * when parsing an input String. |
| * |
| * <p>When setting this property, ensure that the value of the |
| * <code>thousandsSeparatorFrom</code> property does not equal this property. |
| * Otherwise, an error occurs when formatting the value.</p> |
| * |
| * @default "." |
| * |
| * @see #format() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get decimalSeparatorFrom():String |
| { |
| return _decimalSeparatorFrom; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set decimalSeparatorFrom(value:String):void |
| { |
| decimalSeparatorFromOverride = value; |
| |
| _decimalSeparatorFrom = value != null ? |
| value : |
| resourceManager.getString( |
| "SharedResources", "decimalSeparatorFrom"); |
| } |
| |
| //---------------------------------- |
| // decimalSeparatorTo |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the decimalSeparatorTo property. |
| */ |
| private var _decimalSeparatorTo:String; |
| |
| /** |
| * @private |
| */ |
| private var decimalSeparatorToOverride:String; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Decimal separator character to use |
| * when outputting formatted decimal numbers. |
| * |
| * <p>When setting this property, ensure that the value of the |
| * <code>thousandsSeparatorTo</code> property does not equal this property. |
| * Otherwise, an error occurs when formatting the value.</p> |
| * |
| * @default "." |
| * |
| * @see #format() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get decimalSeparatorTo():String |
| { |
| return _decimalSeparatorTo; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set decimalSeparatorTo(value:String):void |
| { |
| decimalSeparatorToOverride = value; |
| |
| _decimalSeparatorTo = value != null ? |
| value : |
| resourceManager.getString( |
| "SharedResources", "decimalSeparatorTo"); |
| } |
| |
| //---------------------------------- |
| // precision |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the precision property. |
| */ |
| private var _precision:Object; |
| |
| /** |
| * @private |
| */ |
| private var precisionOverride:Object; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Number of decimal places to include in the output String. |
| * You can disable precision by setting it to <code>-1</code>. |
| * A value of <code>-1</code> means do not change the precision. For example, |
| * if the input value is 1.453 and <code>rounding</code> |
| * is set to <code>NumberBaseRoundType.NONE</code>, return a value of 1.453. |
| * If <code>precision</code> is <code>-1</code> and you have set some form of |
| * rounding, return a value based on that rounding type. |
| * |
| * @default -1 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get precision():Object |
| { |
| return _precision; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set precision(value:Object):void |
| { |
| precisionOverride = value; |
| |
| _precision = value != null ? |
| int(value) : |
| resourceManager.getInt( |
| "formatters", "numberFormatterPrecision"); |
| } |
| |
| //---------------------------------- |
| // rounding |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the rounding property. |
| */ |
| private var _rounding:String; |
| |
| /** |
| * @private |
| */ |
| private var roundingOverride:String; |
| |
| [Inspectable(category="General", enumeration="none,up,down,nearest", defaultValue="null")] |
| // !!@ Should enumeration include null? |
| |
| /** |
| * Specifies how to round the number. |
| * |
| * <p>In ActionScript, you can use the following constants to set this property: |
| * <code>NumberBaseRoundType.NONE</code>, <code>NumberBaseRoundType.UP</code>, |
| * <code>NumberBaseRoundType.DOWN</code>, or <code>NumberBaseRoundType.NEAREST</code>. |
| * Valid MXML values are "down", "nearest", "up", and "none".</p> |
| * |
| * @default NumberBaseRoundType.NONE |
| * |
| * @see mx.formatters.NumberBaseRoundType |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get rounding():String |
| { |
| return _rounding; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set rounding(value:String):void |
| { |
| roundingOverride = value; |
| |
| _rounding = value != null ? |
| value : |
| resourceManager.getString( |
| "formatters", "rounding"); |
| } |
| |
| //---------------------------------- |
| // thousandsSeparatorFrom |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the thousandsSeparatorFrom property. |
| */ |
| private var _thousandsSeparatorFrom:String; |
| |
| /** |
| * @private |
| */ |
| private var thousandsSeparatorFromOverride:String; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Character to use as the thousands separator |
| * in the input String. |
| * |
| * <p>When setting this property, ensure that the value of the |
| * <code>decimalSeparatorFrom</code> property does not equal this property. |
| * Otherwise, an error occurs when formatting the value.</p> |
| * |
| * @default "," |
| * |
| * @see #format() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get thousandsSeparatorFrom():String |
| { |
| return _thousandsSeparatorFrom; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set thousandsSeparatorFrom(value:String):void |
| { |
| thousandsSeparatorFromOverride = value; |
| |
| _thousandsSeparatorFrom = value != null ? |
| value : |
| resourceManager.getString( |
| "SharedResources", |
| "thousandsSeparatorFrom"); |
| } |
| |
| //---------------------------------- |
| // thousandsSeparatorTo |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the thousandsSeparatorTo property. |
| */ |
| private var _thousandsSeparatorTo:String; |
| |
| /** |
| * @private |
| */ |
| private var thousandsSeparatorToOverride:String; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Character to use as the thousands separator |
| * in the output String. |
| * |
| * <p>When setting this property, ensure that the value of the |
| * <code>decimalSeparatorTo</code> property does not equal this property. |
| * Otherwise, an error occurs when formatting the value.</p> |
| * |
| * @default "," |
| * |
| * @see #format() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get thousandsSeparatorTo():String |
| { |
| return _thousandsSeparatorTo; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set thousandsSeparatorTo(value:String):void |
| { |
| thousandsSeparatorToOverride = value; |
| |
| _thousandsSeparatorTo = value != null ? |
| value : |
| resourceManager.getString( |
| "SharedResources", |
| "thousandsSeparatorTo"); |
| } |
| |
| //---------------------------------- |
| // useNegativeSign |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the useNegativeSign property. |
| */ |
| private var _useNegativeSign:Object; |
| |
| /** |
| * @private |
| */ |
| private var useNegativeSignOverride:Object; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * If <code>true</code>, format a negative number |
| * by preceding it with a minus "-" sign. |
| * If <code>false</code>, format the number |
| * surrounded by parentheses, for example (400). |
| * |
| * @default true |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get useNegativeSign():Object |
| { |
| return _useNegativeSign; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set useNegativeSign(value:Object):void |
| { |
| useNegativeSignOverride = value; |
| |
| _useNegativeSign = value != null ? |
| Boolean(value) : |
| resourceManager.getBoolean( |
| "formatters", "useNegativeSignInNumber"); |
| } |
| |
| //---------------------------------- |
| // useThousandsSeparator |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the useThousandsSeparator property. |
| */ |
| private var _useThousandsSeparator:Object; |
| |
| /** |
| * @private |
| */ |
| private var useThousandsSeparatorOverride:Object; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * If <code>true</code>, split the number into thousands increments |
| * by using a separator character. |
| * |
| * @default true |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get useThousandsSeparator():Object |
| { |
| return _useThousandsSeparator; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set useThousandsSeparator(value:Object):void |
| { |
| useThousandsSeparatorOverride = value; |
| |
| _useThousandsSeparator = value != null ? |
| Boolean(value) : |
| resourceManager.getBoolean( |
| "formatters", "useThousandsSeparator"); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function resourcesChanged():void |
| { |
| super.resourcesChanged(); |
| |
| decimalSeparatorFrom = decimalSeparatorFromOverride; |
| decimalSeparatorTo = decimalSeparatorToOverride; |
| precision = precisionOverride; |
| rounding = roundingOverride; |
| thousandsSeparatorFrom = thousandsSeparatorFromOverride; |
| thousandsSeparatorTo = thousandsSeparatorToOverride; |
| useNegativeSign = useNegativeSignOverride; |
| useThousandsSeparator = useThousandsSeparatorOverride; |
| } |
| |
| /** |
| * Formats the number as a String. |
| * If <code>value</code> cannot be formatted, return an empty String |
| * and write a description of the error to the <code>error</code> property. |
| * |
| * @param value Value to format. |
| * |
| * @return Formatted String. Empty if an error occurs. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override public function format(value:Object):String |
| { |
| // Reset any previous errors. |
| if (error) |
| error = null; |
| |
| if (useThousandsSeparator && |
| ((decimalSeparatorFrom == thousandsSeparatorFrom) || |
| (decimalSeparatorTo == thousandsSeparatorTo))) |
| { |
| error = defaultInvalidFormatError; |
| return ""; |
| } |
| |
| if (decimalSeparatorTo == "" || !isNaN(Number(decimalSeparatorTo))) |
| { |
| error = defaultInvalidFormatError; |
| return ""; |
| } |
| |
| var dataFormatter:NumberBase = new NumberBase(decimalSeparatorFrom, |
| thousandsSeparatorFrom, |
| decimalSeparatorTo, |
| thousandsSeparatorTo); |
| |
| // -- value -- |
| |
| if (value is String) |
| value = dataFormatter.parseNumberString(String(value)); |
| |
| if (value === null || isNaN(Number(value))) |
| { |
| error = defaultInvalidValueError; |
| return ""; |
| } |
| |
| // -- format -- |
| |
| var isNegative:Boolean = (Number(value) < 0); |
| |
| var numStr:String = value.toString(); |
| |
| numStr = numStr.toLowerCase(); |
| var e:int = numStr.indexOf("e"); |
| if (e != -1) //deal with exponents |
| numStr = dataFormatter.expandExponents(numStr); |
| |
| var numArrTemp:Array = numStr.split("."); |
| var numFraction:int = numArrTemp[1] ? String(numArrTemp[1]).length : 0; |
| |
| if (precision < numFraction) |
| { |
| if (rounding != NumberBaseRoundType.NONE) |
| { |
| numStr = dataFormatter.formatRoundingWithPrecision( |
| numStr, rounding, int(precision)); |
| } |
| } |
| |
| var numValue:Number = Number(numStr); |
| if (Math.abs(numValue) >= 1) |
| { |
| numArrTemp = numStr.split("."); |
| var front:String = useThousandsSeparator ? |
| dataFormatter.formatThousands(String(numArrTemp[0])) : |
| String(numArrTemp[0]); |
| if (numArrTemp[1] != null && numArrTemp[1] != "") |
| numStr = front + decimalSeparatorTo + numArrTemp[1]; |
| else |
| numStr = front; |
| } |
| else if (Math.abs(numValue) > 0) |
| { |
| // Check if the string is in scientific notation |
| numStr = numStr.toLowerCase(); |
| if (numStr.indexOf("e") != -1) |
| { |
| var temp:Number = Math.abs(numValue) + 1; |
| numStr = temp.toString(); |
| } |
| numStr = decimalSeparatorTo + |
| numStr.substring(numStr.indexOf(".") + 1); |
| } |
| |
| numStr = dataFormatter.formatPrecision(numStr, int(precision)); |
| |
| // If our value is 0, then don't show -0 |
| if (Number(numStr) == 0) |
| { |
| isNegative = false; |
| } |
| |
| if (isNegative) |
| numStr = dataFormatter.formatNegative(numStr, useNegativeSign); |
| |
| if (!dataFormatter.isValid) |
| { |
| error = defaultInvalidFormatError; |
| return ""; |
| } |
| |
| return numStr; |
| } |
| } |
| |
| } |