| /******************************************************************************* |
| * Copyright: 2004, 2012 1&1 Internet AG, Germany, http://www.1und1.de, |
| * and EclipseSource |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v1.0 which accompanies this |
| * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * 1&1 Internet AG and others - original API and implementation |
| * EclipseSource - adaptation for the Eclipse Remote Application Platform |
| ******************************************************************************/ |
| |
| /** |
| * Manage variants of source code. May it be for different debug options, |
| * browsers or other environment flags. |
| * |
| * Variants enable the selection and removal of code from the build version. |
| * A variant consists of a collection of states from which exactly one is active |
| * at load time of the framework. The global map <code>qxvariants</code> can be |
| * used to select a variant before the Framework is loades. |
| * |
| * Depending on the selected variant a specific code |
| * path can be choosen using the <code>select</code> method. The generator is |
| * able to set a variant and remove all code paths which are |
| * not selected by the variant. |
| * |
| * Variants are used to implement browser optimized builds and to remove |
| * debugging code from the build version. It is very similar to conditional |
| * compilation in C/C++. |
| */ |
| |
| /*global qxvariants:false*/ |
| |
| rwt.qx.Class.define("rwt.util.Variant", |
| { |
| statics : |
| { |
| /** {Map} stored variants */ |
| __variants : {}, |
| |
| |
| /** {Map} cached results */ |
| __cache : {}, |
| |
| |
| /** |
| * Pseudo function as replacement for isSet() which will only be handled by the optimizer |
| * |
| * @return {Boolean} |
| */ |
| compilerIsSet : function() { |
| return true; |
| }, |
| |
| |
| /** |
| * Define a variant |
| * |
| * @param key {String} An Unique key for the variant. The key must be prefixed with a |
| * namespace identifier (e.g. <code>"qx.debug"</code>) |
| * @param allowedValues {String[]} An array of all allowed values for this variant. |
| * @param defaultValue {String} Default value for the variant. Must be one of the values |
| * defined in <code>defaultValues</code>. |
| */ |
| define : function(key, allowedValues, defaultValue) |
| { |
| if (rwt.util.Variant.compilerIsSet("qx.debug", "on")) |
| { |
| if (!this.__isValidArray(allowedValues)) { |
| throw new Error('Allowed values of variant "' + key + '" must be defined!'); |
| } |
| |
| if (defaultValue === undefined) { |
| throw new Error('Default value of variant "' + key + '" must be defined!'); |
| } |
| } |
| |
| if (!this.__variants[key]) |
| { |
| this.__variants[key] = {}; |
| } |
| else if (rwt.util.Variant.compilerIsSet("qx.debug", "on")) |
| { |
| if (this.__variants[key].defaultValue !== undefined) { |
| throw new Error('Variant "' + key + '" is already defined!'); |
| } |
| } |
| |
| this.__variants[key].allowedValues = allowedValues; |
| this.__variants[key].defaultValue = defaultValue; |
| }, |
| |
| |
| /** |
| * Get the current value of a variant. |
| * |
| * @param key {String} name of the variant |
| * @return {String} current value of the variant |
| */ |
| get : function(key) |
| { |
| var data = this.__variants[key]; |
| |
| if (rwt.util.Variant.compilerIsSet("qx.debug", "on")) |
| { |
| if (data === undefined) { |
| throw new Error('Variant "' + key + '" is not defined.'); |
| } |
| } |
| |
| if (data.value !== undefined) { |
| return data.value; |
| } |
| |
| return data.defaultValue; |
| }, |
| |
| |
| /** |
| * Import settings from global qxvariants into current environment |
| * |
| * @return {void} |
| */ |
| __init : function() |
| { |
| if (window.qxvariants) |
| { |
| for (var key in qxvariants) |
| { |
| if (rwt.util.Variant.compilerIsSet("qx.debug", "on")) |
| { |
| if ((key.split(".")).length < 2) { |
| throw new Error('Malformed settings key "' + key + '". Must be following the schema "namespace.key".'); |
| } |
| } |
| |
| if (!this.__variants[key]) { |
| this.__variants[key] = {}; |
| } |
| |
| this.__variants[key].value = qxvariants[key]; |
| } |
| |
| window.qxvariants = undefined; |
| |
| try { |
| delete window.qxvariants; |
| } catch( ex ) { |
| } |
| } |
| }, |
| |
| /** |
| * Select a function depending on the value of the variant. |
| * |
| * Example: |
| * |
| * <pre class='javascript'> |
| * var f = qx.Variant.select("qx.client", { |
| * "gecko": fucntion() { ... }, |
| * "mshtml|opera": function() { ... }, |
| * "default": function() { ... } |
| * }); |
| * </pre> |
| * |
| * Depending on the value of the <code>"qx.client"</code> variant whit will select the |
| * corresponding function. The first case is selected if the variant is "gecko", the second |
| * is selected if the variant is "mshtml" or "opera" and the third function is selected if |
| * none of the other keys match the variant. "default" is the default case. |
| * |
| * @param key {String} name of the variant. To enable the generator to optimize |
| * this selection, the key must be a string literal. |
| * @param variantFunctionMap {Map} map with variant names as keys and functions as values. |
| * @return {Function} The selected function from the map. |
| */ |
| select : function(key, variantFunctionMap) |
| { |
| if (rwt.util.Variant.compilerIsSet("qx.debug", "on")) |
| { |
| // WARINING: all changes to this function must be duplicated in the generator!! |
| // modules/variantoptimizer.py (processVariantSelect) |
| if (!this.__isValidObject(this.__variants[key])) { |
| throw new Error("Variant \"" + key + "\" is not defined"); |
| } |
| |
| if (!this.__isValidObject(variantFunctionMap)) { |
| throw new Error("the second parameter must be a map!"); |
| } |
| } |
| |
| for (var variant in variantFunctionMap) |
| { |
| if (this.isSet(key, variant)) { |
| return variantFunctionMap[variant]; |
| } |
| } |
| |
| if (variantFunctionMap["default"] !== undefined) { |
| return variantFunctionMap["default"]; |
| } |
| |
| if (rwt.util.Variant.compilerIsSet("qx.debug", "on")) |
| { |
| throw new Error('No match for variant "' + key + |
| '" in variants [' + rwt.util.Objects.getKeysAsString(variantFunctionMap) + |
| '] found, and no default ("default") given'); |
| } |
| }, |
| |
| |
| /** |
| * Check whether a variant is set to a given value. To enable the generator to optimize |
| * this selection, both parameters must be string literals. |
| * |
| * This method is meant to be used in if statements to select code paths. If the condition of |
| * an if statement is only this method, the generator is able to optimize the if |
| * statement. |
| * |
| * Example: |
| * |
| * <pre class='javascript'> |
| * if (rwt.util.Variant.isSet("qx.client", "mshtml")) { |
| * // some Internet Explorer specific code |
| * } else if(rwt.util.Variant.isSet("qx.client", "opera")){ |
| * // Opera specific code |
| * } else { |
| * // common code for all other browsers |
| * } |
| * </pre> |
| * |
| * @param key {String} name of the variant |
| * @param variants {String} value to check for. Several values can be "or"-combined by separating |
| * them with a "|" character. A value of "mshtml|opera" would for example check if the variant is |
| * set to "mshtml" or "opera" |
| * @return {Boolean} whether the variant is set to the given value |
| */ |
| isSet : function(key, variants) |
| { |
| var access = key + "$" + variants; |
| if (this.__cache[access] !== undefined) { |
| return this.__cache[access]; |
| } |
| |
| var retval = false; |
| |
| // fast path |
| if (variants.indexOf("|") < 0) |
| { |
| retval = this.get(key) === variants; |
| } |
| else |
| { |
| var keyParts = variants.split("|"); |
| |
| for (var i=0, l=keyParts.length; i<l; i++) |
| { |
| if (this.get(key) === keyParts[i]) |
| { |
| retval = true; |
| break; |
| } |
| } |
| } |
| |
| this.__cache[access] = retval; |
| return retval; |
| }, |
| |
| |
| /** |
| * Whether a value is a valid array. Valid arrays are: |
| * |
| * * type is object |
| * * instance is Array |
| * |
| * @type static |
| * @name __isValidArray |
| * @param v {var} the value to validate. |
| * @return {Boolean} whether the variable is valid |
| */ |
| __isValidArray : function(v) { |
| return typeof v === "object" && v !== null && v instanceof Array; |
| }, |
| |
| |
| /** |
| * Whether a value is a valid object. Valid object are: |
| * |
| * * type is object |
| * * instance != Array |
| * |
| * @type static |
| * @name __isValidObject |
| * @param v {var} the value to validate. |
| * @return {Boolean} whether the variable is valid |
| */ |
| __isValidObject : function(v) { |
| return typeof v === "object" && v !== null && !(v instanceof Array); |
| }, |
| |
| |
| /** |
| * Whether the array contains the given element |
| * |
| * @type static |
| * @name __arrayContains |
| * @param arr {Array} the array |
| * @param obj {var} object to look for |
| * @return {Boolean} whether the array contains the element |
| */ |
| __arrayContains : function(arr, obj) |
| { |
| for (var i=0, l=arr.length; i<l; i++) |
| { |
| if (arr[i] == obj) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| }, |
| |
| |
| |
| |
| /* |
| ***************************************************************************** |
| DEFER |
| ***************************************************************************** |
| */ |
| |
| defer : function(statics) |
| { |
| statics.define("qx.debug", [ "on", "off" ], "on"); |
| statics.define("qx.compatibility", [ "on", "off" ], "on"); |
| statics.define("qx.eventMonitorNoListeners", [ "on", "off" ], "off"); |
| statics.define("qx.aspects", [ "on", "off" ], "off"); |
| statics.define("qx.deprecationWarnings", [ "on", "off" ], "on"); |
| |
| statics.__init(); |
| } |
| }); |