11 Commits
0.6.1 ... 0.8.0

Author SHA1 Message Date
086518ae42 [doc] update readme 2018-03-06 22:25:58 +03:00
a53510d1d4 [macro] added @:view macro, refactored @:template macro 2018-03-06 15:44:07 +03:00
4a65cef02a added meta parser 2018-03-05 17:38:11 +03:00
56baf7cfdc fix 2018-02-16 22:20:33 +03:00
97b7686694 [gui] support yaml in builder style 2018-02-15 23:56:46 +03:00
5b4e8dbb5e [gui] change access for item in ListVIew 2018-02-06 10:54:04 +03:00
9671a37d0d [gui] ListViewListener typedef 2018-02-05 22:42:02 +03:00
823f3ea596 [view] added yaml template support 2018-02-05 17:52:58 +03:00
cc6717f46b [provider] ObjectMap -> StringMap 2018-01-26 10:56:38 +03:00
6bc4f297d5 [provider] fix build method 2018-01-25 22:54:36 +03:00
a6bbcb408f [log] fix SocketLogger for flash 2017-12-20 17:50:57 +03:00
20 changed files with 475 additions and 297 deletions

View File

@@ -14,8 +14,8 @@ form.json:
```json
{
"type":"haxework.gui.VGroupView",
"skin":{"type":"haxework.gui.skin.ColorSkin", "color":"0xffff00"},
"@type":"haxework.gui.VGroupView",
"skin":{"@type":"haxework.gui.skin.ColorSkin", "color":"0xffff00"},
"paddings":20,
"layoutMargin":10,
"views":[
@@ -23,13 +23,13 @@ form.json:
"id":"view1",
"type":"haxework.gui.SpriteView",
"pWidth":100, "pHeight":100,
"skin":{"type":"haxework.gui.skin.ColorSkin", "color":"0xff0000"}
"skin":{"@type":"haxework.gui.skin.ColorSkin", "color":"0xff0000"}
},
{
"id":"view2",
"type":"haxework.gui.SpriteView",
"pWidth":100, "height":50,
"skin":{"type":"haxework.gui.skin.ColorSkin", "color":"0x00ff00"}
"skin":{"@type":"haxework.gui.skin.ColorSkin", "color":"0x00ff00"}
}
]
}
@@ -37,12 +37,15 @@ form.json:
```haxe
@:template("form.json")
class FormView extends VGroupView implements ViewBuilder {}
class FormView extends VGroupView {
@:view public var view1:IView;
@:view("view2") public var anyVarName:IView;
}
var form = new FormView();
Root.bind(form); // Add form to stage as root view element.
trace(form.view1);
trace(form.view2);
trace(form.anyVarName);
```
## Loader

1
extraParams.hxml Normal file
View File

@@ -0,0 +1 @@
--macro haxework.parser.Parser.auto()

View File

@@ -2,13 +2,15 @@
"name": "haxework",
"url" : "https://bitbucket.org/shmyga/haxework.git",
"license": "BSD",
"tags": ["flash"],
"tags": ["flash", "openfl"],
"description": "Framework.",
"version": "0.6.1",
"version": "0.8.0",
"releasenote": "Update.",
"contributors": ["shmyga"],
"classPath": "src/main",
"dependencies": {
"promhx": ""
"promhx": "1.1.0",
"openfl": "7.0.0",
"yaml": "1.3.0"
}
}

View File

@@ -1,4 +1,9 @@
-cp src
-lib haxework
-cp ../../src/main
-lib yaml
-lib promhx
-main ViewExample.hx
--macro haxework.parser.Parser.auto()
-swf target/ViewExample.swf
#-as3 target

View File

@@ -1,29 +1,39 @@
package;
import haxework.gui.ViewBuilder;
import haxework.gui.View;
import haxework.gui.VGroupView;
import haxework.gui.ButtonView;
import haxework.gui.Root;
@:template("form.json")
class FormView extends VGroupView implements ViewBuilder {}
@:template2("form.json")
class FormView extends VGroupView {
@:view public var panel(default, null):View;
@:view public var button1(default, null):View;
@:view public var button2(default, null):View;
@:view public var button3(default, null):View;
private function init() {
trace('Init');
}
}
class ViewExample {
public static function main() {
new ViewExample();
}
public static function main() {
new ViewExample();
}
public function new() {
var form = new FormView({listener:this});
Root.bind(form);
trace(form.panel);
trace(form.button1);
trace(form.button2);
trace(form.button3);
}
public function new() {
var form:FormView = new FormView();
Root.bind(form);
trace(form.panel);
trace(form.button1);
trace(form.button2);
trace(form.button3);
}
public function onPress(view:ButtonView):Void {
trace("onPress: " + view.id);
}
public function onPress(view:ButtonView):Void {
trace("onPress: " + view.id);
}
}

View File

@@ -37,8 +37,7 @@
"width":100,
"pHeight":100,
"skin":{"@type":"haxework.gui.skin.ButtonColorSkin", "color":"0xcc0000"},
"text":"Text1",
"onPress":"@link:listener"
"text":"Text1"
},
{
"id":"button2",
@@ -47,8 +46,7 @@
"skin":{"@type":"haxework.gui.skin.ButtonColorSkin", "color":"0x00cc00"},
"text":"Text2",
"fontFamily":"Georgia",
"fontColor":"0xffffff",
"onPress":"@link:listener"
"fontColor":"0xffffff"
},
{
"id":"button3",
@@ -57,8 +55,7 @@
"skin":{"@type":"haxework.gui.skin.ButtonColorSkin", "color":"0x00cccc"},
"text":"Text 3333333333 ddd",
"fontFamily":"Tahoma",
"fontColor":"0xff0000",
"onPress":"@link:listener"
"fontColor":"0xff0000"
}
]
}

View File

@@ -1,7 +1,7 @@
package haxework.gui;
import flash.text.TextField;
import haxework.gui.IView.Content;
import haxework.gui.IView;
import flash.text.TextFormatAlign;
interface ITextView extends IView extends HasPaddings {

View File

@@ -1,14 +0,0 @@
package haxework.gui;
import haxework.gui.build.Builder;
@:remove @:autoBuild(haxework.gui.ViewBuilderImpl.build())
extern interface ViewBuilder {}
class ViewBuilderImpl {
#if macro
public static function build() {
return new Builder().build();
}
#end
}

View File

@@ -1,193 +0,0 @@
package haxework.gui.build;
#if macro
import haxe.macro.Context;
import haxework.gui.build.PositionJsonParser;
import haxe.macro.Expr;
import haxe.macro.Expr.Field;
class Builder {
private var templateFile:String;
private var templateKey:String;
private var styleFile:String;
private var template:Dynamic;
private var fields:Array<Field>;
private var exprs:Array<Expr>;
private var style:Dynamic;
private var i:Int;
public function new() {
var templateMeta = BuilderUtil.getMeta(":template");
var templatePath = templateMeta[0].split("@");
templateFile = Context.resolvePath(templatePath[0]);
templateKey = templatePath[1];
template = BuilderUtil.loadJsonFile(templateFile);
if (templateKey != null) template = Reflect.field(template, templateKey);
if (templateMeta[1] != null) {
styleFile = Context.resolvePath(templateMeta[1]);
style = BuilderUtil.loadJsonFile(styleFile);
}
fields = Context.getBuildFields();
exprs = [];
i = 0;
}
private function getPosition(?position:JsonKeyPosition):Position {
var min = position == null ? 1 : position.min + 32; // :-(
var max = position == null ? 1 : position.max + 32;
var file = position == null || position.file == null ? templateFile : position.file;
return Context.makePosition({min:min, max:max, file:file});
}
private function specialValue(name:String, key:String, a:Array<String>, position:JsonKeyPosition):Dynamic {
return switch (a[0]) {
case "asset":
switch (a[1]) {
case "image":
"openfl.Assets.getBitmapData(\"" + a[2] + "\")";
case _:
a[2];
}
case "res":
var res = "haxework.provider.Provider.get(haxework.resources.IResources)." + a[1];
var bindExpr = res + ".bind(\"" + a[2] + "\", " + name + ", \"" + key + "\")";
exprs.push(Context.parse(bindExpr, getPosition(position)));
//res + ".get(\"" + a[2] + "\")";
null;
case "locale":
"new haxework.locale.LString(\"" + a[1] + "\")";
case "class":
a[1];
case "layout":
var template = BuilderUtil.loadJsonFile(a[1]);
return getValue(name, key, template, position);
case "link":
"(links == null) ? untyped this : Reflect.field(links, \"" + a[1] + "\")";
case _:
Context.error("Unsupported prefix \"" + a[0] + "\"", getPosition(position));
}
}
private function getValue(name:String, key:String, value:Dynamic, position:JsonKeyPosition):Dynamic {
return if (Std.is(value, Array)) {
value.map(function(v) {
return getValue(null, null, v, position);
});
} else if (Std.is(value, String)) {
if (value.charAt(0) == "@") {
specialValue(name, key, value.substring(1, value.length).split(":"), position);
} else if (~/(0x|#)[A-Fa-f\d]{6}/.match(value)) {
Std.parseInt(StringTools.replace(Std.string(value), "#", "0x"));
} else {
"\"" + value + "\"";
}
} else if (Std.is(value, Float) || (Std.is(value, Bool))) {
value;
} else if (value != null) {
if (Reflect.hasField(value, "@type")) {
var n = "a" + i++;
var type = Reflect.field(value, "@type");
if (type == "Dynamic") {
//ToDo:
exprs.push(Context.parse("var " + n + " = cast {}", getPosition(position)));
} else {
exprs.push(Context.parse("var " + n + " = new " + type + "()", getPosition(position)));
}
createElement(value, n);
n;
} else {
Context.error("Need @type field", getPosition(position));
null;
}
} else {
value;
}
}
private function createElement(template:Dynamic, name:String):String {
if (Reflect.hasField(template, "@style")) {
var s = Reflect.field(style, Reflect.field(template, "@style"));
for (key in Reflect.fields(s)) {
if (key.charAt(0) != "$" && !Reflect.hasField(template, key)) {
Reflect.setField(template, key, Reflect.field(s, key));
Reflect.setField(template, "$" + key, Reflect.field(s, "$" + key));
}
}
}
if (Reflect.hasField(template, "id")) {
var id = Reflect.field(template, "id");
var type = Reflect.field(template, "@type");
var expr = Context.parse("var a:" + type, getPosition());
var complexType = switch (expr.expr) {
case EVars(vars): vars[0].type;
case _: null;
}
fields.push({
name: id,
access: [APublic],
pos: getPosition(),
kind: FProp("default", "null", complexType)
});
exprs.push(Context.parse("this." + id + " = " + name, getPosition()));
}
for (key in Reflect.fields(template)) {
if (key.charAt(0) == "$" || key.charAt(0) == "@") continue;
var position = Reflect.field(template, "$" + key);
var value = getValue(name, key, Reflect.field(template, key), position);
if (value != null) {
exprs.push(Context.parse(name + "." + key + " = " + value, getPosition(position)));
}
}
return name;
}
public function build():Array<Field> {
createElement(template, "this");
var init = false;
for (f in fields) if (f.name == "init") {
init = true;
break;
}
fields.push({
name: "build",
access: [APublic],
pos: getPosition(),
kind: FFun({
args: [{name:"links", type:TPath({name:"Dynamic", pack:[], params:[]}), opt:true, value:null}],
expr: macro $b{exprs},
params: [],
ret: null
})
});
var contstrExprs = [];
contstrExprs.push(macro super());
contstrExprs.push(macro build(links));
if (init) contstrExprs.push(macro init());
fields.push({
name: "new",
access: [APublic],
pos: getPosition(),
kind: FFun({
args: [{name:"links", type:TPath({name:"Dynamic", pack:[], params:[]}), opt:true, value:null}],
expr: macro $b{contstrExprs},
params: [],
ret: null
})
});
return fields;
}
}
#end

View File

@@ -1,36 +0,0 @@
package haxework.gui.build;
#if macro
import haxe.macro.Context;
import haxe.macro.Expr.Constant;
import haxe.macro.Expr.ExprDef;
class BuilderUtil {
public static function loadJsonFile(path:String) {
Context.registerModuleDependency(Context.getLocalModule(), path);
var content = sys.io.File.getContent(path);
var json = null;
try {
json = PositionJsonParser.parse(content, path);
} catch(error:Dynamic) {
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
}
Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
return json;
}
public static function getMeta(key:String):Array<String> {
var c = Context.getLocalClass().get();
for (meta in c.meta.get()) {
if (meta.name == key) {
return meta.params.map(function(param) return switch(param.expr) {
case ExprDef.EConst(Constant.CString(value)): value;
case _: null;
});
}
}
return [];
}
}
#end

View File

@@ -39,7 +39,7 @@ class ListView<D> extends GroupView implements ScrollListener {
private var mask:SpriteView;
private var itemSize:Float;
private var items:Array<IListItemView<D>>;
public var items(default, null):Array<IListItemView<D>>;
private var itemsListeners:Map<IListItemView<D>, MouseEvent->Void>;
public function new(layout:ILayout, otherLayout:ILayout) {
@@ -241,7 +241,7 @@ interface IListItemView<D> extends IView {
public var data(default, set):D;
}
interface ListViewListener<D> {
typedef ListViewListener<D> = {
public function onListItemClick(item:IListItemView<D>):Void;
}

View File

@@ -1,6 +1,6 @@
package haxework.gui.skin;
import haxework.gui.IView.Content;
import haxework.gui.IView;
interface ISkin<V:IView> {
public function draw(view:V):Void;

View File

@@ -47,7 +47,7 @@ class SocketLogger extends BaseLogger {
try {
var s:String = p.fileName + ":" + p.lineNumber + ": " + text + "\n";
#if flash
socket.writeUTF(s);
socket.writeUTFBytes(s);
socket.flush();
#else
socket.write(s);

View File

@@ -0,0 +1,45 @@
package haxework.macro;
import yaml.Parser;
import yaml.Yaml;
import haxe.macro.Context;
class FileUtil {
public static function loadJsonFile(path:String):Dynamic {
Context.registerModuleDependency(Context.getLocalModule(), path);
var content = sys.io.File.getContent(path);
var json = null;
try {
json = PositionJsonParser.parse(content, path);
} catch (error:Dynamic) {
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
}
Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
return json;
}
public static function loadYamlFile(path:String):Dynamic {
Context.registerModuleDependency(Context.getLocalModule(), path);
var content = sys.io.File.getContent(path);
var result = null;
try {
// ToDo: extract poisiton info
result = Yaml.parse(content, Parser.options().useObjects());
} catch (error:Dynamic) {
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
}
//Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
return result;
}
public static function loadFile(path:String):Dynamic {
var ext = path.split('.').pop();
return switch(ext) {
case 'json': loadJsonFile(path);
case 'yml' | 'yaml': loadYamlFile(path);
case x: throw 'Unsupported file format: "${x}"';
}
}
}

View File

@@ -1,4 +1,4 @@
package haxework.gui.build;
package haxework.macro;
typedef JsonKeyPosition = {
var min:Int;

View File

@@ -0,0 +1,52 @@
package haxework.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
class ProvideMacro {
public static function has(field:Field):Bool {
for (md in field.meta) if (md.name == ":provide") {
return true;
}
return false;
}
private var field:Field;
public function new(field:Field) {
this.field = field;
}
public function apply():Array<Field> {
var result:Array<Field> = [];
var type:ComplexType = switch field.kind {
case FieldType.FVar(t): t;
default: null;
}
var name:String = switch type {
case ComplexType.TPath(p): p.name;
default: null;
}
result.push({
name: field.name,
access: [Access.APublic],
pos: field.pos,
kind: FieldType.FProp('get', 'never', type)
});
result.push({
name: 'get_${field.name}',
access: [Access.APrivate, Access.AInline],
pos: field.pos,
kind: FieldType.FFun({
args: [],
expr: Context.parse('return haxework.provider.Provider.get(${name})', field.pos),
params: [],
ret: type
})
});
return result;
}
}

View File

@@ -0,0 +1,232 @@
package haxework.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxework.macro.PositionJsonParser;
class TemplateMacro {
private static inline var metaName:String = ':template';
public static function has(classType:ClassType):Bool {
for (md in classType.meta.get()) if (md.name == metaName) {
return true;
}
return false;
}
private var classType:ClassType;
private var fields:Array<Field>;
private var bindings:Map<String, String>;
private var meta(get, never):MetadataEntry;
private var templateFile:String;
private var template:Dynamic;
private var style:Dynamic;
private var i:Int;
private function get_meta():MetadataEntry {
for (md in classType.meta.get()) if (md.name == metaName) {
return md;
}
return null;
}
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
var params = Util.getMetaParams(meta);
templateFile = Context.resolvePath(params[0]);
template = FileUtil.loadFile(templateFile);
if (params.length > 1) {
var styleFile = params.length > 1 ? Context.resolvePath(params[1]) : null;
style = FileUtil.loadFile(styleFile);
}
bindings = findViewsBindings(fields);
}
private static function getSpecField(object:Dynamic, field:String):Dynamic {
if (Reflect.hasField(object, "@" + field)) {
return Reflect.field(object, "@" + field);
} else if (Reflect.hasField(object, "$" + field)) {
return Reflect.field(object, "$" + field);
} else {
return null;
}
}
private function getPosition(?position:JsonKeyPosition):Position {
var min = position == null ? 1 : position.min + 32; // :-(
var max = position == null ? 1 : position.max + 32;
var file = position == null || position.file == null ? templateFile : position.file;
return Context.makePosition({min:min, max:max, file:file});
}
private function specialValue(name:String, key:String, a:Array<String>, position:JsonKeyPosition, exprs:Array<Expr>):Dynamic {
return switch (a[0]) {
case "asset":
switch (a[1]) {
case "image":
"openfl.Assets.getBitmapData(\"" + a[2] + "\")";
case _:
a[2];
}
case "res":
var res = "haxework.provider.Provider.get(haxework.resources.IResources)." + a[1];
var bindExpr = res + ".bind(\"" + a[2] + "\", " + name + ", \"" + key + "\")";
exprs.push(Context.parse(bindExpr, getPosition(position)));
//res + ".get(\"" + a[2] + "\")";
null;
case "locale":
"new haxework.locale.LString(\"" + a[1] + "\")";
case "class":
a[1];
case "layout":
var template = FileUtil.loadJsonFile(a[1]);
return createValue(name, key, template, position, exprs);
case "link":
"(links == null) ? untyped this : Reflect.field(links, \"" + a[1] + "\")";
case _:
Context.error("Unsupported prefix \"" + a[0] + "\"", getPosition(position));
}
}
private static function getType(value:Dynamic, position:Position):String {
var type:String = getSpecField(value, "type");
if (type == null) {
Context.error("Need @type field", position);
}
return type;
}
private function createValue(name:String, key:String, value:Dynamic, position:JsonKeyPosition, exprs:Array<Expr>):Dynamic {
return if (Std.is(value, Array)) {
value.map(function(v) {
return createValue(null, null, v, position, exprs);
});
} else if (Std.is(value, String)) {
if (value.charAt(0) == "@" || value.charAt(0) == "$") {
specialValue(name, key, value.substring(1, value.length).split(":"), position, exprs);
} else if (~/(0x|#)[A-Fa-f\d]{6}/.match(value)) {
Std.parseInt(StringTools.replace(Std.string(value), "#", "0x"));
} else {
"\"" + value + "\"";
}
} else if (Std.is(value, Float) || (Std.is(value, Bool))) {
value;
} else if (value != null) {
var type = getType(value, getPosition(position));
if (type != null) {
var n = 'a${i++}';
if (type == "Dynamic") {
//ToDo:
exprs.push(Context.parse("var " + n + " = cast {}", getPosition(position)));
} else {
exprs.push(Context.parse("var " + n + " = new " + type + "()", getPosition(position)));
}
createElement(n, value, exprs);
n;
} else {
null;
}
} else {
value;
}
}
private function createElement(name:String, data:Dynamic, exprs:Array<Expr>):String {
var s = getSpecField(data, "style");
if (s != null) {
var s = Reflect.field(style, s);
for (key in Reflect.fields(s)) {
if (key.charAt(0) != "$" && !Reflect.hasField(data, key)) {
Reflect.setField(data, key, Reflect.field(s, key));
Reflect.setField(data, "$" + key, Reflect.field(s, "$" + key));
}
}
}
if (Reflect.hasField(data, "id")) {
var id = Reflect.field(data, "id");
if (bindings.exists(id)) {
var bind = bindings.get(id);
exprs.push(Context.parse('this.${bind} = ${name}', getPosition()));
}
}
for (key in Reflect.fields(data)) {
if (key.charAt(0) == "$" || key.charAt(0) == "@") continue;
var position = Reflect.field(data, "$" + key);
var value = createValue(name, key, Reflect.field(data, key), position, exprs);
if (value != null) {
exprs.push(Context.parse(name + "." + key + " = " + value, getPosition(position)));
}
}
return name;
}
private function buildBuild(exprs:Array<Expr>):Field {
return {
name: "build",
access: [Access.APrivate],
pos: getPosition(),
kind: FieldType.FFun({
args: [],
expr: macro $b{exprs},
params: [],
ret: null
})
}
}
private function buildConstructor(init:Bool):Field {
var contstrExprs = [];
contstrExprs.push(macro super());
contstrExprs.push(macro build());
if (init) contstrExprs.push(macro init());
return {
name: "new",
access: [Access.APublic],
pos: getPosition(),
kind: FieldType.FFun({
args: [],
expr: macro $b{contstrExprs},
params: [],
ret: null
})
};
}
private static function findViewsBindings(fields:Array<Field>):Map<String, String> {
var result:Map<String, String> = new Map();
for (field in fields) if (field.meta != null) {
for (meta in field.meta) {
if (meta.name == ':view') {
var viewId:String = meta.params.length == 0 ? field.name : switch meta.params[0].expr {
case ExprDef.EConst(Constant.CString(value)): value;
default: null;
}
result.set(viewId, field.name);
}
}
}
return result;
}
public function apply():Array<Field> {
i = 0;
var result:Array<Field> = fields.slice(0);
var exprs:Array<Expr> = [];
var init = Lambda.exists(result, function(f) return f.name == 'init');
createElement("this", template, exprs);
result.push(buildBuild(exprs));
result.push(buildConstructor(init));
return result;
}
}

View File

@@ -0,0 +1,18 @@
package haxework.macro;
import haxe.macro.Expr;
class Util {
public static function getMetaParams(meta:MetadataEntry):Array<String> {
return meta.params.map(function(param:Expr) return switch(param.expr) {
case ExprDef.EConst(Constant.CString(value)): value;
case _: null;
});
}
public inline static function DynamicType():ComplexType {
return ComplexType.TPath({name:'Dynamic', pack:[], params:[]});
}
}

View File

@@ -0,0 +1,50 @@
package haxework.parser;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type.ClassType;
import haxe.macro.Type.Ref;
import haxe.macro.Type;
import haxework.macro.ProvideMacro;
import haxework.macro.TemplateMacro;
class Parser {
private static function auto():Void {
haxe.macro.Compiler.addGlobalMetadata("", "@:build(haxework.parser.Parser.autoRun())", true, true, false);
}
private static macro function autoRun():Array<Field> {
var t:Type = Context.getLocalType();
switch (t) {
case null: return null;
case Type.TInst(_.get() => ct, _):
var modify:Bool = false;
var fields:Array<Field> = Context.getBuildFields();
var result:Array<Field> = [];
var appends:Array<Field> = [];
// process fields meta
for (field in fields) {
if (ProvideMacro.has(field)) {
modify = true;
var provide = new ProvideMacro(field);
result = result.concat(provide.apply());
} else {
result.push(field);
}
}
if (modify) {
fields = result;
}
// process class meta
if (TemplateMacro.has(ct)) {
modify = true;
var template = new TemplateMacro(ct, fields);
fields = template.apply();
}
return modify ? fields : null;
default: return null;
}
}
}

View File

@@ -1,30 +1,36 @@
package haxework.provider;
import haxe.ds.ObjectMap;
class Provider {
//private static var factories:ObjectMap<Dynamic, Class<Dynamic>> = new ObjectMap<Dynamic, Class<Dynamic>>();
private static var factories:ObjectMap<Dynamic, Class<Dynamic>> = cast [
private static function key<T>(i:Class<T>, ?type:Dynamic):String {
var result = Type.getClassName(i);
if (type != null) result += ':${type}';
return result;
}
//private static var factories:Map<String, Class<Dynamic>> = new Map();
private static var factories:Map<String, Class<Dynamic>> = cast [
#if (!neko)
haxework.net.manage.LoaderManager => haxework.net.manage.ILoaderManager
key(haxework.net.manage.LoaderManager) => haxework.net.manage.ILoaderManager
#end
];
private static var args:ObjectMap<Dynamic, Array<Dynamic>> = new ObjectMap<Dynamic, Array<Dynamic>>();
private static var instances:ObjectMap<Dynamic, Dynamic> = new ObjectMap<Dynamic, Dynamic>();
private static var args:Map<String, Array<Dynamic>> = new Map();
private static var instances:Map<String, Dynamic> = new Map();
public static function setFactory<T>(i:Class<T>, clazz:Class<T>, ?type:Dynamic, ?args:Array<Dynamic>):Void {
factories.set(type == null ? i : i + type, clazz);
if (args != null) Provider.args.set(type == null ? i : i + type, args);
var key = key(i, type);
factories.set(key, clazz);
if (args != null) Provider.args.set(key, args);
}
public static function set<T>(i:Class<T>, instance:T, ?type:Dynamic):Void {
instances.set(type == null ? i : i + type, instance);
var key = key(i, type);
instances.set(key, instance);
}
public static function get<T>(i:Class<T>, ?type:Dynamic):T {
var key:Dynamic = (type == null) ? i : i + type;
var key = key(i, type);
if (instances.exists(key)) {
return instances.get(key);
} else if (factories.exists(key)) {
@@ -32,17 +38,17 @@ class Provider {
instances.set(key, instance);
return instance;
} else {
throw "Factory for\" " + i + "\" not found";
throw 'Factory for "${key}" not found';
}
}
public static function build<T>(i:Class<T>, ?type:Dynamic):T {
var key:Dynamic = (type == null) ? i : type;
var key = key(i, type);
if (factories.exists(key)) {
var instance:T = Type.createInstance(factories.get(key), args.exists(key) ? args.get(key) : []);
return instance;
} else {
throw "Factory for\"" + i + "\" not found";
throw 'Factory for "${key}" not found';
}
}