@qooxdoo/framework 7.9.2 → 8.0.0-beta.1

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.
Files changed (593) hide show
  1. package/CHANGELOG.md +191 -33
  2. package/Manifest.json +3 -3
  3. package/bin/tools/utils.js +50 -13
  4. package/lib/compiler/compile-info.json +300 -230
  5. package/lib/compiler/index.js +56748 -44036
  6. package/lib/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-node.tmpl.js +1 -0
  7. package/lib/resource/qx/tool/compiler/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css.map +1 -0
  8. package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/cli/templates/template_vars.js +12 -9
  9. package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/schema/Manifest-1-0-0.json +2 -2
  10. package/lib/resource/qx/tool/{schema → compiler/schema}/Manifest-2-0-0.json +2 -2
  11. package/lib/resource/qx/tool/{schema → compiler/schema}/compile-1-0-0.json +15 -3
  12. package/{source/resource/qx/tool → lib/resource/qx/tool/compiler}/schema/qooxdoo-1-0-0.json +1 -1
  13. package/lib/resource/qx/tool/website/build/404.html +22 -22
  14. package/lib/resource/qx/tool/website/build/about.html +23 -23
  15. package/lib/resource/qx/tool/website/build/assets/common.js +30 -18
  16. package/lib/resource/qx/tool/website/build/assets/custom.css +290 -0
  17. package/lib/resource/qx/tool/website/build/assets/qxWeb.js +28 -0
  18. package/lib/resource/qx/tool/website/build/diagnostics/dependson.html +30 -30
  19. package/lib/resource/qx/tool/website/build/diagnostics/dependson.js +49 -40
  20. package/lib/resource/qx/tool/website/build/diagnostics/requiredby.html +20 -23
  21. package/lib/resource/qx/tool/website/build/diagnostics/requiredby.js +38 -31
  22. package/lib/resource/qx/tool/website/build/index.html +24 -24
  23. package/lib/resource/qx/tool/website/build/scripts/serve.js +63 -65
  24. package/lib/resource/qx/tool/website/partials/footer.html +8 -13
  25. package/lib/resource/qx/tool/website/partials/head.html +9 -7
  26. package/lib/resource/qx/tool/website/partials/header.html +3 -3
  27. package/lib/resource/qx/tool/website/src/assets/common.js +32 -0
  28. package/lib/resource/qx/tool/website/src/assets/custom.css +290 -0
  29. package/lib/resource/qx/tool/website/src/assets/qxWeb.js +28 -0
  30. package/lib/resource/qx/tool/website/src/diagnostics/dependson.js +49 -40
  31. package/lib/resource/qx/tool/website/src/diagnostics/requiredby.js +38 -31
  32. package/lib/resource/qx/tool/website/src/index.html +2 -2
  33. package/lib/resource/qx/tool/website/src/scripts/serve.js +63 -65
  34. package/package.json +20 -19
  35. package/source/boot/index.html +2 -2
  36. package/source/class/qx/Bootstrap.js +931 -705
  37. package/source/class/qx/Class.js +1476 -1451
  38. package/source/class/qx/Interface.js +40 -107
  39. package/source/class/qx/Mixin.js +58 -116
  40. package/source/class/qx/Promise.js +1 -0
  41. package/source/class/qx/Theme.js +1 -1
  42. package/source/class/qx/application/Routing.js +2 -0
  43. package/source/class/qx/bom/Font.js +3 -0
  44. package/source/class/qx/bom/client/Locale.js +5 -0
  45. package/source/class/qx/bom/request/Jsonp.js +5 -13
  46. package/source/class/qx/bom/request/Script.js +11 -35
  47. package/source/class/qx/bom/request/SimpleXhr.js +13 -41
  48. package/source/class/qx/bom/request/Xhr.js +19 -80
  49. package/source/class/qx/bom/storage/Memory.js +2 -0
  50. package/source/class/qx/bom/storage/UserData.js +2 -0
  51. package/source/class/qx/bom/storage/Web.js +2 -0
  52. package/source/class/qx/bom/webfonts/Validator.js +13 -5
  53. package/source/class/qx/core/Assert.js +14 -0
  54. package/source/class/qx/core/BaseInit.js +19 -20
  55. package/source/class/qx/core/Environment.js +23 -20
  56. package/source/class/qx/core/MEvent.js +1 -1
  57. package/source/class/qx/core/MObjectId.js +8 -6
  58. package/source/class/qx/core/MProperty.js +172 -136
  59. package/source/class/qx/core/Object.js +88 -102
  60. package/source/class/qx/core/check/AbstractCheck.js +111 -0
  61. package/source/class/qx/core/check/Any.js +63 -0
  62. package/source/class/qx/core/check/CheckFactory.js +151 -0
  63. package/source/class/qx/core/check/DynamicTypeCheck.js +90 -0
  64. package/source/class/qx/core/check/ICheck.js +75 -0
  65. package/source/class/qx/core/check/IsOneOfCheck.js +63 -0
  66. package/source/class/qx/core/check/JsDocCheck.js +71 -0
  67. package/source/class/qx/core/check/SimpleCheck.js +42 -0
  68. package/source/class/qx/core/check/standard/ArrayCheck.js +49 -0
  69. package/source/class/qx/core/check/standard/BooleanCheck.js +47 -0
  70. package/source/class/qx/core/check/standard/ClassCheck.js +33 -0
  71. package/source/class/qx/core/check/standard/ColorCheck.js +33 -0
  72. package/source/class/qx/core/check/standard/DateCheck.js +49 -0
  73. package/source/class/qx/core/check/standard/DecoratorCheck.js +33 -0
  74. package/source/class/qx/core/check/standard/DocumentCheck.js +40 -0
  75. package/source/class/qx/core/check/standard/ElementCheck.js +40 -0
  76. package/source/class/qx/core/check/standard/ErrorCheck.js +46 -0
  77. package/source/class/qx/core/check/standard/EventCheck.js +40 -0
  78. package/source/class/qx/core/check/standard/FontCheck.js +33 -0
  79. package/source/class/qx/core/check/standard/FunctionCheck.js +49 -0
  80. package/source/class/qx/core/check/standard/IntegerCheck.js +54 -0
  81. package/source/class/qx/core/check/standard/InterfaceCheck.js +33 -0
  82. package/source/class/qx/core/check/standard/MapCheck.js +33 -0
  83. package/source/class/qx/core/check/standard/MixinCheck.js +33 -0
  84. package/source/class/qx/core/check/standard/NodeCheck.js +40 -0
  85. package/source/class/qx/core/check/standard/NumberCheck.js +48 -0
  86. package/source/class/qx/core/check/standard/ObjectCheck.js +33 -0
  87. package/source/class/qx/core/check/standard/PositiveIntegerCheck.js +45 -0
  88. package/source/class/qx/core/check/standard/PositiveNumberCheck.js +45 -0
  89. package/source/class/qx/core/check/standard/PromiseCheck.js +33 -0
  90. package/source/class/qx/core/check/standard/RegExpCheck.js +46 -0
  91. package/source/class/qx/core/check/standard/StringCheck.js +43 -0
  92. package/source/class/qx/core/check/standard/ThemeCheck.js +33 -0
  93. package/source/class/qx/core/check/standard/WindowCheck.js +40 -0
  94. package/source/class/qx/core/property/ExplicitPropertyStorage.js +87 -0
  95. package/source/class/qx/core/property/GroupProperty.js +262 -0
  96. package/source/class/qx/core/property/IProperty.js +46 -0
  97. package/source/class/qx/core/property/IPropertyStorage.js +83 -0
  98. package/source/class/qx/core/property/ImmutableArrayStorage.js +38 -0
  99. package/source/class/qx/core/property/ImmutableDataArrayStorage.js +38 -0
  100. package/source/class/qx/core/property/ImmutableObjectStorage.js +39 -0
  101. package/source/class/qx/core/property/Property.js +1481 -0
  102. package/source/class/qx/core/property/PropertyStorageFactory.js +22 -0
  103. package/source/class/qx/core/property/SimplePropertyStorage.js +105 -0
  104. package/source/class/qx/data/Array.js +102 -57
  105. package/source/class/qx/data/MBinding.js +4 -29
  106. package/source/class/qx/data/SingleValueBinding.js +596 -1495
  107. package/source/class/qx/data/binding/AbstractSegment.js +197 -0
  108. package/source/class/qx/data/binding/ArrayIndexSegment.js +148 -0
  109. package/source/class/qx/data/binding/IInputReceiver.js +14 -0
  110. package/source/class/qx/data/binding/PropNameSegment.js +150 -0
  111. package/source/class/qx/data/controller/CheckedList.js +1 -1
  112. package/source/class/qx/data/controller/Form.js +78 -8
  113. package/source/class/qx/data/controller/Tree.js +27 -117
  114. package/source/class/qx/data/marshal/Json.js +46 -149
  115. package/source/class/qx/data/store/Json.js +0 -2
  116. package/source/class/qx/dev/Debug.js +1 -1
  117. package/source/class/qx/dev/LeakDetector.js +144 -0
  118. package/source/class/qx/dev/unit/AsyncWrapper.js +1 -0
  119. package/source/class/qx/dev/unit/MMock.js +7 -2
  120. package/source/class/qx/dev/unit/Sinon.js +0 -4
  121. package/source/class/qx/dev/unit/TestClass.js +2 -2
  122. package/source/class/qx/dev/unit/TestFunction.js +1 -0
  123. package/source/class/qx/dev/unit/TestLoaderBasic.js +1 -0
  124. package/source/class/qx/dev/unit/TestRunner.js +106 -0
  125. package/source/class/qx/event/IEventDispatcher.js +8 -4
  126. package/source/class/qx/event/Manager.js +4 -0
  127. package/source/class/qx/event/Messaging.js +2 -0
  128. package/source/class/qx/event/Pool.js +7 -0
  129. package/source/class/qx/event/Registration.js +33 -55
  130. package/source/class/qx/event/Timer.js +2 -0
  131. package/source/class/qx/event/Utils.js +25 -8
  132. package/source/class/qx/event/dispatch/AbstractBubbling.js +98 -194
  133. package/source/class/qx/event/dispatch/Direct.js +18 -13
  134. package/source/class/qx/event/handler/Appear.js +20 -24
  135. package/source/class/qx/event/handler/Application.js +4 -0
  136. package/source/class/qx/event/handler/DragDrop.js +182 -385
  137. package/source/class/qx/event/handler/Element.js +3 -0
  138. package/source/class/qx/event/handler/Focus.js +36 -30
  139. package/source/class/qx/event/handler/Input.js +5 -0
  140. package/source/class/qx/event/handler/Keyboard.js +107 -165
  141. package/source/class/qx/event/handler/Pointer.js +39 -68
  142. package/source/class/qx/event/handler/PointerCore.js +7 -25
  143. package/source/class/qx/event/handler/Window.js +5 -0
  144. package/source/class/qx/event/type/Event.js +12 -0
  145. package/source/class/qx/event/type/KeySequence.js +3 -0
  146. package/source/class/qx/event/type/Native.js +3 -0
  147. package/source/class/qx/html/Element.js +26 -91
  148. package/source/class/qx/io/jsonrpc/Client.js +1 -1
  149. package/source/class/qx/io/jsonrpc/protocol/Error.js +2 -2
  150. package/source/class/qx/io/jsonrpc/protocol/Parser.js +1 -0
  151. package/source/class/qx/io/jsonrpc/protocol/Result.js +2 -2
  152. package/source/class/qx/io/request/Xhr.js +3 -8
  153. package/source/class/qx/lang/normalize/Array.js +23 -1
  154. package/source/class/qx/locale/Date.js +520 -113
  155. package/source/class/qx/locale/LocalizedString.js +3 -0
  156. package/source/class/qx/locale/Manager.js +14 -3
  157. package/source/class/qx/locale/Number.js +60 -7
  158. package/source/class/qx/log/Logger.js +1 -1
  159. package/source/class/qx/module/Animation.js +2 -0
  160. package/source/class/qx/module/Attribute.js +2 -0
  161. package/source/class/qx/module/Css.js +7 -24
  162. package/source/class/qx/module/Event.js +2 -0
  163. package/source/class/qx/module/Manipulating.js +2 -0
  164. package/source/class/qx/module/Traversing.js +2 -0
  165. package/source/class/qx/test/Bootstrap.js +68 -53
  166. package/source/class/qx/test/Class.js +310 -2
  167. package/source/class/qx/test/Mixin.js +192 -42
  168. package/source/class/qx/test/Promise.js +129 -331
  169. package/source/class/qx/test/Theme.js +11 -0
  170. package/source/class/qx/test/bom/Font.js +2 -5
  171. package/source/class/qx/test/bom/Template.js +1 -1
  172. package/source/class/qx/test/compiler/ClassFile.js +14 -0
  173. package/source/class/qx/test/core/Assert.js +12 -0
  174. package/source/class/qx/test/core/Environment.js +17 -3
  175. package/source/class/qx/test/core/InheritanceDummy.js +10 -1
  176. package/source/class/qx/test/core/Object.js +51 -24
  177. package/source/class/qx/test/core/ObjectId.js +10 -1
  178. package/source/class/qx/test/core/Property.js +1338 -121
  179. package/source/class/qx/test/core/PropertyHelper.js +12 -0
  180. package/source/class/qx/test/core/Target.js +1 -0
  181. package/source/class/qx/test/core/Validation.js +2 -0
  182. package/source/class/qx/test/data/DataArray.js +218 -639
  183. package/source/class/qx/test/data/DataArrayWithChangeBubble.js +45 -215
  184. package/source/class/qx/test/data/MultiBinding.js +42 -0
  185. package/source/class/qx/test/data/async/__init__.js +4 -0
  186. package/source/class/qx/test/data/controller/Form.js +523 -14
  187. package/source/class/qx/test/data/controller/List.js +94 -426
  188. package/source/class/qx/test/data/controller/ListReverse.js +5 -20
  189. package/source/class/qx/test/data/controller/ListWithObjects.js +49 -225
  190. package/source/class/qx/test/data/controller/Object.js +54 -222
  191. package/source/class/qx/test/data/controller/Tree.js +195 -934
  192. package/source/class/qx/test/data/marshal/Json.js +74 -312
  193. package/source/class/qx/test/data/singlevalue/Array.js +55 -279
  194. package/source/class/qx/test/data/singlevalue/Async.js +173 -0
  195. package/source/class/qx/test/data/singlevalue/Deep.js +148 -327
  196. package/source/class/qx/test/data/singlevalue/Resolve.js +8 -28
  197. package/source/class/qx/test/data/singlevalue/Simple.js +124 -359
  198. package/source/class/qx/test/data/store/Json.js +86 -254
  199. package/source/class/qx/test/data/store/Jsonp.js +9 -29
  200. package/source/class/qx/test/data/store/Offline.js +2 -8
  201. package/source/class/qx/test/data/store/Rest.js +3 -3
  202. package/source/class/qx/test/dev/unit/Requirements.js +26 -10
  203. package/source/class/qx/test/event/GlobalError.js +2 -2
  204. package/source/class/qx/test/html/Iframe.js +1 -1
  205. package/source/class/qx/test/io/graphql/Client.js +2 -0
  206. package/source/class/qx/test/io/jsonrpc/Protocol.js +4 -2
  207. package/source/class/qx/test/io/request/MRequest.js +2 -8
  208. package/source/class/qx/test/io/request/Xhr.js +27 -117
  209. package/source/class/qx/test/lang/Function.js +6 -25
  210. package/source/class/qx/test/lang/Type.js +31 -13
  211. package/source/class/qx/test/locale/Date.js +173 -2
  212. package/source/class/qx/test/locale/Locale.js +23 -28
  213. package/source/class/qx/test/locale/Number.js +71 -0
  214. package/source/class/qx/test/log/Logger.js +7 -1
  215. package/source/class/qx/test/log/fixture/ClassA.js +2 -5
  216. package/source/class/qx/test/mobile/basic/Atom.js +3 -3
  217. package/source/class/qx/test/mobile/container/Scroll.js +4 -4
  218. package/source/class/qx/test/mobile/form/CheckBox.js +6 -12
  219. package/source/class/qx/test/performance/Property.js +5 -4
  220. package/source/class/qx/test/performance/widget/WidgetWithDecorator.js +2 -0
  221. package/source/class/qx/test/theme/Simple.js +34 -0
  222. package/source/class/qx/test/{MAppearance.js → theme/SimpleAppearance.js} +5 -4
  223. package/source/class/qx/test/{MDecoration.js → theme/SimpleDecoration.js} +6 -4
  224. package/source/class/qx/test/theme/manager/Meta.js +7 -5
  225. package/source/class/qx/test/tool/__init__.js +3 -0
  226. package/source/class/qx/test/tool/cli/AbstractValue.js +274 -0
  227. package/source/class/qx/test/tool/cli/Argument.js +384 -0
  228. package/source/class/qx/test/tool/cli/Command.js +387 -0
  229. package/source/class/qx/test/tool/cli/Flag.js +413 -0
  230. package/source/class/qx/test/tool/cli/__init__.js +3 -0
  231. package/source/class/qx/test/ui/LayoutTestCase.js +1 -14
  232. package/source/class/qx/test/ui/basic/Label.js +106 -0
  233. package/source/class/qx/test/ui/core/Blocker.js +125 -3
  234. package/source/class/qx/test/ui/form/Form.js +106 -0
  235. package/source/class/qx/test/ui/form/FormManager.js +6 -5
  236. package/source/class/qx/test/ui/form/SplitButton.js +1 -1
  237. package/source/class/qx/test/ui/toolbar/OverflowHandling.js +13 -14
  238. package/source/class/qx/test/ui/toolbar/ToolBar.js +16 -16
  239. package/source/class/qx/test/ui/tree/TreeFolder.js +5 -7
  240. package/source/class/qx/test/ui/tree/virtual/AbstractTreeTest.js +2 -0
  241. package/source/class/qx/test/ui/tree/virtual/Tree.js +36 -0
  242. package/source/class/qx/test/util/DateFormat.js +1 -1
  243. package/source/class/qx/test/util/PropertyUtil.js +0 -36
  244. package/source/class/qx/theme/classic/Appearance.js +1 -1
  245. package/source/class/qx/theme/indigo/ColorDark.js +2 -0
  246. package/source/class/qx/theme/manager/Font.js +6 -1
  247. package/source/class/qx/theme/manager/Meta.js +2 -1
  248. package/source/class/qx/theme/simple/Appearance.js +31 -95
  249. package/source/class/qx/theme/simple/Decoration.js +0 -1
  250. package/source/class/qx/theme/tangible/Appearance.js +1 -1
  251. package/source/class/qx/tool/cli/AbstractCliApp.js +72 -0
  252. package/source/class/qx/tool/cli/AbstractValue.js +186 -0
  253. package/source/class/qx/tool/cli/Argument.js +155 -0
  254. package/source/class/qx/tool/cli/Command.js +518 -0
  255. package/source/class/qx/tool/cli/Flag.js +202 -0
  256. package/source/class/qx/tool/cli/Parser.js +39 -0
  257. package/source/class/qx/tool/cli/__init__.js +26 -1
  258. package/source/class/qx/tool/compiler/Analyser.js +41 -13
  259. package/source/class/qx/tool/compiler/ClassFile.js +37 -9
  260. package/source/class/qx/tool/compiler/Console.js +2 -0
  261. package/source/class/qx/tool/compiler/MetaExtraction.js +53 -33
  262. package/source/class/qx/tool/compiler/app/Library.js +1 -1
  263. package/source/class/qx/tool/compiler/app/WebFont.js +2 -0
  264. package/source/class/qx/tool/compiler/cli/Application.js +58 -0
  265. package/source/class/qx/tool/{cli/commands → compiler/cli}/Command.js +99 -45
  266. package/source/class/qx/tool/{cli → compiler/cli}/ConfigDb.js +7 -7
  267. package/source/class/qx/tool/compiler/cli/ConfigLoader.js +272 -0
  268. package/source/class/qx/tool/{cli → compiler/cli}/LibraryApplication.js +3 -3
  269. package/source/class/qx/tool/compiler/cli/RootCommand.js +63 -0
  270. package/source/class/qx/tool/{cli → compiler/cli}/Watch.js +49 -24
  271. package/source/class/qx/tool/compiler/cli/__init__.js +3 -0
  272. package/source/class/qx/tool/{cli → compiler/cli}/api/AbstractApi.js +2 -11
  273. package/source/class/qx/tool/{cli → compiler/cli}/api/CompilerApi.js +11 -10
  274. package/source/class/qx/tool/{cli → compiler/cli}/api/LibraryApi.js +13 -4
  275. package/source/class/qx/tool/{cli → compiler/cli}/api/Test.js +1 -1
  276. package/source/class/qx/tool/compiler/cli/commands/Add.js +49 -0
  277. package/source/class/qx/tool/{cli → compiler/cli}/commands/Clean.js +12 -25
  278. package/source/class/qx/tool/{cli → compiler/cli}/commands/Compile.js +524 -615
  279. package/source/class/qx/tool/{cli → compiler/cli}/commands/Config.js +22 -20
  280. package/source/class/qx/tool/{cli → compiler/cli}/commands/Create.js +77 -54
  281. package/source/class/qx/tool/{cli → compiler/cli}/commands/Deploy.js +45 -60
  282. package/source/class/qx/tool/{cli → compiler/cli}/commands/Es6ify.js +57 -41
  283. package/source/class/qx/tool/{cli → compiler/cli}/commands/ExportGlyphs.js +26 -7
  284. package/source/class/qx/tool/compiler/cli/commands/Lint.js +420 -0
  285. package/source/class/qx/tool/{cli → compiler/cli}/commands/Migrate.js +40 -20
  286. package/source/class/qx/tool/{cli → compiler/cli}/commands/Package.js +20 -32
  287. package/source/class/qx/tool/compiler/cli/commands/Pkg.js +36 -0
  288. package/source/class/qx/tool/compiler/cli/commands/Prettier.js +278 -0
  289. package/source/class/qx/tool/{cli → compiler/cli}/commands/Run.js +43 -39
  290. package/source/class/qx/tool/{cli → compiler/cli}/commands/Serve.js +63 -61
  291. package/source/class/qx/tool/{cli → compiler/cli}/commands/Test.js +49 -52
  292. package/source/class/qx/tool/{cli → compiler/cli}/commands/Typescript.js +51 -30
  293. package/source/class/qx/tool/{cli → compiler/cli}/commands/add/Class.js +54 -31
  294. package/source/class/qx/tool/{cli → compiler/cli}/commands/add/Script.js +56 -32
  295. package/source/class/qx/tool/{cli → compiler/cli}/commands/config/Delete.js +19 -13
  296. package/source/class/qx/tool/{cli → compiler/cli}/commands/config/Get.js +19 -13
  297. package/source/class/qx/tool/{cli → compiler/cli}/commands/config/List.js +20 -20
  298. package/source/class/qx/tool/{cli → compiler/cli}/commands/config/Set.js +28 -20
  299. package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Install.js +140 -75
  300. package/source/class/qx/tool/{cli → compiler/cli}/commands/package/List.js +119 -80
  301. package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Publish.js +194 -178
  302. package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Remove.js +18 -21
  303. package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Update.js +90 -69
  304. package/source/class/qx/tool/{cli → compiler/cli}/commands/package/Upgrade.js +67 -54
  305. package/source/class/qx/tool/compiler/makers/AbstractAppMaker.js +2 -1
  306. package/source/class/qx/tool/compiler/resources/Manager.js +2 -0
  307. package/source/class/qx/tool/compiler/resources/ScssConverter.js +1 -1
  308. package/source/class/qx/tool/compiler/resources/ScssFile.js +1 -1
  309. package/source/class/qx/tool/compiler/targets/Target.js +5 -10
  310. package/source/class/qx/tool/compiler/targets/TypeScriptWriter.js +6 -2
  311. package/source/class/qx/tool/compiler/targets/meta/ApplicationMeta.js +2 -4
  312. package/source/class/qx/tool/compiler/targets/meta/BootJs.js +2 -0
  313. package/source/class/qx/tool/compiler/targets/meta/PackageJavascript.js +2 -0
  314. package/source/class/qx/tool/config/Abstract.js +5 -5
  315. package/source/class/qx/tool/config/Lockfile.js +1 -1
  316. package/source/class/qx/tool/migration/BaseMigration.js +9 -7
  317. package/source/class/qx/tool/migration/M6_0_0.js +3 -3
  318. package/source/class/qx/tool/migration/M8_0_0.js +958 -0
  319. package/source/class/qx/tool/utils/Debounce.js +0 -1
  320. package/source/class/qx/tool/utils/Http.js +109 -21
  321. package/source/class/qx/tool/utils/LogManager.js +7 -0
  322. package/source/class/qx/tool/utils/Promisify.js +12 -1
  323. package/source/class/qx/tool/utils/QooxdooVersions.js +193 -0
  324. package/source/class/qx/tool/utils/Utils.js +8 -5
  325. package/source/class/qx/tool/utils/Website.js +9 -222
  326. package/source/class/qx/tool/utils/Zip.js +47 -0
  327. package/source/class/qx/tool/utils/files/Utils.js +3 -11
  328. package/source/class/qx/tool/utils/json/Tokenizer.js +5 -0
  329. package/source/class/qx/ui/basic/Atom.js +8 -8
  330. package/source/class/qx/ui/core/Blocker.js +17 -4
  331. package/source/class/qx/ui/core/DragDropCursor.js +2 -1
  332. package/source/class/qx/ui/core/EventHandler.js +13 -21
  333. package/source/class/qx/ui/core/LayoutItem.js +8 -31
  334. package/source/class/qx/ui/core/MExecutable.js +7 -31
  335. package/source/class/qx/ui/core/MNativeOverflow.js +4 -2
  336. package/source/class/qx/ui/core/Widget.js +50 -165
  337. package/source/class/qx/ui/core/scroll/IScrollBar.js +9 -3
  338. package/source/class/qx/ui/core/scroll/ScrollBar.js +7 -1
  339. package/source/class/qx/ui/core/scroll/ScrollPane.js +12 -4
  340. package/source/class/qx/ui/embed/Html.js +6 -2
  341. package/source/class/qx/ui/form/AbstractField.js +4 -12
  342. package/source/class/qx/ui/form/Button.js +6 -4
  343. package/source/class/qx/ui/form/CheckedSelectBox.js +8 -8
  344. package/source/class/qx/ui/form/FileSelectorButton.js +1 -1
  345. package/source/class/qx/ui/form/Form.js +3 -0
  346. package/source/class/qx/ui/form/IListItem.js +3 -1
  347. package/source/class/qx/ui/form/IRadioItem.js +3 -1
  348. package/source/class/qx/ui/form/MForm.js +3 -1
  349. package/source/class/qx/ui/form/Slider.js +6 -2
  350. package/source/class/qx/ui/form/SplitButton.js +5 -5
  351. package/source/class/qx/ui/form/TextField.js +1 -2
  352. package/source/class/qx/ui/form/validation/Manager.js +6 -2
  353. package/source/class/qx/ui/menubar/Button.js +1 -1
  354. package/source/class/qx/ui/mobile/basic/Atom.js +5 -5
  355. package/source/class/qx/ui/mobile/dialog/Menu.js +9 -31
  356. package/source/class/qx/ui/mobile/dialog/Popup.js +13 -1
  357. package/source/class/qx/ui/table/pane/FocusIndicator.js +5 -2
  358. package/source/class/qx/ui/table/pane/Scroller.js +5 -20
  359. package/source/class/qx/ui/table/selection/Model.js +1 -0
  360. package/source/class/qx/ui/toolbar/Button.js +1 -1
  361. package/source/class/qx/ui/toolbar/CheckBox.js +1 -1
  362. package/source/class/qx/ui/toolbar/FileSelectorButton.js +1 -2
  363. package/source/class/qx/ui/toolbar/Part.js +2 -2
  364. package/source/class/qx/ui/toolbar/PartContainer.js +2 -2
  365. package/source/class/qx/ui/toolbar/ToolBar.js +24 -49
  366. package/source/class/qx/ui/tree/VirtualTree.js +6 -4
  367. package/source/class/qx/ui/tree/core/AbstractItem.js +10 -17
  368. package/source/class/qx/ui/tree/core/IVirtualTree.js +4 -2
  369. package/source/class/qx/ui/tree/provider/IVirtualTreeProvider.js +20 -10
  370. package/source/class/qx/ui/treevirtual/SimpleTreeDataModel.js +4 -1
  371. package/source/class/qx/ui/virtual/cell/Cell.js +20 -48
  372. package/source/class/qx/ui/virtual/cell/WidgetCell.js +2 -4
  373. package/source/class/qx/ui/virtual/core/Axis.js +4 -0
  374. package/source/class/qx/ui/virtual/core/ILayer.js +14 -10
  375. package/source/class/qx/ui/virtual/core/Scroller.js +4 -4
  376. package/source/class/qx/ui/virtual/layer/WidgetCell.js +4 -0
  377. package/source/class/qx/ui/virtual/selection/Abstract.js +3 -0
  378. package/source/class/qx/ui/virtual/selection/MModel.js +1 -1
  379. package/source/class/qx/ui/window/IDesktop.js +6 -2
  380. package/source/class/qx/ui/window/IWindowManager.js +10 -4
  381. package/source/class/qx/ui/window/MDesktop.js +2 -1
  382. package/source/class/qx/ui/window/Manager.js +1 -1
  383. package/source/class/qx/ui/window/Window.js +6 -4
  384. package/source/class/qx/util/OOUtil.js +8 -9
  385. package/source/class/qx/util/PropertyUtil.js +34 -154
  386. package/source/class/qx/util/ResponseParser.js +2 -0
  387. package/source/class/qx/util/Serializer.js +69 -114
  388. package/source/class/qx/util/format/DateFormat.js +3 -2
  389. package/source/global.d.ts +4 -0
  390. package/source/resource/qx/tool/bin/download-assets +0 -2
  391. package/source/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-node.tmpl.js +1 -0
  392. package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/cli/templates/template_vars.js +12 -9
  393. package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/schema/Manifest-1-0-0.json +2 -2
  394. package/source/resource/qx/tool/{schema → compiler/schema}/Manifest-2-0-0.json +2 -2
  395. package/source/resource/qx/tool/{schema → compiler/schema}/compile-1-0-0.json +15 -3
  396. package/{lib/resource/qx/tool → source/resource/qx/tool/compiler}/schema/qooxdoo-1-0-0.json +1 -1
  397. package/source/resource/qx/tool/website/build/404.html +22 -22
  398. package/source/resource/qx/tool/website/build/about.html +23 -23
  399. package/source/resource/qx/tool/website/build/assets/common.js +30 -18
  400. package/source/resource/qx/tool/website/build/assets/custom.css +290 -0
  401. package/source/resource/qx/tool/website/build/assets/qxWeb.js +28 -0
  402. package/source/resource/qx/tool/website/build/diagnostics/dependson.html +30 -30
  403. package/source/resource/qx/tool/website/build/diagnostics/dependson.js +49 -40
  404. package/source/resource/qx/tool/website/build/diagnostics/requiredby.html +20 -23
  405. package/source/resource/qx/tool/website/build/diagnostics/requiredby.js +38 -31
  406. package/source/resource/qx/tool/website/build/index.html +24 -24
  407. package/source/resource/qx/tool/website/build/scripts/serve.js +63 -65
  408. package/source/resource/qx/tool/website/partials/footer.html +8 -13
  409. package/source/resource/qx/tool/website/partials/head.html +9 -7
  410. package/source/resource/qx/tool/website/partials/header.html +3 -3
  411. package/source/resource/qx/tool/website/src/assets/common.js +32 -0
  412. package/source/resource/qx/tool/website/src/assets/custom.css +290 -0
  413. package/source/resource/qx/tool/website/src/assets/qxWeb.js +28 -0
  414. package/source/resource/qx/tool/website/src/diagnostics/dependson.js +49 -40
  415. package/source/resource/qx/tool/website/src/diagnostics/requiredby.js +38 -31
  416. package/source/resource/qx/tool/website/src/index.html +2 -2
  417. package/source/resource/qx/tool/website/src/scripts/serve.js +63 -65
  418. package/lib/resource/qx/tool/bin/build-devtools +0 -13
  419. package/lib/resource/qx/tool/bin/build-website +0 -15
  420. package/lib/resource/qx/tool/bin/download-assets +0 -23
  421. package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css.map +0 -1
  422. package/lib/resource/qx/tool/website/build/assets/bootstrap.css +0 -7
  423. package/lib/resource/qx/tool/website/build/assets/bootstrap.min.css +0 -7
  424. package/lib/resource/qx/tool/website/build/assets/bootstrap.min.css.map +0 -1
  425. package/lib/resource/qx/tool/website/build/assets/jquery.js +0 -5453
  426. package/lib/resource/qx/tool/website/build/qooxdoo.css +0 -21
  427. package/lib/resource/qx/tool/website/sass/qooxdoo.css +0 -3
  428. package/lib/resource/qx/tool/website/sass/qooxdoo.css.map +0 -1
  429. package/lib/resource/qx/tool/website/src/assets/bootstrap.css +0 -7
  430. package/lib/resource/qx/tool/website/src/assets/bootstrap.min.css +0 -7
  431. package/lib/resource/qx/tool/website/src/assets/bootstrap.min.css.map +0 -1
  432. package/lib/resource/qx/tool/website/src/assets/jquery.js +0 -5453
  433. package/source/class/qx/core/Property.js +0 -2100
  434. package/source/class/qx/tool/cli/Application.js +0 -47
  435. package/source/class/qx/tool/cli/Cli.js +0 -713
  436. package/source/class/qx/tool/cli/commands/Add.js +0 -46
  437. package/source/class/qx/tool/cli/commands/Lint.js +0 -255
  438. package/source/class/qx/tool/cli/commands/Pkg.js +0 -56
  439. package/source/class/qx/tool/cli/commands/package/Migrate.js +0 -37
  440. package/source/class/qx/tool/compiler/app/Cldr.js +0 -725
  441. package/source/resource/qx/tool/bin/build-devtools +0 -13
  442. package/source/resource/qx/tool/bin/build-website +0 -15
  443. package/source/resource/qx/tool/website/build/assets/bootstrap.css +0 -7
  444. package/source/resource/qx/tool/website/build/assets/bootstrap.min.css +0 -7
  445. package/source/resource/qx/tool/website/build/assets/bootstrap.min.css.map +0 -1
  446. package/source/resource/qx/tool/website/build/assets/jquery.js +0 -5453
  447. package/source/resource/qx/tool/website/build/qooxdoo.css +0 -21
  448. package/source/resource/qx/tool/website/sass/qooxdoo.scss +0 -31
  449. package/source/resource/qx/tool/website/src/assets/bootstrap.css +0 -7
  450. package/source/resource/qx/tool/website/src/assets/bootstrap.min.css +0 -7
  451. package/source/resource/qx/tool/website/src/assets/bootstrap.min.css.map +0 -1
  452. package/source/resource/qx/tool/website/src/assets/jquery.js +0 -5453
  453. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/TypeScriptWriter-base_declaration.d.ts +0 -0
  454. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/default.tmpl.js +0 -0
  455. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/header.tmpl.js +0 -0
  456. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/interface.tmpl.js +0 -0
  457. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/mixin.tmpl.js +0 -0
  458. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/class/singleton.tmpl.js +0 -0
  459. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-browser.tmpl.js +0 -0
  460. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-rhino.tmpl.js +0 -0
  461. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/.gitignore.tmpl +0 -0
  462. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/Manifest.tmpl.json +0 -0
  463. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/compile.tmpl.json +0 -0
  464. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/readme.tmpl.md +0 -0
  465. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/index.tmpl.html +0 -0
  466. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/nojs.tmpl.html +0 -0
  467. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/Application.tmpl.js +0 -0
  468. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/__init__.tmpl.js +0 -0
  469. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/test/DemoTest.tmpl.js +0 -0
  470. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Appearance.tmpl.js +0 -0
  471. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Color.tmpl.js +0 -0
  472. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Decoration.tmpl.js +0 -0
  473. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Font.tmpl.js +0 -0
  474. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Theme.tmpl.js +0 -0
  475. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/app.png +0 -0
  476. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/favicon.png +0 -0
  477. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/js_256x256.png +0 -0
  478. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/test.png +0 -0
  479. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/translation/readme.txt +0 -0
  480. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/.gitignore.tmpl +0 -0
  481. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/Manifest.tmpl.json +0 -0
  482. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/compile.tmpl.json +0 -0
  483. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/readme.tmpl.md +0 -0
  484. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/index.tmpl.html +0 -0
  485. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/nojs.tmpl.html +0 -0
  486. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/Application.tmpl.js +0 -0
  487. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/__init__.tmpl.js +0 -0
  488. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Login.tmpl.js +0 -0
  489. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Overview.tmpl.js +0 -0
  490. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/__init__.tmpl.js +0 -0
  491. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/app.png +0 -0
  492. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/css/.gitignore.tmpl +0 -0
  493. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/favicon.png +0 -0
  494. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/js_256x256.png +0 -0
  495. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/theme/custom/css/custom.css +0 -0
  496. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/translation/readme.txt +0 -0
  497. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/.gitignore.tmpl +0 -0
  498. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/Manifest.tmpl.json +0 -0
  499. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/compile.tmpl.json +0 -0
  500. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/readme.tmpl.md +0 -0
  501. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/Button.tmpl.js +0 -0
  502. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/__init__.tmpl.js +0 -0
  503. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/demo/Application.tmpl.js +0 -0
  504. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/resource/custom/test.png +0 -0
  505. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/test/DemoTest.tmpl.js +0 -0
  506. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Appearance.tmpl.js +0 -0
  507. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Color.tmpl.js +0 -0
  508. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Decoration.tmpl.js +0 -0
  509. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Font.tmpl.js +0 -0
  510. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Theme.tmpl.js +0 -0
  511. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/resource/custom/test.png +0 -0
  512. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/translation/readme.txt +0 -0
  513. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/.gitignore.tmpl +0 -0
  514. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/Manifest.tmpl.json +0 -0
  515. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/compile.tmpl.json +0 -0
  516. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/readme.tmpl.txt +0 -0
  517. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/Application.tmpl.js +0 -0
  518. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/__init__.tmpl.js +0 -0
  519. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/test/DemoTest.tmpl.js +0 -0
  520. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/resource/custom/.gitignore.tmpl +0 -0
  521. /package/lib/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/translation/readme.txt +0 -0
  522. /package/lib/resource/qx/tool/{loadsass.js → compiler/loadsass.js} +0 -0
  523. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/TypeScriptWriter-base_declaration.d.ts +0 -0
  524. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/default.tmpl.js +0 -0
  525. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/header.tmpl.js +0 -0
  526. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/interface.tmpl.js +0 -0
  527. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/mixin.tmpl.js +0 -0
  528. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/class/singleton.tmpl.js +0 -0
  529. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-browser.tmpl.js +0 -0
  530. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/loader/loader-rhino.tmpl.js +0 -0
  531. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/.gitignore.tmpl +0 -0
  532. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/Manifest.tmpl.json +0 -0
  533. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/compile.tmpl.json +0 -0
  534. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/readme.tmpl.md +0 -0
  535. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/index.tmpl.html +0 -0
  536. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/boot/nojs.tmpl.html +0 -0
  537. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/Application.tmpl.js +0 -0
  538. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/__init__.tmpl.js +0 -0
  539. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/test/DemoTest.tmpl.js +0 -0
  540. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Appearance.tmpl.js +0 -0
  541. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Color.tmpl.js +0 -0
  542. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Decoration.tmpl.js +0 -0
  543. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Font.tmpl.js +0 -0
  544. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/class/custom/theme/Theme.tmpl.js +0 -0
  545. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/app.png +0 -0
  546. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/favicon.png +0 -0
  547. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/js_256x256.png +0 -0
  548. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/resource/custom/test.png +0 -0
  549. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/desktop/source/translation/readme.txt +0 -0
  550. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/.gitignore.tmpl +0 -0
  551. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/Manifest.tmpl.json +0 -0
  552. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/compile.tmpl.json +0 -0
  553. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/readme.tmpl.md +0 -0
  554. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/index.tmpl.html +0 -0
  555. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/boot/nojs.tmpl.html +0 -0
  556. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/Application.tmpl.js +0 -0
  557. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/__init__.tmpl.js +0 -0
  558. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Login.tmpl.js +0 -0
  559. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/Overview.tmpl.js +0 -0
  560. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/class/custom/page/__init__.tmpl.js +0 -0
  561. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/app.png +0 -0
  562. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/css/.gitignore.tmpl +0 -0
  563. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/favicon.png +0 -0
  564. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/resource/custom/js_256x256.png +0 -0
  565. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/theme/custom/scss/_styles.scss +0 -0
  566. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/theme/custom/scss/custom.scss +0 -0
  567. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/mobile/source/translation/readme.txt +0 -0
  568. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/.gitignore.tmpl +0 -0
  569. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/Manifest.tmpl.json +0 -0
  570. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/compile.tmpl.json +0 -0
  571. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/readme.tmpl.md +0 -0
  572. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/Button.tmpl.js +0 -0
  573. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/__init__.tmpl.js +0 -0
  574. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/demo/Application.tmpl.js +0 -0
  575. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/resource/custom/test.png +0 -0
  576. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/test/DemoTest.tmpl.js +0 -0
  577. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Appearance.tmpl.js +0 -0
  578. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Color.tmpl.js +0 -0
  579. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Decoration.tmpl.js +0 -0
  580. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Font.tmpl.js +0 -0
  581. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/class/custom/theme/Theme.tmpl.js +0 -0
  582. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/resource/custom/test.png +0 -0
  583. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/package/source/translation/readme.txt +0 -0
  584. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/.gitignore.tmpl +0 -0
  585. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/Manifest.tmpl.json +0 -0
  586. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/compile.tmpl.json +0 -0
  587. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/readme.tmpl.txt +0 -0
  588. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/Application.tmpl.js +0 -0
  589. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/__init__.tmpl.js +0 -0
  590. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/class/custom/test/DemoTest.tmpl.js +0 -0
  591. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/resource/custom/.gitignore.tmpl +0 -0
  592. /package/source/resource/qx/tool/{cli → compiler/cli}/templates/skeleton/server/source/translation/readme.txt +0 -0
  593. /package/source/resource/qx/tool/{loadsass.js → compiler/loadsass.js} +0 -0
