@qooxdoo/framework 7.5.1 → 7.6.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 (85) hide show
  1. package/Manifest.json +169 -44
  2. package/lib/compiler/compile-info.json +76 -68
  3. package/lib/compiler/index.js +3683 -2588
  4. package/lib/resource/qx/tool/schema/Manifest-1-0-0.json +79 -26
  5. package/lib/resource/qx/tool/schema/Manifest-2-0-0.json +17 -26
  6. package/lib/resource/qx/tool/schema/compile-1-0-0.json +40 -53
  7. package/package.json +2 -2
  8. package/source/class/qx/bom/Font.js +36 -0
  9. package/source/class/qx/bom/webfonts/Validator.js +31 -6
  10. package/source/class/qx/bom/webfonts/WebFont.js +60 -64
  11. package/source/class/qx/bom/webfonts/WebFontLoader.js +461 -0
  12. package/source/class/qx/core/Object.js +1 -1
  13. package/source/class/qx/data/Array.js +27 -0
  14. package/source/class/qx/dev/FakeServer.js +1 -1
  15. package/source/class/qx/event/handler/Focus.js +2 -1
  16. package/source/class/qx/event/handler/GestureCore.js +1 -1
  17. package/source/class/qx/test/bom/webfonts/Validator.js +0 -6
  18. package/source/class/qx/test/core/Environment.js +8 -8
  19. package/source/class/qx/test/core/Validation.js +2 -2
  20. package/source/class/qx/test/dev/unit/Requirements.js +6 -6
  21. package/source/class/qx/test/ui/basic/Image.js +3 -3
  22. package/source/class/qx/test/ui/basic/Label.js +0 -65
  23. package/source/class/qx/test/ui/form/Field.js +56 -52
  24. package/source/class/qx/theme/classic/Font.js +7 -23
  25. package/source/class/qx/theme/iconfont/LoadMaterialIcons.js +2 -4
  26. package/source/class/qx/theme/iconfont/LoadMaterialIconsOutlined.js +2 -4
  27. package/source/class/qx/theme/iconfont/LoadMaterialIconsRound.js +2 -4
  28. package/source/class/qx/theme/iconfont/LoadMaterialIconsSharp.js +2 -4
  29. package/source/class/qx/theme/iconfont/LoadMaterialIconsTwoTone.js +2 -4
  30. package/source/class/qx/theme/indigo/Font.js +8 -15
  31. package/source/class/qx/theme/manager/Font.js +151 -38
  32. package/source/class/qx/theme/modern/Font.js +1 -0
  33. package/source/class/qx/theme/simple/Font.js +3 -1
  34. package/source/class/qx/theme/tangible/Appearance.js +1 -0
  35. package/source/class/qx/theme/tangible/Font.js +9 -62
  36. package/source/class/qx/theme/tangible/Image.js +1 -4
  37. package/source/class/qx/tool/cli/Cli.js +12 -0
  38. package/source/class/qx/tool/cli/Watch.js +3 -0
  39. package/source/class/qx/tool/cli/api/CompilerApi.js +8 -0
  40. package/source/class/qx/tool/cli/commands/Add.js +1 -1
  41. package/source/class/qx/tool/cli/commands/Compile.js +22 -0
  42. package/source/class/qx/tool/cli/commands/Config.js +16 -141
  43. package/source/class/qx/tool/cli/commands/ExportGlyphs.js +134 -0
  44. package/source/class/qx/tool/cli/commands/Package.js +3 -0
  45. package/source/class/qx/tool/cli/commands/Pkg.js +1 -1
  46. package/source/class/qx/tool/cli/commands/config/Delete.js +47 -0
  47. package/source/class/qx/tool/cli/commands/config/Get.js +52 -0
  48. package/source/class/qx/tool/cli/commands/config/List.js +81 -0
  49. package/source/class/qx/tool/cli/commands/config/Set.js +61 -0
  50. package/source/class/qx/tool/cli/commands/package/Update.js +3 -3
  51. package/source/class/qx/tool/compiler/Analyser.js +45 -0
  52. package/source/class/qx/tool/compiler/ClassFile.js +41 -0
  53. package/source/class/qx/tool/compiler/Console.js +6 -1
  54. package/source/class/qx/tool/compiler/app/Application.js +19 -0
  55. package/source/class/qx/tool/compiler/app/Library.js +51 -2
  56. package/source/class/qx/tool/compiler/app/ManifestFont.js +181 -0
  57. package/source/class/qx/tool/compiler/app/WebFont.js +144 -234
  58. package/source/class/qx/tool/compiler/makers/AppMaker.js +13 -0
  59. package/source/class/qx/tool/compiler/resources/ImageLoader.js +22 -12
  60. package/source/class/qx/tool/compiler/resources/Manager.js +2 -2
  61. package/source/class/qx/tool/compiler/resources/MetaLoader.js +7 -2
  62. package/source/class/qx/tool/compiler/resources/ResourceLoader.js +21 -0
  63. package/source/class/qx/tool/compiler/targets/Target.js +186 -67
  64. package/source/class/qx/tool/migration/M7_5_6.js +75 -0
  65. package/source/class/qx/tool/utils/Http.js +69 -0
  66. package/source/class/qx/ui/basic/Label.js +20 -38
  67. package/source/class/qx/ui/form/AbstractField.js +8 -2
  68. package/source/class/qx/ui/form/FileSelectorButton.js +5 -0
  69. package/source/class/qx/ui/table/pane/FocusIndicator.js +5 -4
  70. package/source/class/qx/ui/table/pane/Pane.js +14 -0
  71. package/source/class/qx/ui/table/pane/Scroller.js +3 -3
  72. package/source/class/qx/ui/virtual/core/Scroller.js +8 -2
  73. package/source/class/qx/ui/window/Window.js +9 -8
  74. package/source/resource/qx/iconfont/MaterialIcons/materialicons.json +10912 -0
  75. package/source/resource/qx/iconfont/MaterialIcons/materialiconsoutlined.json +10967 -0
  76. package/source/resource/qx/iconfont/MaterialIcons/materialiconsround.json +10992 -0
  77. package/source/resource/qx/iconfont/MaterialIcons/materialiconssharp.json +10992 -0
  78. package/source/resource/qx/iconfont/MaterialIcons/materialiconstwotone.json +9947 -0
  79. package/source/resource/qx/iconfont/MaterialIcons/x.json +10967 -0
  80. package/source/resource/qx/iconfont/export-glyphs.sh +22 -0
  81. package/source/resource/qx/tool/schema/Manifest-1-0-0.json +79 -26
  82. package/source/resource/qx/tool/schema/Manifest-2-0-0.json +17 -26
  83. package/source/resource/qx/tool/schema/compile-1-0-0.json +40 -53
  84. package/source/class/qx/bom/webfonts/Manager.js +0 -652
  85. package/source/class/qx/test/bom/webfonts/Manager.js +0 -238
