//////////////////////////////////////////////////////////////////////////////// // // 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 alignSymbol property. * The currency symbol can contain multiple characters, * including blank spaces. * *

If an error occurs, an empty String is returned and a String that describes * the error is saved to the error property. The error * property can have one of the following values:

* * * * @mxml * *

The <mx:CurrencyFormatter> tag * inherits all of the tag attributes of its superclass, * and adds the following tag attributes:

* *
 *  <mx:CurrencyFormatter
 *    alignSymbol="left|right" 
 *    currencySymbol="$"
 *    decimalSeparatorFrom="."
 *    decimalSeparatorTo="."
 *    precision="-1"
 *    rounding="none|up|down|nearest"
 *    thousandsSeparatorFrom=","
 *    thousandsSeparatorTo=","
 *    useNegativeSign="true|false"
 *    useThousandsSeparator="true|false"
 *	/>  
 *  
* * @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 "left" and "right". * * @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 -1. * A value of -1 means do not change the precision. For example, * if the input value is 1.453 and rounding * is set to NumberBaseRoundType.NONE, return 1.453. * If precision 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 NumberBaseRoundType.NONE, * NumberBaseRoundType.UP, * NumberBaseRoundType.DOWN, or NumberBaseRoundType.NEAREST. * In MXML, the value can be "none", * "up", "down", or "nearest". * * @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 true, format a negative number * by preceding it with a minus "-" sign. * If false, 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 true, 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 value as currency. * If value cannot be formatted, return an empty String * and write a description of the error to the error 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" : ""; 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; } } }