GuiBuilder => Builder

This commit is contained in:
2015-06-30 17:57:36 +03:00
parent e2361b66a0
commit 374f540fe5
2 changed files with 153 additions and 2 deletions

152
haxework/gui/Builder.hx Normal file
View File

@@ -0,0 +1,152 @@
package haxework.gui;
import haxework.resources.Resources.ResMap;
import haxework.resources.IResources;
import haxework.provider.Provider;
import openfl.Assets;
import haxework.locale.LString;
import haxe.Json;
import flash.errors.TypeError;
import flash.errors.Error;
enum Value {
SIMPLE(v:Dynamic);
RESOURCE(res:ResMap<Dynamic>, key:String);
LINK(key:String);
BUILDER(v:Builder);
ARRAY(v:Array<Value>);
}
class Field {
public var key(default, null):String;
public var value(default, null):Value;
public function new(key:String, value:Dynamic) {
this.key = key;
this.value = fieldValue(value);
}
public static function buildValue(value:Value, ?links:Dynamic):Dynamic {
return switch (value) {
case Value.SIMPLE(v):
v;
case Value.BUILDER(v):
v.build(links);
case Value.ARRAY(v):
v.map(function(i) return buildValue(i, links));
case Value.RESOURCE(r, k):
r.get(k);
case Value.LINK(k):
Reflect.field(links, k);
}
}
private static function specialValue(value):Value {
var a = value.split(":");
return switch (a[0]) {
case "asset":
switch (a[1]) {
case "image":
Value.SIMPLE(Assets.getBitmapData(a[2]));
case _:
Value.SIMPLE(value);
}
case "res":
//Reflect.field(Provider.get(IResources), a[1]).bind(a[2], object, field);
Value.RESOURCE(Reflect.field(Provider.get(IResources), a[1]), a[2]);
case "locale":
Value.SIMPLE(new LString(a[1]));
case "class":
Value.SIMPLE(Type.resolveClass(a[1]));
case "layout":
var data = Json.parse(Assets.getText(a[1]));
Value.BUILDER(new Builder(data));
case "link":
Value.LINK(a[1]); //ToDo
case _:
throw new Error("Unsupported prefix \"" + a[0] + "\"");
//Value.SIMPLE(value);
}
}
private static function fieldValue(value:Dynamic):Value {
return if (Std.is(value, Array)) {
Value.ARRAY(value.map(fieldValue));
} else if (Std.is(value, String)) {
if (value.charAt(0) == "@") {
specialValue(value.substr(1));
} else if (~/0x[A-Fa-f\d]{6}/.match(value)) {
Value.SIMPLE(Std.parseInt(value));
} else {
Value.SIMPLE(value);
}
} else if (Std.is(value, Float) || (Std.is(value, Bool))) {
Value.SIMPLE(value);
} else if (value != null) {
if (Reflect.hasField(value, "type")) {
Value.BUILDER(new Builder(value));
} else {
Value.SIMPLE(value);
}
} else {
Value.SIMPLE(value);
}
}
}
class Builder {
private var factory:Class<Dynamic>;
private var fields:Map<String, Field>;
public function new(data:Dynamic) {
if (Reflect.hasField(data, "type")) {
var type = Reflect.field(data, "type");
this.factory = Type.resolveClass(type);
if (factory == null) throw new TypeError("Class \"" + type + "\" not found");
}
this.fields = new Map<String, Field>();
if (Reflect.hasField(data, "style")) {
var style = Provider.get(IResources).styles.get(Reflect.field(data, "style"));
for (key in Reflect.fields(style)) {
fields.set(key, new Field(key, Reflect.field(style, key)));
}
}
for (key in Reflect.fields(data)) {
switch (key) {
case "type":
case "style":
case _: fields.set(key, new Field(key, Reflect.field(data, key)));
}
}
}
public function build(?links:Dynamic):Dynamic {
var instance:Dynamic = Type.createInstance(factory, []);
instance = fill(instance, links);
var initMethod:Dynamic = Reflect.field(instance, "init");
if (initMethod != null) Reflect.callMethod(instance, initMethod, []);
return instance;
}
public function fill(instance:Dynamic, ?links:Dynamic):Dynamic {
for (field in fields) {
Reflect.setProperty(instance, field.key, Field.buildValue(field.value, links));
switch (field.value) {
case Value.RESOURCE(r, k):
r.bind(k, instance, field.key);
case _:
}
}
return instance;
}
public static function createFromAsset(asset:String, ?key:String):Dynamic {
var data = Json.parse(Assets.getText(asset));
if (key != null) {
data = Reflect.field(data, key);
}
return new Builder(data);
}
}

View File

@@ -9,7 +9,6 @@ import haxework.dispath.IDispatcher;
import haxework.gui.IGroupView;
import haxework.gui.ButtonView;
import haxework.gui.skin.ColorSkin;
import haxework.gui.GuiBuilder;
import haxework.gui.GroupView;
class PopupView extends GroupView {
@@ -26,7 +25,7 @@ class PopupView extends GroupView {
inLayout = false;
skin = new ColorSkin(0x000000, 0.6);
contentView = GuiBuilder.buildFromAssets(resource, key, {listener:this});
contentView = Builder.createFromAsset(resource, key).build({listener:this});
addView(contentView);
}