@@ -106,6 +106,22 @@ qx.Class.define("qx.tool.compiler.targets.Target", {
106
106
  check: "Boolean"
107
107
  },
108
108
 
109
+ /**
110
+ * Whether to prefer local fonts instead of CDNs
111
+ */
112
+ preferLocalFonts: {
113
+ init: false,
114
+ check: "Boolean"
115
+ },
116
+
117
+ /**
118
+ * Types of fonts to be included
119
+ */
120
+ fontTypes: {
121
+ init: ["woff"],
122
+ check: "Array"
123
+ },
124
+
109
125
  /**
110
126
  * Whether to add timestamps to all URLs (cache busting)
111
127
  */
@@ -442,7 +458,7 @@ qx.Class.define("qx.tool.compiler.targets.Target", {
442
458
  bootPackage.addJavascriptMeta(
443
459
  new qx.tool.compiler.targets.meta.Browserify(appMeta)
444
460
  );
445
- }
461
+ }
446
462
 
447
463
  /*
448
464
  * Assemble the Parts
@@ -506,12 +522,10 @@ qx.Class.define("qx.tool.compiler.targets.Target", {
506
522
  var assetUris = application.getAssetUris(t, rm, appMeta.getEnvironment()); // Save any changes that getAssets collected
507
523
  await rm.saveDatabase();
508
524
 
509
- var promises = [
510
- analyser.getCldr("en").then(cldr => bootPackage.addLocale("C", cldr)),
511
- t._writeTranslations()
512
- ];
525
+ let cldr = await analyser.getCldr("en");
526
+ await bootPackage.addLocale("C", cldr);
527
+ await this._writeTranslations();
513
528
 
514
- var fontCntr = 0;
515
529
  var assets = {};
516
530
  rm.getAssetsForPaths(assetUris).forEach(asset => {
517
531
  bootPackage.addAsset(asset);
@@ -519,75 +533,180 @@ qx.Class.define("qx.tool.compiler.targets.Target", {
519
533
  });
520
534
 
521
535
  if (analyser.getApplicationTypes().indexOf("browser") > -1) {
522
- // Get a list of all fonts to load; use the font name as a unique identifier, and
523
- // prioritise the application's library's definitions - this allows the application
524
- // the opportunity to override the font definitions. This is important when the
525
- // library uses the open source/free versions of a font but the application
526
- // developer has purchased the commercial/full version of the font (eg FontAwesome)
527
- let appLibrary = appMeta.getAppLibrary();
528
- let fontsToLoad = {};
529
- const addLibraryFonts = library => {
530
- var fonts = library.getWebFonts();
531
- if (!fonts) {
532
- return;
533
- }
534
- fonts.forEach(font => {
535
- fontsToLoad[font.getName()] = {
536
- font,
537
- library
538
- };
539
- });
540
- };
541
- requiredLibs.forEach(libnamespace => {
542
- var library = analyser.findLibrary(libnamespace);
543
- if (library != appLibrary) {
544
- addLibraryFonts(library);
545
- }
546
- });
547
- addLibraryFonts(appLibrary);
548
-
549
- const loadFont = async (library, font) => {
550
- try {
551
- // check if font is asset somewhere
552
- let res = font.getResources().filter(res => assets[res]);
553
- if (res.length === 0) {
554
- qx.tool.compiler.Console.print(
555
- "qx.tool.compiler.webfonts.noResources",
556
- font.toString(),
557
- application.getName(),
558
- font.getResources().join(",")
559
- );
536
+ appMeta.addPreBootCode("qx.$$fontBootstrap={};\n");
537
+ await this.__writeDeprecatedWebFonts(application, appMeta, assets);
538
+ await this.__writeManifestFonts(
539
+ application,
540
+ appMeta,
541
+ assets,
542
+ bootPackage
543
+ );
544
+ }
545
+ await this._writeApplication();
546
+ this.__appMeta = null;
547
+ },
560
548
 
561
- return;
562
- }
563
- font.setResources(res);
549
+ /**
550
+ * Writes the fonts defined in provides.webfonts
551
+ * @deprecated
552
+ */
553
+ async __writeDeprecatedWebFonts(application, appMeta, assets) {
554
+ let analyser = application.getAnalyser();
555
+ const requiredLibs = application.getRequiredLibraries();
564
556
 
565
- await font.generateForTarget(t);
566
- let resources = await font.generateForApplication(t, application);
567
- for (var key in resources) {
568
- appMeta.addResource(key, resources[key]);
569
- }
570
- var code = font.getBootstrapCode(t, application, fontCntr++ == 0);
571
- if (code) {
572
- appMeta.addPreBootCode(code);
573
- }
574
- } catch (ex) {
557
+ // Get a list of all fonts to load; use the font name as a unique identifier, and
558
+ // prioritise the application's library's definitions - this allows the application
559
+ // the opportunity to override the font definitions. This is important when the
560
+ // library uses the open source/free versions of a font but the application
561
+ // developer has purchased the commercial/full version of the font (eg FontAwesome)
562
+ let appLibrary = appMeta.getAppLibrary();
563
+ let fontsToLoad = {};
564
+ const addLibraryFonts = library => {
565
+ var fonts = library.getWebFonts();
566
+ if (!fonts) {
567
+ return;
568
+ }
569
+ fonts.forEach(font => {
570
+ fontsToLoad[font.getName()] = {
571
+ font,
572
+ library
573
+ };
574
+ });
575
+ };
576
+ requiredLibs.forEach(libnamespace => {
577
+ var library = analyser.findLibrary(libnamespace);
578
+ if (library != appLibrary) {
579
+ addLibraryFonts(library);
580
+ }
581
+ });
582
+ addLibraryFonts(appLibrary);
583
+
584
+ const loadFont = async (library, font) => {
585
+ try {
586
+ // check if font is asset somewhere
587
+ let res = font.getResources().filter(res => assets[res]);
588
+ if (res.length === 0) {
575
589
  qx.tool.compiler.Console.print(
576
- "qx.tool.compiler.webfonts.error",
590
+ "qx.tool.compiler.webfonts.noResources",
577
591
  font.toString(),
578
- ex.toString()
592
+ application.getName(),
593
+ font.getResources().join(",")
579
594
  );
595
+
596
+ return;
580
597
  }
581
- };
598
+ font.setResources(res);
582
599
 
583
- Object.keys(fontsToLoad).forEach(fontName => {
584
- let { font, library } = fontsToLoad[fontName];
585
- promises.push(loadFont(library, font));
586
- });
600
+ await font.generateForTarget(this);
601
+ let resources = await font.generateForApplication(this, application);
602
+ for (var key in resources) {
603
+ appMeta.addResource(key, resources[key]);
604
+ }
605
+ var code = font.getBootstrapCode(this, application);
606
+ if (code) {
607
+ appMeta.addPreBootCode(code);
608
+ }
609
+ } catch (ex) {
610
+ qx.tool.compiler.Console.print(
611
+ "qx.tool.compiler.webfonts.error",
612
+ font.toString(),
613
+ ex.toString()
614
+ );
615
+ }
616
+ };
617
+
618
+ for (let fontName of Object.keys(fontsToLoad)) {
619
+ let { font, library } = fontsToLoad[fontName];
620
+ await loadFont(library, font);
621
+ }
622
+ },
623
+
624
+ /**
625
+ * Writes the fonts defined in provides.fonts
626
+ */
627
+ async __writeManifestFonts(application, appMeta, assets, bootPackage) {
628
+ let analyser = application.getAnalyser();
629
+ let rm = analyser.getResourceManager();
630
+
631
+ const addResourcesToBuild = resourcePaths => {
632
+ for (let asset of rm.getAssetsForPaths(resourcePaths)) {
633
+ bootPackage.addAsset(asset);
634
+ assets[asset.getFilename()] = asset.toString();
635
+ }
636
+ };
637
+
638
+ let fontNames = application.getFonts();
639
+ for (let fontName of fontNames) {
640
+ let font = analyser.getFont(fontName);
641
+ if (!font) {
642
+ return;
643
+ }
644
+ let resources = font.getApplicationFontData();
645
+ for (var key in resources) {
646
+ appMeta.addResource(key, resources[key]);
647
+ }
648
+ let fontFaces = font.getFontFaces() || [];
649
+
650
+ // Break out the CSS into local resource files and URLs
651
+ let fontCss = font.getCss() || [];
652
+ let cssUrls = [];
653
+ let cssResources = [];
654
+ for (let urlOrPath of fontCss) {
655
+ if (urlOrPath.match(/^https?:/)) {
656
+ cssUrls.push(urlOrPath);
657
+ } else {
658
+ cssResources.push(urlOrPath);
659
+ }
660
+ }
661
+
662
+ // Exclude font files that we do not want to include
663
+ let types = this.getFontTypes();
664
+ let hasLocalFontResources = false;
665
+ let hasUrlFontResources = false;
666
+ if (types.length) {
667
+ for (let fontFace of fontFaces) {
668
+ fontFace.paths = fontFace.paths.filter(filename => {
669
+ let pos = filename.lastIndexOf(".");
670
+ if (pos > -1) {
671
+ let ext = filename.substring(pos + 1);
672
+ if (types.indexOf(ext) > -1) {
673
+ return true;
674
+ }
675
+ }
676
+ if (!filename.match(/^https?:/)) {
677
+ hasLocalFontResources = true;
678
+ } else {
679
+ hasUrlFontResources = true;
680
+ }
681
+ return false;
682
+ });
683
+ }
684
+ }
685
+
686
+ // It is important to always prefer local fonts if we have them and are not instructed to prefer CDNs
687
+ let useLocalFonts = cssUrls.length == 0 && !hasUrlFontResources;
688
+ if (
689
+ this.isPreferLocalFonts() &&
690
+ (cssResources.length > 0 || hasLocalFontResources)
691
+ ) {
692
+ useLocalFonts = true;
693
+ }
694
+
695
+ // Make sure we add any CSS and font resource files to the target output
696
+ if (useLocalFonts) {
697
+ addResourcesToBuild(cssResources);
698
+
699
+ for (let fontFace of fontFaces) {
700
+ addResourcesToBuild(fontFace.paths);
701
+ }
702
+ }
703
+
704
+ var code = font.getBootstrapCode(this, application, useLocalFonts);
705
+
706
+ if (code) {
707
+ appMeta.addPreBootCode(code);
708
+ }
587
709
  }
588
- await qx.Promise.all(promises);
589
- await t._writeApplication();
590
- this.__appMeta = null;
591
710
  },