@@ -5,1547 +5,639 @@
5
5
  http://qooxdoo.org
6
6
 
7
7
  Copyright:
8
- 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
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
- * Martin Wittemann (martinwittemann)
15
+ * John Spackman (https://github.com/johnspackman, john.spackman@zenesis.com)
16
+ * Patryk Malinowski (https://github.com/patryk-m-malinowski, pmalinowski@vmn.digital)
16
17
 
17
18
  ************************************************************************ */
18
19
 
19
20
  /**
20
- * Single-value binding is a core component of the data binding package.
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
- statics: {
24
- /** internal reference for all bindings indexed by source object */
25
- __bindings: {},
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
- /** internal reference for all bindings indexed by target object */
28
- __bindingsByTarget: {},
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
- * The function is responsible for binding a source objects property to
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
- bind(
115
- sourceObject,
116
- sourcePropertyChain,
117
- targetObject,
118
- targetPropertyChain,
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: null,
176
+ /**
177
+ * @type {qx.core.Object}
178
+ */
179
+ __source: null,
207
180
 
208
- // save the current source
209
- sources[i] = source;
210
-
211
- // check for the last property
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
- // store the listener for further processing
289
- listeners.push(listener);
186
+ /**
187
+ * @type {qx.core.Object}
188
+ */
189
+ __target: null,
290
190
 
291
- // add the chaining listener
292
- listenerIds[i] = source.addListener(eventNames[i], listener);
293
- }
191
+ /** @type {Promise} initialisation promise */
192
+ __initPromise: null,
294
193
 
295
- // get and store the next source
296
- if (
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
- break;
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
- throw ex;
350
- }
351
-
352
- // create the id map
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
- return id;
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
- * @param context {Map} The current context for the listener.
216
+ * @returns {BindingRecord} The representation of this binding as record.
378
217
  */
379
- __chainListener(context) {
380
- // invoke the onUpdate method
381
- if (context.options && context.options.onUpdate) {
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
- // get the current source
402
- var source = context.sources[context.index];
403
- // add new once after the current one
404
- for (var j = context.index + 1; j < context.propertyNames.length; j++) {
405
- // get and store the new source
406
- if (context.arrayIndexValues[j - 1] !== "") {
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
- if (!eventName) {
554
- context.sources[j] = null;
555
- this.__resetTargetValue(
556
- context.targetObject,
557
- context.targetPropertyChain
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
- return;
561
- }
562
- context.listenerIds[j] = source.addListener(
563
- eventName,
564
- context.listeners[j]
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
- * Internal helper for setting up the listening to the changes on the
572
- * target side of the binding. Only works if the target property is a
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 sourceObject {qx.core.Object} The source of the binding.
576
- * @param sourcePropertyChain {String} The property chain which represents
577
- * the source property.
578
- * @param targetObject {qx.core.Object} The object which the source should
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
- __setUpTargetBinding(
587
- sourceObject,
588
- sourcePropertyChain,
589
- targetObject,
590
- targetPropertyChain,
591
- options
592
- ) {
593
- // get the property names
594
- var propertyNames = targetPropertyChain.split(".");
595
-
596
- var arrayIndexValues = this.__checkForArrayInPropertyChain(propertyNames);
597
- var targets = [];
598
- var listeners = [];
599
- var listenerIds = [];
600
- var eventNames = [];
601
- var target = targetObject;
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
- // save the current source
624
- targets[i] = target;
625
-
626
- // create a listener
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
- // get the current target
642
- var target = targets[i];
643
- // add new once after the current one
644
- for (var j = i + 1; j < propertyNames.length - 1; j++) {
645
- var firstUpPropName = qx.lang.String.firstUp(propertyNames[j - 1]);
646
- // get and store the new target
647
- if (arrayIndexValues[j - 1] !== "") {
648
- var currentIndex =
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 promise = 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
- // store the listener for further processing
697
- listeners.push(listener);
297
+ let out;
698
298
 
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]);
299
+ if (qx.Promise.isPromise(promise)) {
300
+ out = promise.then(cb);
708
301
  } else {
709
- target = target["get" + firstUpPropName]();
710
- }
711
- if (!target) {
712
- break;
302
+ out = cb();
713
303
  }
304
+ this.__initPromise = Promise.resolve(out);
305
+ return out;
714
306
  }
715
-
716
- return { listenerIds: listenerIds, targets: targets };
717
307
  },
718
308
 
719
309
  /**
720
- * Helper for updating the target. Gets the current set data from the source
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
310
+ * @returns {qx.core.Object} the source object
734
311
  */
735
- updateTarget(
736
- sourceObject,
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);
312
+ getSource() {
313
+ return this.__source;
754
314
  },
755
315
 
756
316
  /**
757
- * Internal helper for getting the current set value at the property chain.
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.
317
+ * Apply for `targetPath`
763
318
  */
764
- resolvePropertyChain(o, propertyChain) {
765
- var properties = this.__getPropertyChainArray(propertyChain);
766
- return this.__getTargetFromChain(o, properties, properties.length);
319
+ _applyTargetPath(value, oldValue) {
320
+ if (oldValue) {
321
+ throw new Error("Cannot change targetPath after binding has been created");
322
+ }
323
+ this.__record = null; // invalidate record representation cache
324
+ this.__targetSegments = qx.data.SingleValueBinding.__parseSegments(this, value);
325
+ this.__targetSegments.at(-1).addListener("changeInput", this.__updateTarget, this);
767
326
  },
768
327
 
769
328
  /**
770
- * Tries to return a fitting event name to the given source object and
771
- * property name. First, it assumes that the property name is a real property
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.
329
+ * Sets the target object of this binding.
330
+ * If a source is set, the target will be updated with source's value.
777
331
  *
778
- * @param source {qx.core.Object} The source where the property is stored.
779
- * @param propertyName {String} The name of the property.
780
- * @return {String|null} The name of the corresponding event or null.
332
+ * @param {qx.core.Object?} value The source object to get the `value` by looking up `sourcePath`
333
+ * @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,
334
+ * or setting the target was asynchronous.
335
+ * If everything was synchronous, then this will return null.
781
336
  */
782
- __getEventNameForProperty(source, propertyName) {
783
- // get the current event name from the property definition
784
- var eventName = this.__getEventForProperty(source, propertyName);
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
- }
337
+ setTarget(value) {
338
+ if (this.__target === value) {
339
+ return;
801
340
  }
802
- return eventName;
803
- },
804
341
 
805
- /**
806
- * Resets the value of the given target after resolving the target property
807
- * chain.
808
- *
809
- * @param targetObject {qx.core.Object} The object where the property chain
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
- }
342
+ this.__record = null; // invalidate record representation cache
343
+ this.__initPromise = null; // reset the init promise, as the target has changed
344
+ let oldValue = this.__target;
345
+ this.__target = value;
346
+ const SingleValueBinding = qx.data.SingleValueBinding;
827
347
 
828
- // try to reset the property
829
- if (
830
- target["reset" + qx.lang.String.firstUp(lastProperty)] != undefined
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);
348
+ if (oldValue) {
349
+ delete SingleValueBinding.__bindingsByTarget[oldValue.toHashCode()][this.toHashCode()];
350
+ if (qx.lang.Object.isEmpty(SingleValueBinding.__bindingsByTarget[oldValue.toHashCode()])) {
351
+ delete SingleValueBinding.__bindingsByTarget[oldValue.toHashCode()];
844
352
  }
845
353
  }
846
- },
847
354
 
848
- /**
849
- * Sets the given value to the given target after resolving the
850
- * target property chain.
851
- *
852
- * @param targetObject {qx.core.Object} The object where the property chain
853
- * starts.
854
- * @param targetPropertyChain {String} The names of the properties,
855
- * separated with a dot.
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
- }
355
+ if (value) {
356
+ const SingleValueBinding = qx.data.SingleValueBinding;
357
+ SingleValueBinding.__bindingsByTarget[value.toHashCode()] ??= {};
358
+ SingleValueBinding.__bindingsByTarget[value.toHashCode()][this.toHashCode()] = this;
359
+
360
+ let out = this.__targetSegments[0].setInput(value);
361
+ this.__initPromise = Promise.resolve(out);
362
+ return out;
885
363
  }
886
364
  },
887
365
 
888
366
  /**
889
- * Returns the index from a property using bracket notation, e.g.
890
- * "[42]" returns "42", "[last]" returns "last"
891
367
  *
892
- * @param propertyName {String} A property name
893
- * @return {String|null} Array index or null if the property name does
894
- * not use bracket notation
368
+ * @returns {qx.core.Object} the target object
895
369
  */
896
- __getArrayIndex(propertyName) {
897
- var arrayExp = /^\[(\d+|last)\]$/;
898
- var arrayMatch = propertyName.match(arrayExp);
899
- if (arrayMatch) {
900
- return arrayMatch[1];
901
- }
902
- return null;
370
+ getTarget() {
371
+ return this.__target;
903
372
  },
904
373
 
905
374
  /**
906
- * Converts a property chain string into a list of properties and/or
907
- * array indexes
908
- * @param targetPropertyChain {String} property chain
909
- * @return {String[]} Array of property names
375
+ * This method should not be called directly.
376
+ * It is only there to comply with interface `qx.data.binding.IInputReceiver`.
377
+ * @override interface qx.data.binding.IInputReceiver
378
+ *
379
+ * @param {*} input
910
380
  */
911
- __getPropertyChainArray(targetPropertyChain) {
912
- // split properties (dot notation) and array indexes (bracket notation)
913
- return targetPropertyChain
914
- .replace(/\[/g, ".[")
915
- .split(".")
916
- .filter(function (prop) {
917
- return prop !== "";
918
- });
381
+ setInput(input) {
382
+ return this.__setValue(input);
919
383
  },
920
384
 
921
385
  /**
922
- * Helper-Function resolving the object on which the last property of the
923
- * chain should be set.
924
386
  *
925
- * @param targetObject {qx.core.Object} The object where the property chain
926
- * starts.
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.
387
+ * @param {*} value The final value obtained from the sourcePath
388
+ * @returns {Promise?} A promise if setting the target is asynchronous, otherwise null
932
389
  */
933
- __getTargetFromChain(targetObject, targetProperties, index) {
934
- index = index || targetProperties.length - 1;
935
- var target = targetObject;
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
- }
390
+ __setValue(value) {
391
+ if (this.__value === value) {
392
+ return null; // no change
955
393
  }
956
- return target;
394
+ this.__value = value;
395
+ return this.__updateTarget();
957
396
  },
958
397
 
959
398
  /**
960
- * Set the given value to the target property. This method is used for
961
- * initially set the value.
962
399
  *
963
- * @param value {var} The value to set.
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).
400
+ * @returns {*} the value that was set by the sourcePath
972
401
  */
973
- __setInitialValue(
974
- value,
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
- }
402
+ getValue() {
403
+ return this.__value;
1026
404
  },
1027
405
 
1028
406
  /**
1029
- * Checks for an array element in the given property names and adapts the
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.
407
+ * Updates the target with the current value
1036
408
  */
1037
- __checkForArrayInPropertyChain(propertyNames) {
1038
- // array for the values of the array properties
1039
- var arrayIndexValues = [];
1040
-
1041
- // go through all properties and check for array notations
1042
- for (var i = 0; i < propertyNames.length; i++) {
1043
- var name = propertyNames[i];
1044
- // if its an array property in the chain
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
- );
1057
- }
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
- }
409
+ __updateTarget() {
410
+ if (this.__targetSegments) {
411
+ //We need to make sure the target segments are up to date
412
+ //because the listeners may trigger after this point.
413
+ //This is important in bidirectional bindings.
414
+ for (let segment of this.__targetSegments) {
415
+ if (segment.getOutputReceiver()) {
416
+ segment.updateOutput();
1067
417
  }
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
418
  }
1089
419
  }
1090
420
 
1091
- return arrayIndexValues;
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
- }
421
+ let lastSegment = this.__targetSegments.at(-1);
1156
422
 
1157
- // get the data of the array
1158
- var data = sourceObject.getItem(arrayIndex);
1159
-
1160
- // reset the target if the data is not set
1161
- if (data === undefined) {
1162
- qx.data.SingleValueBinding.__resetTargetValue(
1163
- targetObject,
1164
- targetProperty
1165
- );
1166
- }
423
+ if (this.getTarget() && this.getSource()) {
424
+ let value = this.getValue();
1167
425
 
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();
1177
- }
1178
-
1179
- // debug message
1180
- if (qx.core.Environment.get("qx.debug.databinding")) {
1181
- qx.log.Logger.debug(
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);
426
+ let ignoreConverter = false;
427
+ if (this.__options.ignoreConverter) {
428
+ var match = this.getSourcePath().match(new RegExp("^" + this.__options.ignoreConverter));
429
+ ignoreConverter = match ? match.length > 0 : false;
1194
430
  }
1195
431
 
1196
- // convert the data
1197
- data = qx.data.SingleValueBinding.__convertValue(
1198
- data,
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);
432
+ if (this.__options.converter && (value !== undefined || !ignoreConverter)) {
433
+ let model = typeof this.getTarget().getModel == "function" ? this.getTarget().getModel() : null;
434
+ value = this.__options.converter(value, model, this.getSource(), this.getTarget());
1208
435
  }
1209
436
 
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
- );
437
+ const cb = ex => {
438
+ if (ex) {
439
+ this.__options.onSetFail?.();
1219
440
  } else {
1220
- result = qx.data.SingleValueBinding.__resetTargetValue(
1221
- targetObject,
1222
- targetProperty
1223
- );
441
+ this.__options.onUpdate?.(this.getSource(), this.getTarget(), value);
1224
442
  }
443
+ return null;
444
+ };
1225
445
 
1226
- // tell the user that the setter was invoked probably
1227
- if (options && options.onUpdate) {
1228
- options.onUpdate(sourceObject, targetObject, data);
1229
- }
446
+ let ret;
447
+ try {
448
+ ret = lastSegment.setTargetValue(value);
1230
449
  } catch (ex) {
1231
- if (!(ex instanceof qx.core.ValidationError)) {
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
- }
450
+ return cb(ex);
1247
451
  }
1248
- return result;
1249
- };
1250
452
 
1251
- // check if an array index is given
1252
- if (!arrayIndex) {
1253
- // if not, signal it a s an empty string
1254
- arrayIndex = "";
453
+ if (qx.Promise.isPromise(ret)) {
454
+ return ret.then(cb, cb);
455
+ } else {
456
+ cb(null);
457
+ }
1255
458
  }
1256
- // bind the listener function (make the array index in the listener available)
1257
- bindListener = qx.lang.Function.bind(
1258
- bindListener,
1259
- sourceObject,
1260
- arrayIndex
1261
- );
459
+ }
460
+ },
1262
461
 
1263
- // add the listener
1264
- var id = sourceObject.addListener(sourceEvent, bindListener);
462
+ statics: {
463
+ /** @type {Object<String,Object<String,Binding>>} map of maps, outer map is indexed by object hash, inner is indexed by binding hash */
464
+ __bindingsBySource: {},
1265
465
 
1266
- return id;
1267
- },
466
+ /** @type {Object<String,Object<String,Binding>>} map of maps, outer map is indexed by object hash, inner is indexed by binding hash */
467
+ __bindingsByTarget: {},
1268
468
 
1269
469
  /**
1270
- * This method stores the given value as a binding in the internal structure
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.
470
+ * @see {qx.data.SingleValueBinding#construct}
1279
471
  */
1280
- __storeBinding(
1281
- id,
1282
- sourceObject,
1283
- sourceEvent,
1284
- targetObject,
1285
- targetProperty
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] = [];
472
+ bind(sourceObject, sourcePropertyChain, targetObject, targetPropertyChain, options) {
473
+ // check for the arguments
474
+ if (qx.core.Environment.get("qx.debug")) {
475
+ qx.core.Assert.assertObject(sourceObject, "sourceObject");
476
+ qx.core.Assert.assertString(sourcePropertyChain, "sourcePropertyChain");
477
+ qx.core.Assert.assertObject(targetObject, "targetObject");
478
+ qx.core.Assert.assertString(targetPropertyChain, "targetPropertyChain");
1293
479
  }
1294
480
 
1295
- var binding = [
1296
- id,
1297
- sourceObject,
1298
- sourceEvent,
1299
- targetObject,
1300
- targetProperty
1301
- ];
481
+ let binding = new qx.data.SingleValueBinding(sourcePropertyChain, targetPropertyChain, sourceObject, targetObject, options);
1302
482
 
1303
- this.__bindings[hash].push(binding);
1304
-
1305
- // add same binding data indexed by target object
1306
- hash = targetObject.toHashCode();
1307
- if (this.__bindingsByTarget[hash] === undefined) {
1308
- this.__bindingsByTarget[hash] = [];
1309
- }
1310
- this.__bindingsByTarget[hash].push(binding);
483
+ return binding;
1311
484
  },
1312
485
 
1313
486
  /**
1314
- * This method takes the given value, checks if the user has given a
1315
- * converter and converts the value to its target type. If no converter is
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.
487
+ * Removes the binding with the given id from the given sourceObject. The
488
+ * id has to be the id returned by any of the bind functions.
1326
489
  *
1327
- * @return {var} The converted value. If no conversion has been done, the
1328
- * value property will be returned.
1329
- * @throws {qx.core.AssertionError} If there is no property definition
1330
- * of the given target object and target property.
490
+ * @param sourceObject {qx.core.Object} The source object of the binding.
491
+ * @param id {var} The id of the binding.
492
+ * @throws {Error} If the binding could not be found.
1331
493
  */
1332
- __convertValue(
1333
- value,
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
- }
494
+ removeBindingFromObject(sourceObject, binding) {
495
+ binding.dispose();
1369
496
  },
1370
497
 
1371
498
  /**
1372
- * Helper method which tries to figure out if the given property on the
1373
- * given object does have a change event and if returns the name of it.
499
+ * Removes all bindings for the given object.
1374
500
  *
1375
- * @param sourceObject {qx.core.Object} The object to check.
1376
- * @param sourceProperty {String} The name of the property.
501
+ * @param object {qx.core.Object} The object of which the bindings should be
502
+ * removed.
503
+ * @throws {qx.core.AssertionError} If the object is not in the internal
504
+ * registry of the bindings.
505
+ * @throws {Error} If one of the bindings listed internally can not be
506
+ * removed.
507
+ */
508
+ removeAllBindingsForObject(object) {
509
+ qx.core.Assert.assertNotNull(object, "Null is not possible!");
510
+ qx.data.SingleValueBinding.getAllBindingsForObject(object).forEach(binding => binding[0].dispose());
511
+ },
512
+
513
+ /**
514
+ * Debug function which shows some valuable information about the given
515
+ * binding in console. For that it uses {@link qx.log.Logger}.
1377
516
  *
1378
- * @return {String} The name of the change event.
1379
- * @throws {qx.core.AssertionError} If there is no property definition of
1380
- * the given object property pair.
517
+ * @param object {qx.core.Object} the source of the binding.
518
+ * @param id {var} The id of the binding.
1381
519
  */
1382
- __getEventForProperty(sourceObject, sourceProperty) {
1383
- // get the event name
1384
- var propertieDefinition = qx.Class.getPropertyDefinition(
1385
- sourceObject.constructor,
1386
- sourceProperty
520
+ showBindingInLog(object, binding) {
521
+ qx.log.Logger.debug(
522
+ "Binding from '" +
523
+ binding.getSource() +
524
+ "' (" +
525
+ binding.getSourcePath() +
526
+ ") to the object '" +
527
+ binding.getTarget() +
528
+ "' (" +
529
+ binding.getTargetPath() +
530
+ ")."
1387
531
  );
1388
-
1389
- if (propertieDefinition == null) {
1390
- return null;
1391
- }
1392
- return propertieDefinition.event;
1393
532
  },
1394
533
 
1395
534
  /**
1396
- * Tries to convert the data to the type given in the targetCheck argument.
535
+ * Helper for updating the target. Gets the current set data from the source
536
+ * and set that on the target.
1397
537
  *
1398
- * @param data {var} The data to convert.
1399
- * @param targetCheck {String} The value of the check property. That usually
1400
- * contains the target type.
1401
- * @return {Integer|String|Float} The converted data
538
+ * @param sourceObject {qx.core.Object} The source of the binding.
539
+ * @param sourcePropertyChain {String} The property chain which represents
540
+ * the source property.
541
+ * @param targetObject {qx.core.Object} The object which the source should
542
+ * be bind to.
543
+ * @param targetPropertyChain {String} The property name of the target
544
+ * object.
545
+ * @param options {Map} The options map perhaps containing the user defined
546
+ * converter.
547
+ *
548
+ * @internal
1402
549
  */
1403
- __defaultConversion(data, targetCheck) {
1404
- var dataType = qx.lang.Type.getClass(data);
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
- }
550
+ updateTarget(sourceObject, sourcePropertyChain, targetObject, targetPropertyChain, options) {
551
+ options ??= {};
552
+ var value = this.resolvePropertyChain(sourceObject, sourcePropertyChain);
1421
553
 
1422
- // to float
1423
- if (
1424
- (dataType == "Number" || dataType == "String") &&
1425
- (targetCheck == "Number" || targetCheck == "PositiveNumber")
1426
- ) {
1427
- data = parseFloat(data);
554
+ // convert the data before setting
555
+ if (options.converter) {
556
+ let model = typeof targetObject.getModel == "function" ? targetObject.getModel() : null;
557
+ value = options.converter(value, model, sourceObject, targetObject);
1428
558
  }
1429
559
 
1430
- return data;
560
+ return this.__setTargetValue(targetObject, targetPropertyChain, value);
1431
561
  },
1432
562
 
1433
563
  /**
1434
- * Removes the binding with the given id from the given sourceObject. The
1435
- * id has to be the id returned by any of the bind functions.
564
+ * Sets the given value to the given target after resolving the
565
+ * target property chain.
1436
566
  *
1437
- * @param sourceObject {qx.core.Object} The source object of the binding.
1438
- * @param id {var} The id of the binding.
1439
- * @throws {Error} If the binding could not be found.
567
+ * @param targetObject {qx.core.Object} The object where the property chain
568
+ * starts.
569
+ * @param targetPropertyChain {String} The names of the properties,
570
+ * separated with a dot.
571
+ * @param value {var} The value to set.
1440
572
  */
1441
- removeBindingFromObject(sourceObject, id) {
1442
- // check for a deep binding
1443
- if (id.type == "deepBinding") {
1444
- // go through all added listeners (source)
1445
- for (var i = 0; i < id.sources.length; i++) {
1446
- // check if a source is available
1447
- if (id.sources[i]) {
1448
- if (id.listenerIds[i]) {
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
- }
573
+ __setTargetValue(targetObject, targetPropertyChain, value) {
574
+ let segments = qx.data.SingleValueBinding.__parseSegments(null, targetPropertyChain);
575
+ let lastSegment = segments[segments.length - 1];
576
+ segments[0].setInput(targetObject);
577
+ let out = lastSegment.setTargetValue(value);
578
+ segments.forEach(segment => segment.dispose());
579
+ return out;
580
+ },
1486
581
 
1487
- // remove the id from the internal reference system
1488
- var bindings = this.getAllBindingsForObject(sourceObject);
1489
- // check if the binding exists
1490
- if (bindings != undefined) {
1491
- for (var i = 0; i < bindings.length; i++) {
1492
- if (bindings[i][0] == id) {
1493
- // remove binding data from internal reference indexed by target object
1494
- var target = bindings[i][3];
1495
- if (this.__bindingsByTarget[target.toHashCode()]) {
1496
- qx.lang.Array.remove(
1497
- this.__bindingsByTarget[target.toHashCode()],
1498
- bindings[i]
1499
- );
1500
- }
1501
-
1502
- // remove binding data from internal reference indexed by source object
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
- }
582
+ /**
583
+ * Splits a property path into segments.
584
+ * @param {string} path
585
+ * @returns {string[]} an array of segments, split by dot and square brackets.
586
+ * For example, splitSegments(`a.b[0].c`) will return `["a", "b", "[0]", "c"]`
587
+ */
588
+ splitSegments(path) {
589
+ let out = [];
590
+ for (let dotSplit of path.split(".")) {
591
+ let bracketSplits = dotSplit.split("[");
592
+ for (let i = 0; i < bracketSplits.length; i++) {
593
+ let bracketSplit = bracketSplits[i];
594
+ if (i > 0) {
595
+ bracketSplit = "[" + bracketSplit;
596
+ }
597
+ out.push(bracketSplit);
1512
598
  }
1513
599
  }
1514
- throw new Error("Binding could not be found!");
600
+ return out.filter(s => s.length > 0);
1515
601
  },
1516
602
 
1517
603
  /**
1518
- * Removes all bindings for the given object.
604
+ * Finds all bindings for an object, as either a source or target
1519
605
  *
1520
- * @param object {qx.core.Object} The object of which the bindings should be
1521
- * removed.
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.
606
+ * @param {qx.core.Object} object
607
+ * @returns {BindingRecord[]} An array of the bindings represented as records.
1526
608
  */
1527
- removeAllBindingsForObject(object) {
1528
- // check for the null value
609
+ getAllBindingsForObject(object) {
610
+ const SingleValueBinding = qx.data.SingleValueBinding;
611
+ let allBindings = {
612
+ ...(SingleValueBinding.__bindingsBySource[object.toHashCode()] ?? {}),
613
+ ...(SingleValueBinding.__bindingsByTarget[object.toHashCode()] ?? {})
614
+ };
615
+ return Object.values(allBindings).map(binding => binding.asRecord());
616
+ },
1529
617
 
1530
- if (qx.core.Environment.get("qx.debug")) {
1531
- qx.core.Assert.assertNotNull(
1532
- object,
1533
- "Can not remove the bindings for null object!"
1534
- );
1535
- }
618
+ /**
619
+ * Returns a map containing for every bound object an array of data binding
620
+ * information. The key of the map is the hash code of the bound objects.
621
+ * Every binding is represented by an array containing id, sourceObject,
622
+ * sourceEvent, targetObject and targetProperty.
623
+ *
624
+ * @return {Object<string, BindingInfo>} Map containing all bindings.
625
+ *
626
+ * @typedef {[qx.data.SingleValueBinding, qx.core.Object, string, qx.core.Object, string]} BindingInfo
627
+ * Stores the binding ID, source object, source path, target object and target path respectively.
628
+ */
629
+ getAllBindings() {
630
+ let bindings = qx.data.SingleValueBinding.__bindingsBySource;
1536
631
 
1537
- // get the bindings
1538
- var bindings = this.getAllBindingsForObject(object);
1539
- if (bindings != undefined) {
1540
- // remove every binding with the removeBindingFromObject function
1541
- for (var i = bindings.length - 1; i >= 0; i--) {
1542
- this.removeBindingFromObject(object, bindings[i][0]);
632
+ let result = {};
633
+ for (let [objectHash, objectBindings] of Object.entries(bindings)) {
634
+ let objectBindingsArray = [];
635
+ for (let [bindingHash, binding] of Object.entries(objectBindings)) {
636
+ objectBindingsArray.push([binding, binding.getSource(), binding.getSourcePath(), binding.getTarget(), binding.getTargetPath()]);
1543
637
  }
638
+ result[objectHash] = objectBindingsArray;
1544
639
  }
1545
-
1546
- var hash = object.toHashCode();
1547
- delete this.__bindings[hash];
1548
- delete this.__bindingsByTarget[hash];
640
+ return result;
1549
641
  },
1550
642
 
1551
643
  /**
@@ -1561,149 +653,158 @@ qx.Class.define("qx.data.SingleValueBinding", {
1561
653
  * removed.
1562
654
  */
1563
655
  removeRelatedBindings(object, relatedObject) {
1564
- // check for the null value
1565
- if (qx.core.Environment.get("qx.debug")) {
1566
- qx.core.Assert.assertNotNull(
1567
- object,
1568
- "Can not remove the bindings for null object!"
1569
- );
1570
-
1571
- qx.core.Assert.assertNotNull(
1572
- relatedObject,
1573
- "Can not remove the bindings for null object!"
1574
- );
656
+ const SingleValueBinding = qx.data.SingleValueBinding;
657
+
658
+ let bySourceObject = SingleValueBinding.__bindingsBySource[object.toHashCode()];
659
+
660
+ if (bySourceObject) {
661
+ Object.values(bySourceObject).forEach(binding => {
662
+ if (binding.getTarget() === relatedObject) {
663
+ binding.dispose();
664
+ }
665
+ });
1575
666
  }
1576
667
 
1577
- // get the bindings
1578
- var bindings = this.getAllBindingsForObject(object);
1579
- if (bindings != undefined) {
1580
- // remove every binding with the removeBindingFromObject function
1581
- for (var i = bindings.length - 1; i >= 0; i--) {
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]);
668
+ let byRelatedObject = SingleValueBinding.__bindingsBySource[relatedObject.toHashCode()];
669
+ if (byRelatedObject) {
670
+ Object.values(byRelatedObject).forEach(binding => {
671
+ if (binding.getTarget() === object) {
672
+ binding.dispose();
1586
673
  }
1587
- }
674
+ });
1588
675
  }
1589
676
  },
1590
677
 
1591
678
  /**
1592
- * Returns an array which lists all bindings.
679
+ * Helper method that sets a value for a named property
1593
680
  *
1594
- * @param object {qx.core.Object} The object of which the bindings should
1595
- * be returned.
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.
681
+ * @param {qx.core.Object} target object to have a property set
682
+ * @param {String} propertyName the name of the property
683
+ * @param {Object?} value the value to set
1600
684
  */
1601
- getAllBindingsForObject(object) {
1602
- var hash = object.toHashCode();
1603
-
1604
- // get all bindings of object as source
1605
- var sourceBindings = this.__bindings[hash];
1606
-
1607
- // get all bindings of object as target
1608
- var targetBindings = this.__bindingsByTarget[hash];
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);
685
+ set(target, propertyName, value) {
686
+ let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
687
+ if (!prop) {
688
+ let setFuncName = "set" + qx.lang.String.firstUp(propertyName);
689
+ if (typeof target[setFuncName] == "function") {
690
+ return target[setFuncName](value);
691
+ } else {
692
+ throw new Error(`Property ${propertyName} not found on ${target.classname}`);
693
+ }
1618
694
  }
1619
695
 
1620
- return qx.lang.Array.unique(sourceBindings.concat(targetBindings));
696
+ if (prop.isAsync()) {
697
+ return prop.setAsync(target, value);
698
+ } else {
699
+ return prop.set(target, value);
700
+ }
1621
701
  },
1622
702
 
1623
703
  /**
1624
- * Removes all binding in the whole application. After that not a single
1625
- * binding is left.
1626
- * @deprecated {6.0} dispose and destructors are deprecated because of automatic memory management; this
1627
- * will only work for objects explicitly registered with ObjectRegistry.register
704
+ * Helper method to get a value of a named property
705
+ *
706
+ * @param {qx.core.Object} target object to have a property get
707
+ * @param {String} propertyName the name of the property
708
+ * @returns {Object?} the property value
1628
709
  */
1629
- removeAllBindings() {
1630
- // go through all registered objects
1631
- for (var hash in this.__bindings) {
1632
- var object = qx.core.ObjectRegistry.fromHashCode(hash);
1633
- // check for the object, perhaps its already deleted
1634
- if (object == null) {
1635
- delete this.__bindings[hash];
1636
- continue;
1637
- }
1638
- this.removeAllBindingsForObject(object);
710
+ get(target, propertyName) {
711
+ let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
712
+ if (prop.isAsync()) {
713
+ return prop.getAsync(target);
714
+ } else {
715
+ return prop.get(target);
1639
716
  }
1640
- // reset the bindings map
1641
- this.__bindings = {};
1642
717
  },
1643
718
 
1644
719
  /**
1645
- * Returns a map containing for every bound object an array of data binding
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.
720
+ * Helper method that resets a named property
1649
721
  *
1650
- * @return {Map} Map containing all bindings.
722
+ * @param {qx.core.Object} target object to have a property set
723
+ * @param {String} propertyName the name of the property
724
+
1651
725
  */
1652
- getAllBindings() {
1653
- return this.__bindings;
726
+ reset(target, propertyName) {
727
+ let prop = qx.util.PropertyUtil.getProperty(target.constructor, propertyName);
728
+ if (!prop) {
729
+ let setFuncName = "reset" + qx.lang.String.firstUp(propertyName);
730
+ if (typeof target[setFuncName] == "function") {
731
+ return target[setFuncName]();
732
+ } else {
733
+ throw new Error(`Property ${propertyName} not found on ${target.classname}`);
734
+ }
735
+ }
736
+
737
+ if (prop.isAsync()) {
738
+ return prop.resetAsync(target);
739
+ } else {
740
+ return prop.reset(target);
741
+ }
1654
742
  },
1655
743
 
1656
744
  /**
1657
- * Debug function which shows some valuable information about the given
1658
- * binding in console. For that it uses {@link qx.log.Logger}.
1659
745
  *
1660
- * @param object {qx.core.Object} the source of the binding.
1661
- * @param id {var} The id of the binding.
746
+ * Internal helper for getting the current set value at the property chain.
747
+ *
748
+ * @param {qx.core.Object} object The source of the binding.
749
+ * @param {String} propertyChain The property chain which represents
750
+ * the source property.
751
+ * @return {var?undefined} Returns the set value if defined.
1662
752
  */
1663
- showBindingInLog(object, id) {
1664
- var binding;
1665
- // go through all bindings of the given object
1666
- for (var i = 0; i < this.__bindings[object.toHashCode()].length; i++) {
1667
- // the first array item is the id
1668
- if (this.__bindings[object.toHashCode()][i][0] == id) {
1669
- binding = this.__bindings[object.toHashCode()][i];
1670
- break;
753
+ resolvePropertyChain(object, propertyChain) {
754
+ let segments = qx.data.SingleValueBinding.__parseSegments(null, propertyChain);
755
+ let out;
756
+ let receiver = {
757
+ setInput(value) {
758
+ out = value;
1671
759
  }
1672
- }
760
+ };
761
+ segments.at(-1).setOutputReceiver(receiver);
762
+ let promise = segments[0].setInput(object);
763
+
764
+ const cb = () => {
765
+ let first = segments[0];
766
+ if (first instanceof qx.data.binding.PropNameSegment) {
767
+ let property = qx.Class.getByProperty(object.constructor, first.getPropName());
768
+ qx.core.Assert.assertNotNull(property, `Object ${object.classname} does not have property ${first.getPropName()}`);
769
+ }
770
+ segments.forEach(segment => segment.dispose());
771
+ return out;
772
+ };
1673
773
 
1674
- if (binding === undefined) {
1675
- var message = "Binding does not exist!";
774
+ if (qx.Promise.isPromise(promise)) {
775
+ return promise.then(cb);
1676
776
  } else {
1677
- var message =
1678
- "Binding from '" +
1679
- binding[1] +
1680
- "' (" +
1681
- binding[2] +
1682
- ") to the object '" +
1683
- binding[3] +
1684
- "' (" +
1685
- binding[4] +
1686
- ").";
777
+ return cb();
1687
778
  }
1688
-
1689
- qx.log.Logger.debug(message);
1690
779
  },
1691
780
 
1692
781
  /**
1693
- * Debug function which shows all bindings in the log console. To get only
1694
- * one binding in the console use {@link #showBindingInLog}
1695
- * @deprecated {6.0} qx.core.ObjectRegistry no longer stores most objects
782
+ * Parses a path and creates an array of `qx.data.binding.AbstractSegment`
783
+ *
784
+ * @param {String} path the path to parse
785
+ * @return {qx.data.binding.AbstractSegment[]?} the new array of segments
1696
786
  */
1697
- showAllBindingsInLog() {
1698
- // go through all objects in the registry
1699
- for (var hash in this.__bindings) {
1700
- var object = qx.core.ObjectRegistry.fromHashCode(hash);
1701
- if (object) {
1702
- for (var i = 0; i < this.__bindings[hash].length; i++) {
1703
- this.showBindingInLog(object, this.__bindings[hash][i][0]);
1704
- }
787
+ __parseSegments(binding, path) {
788
+ let segsStrings = qx.data.SingleValueBinding.splitSegments(path);
789
+ let segments = [];
790
+
791
+ for (let seg of segsStrings) {
792
+ //if it's an array index:
793
+ if (seg.startsWith("[")) {
794
+ segments.push(new qx.data.binding.ArrayIndexSegment(binding, seg));
795
+ } else {
796
+ //otherwise, it's a normal path
797
+ segments.push(new qx.data.binding.PropNameSegment(binding, seg));
1705
798
  }
1706
799
  }
800
+
801
+ segments.forEach((seg, index) => {
802
+ if (index < segments.length - 1) {
803
+ seg.setOutputReceiver(segments[index + 1]);
804
+ }
805
+ });
806
+
807
+ return segments;
1707
808
  }
1708
809
  }
1709
810
  });