@qooxdoo/framework 7.7.2 → 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 (59) hide show
  1. package/Manifest.json +1 -1
  2. package/lib/compiler/compile-info.json +63 -63
  3. package/lib/compiler/index.js +513 -353
  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/bom/Label.js +82 -2
  7. package/source/class/qx/bom/webfonts/WebFont.js +1 -0
  8. package/source/class/qx/core/Environment.js +82 -1
  9. package/source/class/qx/data/controller/List.js +50 -21
  10. package/source/class/qx/data/controller/MSelection.js +45 -12
  11. package/source/class/qx/dev/unit/AsyncWrapper.js +8 -0
  12. package/source/class/qx/event/Manager.js +163 -124
  13. package/source/class/qx/io/ImageLoader.js +6 -3
  14. package/source/class/qx/io/exception/Transport.js +1 -0
  15. package/source/class/qx/io/jsonrpc/Client.js +64 -8
  16. package/source/class/qx/io/jsonrpc/protocol/Request.js +10 -6
  17. package/source/class/qx/test/bom/client/Pdfjs.js +4 -0
  18. package/source/class/qx/test/bom/element/AnimationJs.js +3 -0
  19. package/source/class/qx/test/bom/element/Style.js +1 -0
  20. package/source/class/qx/test/bom/media/MediaTestCase.js +6 -0
  21. package/source/class/qx/test/core/Environment.js +44 -0
  22. package/source/class/qx/test/io/MAssert.js +94 -0
  23. package/source/class/qx/test/io/TestMAssert.js +47 -0
  24. package/source/class/qx/test/io/jsonrpc/Client.js +79 -19
  25. package/source/class/qx/test/io/jsonrpc/PostMessageClient.js +152 -0
  26. package/source/class/qx/test/io/jsonrpc/Protocol.js +1 -5
  27. package/source/class/qx/test/ui/embed/Iframe.js +1 -1
  28. package/source/class/qx/test/ui/form/TextArea.js +4 -0
  29. package/source/class/qx/test/util/DeferredCall.js +6 -0
  30. package/source/class/qx/test/util/Function.js +2 -2
  31. package/source/class/qx/tool/cli/api/Test.js +22 -0
  32. package/source/class/qx/tool/cli/commands/Compile.js +17 -4
  33. package/source/class/qx/tool/cli/commands/Test.js +7 -1
  34. package/source/class/qx/tool/compiler/Analyser.js +7 -0
  35. package/source/class/qx/tool/compiler/ClassFile.js +3 -2
  36. package/source/class/qx/tool/compiler/MetaExtraction.js +0 -5
  37. package/source/class/qx/tool/compiler/targets/meta/Browserify.js +8 -2
  38. package/source/class/qx/ui/basic/Image.js +72 -8
  39. package/source/class/qx/ui/basic/Label.js +4 -6
  40. package/source/class/qx/ui/control/DateChooser.js +4 -6
  41. package/source/class/qx/ui/core/Blocker.js +4 -6
  42. package/source/class/qx/ui/core/LayoutItem.js +4 -6
  43. package/source/class/qx/ui/core/MPlacement.js +11 -0
  44. package/source/class/qx/ui/core/Widget.js +7 -5
  45. package/source/class/qx/ui/form/AbstractField.js +4 -6
  46. package/source/class/qx/ui/form/MForm.js +4 -6
  47. package/source/class/qx/ui/form/Spinner.js +4 -6
  48. package/source/class/qx/ui/form/renderer/AbstractRenderer.js +4 -6
  49. package/source/class/qx/ui/menu/AbstractButton.js +7 -11
  50. package/source/class/qx/ui/mobile/basic/Label.js +4 -6
  51. package/source/class/qx/ui/mobile/form/Label.js +4 -6
  52. package/source/class/qx/ui/mobile/list/List.js +4 -6
  53. package/source/class/qx/ui/progressive/renderer/table/Row.js +35 -7
  54. package/source/class/qx/ui/progressive/renderer/table/cell/Boolean.js +4 -6
  55. package/source/class/qx/ui/table/Table.js +4 -6
  56. package/source/class/qx/ui/table/cellrenderer/Abstract.js +4 -6
  57. package/source/class/qx/ui/table/cellrenderer/Boolean.js +4 -6
  58. package/source/class/qx/ui/table/rowrenderer/Default.js +4 -6
  59. package/source/resource/qx/tool/schema/compile-1-0-0.json +13 -0
