This is an automated email from the ASF dual-hosted git repository. carlosrovira pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push: new 316fc1a MX CurrencyFormatter compile ok 316fc1a is described below commit 316fc1a62b9d798f1525e76d060215e2d972ab8f Author: Carlos Rovira <carlosrov...@apache.org> AuthorDate: Sat Nov 24 19:37:29 2018 +0100 MX CurrencyFormatter compile ok --- .../MXRoyale/src/main/royale/MXRoyaleClasses.as | 3 + .../main/royale/mx/formatters/CurrencyFormatter.as | 791 +++++++++++++++++++++ .../src/main/royale/mx/formatters/Formatter.as | 44 +- .../src/main/royale/mx/formatters/NumberBase.as | 625 ++++++++++++++++ .../royale/mx/formatters/NumberBaseRoundType.as | 89 +++ 5 files changed, 1530 insertions(+), 22 deletions(-) diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as index 734e9c5..f6796d2 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as +++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as @@ -155,6 +155,9 @@ internal class MXRoyaleClasses import mx.controls.advancedDataGridClasses.MXAdvancedDataGridItemRenderer; MXAdvancedDataGridItemRenderer; import mx.formatters.Formatter; Formatter; import mx.formatters.IFormatter; IFormatter; + import mx.formatters.NumberBase; NumberBase; + import mx.formatters.NumberBaseRoundType; NumberBaseRoundType; + import mx.formatters.CurrencyFormatter; CurrencyFormatter; import mx.events.CalendarLayoutChangeEvent; CalendarLayoutChangeEvent; import mx.net.SharedObject; SharedObject; import mx.modules.ModuleManager; ModuleManager; diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/CurrencyFormatter.as b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/CurrencyFormatter.as new file mode 100644 index 0000000..f360ed8 --- /dev/null +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/CurrencyFormatter.as @@ -0,0 +1,791 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 : "right"; + // 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) : -1; + // 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 : "none"; + // 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) : true; + // 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) : true; + // 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; + } +} + +} diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/Formatter.as b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/Formatter.as index a62c38c..92fe7d1 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/Formatter.as +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/Formatter.as @@ -29,7 +29,7 @@ import mx.managers.SystemManager; use namespace mx_internal; -[ResourceBundle("formatters")] +// [ResourceBundle("formatters")] /** * The Formatter class is the base class for all data formatters. @@ -107,12 +107,12 @@ public class Formatter implements IFormatter * @private * Storage for the defaultInvalidFormatError property. */ - //private static var _defaultInvalidFormatError:String + private static var _defaultInvalidFormatError:String /** * @private */ - //private static var defaultInvalidFormatErrorOverride:String + private static var defaultInvalidFormatErrorOverride:String /** * Error message for an invalid format string specified to the formatter. @@ -128,26 +128,26 @@ public class Formatter implements IFormatter * @playerversion AIR 1.1 * @productversion Flex 3 */ - /* public static function get defaultInvalidFormatError():String + public static function get defaultInvalidFormatError():String { - initialize(); + // initialize(); return _defaultInvalidFormatError; - } */ + } /** * @private */ - /* public static function set defaultInvalidFormatError(value:String):void + public static function set defaultInvalidFormatError(value:String):void { defaultInvalidFormatErrorOverride = value; _defaultInvalidFormatError = value != null ? - value : - static_resourceManager.getString( - "formatters", "defaultInvalidFormatError"); - } */ + value : "Invalid format"; + // static_resourceManager.getString( + // "formatters", "defaultInvalidFormatError"); + } //---------------------------------- // defaultInvalidValueError @@ -157,12 +157,12 @@ public class Formatter implements IFormatter * @private * Storage for the defaultInvalidValueError property. */ - //private static var _defaultInvalidValueError:String + private static var _defaultInvalidValueError:String /** * @private */ - //private static var defaultInvalidValueErrorOverride:String + private static var defaultInvalidValueErrorOverride:String /** * Error messages for an invalid value specified to the formatter. The @@ -178,26 +178,26 @@ public class Formatter implements IFormatter * @playerversion AIR 1.1 * @productversion Flex 3 */ - /* public static function get defaultInvalidValueError():String + public static function get defaultInvalidValueError():String { - initialize(); + // initialize(); return _defaultInvalidValueError; - } */ + } /** * @private */ - /* public static function set defaultInvalidValueError(value:String):void + public static function set defaultInvalidValueError(value:String):void { defaultInvalidValueErrorOverride = value; _defaultInvalidValueError = value != null ? - value : - static_resourceManager.getString( - "formatters", "defaultInvalidValueError"); - } */ + value : "Invalid value"; + // static_resourceManager.getString( + // "formatters", "defaultInvalidValueError"); + } //-------------------------------------------------------------------------- // @@ -299,7 +299,7 @@ public class Formatter implements IFormatter * @playerversion AIR 1.1 * @productversion Flex 3 */ - //public var error:String; + public var error:String; //---------------------------------- // resourceManager diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/NumberBase.as b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/NumberBase.as new file mode 100644 index 0000000..d7e7829 --- /dev/null +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/NumberBase.as @@ -0,0 +1,625 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + +/** + * The NumberBase class is a utility class that contains + * general number formatting capabilities, including rounding, + * precision, thousands formatting, and negative sign formatting. + * The implementation of the formatter classes use this class. + * + * @see mx.formatters.NumberFormatter + * @see mx.formatters.NumberBaseRoundType + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ +public class NumberBase +{ + // include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * Constructor. + * + * @param decimalSeparatorFrom Decimal separator to use + * when parsing an input String. + * + * @param thousandsSeparatorFrom Character to use + * as the thousands separator in the input String. + * + * @param decimalSeparatorTo Decimal separator character to use + * when outputting formatted decimal numbers. + * + * @param thousandsSeparatorTo Character to use + * as the thousands separator in the output String. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function NumberBase(decimalSeparatorFrom:String = ".", + thousandsSeparatorFrom:String = ",", + decimalSeparatorTo:String = ".", + thousandsSeparatorTo:String = ",") + { + super(); + + this.decimalSeparatorFrom = decimalSeparatorFrom; + this.thousandsSeparatorFrom = thousandsSeparatorFrom; + this.decimalSeparatorTo = decimalSeparatorTo; + this.thousandsSeparatorTo = thousandsSeparatorTo; + + isValid = true; + } + + //-------------------------------------------------------------------------- + // + // Properties + // + //-------------------------------------------------------------------------- + + //---------------------------------- + // decimalSeparatorFrom + //---------------------------------- + + /** + * 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 var decimalSeparatorFrom:String; + + //---------------------------------- + // decimalSeparatorTo + //---------------------------------- + + /** + * 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 var decimalSeparatorTo:String; + + //---------------------------------- + // isValid + //---------------------------------- + + /** + * If <code>true</code>, the format succeeded, + * otherwise it is <code>false</code>. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public var isValid:Boolean = false; + + //---------------------------------- + // thousandsSeparatorFrom + //---------------------------------- + + /** + * 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 var thousandsSeparatorFrom:String; + + //---------------------------------- + // thousandsSeparatorTo + //---------------------------------- + + /** + * 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 var thousandsSeparatorTo:String; + + //-------------------------------------------------------------------------- + // + // Methods + // + //-------------------------------------------------------------------------- + + /** + * Formats a number by rounding it. + * The possible rounding types are defined by + * mx.formatters.NumberBaseRoundType. + * + * @param value Value to be rounded. + * + * @param roundType The type of rounding to perform: + * NumberBaseRoundType.NONE, NumberBaseRoundType.UP, + * NumberBaseRoundType.DOWN, or NumberBaseRoundType.NEAREST. + * + * @return Formatted number. + * + * @see mx.formatters.NumberBaseRoundType + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function formatRounding(value:String, roundType:String):String + { + var v:Number = Number(value); + + if (roundType != NumberBaseRoundType.NONE) + { + if (roundType == NumberBaseRoundType.UP) + { + v = Math.ceil(v); + } + else if (roundType == NumberBaseRoundType.DOWN) + { + v = Math.floor(v); + } + else if (roundType == NumberBaseRoundType.NEAREST) + { + v = Math.round(v); + } + else + { + isValid = false; + return ""; + } + } + + return v.toString(); + } + + /** + * Formats a number by rounding it and setting the decimal precision. + * The possible rounding types are defined by + * mx.formatters.NumberBaseRoundType. + * + * @param value Value to be rounded. + * + * @param roundType The type of rounding to perform: + * NumberBaseRoundType.NONE, NumberBaseRoundType.UP, + * NumberBaseRoundType.DOWN, or NumberBaseRoundType.NEAREST. + * + * @param precision int of decimal places to use. + * + * @return Formatted number. + * + * @see mx.formatters.NumberBaseRoundType + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function formatRoundingWithPrecision(value:String, roundType:String, + precision:int):String + { + // precision works differently now. Its default value is -1 + // which means 'do not alter the number's precision'. If a precision + // value is set, all numbers will contain that precision. Otherwise, there + // precision will not be changed. + + var v:Number = Number(value); + + // If rounding is not present and precision is NaN, + // leave value untouched. + if (roundType == NumberBaseRoundType.NONE) + { + if (precision == -1) + return v.toString(); + } + else + { + // If rounding is present but precision is less than 0, + // then do integer rounding. + if (precision < 0) + precision = 0; + + // Shift decimal right as Math functions + // perform only integer ceil/round/floor. + v = v * Math.pow(10, precision); + + // Attempt to get rid of floating point errors + v = Number(v.toString()); + if (roundType == NumberBaseRoundType.UP) + { + v = Math.ceil(v); + } + else if (roundType == NumberBaseRoundType.DOWN) + { + v = Math.floor(v); + } + else if (roundType == NumberBaseRoundType.NEAREST) + { + v = Math.round(v); + } + else + { + isValid = false; + return ""; + } + + // Shift decimal left to get back decimal to original point. + v = v / Math.pow(10, precision); + } + + return v.toString(); + } + + /** + * Formats a number by replacing the default decimal separator, ".", + * with the decimal separator specified by <code>decimalSeparatorTo</code>. + * + * @param value The String value of the Number + * (formatted American style ####.##). + * + * @return String representation of the input where "." is replaced + * with the decimal formatting character. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function formatDecimal(value:String):String + { + var parts:Array = value.split("."); + return parts.join(decimalSeparatorTo); + } + + /** + * Formats a number by using + * the <code>thousandsSeparatorTo</code> property as the thousands separator + * and the <code>decimalSeparatorTo</code> property as the decimal separator. + * + * @param value Value to be formatted. + * + * @return Formatted number. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function formatThousands(value:String):String + { + var v:Number = Number(value); + + var isNegative:Boolean = (v < 0); + + var numStr:String = Math.abs(v).toString(); + + numStr.toLowerCase(); + var e:int = numStr.indexOf("e") + if (e != -1) //deal with exponents + numStr = expandExponents(numStr); + + var numArr:Array = + numStr.split((numStr.indexOf(decimalSeparatorTo) != -1) ? decimalSeparatorTo : "."); + var numLen:int = String(numArr[0]).length; + + if (numLen > 3) + { + var numSep:int = int(Math.floor(numLen / 3)); + + if ((numLen % 3) == 0) + numSep--; + + var b:int = numLen; + var a:int = b - 3; + + var arr:Array = []; + for (var i:int = 0; i <= numSep; i++) + { + arr[i] = numArr[0].slice(a, b); + a = int(Math.max(a - 3, 0)); + b = int(Math.max(b - 3, 1)); + } + + arr.reverse(); + + numArr[0] = arr.join(thousandsSeparatorTo); + } + + numStr = numArr.join(decimalSeparatorTo); + + if (isNegative) + numStr = "-" + numStr; + + return numStr.toString(); + } + + /** + * Formats a number by setting its decimal precision by using + * the <code>decimalSeparatorTo</code> property as the decimal separator. + * + * @param value Value to be formatted. + * + * @param precision Number of decimal points to use. + * + * @return Formatted number. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function formatPrecision(value:String, precision:int):String + { + // precision works differently now. Its default value is -1 + // which stands for 'do not alter the number's precision'. If a precision + // value is set, all numbers will contain that precision. Otherwise, there + // precision will not be changed. + + if (precision == -1) + return value; + + var numArr:Array = value.split(decimalSeparatorTo); + + numArr[0] = numArr[0].length == 0 ? "0" : numArr[0]; + + if (precision > 0) + { + var decimalVal:String = numArr[1] ? String(numArr[1]) : ""; + var fraction:String = + decimalVal + "000000000000000000000000000000000"; + value = numArr[0] + decimalSeparatorTo + fraction.substr(0, precision); + } + else + { + value = String(numArr[0]); + } + + return value.toString(); + } + + /** + * Formats a negative number with either a minus sign (-) + * or parentheses (). + * + * @param value Value to be formatted. + * + * @param useSign If <code>true</code>, use a minus sign (-). + * If <code>false</code>, use parentheses (). + * + * @return Formatted number. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function formatNegative(value:String, useSign:Boolean):String + { + if (useSign) + { + if (value.charAt(0) != "-") + value = "-" + value; + } + else if (!useSign) + { + if (value.charAt(0) == "-") + value = value.substr(1, value.length - 1); + value = "(" + value + ")"; + } + else + { + isValid = false; + return ""; + } + return value; + } + + /** + * Extracts a number from a formatted String. + * Examines the String from left to right + * and returns the first number sequence. + * Ignores thousands separators and includes the + * decimal and numbers trailing the decimal. + * + * @param str String to parse for the numeric value. + * + * @return Value, which can be a decimal. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function parseNumberString(str:String):String + { + // Check the decimal and thousands formatting for validity. + var splitDec:Array = str.split(decimalSeparatorFrom); + if (splitDec.length > 2) + return null; + + // Attempt to extract the first number sequence from the string. + var len:int = str.length; + var count:int = 0; + var letter:String; + var num:String; + var isNegative:Boolean = false; + var hasExponent:Boolean = false + + while (count < len) + { + letter = str.charAt(count); + count++; + + if (("0" <= letter && letter <= "9") || (letter == decimalSeparatorFrom)) + { + var lastLetter:String = str.charAt(count - 2); + // We must handle cases where we have negative input like "-YTL5.000,00" + // and currencySymbol is longer than one character. + if ((lastLetter == "-") || (str.charAt(0) == "-")) + isNegative = true; + num = ""; + count--; + + for (var i:int = count; i < len; i++) + { + letter = str.charAt(count); + count++; + if ("0" <= letter && letter <= "9") + { + num += letter; + } + else if (letter == decimalSeparatorFrom) + { + num += "."; + } + else if (letter == "e" || letter == "E") + { + num += letter; + hasExponent = true; + } + else if (hasExponent && (letter == "-" || letter == "+")) + { + num += letter; + } + else if (letter != thousandsSeparatorFrom || count >= len) + { + break; + } + } + } + } + + // there are all sorts of variations of zero, such as: + // .0 0. 0.0 0000 0000.00000 -0 + // Here, we simply convert to a 'real' Number and see if + // it's resolved to zero. if it does, just return a zero + // string and be done with it. + if ((num != null) && (str != '')) + { + var n:Number = Number(num); + + if (n == 0) + return '0'; + } + + // if the last digit is the dot, whack it + if (num) + { + if (num.charAt(num.length-1) == '.') + { + // we have something like 33. + if (num.length >= 2) + { + num = num.substring(0, num.length-1); + } + // we have merely . + else if (num.length == 1) + { + num = ''; + isNegative = false; + } + } + } + + return isNegative ? "-" + num : num; + } + + /** + * Formats a number in exponent notation, into + * a number in decimal notation. + * + * @param str String to process in exponent notation. + * + * @return Formatted number. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function expandExponents(value:String):String + { + //Break string into component parts + var regExp:RegExp = /^([+-])?(\d+).?(\d*)[eE]([-+]?\d+)$/; + var result:Object = regExp.exec(value); + var sign:String = result[1]; + var first:String = result[2]; + var last:String = result[3]; + var exp:int = int(result[4]); + + //if we didn't get a good exponent to begin with, return what we can figure out + if (!exp) + { + return (sign ? sign : "") + (first ? first : "0") + (last ? "." + last : ""); + } + + var r:String = first + last; + + var decimal:Boolean = exp < 0; + + if (decimal) + { + var o:Number = -1 * (first.length + exp) + 1; + return (sign ? sign : "") + "0." + new Array(o).join("0") + r; + } + else + { + var i:Number = exp + first.length; + if (i >= r.length) + return (sign ? sign : "") + r + new Array(i - r.length + 1).join("0"); + else + return (sign ? sign : "") + r.substr(0,i) + "." + r.substr(i); + } + } +} + +} diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/NumberBaseRoundType.as b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/NumberBaseRoundType.as new file mode 100644 index 0000000..ebf61dc --- /dev/null +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/formatters/NumberBaseRoundType.as @@ -0,0 +1,89 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + +/** + * The NumberBaseRoundType class defines the constant values for formatter properties + * that specify a type of rounding. For example, you can set the + * <code>NumberFormatter.rounding</code> property using these constants. + * + * @see mx.formatters.NumberFormatter + * @see mx.formatters.NumberBase + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ +public final class NumberBaseRoundType +{ + // include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Class constants + // + //-------------------------------------------------------------------------- + + /** + * Rounds a number down to an integer that is both closest to, + * and less than or equal to, the input number. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static const DOWN:String = "down"; + + /** + * Rounds a number up or down to the nearest integer. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static const NEAREST:String = "nearest"; + + /** + * Perform no rounding. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static const NONE:String = "none"; + + /** + * Rounds a number up to an integer value that is both closest to, + * and greater than or equal to, the input number. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static const UP:String = "up"; +} + +}