dragonbones-runtime
Version:
the tools to build dragonbones file for diffrent framework
1,387 lines (1,386 loc) • 70.4 kB
JavaScript
/// <reference path="../types.d.ts" />
/// <reference path="exml_config.ts"/>
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var xml = require("../xml/index");
var utils = require("../utils");
var file = require("../FileUtil");
var CodeUtil = require("./code_util");
var exml_config = require("./exml_config");
var compiler;
function compile(exmlPath, srcPath) {
var result = { exitCode: 0, messages: [] };
exmlPath = exmlPath.split("\\").join("/");
srcPath = srcPath.split("\\").join("/");
var tsPath = exmlPath.substring(0, exmlPath.length - 5) + ".g.ts";
if (srcPath.charAt(srcPath.length - 1) != "/") {
srcPath += "/";
}
if (!compiler) {
compiler = new EXMLCompiler();
}
var exitCode = 0, message = "";
if (!file.exists(exmlPath)) {
result.messages.push(utils.tr(2001, exmlPath));
result.exitCode = 2001;
return result;
}
while (true) {
var className = exmlPath.substring(srcPath.length, exmlPath.length - 5);
className = className.split("/").join(".");
var xmlString = file.read(exmlPath, true);
try {
var xmlData = xml.parse(xmlString);
}
catch (e) {
message = utils.tr(2002, exmlPath, e.message);
exitCode = 2002;
break;
}
if (!xmlData) {
message = utils.tr(2002, exmlPath, "");
exitCode = 2002;
break;
}
try {
var tsText = compiler.compile(xmlData, className, srcPath, exmlPath);
file.save(tsPath, tsText);
}
catch (e) {
message = compiler.errorMessage;
exitCode = compiler.errorCode || 2002;
}
break;
}
if (exitCode) {
file.save(tsPath, "");
}
result.exitCode = exitCode;
result.messages.push(message);
return result;
}
exports.compile = compile;
;
var EXMLCompiler = (function () {
/**
* 构造函数
*/
function EXMLCompiler() {
this.repeatedIdDic = {};
this.exmlPath = "";
this.basicTypes = ["Array", "boolean", "string", "number"];
/**
* 延迟赋值字典
*/
this.delayAssignmentDic = {};
this.htmlEntities = [["<", "<"], [">", ">"], ["&", "&"], ["\"", """], ["'", "'"]];
}
/**
* 获取重复的ID名
*/
EXMLCompiler.prototype.getRepeatedIds = function (xml) {
var result = [];
this.getIds(xml, result);
this.repeatedIdDic = {};
return result;
};
EXMLCompiler.prototype.exit = function (code) {
var params = [];
for (var _i = 1; _i < arguments.length; _i++) {
params[_i - 1] = arguments[_i];
}
this.errorCode = code;
this.errorMessage = utils.tr.apply(utils, [code].concat(params));
throw this.errorMessage;
};
EXMLCompiler.prototype.getIds = function (xml, result) {
if (xml.namespace != EXMLCompiler.W && xml["$id"]) {
var id = xml.$id;
if (this.repeatedIdDic[id]) {
result.push(this.toXMLString(xml));
}
else {
this.repeatedIdDic[id] = true;
}
}
var children = xml.children;
if (children) {
var length = children.length;
for (var i = 0; i < length; i++) {
var node = children[i];
this.getIds(node, result);
}
}
};
EXMLCompiler.prototype.toXMLString = function (node) {
if (!node) {
return "";
}
var str = " at <" + node.name;
for (var key in node) {
if (key.charAt(0) == "$") {
var value = node[key];
key = key.substring(1);
if (key == "id" && value.substring(0, 2) == "__") {
continue;
}
str += " " + key + "=\"" + value + "\"";
}
}
if (node.isSelfClosing) {
str += "/>";
}
else {
str += ">";
}
return str;
};
/**
* 编译指定的XML对象为TypeScript类。
* 注意:编译前要先注入egret-manifest.xml清单文件给manifestData属性。
* @param xmlData 要编译的EXML文件内容
* @param className 要编译成的完整类名,包括命名空间。
*/
EXMLCompiler.prototype.compile = function (xmlData, className, srcPath, exmlPath) {
if (!this.exmlConfig) {
this.exmlConfig = exml_config.getInstance();
}
this.exmlPath = exmlPath;
this.currentXML = xmlData;
this.currentClassName = className;
this.exmlConfig.srcPath = srcPath;
this.delayAssignmentDic = {};
this.idDic = {};
this.idToNode = {};
this.stateCode = [];
this.stateNames = [];
this.skinParts = [];
this.declarations = null;
this.currentClass = new CpClass();
this.stateIds = [];
var index = className.lastIndexOf(".");
if (index != -1) {
this.currentClass.moduleName = className.substring(0, index);
this.currentClass.className = className.substring(index + 1);
this.currentClass.classPath = className.split(".").join("/") + ".ts";
}
else {
this.currentClass.className = className;
}
this.startCompile();
var resutlCode = this.currentClass.toCode();
this.currentClass = null;
return resutlCode;
};
/**
* 开始编译
*/
EXMLCompiler.prototype.startCompile = function () {
var result = this.getRepeatedIds(this.currentXML);
if (result.length > 0) {
this.exit(2004, this.exmlPath, result.join("\n"));
}
this.currentClass.superClass = this.getPackageByNode(this.currentXML);
this.getStateNames();
var children = this.currentXML.children;
if (children) {
var length = children.length;
for (var i = 0; i < length; i++) {
var node = children[i];
if (node.namespace == EXMLCompiler.W &&
node.localName == EXMLCompiler.DECLARATIONS) {
this.declarations = node;
break;
}
}
}
var list = [];
this.checkDeclarations(this.declarations, list);
if (list.length > 0) {
this.exit(2020, this.exmlPath, list.join("\n"));
}
if (!this.currentXML.namespace) {
this.exit(2017, this.exmlPath, this.toXMLString(this.currentXML));
}
this.addIds(this.currentXML.children);
this.currentClass.addVariable(new CpVariable("__s", Modifiers.M_PRIVATE, "Function", "egret.gui.setProperties"));
this.createConstructFunc();
};
/**
* 清理声明节点里的状态标志
*/
EXMLCompiler.prototype.checkDeclarations = function (declarations, list) {
if (!declarations) {
return;
}
var children = declarations.children;
if (children) {
var length = children.length;
for (var i = 0; i < length; i++) {
var node = children[i];
if (node["$includeIn"]) {
list.push(this.toXMLString(node));
delete node.$includeIn;
}
if (node["$excludeFrom"]) {
list.push(this.toXMLString(node));
delete node.$excludeFrom;
}
this.checkDeclarations(node, list);
}
}
};
/**
* 添加必须的id
*/
EXMLCompiler.prototype.addIds = function (items) {
if (!items) {
return;
}
var length = items.length;
for (var i = 0; i < length; i++) {
var node = items[i];
if (!node.namespace) {
this.exit(2017, this.exmlPath, this.toXMLString(node));
}
this.addIds(node.children);
if (node.namespace == EXMLCompiler.W) {
}
else if (node["$id"]) {
this.idToNode[node.$id] = node;
if (this.skinParts.indexOf(node.$id) == -1) {
this.skinParts.push(node.$id);
}
this.createVarForNode(node);
if (this.isStateNode(node))
this.stateIds.push(node.$id);
}
else if (node.localName) {
if (this.isProperty(node)) {
var prop = node.localName;
var index = prop.indexOf(".");
var children = node.children;
if (index == -1 || !children || children.length == 0) {
continue;
}
var firstChild = children[0];
this.stateIds.push(firstChild.$id);
}
else {
this.createIdForNode(node);
this.idToNode[node.$id] = node;
if (this.isStateNode(node))
this.stateIds.push(node.$id);
}
}
}
};
/**
* 检测指定节点的属性是否含有视图状态
*/
EXMLCompiler.prototype.containsState = function (node) {
if (node["$includeIn"] || node["$excludeFrom"]) {
return true;
}
for (var name in node) {
if (name.charAt(0) == "$") {
if (name.indexOf(".") != -1) {
return true;
}
}
}
return false;
};
/**
* 为指定节点创建id属性
*/
EXMLCompiler.prototype.createIdForNode = function (node) {
var idName = this.getNodeId(node);
if (this.idDic[idName] == null)
this.idDic[idName] = 1;
else
this.idDic[idName]++;
idName += this.idDic[idName];
node.$id = idName;
};
/**
* 获取节点ID
*/
EXMLCompiler.prototype.getNodeId = function (node) {
if (node["$id"])
return node.$id;
return "__";
};
/**
* 为指定节点创建变量
*/
EXMLCompiler.prototype.createVarForNode = function (node) {
var moduleName = this.getPackageByNode(node);
if (moduleName == "")
return;
if (!this.currentClass.containsVar(node.$id))
this.currentClass.addVariable(new CpVariable(node.$id, Modifiers.M_PUBLIC, moduleName));
};
/**
* 为指定节点创建初始化函数,返回函数名引用
*/
EXMLCompiler.prototype.createFuncForNode = function (node) {
var className = node.localName;
if (this.isProperty(node))
return "";
var isBasicType = this.isBasicTypeData(className);
if (isBasicType)
return this.createBasicTypeForNode(node);
var moduleName = this.getPackageByNode(node);
var func = new CpFunction;
var tailName = "_i";
var id = node.$id;
func.name = id + tailName;
func.returnType = moduleName;
var cb = new CpCodeBlock;
var varName = "t";
if (className == "Object") {
cb.addVar(varName, "any", "{}");
}
else {
cb.addVar(varName, moduleName, "new " + moduleName + "()");
}
var containsId = this.currentClass.containsVar(node.$id);
if (containsId) {
cb.addAssignment("this." + node.$id, varName);
}
this.addAttributesToCodeBlock(cb, varName, node);
this.initlizeChildNode(node, cb, varName);
if (this.delayAssignmentDic[id]) {
var length = this.delayAssignmentDic[id].length;
for (var i = 0; i < length; i++) {
var delaycb = this.delayAssignmentDic[id][i];
cb.concat(delaycb);
}
}
cb.addReturn(varName);
func.codeBlock = cb;
this.currentClass.addFunction(func);
return "this." + func.name + "()";
};
/**
* 检查目标类名是否是基本数据类型
*/
EXMLCompiler.prototype.isBasicTypeData = function (className) {
return this.basicTypes.indexOf(className) != -1;
};
/**
* 为指定基本数据类型节点实例化,返回实例化后的值。
*/
EXMLCompiler.prototype.createBasicTypeForNode = function (node) {
var className = node.localName;
var returnValue = "";
var child;
var varItem = this.currentClass.getVariableByName(node.$id);
switch (className) {
case "Array":
var values = [];
var children = node.children;
if (children) {
var length = children.length;
for (var i = 0; i < length; i++) {
var child = children[i];
values.push(this.createFuncForNode(child));
}
}
returnValue = "[" + values.join(",") + "]";
break;
case "boolean":
returnValue = node.text.trim();
returnValue = (returnValue == "false" || !returnValue) ? "false" : "true";
break;
case "number":
returnValue = node.text.trim();
if (returnValue.indexOf("%") != -1)
returnValue = returnValue.substring(0, returnValue.length - 1);
break;
case "string":
returnValue = this.formatString(node.toString());
break;
}
if (varItem)
varItem.defaultValue = returnValue;
return returnValue;
};
/**
* 将节点属性赋值语句添加到代码块
*/
EXMLCompiler.prototype.addAttributesToCodeBlock = function (cb, varName, node) {
var keyList = [];
var key;
var value;
for (key in node) {
if (key.charAt(0) != "$" || !this.isNormalKey(key)) {
continue;
}
keyList.push(key);
}
keyList.sort(); //排序一下防止出现随机顺序
var className = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var length = keyList.length;
var values = [];
var keys = [];
for (var i = 0; i < length; i++) {
key = keyList[i];
value = node[key];
key = this.formatKey(key.substring(1), value);
value = this.formatValue(key, value, node);
if (!value) {
continue;
}
if (this.currentClass.containsVar(value)) {
var id = node.$id;
var codeLine = "this." + id + " = t;";
if (!this.currentClass.containsVar(id))
this.createVarForNode(node);
if (!cb.containsCodeLine(codeLine)) {
cb.addCodeLineAt(codeLine, 1);
}
var delayCb = new CpCodeBlock();
if (varName == KeyWords.KW_THIS) {
delayCb.addAssignment(varName, "this." + value, key);
}
else {
delayCb.startIf("this." + id);
delayCb.addAssignment("this." + id, "this." + value, key);
delayCb.endBlock();
}
if (!this.delayAssignmentDic[value]) {
this.delayAssignmentDic[value] = [];
}
this.delayAssignmentDic[value].push(delayCb);
value = "this." + value;
}
if (this.exmlConfig.isStyleProperty(key, className)) {
cb.addCodeLine(varName + ".setStyle(\"" + key + "\"," + value + ")");
}
else {
keys.push(key);
values.push(value);
}
}
var length = keys.length;
if (length > 1) {
var allKey = "[\"" + keys.join("\",\"") + "\"]";
var allValue = "[" + values.join(",") + "]";
cb.addCodeLine("this.__s(" + varName + "," + allKey + "," + allValue + ")");
}
else if (length == 1) {
cb.addAssignment(varName, values[0], keys[0]);
}
};
/**
* 初始化子项
*/
EXMLCompiler.prototype.initlizeChildNode = function (node, cb, varName) {
var children = node.children;
if (!children || children.length == 0)
return;
var className = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var directChild = [];
var length = children.length;
var propList = [];
var isContainer = this.exmlConfig.isInstanceOf(className, "egret.gui.IContainer");
for (var i = 0; i < length; i++) {
var child = children[i];
var prop = child.localName;
if (child.namespace == EXMLCompiler.W) {
continue;
}
if (this.isProperty(child)) {
if (!this.isNormalKey(prop)) {
continue;
}
var type = this.exmlConfig.getPropertyType(child.localName, className);
if (!type) {
globals.warn(2005, this.exmlPath, child.localName, this.getPropertyStr(child));
}
if (!child.children || child.children.length == 0) {
globals.warn(2102, this.exmlPath, this.getPropertyStr(child));
continue;
}
var errorInfo = this.getPropertyStr(child);
this.addChildrenToProp(child.children, type, prop, cb, varName, errorInfo, propList, className, isContainer);
}
else {
directChild.push(child);
}
}
if (directChild.length == 0)
return;
var defaultProp = this.exmlConfig.getDefaultPropById(node.localName, node.namespace);
var defaultType = this.exmlConfig.getPropertyType(defaultProp, className);
var errorInfo = this.getPropertyStr(directChild[0]);
if (!defaultProp || !defaultType) {
this.exit(2012, this.exmlPath, errorInfo);
}
this.addChildrenToProp(directChild, defaultType, defaultProp, cb, varName, errorInfo, propList, className, isContainer);
};
/**
* 添加多个子节点到指定的属性
*/
EXMLCompiler.prototype.addChildrenToProp = function (children, type, prop, cb, varName, errorInfo, propList, className, isContainer) {
var childFunc = "";
var childLength = children.length;
if (childLength > 1) {
if (type != "Array") {
this.exit(2011, this.exmlPath, prop, errorInfo);
}
var values = [];
for (var j = 0; j < childLength; j++) {
var item = children[j];
childFunc = this.createFuncForNode(item);
var childClassName = this.exmlConfig.getClassNameById(item.localName, item.namespace);
if (!this.isStateNode(item))
values.push(childFunc);
}
childFunc = "[" + values.join(",") + "]";
}
else {
var firstChild = children[0];
if (type == "Array") {
if (firstChild.localName == "Array") {
values = [];
if (firstChild.children) {
var len = firstChild.children.length;
for (var k = 0; k < len; k++) {
item = firstChild.children[k];
childFunc = this.createFuncForNode(item);
childClassName = this.exmlConfig.getClassNameById(item.localName, item.namespace);
if (!this.isStateNode(item))
values.push(childFunc);
}
}
childFunc = "[" + values.join(",") + "]";
}
else {
childFunc = this.createFuncForNode(firstChild);
var childClassName = this.exmlConfig.getClassNameById(firstChild.localName, firstChild.namespace);
if (!this.isStateNode(firstChild))
childFunc = "[" + childFunc + "]";
else
childFunc = "[]";
}
}
else {
var targetClass = this.exmlConfig.getClassNameById(firstChild.localName, firstChild.namespace);
if (!this.exmlConfig.isInstanceOf(targetClass, type)) {
this.exit(2008, this.exmlPath, targetClass, prop, errorInfo);
}
childFunc = this.createFuncForNode(firstChild);
}
}
if (childFunc != "") {
if (childFunc.indexOf("()") == -1)
prop = this.formatKey(prop, childFunc);
if (propList.indexOf(prop) == -1) {
propList.push(prop);
}
else {
globals.warn(2103, this.exmlPath, prop, errorInfo);
}
if (this.exmlConfig.isStyleProperty(prop, className)) {
cb.addCodeLine(varName + ".setStyle(\"" + prop + "\"," + childFunc + ")");
}
else {
cb.addAssignment(varName, childFunc, prop);
}
}
};
EXMLCompiler.prototype.getPropertyStr = function (child) {
var parentStr = this.toXMLString(child.parent);
var childStr = this.toXMLString(child).substring(5);
return parentStr + "\n \t" + childStr;
};
/**
* 指定节点是否是属性节点
*/
EXMLCompiler.prototype.isProperty = function (node) {
var name = node.localName;
if (name == null)
return true;
if (this.isBasicTypeData(name))
return false;
var firstChar = name.charAt(0);
return firstChar < "A" || firstChar > "Z";
};
/**
* 是否是普通赋值的key
*/
EXMLCompiler.prototype.isNormalKey = function (key) {
if (!key || key.indexOf(".") != -1 || EXMLCompiler.wingKeys.indexOf(key) != -1)
return false;
return true;
};
/**
* 格式化key
*/
EXMLCompiler.prototype.formatKey = function (key, value) {
if (value.indexOf("%") != -1) {
if (key == "height")
key = "percentHeight";
else if (key == "width")
key = "percentWidth";
}
return key;
};
/**
* 格式化值
*/
EXMLCompiler.prototype.formatValue = function (key, value, node) {
if (!value) {
value = "";
}
var stringValue = value; //除了字符串,其他类型都去除两端多余空格。
value = value.trim();
var className = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var type = this.exmlConfig.getPropertyType(key, className);
if (!type) {
globals.warn(2005, this.exmlPath, key, this.toXMLString(node));
}
if (type != "string" && value.charAt(0) == "{" && value.charAt(value.length - 1) == "}") {
value = value.substr(1, value.length - 2);
value = value.trim();
if (value.indexOf("this.") == 0) {
if (CodeUtil.isVariableWord(value.substring(5))) {
value = value.substring(5);
}
}
if (CodeUtil.isVariableWord(value)) {
var targetNode = this.idToNode[value];
if (!targetNode) {
this.exit(2010, this.exmlPath, key, value, this.toXMLString(node));
}
var targetClass = this.exmlConfig.getClassNameById(targetNode.localName, targetNode.namespace);
if (!this.exmlConfig.isInstanceOf(targetClass, type)) {
this.exit(2008, this.exmlPath, targetClass, key, this.toXMLString(node));
}
}
else {
this.exit(2009, this.exmlPath, this.toXMLString(node));
}
}
else if (type == "Class" && value.indexOf("@ButtonSkin(") == 0 && value.charAt(value.length - 1) == ")") {
value = value.substring(12, value.length - 1);
var skinNames = value.split(",");
if (skinNames.length > 3) {
this.exit(2018, this.exmlPath, this.toXMLString(node));
}
for (var i = skinNames.length - 1; i >= 0; i--) {
var skinName = skinNames[i];
skinName = skinName.trim();
var firstChar = skinName.charAt(0);
var lastChar = skinName.charAt(skinName.length - 1);
if (firstChar != lastChar || (firstChar != "'" && firstChar != "\"")) {
this.exit(2018, this.exmlPath, this.toXMLString(node));
break;
}
skinNames[i] = this.formatString(skinName.substring(1, skinName.length - 1));
}
value = "new egret.gui.ButtonSkin(" + skinNames.join(",") + ")";
}
else if (key == "scale9Grid" && type == "egret.Rectangle") {
var rect = value.split(",");
if (rect.length != 4 || isNaN(parseInt(rect[0])) || isNaN(parseInt(rect[1])) ||
isNaN(parseInt(rect[2])) || isNaN(parseInt(rect[3]))) {
this.exit(2016, this.exmlPath, this.toXMLString(node));
}
value = "egret.gui.getScale9Grid(\"" + value + "\")";
}
else {
var orgValue = value;
switch (type) {
case "egret.gui.IFactory":
value = "new egret.gui.ClassFactory(" + orgValue + ")";
case "Class":
if (!this.exmlConfig.checkClassName(orgValue)) {
this.exit(2015, this.exmlPath, orgValue, this.toXMLString(node));
}
if (value == this.currentClassName) {
this.exit(2014, this.exmlPath, this.toXMLString(node));
}
break;
case "number":
if (value.indexOf("#") == 0)
value = "0x" + value.substring(1);
else if (value.indexOf("%") != -1)
value = (parseFloat(value.substr(0, value.length - 1))).toString();
break;
case "boolean":
value = (value == "false" || !value) ? "false" : "true";
break;
case "string":
case "any":
value = this.formatString(stringValue);
break;
default:
this.exit(2008, this.exmlPath, "string", key + ":" + type, this.toXMLString(node));
break;
}
}
return value;
};
/**
* 格式化字符串
*/
EXMLCompiler.prototype.formatString = function (value) {
value = this.unescapeHTMLEntity(value);
value = value.split("\n").join("\\n");
value = value.split("\r").join("\\n");
value = value.split("\"").join("\\\"");
value = "\"" + value + "\"";
return value;
};
/**
/**
* 转换HTML实体字符为普通字符
*/
EXMLCompiler.prototype.unescapeHTMLEntity = function (str) {
if (!str)
return "";
var list = this.htmlEntities;
var length = list.length;
for (var i = 0; i < length; i++) {
var arr = list[i];
var key = arr[0];
var value = arr[1];
str = str.split(value).join(key);
}
return str;
};
/**
* 创建构造函数
*/
EXMLCompiler.prototype.createConstructFunc = function () {
var cb = new CpCodeBlock;
cb.addEmptyLine();
var varName = KeyWords.KW_THIS;
this.addAttributesToCodeBlock(cb, varName, this.currentXML);
if (this.declarations) {
var children = this.declarations.children;
if (children && children.length > 0) {
var length = children.length;
for (var i = 0; i < length; i++) {
var decl = children[i];
var funcName = this.createFuncForNode(decl);
if (funcName != "") {
cb.addCodeLine(funcName + ";");
}
}
}
}
this.initlizeChildNode(this.currentXML, cb, varName);
var id;
if (this.stateIds.length > 0) {
length = this.stateIds.length;
for (var i = 0; i < length; i++) {
id = this.stateIds[i];
cb.addCodeLine("this." + id + "_i();");
}
cb.addEmptyLine();
}
length = this.skinParts.length;
if (length > 0) {
for (i = 0; i < length; i++) {
this.skinParts[i] = "\"" + this.skinParts[i] + "\"";
}
var skinPartStr = "[" + this.skinParts.join(",") + "]";
var skinPartVar = new CpVariable("_skinParts", Modifiers.M_PRIVATE, "Array<string>", skinPartStr, true);
this.currentClass.addVariable(skinPartVar);
var skinPartFunc = new CpFunction();
skinPartFunc.name = "skinParts";
skinPartFunc.modifierName = Modifiers.M_PUBLIC;
skinPartFunc.isGet = true;
skinPartFunc.returnType = "Array<string>";
var skinPartCB = new CpCodeBlock();
skinPartCB.addReturn(this.currentClass.className + "._skinParts");
skinPartFunc.codeBlock = skinPartCB;
this.currentClass.addFunction(skinPartFunc);
}
this.currentXML.$id = "";
//生成视图状态代码
this.createStates(this.currentXML);
var states;
var node = this.currentXML;
var nodeClassName = this.exmlConfig.getClassNameById(node.localName, node.namespace);
for (var itemName in node) {
var value = node[itemName];
if (itemName.charAt(0) != "$") {
continue;
}
itemName = itemName.substring(1);
var index = itemName.indexOf(".");
if (index != -1) {
var key = itemName.substring(0, index);
key = this.formatKey(key, value);
var itemValue = this.formatValue(key, value, node);
if (!itemValue) {
continue;
}
var stateName = itemName.substr(index + 1);
states = this.getStateByName(stateName, node);
var stateLength = states.length;
if (stateLength > 0) {
for (var i = 0; i < stateLength; i++) {
var state = states[i];
if (this.exmlConfig.isStyleProperty(key, nodeClassName)) {
state.addOverride(new CpSetStyle("", key, itemValue));
}
else {
state.addOverride(new CpSetProperty("", key, itemValue));
}
}
}
}
}
//打印视图状态初始化代码
if (this.stateCode.length > 0) {
cb.addCodeLine("this.states = [");
var first = true;
var indentStr = " ";
var length = this.stateCode.length;
for (var i = 0; i < length; i++) {
state = this.stateCode[i];
if (first)
first = false;
else
cb.addCodeLine(indentStr + ",");
var codes = state.toCode().split("\n");
var codeIndex = 0;
while (codeIndex < codes.length) {
var code = codes[codeIndex];
if (code)
cb.addCodeLine(indentStr + code);
codeIndex++;
}
}
cb.addCodeLine("];");
}
this.currentClass.constructCode = cb;
};
/**
* 是否含有includeIn和excludeFrom属性
*/
EXMLCompiler.prototype.isStateNode = function (node) {
return node.hasOwnProperty("$includeIn") || node.hasOwnProperty("$excludeFrom");
};
/**
* 获取视图状态名称列表
*/
EXMLCompiler.prototype.getStateNames = function () {
var stateNames = this.stateNames;
var states;
var children = this.currentXML.children;
if (children) {
var length = children.length;
for (var i = 0; i < length; i++) {
var item = children[i];
if (item.localName == "states") {
item.namespace = EXMLCompiler.W;
states = item.children;
break;
}
}
}
if (states == null)
return;
if (states.length == 0) {
globals.warn(2102, this.exmlPath, this.getPropertyStr(item));
return;
}
length = states.length;
for (i = 0; i < length; i++) {
var state = states[i];
var stateGroups = [];
if (state["$stateGroups"]) {
var groups = state.$stateGroups.split(",");
var len = groups.length;
for (var j = 0; j < len; j++) {
var group = groups[j].trim();
if (group) {
if (stateNames.indexOf(group) == -1) {
stateNames.push(group);
}
stateGroups.push(group);
}
}
}
var stateName = state.$name;
if (stateNames.indexOf(stateName) == -1) {
stateNames.push(stateName);
}
this.stateCode.push(new CpState(stateName, stateGroups));
}
};
/**
* 解析视图状态代码
*/
EXMLCompiler.prototype.createStates = function (parentNode) {
var items = parentNode.children;
if (!items) {
return;
}
var className = this.exmlConfig.getClassNameById(parentNode.localName, parentNode.namespace);
var length = items.length;
for (var i = 0; i < length; i++) {
var node = items[i];
this.createStates(node);
if (node.namespace == EXMLCompiler.W || !node.localName) {
continue;
}
if (this.isProperty(node)) {
var prop = node.localName;
var index = prop.indexOf(".");
var children = node.children;
if (index == -1 || !children || children.length == 0) {
continue;
}
var stateName = prop.substring(index + 1);
prop = prop.substring(0, index);
var type = this.exmlConfig.getPropertyType(prop, className);
if (type == "Array") {
this.exit(2013, this.exmlPath, this.getPropertyStr(node));
}
if (children.length > 1) {
this.exit(2011, this.exmlPath, prop, this.getPropertyStr(node));
}
var firstChild = children[0];
this.createFuncForNode(firstChild);
this.checkIdForState(firstChild);
var value = "this." + firstChild.$id;
states = this.getStateByName(stateName, node);
var l = states.length;
if (l > 0) {
for (var j = 0; j < l; j++) {
state = states[j];
if (this.exmlConfig.isStyleProperty(prop, className)) {
state.addOverride(new CpSetStyle(parentNode.$id, prop, value));
}
else {
state.addOverride(new CpSetProperty(parentNode.$id, prop, value));
}
}
}
}
else if (this.containsState(node)) {
var id = node.$id;
var nodeClassName = this.exmlConfig.getClassNameById(node.localName, node.namespace);
this.checkIdForState(node);
var stateName;
var states;
var state;
if (this.isStateNode(node)) {
if (!this.isIVisualElement(node)) {
this.exit(2007, this.exmlPath, this.toXMLString(node));
}
var propertyName = "";
var parent = (node.parent);
if (parent.localName == "Array")
parent = parent.parent;
if (this.isProperty(parent))
parent = parent.parent;
if (parent && parent != this.currentXML) {
propertyName = parent.$id;
this.checkIdForState(parent);
}
var positionObj = this.findNearNodeId(node);
var stateNames = [];
if (node.hasOwnProperty("$includeIn")) {
stateNames = node.$includeIn.split(",");
}
else {
var excludeNames = node.$excludeFrom.split(",");
var stateLength = excludeNames.length;
for (var j = 0; j < stateLength; j++) {
var name = excludeNames[j];
this.getStateByName(name, node); //检查exlcudeFrom是否含有未定义的视图状态名
}
stateLength = this.stateCode.length;
for (j = 0; j < stateLength; j++) {
state = this.stateCode[j];
if (excludeNames.indexOf(state.name) == -1)
stateNames.push(state.name);
}
}
var len = stateNames.length;
for (var k = 0; k < len; k++) {
stateName = stateNames[k];
states = this.getStateByName(stateName, node);
if (states.length > 0) {
var l = states.length;
for (var j = 0; j < l; j++) {
state = states[j];
state.addOverride(new CpAddItems(id, propertyName, positionObj.position, positionObj.relativeTo));
}
}
}
}
var name;
for (name in node) {
var value = node[name];
if (name.charAt(0) != "$") {
continue;
}
name = name.substring(1);
var index = name.indexOf(".");
if (index != -1) {
var key = name.substring(0, index);
key = this.formatKey(key, value);
var value = this.formatValue(key, value, node);
if (!value) {
continue;
}
stateName = name.substr(index + 1);
states = this.getStateByName(stateName, node);
var l = states.length;
if (l > 0) {
for (var j = 0; j < l; j++) {
state = states[j];
if (this.exmlConfig.isStyleProperty(key, nodeClassName)) {
state.addOverride(new CpSetStyle(id, key, value));
}
else {
state.addOverride(new CpSetProperty(id, key, value));
}
}
}
}
}
}
}
};
/**
* 检查指定的节点是否是显示对象
*/
EXMLCompiler.prototype.isIVisualElement = function (node) {
var className = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var result = this.exmlConfig.isInstanceOf(className, "egret.gui.IVisualElement");
if (!result) {
return false;
}
var parent = node.parent;
if (!parent) {
return false;
}
if (parent.localName == "Array") {
parent = parent.parent;
}
if (!parent) {
return false;
}
if (this.isProperty(parent)) {
return (parent.localName == "elementsContent");
}
var prop = this.exmlConfig.getDefaultPropById(parent.localName, parent.namespace);
return prop == "elementsContent";
};
/**
* 检查指定的ID是否创建了类成员变量,若没创建则为其创建。
*/
EXMLCompiler.prototype.checkIdForState = function (node) {
if (!node || this.currentClass.containsVar(node.$id)) {
return;
}
this.createVarForNode(node);
var id = node.$id;
var funcName = id + "_i";
var func = this.currentClass.getFuncByName(funcName);
if (!func)
return;
var codeLine = "this." + id + " = t;";
var cb = func.codeBlock;
if (!cb)
return;
if (!cb.containsCodeLine(codeLine)) {
cb.addCodeLineAt(codeLine, 1);
}
};
/**
* 通过视图状态名称获取对应的视图状态
*/
EXMLCompiler.prototype.getStateByName = function (name, node) {
var states = [];
var length = this.stateCode.length;
for (var i = 0; i < length; i++) {
var state = this.stateCode[i];
if (state.name == name) {
if (states.indexOf(state) == -1)
states.push(state);
}
else if (state.stateGroups.length > 0) {
var found = false;
var len = state.stateGroups.length;
for (var j = 0; j < len; j++) {
var g = state.stateGroups[j];
if (g == name) {
found = true;
break;
}
}
if (found) {
if (states.indexOf(state) == -1)
states.push(state);
}
}
}
if (states.length == 0) {
this.exit(2006, this.exmlPath, name, this.toXMLString(node));
}
return states;
};
/**
* 寻找节点的临近节点ID和位置
*/
EXMLCompiler.prototype.findNearNodeId = function (node) {
var parentNode = node.parent;
var targetId = "";
var postion;
var index = -1;
var totalCount = 0;
var preItem;
var afterItem;
var found = false;
var children = parentNode.children;
var length = children.length;
for (var i = 0; i < length; i++) {
var item = children[i];
if (this.isProperty(item))
continue;
if (item == node) {
found = true;
index = i;
}
else {
if (found && !afterItem && !this.isStateNode(item)) {
afterItem = item;
}
}
if (!found && !this.isStateNode(item))
preItem = item;
}
if (index == 0) {
postion = "first";
return { position: postion, relativeTo: targetId };
}
if (index == length - 1) {
postion = "last";
return { position: postion, relativeTo: targetId };
}
if (afterItem) {
postion = "before";
targetId = afterItem.$id;
if (targetId) {
this.checkIdForState(afterItem);
return { position: postion, relativeTo: targetId };
}
}
return { position: "last", relativeTo: targetId };
};
/**
* 根据类名获取对应的包,并自动导入相应的包
*/
EXMLCompiler.prototype.getPackageByNode = function (node) {
var moduleName = this.exmlConfig.getClassNameById(node.localName, node.namespace);
if (!moduleName) {
this.exit(2003, this.exmlPath, this.toXMLString(node));
}
return moduleName;
};
/**
* 检查变量是否是包名
*/
EXMLCompiler.prototype.isPackageName = function (name) {
return name.indexOf(".") != -1;
};
return EXMLCompiler;
}());
/**
* Egret命名空间
*/
EXMLCompiler.E = "http://ns.egret-labs.org/egret";
/**
* Wing命名空间
*/
EXMLCompiler.W = "http://ns.egret-labs.org/wing";
EXMLCompiler.DECLARATIONS = "Declarations";
/**
* 命名空间为fs的属性名列表
*/
EXMLCompiler.wingKeys = ["$id", "$locked", "$includeIn", "$excludeFrom", "id", "locked", "includeIn", "excludeFrom"];
//=================代码生成工具类===================
var CodeBase = (function () {
function CodeBase() {
this.indent = 0;
}
CodeBase.prototype.toCode = function () {
return "";
};
/**
* 获取缩进字符串
*/
CodeBase.prototype.getIndent = function (indent) {
if (indent === void 0) { indent = -1; }
if (indent == -1)
indent = this.indent;
var str = "";
for (var i = 0; i < indent; i++) {
str += " ";
}
return str;
};
return CodeBase;
}());
var CpArguments = (function (_super) {
__extends(CpArguments, _super);
function CpArguments(name, type) {
if (name === void 0) { name = ""; }
if (type === void 0) { type = ""; }
var _this = _super.call(this) || this;
_this.name = "";
_this.type = "";
_this.name = name;
_this.type = type;
return _this;
}
CpArguments.prototype.toCode = function () {
return this.name + ":" + this.type;
};
return CpArguments;
}(CodeBase));
var CpClass = (function (_super) {
__extends(CpClass, _super);
function CpClass() {
var _this = _super.call(this) || this;
/**
* 构造函数的参数列表
*/
_this.argumentBlock = [];
/**
* 类名
*/
_this.className = "CpClass";
/**
* 类所在的路径,用于计算reference的相对路径
*/
_this.classPath = "";
/**
* 包名
*/
_this.moduleName = "";
/**
* 父类类名
*/
_this.superClass = "";
/**
* 接口列表
*/
_this.interfaceBlock = [];
/**
* 引用文件区块
*/
_this.referenceBlock = [];
/**
* 变量定义区块
*/
_this.variableBlock = [];
/**
* 函数定义区块
*/
_this.functionBlock = [];
_this.indent = 1;
return _this;
}
/**
* 添加构造函数的参数
*/
CpClass.prototype.addArgument = function (argumentItem) {
if (this.argumentBlock.indexOf(argumentItem) == -1) {
this.argumentBlock.push(argumentItem);
}
};
/**
* 添加接口
*/
CpClass.prototype.addInterface = function (interfaceName) {
if (interfaceName == null || interfaceName == "")
return;
if (this.interfaceBlock.indexOf(interfaceName) == -1) {
this.interfaceBlock.push(interfaceName);
}
};
/**
* 引用一个文件
*/
CpClass.prototype.addReference = function (referenceItem) {
if (referenceItem == null || referenceItem == "")
return;
if (this.referenceBlock.indexOf(referenceItem) == -1) {
this.referenceBlock.push(referenceItem);
}
};
/**
* 添加变量
*/
CpClass.prototype.addVariable = function (variableItem) {
if (this.variableBlock.indexOf(variableItem) == -1) {
this.variableBlock.push(variableItem);
}
};
/**
* 根据变量名获取变量定义
*/
CpClass.prototype.getVariableByName = function (name) {
var list = this.variableBlock;
var length = list.length;
for (var i; i < length; i++) {
var item = list[i];
if (item.name == name) {
return item;
}
}
return null;
};
/**
* 是否包含指定名称的变量
*/
CpClass.prototype.containsVar = function (name) {
var list = this.variableBlock;
var length = list.length;
for (var i = 0; i < length; i++) {
var item = list[i];
if (item.name == name) {
return true;
}
}
return false;
};
CpClass.prototype.sortOn = function (list, key, reverse) {
if (reverse === void 0) { reverse = false; }
var length = list.length;
for (var i = 0; i < length; i++) {
var min = i;
for (var j = i + 1; j < length; j++) {
if (reverse) {
if (list[j][key] > list[min][key])
min = j;
}
else {
if (list[j][key] < list[min][key])
min = j;
}
}
if (min != i) {