@qooxdoo/framework 7.7.2 → 7.9.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.
- package/Manifest.json +2 -2
- package/lib/compiler/compile-info.json +91 -89
- package/lib/compiler/index.js +2517 -1488
- package/lib/resource/qx/tool/schema/compile-1-0-0.json +13 -0
- package/lib/resource/qx/tool/website/build/404.html +3 -25
- package/lib/resource/qx/tool/website/build/about.html +3 -25
- package/lib/resource/qx/tool/website/build/assets/common.js +20 -0
- package/lib/resource/qx/tool/website/build/diagnostics/dependson.html +3 -25
- package/lib/resource/qx/tool/website/build/diagnostics/requiredby.html +3 -22
- package/lib/resource/qx/tool/website/build/index.html +3 -25
- package/lib/resource/qx/tool/website/partials/footer.html +3 -21
- package/lib/resource/qx/tool/website/partials/head.html +0 -1
- package/package.json +2 -2
- package/source/class/qx/Bootstrap.js +6 -3
- package/source/class/qx/Promise.js +93 -6964
- package/source/class/qx/bom/Label.js +82 -2
- package/source/class/qx/bom/webfonts/WebFont.js +1 -0
- package/source/class/qx/core/Environment.js +83 -1
- package/source/class/qx/data/controller/List.js +50 -21
- package/source/class/qx/data/controller/MSelection.js +45 -12
- package/source/class/qx/data/marshal/Json.js +64 -11
- package/source/class/qx/dev/unit/AsyncWrapper.js +8 -0
- package/source/class/qx/event/Manager.js +163 -124
- package/source/class/qx/io/ImageLoader.js +6 -3
- package/source/class/qx/io/exception/Transport.js +1 -0
- package/source/class/qx/io/jsonrpc/Client.js +64 -8
- package/source/class/qx/io/jsonrpc/protocol/Request.js +10 -6
- package/source/class/qx/lang/Type.js +36 -3
- package/source/class/qx/promise/BluebirdImpl.js +6918 -0
- package/source/class/qx/promise/NativeWrapper.js +738 -0
- package/source/class/qx/test/Promise.js +1145 -22
- package/source/class/qx/test/bom/client/Pdfjs.js +4 -0
- package/source/class/qx/test/bom/element/AnimationJs.js +3 -0
- package/source/class/qx/test/bom/element/Style.js +1 -0
- package/source/class/qx/test/bom/media/MediaTestCase.js +6 -0
- package/source/class/qx/test/core/Environment.js +44 -0
- package/source/class/qx/test/data/controller/List.js +6 -0
- package/source/class/qx/test/data/marshal/Json.js +29 -0
- package/source/class/qx/test/io/MAssert.js +94 -0
- package/source/class/qx/test/io/TestMAssert.js +47 -0
- package/source/class/qx/test/io/jsonrpc/Client.js +79 -19
- package/source/class/qx/test/io/jsonrpc/PostMessageClient.js +152 -0
- package/source/class/qx/test/io/jsonrpc/Protocol.js +1 -5
- package/source/class/qx/test/io/request/Xhr.js +16 -0
- package/source/class/qx/test/lang/Type.js +151 -0
- package/source/class/qx/test/ui/embed/Iframe.js +1 -1
- package/source/class/qx/test/ui/form/TextArea.js +4 -0
- package/source/class/qx/test/util/DeferredCall.js +6 -0
- package/source/class/qx/test/util/Function.js +2 -2
- package/source/class/qx/theme/indigo/ColorDark.js +1 -1
- package/source/class/qx/tool/cli/api/Test.js +22 -0
- package/source/class/qx/tool/cli/commands/Compile.js +17 -4
- package/source/class/qx/tool/cli/commands/Test.js +7 -1
- package/source/class/qx/tool/compiler/Analyser.js +7 -0
- package/source/class/qx/tool/compiler/ClassFile.js +3 -2
- package/source/class/qx/tool/compiler/MetaExtraction.js +0 -5
- package/source/class/qx/tool/compiler/targets/meta/Browserify.js +8 -2
- package/source/class/qx/ui/basic/Image.js +72 -8
- package/source/class/qx/ui/basic/Label.js +4 -6
- package/source/class/qx/ui/control/DateChooser.js +4 -6
- package/source/class/qx/ui/core/Blocker.js +4 -6
- package/source/class/qx/ui/core/LayoutItem.js +4 -6
- package/source/class/qx/ui/core/MPlacement.js +23 -1
- package/source/class/qx/ui/core/Widget.js +7 -5
- package/source/class/qx/ui/form/AbstractField.js +4 -6
- package/source/class/qx/ui/form/MForm.js +4 -6
- package/source/class/qx/ui/form/Spinner.js +4 -6
- package/source/class/qx/ui/form/renderer/AbstractRenderer.js +4 -6
- package/source/class/qx/ui/menu/AbstractButton.js +7 -11
- package/source/class/qx/ui/mobile/basic/Label.js +4 -6
- package/source/class/qx/ui/mobile/form/Label.js +4 -6
- package/source/class/qx/ui/mobile/list/List.js +4 -6
- package/source/class/qx/ui/progressive/renderer/table/Row.js +35 -7
- package/source/class/qx/ui/progressive/renderer/table/cell/Boolean.js +4 -6
- package/source/class/qx/ui/table/Table.js +4 -6
- package/source/class/qx/ui/table/cellrenderer/Abstract.js +4 -6
- package/source/class/qx/ui/table/cellrenderer/Boolean.js +4 -6
- package/source/class/qx/ui/table/pane/Scroller.js +1 -1
- package/source/class/qx/ui/table/rowrenderer/Default.js +4 -6
- package/source/class/qx/util/ConcurrencyLimiter.js +78 -0
- package/source/resource/qx/tool/schema/compile-1-0-0.json +13 -0
- package/source/resource/qx/tool/website/build/404.html +3 -25
- package/source/resource/qx/tool/website/build/about.html +3 -25
- package/source/resource/qx/tool/website/build/assets/common.js +20 -0
- package/source/resource/qx/tool/website/build/diagnostics/dependson.html +3 -25
- package/source/resource/qx/tool/website/build/diagnostics/requiredby.html +3 -22
- package/source/resource/qx/tool/website/build/index.html +3 -25
- package/source/resource/qx/tool/website/partials/footer.html +3 -21
- package/source/resource/qx/tool/website/partials/head.html +0 -1
- package/lib/resource/qx/tool/website/build/assets/bluebird.min.js +0 -4615
- package/lib/resource/qx/tool/website/src/assets/bluebird.min.js +0 -4615
- package/source/resource/qx/tool/website/build/assets/bluebird.min.js +0 -4615
- package/source/resource/qx/tool/website/src/assets/bluebird.min.js +0 -4615
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
/**
|
|
@@ -891,6 +891,7 @@ qx.Bootstrap.define("qx.core.Environment", {
|
|
|
891
891
|
"qx.dynlocale": true,
|
|
892
892
|
"qx.dyntheme": true,
|
|
893
893
|
"qx.blankpage": "qx/static/blank.html",
|
|
894
|
+
"qx.data.marshal.Json.breakOnNonPojos": false,
|
|
894
895
|
"qx.debug.databinding": false,
|
|
895
896
|
"qx.debug.dispose": false,
|
|
896
897
|
"qx.debug.startupTimings": false,
|
|
@@ -913,7 +914,8 @@ qx.Bootstrap.define("qx.core.Environment", {
|
|
|
913
914
|
"qx.promise.warnings": true,
|
|
914
915
|
"qx.promise.longStackTraces": true,
|
|
915
916
|
"qx.command.bindEnabled": false,
|
|
916
|
-
"qx.headless": false
|
|
917
|
+
"qx.headless": false,
|
|
918
|
+
"qx.environment.allowRuntimeMutations": false
|
|
917
919
|
},
|
|
918
920
|
|
|
919
921
|
/**
|
|
@@ -1210,6 +1212,74 @@ qx.Bootstrap.define("qx.core.Environment", {
|
|
|
1210
1212
|
return this._asyncChecks;
|
|
1211
1213
|
},
|
|
1212
1214
|
|
|
1215
|
+
// mutation of environment settings at runtime
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Sets the environment setting for the given key to the given value. This deletes any check function
|
|
1219
|
+
* associated with this key.
|
|
1220
|
+
*
|
|
1221
|
+
* This method is only available if "qx.environment.allowRuntimeMutations" is set to true.
|
|
1222
|
+
*
|
|
1223
|
+
* @param key {String} The key of the environment setting to set.
|
|
1224
|
+
* @param value {var} The value to set the environment setting to. Must be a scalar value.
|
|
1225
|
+
*/
|
|
1226
|
+
set: qx.Bootstrap.getEnvironmentSetting("qx.environment.allowRuntimeMutations") ? function(key, value) {
|
|
1227
|
+
if (key === undefined) {
|
|
1228
|
+
throw new TypeError("Key must be provided to set an environment setting.");
|
|
1229
|
+
}
|
|
1230
|
+
if (this.__environmentBackup === undefined) {
|
|
1231
|
+
qx.Bootstrap.warn("Modifying environment settings at runtime is enabled. This is a security risk and should not be done in production code.");
|
|
1232
|
+
this.__environmentBackup = Object.assign({}, this.__cache);
|
|
1233
|
+
this.__checksBackup = Object.assign({}, this._checks);
|
|
1234
|
+
}
|
|
1235
|
+
this.__cache[key] = value;
|
|
1236
|
+
delete this._checks[key];
|
|
1237
|
+
delete this._checksMap[key];
|
|
1238
|
+
}: undefined,
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* Removes the environment setting for the given key, and any check function associated with it.
|
|
1242
|
+
* This method is only available if "qx.environment.allowRuntimeMutations" is set to true.
|
|
1243
|
+
*
|
|
1244
|
+
* @param key {String} The key of the environment setting to remove.
|
|
1245
|
+
*/
|
|
1246
|
+
remove: qx.Bootstrap.getEnvironmentSetting("qx.environment.allowRuntimeMutations") ? function(key) {
|
|
1247
|
+
if (key === undefined) {
|
|
1248
|
+
throw new TypeError("Key must be provided to remove an environment setting.");
|
|
1249
|
+
}
|
|
1250
|
+
if (this.__environmentBackup === undefined || this.__environmentBackup[key] === undefined) {
|
|
1251
|
+
throw new TypeError(`Environment setting "${key}" does not exist.`);
|
|
1252
|
+
}
|
|
1253
|
+
delete this.__cache[key];
|
|
1254
|
+
delete this._checks[key];
|
|
1255
|
+
delete this._checksMap[key];
|
|
1256
|
+
}: undefined,
|
|
1257
|
+
|
|
1258
|
+
/**
|
|
1259
|
+
* Resets the environment settings to their original values. If a key is provided, only that key is reset.
|
|
1260
|
+
* This method is only available if "qx.environment.allowRuntimeMutations" is set to true.
|
|
1261
|
+
*
|
|
1262
|
+
* @param key {String?} The key of the environment setting to reset. If not provided, all settings are reset.
|
|
1263
|
+
*/
|
|
1264
|
+
reset: qx.Bootstrap.getEnvironmentSetting("qx.environment.allowRuntimeMutations") ? function(key) {
|
|
1265
|
+
if (this.__environmentBackup === undefined) {
|
|
1266
|
+
// no backup available, nothing to reset
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
if (key !== undefined && this.__environmentBackup[key] === undefined) {
|
|
1270
|
+
throw new TypeError(`Environment setting "${key}" does not exist.`);
|
|
1271
|
+
}
|
|
1272
|
+
if (key === undefined) {
|
|
1273
|
+
// reset all keys
|
|
1274
|
+
this.__cache = Object.assign({}, this.__environmentBackup);
|
|
1275
|
+
this._checks = Object.assign({}, this.__checksBackup);
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
// only reset the particular key
|
|
1279
|
+
this.__cache[key] = this.__environmentBackup[key];
|
|
1280
|
+
this._checks[key] = this.__checksBackup[key];
|
|
1281
|
+
}: undefined,
|
|
1282
|
+
|
|
1213
1283
|
/**
|
|
1214
1284
|
* Initializer for the default values of the framework settings.
|
|
1215
1285
|
*/
|
|
@@ -1296,5 +1366,17 @@ qx.Bootstrap.define("qx.core.Environment", {
|
|
|
1296
1366
|
if (statics.get("qx.allowUrlSettings") === true) {
|
|
1297
1367
|
statics.__importFromUrl();
|
|
1298
1368
|
}
|
|
1369
|
+
},
|
|
1370
|
+
|
|
1371
|
+
environment: {
|
|
1372
|
+
/**
|
|
1373
|
+
* By setting this key to true, the environment variables can be mutated at runtime, using the {@link #set} method,
|
|
1374
|
+
* which is otherwise not available. This is only useful for testing and debugging purposes. We strongly advise
|
|
1375
|
+
* against enabling this in production code. You have been warned.
|
|
1376
|
+
* Note: This enviroment key declaration is only for documentation purposes and is not used during bootstrapping, so
|
|
1377
|
+
* changing the value here will have no effect.
|
|
1378
|
+
*/
|
|
1379
|
+
"qx.environment.allowRuntimeMutations": false,
|
|
1299
1380
|
}
|
|
1381
|
+
|
|
1300
1382
|
});
|
|
@@ -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
|
-
|
|
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
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
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
|
-
|
|
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
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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
|
|
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
|
|
285
|
-
var
|
|
314
|
+
// get all models of items selected in the target
|
|
315
|
+
var targetSelectionModels = [];
|
|
286
316
|
for (var i = 0; i < targetSelection.length; i++) {
|
|
287
|
-
|
|
317
|
+
targetSelectionModels[i] = targetSelection[i].getModel();
|
|
288
318
|
}
|
|
289
319
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
|
@@ -37,6 +37,10 @@ qx.Class.define("qx.data.marshal.Json", {
|
|
|
37
37
|
},
|
|
38
38
|
|
|
39
39
|
statics: {
|
|
40
|
+
/**
|
|
41
|
+
* Set to true when a warning has been shown that we are using the deprecated behaviour of trying to marshall non-POJO objects into Qooxdoo objects.
|
|
42
|
+
*/
|
|
43
|
+
__shownNotBreakingOnNonPojosWarning: false,
|
|
40
44
|
$$instance: null,
|
|
41
45
|
|
|
42
46
|
/**
|
|
@@ -76,6 +80,25 @@ qx.Class.define("qx.data.marshal.Json", {
|
|
|
76
80
|
Object.keys(data).sort().join('"') +
|
|
77
81
|
(includeBubbleEvents === true ? "♥" : "")
|
|
78
82
|
);
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* If the environment setting "qx.data.marshal.Json.breakOnNonPojos" is not set,
|
|
87
|
+
* it means we are using the old behaviour of marshalling non-POJO objects.
|
|
88
|
+
* A warning is shown if it hasn't been shown already.
|
|
89
|
+
*/
|
|
90
|
+
checkIfWarnAboutNotBreakingOnNonPojos() {
|
|
91
|
+
if (
|
|
92
|
+
!qx.core.Environment.get("qx.data.marshal.Json.breakOnNonPojos") &&
|
|
93
|
+
!this.__shownNotBreakingOnNonPojosWarning
|
|
94
|
+
) {
|
|
95
|
+
console.warn(
|
|
96
|
+
`Using deprecated behaviour of not breaking on non-POJOs when marshalling.
|
|
97
|
+
Please set the environment setting "qx.data.marshal.Json.breakOnNonPojos" to enable the new behaviour.
|
|
98
|
+
The old behaviour will be removed in the next major release of Qooxdoo.`
|
|
99
|
+
);
|
|
100
|
+
this.__shownNotBreakingOnNonPojosWarning = true;
|
|
101
|
+
}
|
|
79
102
|
}
|
|
80
103
|
},
|
|
81
104
|
|
|
@@ -170,12 +193,26 @@ qx.Class.define("qx.data.marshal.Json", {
|
|
|
170
193
|
* @param depth {Number} The depth of the data relative to the data's root.
|
|
171
194
|
*/
|
|
172
195
|
__toClass(data, includeBubbleEvents, parentProperty, depth) {
|
|
196
|
+
const breakOnNonPojos = qx.core.Environment.get(
|
|
197
|
+
"qx.data.marshal.Json.breakOnNonPojos"
|
|
198
|
+
);
|
|
199
|
+
this.constructor.checkIfWarnAboutNotBreakingOnNonPojos();
|
|
200
|
+
|
|
173
201
|
// break on all primitive json types and qooxdoo objects
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
202
|
+
let shouldBreak;
|
|
203
|
+
if (breakOnNonPojos) {
|
|
204
|
+
shouldBreak =
|
|
205
|
+
!qx.lang.Type.isPojo(data) ||
|
|
206
|
+
!!data.$$isString || // check for localized strings
|
|
207
|
+
data instanceof qx.core.Object;
|
|
208
|
+
} else {
|
|
209
|
+
shouldBreak =
|
|
210
|
+
!qx.lang.Type.isObject(data) ||
|
|
211
|
+
!!data.$$isString || // check for localized strings
|
|
212
|
+
data instanceof qx.core.Object;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (shouldBreak) {
|
|
179
216
|
// check for arrays
|
|
180
217
|
if (data instanceof Array || qx.Bootstrap.getClass(data) == "Array") {
|
|
181
218
|
for (var i = 0; i < data.length; i++) {
|
|
@@ -405,15 +442,31 @@ qx.Class.define("qx.data.marshal.Json", {
|
|
|
405
442
|
* @return {qx.core.Object} The created model object.
|
|
406
443
|
*/
|
|
407
444
|
__toModel(data, includeBubbleEvents, parentProperty, depth) {
|
|
445
|
+
const breakOnNonPojos = qx.core.Environment.get(
|
|
446
|
+
"qx.data.marshal.Json.breakOnNonPojos"
|
|
447
|
+
);
|
|
448
|
+
this.constructor.checkIfWarnAboutNotBreakingOnNonPojos();
|
|
449
|
+
|
|
408
450
|
var isObject = qx.lang.Type.isObject(data);
|
|
451
|
+
var isPojo = qx.lang.Type.isPojo(data);
|
|
452
|
+
|
|
409
453
|
var isArray =
|
|
410
454
|
data instanceof Array || qx.Bootstrap.getClass(data) == "Array";
|
|
411
455
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
456
|
+
let shouldBreak;
|
|
457
|
+
if (breakOnNonPojos) {
|
|
458
|
+
shouldBreak =
|
|
459
|
+
(!isPojo && !isArray) ||
|
|
460
|
+
!!data.$$isString || // check for localized strings
|
|
461
|
+
data instanceof qx.core.Object;
|
|
462
|
+
} else {
|
|
463
|
+
shouldBreak =
|
|
464
|
+
(!isObject && !isArray) ||
|
|
465
|
+
!!data.$$isString || // check for localized strings
|
|
466
|
+
data instanceof qx.core.Object;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (shouldBreak) {
|
|
417
470
|
return data;
|
|
418
471
|
|
|
419
472
|
// ignore rules
|
|
@@ -451,7 +504,7 @@ qx.Class.define("qx.data.marshal.Json", {
|
|
|
451
504
|
);
|
|
452
505
|
}
|
|
453
506
|
return array;
|
|
454
|
-
} else if (isObject) {
|
|
507
|
+
} else if (breakOnNonPojos ? isPojo : isObject) {
|
|
455
508
|
// create an instance for the object
|
|
456
509
|
var hash = this.__jsonToBestHash(data, includeBubbleEvents);
|
|
457
510
|
var model = this.__createInstance(hash, data, parentProperty, depth);
|
|
@@ -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
|
});
|