@@ -318,6 +318,10 @@
318
318
  "type": "object",
319
319
  "description": "Options given to @babel/preset-env. With this options the output type of babel can be defined. For details see here: <https://babeljs.io/docs/en/babel-preset-env#options>. They can be overridden per target."
320
320
  },
321
+ "browserifyOptions": {
322
+ "type": "object",
323
+ "description": "Options given to browserify. For details see here: <https://github.com/browserify/browserify#usage>. They can be overridden per target."
324
+ },
321
325
  "parts": {
322
326
  "$ref": "#/properties/parts"
323
327
  }
@@ -458,6 +462,15 @@
458
462
  "description": "** DEPRECATED - See babel.options instead",
459
463
  "deprecated": true
460
464
  },
465
+ "browserify": {
466
+ "type": "object",
467
+ "properties": {
468
+ "options": {
469
+ "type": "object",
470
+ "description": "Options given to browserify. For details see here: <https://github.com/browserify/browserify#usage>. They can be overridden per target."
471
+ }
472
+ }
473
+ },
461
474
  "jsx": {
462
475
  "type": "object",
463
476
  "description": "Options given to @babel/preset-react to change how JSX HTML is transpiled"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qooxdoo/framework",
3
- "version": "7.7.2",
3
+ "version": "7.8.0",
4
4
  "description": "The JS Framework for Coders",
5
5
  "author": "The qooxdoo project",
6
6
  "keywords": [
@@ -79,7 +79,7 @@
79
79
  "async": "^2.6.3",
80
80
  "babelify": "^10.0.0",
81
81
  "better-ajv-errors": "^1.2.0",
82
- "browserify": "^17.0.0",
82
+ "browserify": "^17.0.1",
83
83
  "chokidar": "^3.5.3",
84
84
  "cldr": "^7.4.1",
85
85
  "columnify": "^1.6.0",
@@ -39,6 +39,9 @@ qx.Bootstrap.define("qx.bom.Label", {
39
39
  letterSpacing: 1
40
40
  },
41
41
 
42
+ /** @type{Object<String,Object>} cache of label sizes */
43
+ __sizeCache: {},
44
+
42
45
  /**
43
46
  * Generates the helper DOM element for text measuring
44
47
  *
@@ -286,6 +289,12 @@ qx.Bootstrap.define("qx.bom.Label", {
286
289
  * @return {Map} A map with preferred <code>width</code> and <code>height</code>.
287
290
  */
288
291
  getHtmlSize(content, styles, width) {
292
+ let cacheKey = this.__getCacheKey(styles, width);
293
+ let size = this.__getCachedSize(cacheKey, content);
294
+ if (size !== undefined) {
295
+ return size;
296
+ }
297
+
289
298
  var element = this._htmlElement || this.__prepareHtml();
290
299
 
291
300
  // apply width
@@ -293,7 +302,9 @@ qx.Bootstrap.define("qx.bom.Label", {
293
302
  // insert content
294
303
  element.innerHTML = content;
295
304
 
296
- return this.__measureSize(element, styles);
305
+ size = this.__measureSize(element, styles);
306
+ this.__storeCacheSize(cacheKey, content, size);
307
+ return size;
297
308
  },
298
309
 
299
310
  /**
@@ -304,6 +315,12 @@ qx.Bootstrap.define("qx.bom.Label", {
304
315
  * @return {Map} A map with preferred <code>width</code> and <code>height</code>.
305
316
  */
306
317
  getTextSize(text, styles) {
318
+ let cacheKey = this.__getCacheKey(styles);
319
+ let size = this.__getCachedSize(cacheKey, text);
320
+ if (size !== undefined) {
321
+ return size;
322
+ }
323
+
307
324
  var element = this._textElement || this.__prepareText();
308
325
 
309
326
  if (
@@ -315,7 +332,70 @@ qx.Bootstrap.define("qx.bom.Label", {
315
332
  qx.bom.element.Attribute.set(element, "text", text);
316
333
  }
317
334
 
318
- return this.__measureSize(element, styles);
335
+ size = this.__measureSize(element, styles);
336
+ this.__storeCacheSize(cacheKey, text, size);
337
+ return size;
338
+ },
339
+
340
+ /**
341
+ * Returns a key for a specific set of styles, used in the caching of size calculations
342
+ *
343
+ * @param {*} styles
344
+ * @param {Integer?} width optional width
345
+ * @returns
346
+ */
347
+ __getCacheKey(styles, width) {
348
+ let cacheKey = [];
349
+ for (let key in styles) {
350
+ let value = styles[key];
351
+ if (value !== null) {
352
+ cacheKey.push(key + ":" + value);
353
+ }
354
+ }
355
+ if (width !== undefined) {
356
+ cacheKey.push("width:" + width);
357
+ }
358
+ return cacheKey.join(",");
359
+ },
360
+
361
+ /**
362
+ * Returns the cached size of the given text
363
+ *
364
+ * @param {String} cacheKey
365
+ * @param {String} text
366
+ * @returns {*} size object
367
+ */
368
+ __getCachedSize(cacheKey, text) {
369
+ let cache = qx.bom.Label.__sizeCache[cacheKey];
370
+ return cache?.sizes[text];
371
+ },
372
+
373
+ /**
374
+ * Stores the size of the given text in the cache
375
+ *
376
+ * @param {String} cacheKey
377
+ * @param {String} text
378
+ * @param {*} size
379
+ */
380
+ __storeCacheSize(cacheKey, text, size) {
381
+ if (!size) {
382
+ return;
383
+ }
384
+
385
+ let cache = qx.bom.Label.__sizeCache[cacheKey];
386
+ if (cache === undefined) {
387
+ cache = qx.bom.Label.__sizeCache[cacheKey] = {
388
+ sizes: {}
389
+ };
390
+ }
391
+ cache.sizes[text] = size;
392
+ },
393
+
394
+ /**
395
+ * Flushes the size cache - use this when something changes, for example webfonts have been loaded
396
+ */
397
+ flushSizeCache() {
398
+ qx.bom.Label.__sizeCache = {};
319
399
  },
320
400
 
321
401
  /**
@@ -112,6 +112,7 @@ qx.Class.define("qx.bom.webfonts.WebFont", {
112
112
  },
113
113
 
114
114
  __applyValid(value) {
115
+ qx.bom.Label.flushSizeCache();
115
116
  this.fireDataEvent("changeStatus", {
116
117
  family: this.getFamily(),
117
118
  valid: value
@@ -913,7 +913,8 @@ qx.Bootstrap.define("qx.core.Environment", {
913
913
  "qx.promise.warnings": true,
914
914
  "qx.promise.longStackTraces": true,
915
915
  "qx.command.bindEnabled": false,
916
- "qx.headless": false
916
+ "qx.headless": false,
917
+ "qx.environment.allowRuntimeMutations": false
917
918
  },
918
919
 
919
920
  /**
@@ -1210,6 +1211,74 @@ qx.Bootstrap.define("qx.core.Environment", {
1210
1211
  return this._asyncChecks;
1211
1212
  },
1212
1213
 
1214
+ // mutation of environment settings at runtime
1215
+
1216
+ /**
1217
+ * Sets the environment setting for the given key to the given value. This deletes any check function
1218
+ * associated with this key.
1219
+ *
1220
+ * This method is only available if "qx.environment.allowRuntimeMutations" is set to true.
1221
+ *
1222
+ * @param key {String} The key of the environment setting to set.
1223
+ * @param value {var} The value to set the environment setting to. Must be a scalar value.
1224
+ */
1225
+ set: qx.Bootstrap.getEnvironmentSetting("qx.environment.allowRuntimeMutations") ? function(key, value) {
1226
+ if (key === undefined) {
1227
+ throw new TypeError("Key must be provided to set an environment setting.");
1228
+ }
1229
+ if (this.__environmentBackup === undefined) {
1230
+ qx.Bootstrap.warn("Modifying environment settings at runtime is enabled. This is a security risk and should not be done in production code.");
1231
+ this.__environmentBackup = Object.assign({}, this.__cache);
1232
+ this.__checksBackup = Object.assign({}, this._checks);
1233
+ }
1234
+ this.__cache[key] = value;
1235
+ delete this._checks[key];
1236
+ delete this._checksMap[key];
1237
+ }: undefined,
1238
+
1239
+ /**
1240
+ * Removes the environment setting for the given key, and any check function associated with it.
1241
+ * This method is only available if "qx.environment.allowRuntimeMutations" is set to true.
1242
+ *
1243
+ * @param key {String} The key of the environment setting to remove.
1244
+ */
1245
+ remove: qx.Bootstrap.getEnvironmentSetting("qx.environment.allowRuntimeMutations") ? function(key) {
1246
+ if (key === undefined) {
1247
+ throw new TypeError("Key must be provided to remove an environment setting.");
1248
+ }
1249
+ if (this.__environmentBackup === undefined || this.__environmentBackup[key] === undefined) {
1250
+ throw new TypeError(`Environment setting "${key}" does not exist.`);
1251
+ }
1252
+ delete this.__cache[key];
1253
+ delete this._checks[key];
1254
+ delete this._checksMap[key];
1255
+ }: undefined,
1256
+
1257
+ /**
1258
+ * Resets the environment settings to their original values. If a key is provided, only that key is reset.
1259
+ * This method is only available if "qx.environment.allowRuntimeMutations" is set to true.
1260
+ *
1261
+ * @param key {String?} The key of the environment setting to reset. If not provided, all settings are reset.
1262
+ */
1263
+ reset: qx.Bootstrap.getEnvironmentSetting("qx.environment.allowRuntimeMutations") ? function(key) {
1264
+ if (this.__environmentBackup === undefined) {
1265
+ // no backup available, nothing to reset
1266
+ return;
1267
+ }
1268
+ if (key !== undefined && this.__environmentBackup[key] === undefined) {
1269
+ throw new TypeError(`Environment setting "${key}" does not exist.`);
1270
+ }
1271
+ if (key === undefined) {
1272
+ // reset all keys
1273
+ this.__cache = Object.assign({}, this.__environmentBackup);
1274
+ this._checks = Object.assign({}, this.__checksBackup);
1275
+ return;
1276
+ }
1277
+ // only reset the particular key
1278
+ this.__cache[key] = this.__environmentBackup[key];
1279
+ this._checks[key] = this.__checksBackup[key];
1280
+ }: undefined,
1281
+
1213
1282
  /**
1214
1283
  * Initializer for the default values of the framework settings.
1215
1284
  */
@@ -1296,5 +1365,17 @@ qx.Bootstrap.define("qx.core.Environment", {
1296
1365
  if (statics.get("qx.allowUrlSettings") === true) {
1297
1366
  statics.__importFromUrl();
1298
1367
  }
1368
+ },
1369
+
1370
+ environment: {
1371
+ /**
1372
+ * By setting this key to true, the environment variables can be mutated at runtime, using the {@link #set} method,
1373
+ * which is otherwise not available. This is only useful for testing and debugging purposes. We strongly advise
1374
+ * against enabling this in production code. You have been warned.
1375
+ * Note: This enviroment key declaration is only for documentation purposes and is not used during bootstrapping, so
1376
+ * changing the value here will have no effect.
1377
+ */
1378
+ "qx.environment.allowRuntimeMutations": false,
1299
1379
  }
1380
+
1300
1381
  });
@@ -207,14 +207,10 @@ qx.Class.define("qx.data.controller.List", {
207
207
  }
208
208
  },
209
209
 
210
- /*
211
- *****************************************************************************
212
- MEMBERS
213
- *****************************************************************************
214
- */
215
-
216
210
  members: {
217
- // private members
211
+ /**
212
+ * Listener ID for the 'change' event of property `model`
213
+ */
218
214
  __changeModelListenerId: null,
219
215
  __lookupTable: null,
220
216
  __onUpdate: null,
@@ -376,12 +372,16 @@ qx.Class.define("qx.data.controller.List", {
376
372
  }
377
373
  }
378
374
 
379
- // erase the selection if there is something selected
380
- if (this.getSelection() != undefined && this.getSelection().length > 0) {
381
- this.getSelection().splice(0, this.getSelection().length).dispose();
375
+ if (!this.getAllowSelectionNotInModel()) {
376
+ //erase the selection if there is something selected
377
+ if (
378
+ this.getSelection() != undefined &&
379
+ this.getSelection().length > 0
380
+ ) {
381
+ this.getSelection().splice(0, this.getSelection().length).dispose();
382
+ }
382
383
  }
383
384
 
384
- // if a model is set
385
385
  if (value != null) {
386
386
  // add a new listener
387
387
  this.__changeModelListenerId = value.addListener(
@@ -392,28 +392,40 @@ qx.Class.define("qx.data.controller.List", {
392
392
 
393
393
  // renew the index lookup table
394
394
  this.__buildUpLookupTable();
395
+
395
396
  // check for the new length
396
397
  this.__changeModelLength();
397
398
 
398
- // as we only change the labels of the items, the selection change event
399
- // may be missing so we invoke it here
400
- if (old == null) {
401
- this._changeTargetSelection();
399
+ if (!this.getAllowSelectionNotInModel()) {
400
+ // as we only change the labels of the items, the selection change event
401
+ // may be missing so we invoke it here
402
+ if (old == null) {
403
+ this._changeTargetSelection();
404
+ } else {
405
+ // update the selection asynchronously
406
+ this.__syncTargetSelection = true;
407
+ qx.ui.core.queue.Widget.add(this);
408
+ }
402
409
  } else {
403
- // update the selection asynchronously
404
- this.__syncTargetSelection = true;
410
+ this.__syncModelSelection = true;
405
411
  qx.ui.core.queue.Widget.add(this);
406
412
  }
407
413
  } else {
408
414
  var target = this.getTarget();
409
415
  // if the model is set to null, we should remove all items in the target
410
416
  if (target != null) {
417
+ if (this.getAllowSelectionNotInModel()) {
418
+ this._startSelectionModification();
419
+ }
411
420
  // we need to remove the bindings too so use the controller method
412
421
  // for removing items
413
422
  var length = target.getChildren().length;
414
423
  for (var i = 0; i < length; i++) {
415
424
  this.__removeItem();
416
425
  }
426
+ if (this.getAllowSelectionNotInModel()) {
427
+ this._endSelectionModification();
428
+ }
417
429
  }
418
430
  }
419
431
  },
@@ -431,6 +443,10 @@ qx.Class.define("qx.data.controller.List", {
431
443
  // add a listener for the target change
432
444
  this._addChangeTargetListener(value, old);
433
445
 
446
+ if (this.getAllowSelectionNotInModel()) {
447
+ this._startSelectionModification();
448
+ }
449
+
434
450
  // if there was an old target
435
451
  if (old != undefined) {
436
452
  // remove all element of the old target
@@ -450,6 +466,10 @@ qx.Class.define("qx.data.controller.List", {
450
466
  }
451
467
  }
452
468
  }
469
+
470
+ if (this.getAllowSelectionNotInModel()) {
471
+ this._endSelectionModification();
472
+ }
453
473
  },
454
474
 
455
475
  /*
@@ -518,6 +538,9 @@ qx.Class.define("qx.data.controller.List", {
518
538
  var newLength = this.__lookupTable.length;
519
539
  var currentLength = this.getTarget().getChildren().length;
520
540
 
541
+ if (this.getAllowSelectionNotInModel()) {
542
+ this._startSelectionModification();
543
+ }
521
544
  // if there are more item
522
545
  if (newLength > currentLength) {
523
546
  // add the new elements
@@ -532,13 +555,19 @@ qx.Class.define("qx.data.controller.List", {
532
555
  }
533
556
  }
534
557
 
558
+ if (this.getAllowSelectionNotInModel()) {
559
+ this._endSelectionModification();
560
+ }
561
+
535
562
  // build up the look up table
536
563
  this.__buildUpLookupTable();
537
564
 
538
- // sync the target selection in case someone deleted a item in
539
- // selection mode "one" [BUG #4839]
540
- this.__syncTargetSelection = true;
541
- qx.ui.core.queue.Widget.add(this);
565
+ if (!this.getAllowSelectionNotInModel()) {
566
+ // sync the target selection in case someone deleted a item in
567
+ // selection mode "one" [BUG #4839]
568
+ this.__syncTargetSelection = true;
569
+ qx.ui.core.queue.Widget.add(this);
570
+ }
542
571
  },
543
572
 
544
573
  /**
@@ -61,6 +61,24 @@ qx.Mixin.define("qx.data.controller.MSelection", {
61
61
  event: "changeSelection",
62
62
  apply: "_applySelection",
63
63
  init: null
64
+ },
65
+
66
+ /**
67
+ * If set to true, the selection property will be allowed to have items which are not in the model property.
68
+ * If the model property changes, this will not cause the selection property to be reset.
69
+ *
70
+ * If the selection property contains items which are not in the model property,
71
+ * the selection of the target widget (e.g. qx.ui.form.SelectBox) will only be the items that are both in this controller's model property
72
+ * and in this controller's selection property.
73
+ *
74
+ * This is useful when it is undesirable to reset the selection when the model changes,
75
+ * because if the selection is bound to a business object,
76
+ * data in the business object may be overwritten.
77
+ */
78
+ allowSelectionNotInModel: {
79
+ check: "Boolean",
80
+ init: false,
81
+ nullable: false
64
82
  }
65
83
  },
66
84
 
@@ -125,6 +143,16 @@ qx.Mixin.define("qx.data.controller.MSelection", {
125
143
  this.resetSelection();
126
144
  },
127
145
 
146
+ /**
147
+ * Removes any items from the selection property that are not in the model property.
148
+ */
149
+ syncSelectionWithModel() {
150
+ //We will create a copy of my selection array and work on that to ensure there is only one change event being fired.
151
+ let mySelection = this.getSelection().copy();
152
+ mySelection = mySelection.filter(item => this.getModel().includes(item));
153
+ this.getSelection().replace(mySelection);
154
+ },
155
+
128
156
  /*
129
157
  ---------------------------------------------------------------------------
130
158
  APPLY METHODS
@@ -226,6 +254,8 @@ qx.Mixin.define("qx.data.controller.MSelection", {
226
254
  /**
227
255
  * Helper method which should be called by the classes including this
228
256
  * Mixin when the target changes.
257
+ * Removes the 'changeSelection' listener from the old target
258
+ * and add a new one to the new target;
229
259
  *
230
260
  * @param value {qx.ui.core.Widget|null} The new target.
231
261
  * @param old {qx.ui.core.Widget|null} The old target.
@@ -268,9 +298,9 @@ qx.Mixin.define("qx.data.controller.MSelection", {
268
298
  // if its a multi selection target
269
299
  if (this.__targetSupportsMultiSelection()) {
270
300
  var targetSelection = [];
271
- // go through the selection array
301
+ // go through my selection array
272
302
  for (var i = 0; i < this.getSelection().length; i++) {
273
- // store each item
303
+ // store each selectable item from target widget
274
304
  var model = this.getSelection().getItem(i);
275
305
  var selectable = this.__getSelectableForModel(model);
276
306
  if (selectable != null) {
@@ -281,21 +311,24 @@ qx.Mixin.define("qx.data.controller.MSelection", {
281
311
 
282
312
  // get the selection of the target
283
313
  targetSelection = this.getTarget().getSelection();
284
- // get all items selected in the list
285
- var targetSelectionItems = [];
314
+ // get all models of items selected in the target
315
+ var targetSelectionModels = [];
286
316
  for (var i = 0; i < targetSelection.length; i++) {
287
- targetSelectionItems[i] = targetSelection[i].getModel();
317
+ targetSelectionModels[i] = targetSelection[i].getModel();
288
318
  }
289
319
 
290
- // go through the controller selection
291
- for (var i = this.getSelection().length - 1; i >= 0; i--) {
292
- // if the item in the controller selection is not selected in the list
293
- if (!targetSelectionItems.includes(this.getSelection().getItem(i))) {
294
- // remove the current element and get rid of the return array
295
- this.getSelection().splice(i, 1).dispose();
320
+ if (!this.getAllowSelectionNotInModel()) {
321
+ // go through the controller selection
322
+ for (var i = this.getSelection().length - 1; i >= 0; i--) {
323
+ // if the item in the controller selection is not selected in the list
324
+ if (
325
+ !targetSelectionModels.includes(this.getSelection().getItem(i))
326
+ ) {
327
+ // remove the current element and get rid of the return array
328
+ this.getSelection().splice(i, 1).dispose();
329
+ }
296
330
  }
297
331
  }
298
-
299
332
  // if its a single selection target
300
333
  } else if (this.__targetSupportsSingleSelection()) {
301
334
  // get the model which should be selected
@@ -85,5 +85,13 @@ qx.Class.define("qx.dev.unit.AsyncWrapper", {
85
85
  nullable: false,
86
86
  init: 10000
87
87
  }
88
+ },
89
+
90
+ environment: {
91
+ /**
92
+ * The factor by which any delay is multiplied or false or zero if no such
93
+ * factor should be applied.
94
+ */
95
+ "qx.test.delay.scale": false
88
96
  }
89
97
  });