@qooxdoo/framework 7.9.2 → 8.0.0-beta.2
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 +224 -33
- package/Manifest.json +3 -3
- package/bin/tools/utils.js +50 -13
- package/lib/compiler/compile-info.json +297 -227
- package/lib/compiler/index.js +55319 -47085
- package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/default.tmpl.js +6 -7
- package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/cli/templates/class/singleton.tmpl.js +5 -6
- package/lib/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-node.tmpl.js +1 -0
- package/lib/resource/qx/tool/compiler/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css.map +1 -0
- package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/cli/templates/template_vars.js +12 -9
- package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/schema/Manifest-1-0-0.json +2 -2
- package/lib/resource/qx/tool/{schema → compiler/schema}/Manifest-2-0-0.json +2 -2
- package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/schema/compile-1-0-0.json +21 -5
- package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/schema/qooxdoo-1-0-0.json +1 -1
- package/lib/resource/qx/tool/website/build/404.html +22 -22
- package/lib/resource/qx/tool/website/build/about.html +23 -23
- package/lib/resource/qx/tool/website/build/assets/common.js +30 -18
- package/lib/resource/qx/tool/website/build/assets/custom.css +290 -0
- package/lib/resource/qx/tool/website/build/assets/qxWeb.js +28 -0
- package/lib/resource/qx/tool/website/build/diagnostics/dependson.html +30 -30
- package/lib/resource/qx/tool/website/build/diagnostics/dependson.js +49 -40
- package/lib/resource/qx/tool/website/build/diagnostics/requiredby.html +20 -23
- package/lib/resource/qx/tool/website/build/diagnostics/requiredby.js +38 -31
- package/lib/resource/qx/tool/website/build/index.html +24 -24
- package/lib/resource/qx/tool/website/build/scripts/serve.js +63 -65
- package/lib/resource/qx/tool/website/partials/footer.html +8 -13
- package/lib/resource/qx/tool/website/partials/head.html +9 -7
- package/lib/resource/qx/tool/website/partials/header.html +3 -3
- package/lib/resource/qx/tool/website/src/assets/common.js +32 -0
- package/lib/resource/qx/tool/website/src/assets/custom.css +290 -0
- package/lib/resource/qx/tool/website/src/assets/qxWeb.js +28 -0
- package/lib/resource/qx/tool/website/src/diagnostics/dependson.js +49 -40
- package/lib/resource/qx/tool/website/src/diagnostics/requiredby.js +38 -31
- package/lib/resource/qx/tool/website/src/index.html +2 -2
- package/lib/resource/qx/tool/website/src/scripts/serve.js +63 -65
- package/package.json +23 -24
- package/source/boot/index.html +2 -2
- package/source/class/qx/Bootstrap.js +931 -705
- package/source/class/qx/Class.js +1476 -1451
- package/source/class/qx/Interface.js +40 -107
- package/source/class/qx/Mixin.js +58 -116
- package/source/class/qx/Promise.js +1 -0
- package/source/class/qx/Theme.js +1 -1
- package/source/class/qx/application/Routing.js +2 -0
- package/source/class/qx/bom/Font.js +3 -0
- package/source/class/qx/bom/client/Locale.js +5 -0
- package/source/class/qx/bom/request/Jsonp.js +5 -13
- package/source/class/qx/bom/request/Script.js +11 -35
- package/source/class/qx/bom/request/SimpleXhr.js +13 -41
- package/source/class/qx/bom/request/Xhr.js +19 -80
- package/source/class/qx/bom/storage/Memory.js +2 -0
- package/source/class/qx/bom/storage/UserData.js +2 -0
- package/source/class/qx/bom/storage/Web.js +2 -0
- package/source/class/qx/bom/webfonts/Validator.js +13 -5
- package/source/class/qx/core/Assert.js +14 -0
- package/source/class/qx/core/BaseInit.js +19 -19
- package/source/class/qx/core/Environment.js +23 -20
- package/source/class/qx/core/MEvent.js +1 -1
- package/source/class/qx/core/MObjectId.js +24 -6
- package/source/class/qx/core/MProperty.js +123 -115
- package/source/class/qx/core/Object.js +88 -102
- package/source/class/qx/core/check/AbstractCheck.js +111 -0
- package/source/class/qx/core/check/Any.js +63 -0
- package/source/class/qx/core/check/CheckFactory.js +151 -0
- package/source/class/qx/core/check/DynamicTypeCheck.js +94 -0
- package/source/class/qx/core/check/ICheck.js +75 -0
- package/source/class/qx/core/check/IsOneOfCheck.js +63 -0
- package/source/class/qx/core/check/JsDocCheck.js +71 -0
- package/source/class/qx/core/check/SimpleCheck.js +42 -0
- package/source/class/qx/core/check/standard/ArrayCheck.js +49 -0
- package/source/class/qx/core/check/standard/BooleanCheck.js +47 -0
- package/source/class/qx/core/check/standard/ClassCheck.js +33 -0
- package/source/class/qx/core/check/standard/ColorCheck.js +33 -0
- package/source/class/qx/core/check/standard/DateCheck.js +49 -0
- package/source/class/qx/core/check/standard/DecoratorCheck.js +33 -0
- package/source/class/qx/core/check/standard/DocumentCheck.js +40 -0
- package/source/class/qx/core/check/standard/ElementCheck.js +40 -0
- package/source/class/qx/core/check/standard/ErrorCheck.js +46 -0
- package/source/class/qx/core/check/standard/EventCheck.js +40 -0
- package/source/class/qx/core/check/standard/FontCheck.js +33 -0
- package/source/class/qx/core/check/standard/FunctionCheck.js +49 -0
- package/source/class/qx/core/check/standard/IntegerCheck.js +54 -0
- package/source/class/qx/core/check/standard/InterfaceCheck.js +33 -0
- package/source/class/qx/core/check/standard/MapCheck.js +33 -0
- package/source/class/qx/core/check/standard/MixinCheck.js +33 -0
- package/source/class/qx/core/check/standard/NodeCheck.js +40 -0
- package/source/class/qx/core/check/standard/NumberCheck.js +48 -0
- package/source/class/qx/core/check/standard/ObjectCheck.js +33 -0
- package/source/class/qx/core/check/standard/PositiveIntegerCheck.js +45 -0
- package/source/class/qx/core/check/standard/PositiveNumberCheck.js +45 -0
- package/source/class/qx/core/check/standard/PromiseCheck.js +33 -0
- package/source/class/qx/core/check/standard/RegExpCheck.js +46 -0
- package/source/class/qx/core/check/standard/StringCheck.js +43 -0
- package/source/class/qx/core/check/standard/ThemeCheck.js +33 -0
- package/source/class/qx/core/check/standard/WindowCheck.js +40 -0
- package/source/class/qx/core/property/ExplicitPropertyStorage.js +87 -0
- package/source/class/qx/core/property/GroupProperty.js +262 -0
- package/source/class/qx/core/property/IProperty.js +46 -0
- package/source/class/qx/core/property/IPropertyStorage.js +83 -0
- package/source/class/qx/core/property/ImmutableArrayStorage.js +38 -0
- package/source/class/qx/core/property/ImmutableDataArrayStorage.js +38 -0
- package/source/class/qx/core/property/ImmutableObjectStorage.js +39 -0
- package/source/class/qx/core/property/Property.js +1482 -0
- package/source/class/qx/core/property/PropertyStorageFactory.js +22 -0
- package/source/class/qx/core/property/SimplePropertyStorage.js +105 -0
- package/source/class/qx/data/Array.js +102 -57
- package/source/class/qx/data/MBinding.js +4 -29
- package/source/class/qx/data/SingleValueBinding.js +595 -1496
- package/source/class/qx/data/binding/AbstractSegment.js +197 -0
- package/source/class/qx/data/binding/ArrayIndexSegment.js +155 -0
- package/source/class/qx/data/binding/IInputReceiver.js +14 -0
- package/source/class/qx/data/binding/PropNameSegment.js +150 -0
- package/source/class/qx/data/controller/CheckedList.js +1 -1
- package/source/class/qx/data/controller/Form.js +78 -8
- package/source/class/qx/data/controller/Tree.js +27 -117
- package/source/class/qx/data/marshal/Json.js +46 -149
- package/source/class/qx/data/store/Json.js +0 -2
- package/source/class/qx/dev/Debug.js +1 -1
- package/source/class/qx/dev/LeakDetector.js +144 -0
- package/source/class/qx/dev/unit/AsyncWrapper.js +1 -0
- package/source/class/qx/dev/unit/MMock.js +7 -2
- package/source/class/qx/dev/unit/Sinon.js +0 -4
- package/source/class/qx/dev/unit/TestCase.js +4 -1
- package/source/class/qx/dev/unit/TestClass.js +2 -2
- package/source/class/qx/dev/unit/TestFunction.js +1 -0
- package/source/class/qx/dev/unit/TestLoaderBasic.js +1 -0
- package/source/class/qx/dev/unit/TestRunner.js +106 -0
- package/source/class/qx/event/IEventDispatcher.js +8 -4
- package/source/class/qx/event/Manager.js +4 -0
- package/source/class/qx/event/Messaging.js +2 -0
- package/source/class/qx/event/Pool.js +7 -0
- package/source/class/qx/event/Registration.js +33 -55
- package/source/class/qx/event/Timer.js +2 -0
- package/source/class/qx/event/Utils.js +25 -8
- package/source/class/qx/event/dispatch/AbstractBubbling.js +98 -194
- package/source/class/qx/event/dispatch/Direct.js +18 -13
- package/source/class/qx/event/handler/Appear.js +20 -24
- package/source/class/qx/event/handler/Application.js +4 -0
- package/source/class/qx/event/handler/DragDrop.js +182 -385
- package/source/class/qx/event/handler/Element.js +3 -0
- package/source/class/qx/event/handler/Focus.js +38 -31
- package/source/class/qx/event/handler/Input.js +5 -0
- package/source/class/qx/event/handler/Keyboard.js +107 -165
- package/source/class/qx/event/handler/Pointer.js +39 -68
- package/source/class/qx/event/handler/PointerCore.js +7 -25
- package/source/class/qx/event/handler/Window.js +5 -0
- package/source/class/qx/event/type/Event.js +12 -0
- package/source/class/qx/event/type/KeySequence.js +3 -0
- package/source/class/qx/event/type/Native.js +3 -0
- package/source/class/qx/html/Element.js +26 -91
- 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 +2 -2
- package/source/class/qx/io/jsonrpc/protocol/Error.js +2 -2
- package/source/class/qx/io/jsonrpc/protocol/Parser.js +1 -0
- package/source/class/qx/io/jsonrpc/protocol/Result.js +2 -2
- package/source/class/qx/io/request/Xhr.js +3 -8
- package/source/class/qx/lang/normalize/Array.js +23 -1
- package/source/class/qx/locale/Date.js +520 -113
- package/source/class/qx/locale/LocalizedString.js +3 -0
- package/source/class/qx/locale/Manager.js +14 -3
- package/source/class/qx/locale/Number.js +60 -7
- package/source/class/qx/log/Logger.js +1 -1
- package/source/class/qx/module/Animation.js +2 -0
- package/source/class/qx/module/Attribute.js +2 -0
- package/source/class/qx/module/Css.js +7 -24
- package/source/class/qx/module/Event.js +2 -0
- package/source/class/qx/module/Manipulating.js +2 -0
- package/source/class/qx/module/Traversing.js +2 -0
- package/source/class/qx/promise/NativeWrapper.js +1 -1
- package/source/class/qx/test/Bootstrap.js +68 -53
- package/source/class/qx/test/Class.js +310 -2
- package/source/class/qx/test/Mixin.js +192 -42
- package/source/class/qx/test/Promise.js +129 -331
- package/source/class/qx/test/Theme.js +11 -0
- package/source/class/qx/test/bom/Font.js +2 -5
- package/source/class/qx/test/bom/Template.js +1 -1
- package/source/class/qx/test/compiler/ClassFile.js +14 -0
- package/source/class/qx/test/core/Assert.js +12 -0
- package/source/class/qx/test/core/Environment.js +17 -3
- package/source/class/qx/test/core/InheritanceDummy.js +10 -1
- package/source/class/qx/test/core/Object.js +51 -24
- package/source/class/qx/test/core/ObjectId.js +10 -1
- package/source/class/qx/test/core/Property.js +1363 -118
- package/source/class/qx/test/core/PropertyHelper.js +12 -0
- package/source/class/qx/test/core/Target.js +1 -0
- package/source/class/qx/test/core/Validation.js +2 -0
- package/source/class/qx/test/data/DataArray.js +218 -639
- package/source/class/qx/test/data/DataArrayWithChangeBubble.js +45 -215
- package/source/class/qx/test/data/MultiBinding.js +42 -0
- package/source/class/qx/test/data/async/__init__.js +4 -0
- package/source/class/qx/test/data/controller/Form.js +523 -14
- package/source/class/qx/test/data/controller/List.js +94 -426
- package/source/class/qx/test/data/controller/ListReverse.js +5 -20
- package/source/class/qx/test/data/controller/ListWithObjects.js +49 -225
- package/source/class/qx/test/data/controller/Object.js +54 -222
- package/source/class/qx/test/data/controller/Tree.js +195 -934
- package/source/class/qx/test/data/marshal/Json.js +74 -312
- package/source/class/qx/test/data/singlevalue/Array.js +55 -279
- package/source/class/qx/test/data/singlevalue/Async.js +173 -0
- package/source/class/qx/test/data/singlevalue/Deep.js +148 -327
- package/source/class/qx/test/data/singlevalue/Resolve.js +8 -28
- package/source/class/qx/test/data/singlevalue/Simple.js +130 -359
- package/source/class/qx/test/data/store/Json.js +86 -254
- package/source/class/qx/test/data/store/Jsonp.js +9 -29
- package/source/class/qx/test/data/store/Offline.js +2 -8
- package/source/class/qx/test/data/store/Rest.js +3 -3
- package/source/class/qx/test/dev/unit/Requirements.js +26 -10
- package/source/class/qx/test/event/GlobalError.js +2 -2
- package/source/class/qx/test/html/Iframe.js +1 -1
- package/source/class/qx/test/io/graphql/Client.js +2 -0
- package/source/class/qx/test/io/jsonrpc/Protocol.js +4 -2
- package/source/class/qx/test/io/request/MRequest.js +2 -8
- package/source/class/qx/test/io/request/Xhr.js +27 -117
- package/source/class/qx/test/lang/Function.js +6 -25
- package/source/class/qx/test/lang/Type.js +31 -13
- package/source/class/qx/test/locale/Date.js +173 -2
- package/source/class/qx/test/locale/Locale.js +23 -28
- package/source/class/qx/test/locale/Number.js +71 -0
- package/source/class/qx/test/log/Logger.js +7 -1
- package/source/class/qx/test/log/fixture/ClassA.js +2 -5
- package/source/class/qx/test/mobile/basic/Atom.js +3 -3
- package/source/class/qx/test/mobile/container/Scroll.js +4 -4
- package/source/class/qx/test/mobile/form/CheckBox.js +6 -12
- package/source/class/qx/test/performance/Property.js +5 -4
- package/source/class/qx/test/performance/widget/WidgetWithDecorator.js +2 -0
- package/source/class/qx/test/theme/Simple.js +34 -0
- package/source/class/qx/test/{MAppearance.js → theme/SimpleAppearance.js} +5 -4
- package/source/class/qx/test/{MDecoration.js → theme/SimpleDecoration.js} +6 -4
- package/source/class/qx/test/theme/manager/Meta.js +7 -5
- package/source/class/qx/test/tool/__init__.js +3 -0
- package/source/class/qx/test/tool/cli/AbstractValue.js +274 -0
- package/source/class/qx/test/tool/cli/Argument.js +384 -0
- package/source/class/qx/test/tool/cli/Command.js +387 -0
- package/source/class/qx/test/tool/cli/Flag.js +413 -0
- package/source/class/qx/test/tool/cli/__init__.js +3 -0
- package/source/class/qx/test/ui/LayoutTestCase.js +1 -14
- package/source/class/qx/test/ui/basic/Label.js +106 -0
- package/source/class/qx/test/ui/core/Blocker.js +125 -3
- package/source/class/qx/test/ui/form/Form.js +106 -0
- package/source/class/qx/test/ui/form/FormManager.js +6 -5
- package/source/class/qx/test/ui/form/SplitButton.js +1 -1
- package/source/class/qx/test/ui/toolbar/OverflowHandling.js +13 -14
- package/source/class/qx/test/ui/toolbar/ToolBar.js +16 -16
- package/source/class/qx/test/ui/tree/TreeFolder.js +5 -7
- package/source/class/qx/test/ui/tree/virtual/AbstractTreeTest.js +2 -0
- package/source/class/qx/test/ui/tree/virtual/Tree.js +36 -0
- package/source/class/qx/test/util/DateFormat.js +1 -1
- package/source/class/qx/test/util/PropertyUtil.js +0 -36
- package/source/class/qx/theme/classic/Appearance.js +22 -1
- package/source/class/qx/theme/indigo/ColorDark.js +2 -0
- package/source/class/qx/theme/manager/Font.js +6 -1
- package/source/class/qx/theme/manager/Meta.js +2 -1
- package/source/class/qx/theme/modern/Appearance.js +21 -0
- package/source/class/qx/theme/simple/Appearance.js +52 -95
- package/source/class/qx/theme/simple/Decoration.js +0 -1
- package/source/class/qx/theme/tangible/Appearance.js +3 -1
- package/source/class/qx/tool/cli/AbstractCliApp.js +88 -0
- package/source/class/qx/tool/cli/AbstractValue.js +186 -0
- package/source/class/qx/tool/cli/Argument.js +155 -0
- package/source/class/qx/tool/cli/Command.js +518 -0
- package/source/class/qx/tool/cli/Flag.js +202 -0
- package/source/class/qx/tool/cli/Parser.js +39 -0
- package/source/class/qx/tool/cli/__init__.js +26 -1
- package/source/class/qx/tool/compiler/Analyser.js +41 -13
- package/source/class/qx/tool/compiler/ClassFile.js +37 -13
- package/source/class/qx/tool/compiler/Console.js +2 -0
- package/source/class/qx/tool/compiler/MetaDatabase.js +47 -0
- package/source/class/qx/tool/compiler/MetaExtraction.js +53 -33
- package/source/class/qx/tool/compiler/app/Library.js +1 -1
- package/source/class/qx/tool/compiler/app/WebFont.js +2 -0
- package/source/class/qx/tool/compiler/cli/Application.js +58 -0
- package/source/class/qx/tool/{cli/commands → compiler/cli}/Command.js +99 -45
- package/source/class/qx/tool/{cli → compiler/cli}/ConfigDb.js +7 -7
- package/source/class/qx/tool/compiler/cli/ConfigLoader.js +272 -0
- package/source/class/qx/tool/{cli → compiler/cli}/LibraryApplication.js +3 -3
- package/source/class/qx/tool/compiler/cli/RootCommand.js +63 -0
- package/source/class/qx/tool/{cli → compiler/cli}/Watch.js +49 -24
- package/source/class/qx/tool/compiler/cli/__init__.js +3 -0
- package/source/class/qx/tool/{cli → compiler/cli}/api/AbstractApi.js +2 -11
- package/source/class/qx/tool/{cli → compiler/cli}/api/CompilerApi.js +11 -10
- package/source/class/qx/tool/{cli → compiler/cli}/api/LibraryApi.js +13 -4
- package/source/class/qx/tool/{cli → compiler/cli}/api/Test.js +1 -1
- package/source/class/qx/tool/compiler/cli/commands/Add.js +49 -0
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Clean.js +12 -25
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Compile.js +630 -590
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Config.js +22 -20
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Create.js +78 -55
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Deploy.js +45 -60
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Es6ify.js +57 -41
- package/source/class/qx/tool/{cli → compiler/cli}/commands/ExportGlyphs.js +26 -7
- package/source/class/qx/tool/compiler/cli/commands/Lint.js +420 -0
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Migrate.js +40 -20
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Package.js +20 -32
- package/source/class/qx/tool/compiler/cli/commands/Pkg.js +36 -0
- package/source/class/qx/tool/compiler/cli/commands/Prettier.js +278 -0
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Run.js +43 -39
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Serve.js +63 -61
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Test.js +49 -52
- package/source/class/qx/tool/{cli → compiler/cli}/commands/Typescript.js +70 -62
- package/source/class/qx/tool/{cli → compiler/cli}/commands/add/Class.js +54 -31
- package/source/class/qx/tool/{cli → compiler/cli}/commands/add/Script.js +57 -33
- package/source/class/qx/tool/{cli → compiler/cli}/commands/config/Delete.js +19 -13
- package/source/class/qx/tool/{cli → compiler/cli}/commands/config/Get.js +19 -13
- package/source/class/qx/tool/{cli → compiler/cli}/commands/config/List.js +20 -20
- package/source/class/qx/tool/{cli → compiler/cli}/commands/config/Set.js +28 -20
- package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Install.js +140 -75
- package/source/class/qx/tool/{cli → compiler/cli}/commands/package/List.js +119 -80
- package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Publish.js +196 -179
- package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Remove.js +18 -21
- package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Update.js +92 -71
- package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Upgrade.js +67 -54
- package/source/class/qx/tool/compiler/makers/AbstractAppMaker.js +2 -1
- package/source/class/qx/tool/compiler/resources/Manager.js +2 -0
- package/source/class/qx/tool/compiler/resources/ScssConverter.js +1 -1
- package/source/class/qx/tool/compiler/resources/ScssFile.js +1 -1
- package/source/class/qx/tool/compiler/targets/Target.js +5 -10
- package/source/class/qx/tool/compiler/targets/TypeScriptWriter.js +9 -2
- package/source/class/qx/tool/compiler/targets/meta/ApplicationMeta.js +2 -4
- package/source/class/qx/tool/compiler/targets/meta/BootJs.js +2 -0
- package/source/class/qx/tool/compiler/targets/meta/Browserify.js +142 -80
- package/source/class/qx/tool/compiler/targets/meta/PackageJavascript.js +2 -0
- package/source/class/qx/tool/config/Abstract.js +5 -5
- package/source/class/qx/tool/config/Lockfile.js +1 -1
- package/source/class/qx/tool/migration/BaseMigration.js +9 -7
- package/source/class/qx/tool/migration/M6_0_0.js +3 -3
- package/source/class/qx/tool/migration/M8_0_0.js +958 -0
- package/source/class/qx/tool/utils/Debounce.js +0 -1
- package/source/class/qx/tool/utils/Http.js +109 -21
- package/source/class/qx/tool/utils/LogManager.js +7 -0
- package/source/class/qx/tool/utils/Promisify.js +12 -1
- package/source/class/qx/tool/utils/QooxdooVersions.js +193 -0
- package/source/class/qx/tool/utils/Utils.js +8 -5
- package/source/class/qx/tool/utils/Website.js +9 -222
- package/source/class/qx/tool/utils/Zip.js +47 -0
- package/source/class/qx/tool/utils/files/Utils.js +3 -11
- package/source/class/qx/tool/utils/json/Tokenizer.js +5 -0
- package/source/class/qx/ui/basic/Atom.js +8 -8
- package/source/class/qx/ui/core/Blocker.js +17 -4
- package/source/class/qx/ui/core/DragDropCursor.js +2 -1
- package/source/class/qx/ui/core/EventHandler.js +13 -21
- package/source/class/qx/ui/core/LayoutItem.js +8 -31
- package/source/class/qx/ui/core/MExecutable.js +7 -31
- package/source/class/qx/ui/core/MNativeOverflow.js +4 -2
- package/source/class/qx/ui/core/Widget.js +50 -165
- package/source/class/qx/ui/core/scroll/IScrollBar.js +9 -3
- package/source/class/qx/ui/core/scroll/ScrollBar.js +7 -1
- package/source/class/qx/ui/core/scroll/ScrollPane.js +12 -4
- package/source/class/qx/ui/embed/Html.js +6 -2
- package/source/class/qx/ui/form/AbstractField.js +4 -12
- package/source/class/qx/ui/form/Button.js +6 -4
- package/source/class/qx/ui/form/CheckedSelectBox.js +8 -8
- package/source/class/qx/ui/form/FileSelectorButton.js +1 -1
- package/source/class/qx/ui/form/Form.js +3 -0
- package/source/class/qx/ui/form/IListItem.js +3 -1
- package/source/class/qx/ui/form/IRadioItem.js +3 -1
- package/source/class/qx/ui/form/MForm.js +3 -1
- package/source/class/qx/ui/form/Slider.js +6 -2
- package/source/class/qx/ui/form/SplitButton.js +5 -5
- package/source/class/qx/ui/form/TextField.js +1 -2
- package/source/class/qx/ui/form/validation/Manager.js +6 -2
- package/source/class/qx/ui/menubar/Button.js +1 -1
- package/source/class/qx/ui/mobile/basic/Atom.js +5 -5
- package/source/class/qx/ui/mobile/dialog/Menu.js +9 -31
- package/source/class/qx/ui/mobile/dialog/Popup.js +13 -1
- package/source/class/qx/ui/table/pane/FocusIndicator.js +5 -2
- package/source/class/qx/ui/table/pane/Scroller.js +5 -20
- package/source/class/qx/ui/table/selection/Model.js +1 -0
- package/source/class/qx/ui/toolbar/Button.js +1 -1
- package/source/class/qx/ui/toolbar/CheckBox.js +1 -1
- package/source/class/qx/ui/toolbar/FileSelectorButton.js +1 -2
- package/source/class/qx/ui/toolbar/Part.js +2 -2
- package/source/class/qx/ui/toolbar/PartContainer.js +2 -2
- package/source/class/qx/ui/toolbar/ToolBar.js +24 -49
- package/source/class/qx/ui/tree/VirtualTree.js +6 -4
- package/source/class/qx/ui/tree/core/AbstractItem.js +10 -17
- package/source/class/qx/ui/tree/core/IVirtualTree.js +4 -2
- package/source/class/qx/ui/tree/provider/IVirtualTreeProvider.js +20 -10
- package/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js +4 -1
- package/source/class/qx/ui/virtual/cell/Cell.js +20 -48
- package/source/class/qx/ui/virtual/cell/WidgetCell.js +2 -4
- package/source/class/qx/ui/virtual/core/Axis.js +4 -0
- package/source/class/qx/ui/virtual/core/ILayer.js +14 -10
- package/source/class/qx/ui/virtual/core/Scroller.js +4 -4
- package/source/class/qx/ui/virtual/layer/WidgetCell.js +4 -0
- package/source/class/qx/ui/virtual/selection/Abstract.js +3 -0
- package/source/class/qx/ui/virtual/selection/MModel.js +1 -1
- package/source/class/qx/ui/window/IDesktop.js +6 -2
- package/source/class/qx/ui/window/IWindowManager.js +10 -4
- package/source/class/qx/ui/window/MDesktop.js +2 -1
- package/source/class/qx/ui/window/Manager.js +1 -1
- package/source/class/qx/ui/window/Window.js +6 -4
- package/source/class/qx/util/OOUtil.js +8 -9
- package/source/class/qx/util/PropertyUtil.js +34 -154
- package/source/class/qx/util/ResponseParser.js +2 -0
- package/source/class/qx/util/Serializer.js +69 -114
- package/source/class/qx/util/format/DateFormat.js +3 -2
- package/source/global.d.ts +4 -0
- package/source/resource/qx/tool/bin/download-assets +0 -2
- package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/default.tmpl.js +6 -7
- package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/cli/templates/class/singleton.tmpl.js +5 -6
- package/source/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-node.tmpl.js +1 -0
- package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/cli/templates/template_vars.js +12 -9
- package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/schema/Manifest-1-0-0.json +2 -2
- package/source/resource/qx/tool/{schema → compiler/schema}/Manifest-2-0-0.json +2 -2
- package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/schema/compile-1-0-0.json +21 -5
- package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/schema/qooxdoo-1-0-0.json +1 -1
- package/source/resource/qx/tool/website/build/404.html +22 -22
- package/source/resource/qx/tool/website/build/about.html +23 -23
- package/source/resource/qx/tool/website/build/assets/common.js +30 -18
- package/source/resource/qx/tool/website/build/assets/custom.css +290 -0
- package/source/resource/qx/tool/website/build/assets/qxWeb.js +28 -0
- package/source/resource/qx/tool/website/build/diagnostics/dependson.html +30 -30
- package/source/resource/qx/tool/website/build/diagnostics/dependson.js +49 -40
- package/source/resource/qx/tool/website/build/diagnostics/requiredby.html +20 -23
- package/source/resource/qx/tool/website/build/diagnostics/requiredby.js +38 -31
- package/source/resource/qx/tool/website/build/index.html +24 -24
- package/source/resource/qx/tool/website/build/scripts/serve.js +63 -65
- package/source/resource/qx/tool/website/partials/footer.html +8 -13
- package/source/resource/qx/tool/website/partials/head.html +9 -7
- package/source/resource/qx/tool/website/partials/header.html +3 -3
- package/source/resource/qx/tool/website/src/assets/common.js +32 -0
- package/source/resource/qx/tool/website/src/assets/custom.css +290 -0
- package/source/resource/qx/tool/website/src/assets/qxWeb.js +28 -0
- package/source/resource/qx/tool/website/src/diagnostics/dependson.js +49 -40
- package/source/resource/qx/tool/website/src/diagnostics/requiredby.js +38 -31
- package/source/resource/qx/tool/website/src/index.html +2 -2
- package/source/resource/qx/tool/website/src/scripts/serve.js +63 -65
- package/lib/resource/qx/tool/bin/build-devtools +0 -13
- package/lib/resource/qx/tool/bin/build-website +0 -15
- package/lib/resource/qx/tool/bin/download-assets +0 -23
- package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css.map +0 -1
- package/lib/resource/qx/tool/website/build/assets/bootstrap.css +0 -7
- package/lib/resource/qx/tool/website/build/assets/bootstrap.min.css +0 -7
- package/lib/resource/qx/tool/website/build/assets/bootstrap.min.css.map +0 -1
- package/lib/resource/qx/tool/website/build/assets/jquery.js +0 -5453
- package/lib/resource/qx/tool/website/build/qooxdoo.css +0 -21
- package/lib/resource/qx/tool/website/sass/qooxdoo.css +0 -3
- package/lib/resource/qx/tool/website/sass/qooxdoo.css.map +0 -1
- package/lib/resource/qx/tool/website/src/assets/bootstrap.css +0 -7
- package/lib/resource/qx/tool/website/src/assets/bootstrap.min.css +0 -7
- package/lib/resource/qx/tool/website/src/assets/bootstrap.min.css.map +0 -1
- package/lib/resource/qx/tool/website/src/assets/jquery.js +0 -5453
- package/source/class/qx/core/Property.js +0 -2100
- package/source/class/qx/tool/cli/Application.js +0 -47
- package/source/class/qx/tool/cli/Cli.js +0 -713
- package/source/class/qx/tool/cli/commands/Add.js +0 -46
- package/source/class/qx/tool/cli/commands/Lint.js +0 -255
- package/source/class/qx/tool/cli/commands/Pkg.js +0 -56
- package/source/class/qx/tool/cli/commands/package/Migrate.js +0 -37
- package/source/class/qx/tool/compiler/app/Cldr.js +0 -725
- package/source/resource/qx/tool/bin/build-devtools +0 -13
- package/source/resource/qx/tool/bin/build-website +0 -15
- package/source/resource/qx/tool/website/build/assets/bootstrap.css +0 -7
- package/source/resource/qx/tool/website/build/assets/bootstrap.min.css +0 -7
- package/source/resource/qx/tool/website/build/assets/bootstrap.min.css.map +0 -1
- package/source/resource/qx/tool/website/build/assets/jquery.js +0 -5453
- package/source/resource/qx/tool/website/build/qooxdoo.css +0 -21
- package/source/resource/qx/tool/website/sass/qooxdoo.scss +0 -31
- package/source/resource/qx/tool/website/src/assets/bootstrap.css +0 -7
- package/source/resource/qx/tool/website/src/assets/bootstrap.min.css +0 -7
- package/source/resource/qx/tool/website/src/assets/bootstrap.min.css.map +0 -1
- package/source/resource/qx/tool/website/src/assets/jquery.js +0 -5453
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/TypeScriptWriter-base_declaration.d.ts +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/header.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/interface.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/mixin.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-browser.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-rhino.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/.gitignore.tmpl +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/Manifest.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/compile.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/readme.tmpl.md +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/index.tmpl.html +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/nojs.tmpl.html +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/Application.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/__init__.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/test/DemoTest.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Appearance.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Color.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Decoration.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Font.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Theme.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/app.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/favicon.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/js_256x256.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/test.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/translation/readme.txt +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/.gitignore.tmpl +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/Manifest.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/compile.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/readme.tmpl.md +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/index.tmpl.html +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/nojs.tmpl.html +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/Application.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/__init__.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Login.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Overview.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/__init__.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/app.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/css/.gitignore.tmpl +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/favicon.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/js_256x256.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/theme/custom/css/custom.css +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/translation/readme.txt +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/.gitignore.tmpl +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/Manifest.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/compile.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/readme.tmpl.md +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/Button.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/__init__.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/demo/Application.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/resource/custom/test.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/test/DemoTest.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Appearance.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Color.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Decoration.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Font.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Theme.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/resource/custom/test.png +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/translation/readme.txt +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/.gitignore.tmpl +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/Manifest.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/compile.tmpl.json +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/readme.tmpl.txt +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/Application.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/__init__.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/test/DemoTest.tmpl.js +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/resource/custom/.gitignore.tmpl +0 -0
- /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/translation/readme.txt +0 -0
- /package/lib/resource/qx/tool/{loadsass.js → compiler/loadsass.js} +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/TypeScriptWriter-base_declaration.d.ts +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/header.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/interface.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/mixin.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-browser.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-rhino.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/.gitignore.tmpl +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/Manifest.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/compile.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/readme.tmpl.md +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/index.tmpl.html +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/nojs.tmpl.html +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/Application.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/__init__.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/test/DemoTest.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Appearance.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Color.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Decoration.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Font.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Theme.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/app.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/favicon.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/js_256x256.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/test.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/translation/readme.txt +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/.gitignore.tmpl +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/Manifest.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/compile.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/readme.tmpl.md +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/index.tmpl.html +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/nojs.tmpl.html +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/Application.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/__init__.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Login.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Overview.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/__init__.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/app.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/css/.gitignore.tmpl +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/favicon.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/js_256x256.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/theme/custom/scss/_styles.scss +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/theme/custom/scss/custom.scss +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/translation/readme.txt +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/.gitignore.tmpl +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/Manifest.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/compile.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/readme.tmpl.md +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/Button.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/__init__.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/demo/Application.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/resource/custom/test.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/test/DemoTest.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Appearance.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Color.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Decoration.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Font.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Theme.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/resource/custom/test.png +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/translation/readme.txt +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/.gitignore.tmpl +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/Manifest.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/compile.tmpl.json +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/readme.tmpl.txt +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/Application.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/__init__.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/test/DemoTest.tmpl.js +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/resource/custom/.gitignore.tmpl +0 -0
- /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/translation/readme.txt +0 -0
- /package/source/resource/qx/tool/{loadsass.js → compiler/loadsass.js} +0 -0
|
@@ -5,1547 +5,637 @@
|
|
|
5
5
|
http://qooxdoo.org
|
|
6
6
|
|
|
7
7
|
Copyright:
|
|
8
|
-
|
|
8
|
+
2022-2023 Zenesis Limited, https://www.zenesis.com
|
|
9
9
|
|
|
10
10
|
License:
|
|
11
11
|
MIT: https://opensource.org/licenses/MIT
|
|
12
12
|
See the LICENSE file in the project's top-level directory for details.
|
|
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, pmalinowski116@gmail.com)
|
|
16
17
|
|
|
17
18
|
************************************************************************ */
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
+
* This class implements bindings as a first class object.
|
|
22
|
+
*
|
|
23
|
+
* The Binding has a source, a value, and optional target; the source (and
|
|
24
|
+
* sourcePath) is read and copied into value; the value is copied into the target
|
|
25
|
+
* if there is one.
|
|
26
|
+
*
|
|
27
|
+
* If the sourcePath is null, then the value will be the source object; if the
|
|
28
|
+
* target or the targetPath is null, then the `value` will still update but will
|
|
29
|
+
* not be copied anywhere
|
|
30
|
+
*
|
|
31
|
+
* Arrays are supported by including `[]` in paths, eg `children[2]`, although this
|
|
32
|
+
* only works with `sourcePath` and not in `targetPath`. Arrays can be native or
|
|
33
|
+
* `qx.data.Array`, but changes to native arrays will not be detected because they
|
|
34
|
+
* dont fire events
|
|
35
|
+
*
|
|
36
|
+
* @typedef {[qx.data.SingleValueBinding, qx.core.Object, string, qx.core.Object, string]} BindingRecord Array representation of the binding,
|
|
37
|
+
* containing the binding, source object, source path, target object and target path respectively.
|
|
21
38
|
*/
|
|
22
39
|
qx.Class.define("qx.data.SingleValueBinding", {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
extend: qx.core.Object,
|
|
41
|
+
implement: [qx.data.binding.IInputReceiver],
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The class is responsible for binding a source objects property to
|
|
45
|
+
* a target objects property. Both properties have to have the usual qooxdoo
|
|
46
|
+
* getter and setter. The source property also needs to fire change-events
|
|
47
|
+
* on every change of its value.
|
|
48
|
+
* Please keep in mind, that this binding is unidirectional. If you need
|
|
49
|
+
* a binding in both directions, you have to use two of this bindings.
|
|
50
|
+
*
|
|
51
|
+
* It's also possible to bind some kind of a hierarchy as a source. This
|
|
52
|
+
* means that you can separate the source properties with a dot and bind
|
|
53
|
+
* by that the object referenced to this property chain.
|
|
54
|
+
* Example with an object 'a' which has object 'b' stored in its 'child'
|
|
55
|
+
* property. Object b has a string property named abc:
|
|
56
|
+
* <pre><code>
|
|
57
|
+
* qx.data.SingleValueBinding.bind(a, "child.abc", textfield, "value");
|
|
58
|
+
* </code></pre>
|
|
59
|
+
* In that case, if the property abc of b changes, the textfield will
|
|
60
|
+
* automatically contain the new value. Also if the child of a changes, the
|
|
61
|
+
* new value (abc of the new child) will be in the textfield.
|
|
62
|
+
*
|
|
63
|
+
* There is also a possibility of binding an array. Therefore the array
|
|
64
|
+
* {@link qx.data.IListData} is needed because this array has change events
|
|
65
|
+
* which the native does not. Imagine a qooxdoo object a which has a
|
|
66
|
+
* children property containing an array holding more of its own kind.
|
|
67
|
+
* Every object has a name property as a string.
|
|
68
|
+
* <pre>
|
|
69
|
+
* var svb = qx.data.SingleValueBinding;
|
|
70
|
+
* // bind the first child's name of 'a' to a textfield
|
|
71
|
+
* svb.bind(a, "children[0].name", textfield, "value");
|
|
72
|
+
* // bind the last child's name of 'a' to a textfield
|
|
73
|
+
* svb.bind(a, "children[last].name", textfield2, "value");
|
|
74
|
+
* // also deeper bindings are possible
|
|
75
|
+
* svb.bind(a, "children[0].children[0].name", textfield3, "value");
|
|
76
|
+
* </pre>
|
|
77
|
+
*
|
|
78
|
+
* As you can see in this example, the abc property of a's b will be bound
|
|
79
|
+
* to the textfield. If now the value of b changed or even the a will get a
|
|
80
|
+
* new b, the binding still shows the right value.
|
|
81
|
+
*
|
|
82
|
+
* @param {qx.core.Object?} sourceObject The source of the binding.
|
|
83
|
+
* @param {String} sourcePropertyChain The property chain which represents
|
|
84
|
+
* the source property.
|
|
85
|
+
* @param {qx.core.Object?} targetObject The object which the source should
|
|
86
|
+
* be bound to.
|
|
87
|
+
* @param {String} targetPropertyChain The property chain to the target
|
|
88
|
+
* object.
|
|
89
|
+
* @param {BindingOptions} options A map containing the options.
|
|
90
|
+
*
|
|
91
|
+
* @typedef BindingOptions
|
|
92
|
+
* @property {converter} converter Data converter function. If no conversion has been done, the given value should be returned.
|
|
93
|
+
* e.g. a number to boolean converter
|
|
94
|
+
* <code>function(data, model, source, target) {return data > 100;}</code>
|
|
95
|
+
* @property {onUpdate} onUpdate This callback will be called if the binding was updated successfully.
|
|
96
|
+
* @property {() => void} onSetFail A callback function can be given here. This function will
|
|
97
|
+
* be called if the set of the value fails.
|
|
98
|
+
* @property {string} ignoreConverter A string which will be matched using the current
|
|
99
|
+
* property chain. If it matches, the converter will not be called.
|
|
100
|
+
*
|
|
101
|
+
*
|
|
102
|
+
* @callback converter
|
|
103
|
+
* @param {*} data The data to convert
|
|
104
|
+
* @param {*} model The corresponding model object, which is only set in case of the use of an controller.
|
|
105
|
+
* @param {qx.core.Object} source The source object for the binding
|
|
106
|
+
* @param {qx.core.Object} target The target object
|
|
107
|
+
* @returns {*} The converted data
|
|
108
|
+
*
|
|
109
|
+
* @callback onUpdate
|
|
110
|
+
* @param {qx.core.Object} source The source object for the binding
|
|
111
|
+
* @param {qx.core.Object} target The target object
|
|
112
|
+
* @param {*} data The data
|
|
113
|
+
|
|
114
|
+
*
|
|
115
|
+
* @returns {qx.data.SingleValueBinding} Returns the internal id for that binding. This can be used
|
|
116
|
+
* for referencing the binding or e.g. for removing. This is not an atomic
|
|
117
|
+
* id so you can't you use it as a hash-map index.
|
|
118
|
+
*
|
|
119
|
+
* @throws {qx.core.AssertionError} If the event is no data event or
|
|
120
|
+
* there is no property definition for object and property (source and
|
|
121
|
+
* target).
|
|
122
|
+
*/
|
|
123
|
+
construct(sourcePath, targetPath, source, target, options) {
|
|
124
|
+
super();
|
|
125
|
+
if (!(sourcePath || targetPath)) {
|
|
126
|
+
throw new Error("SourcePath and targetPath must be specified");
|
|
127
|
+
}
|
|
128
|
+
this.__options = options ?? {};
|
|
129
|
+
let tracker = {};
|
|
130
|
+
|
|
131
|
+
const Utils = qx.event.Utils;
|
|
132
|
+
this.setSourcePath(sourcePath);
|
|
133
|
+
this.setTargetPath(targetPath);
|
|
134
|
+
Utils.then(tracker, () => source && this.setSource(source));
|
|
135
|
+
Utils.then(tracker, () => target && this.setTarget(target));
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
destruct() {
|
|
139
|
+
if (this.__sourceSegments) {
|
|
140
|
+
this.__sourceSegments.forEach(segment => segment.dispose());
|
|
141
|
+
this.__sourceSegments = null;
|
|
142
|
+
}
|
|
143
|
+
if (this.__targetSegments) {
|
|
144
|
+
this.__targetSegments.forEach(segment => segment.dispose());
|
|
145
|
+
this.__targetSegments = null;
|
|
146
|
+
}
|
|
147
|
+
this.setSource(null);
|
|
148
|
+
this.setTarget(null);
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
properties: {
|
|
152
|
+
/** The path into the `source` object */
|
|
153
|
+
sourcePath: {
|
|
154
|
+
init: null,
|
|
155
|
+
nullable: true,
|
|
156
|
+
check: "String",
|
|
157
|
+
event: "changeSourcePath",
|
|
158
|
+
apply: "_applySourcePath"
|
|
159
|
+
},
|
|
26
160
|
|
|
27
|
-
/**
|
|
28
|
-
|
|
161
|
+
/** The path into the `target` object */
|
|
162
|
+
targetPath: {
|
|
163
|
+
init: null,
|
|
164
|
+
nullable: true,
|
|
165
|
+
check: "String",
|
|
166
|
+
event: "changeTargetPath",
|
|
167
|
+
apply: "_applyTargetPath"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
29
170
|
|
|
171
|
+
members: {
|
|
30
172
|
/**
|
|
31
|
-
*
|
|
32
|
-
* a target objects property. Both properties have to have the usual qooxdoo
|
|
33
|
-
* getter and setter. The source property also needs to fire change-events
|
|
34
|
-
* on every change of its value.
|
|
35
|
-
* Please keep in mind, that this binding is unidirectional. If you need
|
|
36
|
-
* a binding in both directions, you have to use two of this bindings.
|
|
37
|
-
*
|
|
38
|
-
* It's also possible to bind some kind of a hierarchy as a source. This
|
|
39
|
-
* means that you can separate the source properties with a dot and bind
|
|
40
|
-
* by that the object referenced to this property chain.
|
|
41
|
-
* Example with an object 'a' which has object 'b' stored in its 'child'
|
|
42
|
-
* property. Object b has a string property named abc:
|
|
43
|
-
* <pre><code>
|
|
44
|
-
* qx.data.SingleValueBinding.bind(a, "child.abc", textfield, "value");
|
|
45
|
-
* </code></pre>
|
|
46
|
-
* In that case, if the property abc of b changes, the textfield will
|
|
47
|
-
* automatically contain the new value. Also if the child of a changes, the
|
|
48
|
-
* new value (abc of the new child) will be in the textfield.
|
|
49
|
-
*
|
|
50
|
-
* There is also a possibility of binding an array. Therefore the array
|
|
51
|
-
* {@link qx.data.IListData} is needed because this array has change events
|
|
52
|
-
* which the native does not. Imagine a qooxdoo object a which has a
|
|
53
|
-
* children property containing an array holding more of its own kind.
|
|
54
|
-
* Every object has a name property as a string.
|
|
55
|
-
* <pre>
|
|
56
|
-
* var svb = qx.data.SingleValueBinding;
|
|
57
|
-
* // bind the first child's name of 'a' to a textfield
|
|
58
|
-
* svb.bind(a, "children[0].name", textfield, "value");
|
|
59
|
-
* // bind the last child's name of 'a' to a textfield
|
|
60
|
-
* svb.bind(a, "children[last].name", textfield2, "value");
|
|
61
|
-
* // also deeper bindings are possible
|
|
62
|
-
* svb.bind(a, "children[0].children[0].name", textfield3, "value");
|
|
63
|
-
* </pre>
|
|
64
|
-
*
|
|
65
|
-
* As you can see in this example, the abc property of a's b will be bound
|
|
66
|
-
* to the textfield. If now the value of b changed or even the a will get a
|
|
67
|
-
* new b, the binding still shows the right value.
|
|
68
|
-
*
|
|
69
|
-
* @param sourceObject {qx.core.Object} The source of the binding.
|
|
70
|
-
* @param sourcePropertyChain {String} The property chain which represents
|
|
71
|
-
* the source property.
|
|
72
|
-
* @param targetObject {qx.core.Object} The object which the source should
|
|
73
|
-
* be bind to.
|
|
74
|
-
* @param targetPropertyChain {String} The property chain to the target
|
|
75
|
-
* object.
|
|
76
|
-
* @param options {Map?null} A map containing the options.
|
|
77
|
-
* <li>converter: A converter function which takes four parameters
|
|
78
|
-
* and should return the converted value.
|
|
79
|
-
* <ol>
|
|
80
|
-
* <li>The data to convert</li>
|
|
81
|
-
* <li>The corresponding model object, which is only set in case of the use of an controller.</li>
|
|
82
|
-
* <li>The source object for the binding</li>
|
|
83
|
-
* <li>The target object.</li>
|
|
84
|
-
* </ol>
|
|
85
|
-
* If no conversion has been done, the given value should be returned.
|
|
86
|
-
* e.g. a number to boolean converter
|
|
87
|
-
* <code>function(data, model, source, target) {return data > 100;}</code>
|
|
88
|
-
* </li>
|
|
89
|
-
* <li>onUpdate: A callback function can be given here. This method will be
|
|
90
|
-
* called if the binding was updated successful. There will be
|
|
91
|
-
* three parameter you do get in that method call.
|
|
92
|
-
* <ol>
|
|
93
|
-
* <li>The source object</li>
|
|
94
|
-
* <li>The target object</li>
|
|
95
|
-
* <li>The data</li>
|
|
96
|
-
* </ol>
|
|
97
|
-
* Here is a sample: <code>onUpdate : function(source, target, data) {...}</code>
|
|
98
|
-
* </li>
|
|
99
|
-
* <li>onSetFail: A callback function can be given here. This method will
|
|
100
|
-
* be called if the set of the value fails.
|
|
101
|
-
* </li>
|
|
102
|
-
* <li>ignoreConverter: A string which will be matched using the current
|
|
103
|
-
* property chain. If it matches, the converter will not be called.
|
|
104
|
-
* </li>
|
|
105
|
-
*
|
|
106
|
-
* @return {var} Returns the internal id for that binding. This can be used
|
|
107
|
-
* for referencing the binding or e.g. for removing. This is not an atomic
|
|
108
|
-
* id so you can't you use it as a hash-map index.
|
|
109
|
-
*
|
|
110
|
-
* @throws {qx.core.AssertionError} If the event is no data event or
|
|
111
|
-
* there is no property definition for object and property (source and
|
|
112
|
-
* target).
|
|
173
|
+
* @type {*}
|
|
113
174
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
options
|
|
120
|
-
) {
|
|
121
|
-
// check for the arguments
|
|
122
|
-
if (qx.core.Environment.get("qx.debug")) {
|
|
123
|
-
qx.core.Assert.assertObject(sourceObject, "sourceObject");
|
|
124
|
-
qx.core.Assert.assertString(sourcePropertyChain, "sourcePropertyChain");
|
|
125
|
-
qx.core.Assert.assertObject(targetObject, "targetObject");
|
|
126
|
-
qx.core.Assert.assertString(targetPropertyChain, "targetPropertyChain");
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// set up the target binding
|
|
130
|
-
var targetListenerMap = this.__setUpTargetBinding(
|
|
131
|
-
sourceObject,
|
|
132
|
-
sourcePropertyChain,
|
|
133
|
-
targetObject,
|
|
134
|
-
targetPropertyChain,
|
|
135
|
-
options
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
// get the property names
|
|
139
|
-
var propertyNames = sourcePropertyChain.split(".");
|
|
140
|
-
|
|
141
|
-
// stuff that's needed to store for the listener function
|
|
142
|
-
var arrayIndexValues = this.__checkForArrayInPropertyChain(propertyNames);
|
|
143
|
-
var sources = [];
|
|
144
|
-
var listeners = [];
|
|
145
|
-
var listenerIds = [];
|
|
146
|
-
var eventNames = [];
|
|
147
|
-
var source = sourceObject;
|
|
148
|
-
var initialPromise = null;
|
|
149
|
-
|
|
150
|
-
// add a try catch to make it possible to remove the listeners of the
|
|
151
|
-
// chain in case the loop breaks after some listeners already added.
|
|
152
|
-
try {
|
|
153
|
-
// go through all property names
|
|
154
|
-
for (var i = 0; i < propertyNames.length; i++) {
|
|
155
|
-
var propertyName = propertyNames[i];
|
|
156
|
-
|
|
157
|
-
// check for the array
|
|
158
|
-
if (arrayIndexValues[i] !== "") {
|
|
159
|
-
// push the array change event
|
|
160
|
-
eventNames.push("change");
|
|
161
|
-
} else {
|
|
162
|
-
var eventName = this.__getEventNameForProperty(
|
|
163
|
-
source,
|
|
164
|
-
propertyName
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
if (!eventName) {
|
|
168
|
-
if (i == 0) {
|
|
169
|
-
// the root property can not change --> error
|
|
170
|
-
throw new qx.core.AssertionError(
|
|
171
|
-
"Binding property " +
|
|
172
|
-
propertyName +
|
|
173
|
-
" of object " +
|
|
174
|
-
source +
|
|
175
|
-
" not possible: No event available. Full property chain: " +
|
|
176
|
-
sourcePropertyChain
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (
|
|
181
|
-
source instanceof qx.core.Object &&
|
|
182
|
-
qx.Class.hasProperty(source.constructor, propertyName)
|
|
183
|
-
) {
|
|
184
|
-
qx.log.Logger.warn(
|
|
185
|
-
"Binding property " +
|
|
186
|
-
propertyName +
|
|
187
|
-
" of object " +
|
|
188
|
-
source +
|
|
189
|
-
" not possible: No event available. Full property chain: " +
|
|
190
|
-
sourcePropertyChain
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// call the converter if no event could be found on binding creation
|
|
195
|
-
initialPromise = this.__setInitialValue(
|
|
196
|
-
undefined,
|
|
197
|
-
targetObject,
|
|
198
|
-
targetPropertyChain,
|
|
199
|
-
options,
|
|
200
|
-
sourceObject
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
eventNames.push(eventName);
|
|
206
|
-
}
|
|
175
|
+
__value: undefined,
|
|
176
|
+
/**
|
|
177
|
+
* @type {qx.core.Object}
|
|
178
|
+
*/
|
|
179
|
+
__source: null,
|
|
207
180
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (i == propertyNames.length - 1) {
|
|
213
|
-
// if it is an array, set the initial value and bind the event
|
|
214
|
-
if (arrayIndexValues[i] !== "") {
|
|
215
|
-
// get the current value
|
|
216
|
-
var itemIndex =
|
|
217
|
-
arrayIndexValues[i] === "last"
|
|
218
|
-
? source.length - 1
|
|
219
|
-
: arrayIndexValues[i];
|
|
220
|
-
var currentValue = source.getItem(itemIndex);
|
|
221
|
-
|
|
222
|
-
// set the initial value
|
|
223
|
-
initialPromise = this.__setInitialValue(
|
|
224
|
-
currentValue,
|
|
225
|
-
targetObject,
|
|
226
|
-
targetPropertyChain,
|
|
227
|
-
options,
|
|
228
|
-
sourceObject
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
// bind the event
|
|
232
|
-
listenerIds[i] = this.__bindEventToProperty(
|
|
233
|
-
source,
|
|
234
|
-
eventNames[i],
|
|
235
|
-
targetObject,
|
|
236
|
-
targetPropertyChain,
|
|
237
|
-
options,
|
|
238
|
-
arrayIndexValues[i]
|
|
239
|
-
);
|
|
240
|
-
} else {
|
|
241
|
-
// try to set the initial value
|
|
242
|
-
if (
|
|
243
|
-
propertyNames[i] != null &&
|
|
244
|
-
source["get" + qx.lang.String.firstUp(propertyNames[i])] != null
|
|
245
|
-
) {
|
|
246
|
-
var currentValue =
|
|
247
|
-
source["get" + qx.lang.String.firstUp(propertyNames[i])]();
|
|
248
|
-
initialPromise = this.__setInitialValue(
|
|
249
|
-
currentValue,
|
|
250
|
-
targetObject,
|
|
251
|
-
targetPropertyChain,
|
|
252
|
-
options,
|
|
253
|
-
sourceObject
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
// bind the property
|
|
257
|
-
listenerIds[i] = this.__bindEventToProperty(
|
|
258
|
-
source,
|
|
259
|
-
eventNames[i],
|
|
260
|
-
targetObject,
|
|
261
|
-
targetPropertyChain,
|
|
262
|
-
options
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// if its not the last property
|
|
267
|
-
} else {
|
|
268
|
-
// create the context for the listener
|
|
269
|
-
var context = {
|
|
270
|
-
index: i,
|
|
271
|
-
propertyNames: propertyNames,
|
|
272
|
-
sources: sources,
|
|
273
|
-
listenerIds: listenerIds,
|
|
274
|
-
arrayIndexValues: arrayIndexValues,
|
|
275
|
-
targetObject: targetObject,
|
|
276
|
-
targetPropertyChain: targetPropertyChain,
|
|
277
|
-
options: options,
|
|
278
|
-
listeners: listeners
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
// create a listener
|
|
282
|
-
var listener = qx.lang.Function.bind(
|
|
283
|
-
this.__chainListener,
|
|
284
|
-
this,
|
|
285
|
-
context
|
|
286
|
-
);
|
|
181
|
+
/**
|
|
182
|
+
* @type {BindingRecord?}
|
|
183
|
+
*/
|
|
184
|
+
__record: null,
|
|
287
185
|
|
|
288
|
-
|
|
289
|
-
|
|
186
|
+
/**
|
|
187
|
+
* @type {qx.core.Object}
|
|
188
|
+
*/
|
|
189
|
+
__target: null,
|
|
290
190
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
191
|
+
/** @type {Promise} initialisation promise */
|
|
192
|
+
__initPromise: null,
|
|
294
193
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
source["get" + qx.lang.String.firstUp(propertyNames[i])] == null
|
|
298
|
-
) {
|
|
299
|
-
source = undefined;
|
|
300
|
-
} else if (arrayIndexValues[i] !== "") {
|
|
301
|
-
var itemIndex =
|
|
302
|
-
arrayIndexValues[i] === "last"
|
|
303
|
-
? source.length - 1
|
|
304
|
-
: arrayIndexValues[i];
|
|
305
|
-
source =
|
|
306
|
-
source["get" + qx.lang.String.firstUp(propertyNames[i])](
|
|
307
|
-
itemIndex
|
|
308
|
-
);
|
|
309
|
-
} else {
|
|
310
|
-
source = source["get" + qx.lang.String.firstUp(propertyNames[i])]();
|
|
311
|
-
// the value should be undefined if we can not find the last part of the property chain
|
|
312
|
-
if (source === null && propertyNames.length - 1 != i) {
|
|
313
|
-
source = undefined;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
if (!source) {
|
|
317
|
-
// call the converter if no source could be found on binding creation
|
|
318
|
-
this.__setInitialValue(
|
|
319
|
-
source,
|
|
320
|
-
targetObject,
|
|
321
|
-
targetPropertyChain,
|
|
322
|
-
options,
|
|
323
|
-
sourceObject
|
|
324
|
-
);
|
|
194
|
+
/** @type {qx.data.binding.AbstractSegment[]?} list of segments of the source path */
|
|
195
|
+
__sourceSegments: null,
|
|
325
196
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
} catch (ex) {
|
|
330
|
-
// remove the already added listener
|
|
331
|
-
// go through all added listeners (source)
|
|
332
|
-
|
|
333
|
-
for (var i = 0; i < sources.length; i++) {
|
|
334
|
-
// check if a source is available
|
|
335
|
-
if (sources[i] && listenerIds[i]) {
|
|
336
|
-
sources[i].removeListenerById(listenerIds[i]);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
var targets = targetListenerMap.targets;
|
|
340
|
-
var targetIds = targetListenerMap.listenerIds;
|
|
341
|
-
// go through all added listeners (target)
|
|
342
|
-
for (var i = 0; i < targets.length; i++) {
|
|
343
|
-
// check if a target is available
|
|
344
|
-
if (targets[i] && targetIds[i]) {
|
|
345
|
-
targets[i].removeListenerById(targetIds[i]);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
197
|
+
/** @type {qx.data.binding.AbstractSegment[]?} list of segments of the target path */
|
|
198
|
+
__targetSegments: null,
|
|
348
199
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
var id = {
|
|
354
|
-
type: "deepBinding",
|
|
355
|
-
listenerIds: listenerIds,
|
|
356
|
-
sources: sources,
|
|
357
|
-
targetListenerIds: targetListenerMap.listenerIds,
|
|
358
|
-
targets: targetListenerMap.targets,
|
|
359
|
-
initialPromise: initialPromise
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
// store the bindings
|
|
363
|
-
this.__storeBinding(
|
|
364
|
-
id,
|
|
365
|
-
sourceObject,
|
|
366
|
-
sourcePropertyChain,
|
|
367
|
-
targetObject,
|
|
368
|
-
targetPropertyChain
|
|
369
|
-
);
|
|
200
|
+
/**
|
|
201
|
+
* @type {BindingOptions}
|
|
202
|
+
*/
|
|
203
|
+
__options: null,
|
|
370
204
|
|
|
371
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Promises/A+ thenable compliance, this means that you can await the binding for initialisation
|
|
207
|
+
* https://promisesaplus.com/
|
|
208
|
+
* @returns {Promise} the promise
|
|
209
|
+
*/
|
|
210
|
+
then(onFulfilled, onRejected) {
|
|
211
|
+
return Promise.resolve(this.__initPromise).then(onFulfilled, onRejected);
|
|
372
212
|
},
|
|
373
213
|
|
|
374
214
|
/**
|
|
375
|
-
* Event listener for the chaining of the properties.
|
|
376
215
|
*
|
|
377
|
-
* @
|
|
216
|
+
* @returns {BindingRecord} The representation of this binding as record.
|
|
378
217
|
*/
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
context.options.onUpdate(
|
|
383
|
-
context.sources[context.index],
|
|
384
|
-
context.targetObject
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// delete all listener after the current one
|
|
389
|
-
for (var j = context.index + 1; j < context.propertyNames.length; j++) {
|
|
390
|
-
// remove the old sources
|
|
391
|
-
var source = context.sources[j];
|
|
392
|
-
context.sources[j] = null;
|
|
393
|
-
if (!source) {
|
|
394
|
-
continue;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// remove the listeners
|
|
398
|
-
source.removeListenerById(context.listenerIds[j]);
|
|
218
|
+
asRecord() {
|
|
219
|
+
if (!this.__record) {
|
|
220
|
+
this.__record = [this, this.getSource(), this.getSourcePath(), this.getTarget(), this.getTargetPath()];
|
|
399
221
|
}
|
|
222
|
+
return this.__record;
|
|
223
|
+
},
|
|
400
224
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
source = source[
|
|
408
|
-
"get" + qx.lang.String.firstUp(context.propertyNames[j - 1])
|
|
409
|
-
](context.arrayIndexValues[j - 1]);
|
|
410
|
-
} else {
|
|
411
|
-
source =
|
|
412
|
-
source[
|
|
413
|
-
"get" + qx.lang.String.firstUp(context.propertyNames[j - 1])
|
|
414
|
-
]();
|
|
415
|
-
}
|
|
416
|
-
context.sources[j] = source;
|
|
417
|
-
// reset the target object if no new source could be found
|
|
418
|
-
if (!source) {
|
|
419
|
-
// use the converter if the property chain breaks [BUG# 6880]
|
|
420
|
-
if (context.options && context.options.converter) {
|
|
421
|
-
var ignoreConverter = false;
|
|
422
|
-
// take care of the ignore pattern used for the controller
|
|
423
|
-
if (context.options.ignoreConverter) {
|
|
424
|
-
// the current property chain as string
|
|
425
|
-
var currentSourceChain = context.propertyNames
|
|
426
|
-
.slice(0, j)
|
|
427
|
-
.join(".");
|
|
428
|
-
// match for the current pattern given in the options
|
|
429
|
-
var match = currentSourceChain.match(
|
|
430
|
-
new RegExp("^" + context.options.ignoreConverter)
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
ignoreConverter = match ? match.length > 0 : false;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (!ignoreConverter) {
|
|
437
|
-
this.__setTargetValue(
|
|
438
|
-
context.targetObject,
|
|
439
|
-
context.targetPropertyChain,
|
|
440
|
-
context.options.converter()
|
|
441
|
-
);
|
|
442
|
-
} else {
|
|
443
|
-
this.__resetTargetValue(
|
|
444
|
-
context.targetObject,
|
|
445
|
-
context.targetPropertyChain
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
} else {
|
|
449
|
-
this.__resetTargetValue(
|
|
450
|
-
context.targetObject,
|
|
451
|
-
context.targetPropertyChain
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
break;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// if its the last property
|
|
459
|
-
if (j == context.propertyNames.length - 1) {
|
|
460
|
-
// if its an array
|
|
461
|
-
if (
|
|
462
|
-
qx.Class.implementsInterface(source, qx.data.IListData) &&
|
|
463
|
-
context.arrayIndexValues[j] !== ""
|
|
464
|
-
) {
|
|
465
|
-
// set the initial value
|
|
466
|
-
var itemIndex =
|
|
467
|
-
context.arrayIndexValues[j] === "last"
|
|
468
|
-
? source.length - 1
|
|
469
|
-
: context.arrayIndexValues[j];
|
|
470
|
-
var currentValue = source.getItem(itemIndex);
|
|
471
|
-
this.__setInitialValue(
|
|
472
|
-
currentValue,
|
|
473
|
-
context.targetObject,
|
|
474
|
-
context.targetPropertyChain,
|
|
475
|
-
context.options,
|
|
476
|
-
context.sources[context.index]
|
|
477
|
-
);
|
|
478
|
-
|
|
479
|
-
// bind the item event to the new target
|
|
480
|
-
context.listenerIds[j] = this.__bindEventToProperty(
|
|
481
|
-
source,
|
|
482
|
-
"change",
|
|
483
|
-
context.targetObject,
|
|
484
|
-
context.targetPropertyChain,
|
|
485
|
-
context.options,
|
|
486
|
-
context.arrayIndexValues[j]
|
|
487
|
-
);
|
|
488
|
-
} else {
|
|
489
|
-
if (
|
|
490
|
-
context.propertyNames[j] != null &&
|
|
491
|
-
source[
|
|
492
|
-
"get" + qx.lang.String.firstUp(context.propertyNames[j])
|
|
493
|
-
] != null
|
|
494
|
-
) {
|
|
495
|
-
var currentValue =
|
|
496
|
-
source[
|
|
497
|
-
"get" + qx.lang.String.firstUp(context.propertyNames[j])
|
|
498
|
-
]();
|
|
499
|
-
|
|
500
|
-
this.__setInitialValue(
|
|
501
|
-
currentValue,
|
|
502
|
-
context.targetObject,
|
|
503
|
-
context.targetPropertyChain,
|
|
504
|
-
context.options,
|
|
505
|
-
context.sources[context.index]
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
var eventName = this.__getEventNameForProperty(
|
|
509
|
-
source,
|
|
510
|
-
context.propertyNames[j]
|
|
511
|
-
);
|
|
512
|
-
|
|
513
|
-
if (!eventName) {
|
|
514
|
-
context.sources[j] = null;
|
|
515
|
-
this.__resetTargetValue(
|
|
516
|
-
context.targetObject,
|
|
517
|
-
context.targetPropertyChain
|
|
518
|
-
);
|
|
519
|
-
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
// bind the last property to the new target
|
|
523
|
-
context.listenerIds[j] = this.__bindEventToProperty(
|
|
524
|
-
source,
|
|
525
|
-
eventName,
|
|
526
|
-
context.targetObject,
|
|
527
|
-
context.targetPropertyChain,
|
|
528
|
-
context.options
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
} else {
|
|
532
|
-
// check if a listener already created
|
|
533
|
-
if (context.listeners[j] == null) {
|
|
534
|
-
var listener = qx.lang.Function.bind(
|
|
535
|
-
this.__chainListener,
|
|
536
|
-
this,
|
|
537
|
-
context
|
|
538
|
-
);
|
|
539
|
-
|
|
540
|
-
// store the listener for further processing
|
|
541
|
-
context.listeners.push(listener);
|
|
542
|
-
}
|
|
543
|
-
// add a new listener
|
|
544
|
-
if (qx.Class.implementsInterface(source, qx.data.IListData)) {
|
|
545
|
-
var eventName = "change";
|
|
546
|
-
} else {
|
|
547
|
-
var eventName = this.__getEventNameForProperty(
|
|
548
|
-
source,
|
|
549
|
-
context.propertyNames[j]
|
|
550
|
-
);
|
|
551
|
-
}
|
|
225
|
+
/**
|
|
226
|
+
* @override
|
|
227
|
+
*/
|
|
228
|
+
toString() {
|
|
229
|
+
return `${super.toString()}: ${this.getSource()}.${this.getSourcePath()} -> ${this.getTarget()}.${this.getTargetPath()}`;
|
|
230
|
+
},
|
|
552
231
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
232
|
+
/**
|
|
233
|
+
*
|
|
234
|
+
* @returns {Promise} A promise which resolves when the initial value has been copied over from source to target
|
|
235
|
+
*/
|
|
236
|
+
getInitPromise() {
|
|
237
|
+
return this.__initPromise;
|
|
238
|
+
},
|
|
559
239
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Apply for `sourcePath`
|
|
242
|
+
*/
|
|
243
|
+
_applySourcePath(value, oldValue) {
|
|
244
|
+
if (oldValue) {
|
|
245
|
+
throw new Error("Cannot change sourcePath after binding has been created");
|
|
246
|
+
}
|
|
247
|
+
this.__record = null; // invalidate record representation cache
|
|
248
|
+
this.__sourceSegments = qx.data.SingleValueBinding.__parseSegments(this, value);
|
|
249
|
+
let lastSegment = this.__sourceSegments.at(-1);
|
|
250
|
+
lastSegment.setOutputReceiver(this);
|
|
568
251
|
},
|
|
569
252
|
|
|
570
253
|
/**
|
|
571
|
-
*
|
|
572
|
-
* target
|
|
573
|
-
* property chain
|
|
254
|
+
* Sets the source object of this binding.
|
|
255
|
+
* If a target is set, the target will be updated with source's value.
|
|
574
256
|
*
|
|
575
|
-
* @param
|
|
576
|
-
* @
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
* be bind to.
|
|
580
|
-
* @param targetPropertyChain {String} The property name of the target
|
|
581
|
-
* object.
|
|
582
|
-
* @param options {Map} The options map perhaps containing the user defined
|
|
583
|
-
* converter.
|
|
584
|
-
* @return {var} A map containing the listener ids and the targets.
|
|
257
|
+
* @param {qx.core.Object?} value The source object to get the `value` by looking up `sourcePath`
|
|
258
|
+
* @returns {Promise?} A promise if any stage of the process was asynchronous, i.e. we had to get a property asynchronously along the source/target path,
|
|
259
|
+
* or setting the target was asynchronous.
|
|
260
|
+
* If everything was synchronous, then this will return null.
|
|
585
261
|
*/
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
// go through all property names
|
|
604
|
-
for (var i = 0; i < propertyNames.length - 1; i++) {
|
|
605
|
-
// check for the array
|
|
606
|
-
if (arrayIndexValues[i] !== "") {
|
|
607
|
-
// push the array change event
|
|
608
|
-
eventNames.push("change");
|
|
609
|
-
} else {
|
|
610
|
-
var eventName = this.__getEventNameForProperty(
|
|
611
|
-
target,
|
|
612
|
-
propertyNames[i]
|
|
613
|
-
);
|
|
614
|
-
|
|
615
|
-
if (!eventName) {
|
|
616
|
-
// if the event names could not be terminated,
|
|
617
|
-
// just ignore the target chain listening
|
|
618
|
-
break;
|
|
619
|
-
}
|
|
620
|
-
eventNames.push(eventName);
|
|
262
|
+
setSource(value) {
|
|
263
|
+
const SingleValueBinding = qx.data.SingleValueBinding;
|
|
264
|
+
if (this.__source === value) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
this.__record = null; // invalidate record representation cache
|
|
269
|
+
let oldValue = this.__source;
|
|
270
|
+
this.__source = value;
|
|
271
|
+
this.__initPromise = null; // reset the init promise, as the source has changed
|
|
272
|
+
|
|
273
|
+
if (oldValue) {
|
|
274
|
+
//Delete old source's bindings if there was one
|
|
275
|
+
delete SingleValueBinding.__bindingsBySource[oldValue.toHashCode()][this.toHashCode()];
|
|
276
|
+
if (qx.lang.Object.isEmpty(SingleValueBinding.__bindingsBySource[oldValue.toHashCode()])) {
|
|
277
|
+
delete SingleValueBinding.__bindingsBySource[oldValue.toHashCode()];
|
|
621
278
|
}
|
|
279
|
+
}
|
|
622
280
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
var listener = function () {
|
|
628
|
-
// delete all listener after the current one
|
|
629
|
-
for (var j = i + 1; j < propertyNames.length - 1; j++) {
|
|
630
|
-
// remove the old sources
|
|
631
|
-
var target = targets[j];
|
|
632
|
-
targets[j] = null;
|
|
633
|
-
if (!target) {
|
|
634
|
-
continue;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// remove the listeners
|
|
638
|
-
target.removeListenerById(listenerIds[j]);
|
|
639
|
-
}
|
|
281
|
+
if (value) {
|
|
282
|
+
//Store the binding
|
|
283
|
+
SingleValueBinding.__bindingsBySource[value.toHashCode()] ??= {};
|
|
284
|
+
SingleValueBinding.__bindingsBySource[value.toHashCode()][this.toHashCode()] = this;
|
|
640
285
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
arrayIndexValues[j - 1] === "last"
|
|
650
|
-
? target.getLength() - 1
|
|
651
|
-
: arrayIndexValues[j - 1];
|
|
652
|
-
target = target["get" + firstUpPropName](currentIndex);
|
|
653
|
-
} else {
|
|
654
|
-
target = target["get" + firstUpPropName]();
|
|
655
|
-
}
|
|
656
|
-
targets[j] = target;
|
|
657
|
-
if (!target) {
|
|
658
|
-
break;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// check if a listener already created
|
|
662
|
-
if (listeners[j] == null) {
|
|
663
|
-
// store the listener for further processing
|
|
664
|
-
listeners.push(listener);
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// add a new listener
|
|
668
|
-
if (qx.Class.implementsInterface(target, qx.data.IListData)) {
|
|
669
|
-
var eventName = "change";
|
|
670
|
-
} else {
|
|
671
|
-
var eventName =
|
|
672
|
-
qx.data.SingleValueBinding.__getEventNameForProperty(
|
|
673
|
-
target,
|
|
674
|
-
propertyNames[j]
|
|
675
|
-
);
|
|
676
|
-
|
|
677
|
-
if (!eventName) {
|
|
678
|
-
// if the event name could not be terminated,
|
|
679
|
-
// ignore the rest
|
|
680
|
-
break;
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
listenerIds[j] = target.addListener(eventName, listeners[j]);
|
|
286
|
+
//Set the input on the first segment of the source path
|
|
287
|
+
let out = this.__sourceSegments[0].setInput(value);
|
|
288
|
+
const cb = () => {
|
|
289
|
+
if (qx.core.Environment.get("qx.debug")) {
|
|
290
|
+
this.assertNotNull(
|
|
291
|
+
this.__sourceSegments[0].getEventName(),
|
|
292
|
+
`Binding property ${this.__sourceSegments[0].toString()} of object ${value.classname} not possible. No event available.`
|
|
293
|
+
);
|
|
685
294
|
}
|
|
686
|
-
|
|
687
|
-
qx.data.SingleValueBinding.updateTarget(
|
|
688
|
-
sourceObject,
|
|
689
|
-
sourcePropertyChain,
|
|
690
|
-
targetObject,
|
|
691
|
-
targetPropertyChain,
|
|
692
|
-
options
|
|
693
|
-
);
|
|
694
295
|
};
|
|
695
296
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
// add the chaining listener
|
|
700
|
-
listenerIds[i] = target.addListener(eventNames[i], listener);
|
|
701
|
-
|
|
702
|
-
var firstUpPropName = qx.lang.String.firstUp(propertyNames[i]);
|
|
703
|
-
// get and store the next target
|
|
704
|
-
if (target["get" + firstUpPropName] == null) {
|
|
705
|
-
target = null;
|
|
706
|
-
} else if (arrayIndexValues[i] !== "") {
|
|
707
|
-
target = target["get" + firstUpPropName](arrayIndexValues[i]);
|
|
297
|
+
if (qx.Promise.isPromise(out)) {
|
|
298
|
+
out = out.then(cb);
|
|
708
299
|
} else {
|
|
709
|
-
|
|
710
|
-
}
|
|
711
|
-
if (!target) {
|
|
712
|
-
break;
|
|
300
|
+
out = cb();
|
|
713
301
|
}
|
|
302
|
+
this.__initPromise = Promise.resolve(out);
|
|
303
|
+
return out;
|
|
714
304
|
}
|
|
715
|
-
|
|
716
|
-
return { listenerIds: listenerIds, targets: targets };
|
|
717
305
|
},
|
|
718
306
|
|
|
719
307
|
/**
|
|
720
|
-
*
|
|
721
|
-
* and set that on the target.
|
|
722
|
-
*
|
|
723
|
-
* @param sourceObject {qx.core.Object} The source of the binding.
|
|
724
|
-
* @param sourcePropertyChain {String} The property chain which represents
|
|
725
|
-
* the source property.
|
|
726
|
-
* @param targetObject {qx.core.Object} The object which the source should
|
|
727
|
-
* be bind to.
|
|
728
|
-
* @param targetPropertyChain {String} The property name of the target
|
|
729
|
-
* object.
|
|
730
|
-
* @param options {Map} The options map perhaps containing the user defined
|
|
731
|
-
* converter.
|
|
732
|
-
*
|
|
733
|
-
* @internal
|
|
308
|
+
* @returns {qx.core.Object} the source object
|
|
734
309
|
*/
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
sourcePropertyChain,
|
|
738
|
-
targetObject,
|
|
739
|
-
targetPropertyChain,
|
|
740
|
-
options
|
|
741
|
-
) {
|
|
742
|
-
var value = this.resolvePropertyChain(sourceObject, sourcePropertyChain);
|
|
743
|
-
|
|
744
|
-
// convert the data before setting
|
|
745
|
-
value = qx.data.SingleValueBinding.__convertValue(
|
|
746
|
-
value,
|
|
747
|
-
targetObject,
|
|
748
|
-
targetPropertyChain,
|
|
749
|
-
options,
|
|
750
|
-
sourceObject
|
|
751
|
-
);
|
|
752
|
-
|
|
753
|
-
this.__setTargetValue(targetObject, targetPropertyChain, value);
|
|
310
|
+
getSource() {
|
|
311
|
+
return this.__source;
|
|
754
312
|
},
|
|
755
313
|
|
|
756
314
|
/**
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
* @param o {qx.core.Object} The source of the binding.
|
|
760
|
-
* @param propertyChain {String} The property chain which represents
|
|
761
|
-
* the source property.
|
|
762
|
-
* @return {var?undefined} Returns the set value if defined.
|
|
315
|
+
* Apply for `targetPath`
|
|
763
316
|
*/
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
317
|
+
_applyTargetPath(value, oldValue) {
|
|
318
|
+
if (oldValue) {
|
|
319
|
+
throw new Error("Cannot change targetPath after binding has been created");
|
|
320
|
+
}
|
|
321
|
+
this.__record = null; // invalidate record representation cache
|
|
322
|
+
this.__targetSegments = qx.data.SingleValueBinding.__parseSegments(this, value);
|
|
323
|
+
this.__targetSegments.at(-1).addListener("changeInput", this.__updateTarget, this);
|
|
767
324
|
},
|
|
768
325
|
|
|
769
326
|
/**
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
* and therefore it checks the property definition for the event. The second
|
|
773
|
-
* possibility is to check if there is an event with the given name. The
|
|
774
|
-
* third and last possibility checked is if there is an event which is named
|
|
775
|
-
* change + propertyName. If this three possibilities fail, an error will be
|
|
776
|
-
* thrown.
|
|
327
|
+
* Sets the target object of this binding.
|
|
328
|
+
* If a source is set, the target will be updated with source's value.
|
|
777
329
|
*
|
|
778
|
-
* @param
|
|
779
|
-
* @
|
|
780
|
-
*
|
|
330
|
+
* @param {qx.core.Object?} value The source object to get the `value` by looking up `sourcePath`
|
|
331
|
+
* @returns {Promise?} A promise if any stage of the process was asynchronous, i.e. we had to get a property asynchronously along the source/target path,
|
|
332
|
+
* or setting the target was asynchronous.
|
|
333
|
+
* If everything was synchronous, then this will return null.
|
|
781
334
|
*/
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
// if no event name could be found
|
|
786
|
-
if (eventName == null) {
|
|
787
|
-
// check if the propertyName is the event name
|
|
788
|
-
if (qx.Class.supportsEvent(source.constructor, propertyName)) {
|
|
789
|
-
eventName = propertyName;
|
|
790
|
-
// check if the change + propertyName is the event name
|
|
791
|
-
} else if (
|
|
792
|
-
qx.Class.supportsEvent(
|
|
793
|
-
source.constructor,
|
|
794
|
-
"change" + qx.lang.String.firstUp(propertyName)
|
|
795
|
-
)
|
|
796
|
-
) {
|
|
797
|
-
eventName = "change" + qx.lang.String.firstUp(propertyName);
|
|
798
|
-
} else {
|
|
799
|
-
return null;
|
|
800
|
-
}
|
|
335
|
+
setTarget(value) {
|
|
336
|
+
if (this.__target === value) {
|
|
337
|
+
return;
|
|
801
338
|
}
|
|
802
|
-
return eventName;
|
|
803
|
-
},
|
|
804
339
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
* starts.
|
|
811
|
-
* @param targetPropertyChain {String} The names of the properties,
|
|
812
|
-
* separated with a dot.
|
|
813
|
-
*/
|
|
814
|
-
__resetTargetValue(targetObject, targetPropertyChain) {
|
|
815
|
-
// get the last target object of the chain
|
|
816
|
-
var properties = this.__getPropertyChainArray(targetPropertyChain);
|
|
817
|
-
var target = this.__getTargetFromChain(targetObject, properties);
|
|
818
|
-
if (target != null) {
|
|
819
|
-
// get the name of the last property
|
|
820
|
-
var lastProperty = properties[properties.length - 1];
|
|
821
|
-
// check for an array and set the value to null
|
|
822
|
-
var index = this.__getArrayIndex(lastProperty);
|
|
823
|
-
if (index) {
|
|
824
|
-
this.__setTargetValue(targetObject, targetPropertyChain, null);
|
|
825
|
-
return;
|
|
826
|
-
}
|
|
340
|
+
this.__record = null; // invalidate record representation cache
|
|
341
|
+
this.__initPromise = null; // reset the init promise, as the target has changed
|
|
342
|
+
let oldValue = this.__target;
|
|
343
|
+
this.__target = value;
|
|
344
|
+
const SingleValueBinding = qx.data.SingleValueBinding;
|
|
827
345
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
target["reset" + qx.lang.String.firstUp(lastProperty)]();
|
|
833
|
-
} else {
|
|
834
|
-
// fallback if no resetter is given (see bug #2456)
|
|
835
|
-
if (
|
|
836
|
-
typeof target["set" + qx.lang.String.firstUp(lastProperty)] !=
|
|
837
|
-
"function"
|
|
838
|
-
) {
|
|
839
|
-
throw new qx.core.AssertionError(
|
|
840
|
-
"No setter for '" + lastProperty + "' on target " + target + "."
|
|
841
|
-
);
|
|
842
|
-
}
|
|
843
|
-
target["set" + qx.lang.String.firstUp(lastProperty)](null);
|
|
346
|
+
if (oldValue) {
|
|
347
|
+
delete SingleValueBinding.__bindingsByTarget[oldValue.toHashCode()][this.toHashCode()];
|
|
348
|
+
if (qx.lang.Object.isEmpty(SingleValueBinding.__bindingsByTarget[oldValue.toHashCode()])) {
|
|
349
|
+
delete SingleValueBinding.__bindingsByTarget[oldValue.toHashCode()];
|
|
844
350
|
}
|
|
845
351
|
}
|
|
846
|
-
},
|
|
847
352
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
* @param value {var} The value to set.
|
|
857
|
-
*/
|
|
858
|
-
__setTargetValue(targetObject, targetPropertyChain, value) {
|
|
859
|
-
// get the last target object of the chain
|
|
860
|
-
var properties = this.__getPropertyChainArray(targetPropertyChain);
|
|
861
|
-
var target = this.__getTargetFromChain(targetObject, properties);
|
|
862
|
-
if (target) {
|
|
863
|
-
// get the name of the last property
|
|
864
|
-
var lastProperty = properties[properties.length - 1];
|
|
865
|
-
|
|
866
|
-
// check for array notation
|
|
867
|
-
var index = this.__getArrayIndex(lastProperty);
|
|
868
|
-
if (index) {
|
|
869
|
-
if (index === "last") {
|
|
870
|
-
// check for the 'last' notation
|
|
871
|
-
index = target.length - 1;
|
|
872
|
-
}
|
|
873
|
-
target.setItem(index, value);
|
|
874
|
-
} else {
|
|
875
|
-
if (
|
|
876
|
-
typeof target["set" + qx.lang.String.firstUp(lastProperty)] !=
|
|
877
|
-
"function"
|
|
878
|
-
) {
|
|
879
|
-
throw new qx.core.AssertionError(
|
|
880
|
-
"No setter for '" + lastProperty + "' on target " + target + "."
|
|
881
|
-
);
|
|
882
|
-
}
|
|
883
|
-
return target["set" + qx.lang.String.firstUp(lastProperty)](value);
|
|
884
|
-
}
|
|
353
|
+
if (value) {
|
|
354
|
+
const SingleValueBinding = qx.data.SingleValueBinding;
|
|
355
|
+
SingleValueBinding.__bindingsByTarget[value.toHashCode()] ??= {};
|
|
356
|
+
SingleValueBinding.__bindingsByTarget[value.toHashCode()][this.toHashCode()] = this;
|
|
357
|
+
|
|
358
|
+
let out = this.__targetSegments[0].setInput(value);
|
|
359
|
+
this.__initPromise = Promise.resolve(out);
|
|
360
|
+
return out;
|
|
885
361
|
}
|
|
886
362
|
},
|
|
887
363
|
|
|
888
364
|
/**
|
|
889
|
-
* Returns the index from a property using bracket notation, e.g.
|
|
890
|
-
* "[42]" returns "42", "[last]" returns "last"
|
|
891
365
|
*
|
|
892
|
-
* @
|
|
893
|
-
* @return {String|null} Array index or null if the property name does
|
|
894
|
-
* not use bracket notation
|
|
366
|
+
* @returns {qx.core.Object} the target object
|
|
895
367
|
*/
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
var arrayMatch = propertyName.match(arrayExp);
|
|
899
|
-
if (arrayMatch) {
|
|
900
|
-
return arrayMatch[1];
|
|
901
|
-
}
|
|
902
|
-
return null;
|
|
368
|
+
getTarget() {
|
|
369
|
+
return this.__target;
|
|
903
370
|
},
|
|
904
371
|
|
|
905
372
|
/**
|
|
906
|
-
*
|
|
907
|
-
*
|
|
908
|
-
* @
|
|
909
|
-
*
|
|
373
|
+
* This method should not be called directly.
|
|
374
|
+
* It is only there to comply with interface `qx.data.binding.IInputReceiver`.
|
|
375
|
+
* @override interface qx.data.binding.IInputReceiver
|
|
376
|
+
*
|
|
377
|
+
* @param {*} input
|
|
910
378
|
*/
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
return targetPropertyChain
|
|
914
|
-
.replace(/\[/g, ".[")
|
|
915
|
-
.split(".")
|
|
916
|
-
.filter(function (prop) {
|
|
917
|
-
return prop !== "";
|
|
918
|
-
});
|
|
379
|
+
setInput(input) {
|
|
380
|
+
return this.__setValue(input);
|
|
919
381
|
},
|
|
920
382
|
|
|
921
383
|
/**
|
|
922
|
-
* Helper-Function resolving the object on which the last property of the
|
|
923
|
-
* chain should be set.
|
|
924
384
|
*
|
|
925
|
-
* @param
|
|
926
|
-
*
|
|
927
|
-
* @param targetProperties {String[]} Array containing the names of the properties
|
|
928
|
-
* @param index {Number?} The array index of the last property to be considered.
|
|
929
|
-
* Default: The last item's index
|
|
930
|
-
* @return {qx.core.Object|null} The object on which the last property
|
|
931
|
-
* should be set.
|
|
385
|
+
* @param {*} value The final value obtained from the sourcePath
|
|
386
|
+
* @returns {Promise?} A promise if setting the target is asynchronous, otherwise null
|
|
932
387
|
*/
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
for (var i = 0; target !== null && i < index; i++) {
|
|
938
|
-
try {
|
|
939
|
-
var property = targetProperties[i];
|
|
940
|
-
|
|
941
|
-
// array notation
|
|
942
|
-
var arrIndex = this.__getArrayIndex(property);
|
|
943
|
-
if (arrIndex) {
|
|
944
|
-
if (arrIndex === "last") {
|
|
945
|
-
// check for the 'last' notation
|
|
946
|
-
arrIndex = target.length - 1;
|
|
947
|
-
}
|
|
948
|
-
target = target.getItem(arrIndex);
|
|
949
|
-
} else {
|
|
950
|
-
target = target["get" + qx.lang.String.firstUp(property)]();
|
|
951
|
-
}
|
|
952
|
-
} catch (ex) {
|
|
953
|
-
return null;
|
|
954
|
-
}
|
|
388
|
+
__setValue(value) {
|
|
389
|
+
if (this.__value === value) {
|
|
390
|
+
return null; // no change
|
|
955
391
|
}
|
|
956
|
-
|
|
392
|
+
this.__value = value;
|
|
393
|
+
return this.__updateTarget();
|
|
957
394
|
},
|
|
958
395
|
|
|
959
396
|
/**
|
|
960
|
-
* Set the given value to the target property. This method is used for
|
|
961
|
-
* initially set the value.
|
|
962
397
|
*
|
|
963
|
-
* @
|
|
964
|
-
* @param targetObject {qx.core.Object} The object which contains the target
|
|
965
|
-
* property.
|
|
966
|
-
* @param targetPropertyChain {String} The name of the target property in the
|
|
967
|
-
* target object.
|
|
968
|
-
* @param options {Map} The options map perhaps containing the user defined
|
|
969
|
-
* converter.
|
|
970
|
-
* @param sourceObject {qx.core.Object} The source object of the binding (
|
|
971
|
-
* used for the onUpdate callback).
|
|
398
|
+
* @returns {*} the value that was set by the sourcePath
|
|
972
399
|
*/
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
targetObject,
|
|
976
|
-
targetPropertyChain,
|
|
977
|
-
options,
|
|
978
|
-
sourceObject
|
|
979
|
-
) {
|
|
980
|
-
// first convert the initial value
|
|
981
|
-
value = this.__convertValue(
|
|
982
|
-
value,
|
|
983
|
-
targetObject,
|
|
984
|
-
targetPropertyChain,
|
|
985
|
-
options,
|
|
986
|
-
sourceObject
|
|
987
|
-
);
|
|
988
|
-
|
|
989
|
-
// check if the converted value is undefined
|
|
990
|
-
if (value === undefined) {
|
|
991
|
-
this.__resetTargetValue(targetObject, targetPropertyChain);
|
|
992
|
-
}
|
|
993
|
-
// only set the initial value if one is given (may be null)
|
|
994
|
-
if (value !== undefined) {
|
|
995
|
-
try {
|
|
996
|
-
var result = this.__setTargetValue(
|
|
997
|
-
targetObject,
|
|
998
|
-
targetPropertyChain,
|
|
999
|
-
value
|
|
1000
|
-
);
|
|
1001
|
-
|
|
1002
|
-
// tell the user that the setter was invoked probably
|
|
1003
|
-
if (options && options.onUpdate) {
|
|
1004
|
-
options.onUpdate(sourceObject, targetObject, value);
|
|
1005
|
-
}
|
|
1006
|
-
return result;
|
|
1007
|
-
} catch (e) {
|
|
1008
|
-
if (!(e instanceof qx.core.ValidationError)) {
|
|
1009
|
-
throw e;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
if (options && options.onSetFail) {
|
|
1013
|
-
options.onSetFail(e);
|
|
1014
|
-
} else {
|
|
1015
|
-
qx.log.Logger.warn(
|
|
1016
|
-
"Failed so set value " +
|
|
1017
|
-
value +
|
|
1018
|
-
" on " +
|
|
1019
|
-
targetObject +
|
|
1020
|
-
". Error message: " +
|
|
1021
|
-
e
|
|
1022
|
-
);
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
400
|
+
getValue() {
|
|
401
|
+
return this.__value;
|
|
1026
402
|
},
|
|
1027
403
|
|
|
1028
404
|
/**
|
|
1029
|
-
*
|
|
1030
|
-
* arrays to fit the algorithm.
|
|
1031
|
-
*
|
|
1032
|
-
* @param propertyNames {Array} The array containing the property names.
|
|
1033
|
-
* Attention, this method can change this parameter!!!
|
|
1034
|
-
* @return {Array} An array containing the values of the array properties
|
|
1035
|
-
* corresponding to the property names.
|
|
405
|
+
* Updates the target with the current value
|
|
1036
406
|
*/
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
if (name.endsWith("]")) {
|
|
1046
|
-
// get the inner value of the array notation
|
|
1047
|
-
var arrayIndex = name.substring(
|
|
1048
|
-
name.indexOf("[") + 1,
|
|
1049
|
-
name.indexOf("]")
|
|
1050
|
-
);
|
|
1051
|
-
|
|
1052
|
-
// check the arrayIndex
|
|
1053
|
-
if (name.indexOf("]") != name.length - 1) {
|
|
1054
|
-
throw new Error(
|
|
1055
|
-
"Please use only one array at a time: " + name + " does not work."
|
|
1056
|
-
);
|
|
407
|
+
__updateTarget() {
|
|
408
|
+
if (this.__targetSegments) {
|
|
409
|
+
//We need to make sure the target segments are up to date
|
|
410
|
+
//because the listeners may trigger after this point.
|
|
411
|
+
//This is important in bidirectional bindings.
|
|
412
|
+
for (let segment of this.__targetSegments) {
|
|
413
|
+
if (segment.getOutputReceiver()) {
|
|
414
|
+
segment.updateOutput();
|
|
1057
415
|
}
|
|
1058
|
-
if (arrayIndex !== "last") {
|
|
1059
|
-
if (arrayIndex == "" || isNaN(parseInt(arrayIndex, 10))) {
|
|
1060
|
-
throw new Error(
|
|
1061
|
-
"No number or 'last' value has been given" +
|
|
1062
|
-
" in an array binding: " +
|
|
1063
|
-
name +
|
|
1064
|
-
" does not work."
|
|
1065
|
-
);
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
// if a property is in front of the array notation
|
|
1070
|
-
if (name.indexOf("[") != 0) {
|
|
1071
|
-
// store the property name without the array notation
|
|
1072
|
-
propertyNames[i] = name.substring(0, name.indexOf("["));
|
|
1073
|
-
// store the values in the array for the current iteration
|
|
1074
|
-
arrayIndexValues[i] = "";
|
|
1075
|
-
// store the properties for the next iteration (the item of the array)
|
|
1076
|
-
arrayIndexValues[i + 1] = arrayIndex;
|
|
1077
|
-
propertyNames.splice(i + 1, 0, "item");
|
|
1078
|
-
// skip the next iteration. its the array item and its already set
|
|
1079
|
-
i++;
|
|
1080
|
-
// it the array notation is the beginning
|
|
1081
|
-
} else {
|
|
1082
|
-
// store the array index and override the entry in the property names
|
|
1083
|
-
arrayIndexValues[i] = arrayIndex;
|
|
1084
|
-
propertyNames.splice(i, 1, "item");
|
|
1085
|
-
}
|
|
1086
|
-
} else {
|
|
1087
|
-
arrayIndexValues[i] = "";
|
|
1088
416
|
}
|
|
1089
417
|
}
|
|
1090
418
|
|
|
1091
|
-
|
|
1092
|
-
},
|
|
1093
|
-
|
|
1094
|
-
/**
|
|
1095
|
-
* Internal helper method which is actually doing all bindings. That means
|
|
1096
|
-
* that an event listener will be added to the source object which listens
|
|
1097
|
-
* to the given event and invokes an set on the target property on the
|
|
1098
|
-
* targetObject.
|
|
1099
|
-
* This method does not store the binding in the internal reference store
|
|
1100
|
-
* so it should NOT be used from outside this class. For an outside usage,
|
|
1101
|
-
* use {@link #bind}.
|
|
1102
|
-
*
|
|
1103
|
-
* @param sourceObject {qx.core.Object} The source of the binding.
|
|
1104
|
-
* @param sourceEvent {String} The event of the source object which could
|
|
1105
|
-
* be the change event in common but has to be an
|
|
1106
|
-
* {@link qx.event.type.Data} event.
|
|
1107
|
-
* @param targetObject {qx.core.Object} The object which the source should
|
|
1108
|
-
* be bind to.
|
|
1109
|
-
* @param targetProperty {String} The property name of the target object.
|
|
1110
|
-
* @param options {Map} A map containing the options. See
|
|
1111
|
-
* {@link #bind} for more information.
|
|
1112
|
-
* @param arrayIndex {String} The index of the given array if its an array
|
|
1113
|
-
* to bind.
|
|
1114
|
-
*
|
|
1115
|
-
* @return {var} Returns the internal id for that binding. This can be used
|
|
1116
|
-
* for referencing the binding or e.g. for removing. This is not an atomic
|
|
1117
|
-
* id so you can't you use it as a hash-map index. It's the id which will
|
|
1118
|
-
* be returned by the {@link qx.core.Object#addListener} method.
|
|
1119
|
-
* @throws {qx.core.AssertionError} If the event is no data event or
|
|
1120
|
-
* there is no property definition for the target object and target
|
|
1121
|
-
* property.
|
|
1122
|
-
*/
|
|
1123
|
-
__bindEventToProperty(
|
|
1124
|
-
sourceObject,
|
|
1125
|
-
sourceEvent,
|
|
1126
|
-
targetObject,
|
|
1127
|
-
targetProperty,
|
|
1128
|
-
options,
|
|
1129
|
-
arrayIndex
|
|
1130
|
-
) {
|
|
1131
|
-
// checks
|
|
1132
|
-
if (qx.core.Environment.get("qx.debug")) {
|
|
1133
|
-
// check for the data event
|
|
1134
|
-
var eventType = qx.Class.getEventType(
|
|
1135
|
-
sourceObject.constructor,
|
|
1136
|
-
sourceEvent
|
|
1137
|
-
);
|
|
1138
|
-
|
|
1139
|
-
qx.core.Assert.assertEquals(
|
|
1140
|
-
"qx.event.type.Data",
|
|
1141
|
-
eventType,
|
|
1142
|
-
sourceEvent +
|
|
1143
|
-
" is not an data (qx.event.type.Data) event on " +
|
|
1144
|
-
sourceObject +
|
|
1145
|
-
"."
|
|
1146
|
-
);
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
var bindListener = function (arrayIndex, e) {
|
|
1150
|
-
// if an array value is given
|
|
1151
|
-
if (arrayIndex !== "") {
|
|
1152
|
-
//check if its the "last" value
|
|
1153
|
-
if (arrayIndex === "last") {
|
|
1154
|
-
arrayIndex = sourceObject.length - 1;
|
|
1155
|
-
}
|
|
419
|
+
let lastSegment = this.__targetSegments.at(-1);
|
|
1156
420
|
|
|
1157
|
-
|
|
1158
|
-
|
|
421
|
+
if (this.getTarget() && this.getSource()) {
|
|
422
|
+
let value = this.getValue();
|
|
1159
423
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
targetProperty
|
|
1165
|
-
);
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// only do something if the current array has been changed
|
|
1169
|
-
var start = e.getData().start;
|
|
1170
|
-
var end = e.getData().end;
|
|
1171
|
-
if (arrayIndex < start || arrayIndex > end) {
|
|
1172
|
-
return;
|
|
1173
|
-
}
|
|
1174
|
-
} else {
|
|
1175
|
-
// get the data out of the event
|
|
1176
|
-
var data = e.getData();
|
|
424
|
+
let ignoreConverter = false;
|
|
425
|
+
if (this.__options.ignoreConverter) {
|
|
426
|
+
var match = this.getSourcePath().match(new RegExp("^" + this.__options.ignoreConverter));
|
|
427
|
+
ignoreConverter = match ? match.length > 0 : false;
|
|
1177
428
|
}
|
|
1178
429
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
"Binding executed from " +
|
|
1183
|
-
sourceObject +
|
|
1184
|
-
" by " +
|
|
1185
|
-
sourceEvent +
|
|
1186
|
-
" to " +
|
|
1187
|
-
targetObject +
|
|
1188
|
-
" (" +
|
|
1189
|
-
targetProperty +
|
|
1190
|
-
")"
|
|
1191
|
-
);
|
|
1192
|
-
|
|
1193
|
-
qx.log.Logger.debug("Data before conversion: " + data);
|
|
430
|
+
if (this.__options.converter && (value !== undefined || !ignoreConverter)) {
|
|
431
|
+
let model = typeof this.getTarget().getModel == "function" ? this.getTarget().getModel() : null;
|
|
432
|
+
value = this.__options.converter(value, model, this.getSource(), this.getTarget());
|
|
1194
433
|
}
|
|
1195
434
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
targetObject,
|
|
1200
|
-
targetProperty,
|
|
1201
|
-
options,
|
|
1202
|
-
sourceObject
|
|
1203
|
-
);
|
|
1204
|
-
|
|
1205
|
-
// debug message
|
|
1206
|
-
if (qx.core.Environment.get("qx.debug.databinding")) {
|
|
1207
|
-
qx.log.Logger.debug("Data after conversion: " + data);
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
// try to set the value
|
|
1211
|
-
var result;
|
|
1212
|
-
try {
|
|
1213
|
-
if (data !== undefined) {
|
|
1214
|
-
result = qx.data.SingleValueBinding.__setTargetValue(
|
|
1215
|
-
targetObject,
|
|
1216
|
-
targetProperty,
|
|
1217
|
-
data
|
|
1218
|
-
);
|
|
435
|
+
const cb = ex => {
|
|
436
|
+
if (ex) {
|
|
437
|
+
this.__options.onSetFail?.();
|
|
1219
438
|
} else {
|
|
1220
|
-
|
|
1221
|
-
targetObject,
|
|
1222
|
-
targetProperty
|
|
1223
|
-
);
|
|
439
|
+
this.__options.onUpdate?.(this.getSource(), this.getTarget(), value);
|
|
1224
440
|
}
|
|
441
|
+
return null;
|
|
442
|
+
};
|
|
1225
443
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
}
|
|
444
|
+
let ret;
|
|
445
|
+
try {
|
|
446
|
+
ret = lastSegment.setTargetValue(value);
|
|
1230
447
|
} catch (ex) {
|
|
1231
|
-
|
|
1232
|
-
throw ex;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
if (options && options.onSetFail) {
|
|
1236
|
-
options.onSetFail(ex);
|
|
1237
|
-
} else {
|
|
1238
|
-
qx.log.Logger.warn(
|
|
1239
|
-
"Failed so set value " +
|
|
1240
|
-
data +
|
|
1241
|
-
" on " +
|
|
1242
|
-
targetObject +
|
|
1243
|
-
". Error message: " +
|
|
1244
|
-
ex
|
|
1245
|
-
);
|
|
1246
|
-
}
|
|
448
|
+
return cb(ex);
|
|
1247
449
|
}
|
|
1248
|
-
return result;
|
|
1249
|
-
};
|
|
1250
450
|
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
451
|
+
if (qx.Promise.isPromise(ret)) {
|
|
452
|
+
return ret.then(cb, cb);
|
|
453
|
+
} else {
|
|
454
|
+
cb(null);
|
|
455
|
+
}
|
|
1255
456
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
bindListener,
|
|
1259
|
-
sourceObject,
|
|
1260
|
-
arrayIndex
|
|
1261
|
-
);
|
|
457
|
+
}
|
|
458
|
+
},
|
|
1262
459
|
|
|
1263
|
-
|
|
1264
|
-
|
|
460
|
+
statics: {
|
|
461
|
+
/** @type {Object<String,Object<String,Binding>>} map of maps, outer map is indexed by object hash, inner is indexed by binding hash */
|
|
462
|
+
__bindingsBySource: {},
|
|
1265
463
|
|
|
1266
|
-
|
|
1267
|
-
},
|
|
464
|
+
/** @type {Object<String,Object<String,Binding>>} map of maps, outer map is indexed by object hash, inner is indexed by binding hash */
|
|
465
|
+
__bindingsByTarget: {},
|
|
1268
466
|
|
|
1269
467
|
/**
|
|
1270
|
-
*
|
|
1271
|
-
* of all bindings.
|
|
1272
|
-
*
|
|
1273
|
-
* @param id {var} The listener id of the id for a deeper binding.
|
|
1274
|
-
* @param sourceObject {qx.core.Object} The source Object of the binding.
|
|
1275
|
-
* @param sourceEvent {String} The name of the source event.
|
|
1276
|
-
* @param targetObject {qx.core.Object} The target object.
|
|
1277
|
-
* @param targetProperty {String} The name of the property on the target
|
|
1278
|
-
* object.
|
|
468
|
+
* @see {qx.data.SingleValueBinding#construct}
|
|
1279
469
|
*/
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
var hash;
|
|
1288
|
-
|
|
1289
|
-
// add the listener id to the internal registry
|
|
1290
|
-
hash = sourceObject.toHashCode();
|
|
1291
|
-
if (this.__bindings[hash] === undefined) {
|
|
1292
|
-
this.__bindings[hash] = [];
|
|
470
|
+
bind(sourceObject, sourcePropertyChain, targetObject, targetPropertyChain, options) {
|
|
471
|
+
// check for the arguments
|
|
472
|
+
if (qx.core.Environment.get("qx.debug")) {
|
|
473
|
+
qx.core.Assert.assertObject(sourceObject, "sourceObject");
|
|
474
|
+
qx.core.Assert.assertString(sourcePropertyChain, "sourcePropertyChain");
|
|
475
|
+
qx.core.Assert.assertObject(targetObject, "targetObject");
|
|
476
|
+
qx.core.Assert.assertString(targetPropertyChain, "targetPropertyChain");
|
|
1293
477
|
}
|
|
1294
478
|
|
|
1295
|
-
|
|
1296
|
-
id,
|
|
1297
|
-
sourceObject,
|
|
1298
|
-
sourceEvent,
|
|
1299
|
-
targetObject,
|
|
1300
|
-
targetProperty
|
|
1301
|
-
];
|
|
1302
|
-
|
|
1303
|
-
this.__bindings[hash].push(binding);
|
|
479
|
+
let binding = new qx.data.SingleValueBinding(sourcePropertyChain, targetPropertyChain, sourceObject, targetObject, options);
|
|
1304
480
|
|
|
1305
|
-
|
|
1306
|
-
hash = targetObject.toHashCode();
|
|
1307
|
-
if (this.__bindingsByTarget[hash] === undefined) {
|
|
1308
|
-
this.__bindingsByTarget[hash] = [];
|
|
1309
|
-
}
|
|
1310
|
-
this.__bindingsByTarget[hash].push(binding);
|
|
481
|
+
return binding;
|
|
1311
482
|
},
|
|
1312
483
|
|
|
1313
484
|
/**
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
* given by the user, the {@link #__defaultConversion} will try to convert
|
|
1317
|
-
* the value.
|
|
1318
|
-
*
|
|
1319
|
-
* @param value {var} The value which possibly should be converted.
|
|
1320
|
-
* @param targetObject {qx.core.Object} The target object.
|
|
1321
|
-
* @param targetPropertyChain {String} The property name of the target object.
|
|
1322
|
-
* @param options {Map} The options map which can includes the converter.
|
|
1323
|
-
* For a detailed information on the map, take a look at
|
|
1324
|
-
* {@link #bind}.
|
|
1325
|
-
* @param sourceObject {qx.core.Object} The source object for the binding.
|
|
485
|
+
* Removes the binding with the given id from the given sourceObject. The
|
|
486
|
+
* id has to be the id returned by any of the bind functions.
|
|
1326
487
|
*
|
|
1327
|
-
* @
|
|
1328
|
-
*
|
|
1329
|
-
* @throws {
|
|
1330
|
-
* of the given target object and target property.
|
|
488
|
+
* @param sourceObject {qx.core.Object} The source object of the binding.
|
|
489
|
+
* @param id {var} The id of the binding.
|
|
490
|
+
* @throws {Error} If the binding could not be found.
|
|
1331
491
|
*/
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
targetObject,
|
|
1335
|
-
targetPropertyChain,
|
|
1336
|
-
options,
|
|
1337
|
-
sourceObject
|
|
1338
|
-
) {
|
|
1339
|
-
// do the conversion given by the user
|
|
1340
|
-
if (options && options.converter) {
|
|
1341
|
-
var model;
|
|
1342
|
-
if (targetObject.getModel) {
|
|
1343
|
-
model = targetObject.getModel();
|
|
1344
|
-
}
|
|
1345
|
-
return options.converter(value, model, sourceObject, targetObject);
|
|
1346
|
-
// try default conversion
|
|
1347
|
-
} else {
|
|
1348
|
-
var properties = this.__getPropertyChainArray(targetPropertyChain);
|
|
1349
|
-
var target = this.__getTargetFromChain(targetObject, properties);
|
|
1350
|
-
var lastProperty = targetPropertyChain.substring(
|
|
1351
|
-
targetPropertyChain.lastIndexOf(".") + 1,
|
|
1352
|
-
targetPropertyChain.length
|
|
1353
|
-
);
|
|
1354
|
-
|
|
1355
|
-
// if no target is currently available, return the original value
|
|
1356
|
-
if (target == null) {
|
|
1357
|
-
return value;
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
var propertieDefinition = qx.Class.getPropertyDefinition(
|
|
1361
|
-
target.constructor,
|
|
1362
|
-
lastProperty
|
|
1363
|
-
);
|
|
1364
|
-
|
|
1365
|
-
var check =
|
|
1366
|
-
propertieDefinition == null ? "" : propertieDefinition.check;
|
|
1367
|
-
return this.__defaultConversion(value, check);
|
|
1368
|
-
}
|
|
492
|
+
removeBindingFromObject(sourceObject, binding) {
|
|
493
|
+
binding.dispose();
|
|
1369
494
|
},
|
|
1370
495
|
|
|
1371
496
|
/**
|
|
1372
|
-
*
|
|
1373
|
-
* given object does have a change event and if returns the name of it.
|
|
497
|
+
* Removes all bindings for the given object.
|
|
1374
498
|
*
|
|
1375
|
-
* @param
|
|
1376
|
-
*
|
|
499
|
+
* @param object {qx.core.Object} The object of which the bindings should be
|
|
500
|
+
* removed.
|
|
501
|
+
* @throws {qx.core.AssertionError} If the object is not in the internal
|
|
502
|
+
* registry of the bindings.
|
|
503
|
+
* @throws {Error} If one of the bindings listed internally can not be
|
|
504
|
+
* removed.
|
|
505
|
+
*/
|
|
506
|
+
removeAllBindingsForObject(object) {
|
|
507
|
+
qx.core.Assert.assertNotNull(object, "Null is not possible!");
|
|
508
|
+
qx.data.SingleValueBinding.getAllBindingsForObject(object).forEach(binding => binding[0].dispose());
|
|
509
|
+
},
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Debug function which shows some valuable information about the given
|
|
513
|
+
* binding in console. For that it uses {@link qx.log.Logger}.
|
|
1377
514
|
*
|
|
1378
|
-
* @
|
|
1379
|
-
* @
|
|
1380
|
-
* the given object property pair.
|
|
515
|
+
* @param object {qx.core.Object} the source of the binding.
|
|
516
|
+
* @param id {var} The id of the binding.
|
|
1381
517
|
*/
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
518
|
+
showBindingInLog(object, binding) {
|
|
519
|
+
qx.log.Logger.debug(
|
|
520
|
+
"Binding from '" +
|
|
521
|
+
binding.getSource() +
|
|
522
|
+
"' (" +
|
|
523
|
+
binding.getSourcePath() +
|
|
524
|
+
") to the object '" +
|
|
525
|
+
binding.getTarget() +
|
|
526
|
+
"' (" +
|
|
527
|
+
binding.getTargetPath() +
|
|
528
|
+
")."
|
|
1387
529
|
);
|
|
1388
|
-
|
|
1389
|
-
if (propertieDefinition == null) {
|
|
1390
|
-
return null;
|
|
1391
|
-
}
|
|
1392
|
-
return propertieDefinition.event;
|
|
1393
530
|
},
|
|
1394
531
|
|
|
1395
532
|
/**
|
|
1396
|
-
*
|
|
533
|
+
* Helper for updating the target. Gets the current set data from the source
|
|
534
|
+
* and set that on the target.
|
|
1397
535
|
*
|
|
1398
|
-
* @param
|
|
1399
|
-
* @param
|
|
1400
|
-
*
|
|
1401
|
-
* @
|
|
536
|
+
* @param sourceObject {qx.core.Object} The source of the binding.
|
|
537
|
+
* @param sourcePropertyChain {String} The property chain which represents
|
|
538
|
+
* the source property.
|
|
539
|
+
* @param targetObject {qx.core.Object} The object which the source should
|
|
540
|
+
* be bind to.
|
|
541
|
+
* @param targetPropertyChain {String} The property name of the target
|
|
542
|
+
* object.
|
|
543
|
+
* @param options {Map} The options map perhaps containing the user defined
|
|
544
|
+
* converter.
|
|
545
|
+
*
|
|
546
|
+
* @internal
|
|
1402
547
|
*/
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
// to integer
|
|
1407
|
-
if (
|
|
1408
|
-
(dataType == "Number" || dataType == "String") &&
|
|
1409
|
-
(targetCheck == "Integer" || targetCheck == "PositiveInteger")
|
|
1410
|
-
) {
|
|
1411
|
-
data = parseInt(data, 10);
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
// to string
|
|
1415
|
-
if (
|
|
1416
|
-
(dataType == "Boolean" || dataType == "Number" || dataType == "Date") &&
|
|
1417
|
-
targetCheck == "String"
|
|
1418
|
-
) {
|
|
1419
|
-
data = data + "";
|
|
1420
|
-
}
|
|
548
|
+
updateTarget(sourceObject, sourcePropertyChain, targetObject, targetPropertyChain, options) {
|
|
549
|
+
options ??= {};
|
|
550
|
+
var value = this.resolvePropertyChain(sourceObject, sourcePropertyChain);
|
|
1421
551
|
|
|
1422
|
-
//
|
|
1423
|
-
if (
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
) {
|
|
1427
|
-
data = parseFloat(data);
|
|
552
|
+
// convert the data before setting
|
|
553
|
+
if (options.converter) {
|
|
554
|
+
let model = typeof targetObject.getModel == "function" ? targetObject.getModel() : null;
|
|
555
|
+
value = options.converter(value, model, sourceObject, targetObject);
|
|
1428
556
|
}
|
|
1429
557
|
|
|
1430
|
-
return
|
|
558
|
+
return this.__setTargetValue(targetObject, targetPropertyChain, value);
|
|
1431
559
|
},
|
|
1432
560
|
|
|
1433
561
|
/**
|
|
1434
|
-
*
|
|
1435
|
-
*
|
|
562
|
+
* Sets the given value to the given target after resolving the
|
|
563
|
+
* target property chain.
|
|
1436
564
|
*
|
|
1437
|
-
* @param
|
|
1438
|
-
*
|
|
1439
|
-
* @
|
|
565
|
+
* @param targetObject {qx.core.Object} The object where the property chain
|
|
566
|
+
* starts.
|
|
567
|
+
* @param targetPropertyChain {String} The names of the properties,
|
|
568
|
+
* separated with a dot.
|
|
569
|
+
* @param value {var} The value to set.
|
|
1440
570
|
*/
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
id.sources[i].removeListenerById(id.listenerIds[i]);
|
|
1450
|
-
}
|
|
1451
|
-
// If the listener id is not available, it is most likely
|
|
1452
|
-
// caused by some hidden error situation.
|
|
1453
|
-
// At least an error message should be displayed
|
|
1454
|
-
else {
|
|
1455
|
-
sourceObject.error(
|
|
1456
|
-
"Could not remove deep bindings. Binding id for " +
|
|
1457
|
-
id.sources[i].classname +
|
|
1458
|
-
" could not be found!"
|
|
1459
|
-
);
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
// go through all added listeners (target)
|
|
1464
|
-
for (var i = 0; i < id.targets.length; i++) {
|
|
1465
|
-
// check if a target is available
|
|
1466
|
-
if (id.targets[i]) {
|
|
1467
|
-
if (id.targetListenerIds[i]) {
|
|
1468
|
-
id.targets[i].removeListenerById(id.targetListenerIds[i]);
|
|
1469
|
-
}
|
|
1470
|
-
// If the target listener id is not available, it is most likely
|
|
1471
|
-
// caused by some hidden error situation.
|
|
1472
|
-
// At least an error message should be displayed
|
|
1473
|
-
else {
|
|
1474
|
-
sourceObject.error(
|
|
1475
|
-
"Could not remove target listener. Listener id for target " +
|
|
1476
|
-
id.targets[i].classname +
|
|
1477
|
-
" could not be found!"
|
|
1478
|
-
);
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
} else {
|
|
1483
|
-
// remove the listener
|
|
1484
|
-
sourceObject.removeListenerById(id);
|
|
1485
|
-
}
|
|
571
|
+
__setTargetValue(targetObject, targetPropertyChain, value) {
|
|
572
|
+
let segments = qx.data.SingleValueBinding.__parseSegments(null, targetPropertyChain);
|
|
573
|
+
let lastSegment = segments[segments.length - 1];
|
|
574
|
+
segments[0].setInput(targetObject);
|
|
575
|
+
let out = lastSegment.setTargetValue(value);
|
|
576
|
+
segments.forEach(segment => segment.dispose());
|
|
577
|
+
return out;
|
|
578
|
+
},
|
|
1486
579
|
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
var source = bindings[i][1];
|
|
1504
|
-
if (this.__bindings[source.toHashCode()]) {
|
|
1505
|
-
qx.lang.Array.remove(
|
|
1506
|
-
this.__bindings[source.toHashCode()],
|
|
1507
|
-
bindings[i]
|
|
1508
|
-
);
|
|
1509
|
-
}
|
|
1510
|
-
return;
|
|
1511
|
-
}
|
|
580
|
+
/**
|
|
581
|
+
* Splits a property path into segments.
|
|
582
|
+
* @param {string} path
|
|
583
|
+
* @returns {string[]} an array of segments, split by dot and square brackets.
|
|
584
|
+
* For example, splitSegments(`a.b[0].c`) will return `["a", "b", "[0]", "c"]`
|
|
585
|
+
*/
|
|
586
|
+
splitSegments(path) {
|
|
587
|
+
let out = [];
|
|
588
|
+
for (let dotSplit of path.split(".")) {
|
|
589
|
+
let bracketSplits = dotSplit.split("[");
|
|
590
|
+
for (let i = 0; i < bracketSplits.length; i++) {
|
|
591
|
+
let bracketSplit = bracketSplits[i];
|
|
592
|
+
if (i > 0) {
|
|
593
|
+
bracketSplit = "[" + bracketSplit;
|
|
594
|
+
}
|
|
595
|
+
out.push(bracketSplit);
|
|
1512
596
|
}
|
|
1513
597
|
}
|
|
1514
|
-
|
|
598
|
+
return out.filter(s => s.length > 0);
|
|
1515
599
|
},
|
|
1516
600
|
|
|
1517
601
|
/**
|
|
1518
|
-
*
|
|
602
|
+
* Finds all bindings for an object, as either a source or target
|
|
1519
603
|
*
|
|
1520
|
-
* @param
|
|
1521
|
-
*
|
|
1522
|
-
* @throws {qx.core.AssertionError} If the object is not in the internal
|
|
1523
|
-
* registry of the bindings.
|
|
1524
|
-
* @throws {Error} If one of the bindings listed internally can not be
|
|
1525
|
-
* removed.
|
|
604
|
+
* @param {qx.core.Object} object
|
|
605
|
+
* @returns {BindingRecord[]} An array of the bindings represented as records.
|
|
1526
606
|
*/
|
|
1527
|
-
|
|
1528
|
-
|
|
607
|
+
getAllBindingsForObject(object) {
|
|
608
|
+
const SingleValueBinding = qx.data.SingleValueBinding;
|
|
609
|
+
let allBindings = {
|
|
610
|
+
...(SingleValueBinding.__bindingsBySource[object.toHashCode()] ?? {}),
|
|
611
|
+
...(SingleValueBinding.__bindingsByTarget[object.toHashCode()] ?? {})
|
|
612
|
+
};
|
|
613
|
+
return Object.values(allBindings).map(binding => binding.asRecord());
|
|
614
|
+
},
|
|
1529
615
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
616
|
+
/**
|
|
617
|
+
* Returns a map containing for every bound object an array of data binding
|
|
618
|
+
* information. The key of the map is the hash code of the bound objects.
|
|
619
|
+
* Every binding is represented by an array containing id, sourceObject,
|
|
620
|
+
* sourceEvent, targetObject and targetProperty.
|
|
621
|
+
*
|
|
622
|
+
* @return {Object<string, BindingInfo>} Map containing all bindings.
|
|
623
|
+
*
|
|
624
|
+
* @typedef {[qx.data.SingleValueBinding, qx.core.Object, string, qx.core.Object, string]} BindingInfo
|
|
625
|
+
* Stores the binding ID, source object, source path, target object and target path respectively.
|
|
626
|
+
*/
|
|
627
|
+
getAllBindings() {
|
|
628
|
+
let bindings = qx.data.SingleValueBinding.__bindingsBySource;
|
|
1536
629
|
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
this.removeBindingFromObject(object, bindings[i][0]);
|
|
630
|
+
let result = {};
|
|
631
|
+
for (let [objectHash, objectBindings] of Object.entries(bindings)) {
|
|
632
|
+
let objectBindingsArray = [];
|
|
633
|
+
for (let [bindingHash, binding] of Object.entries(objectBindings)) {
|
|
634
|
+
objectBindingsArray.push([binding, binding.getSource(), binding.getSourcePath(), binding.getTarget(), binding.getTargetPath()]);
|
|
1543
635
|
}
|
|
636
|
+
result[objectHash] = objectBindingsArray;
|
|
1544
637
|
}
|
|
1545
|
-
|
|
1546
|
-
var hash = object.toHashCode();
|
|
1547
|
-
delete this.__bindings[hash];
|
|
1548
|
-
delete this.__bindingsByTarget[hash];
|
|
638
|
+
return result;
|
|
1549
639
|
},
|
|
1550
640
|
|
|
1551
641
|
/**
|
|
@@ -1561,149 +651,158 @@ qx.Class.define("qx.data.SingleValueBinding", {
|
|
|
1561
651
|
* removed.
|
|
1562
652
|
*/
|
|
1563
653
|
removeRelatedBindings(object, relatedObject) {
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
)
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
);
|
|
654
|
+
const SingleValueBinding = qx.data.SingleValueBinding;
|
|
655
|
+
|
|
656
|
+
let bySourceObject = SingleValueBinding.__bindingsBySource[object.toHashCode()];
|
|
657
|
+
|
|
658
|
+
if (bySourceObject) {
|
|
659
|
+
Object.values(bySourceObject).forEach(binding => {
|
|
660
|
+
if (binding.getTarget() === relatedObject) {
|
|
661
|
+
binding.dispose();
|
|
662
|
+
}
|
|
663
|
+
});
|
|
1575
664
|
}
|
|
1576
665
|
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
var source = bindings[i][1];
|
|
1583
|
-
var target = bindings[i][3];
|
|
1584
|
-
if (source === relatedObject || target === relatedObject) {
|
|
1585
|
-
this.removeBindingFromObject(object, bindings[i][0]);
|
|
666
|
+
let byRelatedObject = SingleValueBinding.__bindingsBySource[relatedObject.toHashCode()];
|
|
667
|
+
if (byRelatedObject) {
|
|
668
|
+
Object.values(byRelatedObject).forEach(binding => {
|
|
669
|
+
if (binding.getTarget() === object) {
|
|
670
|
+
binding.dispose();
|
|
1586
671
|
}
|
|
1587
|
-
}
|
|
672
|
+
});
|
|
1588
673
|
}
|
|
1589
674
|
},
|
|
1590
675
|
|
|
1591
676
|
/**
|
|
1592
|
-
*
|
|
677
|
+
* Helper method that sets a value for a named property
|
|
1593
678
|
*
|
|
1594
|
-
* @param
|
|
1595
|
-
*
|
|
1596
|
-
*
|
|
1597
|
-
* @return {Array} An array of binding informations. Every binding
|
|
1598
|
-
* information is an array itself containing id, sourceObject,
|
|
1599
|
-
* sourceEvent, targetObject and targetProperty in that order.
|
|
679
|
+
* @param {qx.core.Object} target object to have a property set
|
|
680
|
+
* @param {String} propertyName the name of the property
|
|
681
|
+
* @param {Object?} value the value to set
|
|
1600
682
|
*/
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
if (!sourceBindings && !targetBindings) {
|
|
1611
|
-
return [];
|
|
1612
|
-
}
|
|
1613
|
-
if (!sourceBindings) {
|
|
1614
|
-
return qx.lang.Array.clone(targetBindings);
|
|
1615
|
-
}
|
|
1616
|
-
if (!targetBindings) {
|
|
1617
|
-
return qx.lang.Array.clone(sourceBindings);
|
|
683
|
+
set(target, propertyName, value) {
|
|
684
|
+
let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
|
|
685
|
+
if (!prop) {
|
|
686
|
+
let setFuncName = "set" + qx.lang.String.firstUp(propertyName);
|
|
687
|
+
if (typeof target[setFuncName] == "function") {
|
|
688
|
+
return target[setFuncName](value);
|
|
689
|
+
} else {
|
|
690
|
+
throw new Error(`Property ${propertyName} not found on ${target.classname}`);
|
|
691
|
+
}
|
|
1618
692
|
}
|
|
1619
693
|
|
|
1620
|
-
|
|
694
|
+
if (prop.isAsync()) {
|
|
695
|
+
return prop.setAsync(target, value);
|
|
696
|
+
} else {
|
|
697
|
+
return prop.set(target, value);
|
|
698
|
+
}
|
|
1621
699
|
},
|
|
1622
700
|
|
|
1623
701
|
/**
|
|
1624
|
-
*
|
|
1625
|
-
*
|
|
1626
|
-
* @
|
|
1627
|
-
*
|
|
702
|
+
* Helper method to get a value of a named property
|
|
703
|
+
*
|
|
704
|
+
* @param {qx.core.Object} target object to have a property get
|
|
705
|
+
* @param {String} propertyName the name of the property
|
|
706
|
+
* @returns {Object?} the property value
|
|
1628
707
|
*/
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
delete this.__bindings[hash];
|
|
1636
|
-
continue;
|
|
1637
|
-
}
|
|
1638
|
-
this.removeAllBindingsForObject(object);
|
|
708
|
+
get(target, propertyName) {
|
|
709
|
+
let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
|
|
710
|
+
if (prop.isAsync()) {
|
|
711
|
+
return prop.getAsync(target);
|
|
712
|
+
} else {
|
|
713
|
+
return prop.get(target);
|
|
1639
714
|
}
|
|
1640
|
-
// reset the bindings map
|
|
1641
|
-
this.__bindings = {};
|
|
1642
715
|
},
|
|
1643
716
|
|
|
1644
717
|
/**
|
|
1645
|
-
*
|
|
1646
|
-
* information. The key of the map is the hash code of the bound objects.
|
|
1647
|
-
* Every binding is represented by an array containing id, sourceObject,
|
|
1648
|
-
* sourceEvent, targetObject and targetProperty.
|
|
718
|
+
* Helper method that resets a named property
|
|
1649
719
|
*
|
|
1650
|
-
* @
|
|
720
|
+
* @param {qx.core.Object} target object to have a property set
|
|
721
|
+
* @param {String} propertyName the name of the property
|
|
722
|
+
|
|
1651
723
|
*/
|
|
1652
|
-
|
|
1653
|
-
|
|
724
|
+
reset(target, propertyName) {
|
|
725
|
+
let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
|
|
726
|
+
if (!prop) {
|
|
727
|
+
let setFuncName = "reset" + qx.lang.String.firstUp(propertyName);
|
|
728
|
+
if (typeof target[setFuncName] == "function") {
|
|
729
|
+
return target[setFuncName]();
|
|
730
|
+
} else {
|
|
731
|
+
throw new Error(`Property ${propertyName} not found on ${target.classname}`);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if (prop.isAsync()) {
|
|
736
|
+
return prop.resetAsync(target);
|
|
737
|
+
} else {
|
|
738
|
+
return prop.reset(target);
|
|
739
|
+
}
|
|
1654
740
|
},
|
|
1655
741
|
|
|
1656
742
|
/**
|
|
1657
|
-
* Debug function which shows some valuable information about the given
|
|
1658
|
-
* binding in console. For that it uses {@link qx.log.Logger}.
|
|
1659
743
|
*
|
|
1660
|
-
*
|
|
1661
|
-
*
|
|
744
|
+
* Internal helper for getting the current set value at the property chain.
|
|
745
|
+
*
|
|
746
|
+
* @param {qx.core.Object} object The source of the binding.
|
|
747
|
+
* @param {String} propertyChain The property chain which represents
|
|
748
|
+
* the source property.
|
|
749
|
+
* @return {var?undefined} Returns the set value if defined.
|
|
1662
750
|
*/
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
binding = this.__bindings[object.toHashCode()][i];
|
|
1670
|
-
break;
|
|
751
|
+
resolvePropertyChain(object, propertyChain) {
|
|
752
|
+
let segments = qx.data.SingleValueBinding.__parseSegments(null, propertyChain);
|
|
753
|
+
let out;
|
|
754
|
+
let receiver = {
|
|
755
|
+
setInput(value) {
|
|
756
|
+
out = value;
|
|
1671
757
|
}
|
|
1672
|
-
}
|
|
758
|
+
};
|
|
759
|
+
segments.at(-1).setOutputReceiver(receiver);
|
|
760
|
+
let promise = segments[0].setInput(object);
|
|
761
|
+
|
|
762
|
+
const cb = () => {
|
|
763
|
+
let first = segments[0];
|
|
764
|
+
if (first instanceof qx.data.binding.PropNameSegment) {
|
|
765
|
+
let property = qx.Class.getByProperty(object.constructor, first.getPropName());
|
|
766
|
+
qx.core.Assert.assertNotNull(property, `Object ${object.classname} does not have property ${first.getPropName()}`);
|
|
767
|
+
}
|
|
768
|
+
segments.forEach(segment => segment.dispose());
|
|
769
|
+
return out;
|
|
770
|
+
};
|
|
1673
771
|
|
|
1674
|
-
if (
|
|
1675
|
-
|
|
772
|
+
if (qx.Promise.isPromise(promise)) {
|
|
773
|
+
return promise.then(cb);
|
|
1676
774
|
} else {
|
|
1677
|
-
|
|
1678
|
-
"Binding from '" +
|
|
1679
|
-
binding[1] +
|
|
1680
|
-
"' (" +
|
|
1681
|
-
binding[2] +
|
|
1682
|
-
") to the object '" +
|
|
1683
|
-
binding[3] +
|
|
1684
|
-
"' (" +
|
|
1685
|
-
binding[4] +
|
|
1686
|
-
").";
|
|
775
|
+
return cb();
|
|
1687
776
|
}
|
|
1688
|
-
|
|
1689
|
-
qx.log.Logger.debug(message);
|
|
1690
777
|
},
|
|
1691
778
|
|
|
1692
779
|
/**
|
|
1693
|
-
*
|
|
1694
|
-
*
|
|
1695
|
-
* @
|
|
780
|
+
* Parses a path and creates an array of `qx.data.binding.AbstractSegment`
|
|
781
|
+
*
|
|
782
|
+
* @param {String} path the path to parse
|
|
783
|
+
* @return {qx.data.binding.AbstractSegment[]?} the new array of segments
|
|
1696
784
|
*/
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
785
|
+
__parseSegments(binding, path) {
|
|
786
|
+
let segsStrings = qx.data.SingleValueBinding.splitSegments(path);
|
|
787
|
+
let segments = [];
|
|
788
|
+
|
|
789
|
+
for (let seg of segsStrings) {
|
|
790
|
+
//if it's an array index:
|
|
791
|
+
if (seg.startsWith("[")) {
|
|
792
|
+
segments.push(new qx.data.binding.ArrayIndexSegment(binding, seg));
|
|
793
|
+
} else {
|
|
794
|
+
//otherwise, it's a normal path
|
|
795
|
+
segments.push(new qx.data.binding.PropNameSegment(binding, seg));
|
|
1705
796
|
}
|
|
1706
797
|
}
|
|
798
|
+
|
|
799
|
+
segments.forEach((seg, index) => {
|
|
800
|
+
if (index < segments.length - 1) {
|
|
801
|
+
seg.setOutputReceiver(segments[index + 1]);
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
return segments;
|
|
1707
806
|
}
|
|
1708
807
|
}
|
|
1709
808
|
});
|