@qooxdoo/framework 7.2.1 → 7.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/Manifest.json +1 -1
  2. package/lib/compiler/compile-info.json +55 -55
  3. package/lib/compiler/index.js +718 -474
  4. package/lib/resource/qx/tool/schema/compile-1-0-0.json +4 -0
  5. package/npm-shrinkwrap.json +23 -23
  6. package/package.json +3 -2
  7. package/source/class/qx/bom/webfonts/Manager.js +16 -8
  8. package/source/class/qx/core/MEvent.js +91 -22
  9. package/source/class/qx/core/MObjectId.js +8 -0
  10. package/source/class/qx/core/MProperty.js +45 -5
  11. package/source/class/qx/core/Object.js +5 -1
  12. package/source/class/qx/data/MBinding.js +6 -4
  13. package/source/class/qx/data/controller/CheckedList.js +2 -2
  14. package/source/class/qx/test/Interface.js +12 -10
  15. package/source/class/qx/test/core/Property.js +104 -0
  16. package/source/class/qx/theme/simple/Appearance.js +35 -0
  17. package/source/class/qx/theme/simple/Decoration.js +16 -0
  18. package/source/class/qx/theme/tangible/Appearance.js +9 -9
  19. package/source/class/qx/tool/cli/Cli.js +4 -0
  20. package/source/class/qx/tool/cli/Watch.js +3 -0
  21. package/source/class/qx/tool/cli/commands/Compile.js +5 -3
  22. package/source/class/qx/tool/cli/commands/Es6ify.js +51 -0
  23. package/source/class/qx/tool/compiler/Analyser.js +62 -13
  24. package/source/class/qx/tool/compiler/ClassFile.js +30 -48
  25. package/source/class/qx/tool/compiler/Console.js +2 -0
  26. package/source/class/qx/tool/compiler/Es6ify.js +1 -0
  27. package/source/class/qx/tool/compiler/targets/Target.js +7 -3
  28. package/source/class/qx/tool/compiler/targets/meta/Browserify.js +21 -14
  29. package/source/class/qx/tool/compiler/targets/meta/Uglify.js +2 -0
  30. package/source/class/qx/tool/config/Abstract.js +4 -0
  31. package/source/class/qx/ui/basic/Image.js +1 -1
  32. package/source/class/qx/ui/basic/Label.js +2 -3
  33. package/source/class/qx/ui/container/Composite.js +0 -11
  34. package/source/class/qx/ui/control/DateChooser.js +39 -0
  35. package/source/class/qx/ui/core/MChildrenHandling.js +4 -0
  36. package/source/class/qx/ui/core/MLayoutHandling.js +4 -0
  37. package/source/class/qx/ui/core/MRemoteLayoutHandling.js +11 -2
  38. package/source/class/qx/ui/form/FileSelectorButton.js +30 -18
  39. package/source/class/qx/ui/form/MForm.js +3 -2
  40. package/source/class/qx/ui/form/Slider.js +13 -13
  41. package/source/class/qx/ui/form/validation/Manager.js +29 -4
  42. package/source/class/qx/ui/layout/Canvas.js +4 -1
  43. package/source/class/qx/ui/tabview/Page.js +9 -0
  44. package/source/class/qx/ui/tabview/ScrollingPage.js +54 -0
  45. package/source/class/qx/ui/toolbar/FileSelectorButton.js +6 -4
  46. package/source/class/qx/ui/toolbar/ToolBar.js +6 -2
  47. package/source/resource/qx/tool/schema/compile-1-0-0.json +4 -0
  48. package/source/translation/ru.po +2 -2
