From 374f540fe509153c9b3a7f0e7cfc8a93bf837fd6 Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 30 Jun 2015 17:57:36 +0300 Subject: [PATCH] GuiBuilder => Builder --- haxework/gui/Builder.hx | 152 ++++++++++++++++++++++++++++++++ haxework/gui/popup/PopupView.hx | 3 +- 2 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 haxework/gui/Builder.hx diff --git a/haxework/gui/Builder.hx b/haxework/gui/Builder.hx new file mode 100644 index 0000000..0b3c142 --- /dev/null +++ b/haxework/gui/Builder.hx @@ -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, key:String); + LINK(key:String); + BUILDER(v:Builder); + ARRAY(v:Array); +} + +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; + private var fields:Map; + + 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(); + 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); + } +} \ No newline at end of file diff --git a/haxework/gui/popup/PopupView.hx b/haxework/gui/popup/PopupView.hx index c6a5d6d..e0dc891 100755 --- a/haxework/gui/popup/PopupView.hx +++ b/haxework/gui/popup/PopupView.hx @@ -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); }