@qooxdoo/framework 7.7.1 → 7.8.0

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 (68) hide show
  1. package/Manifest.json +1 -1
  2. package/lib/compiler/compile-info.json +69 -69
  3. package/lib/compiler/index.js +542 -380
  4. package/lib/resource/qx/tool/schema/compile-1-0-0.json +13 -0
  5. package/package.json +2 -2
  6. package/source/class/qx/Class.js +1 -1
  7. package/source/class/qx/Mixin.js +7 -5
  8. package/source/class/qx/bom/Input.js +24 -13
  9. package/source/class/qx/bom/Label.js +82 -2
  10. package/source/class/qx/bom/webfonts/WebFont.js +1 -0
  11. package/source/class/qx/core/Environment.js +82 -1
  12. package/source/class/qx/data/controller/List.js +50 -21
  13. package/source/class/qx/data/controller/MSelection.js +45 -12
  14. package/source/class/qx/dev/unit/AsyncWrapper.js +8 -0
  15. package/source/class/qx/event/Manager.js +163 -124
  16. package/source/class/qx/io/ImageLoader.js +6 -3
  17. package/source/class/qx/io/exception/Transport.js +1 -0
  18. package/source/class/qx/io/jsonrpc/Client.js +64 -8
  19. package/source/class/qx/io/jsonrpc/protocol/Request.js +10 -6
  20. package/source/class/qx/lang/Function.js +5 -1
  21. package/source/class/qx/test/Mixin.js +260 -0
  22. package/source/class/qx/test/bom/client/Pdfjs.js +4 -0
  23. package/source/class/qx/test/bom/element/AnimationJs.js +3 -0
  24. package/source/class/qx/test/bom/element/Style.js +1 -0
  25. package/source/class/qx/test/bom/media/MediaTestCase.js +6 -0
  26. package/source/class/qx/test/core/Environment.js +44 -0
  27. package/source/class/qx/test/io/MAssert.js +94 -0
  28. package/source/class/qx/test/io/TestMAssert.js +47 -0
  29. package/source/class/qx/test/io/jsonrpc/Client.js +79 -19
  30. package/source/class/qx/test/io/jsonrpc/PostMessageClient.js +152 -0
  31. package/source/class/qx/test/io/jsonrpc/Protocol.js +1 -5
  32. package/source/class/qx/test/ui/embed/Iframe.js +1 -1
  33. package/source/class/qx/test/ui/form/TextArea.js +4 -0
  34. package/source/class/qx/test/util/DeferredCall.js +6 -0
  35. package/source/class/qx/test/util/Function.js +2 -2
  36. package/source/class/qx/tool/cli/api/Test.js +22 -0
  37. package/source/class/qx/tool/cli/commands/Compile.js +17 -7
  38. package/source/class/qx/tool/cli/commands/Test.js +7 -1
  39. package/source/class/qx/tool/compiler/Analyser.js +7 -0
  40. package/source/class/qx/tool/compiler/ClassFile.js +12 -6
  41. package/source/class/qx/tool/compiler/MetaExtraction.js +0 -5
  42. package/source/class/qx/tool/compiler/targets/Target.js +2 -2
  43. package/source/class/qx/tool/compiler/targets/meta/Browserify.js +8 -2
  44. package/source/class/qx/ui/basic/Image.js +72 -8
  45. package/source/class/qx/ui/basic/Label.js +4 -6
  46. package/source/class/qx/ui/control/DateChooser.js +4 -6
  47. package/source/class/qx/ui/core/Blocker.js +4 -6
  48. package/source/class/qx/ui/core/LayoutItem.js +4 -6
  49. package/source/class/qx/ui/core/MPlacement.js +11 -0
  50. package/source/class/qx/ui/core/Widget.js +7 -5
  51. package/source/class/qx/ui/form/AbstractField.js +14 -16
  52. package/source/class/qx/ui/form/IListItem.js +48 -1
  53. package/source/class/qx/ui/form/List.js +11 -6
  54. package/source/class/qx/ui/form/MForm.js +4 -6
  55. package/source/class/qx/ui/form/Spinner.js +4 -6
  56. package/source/class/qx/ui/form/renderer/AbstractRenderer.js +4 -6
  57. package/source/class/qx/ui/menu/AbstractButton.js +7 -11
  58. package/source/class/qx/ui/mobile/basic/Label.js +4 -6
  59. package/source/class/qx/ui/mobile/form/Label.js +4 -6
  60. package/source/class/qx/ui/mobile/list/List.js +4 -6
  61. package/source/class/qx/ui/progressive/renderer/table/Row.js +35 -7
  62. package/source/class/qx/ui/progressive/renderer/table/cell/Boolean.js +4 -6
  63. package/source/class/qx/ui/table/Table.js +12 -6
  64. package/source/class/qx/ui/table/cellrenderer/Abstract.js +4 -6
  65. package/source/class/qx/ui/table/cellrenderer/Boolean.js +4 -6
  66. package/source/class/qx/ui/table/pane/Scroller.js +35 -0
  67. package/source/class/qx/ui/table/rowrenderer/Default.js +4 -6
  68. package/source/resource/qx/tool/schema/compile-1-0-0.json +13 -0