@@ -55,9 +55,9 @@ qx.Class.define("qx.tool.compiler.targets.meta.Browserify", {
55
55
  this.__appMeta.getEnvironmentValue("qx.compiler.applicationType") ==
56
56
  "browser"
57
57
  ) {
58
- // Get a Set of unique `require`d CommonJS module names from
59
- // all classes
60
- for (let className in db.classInfo) {
58
+ // Get a Set of unique `require`d CommonJS module names from classes needed by the application
59
+ let classnames = this.__appMeta.getApplication().getDependencies();
60
+ for (let className of classnames) {
61
61
  let classInfo = db.classInfo[className];
62
62
  if (classInfo.commonjsModules) {
63
63
  Object.keys(classInfo.commonjsModules).forEach(moduleName => {
@@ -121,16 +121,18 @@ qx.Class.define("qx.tool.compiler.targets.meta.Browserify", {
121
121
  let message = [];
122
122
 
123
123
  message.push(`ERROR: could not locate require()d module: "${id}"`);
124
- message.push(" required from:");
125
-
126
- try {
127
- [...references[id]].forEach(refs => {
128
- refs.forEach(ref => {
129
- message.push(` ${ref}`);
124
+ if (references[id]) {
125
+ message.push(" required from:");
126
+
127
+ try {
128
+ [...references[id]].forEach(refs => {
129
+ refs.forEach(ref => {
130
+ message.push(` ${ref}`);
131
+ });
130
132
  });
131
- });
132
- } catch (e) {
133
- message.push(` <compile.json:application.localModules'>`);
133
+ } catch (e) {
134
+ message.push(` <compile.json:application.localModules'>`);
135
+ }
134
136
  }
135
137
 
136
138
  qx.tool.compiler.Console.error(message.join("\n"));
@@ -159,8 +161,13 @@ qx.Class.define("qx.tool.compiler.targets.meta.Browserify", {
159
161
  b.bundle((e, output) => {
160
162
  if (e) {
161
163
  // We've already handled the case of missing module. This is something else.
162
- qx.tool.compiler.Console.error(`Failed: ${e}`);
163
- throw e;
164
+ qx.tool.compiler.Console.error(
165
+ `Unable to browserify - this is probably because a module is being require()'d which is not compatible with Browserify: ${e.message}`
166
+ );
167
+
168
+ // Do not throw an error here, otherwise a problem in the users code will kill the watch with pages of error
169
+ resolve(null);
170
+ return;
164
171
  }
165
172
 
166
173
  ws.write(output);
@@ -127,10 +127,12 @@ qx.Class.define("qx.tool.compiler.targets.meta.Uglify", {
127
127
  await fs.writeFileAsync(outJsFilename + ".map", result.map, {
128
128
  encoding: "utf8"
129
129
  });
130
+
130
131
  if (this._appMeta.getTarget().isSaveUnminified()) {
131
132
  await fs.writeFileAsync(outJsFilename + ".unminified", inSourceCode, {
132
133
  encoding: "utf8"
133
134
  });
135
+
134
136
  await fs.writeFileAsync(
135
137
  outJsFilename + ".unminified.map",
136
138
  JSON.stringify(inSourceMap, null, 2),
@@ -299,6 +299,10 @@ qx.Class.define("qx.tool.config.Abstract", {
299
299
  );
300
300
  }
301
301
  }
302
+ if (data.$schema === undefined) {
303
+ // don't validate if there is no schema
304
+ this.setValidate(false);
305
+ }
302
306
  // load schema if validation is enabled
303
307
  if (this.isValidate() && this.getVersion() !== null) {
304
308
  // check initial data
@@ -785,7 +785,7 @@ qx.Class.define("qx.ui.basic.Image", {
785
785
  if (this.getScale()) {
786
786
  el.setStyle("fontSize", (width > height ? height : width) + "px");
787
787
  } else {
788
- var source = this.getSource();
788
+ var source = qx.util.AliasManager.getInstance().resolve(this.getSource());
789
789
  var sparts = source.split("/");
790
790
  var font = this.__getFont(source);
791
791
  var size = parseInt(sparts[2] || font.getSize());
@@ -368,6 +368,7 @@ qx.Class.define("qx.ui.basic.Label", {
368
368
  this.__fixEllipsis();
369
369
  }
370
370
  if (rich && this.getBreakWithinWords()) {
371
+ styles = qx.lang.Object.clone(styles);
371
372
  styles.wordBreak = "break-all";
372
373
  }
373
374
 
@@ -461,12 +462,10 @@ qx.Class.define("qx.ui.basic.Label", {
461
462
 
462
463
  // property apply
463
464
  _applyBreakWithinWords(value, old) {
464
- if (this.isRich()) {
465
465
  this.getContentElement().setStyle(
466
466
  "wordBreak",
467
- value ? "break-all" : "normal"
467
+ this.isRich() && value ? "break-all" : "normal"
468
468
  );
469
- }
470
469
  },
471
470
 
472
471
  /**
@@ -112,16 +112,5 @@ qx.Class.define("qx.ui.container.Composite", {
112
112
  child
113
113
  ]);
114
114
  }
115
- },
116
-
117
- /*
118
- *****************************************************************************
119
- DEFER
120
- *****************************************************************************
121
- */
122
-
123
- defer(statics, members) {
124
- qx.ui.core.MChildrenHandling.remap(members);
125
- qx.ui.core.MLayoutHandling.remap(members);
126
115
  }
127
116
  });
@@ -204,6 +204,28 @@ qx.Class.define("qx.ui.control.DateChooser", {
204
204
  nullable: true,
205
205
  event: "changeValue",
206
206
  apply: "_applyValue"
207
+ },
208
+
209
+ /**
210
+ * The minimal date value of the widget. Dates which are less
211
+ * than this property value will be shown as disabled (not clickable).
212
+ */
213
+ minValue: {
214
+ check: "Date",
215
+ init: null,
216
+ nullable: true,
217
+ apply: "_applyMinValue"
218
+ },
219
+
220
+ /**
221
+ * The maximal date value of the widget. Dates which are greater
222
+ * than this property value will be shown as disabled (not clickable).
223
+ */
224
+ maxValue: {
225
+ check: "Date",
226
+ init: null,
227
+ nullable: true,
228
+ apply: "_applyMaxValue"
207
229
  }
208
230
  },
209
231
 
@@ -415,6 +437,14 @@ qx.Class.define("qx.ui.control.DateChooser", {
415
437
  }
416
438
  },
417
439
 
440
+ _applyMinValue(){
441
+ this._updateDatePane();
442
+ },
443
+
444
+ _applyMaxValue(){
445
+ this._updateDatePane();
446
+ },
447
+
418
448
  /*
419
449
  ---------------------------------------------------------------------------
420
450
  EVENT HANDLER
@@ -724,6 +754,7 @@ qx.Class.define("qx.ui.control.DateChooser", {
724
754
 
725
755
  dayLabel.setValue("" + dayOfMonth);
726
756
  dayLabel.dateTime = helpDate.getTime();
757
+ dayLabel.setEnabled(!this.__exceedsLimits(helpDate));
727
758
 
728
759
  // Go to the next day
729
760
  helpDate.setDate(helpDate.getDate() + 1);
@@ -733,6 +764,14 @@ qx.Class.define("qx.ui.control.DateChooser", {
733
764
  monthYearFormat.dispose();
734
765
  weekDayFormat.dispose();
735
766
  weekFormat.dispose();
767
+ },
768
+
769
+ __exceedsLimits(date){
770
+ const d = new Date(date);
771
+ d.setHours(0,0,0,0);
772
+ var exceedsMin = this.getMinValue() !== null && d < this.getMinValue();
773
+ var exceedsMax = this.getMaxValue() !== null && d > this.getMaxValue();
774
+ return exceedsMin || exceedsMax;
736
775
  }
737
776
  },
738
777
 
@@ -178,8 +178,12 @@ qx.Mixin.define("qx.ui.core.MChildrenHandling", {
178
178
  * this methods in the defer block of the including class.
179
179
  *
180
180
  * @param members {Map} The including classes members map
181
+ * @deprecated {7.0} this is not necessary in modern compilers and leads to unexpected behaviour
181
182
  */
182
183
  remap(members) {
184
+ if (qx.core.Environment.get("qx.debug")) {
185
+ qx.log.Logger.debug("Calling qx.ui.core.MChildrenHandling.remap is deprecated, please dont use it");
186
+ }
183
187
  members.getChildren = members._getChildren;
184
188
  members.hasChildren = members._hasChildren;
185
189
  members.indexOf = members._indexOf;
@@ -68,8 +68,12 @@ qx.Mixin.define("qx.ui.core.MLayoutHandling", {
68
68
  * this methods in the defer block of the including class.
69
69
  *
70
70
  * @param members {Map} The including classes members map
71
+ * @deprecated {7.0} this is not necessary in modern compilers and leads to unexpected behaviour
71
72
  */
72
73
  remap(members) {
74
+ if (qx.core.Environment.get("qx.debug")) {
75
+ qx.log.Logger.debug("Calling qx.ui.core.MLayoutHandling.remap is deprecated, please dont use it");
76
+ }
73
77
  members.getLayout = members._getLayout;
74
78
  members.setLayout = members._setLayout;
75
79
  }
@@ -43,7 +43,12 @@ qx.Mixin.define("qx.ui.core.MRemoteLayoutHandling", {
43
43
  * <code>null</code> to reset the layout.
44
44
  */
45
45
  setLayout(layout) {
46
- this.getChildrenContainer().setLayout(layout);
46
+ var container = this.getChildrenContainer();
47
+ if (container === this) {
48
+ container._setLayout(layout);
49
+ } else {
50
+ container.setLayout(layout);
51
+ }
47
52
  },
48
53
 
49
54
  /**
@@ -52,7 +57,11 @@ qx.Mixin.define("qx.ui.core.MRemoteLayoutHandling", {
52
57
  * @return {qx.ui.layout.Abstract} The widget's layout manager
53
58
  */
54
59
  getLayout() {
55
- return this.getChildrenContainer().getLayout();
60
+ var container = this.getChildrenContainer();
61
+ if (container === this) {
62
+ return container._getLayout();
63
+ }
64
+ return container.getLayout();
56
65
  }
57
66
  }
58
67
  });
@@ -21,11 +21,11 @@
21
21
  * files from the local filesystem. A FileList is returned which allows access
22
22
  * to the content of the selected files from javascript. The file(s) can now be
23
23
  * processed in javascript, or it/they can be uploaded to a server.
24
- *
24
+ *
25
25
  * *Example*
26
26
  *
27
27
  * Post the content of the file to the server.
28
- *
28
+ *
29
29
  * ```javascript
30
30
  * let button = new qx.ui.form.FileSelectorButton("Select File");
31
31
  * button.addListener('changeFileSelection',function(e){
@@ -40,9 +40,9 @@
40
40
  * });
41
41
  * });
42
42
  * ```
43
- *
43
+ *
44
44
  * Process the file directly in javascript using the FileReader API.
45
- *
45
+ *
46
46
  * ```javascript
47
47
  * let button = new qx.ui.form.FileSelectorButton("Select File");
48
48
  * button.addListener('changeFileSelection',function(e){
@@ -55,14 +55,18 @@
55
55
  * const file = fileList[0];
56
56
  * reader.readAsText(file.slice(0,4));
57
57
  * });
58
-
59
- *
58
+ * ```
59
+ *
60
60
  * [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/File_API/Using_files_from_web_applications)
61
61
  */
62
62
 
63
- let InputElementIdCounter = 0;
64
63
  qx.Class.define("qx.ui.form.FileSelectorButton", {
65
64
  extend: qx.ui.form.Button,
65
+
66
+ statics: {
67
+ _fileInputElementIdCounter: 0
68
+ },
69
+
66
70
  events: {
67
71
  /**
68
72
  * The event is fired when the file selection changes.
@@ -72,6 +76,7 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
72
76
  */
73
77
  changeFileSelection: "qx.event.type.Data"
74
78
  },
79
+
75
80
  properties: {
76
81
  /**
77
82
  * What type of files should be offered in the fileselection dialog.
@@ -87,6 +92,7 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
87
92
  check: "String",
88
93
  apply: "_applyAttribute"
89
94
  },
95
+
90
96
  /**
91
97
  * Specify that the camera should be used for getting the "file". The
92
98
  * value defines which camera should be used for capturing images.
@@ -98,6 +104,7 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
98
104
  check: ["user", "environment"],
99
105
  apply: "_applyAttribute"
100
106
  },
107
+
101
108
  /**
102
109
  * Set to "true" if you want to allow the selection of multiple files.
103
110
  */
@@ -106,6 +113,7 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
106
113
  check: "Boolean",
107
114
  apply: "_applyAttribute"
108
115
  },
116
+
109
117
  /**
110
118
  * If present, indicates that only directories should be available for
111
119
  * selection.
@@ -116,13 +124,14 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
116
124
  apply: "_applyAttribute"
117
125
  }
118
126
  },
127
+
119
128
  members: {
120
129
  __inputObject: null,
121
130
 
122
- _applyAttribute: function (value, old, attr) {
131
+ _applyAttribute(value, old, attr) {
123
132
  if (attr === "directoriesOnly") {
124
133
  // while the name of the attribute indicates that this only
125
- // works for webkit borwsers, this is not the case. These
134
+ // works for webkit browsers, this is not the case. These
126
135
  // days the attribute is supported by
127
136
  // [everyone](https://caniuse.com/?search=webkitdirectory).
128
137
  attr = "webkitdirectory";
@@ -130,22 +139,25 @@ qx.Class.define("qx.ui.form.FileSelectorButton", {
130
139
  this.__inputObject.setAttribute(attr, value);
131
140
  },
132
141
 
133
- _createContentElement: function () {
134
- let id = "qxFileSelector_" + InputElementIdCounter++;
142
+ _createContentElement() {
143
+ let id = "qxFileSelector_" + (++qx.ui.form.FileSelectorButton._fileInputElementIdCounter);
135
144
  let input = (this.__inputObject = new qx.html.Input(
136
145
  "file",
137
- { display: "none" },
146
+ null,
138
147
  { id: id }
139
148
  ));
149
+
140
150
  let label = new qx.html.Element("label", {}, { for: id });
141
- label.addListenerOnce(
142
- "appear",
143
- e => {
144
- label.add(input);
145
- }
146
- );
151
+ label.addListenerOnce("appear", e => {
152
+ label.add(input);
153
+ });
154
+
147
155
  input.addListenerOnce("appear", e => {
148
156
  let inputEl = input.getDomElement();
157
+ // since qx.html.Node does not even create the
158
+ // domNode if it is not set to visible initially
159
+ // we have to quickly hide it after creation.
160
+ input.setVisible(false);
149
161
  inputEl.addEventListener("change", e => {
150
162
  this.fireDataEvent("changeFileSelection", inputEl.files);
151
163
  inputEl.value = "";
@@ -55,8 +55,9 @@ qx.Mixin.define("qx.ui.form.MForm", {
55
55
  * Message which is shown in an invalid tooltip.
56
56
  */
57
57
  invalidMessage: {
58
+ init: null,
59
+ nullable: true,
58
60
  check: "String",
59
- init: "",
60
61
  event: "changeInvalidMessage"
61
62
  },
62
63
 
@@ -67,7 +68,7 @@ qx.Mixin.define("qx.ui.form.MForm", {
67
68
  requiredInvalidMessage: {
68
69
  check: "String",
69
70
  nullable: true,
70
- event: "changeInvalidMessage"
71
+ event: "changeRequiredInvalidMessage"
71
72
  }
72
73
  },
73
74
 
@@ -80,17 +80,17 @@ qx.Class.define("qx.ui.form.Slider", {
80
80
  this.getContentElement().setAttribute("role", "slider");
81
81
 
82
82
  // Add listeners
83
- this.addListener("keypress", this._onKeyPress);
84
- this.addListener("roll", this._onRoll);
85
- this.addListener("pointerdown", this._onPointerDown);
86
- this.addListener("pointerup", this._onPointerUp);
87
- this.addListener("losecapture", this._onPointerUp);
88
- this.addListener("resize", this._onUpdate);
83
+ this.addListener("keypress", this._onKeyPress, this);
84
+ this.addListener("roll", this._onRoll, this);
85
+ this.addListener("pointerdown", this._onPointerDown, this);
86
+ this.addListener("pointerup", this._onPointerUp, this);
87
+ this.addListener("losecapture", this._onPointerUp, this);
88
+ this.addListener("resize", this._onUpdate, this);
89
89
 
90
90
  // Stop events
91
- this.addListener("contextmenu", this._onStopEvent);
92
- this.addListener("tap", this._onStopEvent);
93
- this.addListener("dbltap", this._onStopEvent);
91
+ this.addListener("contextmenu", this._onStopEvent, this);
92
+ this.addListener("tap", this._onStopEvent, this);
93
+ this.addListener("dbltap", this._onStopEvent, this);
94
94
 
95
95
  // Initialize orientation
96
96
  if (orientation != null) {
@@ -256,8 +256,8 @@ qx.Class.define("qx.ui.form.Slider", {
256
256
  control = new qx.ui.core.Widget();
257
257
 
258
258
  control.addListener("resize", this._onUpdate, this);
259
- control.addListener("pointerover", this._onPointerOver);
260
- control.addListener("pointerout", this._onPointerOut);
259
+ control.addListener("pointerover", this._onPointerOver, this);
260
+ control.addListener("pointerout", this._onPointerOut, this);
261
261
  this._add(control);
262
262
  break;
263
263
  }
@@ -437,7 +437,7 @@ qx.Class.define("qx.ui.form.Slider", {
437
437
  }
438
438
 
439
439
  // Register move listener
440
- this.addListener("pointermove", this._onPointerMove);
440
+ this.addListener("pointermove", this._onPointerMove, this);
441
441
 
442
442
  // Activate capturing
443
443
  this.capture();
@@ -524,7 +524,7 @@ qx.Class.define("qx.ui.form.Slider", {
524
524
  }
525
525
 
526
526
  // Remove move listener again
527
- this.removeListener("pointermove", this._onPointerMove);
527
+ this.removeListener("pointermove", this._onPointerMove, this);
528
528
 
529
529
  // Stop event
530
530
  if (e.getType() === "pointerup") {
@@ -482,7 +482,13 @@ qx.Class.define("qx.ui.form.validation.Manager", {
482
482
  continue;
483
483
  }
484
484
 
485
- tooltip.setLabel(item.getInvalidMessage());
485
+ let msg = item.getInvalidMessage();
486
+ if (!msg && qx.core.Environment.get("qx.ui.form.validation.Manager.allowDefaultInvalidMessage")) {
487
+ msg = "Invalid field";
488
+ } else if (qx.core.Environment.get("qx.debug")) {
489
+ this.assertTrue(msg != null && msg.length > 0);
490
+ }
491
+ tooltip.setLabel(msg);
486
492
 
487
493
  if (tooltip.getPlaceMethod() == "mouse") {
488
494
  var location = item.getContentLocation();
@@ -531,12 +537,25 @@ qx.Class.define("qx.ui.form.validation.Manager", {
531
537
  for (var i = 0; i < this.__formItems.length; i++) {
532
538
  var formItem = this.__formItems[i].item;
533
539
  if (!formItem.getValid()) {
534
- messages.push(formItem.getInvalidMessage());
540
+ let msg = formItem.getInvalidMessage();
541
+ if (!msg && qx.core.Environment.get("qx.ui.form.validation.Manager.allowDefaultInvalidMessage")) {
542
+ msg = "Invalid field";
543
+ } else if (qx.core.Environment.get("qx.debug")) {
544
+ this.assertTrue(msg !== null && msg.length > 0);
545
+ }
546
+ messages.push(msg);
535
547
  }
536
548
  }
549
+
537
550
  // add the forms fail message
538
- if (this.getInvalidMessage() != "") {
539
- messages.push(this.getInvalidMessage());
551
+ if (!this.isValid()) {
552
+ let msg = this.getInvalidMessage();
553
+ if (!msg && qx.core.Environment.get("qx.ui.form.validation.Manager.allowDefaultInvalidMessage")) {
554
+ msg = "Invalid field";
555
+ } else if (qx.core.Environment.get("qx.debug")) {
556
+ this.assertTrue(msg !== null && msg.length > 0);
557
+ }
558
+ messages.push(msg);
540
559
  }
541
560
 
542
561
  return messages;
@@ -643,5 +662,11 @@ qx.Class.define("qx.ui.form.validation.Manager", {
643
662
  destruct() {
644
663
  this._showToolTip(true);
645
664
  this.__formItems = null;
665
+ },
666
+
667
+ environment: {
668
+ // Whether to assume a default "Invalid Field" message for invalid fields; if false, an
669
+ // exception will be raised if invalid fields do not have an `invalidMessage`
670
+ "qx.ui.form.validation.Manager.allowDefaultInvalidMessage": true
646
671
  }
647
672
  });
@@ -286,7 +286,10 @@ qx.Class.define("qx.ui.layout.Canvas", {
286
286
  if (top == null && bottom == null) {
287
287
  switch (child.getAlignY()) {
288
288
  case "middle":
289
- top = Math.round((availHeight - size.height) / 2 - marginBottom);
289
+ top = Math.round(
290
+ (availHeight - size.height) / 2 - marginBottom
291
+ );
292
+
290
293
  break;
291
294
  case "bottom":
292
295
  bottom = 0;
@@ -256,6 +256,15 @@ qx.Class.define("qx.ui.tabview.Page", {
256
256
  ---------------------------------------------------------------------------
257
257
  */
258
258
 
259
+ /**
260
+ * By default, widgets are added to `this`
261
+ *
262
+ * @return {qx.ui.core.Widget} the widget to add to
263
+ */
264
+ getChildrenContainer() {
265
+ return this;
266
+ },
267
+
259
268
  /**
260
269
  * Returns the button used within this page. This method is used by
261
270
  * the TabView to access the button.
@@ -0,0 +1,54 @@
1
+ /* ************************************************************************
2
+
3
+ qooxdoo - the new era of web development
4
+
5
+ http://qooxdoo.org
6
+
7
+ Copyright:
8
+ 2022 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
+ /**
20
+ * A scrolling page uses a `qx.ui.container.Scroll` to make sure that the contents
21
+ * never cause the parent TabView to size outside of it's natural boundaries; a
22
+ * side effect of this is that if you use all `ScrollingPage` and do not use `Page`
23
+ * instances, then the tabview will be very small unless you use a layout which will
24
+ * expand the TabView.
25
+ */
26
+ qx.Class.define("qx.ui.tabview.ScrollingPage", {
27
+ extend: qx.ui.tabview.Page,
28
+
29
+ /**
30
+ * @param label {String} Initial label of the tab
31
+ * @param icon {String} Initial icon of the tab
32
+ */
33
+ construct(label, icon) {
34
+ super(label, icon);
35
+ this._setLayout(new qx.ui.layout.Grow());
36
+ this.__childContainer = new qx.ui.container.Composite();
37
+ let scroll = new qx.ui.container.Scroll(this.__childContainer);
38
+ this._add(scroll);
39
+ },
40
+
41
+ members: {
42
+ /** @type{qx.ui.core.Widget} the container that the user's children are added to */
43
+ __childContainer: null,
44
+
45
+ /**
46
+ * Make sure that children are added to the scrolling container
47
+ *
48
+ * @return {qx.ui.core.Widget} the widget to add to
49
+ */
50
+ getChildrenContainer() {
51
+ return this.__childContainer;
52
+ }
53
+ }
54
+ });
@@ -22,8 +22,8 @@
22
22
 
23
23
  qx.Class.define("qx.ui.toolbar.FileSelectorButton", {
24
24
  extend: qx.ui.form.FileSelectorButton,
25
- construct: function (label, icon, command) {
26
- this.base(arguments, label, icon, command);
25
+ construct(label, icon, command) {
26
+ super(label, icon, command);
27
27
  // Toolbar buttons should not support the keyboard events
28
28
  this.removeListener("keydown", this._onKeyDown);
29
29
  this.removeListener("keyup", this._onKeyUp);
@@ -33,10 +33,12 @@ qx.Class.define("qx.ui.toolbar.FileSelectorButton", {
33
33
  refine: true,
34
34
  init: "toolbar-button"
35
35
  },
36
+
36
37
  show: {
37
38
  refine: true,
38
39
  init: "inherit"
39
40
  },
41
+
40
42
  focusable: {
41
43
  refine: true,
42
44
  init: false
@@ -45,8 +47,8 @@ qx.Class.define("qx.ui.toolbar.FileSelectorButton", {
45
47
 
46
48
  members: {
47
49
  // overridden
48
- _applyVisibility: function (value, old) {
49
- this.base(arguments, value, old);
50
+ _applyVisibility(value, old) {
51
+ super._applyVisibility(value, old);
50
52
  // trigger a appearance recalculation of the parent
51
53
  let parent = this.getLayoutParent();
52
54
  if (parent && parent instanceof qx.ui.toolbar.PartContainer) {
@@ -41,14 +41,18 @@ qx.Class.define("qx.ui.toolbar.ToolBar", {
41
41
  *****************************************************************************
42
42
  */
43
43
 
44
- construct() {
44
+ /**
45
+ * Constructor
46
+ * @param {qx.ui.layout.Abstract?} layout optional layout, defaults to qx.ui.layout.HBox
47
+ */
48
+ construct(layout) {
45
49
  super();
46
50
 
47
51
  // ARIA attrs
48
52
  this.getContentElement().setAttribute("role", "toolbar");
49
53
 
50
54
  // add needed layout
51
- this._setLayout(new qx.ui.layout.HBox());
55
+ this._setLayout(layout || new qx.ui.layout.HBox());
52
56
 
53
57
  // initialize the overflow handling
54
58
  this.__removedItems = [];
@@ -224,6 +224,10 @@
224
224
  "description": "The folder where the deploy outputs to.",
225
225
  "type": "string"
226
226
  },
227
+ "proxySourcePath": {
228
+ "description": "The folder containing proxy classes (normally machine generated) to take precedence over those found in normal library sources",
229
+ "type": "string"
230
+ },
227
231
  "targetClass": {
228
232
  "description": "If you want to use more than the two default target types and/or use custom target classes, you can use the targetClass key to supply the name of the class as a string.",
229
233
  "type": "string"