@qooxdoo/framework 8.0.0-beta.1 → 8.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/Manifest.json +1 -1
- package/lib/compiler/compile-info.json +54 -55
- package/lib/compiler/index.js +19039 -23607
- package/lib/resource/qx/tool/compiler/cli/templates/class/default.tmpl.js +6 -7
- package/lib/resource/qx/tool/compiler/cli/templates/class/singleton.tmpl.js +5 -6
- package/lib/resource/qx/tool/compiler/schema/compile-1-0-0.json +6 -2
- package/package.json +8 -10
- package/source/class/qx/Class.js +26 -7
- package/source/class/qx/Mixin.js +15 -6
- package/source/class/qx/core/BaseInit.js +14 -13
- package/source/class/qx/core/MObjectId.js +16 -0
- package/source/class/qx/core/MProperty.js +147 -175
- package/source/class/qx/core/check/AbstractCheck.js +5 -1
- package/source/class/qx/core/check/CheckFactory.js +6 -0
- package/source/class/qx/core/check/DynamicTypeCheck.js +9 -0
- package/source/class/qx/core/property/ExplicitPropertyStorage.js +7 -19
- package/source/class/qx/core/property/IPropertyStorage.js +2 -21
- package/source/class/qx/core/property/Property.js +115 -90
- package/source/class/qx/core/property/SimplePropertyStorage.js +2 -18
- package/source/class/qx/data/MBinding.js +1 -1
- package/source/class/qx/data/SingleValueBinding.js +63 -107
- package/source/class/qx/data/binding/AbstractSegment.js +16 -11
- package/source/class/qx/data/binding/ArrayIndexSegment.js +17 -10
- package/source/class/qx/data/binding/IInputReceiver.js +1 -1
- package/source/class/qx/data/binding/PropNameSegment.js +35 -12
- package/source/class/qx/dev/unit/TestCase.js +4 -1
- package/source/class/qx/event/handler/Focus.js +2 -1
- package/source/class/qx/html/Jsx.js +2 -3
- package/source/class/qx/html/Node.js +3 -3
- package/source/class/qx/io/jsonrpc/Client.js +1 -1
- package/source/class/qx/promise/NativeWrapper.js +1 -1
- package/source/class/qx/test/Mixin.js +219 -0
- package/source/class/qx/test/Promise.js +10 -11
- package/source/class/qx/test/core/Property.js +50 -16
- package/source/class/qx/test/data/singlevalue/Async.js +17 -4
- package/source/class/qx/test/data/singlevalue/Simple.js +6 -0
- package/source/class/qx/test/locale/Date.js +2 -2
- package/source/class/qx/test/performance/Property.js +0 -1
- package/source/class/qx/test/ui/core/SingleSelectionManager.js +150 -0
- package/source/class/qx/theme/classic/Appearance.js +21 -0
- package/source/class/qx/theme/modern/Appearance.js +21 -0
- package/source/class/qx/theme/simple/Appearance.js +21 -0
- package/source/class/qx/theme/tangible/Appearance.js +2 -0
- package/source/class/qx/tool/cli/AbstractCliApp.js +18 -2
- package/source/class/qx/tool/compiler/ClassFile.js +0 -4
- package/source/class/qx/tool/compiler/MetaDatabase.js +47 -0
- package/source/class/qx/tool/compiler/cli/api/CompilerApi.js +1 -2
- package/source/class/qx/tool/compiler/cli/commands/Compile.js +139 -8
- package/source/class/qx/tool/compiler/cli/commands/Create.js +1 -1
- package/source/class/qx/tool/compiler/cli/commands/Serve.js +1 -1
- package/source/class/qx/tool/compiler/cli/commands/Typescript.js +26 -39
- package/source/class/qx/tool/compiler/cli/commands/add/Script.js +1 -1
- package/source/class/qx/tool/compiler/cli/commands/package/Publish.js +3 -2
- package/source/class/qx/tool/compiler/cli/commands/package/Update.js +2 -2
- package/source/class/qx/tool/compiler/targets/TypeScriptWriter.js +3 -0
- package/source/class/qx/tool/compiler/targets/meta/Browserify.js +142 -80
- package/source/class/qx/tool/migration/M8_0_0.js +4 -4
- package/source/class/qx/ui/core/SingleSelectionManager.js +4 -4
- package/source/class/qx/ui/form/validation/Manager.js +1 -1
- package/source/class/qx/ui/toolbar/ToolBar.js +4 -4
- package/source/resource/qx/decoration/Modern/table/boolean-false.png +0 -0
- package/source/resource/qx/decoration/Modern/table/boolean-true.png +0 -0
- package/source/resource/qx/tool/compiler/cli/templates/class/default.tmpl.js +6 -7
- package/source/resource/qx/tool/compiler/cli/templates/class/singleton.tmpl.js +5 -6
- package/source/resource/qx/tool/compiler/schema/compile-1-0-0.json +6 -2
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
Authors:
|
|
15
15
|
* John Spackman (https://github.com/johnspackman, john.spackman@zenesis.com)
|
|
16
|
-
* Patryk Malinowski (https://github.com/patryk-m-malinowski,
|
|
16
|
+
* Patryk Malinowski (https://github.com/patryk-m-malinowski, pmalinowski116@gmail.com)
|
|
17
17
|
|
|
18
18
|
************************************************************************ */
|
|
19
19
|
|
|
@@ -97,6 +97,12 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
97
97
|
* be called if the set of the value fails.
|
|
98
98
|
* @property {string} ignoreConverter A string which will be matched using the current
|
|
99
99
|
* property chain. If it matches, the converter will not be called.
|
|
100
|
+
* @property {boolean} async If true, the following will happen:
|
|
101
|
+
* - The binding's init promise (returned by `getInitPromise`) will resolve only after the initial value has been set on the target.
|
|
102
|
+
* If any properties in the source and target chains have async getters,
|
|
103
|
+
* the initial set may happen on a later tick.
|
|
104
|
+
* - The binding will call setAsync on the target value instead of the synchronous `set` and the init promise will resolve after the initial setAsync call has resolved.
|
|
105
|
+
*
|
|
100
106
|
*
|
|
101
107
|
*
|
|
102
108
|
* @callback converter
|
|
@@ -126,6 +132,7 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
126
132
|
throw new Error("SourcePath and targetPath must be specified");
|
|
127
133
|
}
|
|
128
134
|
this.__options = options ?? {};
|
|
135
|
+
this.__async = !!this.__options.async;
|
|
129
136
|
let tracker = {};
|
|
130
137
|
|
|
131
138
|
const Utils = qx.event.Utils;
|
|
@@ -169,10 +176,14 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
169
176
|
},
|
|
170
177
|
|
|
171
178
|
members: {
|
|
179
|
+
/**
|
|
180
|
+
* Whether this binding is asynchronous
|
|
181
|
+
*/
|
|
182
|
+
__async: false,
|
|
172
183
|
/**
|
|
173
184
|
* @type {*}
|
|
174
185
|
*/
|
|
175
|
-
__value:
|
|
186
|
+
__value: undefined,
|
|
176
187
|
/**
|
|
177
188
|
* @type {qx.core.Object}
|
|
178
189
|
*/
|
|
@@ -202,6 +213,14 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
202
213
|
*/
|
|
203
214
|
__options: null,
|
|
204
215
|
|
|
216
|
+
/**
|
|
217
|
+
*
|
|
218
|
+
* @returns {boolean}
|
|
219
|
+
*/
|
|
220
|
+
isAsync() {
|
|
221
|
+
return this.__async;
|
|
222
|
+
},
|
|
223
|
+
|
|
205
224
|
/**
|
|
206
225
|
* Promises/A+ thenable compliance, this means that you can await the binding for initialisation
|
|
207
226
|
* https://promisesaplus.com/
|
|
@@ -284,7 +303,7 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
284
303
|
SingleValueBinding.__bindingsBySource[value.toHashCode()][this.toHashCode()] = this;
|
|
285
304
|
|
|
286
305
|
//Set the input on the first segment of the source path
|
|
287
|
-
let
|
|
306
|
+
let out = this.__sourceSegments[0].setInput(value);
|
|
288
307
|
const cb = () => {
|
|
289
308
|
if (qx.core.Environment.get("qx.debug")) {
|
|
290
309
|
this.assertNotNull(
|
|
@@ -294,10 +313,8 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
294
313
|
}
|
|
295
314
|
};
|
|
296
315
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (qx.Promise.isPromise(promise)) {
|
|
300
|
-
out = promise.then(cb);
|
|
316
|
+
if (qx.Promise.isPromise(out)) {
|
|
317
|
+
out = out.then(cb);
|
|
301
318
|
} else {
|
|
302
319
|
out = cb();
|
|
303
320
|
}
|
|
@@ -322,7 +339,7 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
322
339
|
}
|
|
323
340
|
this.__record = null; // invalidate record representation cache
|
|
324
341
|
this.__targetSegments = qx.data.SingleValueBinding.__parseSegments(this, value);
|
|
325
|
-
this.__targetSegments.at(-1).
|
|
342
|
+
this.__targetSegments.at(-1).setChangeInputCallback(() => this.__updateTarget());
|
|
326
343
|
},
|
|
327
344
|
|
|
328
345
|
/**
|
|
@@ -579,27 +596,6 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
579
596
|
return out;
|
|
580
597
|
},
|
|
581
598
|
|
|
582
|
-
/**
|
|
583
|
-
* Splits a property path into segments.
|
|
584
|
-
* @param {string} path
|
|
585
|
-
* @returns {string[]} an array of segments, split by dot and square brackets.
|
|
586
|
-
* For example, splitSegments(`a.b[0].c`) will return `["a", "b", "[0]", "c"]`
|
|
587
|
-
*/
|
|
588
|
-
splitSegments(path) {
|
|
589
|
-
let out = [];
|
|
590
|
-
for (let dotSplit of path.split(".")) {
|
|
591
|
-
let bracketSplits = dotSplit.split("[");
|
|
592
|
-
for (let i = 0; i < bracketSplits.length; i++) {
|
|
593
|
-
let bracketSplit = bracketSplits[i];
|
|
594
|
-
if (i > 0) {
|
|
595
|
-
bracketSplit = "[" + bracketSplit;
|
|
596
|
-
}
|
|
597
|
-
out.push(bracketSplit);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
return out.filter(s => s.length > 0);
|
|
601
|
-
},
|
|
602
|
-
|
|
603
599
|
/**
|
|
604
600
|
* Finds all bindings for an object, as either a source or target
|
|
605
601
|
*
|
|
@@ -675,72 +671,6 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
675
671
|
}
|
|
676
672
|
},
|
|
677
673
|
|
|
678
|
-
/**
|
|
679
|
-
* Helper method that sets a value for a named property
|
|
680
|
-
*
|
|
681
|
-
* @param {qx.core.Object} target object to have a property set
|
|
682
|
-
* @param {String} propertyName the name of the property
|
|
683
|
-
* @param {Object?} value the value to set
|
|
684
|
-
*/
|
|
685
|
-
set(target, propertyName, value) {
|
|
686
|
-
let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
|
|
687
|
-
if (!prop) {
|
|
688
|
-
let setFuncName = "set" + qx.lang.String.firstUp(propertyName);
|
|
689
|
-
if (typeof target[setFuncName] == "function") {
|
|
690
|
-
return target[setFuncName](value);
|
|
691
|
-
} else {
|
|
692
|
-
throw new Error(`Property ${propertyName} not found on ${target.classname}`);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
if (prop.isAsync()) {
|
|
697
|
-
return prop.setAsync(target, value);
|
|
698
|
-
} else {
|
|
699
|
-
return prop.set(target, value);
|
|
700
|
-
}
|
|
701
|
-
},
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Helper method to get a value of a named property
|
|
705
|
-
*
|
|
706
|
-
* @param {qx.core.Object} target object to have a property get
|
|
707
|
-
* @param {String} propertyName the name of the property
|
|
708
|
-
* @returns {Object?} the property value
|
|
709
|
-
*/
|
|
710
|
-
get(target, propertyName) {
|
|
711
|
-
let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
|
|
712
|
-
if (prop.isAsync()) {
|
|
713
|
-
return prop.getAsync(target);
|
|
714
|
-
} else {
|
|
715
|
-
return prop.get(target);
|
|
716
|
-
}
|
|
717
|
-
},
|
|
718
|
-
|
|
719
|
-
/**
|
|
720
|
-
* Helper method that resets a named property
|
|
721
|
-
*
|
|
722
|
-
* @param {qx.core.Object} target object to have a property set
|
|
723
|
-
* @param {String} propertyName the name of the property
|
|
724
|
-
|
|
725
|
-
*/
|
|
726
|
-
reset(target, propertyName) {
|
|
727
|
-
let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
|
|
728
|
-
if (!prop) {
|
|
729
|
-
let setFuncName = "reset" + qx.lang.String.firstUp(propertyName);
|
|
730
|
-
if (typeof target[setFuncName] == "function") {
|
|
731
|
-
return target[setFuncName]();
|
|
732
|
-
} else {
|
|
733
|
-
throw new Error(`Property ${propertyName} not found on ${target.classname}`);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
if (prop.isAsync()) {
|
|
738
|
-
return prop.resetAsync(target);
|
|
739
|
-
} else {
|
|
740
|
-
return prop.reset(target);
|
|
741
|
-
}
|
|
742
|
-
},
|
|
743
|
-
|
|
744
674
|
/**
|
|
745
675
|
*
|
|
746
676
|
* Internal helper for getting the current set value at the property chain.
|
|
@@ -785,26 +715,52 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
785
715
|
* @return {qx.data.binding.AbstractSegment[]?} the new array of segments
|
|
786
716
|
*/
|
|
787
717
|
__parseSegments(binding, path) {
|
|
788
|
-
let segsStrings =
|
|
718
|
+
let segsStrings = this.__splitSegments(path);
|
|
719
|
+
//should be let segsStrings = path.split(/\.|(?=\[)|(?<=\])/g);// split by dot or square brackets, but keep the brackets as part of the segments
|
|
720
|
+
//but this breaks our Rhino because it's really old
|
|
721
|
+
//TODO update Rhino
|
|
722
|
+
|
|
789
723
|
let segments = [];
|
|
790
724
|
|
|
791
|
-
|
|
725
|
+
let previous;
|
|
726
|
+
for (let segStr of segsStrings) {
|
|
727
|
+
let seg;
|
|
792
728
|
//if it's an array index:
|
|
793
|
-
if (
|
|
794
|
-
|
|
729
|
+
if (segStr.startsWith("[")) {
|
|
730
|
+
seg = new qx.data.binding.ArrayIndexSegment(binding, segStr);
|
|
795
731
|
} else {
|
|
796
732
|
//otherwise, it's a normal path
|
|
797
|
-
|
|
733
|
+
seg = new qx.data.binding.PropNameSegment(binding, segStr);
|
|
798
734
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
segments.forEach((seg, index) => {
|
|
802
|
-
if (index < segments.length - 1) {
|
|
803
|
-
seg.setOutputReceiver(segments[index + 1]);
|
|
735
|
+
if (previous) {
|
|
736
|
+
previous.setOutputReceiver(seg);
|
|
804
737
|
}
|
|
805
|
-
|
|
738
|
+
previous = seg;
|
|
739
|
+
segments.push(seg);
|
|
740
|
+
}
|
|
806
741
|
|
|
807
742
|
return segments;
|
|
808
|
-
}
|
|
743
|
+
},
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Splits a property path into segments.
|
|
747
|
+
* @param {string} path
|
|
748
|
+
* @returns {string[]} an array of segments, split by dot and square brackets.
|
|
749
|
+
* For example, splitSegments(`a.b[0].c`) will return `["a", "b", "[0]", "c"]`
|
|
750
|
+
*/
|
|
751
|
+
__splitSegments(path) {
|
|
752
|
+
let out = [];
|
|
753
|
+
for (let dotSplit of path.split(".")) {
|
|
754
|
+
let bracketSplits = dotSplit.split("[");
|
|
755
|
+
for (let i = 0; i < bracketSplits.length; i++) {
|
|
756
|
+
let bracketSplit = bracketSplits[i];
|
|
757
|
+
if (i > 0) {
|
|
758
|
+
bracketSplit = "[" + bracketSplit;
|
|
759
|
+
}
|
|
760
|
+
out.push(bracketSplit);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return out.filter(s => s.length > 0);
|
|
764
|
+
},
|
|
809
765
|
}
|
|
810
766
|
});
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
See the LICENSE file in the project's top-level directory for details.
|
|
13
13
|
|
|
14
14
|
Authors:
|
|
15
|
-
|
|
15
|
+
* Patryk Malinowski (https://github.com/patryk-m-malinowski, pmalinowski116@gmail.com)
|
|
16
16
|
|
|
17
17
|
************************************************************************ */
|
|
18
18
|
|
|
@@ -47,15 +47,12 @@ qx.Class.define("qx.data.binding.AbstractSegment", {
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
|
|
50
|
-
/**
|
|
51
|
-
* Fired when this segment's input changed, and it has been received and fully processed by the next segments in the chain,
|
|
52
|
-
* i.e. any async set/get operations have completed.
|
|
53
|
-
*/
|
|
54
|
-
events: {
|
|
55
|
-
changeInput: "qx.event.type.Data"
|
|
56
|
-
},
|
|
57
|
-
|
|
58
50
|
members: {
|
|
51
|
+
/**
|
|
52
|
+
* Called when this segment's input changed, and it has been received and fully processed by the next segments in the chain,
|
|
53
|
+
* i.e. any async set/get operations have completed.
|
|
54
|
+
*/
|
|
55
|
+
__changeInputCallback: () => {},
|
|
59
56
|
/**
|
|
60
57
|
* @type {qx.data.SingleValueBinding}
|
|
61
58
|
*/
|
|
@@ -70,6 +67,14 @@ qx.Class.define("qx.data.binding.AbstractSegment", {
|
|
|
70
67
|
*/
|
|
71
68
|
__outputReceiver: null,
|
|
72
69
|
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
* @param {Function} callback
|
|
73
|
+
*/
|
|
74
|
+
setChangeInputCallback(callback) {
|
|
75
|
+
this.__changeInputCallback = callback;
|
|
76
|
+
},
|
|
77
|
+
|
|
73
78
|
/**
|
|
74
79
|
*
|
|
75
80
|
* @returns {qx.data.SingleValueBinding} the binding that this segment belongs to. Useful for debugging purposes.
|
|
@@ -125,9 +130,9 @@ qx.Class.define("qx.data.binding.AbstractSegment", {
|
|
|
125
130
|
|
|
126
131
|
let out = this._applyInput(value, old);
|
|
127
132
|
if (qx.lang.Type.isPromise(out)) {
|
|
128
|
-
return out.then(() => this.
|
|
133
|
+
return out.then(() => this.__changeInputCallback(value, old));
|
|
129
134
|
} else {
|
|
130
|
-
return this.
|
|
135
|
+
return this.__changeInputCallback(value, old);
|
|
131
136
|
}
|
|
132
137
|
},
|
|
133
138
|
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
See the LICENSE file in the project's top-level directory for details.
|
|
13
13
|
|
|
14
14
|
Authors:
|
|
15
|
-
|
|
15
|
+
* Patryk Malinowski (https://github.com/patryk-m-malinowski, pmalinowski116@gmail.com)
|
|
16
16
|
|
|
17
17
|
************************************************************************ */
|
|
18
18
|
|
|
@@ -51,7 +51,7 @@ qx.Class.define("qx.data.binding.ArrayIndexSegment", {
|
|
|
51
51
|
destruct() {
|
|
52
52
|
let input = this.getInput();
|
|
53
53
|
if (input) {
|
|
54
|
-
if (this.getInput()
|
|
54
|
+
if (this.__isListData(this.getInput())) {
|
|
55
55
|
this.getInput().removeListener("change", this.__onChangeContents, this);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -71,19 +71,23 @@ qx.Class.define("qx.data.binding.ArrayIndexSegment", {
|
|
|
71
71
|
return this.__string;
|
|
72
72
|
},
|
|
73
73
|
|
|
74
|
+
__isListData(input) {
|
|
75
|
+
return qx.Interface.objectImplements(input, qx.data.IListData);
|
|
76
|
+
},
|
|
77
|
+
|
|
74
78
|
/**
|
|
75
79
|
* @override
|
|
76
80
|
*/
|
|
77
81
|
_applyInput(value, oldValue) {
|
|
78
82
|
if (oldValue) {
|
|
79
83
|
this.setEventName(null);
|
|
80
|
-
if (oldValue
|
|
84
|
+
if (this.__isListData(oldValue)) {
|
|
81
85
|
oldValue.removeListener("change", this.__onChangeContents, this);
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
if (value) {
|
|
86
|
-
if (value
|
|
90
|
+
if (this.__isListData(value)) {
|
|
87
91
|
value.addListener("change", this.__onChangeContents, this);
|
|
88
92
|
this.setEventName("change");
|
|
89
93
|
}
|
|
@@ -108,8 +112,10 @@ qx.Class.define("qx.data.binding.ArrayIndexSegment", {
|
|
|
108
112
|
return undefined;
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
if (input
|
|
112
|
-
|
|
115
|
+
if (this.__isListData(input)) {
|
|
116
|
+
const len = input.getLength();
|
|
117
|
+
const idx = this.__index === -1 ? len - 1 : this.__index;
|
|
118
|
+
return idx >= len ? undefined : input.getItem(idx);
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
if (this.__index >= input.length) {
|
|
@@ -126,11 +132,12 @@ qx.Class.define("qx.data.binding.ArrayIndexSegment", {
|
|
|
126
132
|
if (!input) {
|
|
127
133
|
return;
|
|
128
134
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
input.setItem(
|
|
135
|
+
if (this.__isListData(input)) {
|
|
136
|
+
const idx = this.__index === -1 ? input.getLength() - 1 : this.__index;
|
|
137
|
+
input.setItem(idx, targetValue);
|
|
132
138
|
} else {
|
|
133
|
-
|
|
139
|
+
const idx = this.__index === -1 ? input.length - 1 : this.__index;
|
|
140
|
+
input[idx] = targetValue;
|
|
134
141
|
}
|
|
135
142
|
},
|
|
136
143
|
|
|
@@ -7,7 +7,7 @@ qx.Interface.define("qx.data.binding.IInputReceiver", {
|
|
|
7
7
|
*
|
|
8
8
|
* @param {*} value
|
|
9
9
|
* @returns {Promise?} If the operation is asynchronous, it should return a Promise which resolves when it has completed.
|
|
10
|
-
* If it's
|
|
10
|
+
* If it's synchronous, it should return null.
|
|
11
11
|
*/
|
|
12
12
|
setInput(input) {}
|
|
13
13
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
See the LICENSE file in the project's top-level directory for details.
|
|
13
13
|
|
|
14
14
|
Authors:
|
|
15
|
-
*
|
|
15
|
+
* Patryk Malinowski (https://github.com/patryk-m-malinowski, pmalinowski116@gmail.com)
|
|
16
16
|
|
|
17
17
|
************************************************************************ */
|
|
18
18
|
|
|
@@ -69,6 +69,10 @@ qx.Class.define("qx.data.binding.PropNameSegment", {
|
|
|
69
69
|
* Apply for `input`
|
|
70
70
|
*/
|
|
71
71
|
_applyInput(value, oldValue) {
|
|
72
|
+
if (!this.getOutputReceiver()) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
72
76
|
if (oldValue) {
|
|
73
77
|
let eventName = this.__getEventName(oldValue);
|
|
74
78
|
eventName && oldValue.removeListener(eventName, this.__onChangeInputProperty, this);
|
|
@@ -81,9 +85,7 @@ qx.Class.define("qx.data.binding.PropNameSegment", {
|
|
|
81
85
|
this.setEventName(eventName);
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
return this.updateOutput();
|
|
86
|
-
}
|
|
88
|
+
return this.updateOutput();
|
|
87
89
|
},
|
|
88
90
|
|
|
89
91
|
updateOutput() {
|
|
@@ -95,10 +97,15 @@ qx.Class.define("qx.data.binding.PropNameSegment", {
|
|
|
95
97
|
if (property === null) {
|
|
96
98
|
return this._setOutput(null);
|
|
97
99
|
}
|
|
98
|
-
if (!property.
|
|
99
|
-
let nextInput = property.get(input
|
|
100
|
+
if (!property.supportsGetAsync() || property.hasLocalValue(input)) {
|
|
101
|
+
let nextInput = property.get(input);
|
|
100
102
|
return this._setOutput(nextInput);
|
|
101
103
|
} else {
|
|
104
|
+
if (qx.core.Environment.get("qx.debug")) {
|
|
105
|
+
if (!(this.getBinding()?.isAsync())) {
|
|
106
|
+
this.warn(`In binding ${this}, property "${this.__propName}" wasn't available synchronously but the binding is not async. This will cause the target to be updated in a later tick. If you want to await the initial set, use 'object.bindAsync' or add 'async: true' in the binding options.`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
102
109
|
let promise = property.getAsync(input);
|
|
103
110
|
return promise.then(nextInput => this._setOutput(nextInput));
|
|
104
111
|
}
|
|
@@ -109,13 +116,31 @@ qx.Class.define("qx.data.binding.PropNameSegment", {
|
|
|
109
116
|
* @override
|
|
110
117
|
*/
|
|
111
118
|
setTargetValue(targetValue) {
|
|
112
|
-
|
|
119
|
+
let input = this.getInput();
|
|
120
|
+
if (input == null || input === undefined) {
|
|
113
121
|
return;
|
|
114
122
|
}
|
|
123
|
+
|
|
124
|
+
let async = this.getBinding()?.isAsync();
|
|
125
|
+
|
|
126
|
+
//get the setter method name
|
|
127
|
+
let upname = qx.lang.String.firstUp(this.__propName);
|
|
128
|
+
|
|
129
|
+
let method;
|
|
115
130
|
if (targetValue !== undefined) {
|
|
116
|
-
|
|
131
|
+
if (async) {
|
|
132
|
+
method = `set${upname}Async`;
|
|
133
|
+
} else {
|
|
134
|
+
method = `set${upname}`;
|
|
135
|
+
}
|
|
136
|
+
return input[method](targetValue);
|
|
117
137
|
} else {
|
|
118
|
-
|
|
138
|
+
if (async) {
|
|
139
|
+
method = `reset${upname}Async`;
|
|
140
|
+
} else {
|
|
141
|
+
method = `reset${upname}`;
|
|
142
|
+
}
|
|
143
|
+
return input[method]();
|
|
119
144
|
}
|
|
120
145
|
},
|
|
121
146
|
|
|
@@ -125,9 +150,7 @@ qx.Class.define("qx.data.binding.PropNameSegment", {
|
|
|
125
150
|
* @param {qx.event.type.Data} evt
|
|
126
151
|
*/
|
|
127
152
|
__onChangeInputProperty(evt) {
|
|
128
|
-
|
|
129
|
-
return this._setOutput(evt.getData());
|
|
130
|
-
}
|
|
153
|
+
return this._setOutput(evt.getData());
|
|
131
154
|
},
|
|
132
155
|
|
|
133
156
|
/**
|
|
@@ -201,7 +201,10 @@ qx.Class.define("qx.dev.unit.TestCase", {
|
|
|
201
201
|
if (this.__autoDispose) {
|
|
202
202
|
this.__autoDispose.forEach(function (obj) {
|
|
203
203
|
if (!obj.isDisposed()) {
|
|
204
|
-
|
|
204
|
+
// Do not make an actual reference to qx.ui.core.Widget otherwise the compiler will load
|
|
205
|
+
// dependencies and that prevents this class from being used in node-only builds
|
|
206
|
+
const Widget = qx.Class.getByName("qx.ui.core.Widget");
|
|
207
|
+
if (obj instanceof Widget) {
|
|
205
208
|
obj.destroy();
|
|
206
209
|
} else if (obj instanceof qx.core.Object) {
|
|
207
210
|
obj.dispose();
|
|
@@ -1344,8 +1344,9 @@ qx.Class.define("qx.event.handler.Focus", {
|
|
|
1344
1344
|
return focusedElement;
|
|
1345
1345
|
}
|
|
1346
1346
|
if (qx.Class.isClass("qx.ui.core.Widget")) {
|
|
1347
|
+
const Widget = qx.Class.getByName("qx.ui.core.Widget");
|
|
1347
1348
|
// Check compound widgets
|
|
1348
|
-
var widget =
|
|
1349
|
+
var widget = Widget.getWidgetByElement(focusedElement),
|
|
1349
1350
|
textField =
|
|
1350
1351
|
widget &&
|
|
1351
1352
|
widget.getChildControl &&
|
|
@@ -48,11 +48,10 @@ qx.Class.define("qx.html.Jsx", {
|
|
|
48
48
|
*
|
|
49
49
|
* @param tagname {String|Function} the name of the tag
|
|
50
50
|
* @param attributes {Record<string, any>} map of attribute values
|
|
51
|
-
* @param children {qx.html.Node
|
|
51
|
+
* @param children {...qx.html.Node} children
|
|
52
52
|
* @return {qx.html.Element|qx.data.Array}
|
|
53
53
|
*/
|
|
54
|
-
createElement(tagname, attributes) {
|
|
55
|
-
const children = qx.lang.Array.fromArguments(arguments, 2);
|
|
54
|
+
createElement(tagname, attributes, ...children) {
|
|
56
55
|
attributes ??= {};
|
|
57
56
|
|
|
58
57
|
// CSS CUSTOM PROPERTIES
|
|
@@ -889,10 +889,10 @@ qx.Class.define("qx.html.Node", {
|
|
|
889
889
|
/**
|
|
890
890
|
* Append all given children at the end of this element.
|
|
891
891
|
*
|
|
892
|
-
* @param
|
|
892
|
+
* @param {...qx.html.Element} children elements to insert
|
|
893
893
|
* @return {qx.html.Element} this object (for chaining support)
|
|
894
894
|
*/
|
|
895
|
-
add(
|
|
895
|
+
add(...children) {
|
|
896
896
|
var self = this;
|
|
897
897
|
function addImpl(arr) {
|
|
898
898
|
arr.forEach(function (child) {
|
|
@@ -917,7 +917,7 @@ qx.Class.define("qx.html.Node", {
|
|
|
917
917
|
self._children.push(child);
|
|
918
918
|
});
|
|
919
919
|
}
|
|
920
|
-
addImpl(
|
|
920
|
+
addImpl(children);
|
|
921
921
|
|
|
922
922
|
// Chaining support
|
|
923
923
|
return this;
|
|
@@ -406,6 +406,6 @@ qx.Class.define("qx.io.jsonrpc.Client", {
|
|
|
406
406
|
* @deprecated
|
|
407
407
|
* Behavior in v8 will be as if the environment variable value is `true`, but the environment variable will no longer be available.
|
|
408
408
|
*/
|
|
409
|
-
"qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest":
|
|
409
|
+
"qx.io.jsonrpc.forwardTransportPromiseRejectionToRequest": true
|
|
410
410
|
}
|
|
411
411
|
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
Authors:
|
|
15
15
|
* John Spackman (john.spackman@zenesis.com)
|
|
16
|
-
* Patryk Malinowski (
|
|
16
|
+
* Patryk Malinowski (https://github.com/patryk-m-malinowski, pmalinowski116@gmail.com)
|
|
17
17
|
|
|
18
18
|
************************************************************************ */
|
|
19
19
|
|