@@ -144,6 +144,16 @@ qx.Class.define("qx.ui.basic.Image", {
144
144
  allowGrowY: {
145
145
  refine: true,
146
146
  init: false
147
+ },
148
+
149
+ /**
150
+ * Source of image to display if the image in the `source` property fails to load.
151
+ */
152
+ fallbackSource: {
153
+ check: "String",
154
+ init: null,
155
+ nullable: true,
156
+ event: "changeFallbackSource"
147
157
  }
148
158
  },
149
159
 
@@ -189,6 +199,19 @@ qx.Class.define("qx.ui.basic.Image", {
189
199
  __currentContentElement: null,
190
200
  __wrapper: null,
191
201
  __requestId: 0,
202
+ /**
203
+ * If the image in the `source` property failed to load.
204
+ */
205
+ __failedToLoad: false,
206
+
207
+ /**
208
+ * @type {string} The actual source of the image that we display.
209
+ * While the `source` property is what we want to display,
210
+ * this property is what we are actually showing.
211
+ * This can be the `source` property but it can also be the `fallbackSource` property
212
+ * if the image in the `source` property failed to load.
213
+ */
214
+ __sourceToDisplay: null,
192
215
 
193
216
  // overridden
194
217
  _onChangeTheme() {
@@ -225,7 +248,7 @@ qx.Class.define("qx.ui.basic.Image", {
225
248
  _applyDecorator(value, old) {
226
249
  super._applyDecorator(value, old);
227
250
 
228
- var source = this.getSource();
251
+ var source = this.__sourceToDisplay;
229
252
  source = qx.util.AliasManager.getInstance().resolve(source);
230
253
  var el = this.getContentElement();
231
254
  if (this.__wrapper) {
@@ -307,7 +330,7 @@ qx.Class.define("qx.ui.basic.Image", {
307
330
  _applyEnabled(value, old) {
308
331
  super._applyEnabled(value, old);
309
332
 
310
- if (this.getSource()) {
333
+ if (this.__sourceToDisplay) {
311
334
  this._styleSource();
312
335
  }
313
336
  },
@@ -321,6 +344,8 @@ qx.Class.define("qx.ui.basic.Image", {
321
344
  }
322
345
  }
323
346
 
347
+ this.__failedToLoad = false;
348
+ this.__sourceToDisplay = value;
324
349
  this._styleSource();
325
350
  },
326
351
 
@@ -345,7 +370,7 @@ qx.Class.define("qx.ui.basic.Image", {
345
370
  */
346
371
  __getMode() {
347
372
  if (this.__mode == null) {
348
- var source = this.getSource();
373
+ var source = this.__sourceToDisplay;
349
374
 
350
375
  if (source && qx.lang.String.startsWith(source, "@")) {
351
376
  this.__mode = "font";
@@ -458,13 +483,12 @@ qx.Class.define("qx.ui.basic.Image", {
458
483
  /**
459
484
  * Applies the source to the clipped image instance or preload
460
485
  * an image to detect sizes and apply it afterwards.
461
- *
462
486
  */
463
487
  _styleSource() {
464
488
  var AliasManager = qx.util.AliasManager.getInstance();
465
489
  var ResourceManager = qx.util.ResourceManager.getInstance();
466
490
 
467
- var source = AliasManager.resolve(this.getSource());
491
+ var source = AliasManager.resolve(this.__sourceToDisplay);
468
492
 
469
493
  var element = this.getContentElement();
470
494
  if (this.__wrapper) {
@@ -791,7 +815,7 @@ qx.Class.define("qx.ui.basic.Image", {
791
815
  el.setStyle("fontSize", (width > height ? height : width) + "px");
792
816
  } else {
793
817
  var source = qx.util.AliasManager.getInstance().resolve(
794
- this.getSource()
818
+ this.__sourceToDisplay
795
819
  );
796
820
 
797
821
  var sparts = source.split("/");
@@ -805,7 +829,8 @@ qx.Class.define("qx.ui.basic.Image", {
805
829
  super._applyDimension();
806
830
 
807
831
  var isFont =
808
- this.getSource() && qx.lang.String.startsWith(this.getSource(), "@");
832
+ this.__sourceToDisplay &&
833
+ qx.lang.String.startsWith(this.__sourceToDisplay, "@");
809
834
  if (isFont) {
810
835
  var el = this.getContentElement();
811
836
  if (el) {
@@ -872,6 +897,11 @@ qx.Class.define("qx.ui.basic.Image", {
872
897
  ImageLoader.load(source, this.__loaderCallback, this);
873
898
  } else {
874
899
  this.__resetSource(el);
900
+ if (!this.__failedToLoad && this.getFallbackSource()) {
901
+ this.__failedToLoad = true;
902
+ this.__sourceToDisplay = this.getFallbackSource();
903
+ this._styleSource();
904
+ }
875
905
  }
876
906
  },
877
907
 
@@ -904,6 +934,7 @@ qx.Class.define("qx.ui.basic.Image", {
904
934
  },
905
935
 
906
936
  /**
937
+ * Sets image source on the DOM element
907
938
  * Combines the decorator's image styles with our own image to make sure
908
939
  * gradient and backgroundImage decorators work on Images.
909
940
  *
@@ -991,6 +1022,32 @@ qx.Class.define("qx.ui.basic.Image", {
991
1022
  }
992
1023
  },
993
1024
 
1025
+ /**
1026
+ * Tries to display the image in the `source` property again if it has failed to load.
1027
+ */
1028
+ tryReload() {
1029
+ if (!this.__failedToLoad) {
1030
+ return;
1031
+ }
1032
+ this.__failedToLoad = false;
1033
+ this.__sourceToDisplay = this.getSource();
1034
+ qx.io.ImageLoader.load(
1035
+ this.getSource(),
1036
+ () => this._styleSource(),
1037
+ undefined,
1038
+ {
1039
+ retryFailed: true
1040
+ }
1041
+ );
1042
+ },
1043
+
1044
+ /**
1045
+ * @returns {boolean} If the image in the `source` property failed to load.
1046
+ */
1047
+ hasFailedToLoad() {
1048
+ return this.__failedToLoad;
1049
+ },
1050
+
994
1051
  /**
995
1052
  * Event handler fired after the preloader has finished loading the icon
996
1053
  *
@@ -1005,7 +1062,8 @@ qx.Class.define("qx.ui.basic.Image", {
1005
1062
 
1006
1063
  // Ignore when the source has already been modified
1007
1064
  if (
1008
- source !== qx.util.AliasManager.getInstance().resolve(this.getSource())
1065
+ source !==
1066
+ qx.util.AliasManager.getInstance().resolve(this.__sourceToDisplay)
1009
1067
  ) {
1010
1068
  this.fireEvent("aborted");
1011
1069
  return;
@@ -1015,6 +1073,12 @@ qx.Class.define("qx.ui.basic.Image", {
1015
1073
  if (imageInfo.failed) {
1016
1074
  this.warn("Image could not be loaded: " + source);
1017
1075
  this.fireEvent("loadingFailed");
1076
+ if (!this.__failedToLoad && this.getFallbackSource()) {
1077
+ this.__failedToLoad = true;
1078
+ this.__sourceToDisplay = this.getFallbackSource();
1079
+ this._styleSource();
1080
+ return;
1081
+ }
1018
1082
  } else if (imageInfo.aborted) {
1019
1083
  this.fireEvent("aborted");
1020
1084
  return;
@@ -79,7 +79,7 @@ qx.Class.define("qx.ui.basic.Label", {
79
79
  }
80
80
 
81
81
  if (qx.core.Environment.get("qx.dynlocale")) {
82
- qx.locale.Manager.getInstance().addListener(
82
+ this.__changeLocaleLabelListenerId = qx.locale.Manager.getInstance().addListener(
83
83
  "changeLocale",
84
84
  this._onChangeLocale,
85
85
  this
@@ -529,11 +529,9 @@ qx.Class.define("qx.ui.basic.Label", {
529
529
  */
530
530
 
531
531
  destruct() {
532
- if (qx.core.Environment.get("qx.dynlocale")) {
533
- qx.locale.Manager.getInstance().removeListener(
534
- "changeLocale",
535
- this._onChangeLocale,
536
- this
532
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleLabelListenerId) {
533
+ qx.locale.Manager.getInstance().removeListenerById(
534
+ this.__changeLocaleLabelListenerId
537
535
  );
538
536
  }
539
537
 
@@ -102,7 +102,7 @@ qx.Class.define("qx.ui.control.DateChooser", {
102
102
 
103
103
  // listen for locale changes
104
104
  if (qx.core.Environment.get("qx.dynlocale")) {
105
- qx.locale.Manager.getInstance().addListener(
105
+ this.__changeLocaleDatePaneListenerId = qx.locale.Manager.getInstance().addListener(
106
106
  "changeLocale",
107
107
  this._updateDatePane,
108
108
  this
@@ -782,11 +782,9 @@ qx.Class.define("qx.ui.control.DateChooser", {
782
782
  */
783
783
 
784
784
  destruct() {
785
- if (qx.core.Environment.get("qx.dynlocale")) {
786
- qx.locale.Manager.getInstance().removeListener(
787
- "changeLocale",
788
- this._updateDatePane,
789
- this
785
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleDatePaneListenerId) {
786
+ qx.locale.Manager.getInstance().removeListenerById(
787
+ this.__changeLocaleDatePaneListenerId
790
788
  );
791
789
  }
792
790
 
@@ -63,7 +63,7 @@ qx.Class.define("qx.ui.core.Blocker", {
63
63
 
64
64
  // dynamic theme switch
65
65
  if (qx.core.Environment.get("qx.dyntheme")) {
66
- qx.theme.manager.Meta.getInstance().addListener(
66
+ this.__changeThemeBlockerListenerId = qx.theme.manager.Meta.getInstance().addListener(
67
67
  "changeTheme",
68
68
  this._onChangeTheme,
69
69
  this
@@ -499,11 +499,9 @@ qx.Class.define("qx.ui.core.Blocker", {
499
499
 
500
500
  destruct() {
501
501
  // remove dynamic theme listener
502
- if (qx.core.Environment.get("qx.dyntheme")) {
503
- qx.theme.manager.Meta.getInstance().removeListener(
504
- "changeTheme",
505
- this._onChangeTheme,
506
- this
502
+ if (qx.core.Environment.get("qx.dyntheme") && this.__changeThemeBlockerListenerId) {
503
+ qx.theme.manager.Meta.getInstance().removeListenerById(
504
+ this.__changeThemeBlockerListenerId
507
505
  );
508
506
  }
509
507
 
@@ -30,7 +30,7 @@ qx.Class.define("qx.ui.core.LayoutItem", {
30
30
 
31
31
  // dynamic theme switch
32
32
  if (qx.core.Environment.get("qx.dyntheme")) {
33
- qx.theme.manager.Meta.getInstance().addListener(
33
+ this.__changeThemeLayoutItemListenerId = qx.theme.manager.Meta.getInstance().addListener(
34
34
  "changeTheme",
35
35
  this._onChangeTheme,
36
36
  this
@@ -933,11 +933,9 @@ qx.Class.define("qx.ui.core.LayoutItem", {
933
933
 
934
934
  destruct() {
935
935
  // remove dynamic theme listener
936
- if (qx.core.Environment.get("qx.dyntheme")) {
937
- qx.theme.manager.Meta.getInstance().removeListener(
938
- "changeTheme",
939
- this._onChangeTheme,
940
- this
936
+ if (qx.core.Environment.get("qx.dyntheme") && this.__changeThemeLayoutItemListenerId) {
937
+ qx.theme.manager.Meta.getInstance().removeListenerById(
938
+ this.__changeThemeLayoutItemListenerId
941
939
  );
942
940
  }
943
941
  this.$$parent =
@@ -203,6 +203,8 @@ qx.Mixin.define("qx.ui.core.MPlacement", {
203
203
  __ptwLiveUpdater: null,
204
204
  __ptwLiveDisappearListener: null,
205
205
  __ptwLiveUpdateDisappearListener: null,
206
+ /**@type {Record<"top" | "right" | "bottom" | "left", number> | null}*/
207
+ __lastKnownCoords: null,
206
208
 
207
209
  /**
208
210
  * Returns the location data like {qx.bom.element.Location#get} does,
@@ -378,6 +380,15 @@ qx.Mixin.define("qx.ui.core.MPlacement", {
378
380
  target.getContentLocation() || this.getLayoutLocation(target);
379
381
 
380
382
  if (coords != null) {
383
+ if (
384
+ coords.top === this.__lastKnownCoords?.top &&
385
+ coords.right === this.__lastKnownCoords?.right &&
386
+ coords.bottom === this.__lastKnownCoords?.bottom &&
387
+ coords.left === this.__lastKnownCoords?.left
388
+ ) {
389
+ return true;
390
+ }
391
+ this.__lastKnownCoords = coords;
381
392
  this._place(coords);
382
393
  return true;
383
394
  } else {
@@ -2128,11 +2128,13 @@ qx.Class.define("qx.ui.core.Widget", {
2128
2128
  }, // property apply
2129
2129
  _applyVisibility(value, old) {
2130
2130
  var content = this.getContentElement();
2131
- if (value === "visible") {
2132
- content.show();
2133
- } else {
2134
- content.hide();
2135
- } // only force a layout update if visibility change from/to "exclude"
2131
+ if (content) {
2132
+ if (value === "visible") {
2133
+ content.show();
2134
+ } else {
2135
+ content.hide();
2136
+ } // only force a layout update if visibility change from/to "exclude"
2137
+ }
2136
2138
  var parent = this.$$parent;
2137
2139
  if (
2138
2140
  parent &&
@@ -35,19 +35,19 @@ qx.Class.define("qx.ui.form.AbstractField", {
35
35
  type: "abstract",
36
36
 
37
37
  statics: {
38
- /** Stylesheet needed to style the native placeholder element. */
39
- __stylesheet: null,
40
-
41
- __addedPlaceholderRules: false,
38
+ __addedPlaceholderRules: "",
42
39
 
43
40
  /**
44
41
  * Adds the CSS rules needed to style the native placeholder element.
45
42
  */
46
43
  __addPlaceholderRules() {
47
- if (qx.ui.form.AbstractField.__addedPlaceholderRules) {
44
+ const theme = qx.theme.manager.Meta.getInstance().getTheme();
45
+ const currentThemeName = theme ? theme.title || theme.name : "";
46
+
47
+ if (qx.ui.form.AbstractField.__addedPlaceholderRules === currentThemeName) {
48
48
  return;
49
49
  }
50
- qx.ui.form.AbstractField.__addedPlaceholderRules = true;
50
+ qx.ui.form.AbstractField.__addedPlaceholderRules = currentThemeName;
51
51
  var engine = qx.core.Environment.get("engine.name");
52
52
  var browser = qx.core.Environment.get("browser.name");
53
53
  var colorManager = qx.theme.manager.Color.getInstance();
@@ -100,7 +100,9 @@ qx.Class.define("qx.ui.form.AbstractField", {
100
100
  "-ms-input-placeholder"
101
101
  ].join(separator);
102
102
  }
103
-
103
+ if(qx.ui.style.Stylesheet.getInstance().hasRule(selector)) {
104
+ qx.ui.style.Stylesheet.getInstance().removeRule(selector);
105
+ }
104
106
  qx.ui.style.Stylesheet.getInstance().addRule(
105
107
  selector,
106
108
  "color: " + color + " !important"
@@ -142,7 +144,7 @@ qx.Class.define("qx.ui.form.AbstractField", {
142
144
 
143
145
  // translation support
144
146
  if (qx.core.Environment.get("qx.dynlocale")) {
145
- qx.locale.Manager.getInstance().addListener(
147
+ this.__changeLocaleAbstractFieldListenerId = qx.locale.Manager.getInstance().addListener(
146
148
  "changeLocale",
147
149
  this._onChangeLocale,
148
150
  this
@@ -931,9 +933,7 @@ qx.Class.define("qx.ui.form.AbstractField", {
931
933
  this._placeholder.dispose();
932
934
  this._placeholder = null;
933
935
  }
934
- if (!this.__useQxPlaceholder && qx.ui.form.AbstractField.__stylesheet) {
935
- qx.bom.Stylesheet.removeSheet(qx.ui.form.AbstractField.__stylesheet);
936
- qx.ui.form.AbstractField.__stylesheet = null;
936
+ if (!this.__useQxPlaceholder) {
937
937
  qx.ui.form.AbstractField.__addPlaceholderRules();
938
938
  }
939
939
  },
@@ -1074,11 +1074,9 @@ qx.Class.define("qx.ui.form.AbstractField", {
1074
1074
 
1075
1075
  this._placeholder = this.__font = null;
1076
1076
 
1077
- if (qx.core.Environment.get("qx.dynlocale")) {
1078
- qx.locale.Manager.getInstance().removeListener(
1079
- "changeLocale",
1080
- this._onChangeLocale,
1081
- this
1077
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleAbstractFieldListenerId) {
1078
+ qx.locale.Manager.getInstance().removeListenerById(
1079
+ this.__changeLocaleAbstractFieldListenerId
1082
1080
  );
1083
1081
  }
1084
1082
 
@@ -20,4 +20,51 @@
20
20
  * This is a marker interface for classes which can act as a children of
21
21
  * {@link qx.ui.form.List}
22
22
  */
23
- qx.Interface.define("qx.ui.form.IListItem", {});
23
+ qx.Interface.define("qx.ui.form.IListItem", {
24
+ /*
25
+ *****************************************************************************
26
+ EVENTS
27
+ *****************************************************************************
28
+ */
29
+
30
+ events: {
31
+ /** Fired when the value was modified */
32
+ changeReadOnly: "qx.event.type.Data"
33
+ },
34
+
35
+ /*
36
+ *****************************************************************************
37
+ MEMBERS
38
+ *****************************************************************************
39
+ */
40
+
41
+ members: {
42
+ /*
43
+ ---------------------------------------------------------------------------
44
+ READONLY PROPERTY
45
+ ---------------------------------------------------------------------------
46
+ */
47
+
48
+ /**
49
+ * Sets the element's value.
50
+ *
51
+ * @param value {Boolean|null} The new value of the element.
52
+ * @return {Boolean|null}
53
+ */
54
+ setReadOnly(value) {
55
+ this.assertArgumentsCount(arguments, 1, 1);
56
+ },
57
+
58
+ /**
59
+ * Resets the element's value to its initial value.
60
+ */
61
+ resetReadOnly() {},
62
+
63
+ /**
64
+ * The element's user set value.
65
+ *
66
+ * @return {Boolean|null} The value.
67
+ */
68
+ getReadOnly() {}
69
+ }
70
+ });
@@ -199,10 +199,12 @@ qx.Class.define("qx.ui.form.List", {
199
199
  */
200
200
  _onAddChild(e) {
201
201
  const child = e.getData();
202
- this.__childrenBindings.set(
203
- child.toHashCode(),
204
- this.bind("readOnly", child, "readOnly")
205
- );
202
+ if (qx.Class.implementsInterface(child, qx.ui.form.IListItem)) {
203
+ this.__childrenBindings.set(
204
+ child.toHashCode(),
205
+ this.bind("readOnly", child, "readOnly")
206
+ );
207
+ }
206
208
 
207
209
  this.fireDataEvent("addItem", child);
208
210
  },
@@ -214,8 +216,11 @@ qx.Class.define("qx.ui.form.List", {
214
216
  */
215
217
  _onRemoveChild(e) {
216
218
  const child = e.getData();
217
- child.removeBinding(this.__childrenBindings.get(child.toHashCode()));
218
- this.__childrenBindings.delete(child.toHashCode());
219
+ const binding = this.__childrenBindings.get(child.toHashCode());
220
+ if (binding) {
221
+ child.removeBinding(binding);
222
+ this.__childrenBindings.delete(child.toHashCode());
223
+ }
219
224
  this.fireDataEvent("removeItem", child);
220
225
  },
221
226
 
@@ -22,7 +22,7 @@
22
22
  qx.Mixin.define("qx.ui.form.MForm", {
23
23
  construct() {
24
24
  if (qx.core.Environment.get("qx.dynlocale")) {
25
- qx.locale.Manager.getInstance().addListener(
25
+ this.__changeLocaleMFormListenerId = qx.locale.Manager.getInstance().addListener(
26
26
  "changeLocale",
27
27
  this.__onChangeLocale,
28
28
  this
@@ -103,11 +103,9 @@ qx.Mixin.define("qx.ui.form.MForm", {
103
103
  },
104
104
 
105
105
  destruct() {
106
- if (qx.core.Environment.get("qx.dynlocale")) {
107
- qx.locale.Manager.getInstance().removeListener(
108
- "changeLocale",
109
- this.__onChangeLocale,
110
- this
106
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleMFormListenerId) {
107
+ qx.locale.Manager.getInstance().removeListenerById(
108
+ this.__changeLocaleMFormListenerId
111
109
  );
112
110
  }
113
111
  }
@@ -87,7 +87,7 @@ qx.Class.define("qx.ui.form.Spinner", {
87
87
  this.addListener("roll", this._onRoll, this);
88
88
 
89
89
  if (qx.core.Environment.get("qx.dynlocale")) {
90
- qx.locale.Manager.getInstance().addListener(
90
+ this.__changeLocaleSpinnerListenerId = qx.locale.Manager.getInstance().addListener(
91
91
  "changeLocale",
92
92
  this._onChangeLocale,
93
93
  this
@@ -800,11 +800,9 @@ qx.Class.define("qx.ui.form.Spinner", {
800
800
  nf.removeListener("changeNumberFormat", this._onChangeNumberFormat, this);
801
801
  }
802
802
 
803
- if (qx.core.Environment.get("qx.dynlocale")) {
804
- qx.locale.Manager.getInstance().removeListener(
805
- "changeLocale",
806
- this._onChangeLocale,
807
- this
803
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleSpinnerListenerId) {
804
+ qx.locale.Manager.getInstance().removeListenerById(
805
+ this.__changeLocaleSpinnerListenerId
808
806
  );
809
807
  }
810
808
  }
@@ -38,7 +38,7 @@ qx.Class.define("qx.ui.form.renderer.AbstractRenderer", {
38
38
 
39
39
  // translation support
40
40
  if (qx.core.Environment.get("qx.dynlocale")) {
41
- qx.locale.Manager.getInstance().addListener(
41
+ this.__changeLocaleRendererListenerId = qx.locale.Manager.getInstance().addListener(
42
42
  "changeLocale",
43
43
  this._onChangeLocale,
44
44
  this
@@ -190,11 +190,9 @@ qx.Class.define("qx.ui.form.renderer.AbstractRenderer", {
190
190
  */
191
191
 
192
192
  destruct() {
193
- if (qx.core.Environment.get("qx.dynlocale")) {
194
- qx.locale.Manager.getInstance().removeListener(
195
- "changeLocale",
196
- this._onChangeLocale,
197
- this
193
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleRendererListenerId) {
194
+ qx.locale.Manager.getInstance().removeListenerById(
195
+ this.__changeLocaleRendererListenerId
198
196
  );
199
197
  }
200
198
  this._names = null;
@@ -265,17 +265,15 @@ qx.Class.define("qx.ui.menu.AbstractButton", {
265
265
  if (qx.core.Environment.get("qx.dynlocale")) {
266
266
  var oldCommand = e.getOldData();
267
267
  if (!oldCommand) {
268
- qx.locale.Manager.getInstance().addListener(
268
+ this.__changeLocaleCommandListenerId = qx.locale.Manager.getInstance().addListener(
269
269
  "changeLocale",
270
270
  this._onChangeLocale,
271
271
  this
272
272
  );
273
273
  }
274
- if (!command) {
275
- qx.locale.Manager.getInstance().removeListener(
276
- "changeLocale",
277
- this._onChangeLocale,
278
- this
274
+ if (!command && this.__changeLocaleCommandListenerId) {
275
+ qx.locale.Manager.getInstance().removeListenerById(
276
+ this.__changeLocaleCommandListenerId
279
277
  );
280
278
  }
281
279
  }
@@ -397,11 +395,9 @@ qx.Class.define("qx.ui.menu.AbstractButton", {
397
395
  }
398
396
  }
399
397
 
400
- if (qx.core.Environment.get("qx.dynlocale")) {
401
- qx.locale.Manager.getInstance().removeListener(
402
- "changeLocale",
403
- this._onChangeLocale,
404
- this
398
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleCommandListenerId) {
399
+ qx.locale.Manager.getInstance().removeListenerById(
400
+ this.__changeLocaleCommandListenerId
405
401
  );
406
402
  }
407
403
  }
@@ -51,7 +51,7 @@ qx.Class.define("qx.ui.mobile.basic.Label", {
51
51
  this.initWrap();
52
52
 
53
53
  if (qx.core.Environment.get("qx.dynlocale")) {
54
- qx.locale.Manager.getInstance().addListener(
54
+ this.__changeLocaleLabelListenerId = qx.locale.Manager.getInstance().addListener(
55
55
  "changeLocale",
56
56
  this._onChangeLocale,
57
57
  this
@@ -145,11 +145,9 @@ qx.Class.define("qx.ui.mobile.basic.Label", {
145
145
  */
146
146
 
147
147
  destruct() {
148
- if (qx.core.Environment.get("qx.dynlocale")) {
149
- qx.locale.Manager.getInstance().removeListener(
150
- "changeLocale",
151
- this._onChangeLocale,
152
- this
148
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleLabelListenerId) {
149
+ qx.locale.Manager.getInstance().removeListenerById(
150
+ this.__changeLocaleLabelListenerId
153
151
  );
154
152
  }
155
153
  }
@@ -71,7 +71,7 @@ qx.Class.define("qx.ui.mobile.form.Label", {
71
71
  this.initWrap();
72
72
 
73
73
  if (qx.core.Environment.get("qx.dynlocale")) {
74
- qx.locale.Manager.getInstance().addListener(
74
+ this.__changeLocaleLabelListenerId = qx.locale.Manager.getInstance().addListener(
75
75
  "changeLocale",
76
76
  this._onChangeLocale,
77
77
  this
@@ -242,11 +242,9 @@ qx.Class.define("qx.ui.mobile.form.Label", {
242
242
 
243
243
  this.__forWidget = null;
244
244
  }
245
- if (qx.core.Environment.get("qx.dynlocale")) {
246
- qx.locale.Manager.getInstance().removeListener(
247
- "changeLocale",
248
- this._onChangeLocale,
249
- this
245
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleLabelListenerId) {
246
+ qx.locale.Manager.getInstance().removeListenerById(
247
+ this.__changeLocaleLabelListenerId
250
248
  );
251
249
  }
252
250
  }
@@ -89,7 +89,7 @@ qx.Class.define("qx.ui.mobile.list.List", {
89
89
  }
90
90
 
91
91
  if (qx.core.Environment.get("qx.dynlocale")) {
92
- qx.locale.Manager.getInstance().addListener(
92
+ this.__changeLocaleListListenerId = qx.locale.Manager.getInstance().addListener(
93
93
  "changeLocale",
94
94
  this._onChangeLocale,
95
95
  this
@@ -615,11 +615,9 @@ qx.Class.define("qx.ui.mobile.list.List", {
615
615
  destruct() {
616
616
  this.__trackElement = null;
617
617
  this._disposeObjects("__provider");
618
- if (qx.core.Environment.get("qx.dynlocale")) {
619
- qx.locale.Manager.getInstance().removeListener(
620
- "changeLocale",
621
- this._onChangeLocale,
622
- this
618
+ if (qx.core.Environment.get("qx.dynlocale") && this.__changeLocaleListListenerId) {
619
+ qx.locale.Manager.getInstance().removeListenerById(
620
+ this.__changeLocaleListListenerId
623
621
  );
624
622
  }
625
623
  }