592
711
 
593
712
  /**
@@ -0,0 +1,75 @@
1
+ /* ************************************************************************
2
+
3
+ qooxdoo - the new era of web development
4
+
5
+ http://qooxdoo.org
6
+
7
+ Copyright:
8
+ 2023 Zenesis Limited https://www.zenesis.com
9
+
10
+ License:
11
+ MIT: https://opensource.org/licenses/MIT
12
+ See the LICENSE file in the project's top-level directory for details.
13
+
14
+ Authors:
15
+ * John Spackman (@johnspackman)
16
+
17
+ ************************************************************************ */
18
+
19
+ const process = require("process");
20
+ const path = require("upath");
21
+ const semver = require("semver");
22
+ const fs = qx.tool.utils.Promisify.fs;
23
+
24
+ /**
25
+ * Migration class for updating to v7.5.6
26
+ */
27
+ qx.Class.define("qx.tool.migration.M7_5_6", {
28
+ extend: qx.tool.migration.BaseMigration,
29
+ members: {
30
+ async migrateManifest() {
31
+ let dryRun = this.getRunner().getDryRun();
32
+ let verbose = this.getRunner().getVerbose();
33
+ // Update all Manifests
34
+ let updateManifest = false;
35
+ for (const manifestModel of await qx.tool.config.Utils.getManifestModels()) {
36
+ manifestModel.set({ warnOnly: true });
37
+ await manifestModel.load();
38
+ let data = manifestModel.getData();
39
+
40
+ if (
41
+ data.provides?.webfonts !== undefined &&
42
+ data.provides?.fonts === undefined
43
+ ) {
44
+ if (dryRun) {
45
+ this.markAsPending(
46
+ "provides.webfonts will be replaced with provides.fonts"
47
+ );
48
+ } else {
49
+ this.markAsApplied();
50
+ let fontsData = {};
51
+ data.provides.webfonts.forEach(data => {
52
+ let fontData = (fontsData[data.name] = {});
53
+ ["defaultSize", "comparisonString"].forEach(name => {
54
+ let value = data[name];
55
+ if (value !== undefined) {
56
+ fontData[name] = value;
57
+ }
58
+ });
59
+ if (data.resources !== undefined) {
60
+ fontData.sources = data.resources;
61
+ }
62
+ });
63
+ data.provides.fonts = fontsData;
64
+ delete data.provides.webfonts;
65
+ }
66
+ }
67
+
68
+ // save Manifest file
69
+ if (!dryRun) {
70
+ await manifestModel.save();
71
+ }
72
+ }
73
+ }
74
+ }
75
+ });
@@ -0,0 +1,69 @@
1
+ /* ************************************************************************
2
+
3
+ qooxdoo - the new era of web development
4
+
5
+ http://qooxdoo.org
6
+
7
+ Copyright:
8
+ 2023 Zenesis Limited https://www.zenesis.com
9
+
10
+ License:
11
+ MIT: https://opensource.org/licenses/MIT
12
+ See the LICENSE file in the project's top-level directory for details.
13
+
14
+ Authors:
15
+ * John Spackman (@johnspackman)
16
+
17
+ ************************************************************************ */
18
+
19
+ const fs = require("fs");
20
+ const path = require("path");
21
+ const tmp = require("tmp");
22
+ const http = require("http");
23
+
24
+ /**
25
+ * Helper methods for HTTP
26
+ */
27
+ qx.Class.define("qx.tool.utils.Http", {
28
+ extend: qx.core.Object,
29
+
30
+ statics: {
31
+ /**
32
+ * Downloads a URL into a temporary file
33
+ *
34
+ * @param {String} url URL to download
35
+ * @param {RegEx?} contentTypeRegEx optional regex for the content type
36
+ * @return {String} temporary filename
37
+ */
38
+ async downloadToTempfile(url, contentTypeRegEx) {
39
+ let tmpFilename = await qx.tool.utils.Promisify.call(cb =>
40
+ tmp.tmpName(cb)
41
+ );
42
+
43
+ await new Promise((resolve, reject) => {
44
+ http.get(url, res => {
45
+ let error;
46
+ const { statusCode } = res;
47
+ const contentType = res.headers["content-type"];
48
+
49
+ if (statusCode !== 200) {
50
+ error = new Error(`Request Failed.\nStatus Code: ${statusCode}`);
51
+ } else if (contentTypeRegEx && !contentTypeRegEx.test(contentType)) {
52
+ error = new Error(`Invalid content-type, received ${contentType}`);
53
+ }
54
+
55
+ if (error) {
56
+ res.resume();
57
+ reject(error);
58
+ return;
59
+ }
60
+
61
+ let outFile = fs.createWriteStream(tmpFilename);
62
+ outFile.on("close", () => resolve(tmpFilename));
63
+ res.on("data", chunk => outFile.write(chunk));
64
+ res.on("end", () => outFile.end());
65
+ });
66
+ });
67
+ }
68
+ }
69
+ });
@@ -318,15 +318,23 @@ qx.Class.define("qx.ui.basic.Label", {
318
318
  // Apply
319
319
  var styles;
320
320
  if (value) {
321
- this.__font = qx.theme.manager.Font.getInstance().resolve(value);
322
- if (this.__font instanceof qx.bom.webfonts.WebFont) {
323
- if (!this.__font.isValid()) {
324
- this.__webfontListenerId = this.__font.addListener(
325
- "changeStatus",
326
- this._onWebFontStatusChange,
327
- this
328
- );
329
- }
321
+ if (qx.lang.Type.isString(value)) {
322
+ value = qx.theme.manager.Font.getInstance().resolve(value);
323
+ }
324
+ this.__font = value;
325
+ if (
326
+ this.__font instanceof qx.bom.webfonts.WebFont &&
327
+ !this.__font.isValid()
328
+ ) {
329
+ this.__webfontListenerId = this.__font.addListener(
330
+ "changeStatus",
331
+ evt => {
332
+ if (evt.getData().valid) {
333
+ this.__invalidContentSize = true;
334
+ qx.ui.core.queue.Layout.add(this);
335
+ }
336
+ }
337
+ );
330
338
  }
331
339
  styles = this.__font.getStyles();
332
340
  } else {
@@ -462,10 +470,10 @@ qx.Class.define("qx.ui.basic.Label", {
462
470
 
463
471
  // property apply
464
472
  _applyBreakWithinWords(value, old) {
465
- this.getContentElement().setStyle(
466
- "wordBreak",
473
+ this.getContentElement().setStyle(
474
+ "wordBreak",
467
475
  this.isRich() && value ? "break-all" : "normal"
468
- );
476
+ );
469
477
  },
470
478
 
471
479
  /**
@@ -485,32 +493,6 @@ qx.Class.define("qx.ui.basic.Label", {
485
493
  false: null
486
494
  }),
487
495
 
488
- /**
489
- * Triggers layout recalculation after a web font was loaded
490
- *
491
- * @param ev {qx.event.type.Data} "changeStatus" event
492
- */
493
- _onWebFontStatusChange(ev) {
494
- if (ev.getData().valid === true) {
495
- // safari has trouble resizing, adding it again fixed the issue [BUG #8786]
496
- if (
497
- qx.core.Environment.get("browser.name") == "safari" &&
498
- parseFloat(qx.core.Environment.get("browser.version")) >= 8
499
- ) {
500
- window.setTimeout(
501
- function () {
502
- this.__invalidContentSize = true;
503
- qx.ui.core.queue.Layout.add(this);
504
- }.bind(this),
505
- 0
506
- );
507
- }
508
-
509
- this.__invalidContentSize = true;
510
- qx.ui.core.queue.Layout.add(this);
511
- }
512
- },
513
-
514
496
  // property apply
515
497
  _applyValue: qx.core.Environment.select("qx.dynlocale", {
516
498
  true(value, old) {
@@ -462,8 +462,14 @@ qx.Class.define("qx.ui.form.AbstractField", {
462
462
  // Apply
463
463
  var styles;
464
464
  if (value) {
465
- this.__font = qx.theme.manager.Font.getInstance().resolve(value);
466
- if (this.__font instanceof qx.bom.webfonts.WebFont) {
465
+ if (qx.lang.Type.isString(value)) {
466
+ value = qx.theme.manager.Font.getInstance().resolve(value);
467
+ }
468
+ this.__font = value;
469
+ if (
470
+ this.__font instanceof qx.bom.webfonts.WebFont &&
471
+ !this.__font.isValid()
472
+ ) {
467
473
  this.__webfontListenerId = this.__font.addListener(
468
474
  "changeStatus",
469
475
  this._onWebFontStatusChange,
@@ -139,6 +139,11 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
139
139
  this.__inputObject.setAttribute(attr, value);
140
140
  },
141
141
 
142
+ setEnabled(value){
143
+ this.__inputObject.setEnabled(value);
144
+ super.setEnabled(value);
145
+ },
146
+
142
147
  _createContentElement() {
143
148
  let id = "qxFileSelector_" + (++qx.ui.form.FileSelectorButton._fileInputElementIdCounter);
144
149
  let input = (this.__inputObject = new qx.html.Input(
@@ -124,8 +124,9 @@ qx.Class.define("qx.ui.table.pane.FocusIndicator", {
124
124
  wl = deco.getWidthLeft();
125
125
  }
126
126
  }
127
- var userHeight = rowHeight + (wl + wr - 2);
128
- var userTop = (row - firstRow) * rowHeight - (wr - 1);
127
+ var userHeight = rowHeight + (wt + wb - 2);
128
+ var renderedRowHeight = this.__scroller.getTablePane().getRenderedRowHeight();
129
+ var userTop = Math.floor((row - firstRow) * renderedRowHeight) - (wt - 1);
129
130
  if (
130
131
  editing &&
131
132
  this.__scroller.getMinCellEditHeight() &&
@@ -139,9 +140,9 @@ qx.Class.define("qx.ui.table.pane.FocusIndicator", {
139
140
  }
140
141
 
141
142
  this.setUserBounds(
142
- paneModel.getColumnLeft(col) - (wt - 1),
143
+ paneModel.getColumnLeft(col) - (wl - 1),
143
144
  userTop,
144
- columnModel.getColumnWidth(col) + (wt + wb - 3),
145
+ columnModel.getColumnWidth(col) + (wl + wr - 3),
145
146
  userHeight
146
147
  );
147
148
 
@@ -710,6 +710,20 @@ qx.Class.define("qx.ui.table.pane.Pane", {
710
710
  this.__lastColCount = colCount;
711
711
  this.__lastRowCount = rowCount;
712
712
  this.fireEvent("paneUpdated");
713
+ },
714
+
715
+ getRenderedRowHeight() {
716
+ var rowHeight = this.getTable().getRowHeight();
717
+
718
+ var elem = this.getContentElement().getDomElement();
719
+ if (elem && elem.firstChild) {
720
+ // pane has been rendered
721
+ var tableBody = elem.firstChild;
722
+ if (tableBody.childNodes && tableBody.childNodes.length > 0) {
723
+ rowHeight = tableBody.childNodes[0].getBoundingClientRect().height;
724
+ }
725
+ }
726
+ return rowHeight;
713
727
  }
714
728
  },
715
729
 
@@ -833,7 +833,7 @@ qx.Class.define("qx.ui.table.pane.Scroller", {
833
833
  }
834
834
  var scrollbar = this.__verScrollBar;
835
835
  this.__inOnScrollY = true;
836
- // calculate delta so that one row is scrolled at an minimum
836
+ // calculate delta so that one row is scrolled at a minimum
837
837
  var rowHeight = this.getTable().getRowHeight();
838
838
  var delta = e.getData() - e.getOldData();
839
839
  if (Math.abs(delta) > 1 && Math.abs(delta) < rowHeight) {
@@ -2037,12 +2037,12 @@ qx.Class.define("qx.ui.table.pane.Scroller", {
2037
2037
 
2038
2038
  if (pageY >= panePos.top && pageY <= panePos.bottom) {
2039
2039
  // This event is in the pane -> Get the row
2040
- var rowHeight = this.getTable().getRowHeight();
2040
+ var rowHeight = this.__tablePane.getRenderedRowHeight()
2041
2041
 
2042
2042
  var scrollY = this.__verScrollBar.getPosition();
2043
2043
 
2044
2044
  if (this.getTable().getKeepFirstVisibleRowComplete()) {
2045
- scrollY = Math.floor(scrollY / rowHeight) * rowHeight;
2045
+ scrollY = Math.floor(scrollY / this.getTable().getRowHeight()) * rowHeight;
2046
2046
  }
2047
2047
 
2048
2048
  var tableY = scrollY + pageY - panePos.top;
@@ -145,12 +145,18 @@ qx.Class.define("qx.ui.virtual.core.Scroller", {
145
145
 
146
146
  // overridden
147
147
  _onScrollBarX(e) {
148
- this.__pane.setScrollX(e.getData());
148
+ // Use Math.round to convert possible decimal values to
149
+ // integer values if a zoom level not equal to 100 is
150
+ // set in the browser
151
+ this.__pane.setScrollX(Math.round(e.getData()));
149
152
  },
150
153
 
151
154
  // overridden
152
155
  _onScrollBarY(e) {
153
- this.__pane.setScrollY(e.getData());
156
+ // Use Math.round to convert possible decimal values to
157
+ // integer values if a zoom level not equal to 100 is
158
+ // set in the browser
159
+ this.__pane.setScrollY(Math.round(e.getData()));
154
160
  }
155
161
  },
156
162
 
@@ -639,16 +639,17 @@ qx.Class.define("qx.ui.window.Window", {
639
639
  return;
640
640
  }
641
641
 
642
- if (
643
- this.fireNonBubblingEvent("beforeClose", qx.event.type.Event, [
644
- false,
645
- true
646
- ])
647
- ) {
648
- this.hide();
649
- this.fireEvent("close");
642
+ if (! this.fireNonBubblingEvent(
643
+ "beforeClose",
644
+ qx.event.type.Event,
645
+ [ false, true ])) {
646
+ // preventDefault() was called
647
+ return;
650
648
  }
651
649
 
650
+ this.hide();
651
+ this.fireEvent("close");
652
+
652
653
  // If automatically destroying the window upon close was requested, do
653
654
  // so now. (Note that we explicitly re-obtain the autoDestroy property
654
655
  // value, allowing the user's close handler to enable/disable it before