From aac6e6fadacb4ede43f0cfa5ff55f34cc6173cd1 Mon Sep 17 00:00:00 2001 From: Dmitri Granetchi Date: Sat, 27 Jun 2015 00:41:58 +0300 Subject: [PATCH] bindAll support --- src/bindx/Bind.hx | 4 +++ src/bindx/BindSignal.hx | 38 +++++++++++++++++++++ src/bindx/macro/BindMacros.hx | 8 +++++ src/bindx/macro/BindSignalProvider.hx | 4 +++ src/bindx/macro/IBindingSignalProvider.hx | 1 + test/BaseTest.hx | 40 +++++++++++++++++++++++ 6 files changed, 95 insertions(+) diff --git a/src/bindx/Bind.hx b/src/bindx/Bind.hx index 3de4fe0..2a6972f 100644 --- a/src/bindx/Bind.hx +++ b/src/bindx/Bind.hx @@ -25,4 +25,8 @@ class Bind { @:noUsing macro static public function unbindAll(object:ExprOf):Expr { return BindMacros.unbindAll(object); } + + @:noUsing macro static public function bindAll(object:ExprOf, listener:Expr, force:Bool = true):Expr { + return BindMacros.bindAll(object, listener, force); + } } \ No newline at end of file diff --git a/src/bindx/BindSignal.hx b/src/bindx/BindSignal.hx index 11ec51b..7adfbbd 100644 --- a/src/bindx/BindSignal.hx +++ b/src/bindx/BindSignal.hx @@ -92,4 +92,42 @@ class SignalTools { } } } + + static public function bindAll(bindable:bindx.IBindable, callback:Void -> Void, force = true):Void -> Void { + var listenField = function (_, _) callback(); + var listenMethod = callback; + + var signals = getSignals(bindable, force); + for (signal in signals) { + if (Std.is(signal, FieldSignal)) signal.add(listenField); + else signal.add(listenMethod); + } + + return function () { + for (signal in signals) { + if (Std.is(signal, FieldSignal)) signal.remove(listenField); + else signal.remove(listenMethod); + } + } + } + + static function getSignals(bindable:bindx.IBindable, force = true):Array> { + var signals = []; + var meta = haxe.rtti.Meta.getFields(std.Type.getClass(bindable)); + if (meta != null) for (m in std.Reflect.fields(meta)) { + var data = std.Reflect.field(meta, m); + if (std.Reflect.hasField(data, BIND_SIGNAL_META)) { + var signal:bindx.BindSignal.Signal = cast std.Reflect.field(bindable, m); + trace(signal); + if (signal == null && force) { + var args:Array = std.Reflect.field(data, BIND_SIGNAL_META); + var lazy:Bool = args[0]; + if (lazy) signal = cast std.Reflect.getProperty(bindable, m.substr(1)); + trace(signal); + } + if (signal != null) signals.push(signal); + } + } + return signals; + } } \ No newline at end of file diff --git a/src/bindx/macro/BindMacros.hx b/src/bindx/macro/BindMacros.hx index 3a07a0f..562e4ea 100644 --- a/src/bindx/macro/BindMacros.hx +++ b/src/bindx/macro/BindMacros.hx @@ -38,6 +38,14 @@ class BindMacros { return BindableMacros.bindingSignalProvider.getUnbindAllExpr(object, type); } + static inline function bindAll(object:ExprOf, listener:Expr, force:Bool = true):Expr { + var type = object.deepTypeof(); + if (!isBindable(type.getClass())) { + Context.error('\'${object.toString()}\' must be bindx.IBindable', object.pos); + } + return BindableMacros.bindingSignalProvider.getBindAllExpr(object, type, listener, force); + } + static inline function warnCheckField(field:Expr):{e:Expr, field:ClassField} { var res = null; try { diff --git a/src/bindx/macro/BindSignalProvider.hx b/src/bindx/macro/BindSignalProvider.hx index 8a68d61..3537c3c 100644 --- a/src/bindx/macro/BindSignalProvider.hx +++ b/src/bindx/macro/BindSignalProvider.hx @@ -93,6 +93,10 @@ class BindSignalProvider implements IBindingSignalProvider { return macro bindx.BindSignal.SignalTools.unbindAll($expr); } + public function getBindAllExpr(expr:ExprOf, type:Type, listener:Expr, force:Bool = true):Expr { + return macro bindx.BindSignal.SignalTools.bindAll($expr, $listener, $v{force}); + } + function generateSignal(field:Field, type:ComplexType, builder:Expr, res:Array):Void { var signalName = signalName(field.name); var meta = field.bindableMeta(); diff --git a/src/bindx/macro/IBindingSignalProvider.hx b/src/bindx/macro/IBindingSignalProvider.hx index 8a72f80..1c4d5d7 100644 --- a/src/bindx/macro/IBindingSignalProvider.hx +++ b/src/bindx/macro/IBindingSignalProvider.hx @@ -13,4 +13,5 @@ interface IBindingSignalProvider { function getClassFieldUnbindExpr(expr:Expr, field:ClassField, listener:Expr):Expr; function getClassFieldChangedExpr(expr:Expr, field:ClassField, oldValue:Expr, newValue:Expr):Expr; function getUnbindAllExpr(expr:ExprOf, type:Type):Expr; + function getBindAllExpr(expr:ExprOf, type:Type, listener:Expr, force:Bool = true):Expr; } \ No newline at end of file diff --git a/test/BaseTest.hx b/test/BaseTest.hx index 982ec73..42dea32 100644 --- a/test/BaseTest.hx +++ b/test/BaseTest.hx @@ -288,6 +288,46 @@ class BaseTest extends BuddySuite { true.should.be(true); }); + + it("bindx should bind all bindings (force mode)", function () { + var unbind = Bind.bindAll(b, function () callNum ++, true); + + b.str = "123"; + b.str2 = "123"; + Bind.notify(b.bind); + Bind.notify(b.bind2); + + callNum.should.be(4); + + unbind(); + + b.str = "234"; + b.str2 = "234"; + Bind.notify(b.bind); + Bind.notify(b.bind2); + + callNum.should.be(4); + }); + + it("bindx should bind all bindings (simple mode)", function () { + var unbind = Bind.bindAll(b, function () callNum ++, false); + + b.str = "123"; + b.str2 = "123"; + Bind.notify(b.bind); + Bind.notify(b.bind2); + + callNum.should.be(2); // ignore lazy signals + + unbind(); + + b.str = "234"; + b.str2 = "234"; + Bind.notify(b.bind); + Bind.notify(b.bind2); + + callNum.should.be(2); + }); it("bindx should resolve typedefs", function () { var a:TypeBindable1 = new TypeBindable1();