| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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.CurrencyFormatter", since="4.5")] |
| /** |
| * The CurrencyFormatter class formats a valid number as a currency value. |
| * It adjusts the decimal rounding and precision, the thousands separator, |
| * and the negative sign; it also adds a currency symbol. |
| * You place the currency symbol on either the left or the right side |
| * of the value with the <code>alignSymbol</code> property. |
| * The currency symbol can contain multiple characters, |
| * including blank spaces. |
| * |
| * <p>If an error occurs, an empty String is returned and a String that describes |
| * 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 contains an unusable setting.</li> |
| * </ul> |
| * |
| * @mxml |
| * |
| * <p>The <code><mx:CurrencyFormatter></code> tag |
| * inherits all of the tag attributes of its superclass, |
| * and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <mx:CurrencyFormatter |
| * alignSymbol="left|right" |
| * currencySymbol="$" |
| * decimalSeparatorFrom="." |
| * decimalSeparatorTo="." |
| * precision="-1" |
| * rounding="none|up|down|nearest" |
| * thousandsSeparatorFrom="," |
| * thousandsSeparatorTo="," |
| * useNegativeSign="true|false" |
| * useThousandsSeparator="true|false" |
| * /> |
| * </pre> |
| * |
| * @includeExample examples/CurrencyFormatterExample.mxml |
| * |
| * @see mx.formatters.NumberBase |
| * @see mx.formatters.NumberBaseRoundType |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class CurrencyFormatter extends Formatter |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function CurrencyFormatter() |
| { |
| super(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // alignSymbol |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the alignSymbol property. |
| */ |
| private var _alignSymbol:String; |
| |
| /** |
| * @private |
| */ |
| private var alignSymbolOverride:String; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Aligns currency symbol to the left side or the right side |
| * of the formatted number. |
| * Permitted values are <code>"left"</code> and <code>"right"</code>. |
| * |
| * @default "left" |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get alignSymbol():String |
| { |
| return _alignSymbol; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set alignSymbol(value:String):void |
| { |
| alignSymbolOverride = value; |
| |
| _alignSymbol = value != null ? |
| value : |
| resourceManager.getString( |
| "SharedResources", "alignSymbol"); |
| } |
| |
| //---------------------------------- |
| // currencySymbol |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the currencySymbol property. |
| */ |
| private var _currencySymbol:String; |
| |
| /** |
| * @private |
| */ |
| private var currencySymbolOverride:String; |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * Character to use as a currency symbol for a formatted number. |
| * You can use one or more characters to represent the currency |
| * symbol; for example, "$" or "YEN". |
| * You can also use empty spaces to add space between the |
| * currency character and the formatted number. |
| * When the number is a negative value, the currency symbol |
| * appears between the number and the minus sign or parentheses. |
| * |
| * @default "$" |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get currencySymbol():String |
| { |
| return _currencySymbol; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set currencySymbol(value:String):void |
| { |
| currencySymbolOverride = value; |
| |
| _currencySymbol = value != null ? |
| value : |
| resourceManager.getString( |
| "SharedResources", "currencySymbol"); |
| } |
| |
| //---------------------------------- |
| // 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. |
| * |
| * @default "." |
| * |
| * @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. |
| * |
| * @default "." |
| * |
| * @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 1.453. |
| * If <code>precision</code> is -1 and you 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", "currencyFormatterPrecision"); |
| } |
| |
| //---------------------------------- |
| // 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")] |
| |
| /** |
| * How to round the number. |
| * In ActionScript, the value can be <code>NumberBaseRoundType.NONE</code>, |
| * <code>NumberBaseRoundType.UP</code>, |
| * <code>NumberBaseRoundType.DOWN</code>, or <code>NumberBaseRoundType.NEAREST</code>. |
| * In MXML, the value can be <code>"none"</code>, |
| * <code>"up"</code>, <code>"down"</code>, or <code>"nearest"</code>. |
| * |
| * @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. |
| * |
| * @default "," |
| * |
| * @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. |
| * |
| * @default "," |
| * |
| * @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", "useNegativeSignInCurrency"); |
| } |
| |
| //---------------------------------- |
| // 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(); |
| |
| alignSymbol = alignSymbolOverride; |
| currencySymbol = currencySymbolOverride; |
| decimalSeparatorFrom = decimalSeparatorFromOverride; |
| decimalSeparatorTo = decimalSeparatorToOverride; |
| precision = precisionOverride; |
| rounding = roundingOverride; |
| thousandsSeparatorFrom = thousandsSeparatorFromOverride; |
| thousandsSeparatorTo = thousandsSeparatorToOverride; |
| useNegativeSign = useNegativeSignOverride; |
| useThousandsSeparator = useThousandsSeparatorOverride; |
| } |
| |
| /** |
| * Formats <code>value</code> as currency. |
| * 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 == "") |
| { |
| error = defaultInvalidFormatError; |
| return ""; |
| } |
| |
| var dataFormatter:NumberBase = new NumberBase(decimalSeparatorFrom, |
| thousandsSeparatorFrom, |
| decimalSeparatorTo, |
| thousandsSeparatorTo); |
| |
| // -- value -- |
| |
| if (value is String) |
| { |
| var temp_value:String = dataFormatter.parseNumberString(String(value)); |
| |
| // If we got 0 back, but string was longer than one character, NumberBase |
| // Chopped our value. So we need to do some formatting to get our value back |
| // to the way it was. |
| if (temp_value == "0") |
| { |
| var valueArr:Array = value.split(decimalSeparatorFrom); |
| value = valueArr[0]; |
| if (valueArr[1] != undefined) |
| value += "." + valueArr[1]; |
| else |
| value = temp_value; |
| } |
| else |
| value = temp_value; |
| } |
| |
| if (value === null || isNaN(Number(value))) |
| { |
| error = defaultInvalidValueError; |
| return ""; |
| } |
| |
| // -- format -- |
| |
| var isNegative:Boolean = (Number(value) < 0); |
| |
| var numStr:String = value.toString(); |
| 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) |
| { |
| // if the value is in scientefic notation then the search for '.' |
| // doesnot give the correct result. Adding one to the value forces |
| // the value to normal decimal notation. |
| // As we are dealing with only the decimal portion we need not |
| // worry about reverting the addition |
| if (numStr.indexOf("e") != -1) |
| { |
| var temp:Number = Math.abs(numValue) + 1; |
| numStr = temp.toString(); |
| } |
| |
| // Handle leading zero if we got one give one if not don't |
| var position:Number = numStr.indexOf("."); |
| var leading:String = position > 0 ? "0" : ""; |
| |
| // must be zero ("0") if no "." and >= 0 and < 1 |
| if (position != -1) |
| { |
| numStr = leading + decimalSeparatorTo + |
| numStr.substring(position + 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 ""; |
| } |
| |
| // -- currency -- |
| |
| if (alignSymbol == "left") |
| { |
| if (isNegative) |
| { |
| var nSign:String = numStr.charAt(0); |
| var baseVal:String = numStr.substr(1, numStr.length - 1); |
| numStr = nSign + currencySymbol + baseVal; |
| } |
| else |
| { |
| numStr = currencySymbol + numStr; |
| } |
| } |
| else if (alignSymbol == "right") |
| { |
| var lastChar:String = numStr.charAt(numStr.length - 1); |
| if (isNegative && lastChar == ")") |
| { |
| baseVal = numStr.substr(0, numStr.length - 1); |
| numStr = baseVal + currencySymbol + lastChar; |
| } |
| else |
| { |
| numStr = numStr + currencySymbol; |
| } |
| } |
| else |
| { |
| error = defaultInvalidFormatError; |
| return ""; |
| } |
| |
| return numStr; |
| } |
| } |
| |
| } |