diff --git a/haxe/ui/Toolkit.hx b/haxe/ui/Toolkit.hx index af34443c7..6ad3529d3 100644 --- a/haxe/ui/Toolkit.hx +++ b/haxe/ui/Toolkit.hx @@ -1,7 +1,6 @@ package haxe.ui; import haxe.ui.backend.ToolkitOptions; -import haxe.ui.binding.BindingManager; import haxe.ui.containers.dialogs.Dialog; import haxe.ui.containers.dialogs.MessageBox; import haxe.ui.containers.dialogs.MessageBox.MessageBoxType; @@ -50,7 +49,6 @@ class Toolkit { _theme = value; if (_initialized == true) { ThemeManager.instance.applyTheme(_theme); - BindingManager.instance.refreshAll(); Screen.instance.onThemeChanged(); Screen.instance.invalidateAll(); } diff --git a/haxe/ui/backend/DialogBase.hx b/haxe/ui/backend/DialogBase.hx index 448de40f7..67a8bd323 100644 --- a/haxe/ui/backend/DialogBase.hx +++ b/haxe/ui/backend/DialogBase.hx @@ -1,7 +1,6 @@ package haxe.ui.backend; import haxe.ui.Toolkit; -import haxe.ui.binding.BindingManager; import haxe.ui.components.Button; import haxe.ui.containers.Box; import haxe.ui.containers.dialogs.Dialog; diff --git a/haxe/ui/behaviours/Behaviours.hx b/haxe/ui/behaviours/Behaviours.hx index 484f46e4e..c66d52947 100644 --- a/haxe/ui/behaviours/Behaviours.hx +++ b/haxe/ui/behaviours/Behaviours.hx @@ -1,6 +1,5 @@ package haxe.ui.behaviours; -import haxe.ui.binding.BindingManager; import haxe.ui.core.Component; import haxe.ui.events.UIEvent; import haxe.ui.util.Variant; @@ -249,7 +248,6 @@ class Behaviours { } _autoDispatch = null; - BindingManager.instance.refreshAll(); } private var _autoDispatch:Map>; diff --git a/haxe/ui/binding/BindingManager.hx b/haxe/ui/binding/BindingManager.hx deleted file mode 100644 index 62ba49a31..000000000 --- a/haxe/ui/binding/BindingManager.hx +++ /dev/null @@ -1,437 +0,0 @@ -package haxe.ui.binding; - -import haxe.ui.Toolkit; -import haxe.ui.core.Component; -import haxe.ui.core.TypeMap; -import haxe.ui.locale.LocaleManager; -import haxe.ui.scripting.ScriptInterp; -import haxe.ui.themes.ThemeManager; -import haxe.ui.util.Variant; -import hscript.Expr; -import hscript.Parser; - -class PropertyInfo { - public var name:String; - public var script:String; - public var languageBinding:Bool = false; - - public var objects:Map> = new Map>(); - - public function new() { - } - - public function addObject(objectId:String, objectProp:String) { - var array:Array = objects.get(objectId); - if (array == null) { - array = []; - objects.set(objectId, array); - } - if (array.indexOf(objectProp) == -1) { - array.push(objectProp); - } - } - - public function reset() { - objects = new Map>(); - } -} - -class TargetInfo { - public var props:Map>> = new Map>>(); - - public function new() { - } - - public function addBinding(sourceProp:String, target:Component, targetProp:PropertyInfo) { - var map:Map> = props.get(sourceProp); - if (map == null) { - map = new Map>(); - props.set(sourceProp, map); - } - - var array = map.get(target); - if (array == null) { - array = []; - map.set(target, array); - } - - array.push(targetProp); - } -} - -class BindingInfo { - public var props:Map = new Map(); - - public function new() { - } - - public function addProp(name:String, script:String):PropertyInfo { - var p = props.get(name); - if (p == null) { - p = new PropertyInfo(); - p.name = name; - p.script = script; - props.set(name, p); - } - return p; - } -} - -class BindingManager { - private static var _instance:BindingManager = null; - public static var instance(get, null):BindingManager; - private static function get_instance():BindingManager { - if (_instance == null) { - _instance = new BindingManager(); - } - return _instance; - } - - //**************************************************************************************************** - // Instance - //**************************************************************************************************** - private static var bindingInfo:Map = new Map(); - private static var targets:Map = new Map(); - - private function new() { - addStaticClass("theme", ThemeManager.instance); - addStaticClass("lookupLocaleString", LocaleManager.instance.lookupString); - } - - public function refreshAll() { - for (c in bindingInfo.keys()) { - refreshFor(c); - } - } - - public function refreshFor(c:Component) { - if (bindingInfo.exists(c) == false) { - return; - } - - var info:BindingInfo = bindingInfo.get(c); - for (propName in info.props.keys()) { - var propInfo:PropertyInfo = info.props.get(propName); - handleProp(c, propInfo); - } - } - - public function addStaticClass(name:String, c:Dynamic) { - interp.variables.set(name, c); - } - - public function add(c:Component, prop:String, script:String) { - if (c.isReady == false) { - Toolkit.callLater(function() { - add(c, prop, script); - }); - return; - } - - if (hasBindingInfo(c, prop, script) == true) { - return; - } - - var n1:Int = script.indexOf("${"); - while (n1 != -1) { - var n2:Int = script.indexOf("}", n1); - var scriptPart:String = script.substr(n1 + 2, n2 - n1 - 2); - var parser:Parser = new Parser(); - var expr:Expr = parser.parseString(scriptPart); - - var info = bindingInfo.get(c); - if (info == null) { - info = new BindingInfo(); - bindingInfo.set(c, info); - } - - var propInfo:PropertyInfo = info.addProp(prop, script); - extractFields(expr, propInfo); - for (objectId in propInfo.objects.keys()) { - for (fieldId in propInfo.objects.get(objectId)) { - var targetInfo = targets.get(objectId); - if (targetInfo == null) { - targetInfo = new TargetInfo(); - targets.set(objectId, targetInfo); - } - targetInfo.addBinding(fieldId, c, propInfo); - } - } - handleProp(c, propInfo); - - n1 = script.indexOf("${", n2); - } - } - - public function findLanguageBinding(c:Component, prop:String):PropertyInfo { - var info = bindingInfo.get(c); - if (info == null) { - return null; - } - - var propInfo:PropertyInfo = info.props.get(prop); - return propInfo; - } - - public function addLanguageBinding_old(c:Component, prop:String, script:String, overwrite:Bool = true) { - if (hasBindingInfo(c, prop, script) == true && overwrite == false) { - return; - } - - var n1:Int = script.indexOf("{{"); - while (n1 != -1) { - var n2:Int = script.indexOf("}}", n1); - var scriptPart:String = script.substr(n1 + 2, n2 - n1 - 2); - scriptPart = buildLocaleScript(scriptPart); - var parser:Parser = new Parser(); - var expr:Expr = parser.parseString(scriptPart); - - var info = bindingInfo.get(c); - if (info == null) { - info = new BindingInfo(); - bindingInfo.set(c, info); - } - var propInfo:PropertyInfo = info.props.get(prop); - if (propInfo == null) { - propInfo = info.addProp(prop, script); - } else { - propInfo.reset(); - propInfo.script = script; - } - - propInfo.languageBinding = true; - extractFields(expr, propInfo); - for (objectId in propInfo.objects.keys()) { - for (fieldId in propInfo.objects.get(objectId)) { - var targetInfo = targets.get(objectId); - if (targetInfo == null) { - targetInfo = new TargetInfo(); - targets.set(objectId, targetInfo); - } - targetInfo.addBinding(fieldId, c, propInfo); - } - } - handleProp(c, propInfo); - - n1 = script.indexOf("{{", n2); - } - } - - public function remove(c:Component) { - bindingInfo.remove(c); - } - - public function cloneBinding_old(from:Component, to:Component) { - var info = bindingInfo.get(from); - if (info == null) { - return; - } - - for (prop in info.props.keys()) { - var propInfo = info.props.get(prop); - if (propInfo.languageBinding == false) { - add(to, prop, propInfo.script); - } else { - addLanguageBinding_old(to, prop, propInfo.script); - } - } - } - - private function hasBindingInfo(c:Component, prop:String, script:String):Bool { - var info = bindingInfo.get(c); - if (info == null) { - return false; - } - - if (info.props.exists(prop) == false) { - return false; - } - - var bindingScript = info.props.get(prop); - return bindingScript.script == script; - } - -// private function isLocaleString(script:String):Bool { -// return LocaleManager.instance.hasString(StringTools.trim(script.split(",")[0])); -// } - - private function buildLocaleScript(script:String):String { - if (script == null) { - return null; - } - if (script.length == 0) { - return script; - } - if (StringTools.startsWith(script, "lookupLocaleString(")) { - return script; - } - var params = script.split(","); - script = "lookupLocaleString('" + params[0] + "'"; - params.shift(); - if (params.length > 0) { - script += ","; - script += params.join(","); - } - script += ")"; - return script; - } - - public function componentPropChanged(c:Component, prop:String) { - if (c == null || c.id == null) { - return; - } - - var targetInfo = targets.get(c.id); - if (targetInfo == null) { - return; - } - - var map:Map> = targetInfo.props.get(prop); - if (map == null) { - return; - } - - for (t in map.keys()) { - var array:Array = map.get(t); - for (prop in array) { - handleProp(t, prop); - } - } - } - - private function handleProp(t:Component, prop:PropertyInfo) { - var result:Dynamic = interpolate(prop.script, prop, t); - var currentType = Type.typeof(Reflect.getProperty(t, prop.name)); - if (currentType == TFloat) { - result = Std.parseFloat(Std.string(result)); - } else if (currentType == TInt) { - result = Std.parseInt(Std.string(result)); - } else if (currentType == TBool) { - result = (Std.string(result) == "true"); - } else if (TypeMap.getTypeInfo(t.className, prop.name) == "Variant") { - result = Variant.fromDynamic(result); - } - - Reflect.setProperty(t, prop.name, result); - } - - private function interpolate(s:String, prop:PropertyInfo, t:Component):String { - var copy:String = s; - copy = StringTools.replace(copy, "{{", "${"); - copy = StringTools.replace(copy, "}}", "}"); - var n1:Int = copy.indexOf("${"); - while (n1 != -1) { - var n2:Int = copy.indexOf("}", n1); - var before:String = copy.substr(0, n1); - var after:String = copy.substr(n2 + 1, copy.length); - var script:String = copy.substr(n1 + 2, n2 - n1 - 2); - - var result:Any = exec(script, prop, t, prop.languageBinding); - - copy = before + result + after; - n1 = copy.indexOf("${"); - } - return copy; - } - - private var interp:ScriptInterp = new ScriptInterp(); - private function exec(script:String, prop:PropertyInfo, t:Component, isLocaleString:Bool):Dynamic { - if (isLocaleString) { - script = buildLocaleScript(script); - } - var parser = new Parser(); - var expr = parser.parseString(script); - - var root = findRoot(t); - for (objectId in prop.objects.keys()) { - var object = root.findComponent(objectId, Component); - if (object != null) { - interp.variables.set(objectId, object); - } - } - interp.variables.set("this", t); - - var result:Dynamic = null; - try { - result = interp.expr(expr); - } catch (e:Dynamic) { - #if debug - trace(e); - #end - } - return result; - } - - private function findRoot(c:Component):Component { - var root = c; - - var ref = c; - while (ref != null) { - root = ref; - if (root.bindingRoot) { - break; - } - ref = ref.parentComponent; - } - - return root; - } - - private function extractFields(expr:Expr, propInfo:PropertyInfo) { - #if hscriptPos - var ex = expr.e; - #else - var ex = expr; - #end - switch (ex) { - case ECall(_, params): - for (p in params) { - extractFields(p, propInfo); - } - case EField(o, fieldId): - #if hscriptPos - var oe = o.e; - #else - var oe = o; - #end - switch (oe) { - case EIdent(objectId): - propInfo.addObject(objectId, fieldId); - case EField(o, fieldId): - #if hscriptPos - var oe = o.e; - #else - var oe = o; - #end - switch (oe) { - case EIdent(objectId): - propInfo.addObject(objectId, fieldId); - case _: - } - case _: - } - /* - case EField(EIdent(objectId), fieldId): - propInfo.addObject(objectId, fieldId); - */ - /* - case EField(EField(EIdent(objectId), fieldId), _): - propInfo.addObject(objectId, fieldId); - */ - case EIdent(objectId): - propInfo.addObject(objectId, "value"); - case EBinop(_, e1, e2): - extractFields(e1, propInfo); - extractFields(e2, propInfo); - case EUnop(_, _, e): - extractFields(e, propInfo); - case EArrayDecl(values): - for (v in values) { - extractFields(v, propInfo); - } - case EConst(_): - case _: - trace(expr); - } - } -} diff --git a/haxe/ui/components/DropDown.hx b/haxe/ui/components/DropDown.hx index 63e25320b..6b8f4e58f 100644 --- a/haxe/ui/components/DropDown.hx +++ b/haxe/ui/components/DropDown.hx @@ -2,7 +2,6 @@ package haxe.ui.components; import haxe.ui.behaviours.DataBehaviour; import haxe.ui.behaviours.DefaultBehaviour; -import haxe.ui.binding.BindingManager; import haxe.ui.components.Button.ButtonBuilder; import haxe.ui.components.Button.ButtonEvents; import haxe.ui.containers.Box; @@ -15,6 +14,7 @@ import haxe.ui.data.ArrayDataSource; import haxe.ui.data.DataSource; import haxe.ui.events.MouseEvent; import haxe.ui.events.UIEvent; +import haxe.ui.locale.LocaleManager; import haxe.ui.util.Variant; @:composite(DropDownEvents, DropDownBuilder) @@ -298,9 +298,9 @@ class ListDropDownHandler extends DropDownHandler { } if (index == -1 && _dropdown.dataSource != null) { - var info = BindingManager.instance.findLanguageBinding(_dropdown, "text"); - if (info != null && info.script != null) { - text = info.script; + var expr = LocaleManager.instance.findBindingExpr(_dropdown, "text"); + if (expr != null) { + text = expr; for (i in 0..._dropdown.dataSource.size) { var item:Dynamic = _dropdown.dataSource.get(i); if (item == text || item.value == text || item.text == text) { diff --git a/haxe/ui/containers/ListView.hx b/haxe/ui/containers/ListView.hx index 5a5886a69..958061b2d 100644 --- a/haxe/ui/containers/ListView.hx +++ b/haxe/ui/containers/ListView.hx @@ -4,7 +4,6 @@ import haxe.ui.behaviours.Behaviour; import haxe.ui.behaviours.DataBehaviour; import haxe.ui.behaviours.DefaultBehaviour; import haxe.ui.behaviours.LayoutBehaviour; -import haxe.ui.binding.BindingManager; import haxe.ui.components.VerticalScroll; import haxe.ui.constants.SelectionMode; import haxe.ui.containers.ScrollView.ScrollViewBuilder; @@ -382,7 +381,6 @@ private class DataSourceBehaviour extends DataBehaviour { _firstPass = false; _component.invalidateComponentLayout(); } - BindingManager.instance.componentPropChanged(_component, "dataSource"); } _component.invalidateComponentLayout(); } else { diff --git a/haxe/ui/containers/TableView.hx b/haxe/ui/containers/TableView.hx index 0964b1eff..99994383a 100644 --- a/haxe/ui/containers/TableView.hx +++ b/haxe/ui/containers/TableView.hx @@ -4,7 +4,6 @@ import haxe.ui.behaviours.Behaviour; import haxe.ui.behaviours.DataBehaviour; import haxe.ui.behaviours.DefaultBehaviour; import haxe.ui.behaviours.LayoutBehaviour; -import haxe.ui.binding.BindingManager; import haxe.ui.components.Column; import haxe.ui.components.Label; import haxe.ui.components.VerticalScroll; @@ -597,7 +596,6 @@ private class DataSourceBehaviour extends DataBehaviour { _firstPass = false; _component.invalidateComponentLayout(); } - BindingManager.instance.componentPropChanged(_component, "dataSource"); } _component.invalidateComponentLayout(); } else { diff --git a/haxe/ui/containers/menus/MenuBar.hx b/haxe/ui/containers/menus/MenuBar.hx index 1ede48931..d9a4874b3 100644 --- a/haxe/ui/containers/menus/MenuBar.hx +++ b/haxe/ui/containers/menus/MenuBar.hx @@ -2,7 +2,6 @@ package haxe.ui.containers.menus; import haxe.ui.Toolkit; import haxe.ui.behaviours.DefaultBehaviour; -import haxe.ui.binding.BindingManager; import haxe.ui.components.Button; import haxe.ui.containers.HBox; import haxe.ui.containers.menus.Menu; diff --git a/haxe/ui/core/Component.hx b/haxe/ui/core/Component.hx index c03a0042c..cf4269d1a 100644 --- a/haxe/ui/core/Component.hx +++ b/haxe/ui/core/Component.hx @@ -1,7 +1,6 @@ package haxe.ui.core; import haxe.ui.backend.ComponentImpl; -import haxe.ui.binding.BindingManager; import haxe.ui.dragdrop.DragManager; import haxe.ui.events.AnimationEvent; import haxe.ui.events.MouseEvent; @@ -11,6 +10,7 @@ import haxe.ui.geom.Size; import haxe.ui.layouts.DefaultLayout; import haxe.ui.layouts.DelegateLayout; import haxe.ui.layouts.Layout; +import haxe.ui.locale.LocaleManager; import haxe.ui.scripting.ScriptInterp; import haxe.ui.styles.Parser; import haxe.ui.styles.Style; @@ -542,7 +542,7 @@ class Component extends ComponentImpl implements IComponentBase implements IVali if (_compositeBuilder != null) { _compositeBuilder.destroy(); } - BindingManager.instance.remove(this); + LocaleManager.instance.unregisterComponent(this); onDestroy(); } diff --git a/haxe/ui/locale/LocaleManager.hx b/haxe/ui/locale/LocaleManager.hx index 3fd41ec04..115866948 100644 --- a/haxe/ui/locale/LocaleManager.hx +++ b/haxe/ui/locale/LocaleManager.hx @@ -64,6 +64,20 @@ class LocaleManager { refreshFor(component); } + public function unregisterComponent(component:Component) { + _registeredComponents.remove(component); + } + + public function findBindingExpr(component:Component, prop:String):String { + var propMap = _registeredComponents.get(component); + if (propMap == null) { + return null; + } + + var entry = propMap.get(prop); + return entry.expr; + } + public function cloneForComponent(from:Component, to:Component) { var propMap = _registeredComponents.get(from); if (propMap == null) {