Rodrigo Lopez Peker

- Clean up more code on GetInstance() and added more docs.

- Fixes issue #521. Still needs to be tested, is a partial solution and i believe parse_route.dart requires a much deeper cleanup.
- Added a new BindingsBuilder(), to simplify the Bindings generation without the need to use a custom class.
- Modified several operators in _RxImpl and subclasses. rx.toString() solves to rx.value.toString(), and in all Rx >>= works as assignment, also specific operator overloads were added to RX versions of List, String, double, num, int.
1 -import 'package:flutter/cupertino.dart';  
2 import 'package:get/src/core/log.dart'; 1 import 'package:get/src/core/log.dart';
3 import 'package:get/src/navigation/root/smart_management.dart'; 2 import 'package:get/src/navigation/root/smart_management.dart';
4 import 'package:get/src/state_manager/rx/rx_interface.dart'; 3 import 'package:get/src/state_manager/rx/rx_interface.dart';
@@ -11,28 +10,26 @@ class GetConfig { @@ -11,28 +10,26 @@ class GetConfig {
11 static String currentRoute; 10 static String currentRoute;
12 } 11 }
13 12
14 -class Lazy {  
15 - Lazy(this.builder, this.fenix);  
16 - bool fenix;  
17 - FcBuilderFunc builder;  
18 -}  
19 -  
20 class GetInstance { 13 class GetInstance {
21 - factory GetInstance() {  
22 - if (_getInstance == null) _getInstance = GetInstance._();  
23 - return _getInstance;  
24 - } 14 + factory GetInstance() => _getInstance ??= GetInstance._();
25 const GetInstance._(); 15 const GetInstance._();
26 static GetInstance _getInstance; 16 static GetInstance _getInstance;
27 17
28 - static Map<dynamic, dynamic> _singl = {};  
29 - static Map<dynamic, Lazy> _factory = {}; 18 + /// Holds references to every registered Instance when using
  19 + /// Get.[put]
  20 + static Map<String, _FcBuilder> _singl = {};
  21 +
  22 + /// Holds a reference to every registered callback when using
  23 + /// Get.[lazyPut]
  24 + static Map<String, _Lazy> _factory = {};
  25 +
30 static Map<String, String> _routesKey = {}; 26 static Map<String, String> _routesKey = {};
31 27
  28 + static GetQueue _queue = GetQueue();
  29 +
32 void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) { 30 void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
33 String key = _getKey(S, tag); 31 String key = _getKey(S, tag);
34 -  
35 - _factory.putIfAbsent(key, () => Lazy(builder, fenix)); 32 + _factory.putIfAbsent(key, () => _Lazy(builder, fenix));
36 } 33 }
37 34
38 Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder, 35 Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
@@ -40,7 +37,7 @@ class GetInstance { @@ -40,7 +37,7 @@ class GetInstance {
40 return put<S>(await builder(), tag: tag, permanent: permanent); 37 return put<S>(await builder(), tag: tag, permanent: permanent);
41 } 38 }
42 39
43 - /// Injects a Instance [S] in [GetInstance]. 40 + /// Injects an instance <[S]> in memory to be globally accessible.
44 /// 41 ///
45 /// No need to define the generic type <[S]> as it's inferred from the [dependency] 42 /// No need to define the generic type <[S]> as it's inferred from the [dependency]
46 /// 43 ///
@@ -48,7 +45,6 @@ class GetInstance { @@ -48,7 +45,6 @@ class GetInstance {
48 /// - [tag] optionally, use a [tag] as an "id" to create multiple records of the same Type<[S]> 45 /// - [tag] optionally, use a [tag] as an "id" to create multiple records of the same Type<[S]>
49 /// - [permanent] keeps the Instance in memory, not following [GetConfig.smartManagement] 46 /// - [permanent] keeps the Instance in memory, not following [GetConfig.smartManagement]
50 /// rules. 47 /// rules.
51 - ///  
52 S put<S>( 48 S put<S>(
53 S dependency, { 49 S dependency, {
54 String tag, 50 String tag,
@@ -73,7 +69,6 @@ class GetInstance { @@ -73,7 +69,6 @@ class GetInstance {
73 /// Repl a = find(); 69 /// Repl a = find();
74 /// Repl b = find(); 70 /// Repl b = find();
75 /// print(a==b); (false)``` 71 /// print(a==b); (false)```
76 - ///  
77 void create<S>( 72 void create<S>(
78 FcBuilderFunc<S> builder, { 73 FcBuilderFunc<S> builder, {
79 String name, 74 String name,
@@ -84,7 +79,6 @@ class GetInstance { @@ -84,7 +79,6 @@ class GetInstance {
84 } 79 }
85 80
86 /// Injects the Instance [S] builder into the [_singleton] HashMap. 81 /// Injects the Instance [S] builder into the [_singleton] HashMap.
87 - ///  
88 void _insert<S>({ 82 void _insert<S>({
89 bool isSingleton, 83 bool isSingleton,
90 String name, 84 String name,
@@ -94,13 +88,12 @@ class GetInstance { @@ -94,13 +88,12 @@ class GetInstance {
94 assert(builder != null); 88 assert(builder != null);
95 final key = _getKey(S, name); 89 final key = _getKey(S, name);
96 _singl.putIfAbsent( 90 _singl.putIfAbsent(
97 - key, () => FcBuilder<S>(isSingleton, builder, permanent, false)); 91 + key, () => _FcBuilder<S>(isSingleton, builder, permanent, false));
98 } 92 }
99 93
100 /// Clears from memory registered Instances associated with [routeName] when 94 /// Clears from memory registered Instances associated with [routeName] when
101 /// using [GetConfig.smartManagement] as [SmartManagement.full] or [SmartManagement.keepFactory] 95 /// using [GetConfig.smartManagement] as [SmartManagement.full] or [SmartManagement.keepFactory]
102 /// Meant for internal usage of [GetPageRoute] and [GetDialogRoute] 96 /// Meant for internal usage of [GetPageRoute] and [GetDialogRoute]
103 - ///  
104 Future<void> removeDependencyByRoute(String routeName) async { 97 Future<void> removeDependencyByRoute(String routeName) async {
105 final keysToRemove = <String>[]; 98 final keysToRemove = <String>[];
106 _routesKey.forEach((key, value) { 99 _routesKey.forEach((key, value) {
@@ -123,7 +116,6 @@ class GetInstance { @@ -123,7 +116,6 @@ class GetInstance {
123 /// Optionally associating the current Route to the lifetime of the instance, 116 /// Optionally associating the current Route to the lifetime of the instance,
124 /// if [GetConfig.smartManagement] is marked as [SmartManagement.full] or 117 /// if [GetConfig.smartManagement] is marked as [SmartManagement.full] or
125 /// [GetConfig.keepFactory] 118 /// [GetConfig.keepFactory]
126 - ///  
127 bool _initDependencies<S>({String name}) { 119 bool _initDependencies<S>({String name}) {
128 final key = _getKey(S, name); 120 final key = _getKey(S, name);
129 bool isInit = _singl[key].isInit; 121 bool isInit = _singl[key].isInit;
@@ -139,23 +131,23 @@ class GetInstance { @@ -139,23 +131,23 @@ class GetInstance {
139 131
140 /// Links a Class instance [S] (or [tag]) to the current route. 132 /// Links a Class instance [S] (or [tag]) to the current route.
141 /// Requires usage of [GetMaterialApp]. 133 /// Requires usage of [GetMaterialApp].
142 - ///  
143 void _registerRouteInstance<S>({String tag}) { 134 void _registerRouteInstance<S>({String tag}) {
144 _routesKey.putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute); 135 _routesKey.putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute);
145 } 136 }
146 137
147 - /// Finds and returns a Class instance [S] (or tag) without further processing. 138 + /// Finds and returns a Instance<[S]> (or [tag]) without further processing.
148 S findByType<S>(Type type, {String tag}) { 139 S findByType<S>(Type type, {String tag}) {
149 String key = _getKey(type, tag); 140 String key = _getKey(type, tag);
150 return _singl[key].getDependency() as S; 141 return _singl[key].getDependency() as S;
151 } 142 }
152 143
  144 + /// Initializes the controller
153 void _startController<S>({String tag}) { 145 void _startController<S>({String tag}) {
154 final key = _getKey(S, tag); 146 final key = _getKey(S, tag);
155 final i = _singl[key].getDependency(); 147 final i = _singl[key].getDependency();
156 if (i is DisposableInterface) { 148 if (i is DisposableInterface) {
157 i.onStart(); 149 i.onStart();
158 - GetConfig.log('$key has been initialized'); 150 + GetConfig.log('"$key" has been initialized');
159 } 151 }
160 } 152 }
161 153
@@ -180,20 +172,20 @@ class GetInstance { @@ -180,20 +172,20 @@ class GetInstance {
180 // } 172 // }
181 // } 173 // }
182 174
183 - /// Finds a instance of the required Class<[S]> (or [tag])  
184 - /// In the case of using Get.[create], it will create an instance  
185 - /// each time you call [find]  
186 - /// 175 + /// Finds the registered type <[S]> (or [tag])
  176 + /// In case of using Get.[create] to register a type <[S]> or [tag], it will create an instance
  177 + /// each time you call [find].
  178 + /// If the registered type <[S]> (or [tag]) is a Controller, it will initialize
  179 + /// it's lifecycle.
187 S find<S>({String tag}) { 180 S find<S>({String tag}) {
188 String key = _getKey(S, tag); 181 String key = _getKey(S, tag);
189 -  
190 if (isRegistered<S>(tag: tag)) { 182 if (isRegistered<S>(tag: tag)) {
191 - FcBuilder builder = _singl[key] as FcBuilder; 183 + _FcBuilder builder = _singl[key] as _FcBuilder;
192 if (builder == null) { 184 if (builder == null) {
193 if (tag == null) { 185 if (tag == null) {
194 - throw "class ${S.toString()} is not register"; 186 + throw 'Class "$S" is not register';
195 } else { 187 } else {
196 - throw "class ${S.toString()} with tag '$tag' is not register"; 188 + throw 'Class "$S" with tag "$tag" is not register';
197 } 189 }
198 } 190 }
199 _initDependencies<S>(name: tag); 191 _initDependencies<S>(name: tag);
@@ -201,9 +193,11 @@ class GetInstance { @@ -201,9 +193,11 @@ class GetInstance {
201 return _singl[key].getDependency() as S; 193 return _singl[key].getDependency() as S;
202 } else { 194 } else {
203 if (!_factory.containsKey(key)) 195 if (!_factory.containsKey(key))
204 - throw "$S not found. You need call put<$S>($S()) before"; 196 + throw '"$S" not found. You need to call "Get.put<$S>($S())"';
  197 +
  198 + // TODO: This message is not clear
  199 + GetConfig.log('"$S" instance was created at that time');
205 200
206 - GetConfig.log('$S instance was created at that time');  
207 S _value = put<S>(_factory[key].builder() as S); 201 S _value = put<S>(_factory[key].builder() as S);
208 202
209 _initDependencies<S>(name: tag); 203 _initDependencies<S>(name: tag);
@@ -234,8 +228,6 @@ class GetInstance { @@ -234,8 +228,6 @@ class GetInstance {
234 return true; 228 return true;
235 } 229 }
236 230
237 - static GetQueue queue = GetQueue();  
238 -  
239 // Future<bool> delete<S>({String tag, String key, bool force = false}) async { 231 // Future<bool> delete<S>({String tag, String key, bool force = false}) async {
240 // final s = await queue 232 // final s = await queue
241 // .add<bool>(() async => dele<S>(tag: tag, key: key, force: force)); 233 // .add<bool>(() async => dele<S>(tag: tag, key: key, force: force));
@@ -247,17 +239,16 @@ class GetInstance { @@ -247,17 +239,16 @@ class GetInstance {
247 Future<bool> delete<S>({String tag, String key, bool force = false}) async { 239 Future<bool> delete<S>({String tag, String key, bool force = false}) async {
248 final newKey = key ?? _getKey(S, tag); 240 final newKey = key ?? _getKey(S, tag);
249 241
250 - return queue.add<bool>(() async { 242 + return _queue.add<bool>(() async {
251 if (!_singl.containsKey(newKey)) { 243 if (!_singl.containsKey(newKey)) {
252 -  
253 - GetConfig.log('Instance $newKey already been removed.', isError: true); 244 + GetConfig.log('Instance "$newKey" already removed.', isError: true);
254 return false; 245 return false;
255 } 246 }
256 247
257 - FcBuilder builder = _singl[newKey] as FcBuilder; 248 + _FcBuilder builder = _singl[newKey] as _FcBuilder;
258 if (builder.permanent && !force) { 249 if (builder.permanent && !force) {
259 GetConfig.log( 250 GetConfig.log(
260 - '[$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.', 251 + '"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.',
261 isError: true); 252 isError: true);
262 return false; 253 return false;
263 } 254 }
@@ -268,14 +259,14 @@ class GetInstance { @@ -268,14 +259,14 @@ class GetInstance {
268 } 259 }
269 if (i is DisposableInterface) { 260 if (i is DisposableInterface) {
270 await i.onClose(); 261 await i.onClose();
271 - GetConfig.log('onClose of $newKey called'); 262 + GetConfig.log('"$newKey" onClose() called');
272 } 263 }
273 264
274 _singl.removeWhere((oldKey, value) => (oldKey == newKey)); 265 _singl.removeWhere((oldKey, value) => (oldKey == newKey));
275 if (_singl.containsKey(newKey)) { 266 if (_singl.containsKey(newKey)) {
276 - GetConfig.log('error on remove object $newKey', isError: true); 267 + GetConfig.log('Error removing object "$newKey"', isError: true);
277 } else { 268 } else {
278 - GetConfig.log('$newKey deleted from memory'); 269 + GetConfig.log('"$newKey" deleted from memory');
279 } 270 }
280 // _routesKey?.remove(key); 271 // _routesKey?.remove(key);
281 return true; 272 return true;
@@ -293,23 +284,37 @@ typedef FcBuilderFunc<S> = S Function(); @@ -293,23 +284,37 @@ typedef FcBuilderFunc<S> = S Function();
293 284
294 typedef FcBuilderFuncAsync<S> = Future<S> Function(); 285 typedef FcBuilderFuncAsync<S> = Future<S> Function();
295 286
296 -class FcBuilder<S> { 287 +/// Internal class to register instances with Get.[put]<[S]>().
  288 +class _FcBuilder<S> {
  289 + /// Marks the Builder as a single instance.
  290 + /// For reusing [dependency] instead of [builderFunc]
297 bool isSingleton; 291 bool isSingleton;
298 - FcBuilderFunc builderFunc; 292 +
  293 + /// Stores the actual object instance when [isSingleton]=true.
299 S dependency; 294 S dependency;
  295 +
  296 + /// Generates (and regenerates) the instance when [isSingleton]=false.
  297 + /// Usually used by factory methods
  298 + FcBuilderFunc<S> builderFunc;
  299 +
  300 + /// Flag to persist the instance in memory,
  301 + /// without considering [GetConfig.smartManagement]
300 bool permanent = false; 302 bool permanent = false;
  303 +
301 bool isInit = false; 304 bool isInit = false;
302 305
303 - FcBuilder(this.isSingleton, this.builderFunc, this.permanent, this.isInit); 306 + _FcBuilder(this.isSingleton, this.builderFunc, this.permanent, this.isInit);
304 307
  308 + /// Gets the actual instance by it's [builderFunc] or the persisted instance.
305 S getDependency() { 309 S getDependency() {
306 - if (isSingleton) {  
307 - if (dependency == null) {  
308 - dependency = builderFunc() as S;  
309 - }  
310 - return dependency;  
311 - } else {  
312 - return builderFunc() as S;  
313 - } 310 + return isSingleton ? dependency ??= builderFunc() : builderFunc();
314 } 311 }
315 } 312 }
  313 +
  314 +/// Internal class to register a future instance with [lazyPut],
  315 +/// keeps a reference to the callback to be called.
  316 +class _Lazy {
  317 + bool fenix;
  318 + FcBuilderFunc builder;
  319 + _Lazy(this.builder, this.fenix);
  320 +}
@@ -10,6 +10,7 @@ class GetPageMatch { @@ -10,6 +10,7 @@ class GetPageMatch {
10 10
11 class ParseRouteTree { 11 class ParseRouteTree {
12 final List<ParseRouteTreeNode> _nodes = <ParseRouteTreeNode>[]; 12 final List<ParseRouteTreeNode> _nodes = <ParseRouteTreeNode>[];
  13 +
13 // bool _hasDefaultRoute = false; 14 // bool _hasDefaultRoute = false;
14 15
15 void addRoute(GetPage route) { 16 void addRoute(GetPage route) {
@@ -59,11 +60,14 @@ class ParseRouteTree { @@ -59,11 +60,14 @@ class ParseRouteTree {
59 if (usePath.startsWith("/")) { 60 if (usePath.startsWith("/")) {
60 usePath = path.substring(1); 61 usePath = path.substring(1);
61 } 62 }
62 - List<String> components = usePath.split("/"); 63 +
  64 + // should take off url parameters first..
  65 + final uri = Uri.tryParse(usePath);
  66 +// List<String> components = usePath.split("/");
  67 + List<String> components = uri.pathSegments;
63 if (path == Navigator.defaultRouteName) { 68 if (path == Navigator.defaultRouteName) {
64 components = ["/"]; 69 components = ["/"];
65 } 70 }
66 -  
67 Map<ParseRouteTreeNode, ParseRouteTreeNodeMatch> nodeMatches = 71 Map<ParseRouteTreeNode, ParseRouteTreeNodeMatch> nodeMatches =
68 <ParseRouteTreeNode, ParseRouteTreeNodeMatch>{}; 72 <ParseRouteTreeNode, ParseRouteTreeNodeMatch>{};
69 List<ParseRouteTreeNode> nodesToCheck = _nodes; 73 List<ParseRouteTreeNode> nodesToCheck = _nodes;
@@ -103,6 +107,10 @@ class ParseRouteTree { @@ -103,6 +107,10 @@ class ParseRouteTree {
103 ParseRouteTreeNodeMatch parentMatch = nodeMatches[node.parent]; 107 ParseRouteTreeNodeMatch parentMatch = nodeMatches[node.parent];
104 ParseRouteTreeNodeMatch match = 108 ParseRouteTreeNodeMatch match =
105 ParseRouteTreeNodeMatch.fromMatch(parentMatch, node); 109 ParseRouteTreeNodeMatch.fromMatch(parentMatch, node);
  110 +
  111 + // TODO: find a way to clean this implementation.
  112 + match.parameters.addAll(uri.queryParameters);
  113 +
106 if (node.isParameter()) { 114 if (node.isParameter()) {
107 String paramKey = node.part.substring(1); 115 String paramKey = node.part.substring(1);
108 match.parameters[paramKey] = pathPart; 116 match.parameters[paramKey] = pathPart;
  1 +/// [Bindings] should be extended or implemented.
  2 +/// When using [GetMaterialApp], all [GetPage]s and navigation methods (like Get.to())
  3 +/// have a [binding] property that takes an instance of Bindings to manage the
  4 +/// dependencies() (via [Get.put()]) for the Route you are opening.
1 abstract class Bindings { 5 abstract class Bindings {
2 void dependencies(); 6 void dependencies();
3 } 7 }
4 8
  9 +/// Simplifies Bindings generation from a single callback.
  10 +/// To avoid the creation of a custom Binding instance per route.
  11 +///
  12 +/// Example:
  13 +/// ```
  14 +/// GetPage(
  15 +/// name: '/',
  16 +/// page: () => Home(),
  17 +/// binding: BindingsBuilder(() => Get.put(HomeController())),
  18 +/// ),
  19 +/// ````
  20 +class BindingsBuilder extends Bindings {
  21 + /// Register your dependencies in the [builder] callback.
  22 + final Function() builder;
  23 +
  24 + BindingsBuilder(this.builder);
  25 +
  26 + @override
  27 + void dependencies() {
  28 + builder();
  29 + }
  30 +}
  31 +
5 // abstract class INavigation {} 32 // abstract class INavigation {}
6 // typedef Snack = Function(); 33 // typedef Snack = Function();
7 // typedef Modal = Function(); 34 // typedef Modal = Function();
1 import 'dart:async'; 1 import 'dart:async';
2 import 'dart:collection'; 2 import 'dart:collection';
  3 +
3 import 'rx_interface.dart'; 4 import 'rx_interface.dart';
4 5
  6 +RxInterface getObs;
  7 +
  8 +typedef bool Condition();
  9 +
5 class _RxImpl<T> implements RxInterface<T> { 10 class _RxImpl<T> implements RxInterface<T> {
6 StreamController<T> subject = StreamController<T>.broadcast(); 11 StreamController<T> subject = StreamController<T>.broadcast();
7 HashMap<Stream<T>, StreamSubscription> _subscriptions = 12 HashMap<Stream<T>, StreamSubscription> _subscriptions =
@@ -15,14 +20,26 @@ class _RxImpl<T> implements RxInterface<T> { @@ -15,14 +20,26 @@ class _RxImpl<T> implements RxInterface<T> {
15 return _value; 20 return _value;
16 } 21 }
17 22
18 - bool get canUpdate {  
19 - return _subscriptions.length > 0; 23 + /// Common to all Types [T], this operator overloading is using for
  24 + /// assignment, same as rx.value
  25 + ///
  26 + /// Example:
  27 + /// ```
  28 + /// var counter = 0.obs ;
  29 + /// counter >>= 3; // same as counter.value=3;
  30 + /// print(counter); // calls .toString() now
  31 + /// ```
  32 + ///
  33 + /// WARNING: still WIP, needs testing!
  34 + _RxImpl<T> operator >>(T val) {
  35 + subject.add(value = val);
  36 + return this;
20 } 37 }
21 38
  39 + bool get canUpdate => _subscriptions.isNotEmpty;
  40 +
22 T call([T v]) { 41 T call([T v]) {
23 - if (v != null) {  
24 - this.value = v;  
25 - } 42 + if (v != null) this.value = v;
26 return this.value; 43 return this.value;
27 } 44 }
28 45
@@ -33,15 +50,24 @@ class _RxImpl<T> implements RxInterface<T> { @@ -33,15 +50,24 @@ class _RxImpl<T> implements RxInterface<T> {
33 50
34 String get string => value.toString(); 51 String get string => value.toString();
35 52
36 - close() {  
37 - _subscriptions.forEach((observable, subscription) {  
38 - subscription.cancel();  
39 - }); 53 + @override
  54 + String toString() => value.toString();
  55 +
  56 + /// This equality override works for _RxImpl instances and the internal values.
  57 + bool operator ==(o) {
  58 + // Todo, find a common implementation for the hashCode of different Types.
  59 + if (o is T) return _value == o;
  60 + if (o is _RxImpl<T>) return _value == o.value;
  61 + return false;
  62 + }
  63 +
  64 + void close() {
  65 + _subscriptions.forEach((observable, subscription) => subscription.cancel());
40 _subscriptions.clear(); 66 _subscriptions.clear();
41 subject.close(); 67 subject.close();
42 } 68 }
43 69
44 - addListener(Stream<T> rxGetx) { 70 + void addListener(Stream<T> rxGetx) {
45 if (_subscriptions.containsKey(rxGetx)) { 71 if (_subscriptions.containsKey(rxGetx)) {
46 return; 72 return;
47 } 73 }
@@ -286,6 +312,16 @@ class RxList<E> extends Iterable<E> implements RxInterface<List<E>> { @@ -286,6 +312,16 @@ class RxList<E> extends Iterable<E> implements RxInterface<List<E>> {
286 subject.add(_list); 312 subject.add(_list);
287 } 313 }
288 314
  315 + /// Special override to push() element(s) in a reactive way
  316 + /// inside the List,
  317 + RxList<E> operator +(val) {
  318 + if (val is Iterable)
  319 + subject.add(_list..addAll(val));
  320 + else
  321 + subject.add(_list..add(val));
  322 + return this;
  323 + }
  324 +
289 E operator [](int index) { 325 E operator [](int index) {
290 return value[index]; 326 return value[index];
291 } 327 }
@@ -428,10 +464,6 @@ class RxList<E> extends Iterable<E> implements RxInterface<List<E>> { @@ -428,10 +464,6 @@ class RxList<E> extends Iterable<E> implements RxInterface<List<E>> {
428 List<E> _list = <E>[]; 464 List<E> _list = <E>[];
429 } 465 }
430 466
431 -RxInterface getObs;  
432 -  
433 -typedef bool Condition();  
434 -  
435 class RxBool extends _RxImpl<bool> { 467 class RxBool extends _RxImpl<bool> {
436 RxBool([bool initial]) { 468 RxBool([bool initial]) {
437 _value = initial; 469 _value = initial;
@@ -442,24 +474,109 @@ class RxDouble extends _RxImpl<double> { @@ -442,24 +474,109 @@ class RxDouble extends _RxImpl<double> {
442 RxDouble([double initial]) { 474 RxDouble([double initial]) {
443 _value = initial; 475 _value = initial;
444 } 476 }
  477 +
  478 + RxDouble operator +(double val) {
  479 + subject.add(value += val);
  480 + return this;
  481 + }
  482 +
  483 + RxDouble operator -(double val) {
  484 + subject.add(value -= val);
  485 + return this;
  486 + }
  487 +
  488 + RxDouble operator /(double val) {
  489 + subject.add(value /= val);
  490 + return this;
  491 + }
  492 +
  493 + RxDouble operator *(double val) {
  494 + subject.add(value *= val);
  495 + return this;
  496 + }
445 } 497 }
446 498
447 class RxNum extends _RxImpl<num> { 499 class RxNum extends _RxImpl<num> {
448 RxNum([num initial]) { 500 RxNum([num initial]) {
449 _value = initial; 501 _value = initial;
450 } 502 }
  503 +
  504 + RxNum operator >>(num val) {
  505 + subject.add(value = val);
  506 + return this;
  507 + }
  508 +
  509 + RxNum operator +(num val) {
  510 + subject.add(value += val);
  511 + return this;
  512 + }
  513 +
  514 + RxNum operator -(num val) {
  515 + subject.add(value -= val);
  516 + return this;
  517 + }
  518 +
  519 + RxNum operator /(num val) {
  520 + subject.add(value /= val);
  521 + return this;
  522 + }
  523 +
  524 + RxNum operator *(num val) {
  525 + subject.add(value *= val);
  526 + return this;
  527 + }
451 } 528 }
452 529
453 class RxString extends _RxImpl<String> { 530 class RxString extends _RxImpl<String> {
454 RxString([String initial]) { 531 RxString([String initial]) {
455 _value = initial; 532 _value = initial;
456 } 533 }
  534 +
  535 + RxString operator >>(String val) {
  536 + subject.add(value = val);
  537 + return this;
  538 + }
  539 +
  540 + RxString operator +(String val) {
  541 + subject.add(value += val);
  542 + return this;
  543 + }
  544 +
  545 + RxString operator *(int val) {
  546 + subject.add(value *= val);
  547 + return this;
  548 + }
457 } 549 }
458 550
459 class RxInt extends _RxImpl<int> { 551 class RxInt extends _RxImpl<int> {
460 RxInt([int initial]) { 552 RxInt([int initial]) {
461 _value = initial; 553 _value = initial;
462 } 554 }
  555 +
  556 + RxInt operator >>(int val) {
  557 + subject.add(value = val);
  558 + return this;
  559 + }
  560 +
  561 + RxInt operator +(int val) {
  562 + subject.add(value += val);
  563 + return this;
  564 + }
  565 +
  566 + RxInt operator -(int val) {
  567 + subject.add(value -= val);
  568 + return this;
  569 + }
  570 +
  571 + RxInt operator /(int val) {
  572 + subject.add(value ~/= val);
  573 + return this;
  574 + }
  575 +
  576 + RxInt operator *(int val) {
  577 + subject.add(value *= val);
  578 + return this;
  579 + }
463 } 580 }
464 581
465 class Rx<T> extends _RxImpl<T> { 582 class Rx<T> extends _RxImpl<T> {