zuzu-js 0.1.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/LICENSE +5 -0
- package/README.md +113 -0
- package/bin/zuzu +17 -0
- package/bin/zuzu-build-browser-bundle +57 -0
- package/bin/zuzu-generate-browser-stdlib +584 -0
- package/bin/zuzu-js +23 -0
- package/bin/zuzu-js-compile +152 -0
- package/bin/zuzu-js-electron +19 -0
- package/dist/zuzu-browser-worker.js +45574 -0
- package/dist/zuzu-browser.js +45362 -0
- package/lib/browser-bundle-entry.js +160 -0
- package/lib/browser-gui-renderer.js +387 -0
- package/lib/browser-runtime.js +167 -0
- package/lib/browser-worker-entry.js +413 -0
- package/lib/browser-ztests/runner.html +103 -0
- package/lib/browser-ztests/runner.js +369 -0
- package/lib/cli.js +350 -0
- package/lib/collections.js +367 -0
- package/lib/compiler.js +303 -0
- package/lib/electron/launcher.js +70 -0
- package/lib/electron/main.js +956 -0
- package/lib/electron/preload.js +80 -0
- package/lib/electron/renderer.html +122 -0
- package/lib/electron/renderer.js +24 -0
- package/lib/execution-metadata.js +18 -0
- package/lib/gui/dom-renderer.js +778 -0
- package/lib/host/browser-host.js +278 -0
- package/lib/host/capabilities.js +47 -0
- package/lib/host/electron-host.js +15 -0
- package/lib/host/node-host.js +74 -0
- package/lib/paths.js +150 -0
- package/lib/runtime-entrypoints.js +60 -0
- package/lib/runtime-helpers.js +886 -0
- package/lib/runtime.js +3529 -0
- package/lib/tap.js +37 -0
- package/lib/transpiler-new/ast.js +23 -0
- package/lib/transpiler-new/codegen.js +2455 -0
- package/lib/transpiler-new/errors.js +28 -0
- package/lib/transpiler-new/index.js +26 -0
- package/lib/transpiler-new/lexer.js +834 -0
- package/lib/transpiler-new/parser.js +2332 -0
- package/lib/transpiler-new/validate-bindings.js +326 -0
- package/lib/transpiler-utils.js +95 -0
- package/lib/transpiler.js +33 -0
- package/lib/zuzu.js +53 -0
- package/modules/javascript.js +193 -0
- package/modules/std/archive.js +603 -0
- package/modules/std/clib.js +338 -0
- package/modules/std/data/csv.js +1331 -0
- package/modules/std/data/json.js +531 -0
- package/modules/std/data/xml.js +441 -0
- package/modules/std/data/yaml.js +256 -0
- package/modules/std/db-worker.js +250 -0
- package/modules/std/db.js +664 -0
- package/modules/std/digest/_hash.js +443 -0
- package/modules/std/digest/md5.js +26 -0
- package/modules/std/digest/sha.js +72 -0
- package/modules/std/eval.js +10 -0
- package/modules/std/gui/objects.js +1519 -0
- package/modules/std/internals.js +571 -0
- package/modules/std/io/socks-worker.js +318 -0
- package/modules/std/io/socks.js +186 -0
- package/modules/std/io.js +475 -0
- package/modules/std/marshal/cbor.js +463 -0
- package/modules/std/marshal/graph.js +1624 -0
- package/modules/std/marshal.js +87 -0
- package/modules/std/math/bignum.js +91 -0
- package/modules/std/math.js +79 -0
- package/modules/std/net/dns.js +306 -0
- package/modules/std/net/http.js +820 -0
- package/modules/std/net/smtp.js +943 -0
- package/modules/std/net/url.js +109 -0
- package/modules/std/proc.js +602 -0
- package/modules/std/secure.js +3724 -0
- package/modules/std/string/base64.js +138 -0
- package/modules/std/string.js +299 -0
- package/modules/std/task.js +914 -0
- package/modules/std/time.js +579 -0
- package/modules/std/tui.js +188 -0
- package/modules/std/worker-thread.js +246 -0
- package/modules/std/worker.js +790 -0
- package/package.json +67 -0
- package/stdlib/modules/javascript.zzm +99 -0
- package/stdlib/modules/perl.zzm +105 -0
- package/stdlib/modules/std/archive.zzm +132 -0
- package/stdlib/modules/std/cache/lru.zzm +174 -0
- package/stdlib/modules/std/clib.zzm +112 -0
- package/stdlib/modules/std/colour.zzm +220 -0
- package/stdlib/modules/std/config.zzm +818 -0
- package/stdlib/modules/std/data/cbor.zzm +497 -0
- package/stdlib/modules/std/data/csv.zzm +285 -0
- package/stdlib/modules/std/data/ini.zzm +472 -0
- package/stdlib/modules/std/data/json/schema/core.zzm +573 -0
- package/stdlib/modules/std/data/json/schema/format.zzm +581 -0
- package/stdlib/modules/std/data/json/schema/model.zzm +255 -0
- package/stdlib/modules/std/data/json/schema/output.zzm +272 -0
- package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +299 -0
- package/stdlib/modules/std/data/json/schema/validation.zzm +1503 -0
- package/stdlib/modules/std/data/json/schema.zzm +306 -0
- package/stdlib/modules/std/data/json.zzm +102 -0
- package/stdlib/modules/std/data/kdl/json.zzm +460 -0
- package/stdlib/modules/std/data/kdl/xml.zzm +387 -0
- package/stdlib/modules/std/data/kdl.zzm +1631 -0
- package/stdlib/modules/std/data/toml.zzm +756 -0
- package/stdlib/modules/std/data/toon.zzm +1017 -0
- package/stdlib/modules/std/data/xml/escape.zzm +156 -0
- package/stdlib/modules/std/data/xml.zzm +276 -0
- package/stdlib/modules/std/data/yaml.zzm +94 -0
- package/stdlib/modules/std/db.zzm +173 -0
- package/stdlib/modules/std/defer.zzm +75 -0
- package/stdlib/modules/std/digest/crc32.zzm +196 -0
- package/stdlib/modules/std/digest/md5.zzm +54 -0
- package/stdlib/modules/std/digest/sha.zzm +83 -0
- package/stdlib/modules/std/dump.zzm +317 -0
- package/stdlib/modules/std/eval.zzm +63 -0
- package/stdlib/modules/std/getopt.zzm +432 -0
- package/stdlib/modules/std/gui/dialogue.zzm +592 -0
- package/stdlib/modules/std/gui/objects.zzm +123 -0
- package/stdlib/modules/std/gui.zzm +1914 -0
- package/stdlib/modules/std/internals.zzm +139 -0
- package/stdlib/modules/std/io/socks.zzm +139 -0
- package/stdlib/modules/std/io.zzm +157 -0
- package/stdlib/modules/std/lingua/en.zzm +347 -0
- package/stdlib/modules/std/log.zzm +169 -0
- package/stdlib/modules/std/mail.zzm +2726 -0
- package/stdlib/modules/std/marshal.zzm +138 -0
- package/stdlib/modules/std/math/bignum.zzm +98 -0
- package/stdlib/modules/std/math/range.zzm +116 -0
- package/stdlib/modules/std/math/roman.zzm +156 -0
- package/stdlib/modules/std/math.zzm +141 -0
- package/stdlib/modules/std/net/dns.zzm +93 -0
- package/stdlib/modules/std/net/http.zzm +278 -0
- package/stdlib/modules/std/net/smtp.zzm +257 -0
- package/stdlib/modules/std/net/url.zzm +69 -0
- package/stdlib/modules/std/path/jsonpointer.zzm +526 -0
- package/stdlib/modules/std/path/kdl.zzm +1003 -0
- package/stdlib/modules/std/path/simple.zzm +520 -0
- package/stdlib/modules/std/path/z/context.zzm +147 -0
- package/stdlib/modules/std/path/z/evaluate.zzm +549 -0
- package/stdlib/modules/std/path/z/functions.zzm +874 -0
- package/stdlib/modules/std/path/z/lexer.zzm +490 -0
- package/stdlib/modules/std/path/z/node.zzm +1455 -0
- package/stdlib/modules/std/path/z/operators.zzm +445 -0
- package/stdlib/modules/std/path/z/parser.zzm +359 -0
- package/stdlib/modules/std/path/z.zzm +403 -0
- package/stdlib/modules/std/path/zz/functions.zzm +828 -0
- package/stdlib/modules/std/path/zz/operators.zzm +1036 -0
- package/stdlib/modules/std/path/zz.zzm +100 -0
- package/stdlib/modules/std/proc.zzm +155 -0
- package/stdlib/modules/std/result.zzm +149 -0
- package/stdlib/modules/std/secure.zzm +606 -0
- package/stdlib/modules/std/string/base64.zzm +66 -0
- package/stdlib/modules/std/string/quoted_printable.zzm +485 -0
- package/stdlib/modules/std/string.zzm +179 -0
- package/stdlib/modules/std/task.zzm +221 -0
- package/stdlib/modules/std/template/z.zzm +531 -0
- package/stdlib/modules/std/template/zz.zzm +62 -0
- package/stdlib/modules/std/time.zzm +188 -0
- package/stdlib/modules/std/tui.zzm +89 -0
- package/stdlib/modules/std/uuid.zzm +223 -0
- package/stdlib/modules/std/web/session.zzm +388 -0
- package/stdlib/modules/std/web/static.zzm +329 -0
- package/stdlib/modules/std/web.zzm +1942 -0
- package/stdlib/modules/std/worker.zzm +202 -0
- package/stdlib/modules/std/zuzuzoo.zzm +3960 -0
- package/stdlib/modules/test/more.zzm +528 -0
- package/stdlib/modules/test/parser.zzm +209 -0
|
@@ -0,0 +1,1914 @@
|
|
|
1
|
+
=encoding utf8
|
|
2
|
+
|
|
3
|
+
=head1 NAME
|
|
4
|
+
|
|
5
|
+
std/gui - User-facing GUI constructor helpers.
|
|
6
|
+
|
|
7
|
+
=head1 SYNOPSIS
|
|
8
|
+
|
|
9
|
+
from std/gui import *;
|
|
10
|
+
|
|
11
|
+
let w := Window(
|
|
12
|
+
title: "Demo",
|
|
13
|
+
VBox(
|
|
14
|
+
Label( text: "Name:" ),
|
|
15
|
+
Input( id: "name" ),
|
|
16
|
+
Button( text: "OK", id: "submit" ),
|
|
17
|
+
),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
=head1 IMPLEMENTATION SUPPORT
|
|
21
|
+
|
|
22
|
+
This module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Electron.
|
|
23
|
+
It is not supported by zuzu-js on Node. It is partially supported by
|
|
24
|
+
zuzu-js in the browser: core GUI and widget lifecycle coverage passes,
|
|
25
|
+
but filesystem-backed file and directory dialogue coverage is unsupported.
|
|
26
|
+
|
|
27
|
+
=head1 DESCRIPTION
|
|
28
|
+
|
|
29
|
+
This module provides thin constructor helpers over C<std/gui/objects>.
|
|
30
|
+
Host runtimes expose the shared widget, object tree, event, and window
|
|
31
|
+
lifecycle APIs when GUI support is available. It also re-exports
|
|
32
|
+
backend-native file and directory dialogue hooks for C<std/gui/dialogue>.
|
|
33
|
+
|
|
34
|
+
The module exports C<EM>, the standard UI font height in logical
|
|
35
|
+
pixels, derived from C<std/gui/objects> metadata.
|
|
36
|
+
|
|
37
|
+
=head1 EXPORTS
|
|
38
|
+
|
|
39
|
+
=head2 Constants
|
|
40
|
+
|
|
41
|
+
=over
|
|
42
|
+
|
|
43
|
+
=item C<EM>
|
|
44
|
+
|
|
45
|
+
Type: C<Number>. Standard UI font height in logical pixels.
|
|
46
|
+
|
|
47
|
+
=item C<GUI_XML_NS>
|
|
48
|
+
|
|
49
|
+
Type: C<String>. XML namespace URI used by GUI XML serialization and
|
|
50
|
+
parsing.
|
|
51
|
+
|
|
52
|
+
=back
|
|
53
|
+
|
|
54
|
+
=head2 Functions
|
|
55
|
+
|
|
56
|
+
=over
|
|
57
|
+
|
|
58
|
+
=item C<< Window(... PairList p, Array c) >>, C<< VBox(... PairList p, Array c) >>, C<< HBox(... PairList p, Array c) >>, C<< Frame(... PairList p, Array c) >>
|
|
59
|
+
|
|
60
|
+
Parameters: C<p> are widget properties and C<c> contains child widgets.
|
|
61
|
+
Returns: widget object. Constructs window and layout widgets.
|
|
62
|
+
|
|
63
|
+
=item C<< Label(... PairList p, Array c) >>, C<< Text(... PairList p, Array c) >>, C<< RichText(... PairList p, Array c) >>, C<< Image(... PairList p, Array c) >>
|
|
64
|
+
|
|
65
|
+
Parameters: C<p> are widget properties and C<c> contains child widgets.
|
|
66
|
+
Returns: widget object. Constructs content widgets.
|
|
67
|
+
|
|
68
|
+
=item C<< Input(... PairList p, Array c) >>, C<< DatePicker(... PairList p, Array c) >>, C<< Checkbox(... PairList p, Array c) >>, C<< Radio(... PairList p, Array c) >>, C<< RadioGroup(... PairList p, Array c) >>, C<< Select(... PairList p, Array c) >>
|
|
69
|
+
|
|
70
|
+
Parameters: C<p> are widget properties and C<c> contains child widgets.
|
|
71
|
+
Returns: widget object. Constructs input widgets.
|
|
72
|
+
|
|
73
|
+
=item C<< Menu(... PairList p, Array c) >>, C<< MenuItem(... PairList p, Array c) >>, C<< Button(... PairList p, Array c) >>, C<< Separator(... PairList p, Array c) >>, C<< Slider(... PairList p, Array c) >>, C<< Progress(... PairList p, Array c) >>
|
|
74
|
+
|
|
75
|
+
Parameters: C<p> are widget properties and C<c> contains child widgets.
|
|
76
|
+
Returns: widget object. Constructs command and control widgets.
|
|
77
|
+
|
|
78
|
+
=item C<< Tabs(... PairList p, Array c) >>, C<< Tab(... PairList p, Array c) >>, C<< ListView(... PairList p, Array c) >>, C<< TreeView(... PairList p, Array c) >>
|
|
79
|
+
|
|
80
|
+
Parameters: C<p> are widget properties and C<c> contains child widgets.
|
|
81
|
+
Returns: widget object. Constructs tabular and collection widgets.
|
|
82
|
+
|
|
83
|
+
=item C<< unbind(BindingToken token) >>
|
|
84
|
+
|
|
85
|
+
Parameters: C<token> is a binding token. Returns: C<null>. Removes a GUI
|
|
86
|
+
binding.
|
|
87
|
+
|
|
88
|
+
=item C<< gui_from_xml(String xml) >>, C<< gui_from_xml_file(path) >>
|
|
89
|
+
|
|
90
|
+
Parameters: C<xml> is GUI XML text and C<path> is a file path. Returns:
|
|
91
|
+
widget object. Builds a GUI object tree from XML.
|
|
92
|
+
|
|
93
|
+
=item C<< gui_to_xml(Widget root) >>
|
|
94
|
+
|
|
95
|
+
Parameters: C<root> is a GUI widget. Returns: C<String>. Serializes a
|
|
96
|
+
GUI object tree to XML.
|
|
97
|
+
|
|
98
|
+
=back
|
|
99
|
+
|
|
100
|
+
=head2 Classes
|
|
101
|
+
|
|
102
|
+
=over
|
|
103
|
+
|
|
104
|
+
=item C<BindingToken>
|
|
105
|
+
|
|
106
|
+
Represents a model/widget binding.
|
|
107
|
+
|
|
108
|
+
=over
|
|
109
|
+
|
|
110
|
+
=item C<< token.is_active() >>
|
|
111
|
+
|
|
112
|
+
Parameters: none. Returns: C<Boolean>. Returns true while the binding is
|
|
113
|
+
active.
|
|
114
|
+
|
|
115
|
+
=item C<< token.set_listener(token) >>
|
|
116
|
+
|
|
117
|
+
Parameters: C<token> is a listener token. Returns: C<BindingToken>.
|
|
118
|
+
Stores the listener token associated with the binding.
|
|
119
|
+
|
|
120
|
+
=item C<< token.sync_model_to_widget() >>, C<< token.sync_widget_to_model() >>
|
|
121
|
+
|
|
122
|
+
Parameters: none. Returns: C<null>. Synchronizes the bound values.
|
|
123
|
+
|
|
124
|
+
=item C<< token.unbind() >>
|
|
125
|
+
|
|
126
|
+
Parameters: none. Returns: C<null>. Removes the binding.
|
|
127
|
+
|
|
128
|
+
=back
|
|
129
|
+
|
|
130
|
+
=back
|
|
131
|
+
|
|
132
|
+
=head1 COPYRIGHT AND LICENCE
|
|
133
|
+
|
|
134
|
+
B<< std/gui >> is copyright Toby Inkster.
|
|
135
|
+
|
|
136
|
+
It is free software; you may redistribute it and/or modify it under
|
|
137
|
+
the terms of either the Artistic License 1.0 or the GNU General Public
|
|
138
|
+
License version 2.
|
|
139
|
+
|
|
140
|
+
=cut
|
|
141
|
+
|
|
142
|
+
from std/gui/objects import
|
|
143
|
+
Window as _WindowClass,
|
|
144
|
+
VBox as _VBoxClass,
|
|
145
|
+
HBox as _HBoxClass,
|
|
146
|
+
Frame as _FrameClass,
|
|
147
|
+
Label as _LabelClass,
|
|
148
|
+
Text as _TextClass,
|
|
149
|
+
RichText as _RichTextClass,
|
|
150
|
+
Image as _ImageClass,
|
|
151
|
+
Input as _InputClass,
|
|
152
|
+
DatePicker as _DatePickerClass,
|
|
153
|
+
Checkbox as _CheckboxClass,
|
|
154
|
+
Radio as _RadioClass,
|
|
155
|
+
RadioGroup as _RadioGroupClass,
|
|
156
|
+
Select as _SelectClass,
|
|
157
|
+
Menu as _MenuClass,
|
|
158
|
+
MenuItem as _MenuItemClass,
|
|
159
|
+
Button as _ButtonClass,
|
|
160
|
+
Separator as _SeparatorClass,
|
|
161
|
+
Slider as _SliderClass,
|
|
162
|
+
Progress as _ProgressClass,
|
|
163
|
+
Tabs as _TabsClass,
|
|
164
|
+
Tab as _TabClass,
|
|
165
|
+
ListView as _ListViewClass,
|
|
166
|
+
TreeView as _TreeViewClass,
|
|
167
|
+
Widget,
|
|
168
|
+
Event,
|
|
169
|
+
ListenerToken,
|
|
170
|
+
native_file_open,
|
|
171
|
+
native_file_save,
|
|
172
|
+
native_directory_open,
|
|
173
|
+
native_directory_save,
|
|
174
|
+
native_colour_picker,
|
|
175
|
+
meta as _gui_meta;
|
|
176
|
+
|
|
177
|
+
from std/gui/objects try import
|
|
178
|
+
native_alert,
|
|
179
|
+
native_confirm,
|
|
180
|
+
native_prompt;
|
|
181
|
+
|
|
182
|
+
from std/data/xml import XML;
|
|
183
|
+
from std/data/xml/escape import escape_xml;
|
|
184
|
+
from std/internals import getupperprop;
|
|
185
|
+
from std/path/zz import ZZPath;
|
|
186
|
+
from std/string import join, split, substr, trim;
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
const Number EM := _gui_meta{font_size_pixels};
|
|
190
|
+
|
|
191
|
+
function _assert_known_props ( String ctor, PairList props, Array allowed ) {
|
|
192
|
+
let geometry := [
|
|
193
|
+
"width",
|
|
194
|
+
"height",
|
|
195
|
+
"minwidth",
|
|
196
|
+
"minheight",
|
|
197
|
+
"maxwidth",
|
|
198
|
+
"maxheight",
|
|
199
|
+
];
|
|
200
|
+
for ( let key in props.keys() ) {
|
|
201
|
+
if ( key ∉ allowed and key ∉ geometry ) {
|
|
202
|
+
die `GUI_PROP_UNKNOWN: ${ctor} does not accept property '${key}'`;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function _assert_prop_value ( String ctor, String prop, value, Array allowed ) {
|
|
208
|
+
if ( value ∉ allowed ) {
|
|
209
|
+
die `GUI_PROP_TYPE: ${ctor} property '${prop}' has invalid value`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function _assert_prop_array ( String ctor, String prop, value ) {
|
|
214
|
+
if ( not( value instanceof Array ) ) {
|
|
215
|
+
die `GUI_PROP_TYPE: ${ctor} property '${prop}' expects Array`;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function _with_geometry_props ( Array allowed ) {
|
|
220
|
+
for ( let key in [
|
|
221
|
+
"width",
|
|
222
|
+
"height",
|
|
223
|
+
"minwidth",
|
|
224
|
+
"minheight",
|
|
225
|
+
"maxwidth",
|
|
226
|
+
"maxheight",
|
|
227
|
+
] ) {
|
|
228
|
+
allowed.push(key) unless key ∈ allowed;
|
|
229
|
+
}
|
|
230
|
+
return allowed;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function _apply_geometry ( Widget widget, PairList p ) {
|
|
234
|
+
for ( let key in [
|
|
235
|
+
"width",
|
|
236
|
+
"height",
|
|
237
|
+
"minwidth",
|
|
238
|
+
"minheight",
|
|
239
|
+
"maxwidth",
|
|
240
|
+
"maxheight",
|
|
241
|
+
] ) {
|
|
242
|
+
if ( p.has(key) ) {
|
|
243
|
+
widget.(key)( p.get(key) );
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return widget;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function Window ( ... PairList p, Array c ) {
|
|
250
|
+
_assert_known_props(
|
|
251
|
+
"Window",
|
|
252
|
+
p,
|
|
253
|
+
_with_geometry_props( [
|
|
254
|
+
"id",
|
|
255
|
+
"title",
|
|
256
|
+
"width",
|
|
257
|
+
"height",
|
|
258
|
+
"resizable",
|
|
259
|
+
"modal",
|
|
260
|
+
"visible",
|
|
261
|
+
"enabled",
|
|
262
|
+
"disabled",
|
|
263
|
+
] ),
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
return new _WindowClass(
|
|
267
|
+
id: p.get( "id", null ),
|
|
268
|
+
title: p.get( "title", "" ),
|
|
269
|
+
width: p.get( "width", 800 ),
|
|
270
|
+
height: p.get( "height", 600 ),
|
|
271
|
+
minwidth: p.get( "minwidth", null ),
|
|
272
|
+
minheight: p.get( "minheight", null ),
|
|
273
|
+
maxwidth: p.get( "maxwidth", null ),
|
|
274
|
+
maxheight: p.get( "maxheight", null ),
|
|
275
|
+
resizable: p.get( "resizable", true ),
|
|
276
|
+
modal: p.get( "modal", false ),
|
|
277
|
+
visible: p.get( "visible", true ),
|
|
278
|
+
enabled: p.get( "enabled", true ),
|
|
279
|
+
disabled: p.get( "disabled", false ),
|
|
280
|
+
children: c,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function VBox ( ... PairList p, Array c ) {
|
|
285
|
+
_assert_known_props(
|
|
286
|
+
"VBox",
|
|
287
|
+
p,
|
|
288
|
+
[
|
|
289
|
+
"id",
|
|
290
|
+
"align",
|
|
291
|
+
"gap",
|
|
292
|
+
"padding",
|
|
293
|
+
"visible",
|
|
294
|
+
"enabled",
|
|
295
|
+
"disabled",
|
|
296
|
+
],
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
_assert_prop_value(
|
|
300
|
+
"VBox",
|
|
301
|
+
"align",
|
|
302
|
+
p.get( "align", "top" ),
|
|
303
|
+
[ "top", "centre", "bottom", "stretch" ],
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
return _apply_geometry( new _VBoxClass(
|
|
307
|
+
id: p.get( "id", null ),
|
|
308
|
+
align: p.get( "align", "top" ),
|
|
309
|
+
gap: p.get( "gap", 0 ),
|
|
310
|
+
padding: p.get( "padding", 0 ),
|
|
311
|
+
visible: p.get( "visible", true ),
|
|
312
|
+
enabled: p.get( "enabled", true ),
|
|
313
|
+
disabled: p.get( "disabled", false ),
|
|
314
|
+
children: c,
|
|
315
|
+
), p );
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function HBox ( ... PairList p, Array c ) {
|
|
319
|
+
_assert_known_props(
|
|
320
|
+
"HBox",
|
|
321
|
+
p,
|
|
322
|
+
_with_geometry_props( [
|
|
323
|
+
"id",
|
|
324
|
+
"align",
|
|
325
|
+
"gap",
|
|
326
|
+
"padding",
|
|
327
|
+
"visible",
|
|
328
|
+
"enabled",
|
|
329
|
+
"disabled",
|
|
330
|
+
] ),
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
_assert_prop_value(
|
|
334
|
+
"HBox",
|
|
335
|
+
"align",
|
|
336
|
+
p.get( "align", "left" ),
|
|
337
|
+
[ "left", "centre", "right", "stretch" ],
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
return new _HBoxClass(
|
|
341
|
+
id: p.get( "id", null ),
|
|
342
|
+
align: p.get( "align", "left" ),
|
|
343
|
+
gap: p.get( "gap", 0 ),
|
|
344
|
+
padding: p.get( "padding", 0 ),
|
|
345
|
+
width: p.get( "width", null ),
|
|
346
|
+
height: p.get( "height", null ),
|
|
347
|
+
minwidth: p.get( "minwidth", null ),
|
|
348
|
+
minheight: p.get( "minheight", null ),
|
|
349
|
+
maxwidth: p.get( "maxwidth", null ),
|
|
350
|
+
maxheight: p.get( "maxheight", null ),
|
|
351
|
+
visible: p.get( "visible", true ),
|
|
352
|
+
enabled: p.get( "enabled", true ),
|
|
353
|
+
disabled: p.get( "disabled", false ),
|
|
354
|
+
children: c,
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function Frame ( ... PairList p, Array c ) {
|
|
359
|
+
_assert_known_props(
|
|
360
|
+
"Frame",
|
|
361
|
+
p,
|
|
362
|
+
[
|
|
363
|
+
"id",
|
|
364
|
+
"label",
|
|
365
|
+
"collapsible",
|
|
366
|
+
"collapsed",
|
|
367
|
+
"visible",
|
|
368
|
+
"enabled",
|
|
369
|
+
"disabled",
|
|
370
|
+
],
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
return _apply_geometry( new _FrameClass(
|
|
374
|
+
id: p.get( "id", null ),
|
|
375
|
+
label: p.get( "label", "" ),
|
|
376
|
+
collapsible: p.get( "collapsible", false ),
|
|
377
|
+
collapsed: p.get( "collapsed", false ),
|
|
378
|
+
visible: p.get( "visible", true ),
|
|
379
|
+
enabled: p.get( "enabled", true ),
|
|
380
|
+
disabled: p.get( "disabled", false ),
|
|
381
|
+
children: c,
|
|
382
|
+
), p );
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function Label ( ... PairList p, Array c ) {
|
|
386
|
+
_assert_known_props(
|
|
387
|
+
"Label",
|
|
388
|
+
p,
|
|
389
|
+
[ "id", "text", "for", "visible", "enabled", "disabled" ],
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
let label := new _LabelClass(
|
|
393
|
+
id: p.get( "id", null ),
|
|
394
|
+
text: p.get( "text", "" ),
|
|
395
|
+
visible: p.get( "visible", true ),
|
|
396
|
+
enabled: p.get( "enabled", true ),
|
|
397
|
+
disabled: p.get( "disabled", false ),
|
|
398
|
+
children: c,
|
|
399
|
+
);
|
|
400
|
+
if ( p.has("for") ) {
|
|
401
|
+
label.set_for_id( p.get( "for", null ) );
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return _apply_geometry( label, p );
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function Text ( ... PairList p, Array c ) {
|
|
408
|
+
_assert_known_props(
|
|
409
|
+
"Text",
|
|
410
|
+
p,
|
|
411
|
+
[
|
|
412
|
+
"id",
|
|
413
|
+
"value",
|
|
414
|
+
"multiline",
|
|
415
|
+
"readonly",
|
|
416
|
+
"wrap",
|
|
417
|
+
"visible",
|
|
418
|
+
"enabled",
|
|
419
|
+
"disabled",
|
|
420
|
+
],
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
return _apply_geometry( new _TextClass(
|
|
424
|
+
id: p.get( "id", null ),
|
|
425
|
+
value: p.get( "value", "" ),
|
|
426
|
+
multiline: p.get( "multiline", false ),
|
|
427
|
+
readonly: p.get( "readonly", false ),
|
|
428
|
+
wrap: p.get( "wrap", true ),
|
|
429
|
+
visible: p.get( "visible", true ),
|
|
430
|
+
enabled: p.get( "enabled", true ),
|
|
431
|
+
disabled: p.get( "disabled", false ),
|
|
432
|
+
children: c,
|
|
433
|
+
), p );
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function RichText ( ... PairList p, Array c ) {
|
|
437
|
+
_assert_known_props(
|
|
438
|
+
"RichText",
|
|
439
|
+
p,
|
|
440
|
+
[
|
|
441
|
+
"id",
|
|
442
|
+
"value",
|
|
443
|
+
"multiline",
|
|
444
|
+
"readonly",
|
|
445
|
+
"visible",
|
|
446
|
+
"enabled",
|
|
447
|
+
"disabled",
|
|
448
|
+
],
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
return _apply_geometry( new _RichTextClass(
|
|
452
|
+
id: p.get( "id", null ),
|
|
453
|
+
value: p.get( "value", "" ),
|
|
454
|
+
multiline: p.get( "multiline", true ),
|
|
455
|
+
readonly: p.get( "readonly", true ),
|
|
456
|
+
visible: p.get( "visible", true ),
|
|
457
|
+
enabled: p.get( "enabled", true ),
|
|
458
|
+
disabled: p.get( "disabled", false ),
|
|
459
|
+
children: c,
|
|
460
|
+
), p );
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function Image ( ... PairList p, Array c ) {
|
|
464
|
+
_assert_known_props(
|
|
465
|
+
"Image",
|
|
466
|
+
p,
|
|
467
|
+
[ "id", "src", "alt", "fit", "visible", "enabled", "disabled" ],
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
_assert_prop_value(
|
|
471
|
+
"Image",
|
|
472
|
+
"fit",
|
|
473
|
+
p.get( "fit", "none" ),
|
|
474
|
+
[ "none", "contain", "cover", "stretch" ],
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
return _apply_geometry( new _ImageClass(
|
|
478
|
+
id: p.get( "id", null ),
|
|
479
|
+
src: p.get( "src", "" ),
|
|
480
|
+
alt: p.get( "alt", "" ),
|
|
481
|
+
fit: p.get( "fit", "none" ),
|
|
482
|
+
visible: p.get( "visible", true ),
|
|
483
|
+
enabled: p.get( "enabled", true ),
|
|
484
|
+
disabled: p.get( "disabled", false ),
|
|
485
|
+
children: c,
|
|
486
|
+
), p );
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function Input ( ... PairList p, Array c ) {
|
|
490
|
+
_assert_known_props(
|
|
491
|
+
"Input",
|
|
492
|
+
p,
|
|
493
|
+
[
|
|
494
|
+
"id",
|
|
495
|
+
"value",
|
|
496
|
+
"placeholder",
|
|
497
|
+
"multiline",
|
|
498
|
+
"readonly",
|
|
499
|
+
"password",
|
|
500
|
+
"required",
|
|
501
|
+
"visible",
|
|
502
|
+
"enabled",
|
|
503
|
+
"disabled",
|
|
504
|
+
],
|
|
505
|
+
);
|
|
506
|
+
|
|
507
|
+
return _apply_geometry( new _InputClass(
|
|
508
|
+
id: p.get( "id", null ),
|
|
509
|
+
value: p.get( "value", "" ),
|
|
510
|
+
placeholder: p.get( "placeholder", "" ),
|
|
511
|
+
multiline: p.get( "multiline", false ),
|
|
512
|
+
readonly: p.get( "readonly", false ),
|
|
513
|
+
password: p.get( "password", false ),
|
|
514
|
+
required: p.get( "required", false ),
|
|
515
|
+
visible: p.get( "visible", true ),
|
|
516
|
+
enabled: p.get( "enabled", true ),
|
|
517
|
+
disabled: p.get( "disabled", false ),
|
|
518
|
+
children: c,
|
|
519
|
+
), p );
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function DatePicker ( ... PairList p, Array c ) {
|
|
523
|
+
_assert_known_props(
|
|
524
|
+
"DatePicker",
|
|
525
|
+
p,
|
|
526
|
+
[
|
|
527
|
+
"id",
|
|
528
|
+
"value",
|
|
529
|
+
"min",
|
|
530
|
+
"max",
|
|
531
|
+
"first_day_of_week",
|
|
532
|
+
"visible",
|
|
533
|
+
"enabled",
|
|
534
|
+
"disabled",
|
|
535
|
+
],
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
return _apply_geometry( new _DatePickerClass(
|
|
539
|
+
id: p.get( "id", null ),
|
|
540
|
+
value: p.get( "value", null ),
|
|
541
|
+
min: p.get( "min", null ),
|
|
542
|
+
max: p.get( "max", null ),
|
|
543
|
+
first_day_of_week: p.get( "first_day_of_week", 0 ),
|
|
544
|
+
visible: p.get( "visible", true ),
|
|
545
|
+
enabled: p.get( "enabled", true ),
|
|
546
|
+
disabled: p.get( "disabled", false ),
|
|
547
|
+
children: c,
|
|
548
|
+
), p );
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function Checkbox ( ... PairList p, Array c ) {
|
|
552
|
+
_assert_known_props(
|
|
553
|
+
"Checkbox",
|
|
554
|
+
p,
|
|
555
|
+
[
|
|
556
|
+
"id",
|
|
557
|
+
"label",
|
|
558
|
+
"checked",
|
|
559
|
+
"indeterminate",
|
|
560
|
+
"visible",
|
|
561
|
+
"enabled",
|
|
562
|
+
"disabled",
|
|
563
|
+
],
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
return _apply_geometry( new _CheckboxClass(
|
|
567
|
+
id: p.get( "id", null ),
|
|
568
|
+
label: p.get( "label", "" ),
|
|
569
|
+
checked: p.get( "checked", false ),
|
|
570
|
+
indeterminate: p.get( "indeterminate", false ),
|
|
571
|
+
visible: p.get( "visible", true ),
|
|
572
|
+
enabled: p.get( "enabled", true ),
|
|
573
|
+
disabled: p.get( "disabled", false ),
|
|
574
|
+
children: c,
|
|
575
|
+
), p );
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function Radio ( ... PairList p, Array c ) {
|
|
579
|
+
_assert_known_props(
|
|
580
|
+
"Radio",
|
|
581
|
+
p,
|
|
582
|
+
[
|
|
583
|
+
"id",
|
|
584
|
+
"label",
|
|
585
|
+
"value",
|
|
586
|
+
"group",
|
|
587
|
+
"checked",
|
|
588
|
+
"visible",
|
|
589
|
+
"enabled",
|
|
590
|
+
"disabled",
|
|
591
|
+
],
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
return _apply_geometry( new _RadioClass(
|
|
595
|
+
id: p.get( "id", null ),
|
|
596
|
+
label: p.get( "label", "" ),
|
|
597
|
+
value: p.get( "value", "" ),
|
|
598
|
+
group: p.get( "group", null ),
|
|
599
|
+
checked: p.get( "checked", false ),
|
|
600
|
+
visible: p.get( "visible", true ),
|
|
601
|
+
enabled: p.get( "enabled", true ),
|
|
602
|
+
disabled: p.get( "disabled", false ),
|
|
603
|
+
children: c,
|
|
604
|
+
), p );
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function RadioGroup ( ... PairList p, Array c ) {
|
|
608
|
+
_assert_known_props(
|
|
609
|
+
"RadioGroup",
|
|
610
|
+
p,
|
|
611
|
+
[
|
|
612
|
+
"id",
|
|
613
|
+
"name",
|
|
614
|
+
"value",
|
|
615
|
+
"visible",
|
|
616
|
+
"enabled",
|
|
617
|
+
"disabled",
|
|
618
|
+
],
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
return _apply_geometry( new _RadioGroupClass(
|
|
622
|
+
id: p.get( "id", null ),
|
|
623
|
+
name: p.get( "name", "" ),
|
|
624
|
+
value: p.get( "value", null ),
|
|
625
|
+
visible: p.get( "visible", true ),
|
|
626
|
+
enabled: p.get( "enabled", true ),
|
|
627
|
+
disabled: p.get( "disabled", false ),
|
|
628
|
+
children: c,
|
|
629
|
+
), p );
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function Select ( ... PairList p, Array c ) {
|
|
633
|
+
_assert_known_props(
|
|
634
|
+
"Select",
|
|
635
|
+
p,
|
|
636
|
+
[
|
|
637
|
+
"id",
|
|
638
|
+
"value",
|
|
639
|
+
"options",
|
|
640
|
+
"multiple",
|
|
641
|
+
"visible",
|
|
642
|
+
"enabled",
|
|
643
|
+
"disabled",
|
|
644
|
+
],
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
if ( p.has("options") ) {
|
|
648
|
+
_assert_prop_array( "Select", "options", p.get("options") );
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
return _apply_geometry( new _SelectClass(
|
|
652
|
+
id: p.get( "id", null ),
|
|
653
|
+
value: p.get( "value", null ),
|
|
654
|
+
options: p.get( "options", [] ),
|
|
655
|
+
multiple: p.get( "multiple", false ),
|
|
656
|
+
visible: p.get( "visible", true ),
|
|
657
|
+
enabled: p.get( "enabled", true ),
|
|
658
|
+
disabled: p.get( "disabled", false ),
|
|
659
|
+
children: c,
|
|
660
|
+
), p );
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
function Menu ( ... PairList p, Array c ) {
|
|
664
|
+
_assert_known_props(
|
|
665
|
+
"Menu",
|
|
666
|
+
p,
|
|
667
|
+
[ "id", "text", "visible", "enabled", "disabled" ],
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
return _apply_geometry( new _MenuClass(
|
|
671
|
+
id: p.get( "id", null ),
|
|
672
|
+
text: p.get( "text", "" ),
|
|
673
|
+
visible: p.get( "visible", true ),
|
|
674
|
+
enabled: p.get( "enabled", true ),
|
|
675
|
+
disabled: p.get( "disabled", false ),
|
|
676
|
+
children: c,
|
|
677
|
+
), p );
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function MenuItem ( ... PairList p, Array c ) {
|
|
681
|
+
_assert_known_props(
|
|
682
|
+
"MenuItem",
|
|
683
|
+
p,
|
|
684
|
+
[ "id", "text", "disabled", "visible", "enabled" ],
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
return _apply_geometry( new _MenuItemClass(
|
|
688
|
+
id: p.get( "id", null ),
|
|
689
|
+
text: p.get( "text", "" ),
|
|
690
|
+
visible: p.get( "visible", true ),
|
|
691
|
+
enabled: p.get( "enabled", true ),
|
|
692
|
+
disabled: p.get( "disabled", false ),
|
|
693
|
+
children: c,
|
|
694
|
+
), p );
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function Button ( ... PairList p, Array c ) {
|
|
698
|
+
_assert_known_props(
|
|
699
|
+
"Button",
|
|
700
|
+
p,
|
|
701
|
+
_with_geometry_props( [
|
|
702
|
+
"id",
|
|
703
|
+
"text",
|
|
704
|
+
"variant",
|
|
705
|
+
"visible",
|
|
706
|
+
"enabled",
|
|
707
|
+
"disabled",
|
|
708
|
+
] ),
|
|
709
|
+
);
|
|
710
|
+
|
|
711
|
+
_assert_prop_value(
|
|
712
|
+
"Button",
|
|
713
|
+
"variant",
|
|
714
|
+
p.get( "variant", "default" ),
|
|
715
|
+
[ "default", "primary", "danger" ],
|
|
716
|
+
);
|
|
717
|
+
|
|
718
|
+
return new _ButtonClass(
|
|
719
|
+
id: p.get( "id", null ),
|
|
720
|
+
text: p.get( "text", "" ),
|
|
721
|
+
variant: p.get( "variant", "default" ),
|
|
722
|
+
width: p.get( "width", null ),
|
|
723
|
+
height: p.get( "height", null ),
|
|
724
|
+
minwidth: p.get( "minwidth", null ),
|
|
725
|
+
minheight: p.get( "minheight", null ),
|
|
726
|
+
maxwidth: p.get( "maxwidth", null ),
|
|
727
|
+
maxheight: p.get( "maxheight", null ),
|
|
728
|
+
visible: p.get( "visible", true ),
|
|
729
|
+
enabled: p.get( "enabled", true ),
|
|
730
|
+
disabled: p.get( "disabled", false ),
|
|
731
|
+
children: c,
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function Separator ( ... PairList p, Array c ) {
|
|
736
|
+
_assert_known_props(
|
|
737
|
+
"Separator",
|
|
738
|
+
p,
|
|
739
|
+
[ "id", "orientation", "visible", "enabled", "disabled" ],
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
_assert_prop_value(
|
|
743
|
+
"Separator",
|
|
744
|
+
"orientation",
|
|
745
|
+
p.get( "orientation", "horizontal" ),
|
|
746
|
+
[ "horizontal", "vertical" ],
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
return _apply_geometry( new _SeparatorClass(
|
|
750
|
+
id: p.get( "id", null ),
|
|
751
|
+
orientation: p.get( "orientation", "horizontal" ),
|
|
752
|
+
visible: p.get( "visible", true ),
|
|
753
|
+
enabled: p.get( "enabled", true ),
|
|
754
|
+
disabled: p.get( "disabled", false ),
|
|
755
|
+
children: c,
|
|
756
|
+
), p );
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
function Slider ( ... PairList p, Array c ) {
|
|
760
|
+
_assert_known_props(
|
|
761
|
+
"Slider",
|
|
762
|
+
p,
|
|
763
|
+
[
|
|
764
|
+
"id",
|
|
765
|
+
"value",
|
|
766
|
+
"min",
|
|
767
|
+
"max",
|
|
768
|
+
"step",
|
|
769
|
+
"orientation",
|
|
770
|
+
"readonly",
|
|
771
|
+
"visible",
|
|
772
|
+
"enabled",
|
|
773
|
+
"disabled",
|
|
774
|
+
],
|
|
775
|
+
);
|
|
776
|
+
|
|
777
|
+
_assert_prop_value(
|
|
778
|
+
"Slider",
|
|
779
|
+
"orientation",
|
|
780
|
+
p.get( "orientation", "horizontal" ),
|
|
781
|
+
[ "horizontal", "vertical" ],
|
|
782
|
+
);
|
|
783
|
+
|
|
784
|
+
return _apply_geometry( new _SliderClass(
|
|
785
|
+
id: p.get( "id", null ),
|
|
786
|
+
value: p.get( "value", 0 ),
|
|
787
|
+
min: p.get( "min", 0 ),
|
|
788
|
+
max: p.get( "max", 100 ),
|
|
789
|
+
step: p.get( "step", 1 ),
|
|
790
|
+
orientation: p.get( "orientation", "horizontal" ),
|
|
791
|
+
readonly: p.get( "readonly", false ),
|
|
792
|
+
visible: p.get( "visible", true ),
|
|
793
|
+
enabled: p.get( "enabled", true ),
|
|
794
|
+
disabled: p.get( "disabled", false ),
|
|
795
|
+
children: c,
|
|
796
|
+
), p );
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function Progress ( ... PairList p, Array c ) {
|
|
800
|
+
_assert_known_props(
|
|
801
|
+
"Progress",
|
|
802
|
+
p,
|
|
803
|
+
[
|
|
804
|
+
"id",
|
|
805
|
+
"value",
|
|
806
|
+
"min",
|
|
807
|
+
"max",
|
|
808
|
+
"indeterminate",
|
|
809
|
+
"show_text",
|
|
810
|
+
"visible",
|
|
811
|
+
"enabled",
|
|
812
|
+
"disabled",
|
|
813
|
+
],
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
return _apply_geometry( new _ProgressClass(
|
|
817
|
+
id: p.get( "id", null ),
|
|
818
|
+
value: p.get( "value", 0 ),
|
|
819
|
+
min: p.get( "min", 0 ),
|
|
820
|
+
max: p.get( "max", 100 ),
|
|
821
|
+
indeterminate: p.get( "indeterminate", false ),
|
|
822
|
+
show_text: p.get( "show_text", false ),
|
|
823
|
+
visible: p.get( "visible", true ),
|
|
824
|
+
enabled: p.get( "enabled", true ),
|
|
825
|
+
disabled: p.get( "disabled", false ),
|
|
826
|
+
children: c,
|
|
827
|
+
), p );
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function Tabs ( ... PairList p, Array c ) {
|
|
831
|
+
_assert_known_props(
|
|
832
|
+
"Tabs",
|
|
833
|
+
p,
|
|
834
|
+
[
|
|
835
|
+
"id",
|
|
836
|
+
"selected",
|
|
837
|
+
"placement",
|
|
838
|
+
"visible",
|
|
839
|
+
"enabled",
|
|
840
|
+
"disabled",
|
|
841
|
+
],
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
_assert_prop_value(
|
|
845
|
+
"Tabs",
|
|
846
|
+
"placement",
|
|
847
|
+
p.get( "placement", "top" ),
|
|
848
|
+
[ "top", "bottom", "left", "right" ],
|
|
849
|
+
);
|
|
850
|
+
|
|
851
|
+
return _apply_geometry( new _TabsClass(
|
|
852
|
+
id: p.get( "id", null ),
|
|
853
|
+
selected: p.get( "selected", null ),
|
|
854
|
+
placement: p.get( "placement", "top" ),
|
|
855
|
+
visible: p.get( "visible", true ),
|
|
856
|
+
enabled: p.get( "enabled", true ),
|
|
857
|
+
disabled: p.get( "disabled", false ),
|
|
858
|
+
children: c,
|
|
859
|
+
), p );
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
function Tab ( ... PairList p, Array c ) {
|
|
863
|
+
_assert_known_props(
|
|
864
|
+
"Tab",
|
|
865
|
+
p,
|
|
866
|
+
[
|
|
867
|
+
"id",
|
|
868
|
+
"title",
|
|
869
|
+
"value",
|
|
870
|
+
"selected",
|
|
871
|
+
"closable",
|
|
872
|
+
"icon",
|
|
873
|
+
"visible",
|
|
874
|
+
"enabled",
|
|
875
|
+
"disabled",
|
|
876
|
+
],
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
return _apply_geometry( new _TabClass(
|
|
880
|
+
id: p.get( "id", null ),
|
|
881
|
+
title: p.get( "title", "" ),
|
|
882
|
+
value: p.get( "value", "" ),
|
|
883
|
+
selected: p.get( "selected", false ),
|
|
884
|
+
closable: p.get( "closable", false ),
|
|
885
|
+
icon: p.get( "icon", null ),
|
|
886
|
+
visible: p.get( "visible", true ),
|
|
887
|
+
enabled: p.get( "enabled", true ),
|
|
888
|
+
disabled: p.get( "disabled", false ),
|
|
889
|
+
children: c,
|
|
890
|
+
), p );
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function ListView ( ... PairList p, Array c ) {
|
|
894
|
+
_assert_known_props(
|
|
895
|
+
"ListView",
|
|
896
|
+
p,
|
|
897
|
+
[
|
|
898
|
+
"id",
|
|
899
|
+
"items",
|
|
900
|
+
"selected_index",
|
|
901
|
+
"multiple",
|
|
902
|
+
"visible",
|
|
903
|
+
"enabled",
|
|
904
|
+
"disabled",
|
|
905
|
+
],
|
|
906
|
+
);
|
|
907
|
+
|
|
908
|
+
if ( p.has("items") ) {
|
|
909
|
+
_assert_prop_array( "ListView", "items", p.get("items") );
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
return _apply_geometry( new _ListViewClass(
|
|
913
|
+
id: p.get( "id", null ),
|
|
914
|
+
items: p.get( "items", [] ),
|
|
915
|
+
selected_index: p.get( "selected_index", null ),
|
|
916
|
+
multiple: p.get( "multiple", false ),
|
|
917
|
+
visible: p.get( "visible", true ),
|
|
918
|
+
enabled: p.get( "enabled", true ),
|
|
919
|
+
disabled: p.get( "disabled", false ),
|
|
920
|
+
children: c,
|
|
921
|
+
), p );
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function TreeView ( ... PairList p, Array c ) {
|
|
925
|
+
_assert_known_props(
|
|
926
|
+
"TreeView",
|
|
927
|
+
p,
|
|
928
|
+
[
|
|
929
|
+
"id",
|
|
930
|
+
"items",
|
|
931
|
+
"selected_path",
|
|
932
|
+
"multiple",
|
|
933
|
+
"visible",
|
|
934
|
+
"enabled",
|
|
935
|
+
"disabled",
|
|
936
|
+
],
|
|
937
|
+
);
|
|
938
|
+
|
|
939
|
+
if ( p.has("items") ) {
|
|
940
|
+
_assert_prop_array( "TreeView", "items", p.get("items") );
|
|
941
|
+
}
|
|
942
|
+
if ( p.has("selected_path") ) {
|
|
943
|
+
_assert_prop_array( "TreeView", "selected_path", p.get("selected_path") );
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
return _apply_geometry( new _TreeViewClass(
|
|
947
|
+
id: p.get( "id", null ),
|
|
948
|
+
items: p.get( "items", [] ),
|
|
949
|
+
selected_path: p.get( "selected_path", [] ),
|
|
950
|
+
multiple: p.get( "multiple", false ),
|
|
951
|
+
visible: p.get( "visible", true ),
|
|
952
|
+
enabled: p.get( "enabled", true ),
|
|
953
|
+
disabled: p.get( "disabled", false ),
|
|
954
|
+
children: c,
|
|
955
|
+
), p );
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
function _binding_path_class ( path_class ) {
|
|
959
|
+
if ( path_class ≡ null ) {
|
|
960
|
+
return ZZPath;
|
|
961
|
+
}
|
|
962
|
+
if ( not( path_class instanceof Class ) ) {
|
|
963
|
+
die "GUI_BIND_PATH: paths special property must be Class or null";
|
|
964
|
+
}
|
|
965
|
+
return path_class;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
function _binding_compile_path ( String path_text, path_class ) {
|
|
969
|
+
if ( path_class ≡ null ) {
|
|
970
|
+
try {
|
|
971
|
+
return new ZZPath( path: path_text );
|
|
972
|
+
}
|
|
973
|
+
catch ( Exception e ) {
|
|
974
|
+
die `GUI_BIND_PATH: ${e{message}}`;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
let path_type := _binding_path_class(path_class);
|
|
979
|
+
try {
|
|
980
|
+
return new path_type( path: path_text );
|
|
981
|
+
}
|
|
982
|
+
catch ( Exception e ) {
|
|
983
|
+
die `GUI_BIND_PATH: ${e{message}}`;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function _binding_path ( pathish, path_class ) {
|
|
988
|
+
if ( pathish instanceof String ) {
|
|
989
|
+
return _binding_compile_path( pathish, path_class );
|
|
990
|
+
}
|
|
991
|
+
if (
|
|
992
|
+
pathish can first
|
|
993
|
+
and ( pathish can assign_first or pathish can ref_first )
|
|
994
|
+
) {
|
|
995
|
+
return pathish;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
die "GUI_BIND_PATH: binding path must be String or path-like Object";
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
function _binding_get ( model, path ) {
|
|
1002
|
+
return path.first( model, null );
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function _binding_set ( model, path, value ) {
|
|
1006
|
+
if ( path can assign_first ) {
|
|
1007
|
+
return path.assign_first( model, value );
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
let ref := path.ref_first(model);
|
|
1011
|
+
return ref(value);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
class BindingToken {
|
|
1015
|
+
let Widget widget but weak;
|
|
1016
|
+
let String widget_prop;
|
|
1017
|
+
let model;
|
|
1018
|
+
let model_path;
|
|
1019
|
+
let String event := "change";
|
|
1020
|
+
let listener := null;
|
|
1021
|
+
let Boolean _active := true;
|
|
1022
|
+
|
|
1023
|
+
method is_active () {
|
|
1024
|
+
return _active;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
method set_listener ( token ) {
|
|
1028
|
+
listener := token;
|
|
1029
|
+
return self;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
method sync_model_to_widget () {
|
|
1033
|
+
widget.(widget_prop)( _binding_get( model, model_path ) );
|
|
1034
|
+
return self;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
method sync_widget_to_model () {
|
|
1038
|
+
_binding_set( model, model_path, widget.(widget_prop)() );
|
|
1039
|
+
return self;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
method unbind () {
|
|
1043
|
+
if ( _active and listener ≢ null ) {
|
|
1044
|
+
widget.off(listener);
|
|
1045
|
+
}
|
|
1046
|
+
_active := false;
|
|
1047
|
+
return self;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
function bind (
|
|
1052
|
+
Widget widget,
|
|
1053
|
+
String widget_prop,
|
|
1054
|
+
model,
|
|
1055
|
+
model_path,
|
|
1056
|
+
... PairList p
|
|
1057
|
+
) {
|
|
1058
|
+
let path := _binding_path( model_path, getupperprop( 1, "paths" ) );
|
|
1059
|
+
|
|
1060
|
+
let token := new BindingToken(
|
|
1061
|
+
widget: widget,
|
|
1062
|
+
widget_prop: widget_prop,
|
|
1063
|
+
model: model,
|
|
1064
|
+
model_path: path,
|
|
1065
|
+
event: p.get( "event", "change" ),
|
|
1066
|
+
);
|
|
1067
|
+
let event_name := p.get( "event", "change" );
|
|
1068
|
+
|
|
1069
|
+
switch ( p.get( "initial", "model" ): eq ) {
|
|
1070
|
+
case "model":
|
|
1071
|
+
token.sync_model_to_widget();
|
|
1072
|
+
case "widget":
|
|
1073
|
+
token.sync_widget_to_model();
|
|
1074
|
+
case "none":
|
|
1075
|
+
// No initial sync.
|
|
1076
|
+
default:
|
|
1077
|
+
die "GUI_BIND_INITIAL: initial must be model, widget, or none";
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
token.set_listener(
|
|
1081
|
+
widget.on( event_name, function () {
|
|
1082
|
+
if ( token.is_active() ) {
|
|
1083
|
+
token.sync_widget_to_model();
|
|
1084
|
+
}
|
|
1085
|
+
} ),
|
|
1086
|
+
);
|
|
1087
|
+
return token;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
function unbind ( BindingToken token ) {
|
|
1091
|
+
return token.unbind();
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
let GUI_XML_NS := "https://zuzulang.org/ns/std/gui";
|
|
1095
|
+
|
|
1096
|
+
function _xml_error ( String code, String message ) {
|
|
1097
|
+
die `${code}: ${message}`;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
function _xml_tag_name ( node ) {
|
|
1101
|
+
return node.localName() ?: node.nodeName();
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
function _xml_assert_namespace ( node ) {
|
|
1105
|
+
let ns := node.namespaceURI();
|
|
1106
|
+
if ( ns ≢ null and ns ≢ "" and ns ≢ GUI_XML_NS ) {
|
|
1107
|
+
_xml_error(
|
|
1108
|
+
"GUI_XML_STRUCTURE",
|
|
1109
|
+
`unsupported GUI XML namespace '${ns}'`,
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
function _xml_common_allowed ( Array extra ) {
|
|
1115
|
+
let out := [
|
|
1116
|
+
"id",
|
|
1117
|
+
"visible",
|
|
1118
|
+
"enabled",
|
|
1119
|
+
"disabled",
|
|
1120
|
+
"width",
|
|
1121
|
+
"height",
|
|
1122
|
+
"minwidth",
|
|
1123
|
+
"minheight",
|
|
1124
|
+
"maxwidth",
|
|
1125
|
+
"maxheight",
|
|
1126
|
+
];
|
|
1127
|
+
for ( let attr in extra ) {
|
|
1128
|
+
out.push(attr);
|
|
1129
|
+
}
|
|
1130
|
+
return out;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
function _xml_allowed_attrs ( String tag ) {
|
|
1134
|
+
switch ( tag: eq ) {
|
|
1135
|
+
case "Window":
|
|
1136
|
+
return _xml_common_allowed(
|
|
1137
|
+
[ "title", "width", "height", "resizable", "modal" ],
|
|
1138
|
+
);
|
|
1139
|
+
case "VBox", "HBox":
|
|
1140
|
+
return _xml_common_allowed( [ "align", "gap", "padding" ] );
|
|
1141
|
+
case "Frame":
|
|
1142
|
+
return _xml_common_allowed( [ "label", "collapsible", "collapsed" ] );
|
|
1143
|
+
case "Label":
|
|
1144
|
+
return _xml_common_allowed( [ "text", "for" ] );
|
|
1145
|
+
case "Text":
|
|
1146
|
+
return _xml_common_allowed(
|
|
1147
|
+
[ "value", "multiline", "readonly", "wrap" ],
|
|
1148
|
+
);
|
|
1149
|
+
case "RichText":
|
|
1150
|
+
return _xml_common_allowed(
|
|
1151
|
+
[ "value", "multiline", "readonly" ],
|
|
1152
|
+
);
|
|
1153
|
+
case "Image":
|
|
1154
|
+
return _xml_common_allowed( [ "src", "alt", "fit" ] );
|
|
1155
|
+
case "Input":
|
|
1156
|
+
return _xml_common_allowed( [
|
|
1157
|
+
"value",
|
|
1158
|
+
"placeholder",
|
|
1159
|
+
"multiline",
|
|
1160
|
+
"readonly",
|
|
1161
|
+
"password",
|
|
1162
|
+
"required",
|
|
1163
|
+
] );
|
|
1164
|
+
case "DatePicker":
|
|
1165
|
+
return _xml_common_allowed(
|
|
1166
|
+
[ "value", "min", "max", "first_day_of_week" ],
|
|
1167
|
+
);
|
|
1168
|
+
case "Checkbox":
|
|
1169
|
+
return _xml_common_allowed( [ "label", "checked", "indeterminate" ] );
|
|
1170
|
+
case "Radio":
|
|
1171
|
+
return _xml_common_allowed( [ "label", "value", "group", "checked" ] );
|
|
1172
|
+
case "RadioGroup":
|
|
1173
|
+
return _xml_common_allowed( [ "name", "value" ] );
|
|
1174
|
+
case "Select":
|
|
1175
|
+
return _xml_common_allowed( [ "value", "multiple" ] );
|
|
1176
|
+
case "Menu":
|
|
1177
|
+
return _xml_common_allowed( [ "text" ] );
|
|
1178
|
+
case "MenuItem":
|
|
1179
|
+
return _xml_common_allowed( [ "text" ] );
|
|
1180
|
+
case "Button":
|
|
1181
|
+
return _xml_common_allowed( [ "text", "variant" ] );
|
|
1182
|
+
case "Separator":
|
|
1183
|
+
return _xml_common_allowed( [ "orientation" ] );
|
|
1184
|
+
case "Slider":
|
|
1185
|
+
return _xml_common_allowed( [
|
|
1186
|
+
"value",
|
|
1187
|
+
"min",
|
|
1188
|
+
"max",
|
|
1189
|
+
"step",
|
|
1190
|
+
"orientation",
|
|
1191
|
+
"readonly",
|
|
1192
|
+
] );
|
|
1193
|
+
case "Progress":
|
|
1194
|
+
return _xml_common_allowed( [
|
|
1195
|
+
"value",
|
|
1196
|
+
"min",
|
|
1197
|
+
"max",
|
|
1198
|
+
"indeterminate",
|
|
1199
|
+
"show_text",
|
|
1200
|
+
] );
|
|
1201
|
+
case "Tabs":
|
|
1202
|
+
return _xml_common_allowed( [ "selected", "placement" ] );
|
|
1203
|
+
case "Tab":
|
|
1204
|
+
return _xml_common_allowed(
|
|
1205
|
+
[ "title", "value", "selected", "closable", "icon" ],
|
|
1206
|
+
);
|
|
1207
|
+
case "ListView":
|
|
1208
|
+
return _xml_common_allowed( [ "selected_index", "multiple" ] );
|
|
1209
|
+
case "TreeView":
|
|
1210
|
+
return _xml_common_allowed( [ "selected_path", "multiple" ] );
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
_xml_error( "GUI_XML_STRUCTURE", `unsupported GUI XML element '${tag}'` );
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
function _xml_bool_attrs ( String tag ) {
|
|
1217
|
+
return [
|
|
1218
|
+
"visible",
|
|
1219
|
+
"enabled",
|
|
1220
|
+
"disabled",
|
|
1221
|
+
"resizable",
|
|
1222
|
+
"modal",
|
|
1223
|
+
"collapsible",
|
|
1224
|
+
"collapsed",
|
|
1225
|
+
"multiline",
|
|
1226
|
+
"readonly",
|
|
1227
|
+
"wrap",
|
|
1228
|
+
"password",
|
|
1229
|
+
"required",
|
|
1230
|
+
"checked",
|
|
1231
|
+
"indeterminate",
|
|
1232
|
+
"multiple",
|
|
1233
|
+
"show_text",
|
|
1234
|
+
"selected",
|
|
1235
|
+
"closable",
|
|
1236
|
+
];
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
function _xml_number_attrs ( String tag ) {
|
|
1240
|
+
return [
|
|
1241
|
+
"width",
|
|
1242
|
+
"height",
|
|
1243
|
+
"minwidth",
|
|
1244
|
+
"minheight",
|
|
1245
|
+
"maxwidth",
|
|
1246
|
+
"maxheight",
|
|
1247
|
+
"gap",
|
|
1248
|
+
"padding",
|
|
1249
|
+
"first_day_of_week",
|
|
1250
|
+
"selected_index",
|
|
1251
|
+
"value",
|
|
1252
|
+
"min",
|
|
1253
|
+
"max",
|
|
1254
|
+
"step",
|
|
1255
|
+
];
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
function _xml_bool ( String tag, String attr, String raw ) {
|
|
1259
|
+
switch ( lc(raw): eq ) {
|
|
1260
|
+
case "true", "1", "yes", "on": return true;
|
|
1261
|
+
case "false", "0", "no", "off": return false;
|
|
1262
|
+
}
|
|
1263
|
+
_xml_error(
|
|
1264
|
+
"GUI_XML_ATTR_TYPE",
|
|
1265
|
+
`${tag}.${attr} expects a boolean XML attribute`,
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
function _xml_number ( String tag, String attr, String raw ) {
|
|
1270
|
+
if ( not ( raw ~ /^-?[0-9]+(\.[0-9]+)?$/ ) ) {
|
|
1271
|
+
_xml_error(
|
|
1272
|
+
"GUI_XML_ATTR_TYPE",
|
|
1273
|
+
`${tag}.${attr} expects a numeric XML attribute`,
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
return 0 + raw;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
function _xml_int_list ( String tag, String attr, String raw ) {
|
|
1280
|
+
let out := [];
|
|
1281
|
+
return out if raw eq "";
|
|
1282
|
+
for ( let part in split( raw, "," ) ) {
|
|
1283
|
+
let item := trim(part);
|
|
1284
|
+
if ( not ( item ~ /^-?[0-9]+$/ ) ) {
|
|
1285
|
+
_xml_error(
|
|
1286
|
+
"GUI_XML_ATTR_TYPE",
|
|
1287
|
+
`${tag}.${attr} expects comma-separated integers`,
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
out.push( 0 + item );
|
|
1291
|
+
}
|
|
1292
|
+
return out;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
function _xml_coerce_attr ( String tag, String attr, String raw ) {
|
|
1296
|
+
if ( attr eq "selected" and tag eq "Tabs" ) {
|
|
1297
|
+
return raw;
|
|
1298
|
+
}
|
|
1299
|
+
if ( attr eq "value" and tag ∉ [ "Slider", "Progress" ] ) {
|
|
1300
|
+
return raw;
|
|
1301
|
+
}
|
|
1302
|
+
if ( attr eq "min" and tag eq "DatePicker" ) {
|
|
1303
|
+
return raw;
|
|
1304
|
+
}
|
|
1305
|
+
if ( attr eq "max" and tag eq "DatePicker" ) {
|
|
1306
|
+
return raw;
|
|
1307
|
+
}
|
|
1308
|
+
if ( attr eq "selected_path" ) {
|
|
1309
|
+
return _xml_int_list( tag, attr, raw );
|
|
1310
|
+
}
|
|
1311
|
+
if ( attr ∈ _xml_bool_attrs(tag) ) {
|
|
1312
|
+
return _xml_bool( tag, attr, raw );
|
|
1313
|
+
}
|
|
1314
|
+
if ( attr ∈ _xml_number_attrs(tag) ) {
|
|
1315
|
+
return _xml_number( tag, attr, raw );
|
|
1316
|
+
}
|
|
1317
|
+
return raw;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
function _xml_attrs ( node ) {
|
|
1321
|
+
let tag := _xml_tag_name(node);
|
|
1322
|
+
let props := {};
|
|
1323
|
+
let meta := {};
|
|
1324
|
+
let meta_keys := [];
|
|
1325
|
+
let style := {};
|
|
1326
|
+
let style_keys := [];
|
|
1327
|
+
let allowed := _xml_allowed_attrs(tag);
|
|
1328
|
+
|
|
1329
|
+
for ( let attr in node.attributeNames() ) {
|
|
1330
|
+
next if attr eq "xmlns";
|
|
1331
|
+
next if substr( attr, 0, 6 ) eq "xmlns:";
|
|
1332
|
+
let value := node.getAttribute(attr);
|
|
1333
|
+
if ( substr( attr, 0, 5 ) eq "meta." ) {
|
|
1334
|
+
let key := substr( attr, 5 );
|
|
1335
|
+
_xml_error( "GUI_XML_ATTR_UNKNOWN", "empty meta attribute name" )
|
|
1336
|
+
if key eq "";
|
|
1337
|
+
meta{(key)} := value;
|
|
1338
|
+
meta_keys.push(key);
|
|
1339
|
+
next;
|
|
1340
|
+
}
|
|
1341
|
+
if ( substr( attr, 0, 6 ) eq "style." ) {
|
|
1342
|
+
let key := substr( attr, 6 );
|
|
1343
|
+
_xml_error( "GUI_XML_ATTR_UNKNOWN", "empty style attribute name" )
|
|
1344
|
+
if key eq "";
|
|
1345
|
+
style{(key)} := value;
|
|
1346
|
+
style_keys.push(key);
|
|
1347
|
+
next;
|
|
1348
|
+
}
|
|
1349
|
+
if ( attr ∉ allowed ) {
|
|
1350
|
+
_xml_error(
|
|
1351
|
+
"GUI_XML_ATTR_UNKNOWN",
|
|
1352
|
+
`${tag} does not accept XML attribute '${attr}'`,
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
props{(attr)} := _xml_coerce_attr( tag, attr, value );
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
return {
|
|
1359
|
+
props: props,
|
|
1360
|
+
meta: meta,
|
|
1361
|
+
meta_keys: meta_keys,
|
|
1362
|
+
style: style,
|
|
1363
|
+
style_keys: style_keys,
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
function _xml_apply_meta ( Widget widget, Dict meta, Array keys ) {
|
|
1368
|
+
for ( let key in keys ) {
|
|
1369
|
+
widget.meta( key, meta{(key)} );
|
|
1370
|
+
}
|
|
1371
|
+
if ( keys.length() > 0 ) {
|
|
1372
|
+
widget.meta( "__xml_meta_keys", keys );
|
|
1373
|
+
}
|
|
1374
|
+
return widget;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
function _xml_apply_style ( Widget widget, Dict style, Array keys ) {
|
|
1378
|
+
for ( let key in keys ) {
|
|
1379
|
+
widget.style( key, style{(key)} );
|
|
1380
|
+
}
|
|
1381
|
+
if ( keys.length() > 0 ) {
|
|
1382
|
+
widget.meta( "__xml_style_keys", keys );
|
|
1383
|
+
}
|
|
1384
|
+
return widget;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
function _xml_widget_from_node ( node ) {
|
|
1388
|
+
_xml_assert_namespace(node);
|
|
1389
|
+
|
|
1390
|
+
let tag := _xml_tag_name(node);
|
|
1391
|
+
let child_widgets := [];
|
|
1392
|
+
for ( let child in node.children() ) {
|
|
1393
|
+
child_widgets.push( _xml_widget_from_node(child) );
|
|
1394
|
+
}
|
|
1395
|
+
let parsed := _xml_attrs(node);
|
|
1396
|
+
let p := parsed{props};
|
|
1397
|
+
let widget;
|
|
1398
|
+
|
|
1399
|
+
switch ( tag: eq ) {
|
|
1400
|
+
case "Window":
|
|
1401
|
+
widget := new _WindowClass(
|
|
1402
|
+
id: p.get( "id", null ),
|
|
1403
|
+
title: p.get( "title", "" ),
|
|
1404
|
+
width: p.get( "width", 800 ),
|
|
1405
|
+
height: p.get( "height", 600 ),
|
|
1406
|
+
resizable: p.get( "resizable", true ),
|
|
1407
|
+
modal: p.get( "modal", false ),
|
|
1408
|
+
visible: p.get( "visible", true ),
|
|
1409
|
+
enabled: p.get( "enabled", true ),
|
|
1410
|
+
disabled: p.get( "disabled", false ),
|
|
1411
|
+
children: child_widgets,
|
|
1412
|
+
);
|
|
1413
|
+
case "VBox":
|
|
1414
|
+
widget := new _VBoxClass(
|
|
1415
|
+
id: p.get( "id", null ),
|
|
1416
|
+
align: p.get( "align", "top" ),
|
|
1417
|
+
gap: p.get( "gap", 0 ),
|
|
1418
|
+
padding: p.get( "padding", 0 ),
|
|
1419
|
+
visible: p.get( "visible", true ),
|
|
1420
|
+
enabled: p.get( "enabled", true ),
|
|
1421
|
+
disabled: p.get( "disabled", false ),
|
|
1422
|
+
children: child_widgets,
|
|
1423
|
+
);
|
|
1424
|
+
case "HBox":
|
|
1425
|
+
widget := new _HBoxClass(
|
|
1426
|
+
id: p.get( "id", null ),
|
|
1427
|
+
align: p.get( "align", "left" ),
|
|
1428
|
+
gap: p.get( "gap", 0 ),
|
|
1429
|
+
padding: p.get( "padding", 0 ),
|
|
1430
|
+
visible: p.get( "visible", true ),
|
|
1431
|
+
enabled: p.get( "enabled", true ),
|
|
1432
|
+
disabled: p.get( "disabled", false ),
|
|
1433
|
+
children: child_widgets,
|
|
1434
|
+
);
|
|
1435
|
+
case "Frame":
|
|
1436
|
+
widget := new _FrameClass(
|
|
1437
|
+
id: p.get( "id", null ),
|
|
1438
|
+
label: p.get( "label", "" ),
|
|
1439
|
+
collapsible: p.get( "collapsible", false ),
|
|
1440
|
+
collapsed: p.get( "collapsed", false ),
|
|
1441
|
+
visible: p.get( "visible", true ),
|
|
1442
|
+
enabled: p.get( "enabled", true ),
|
|
1443
|
+
disabled: p.get( "disabled", false ),
|
|
1444
|
+
children: child_widgets,
|
|
1445
|
+
);
|
|
1446
|
+
case "Label":
|
|
1447
|
+
widget := Label(
|
|
1448
|
+
id: p.get( "id", null ),
|
|
1449
|
+
text: p.get( "text", "" ),
|
|
1450
|
+
("for"): p.get( "for", null ),
|
|
1451
|
+
visible: p.get( "visible", true ),
|
|
1452
|
+
enabled: p.get( "enabled", true ),
|
|
1453
|
+
disabled: p.get( "disabled", false ),
|
|
1454
|
+
);
|
|
1455
|
+
case "Text":
|
|
1456
|
+
widget := Text(
|
|
1457
|
+
id: p.get( "id", null ),
|
|
1458
|
+
value: p.get( "value", "" ),
|
|
1459
|
+
multiline: p.get( "multiline", false ),
|
|
1460
|
+
readonly: p.get( "readonly", false ),
|
|
1461
|
+
wrap: p.get( "wrap", true ),
|
|
1462
|
+
visible: p.get( "visible", true ),
|
|
1463
|
+
enabled: p.get( "enabled", true ),
|
|
1464
|
+
disabled: p.get( "disabled", false ),
|
|
1465
|
+
);
|
|
1466
|
+
case "RichText":
|
|
1467
|
+
widget := RichText(
|
|
1468
|
+
id: p.get( "id", null ),
|
|
1469
|
+
value: p.get( "value", "" ),
|
|
1470
|
+
multiline: p.get( "multiline", true ),
|
|
1471
|
+
readonly: p.get( "readonly", true ),
|
|
1472
|
+
visible: p.get( "visible", true ),
|
|
1473
|
+
enabled: p.get( "enabled", true ),
|
|
1474
|
+
disabled: p.get( "disabled", false ),
|
|
1475
|
+
);
|
|
1476
|
+
case "Image":
|
|
1477
|
+
widget := Image(
|
|
1478
|
+
id: p.get( "id", null ),
|
|
1479
|
+
src: p.get( "src", "" ),
|
|
1480
|
+
alt: p.get( "alt", "" ),
|
|
1481
|
+
fit: p.get( "fit", "none" ),
|
|
1482
|
+
visible: p.get( "visible", true ),
|
|
1483
|
+
enabled: p.get( "enabled", true ),
|
|
1484
|
+
disabled: p.get( "disabled", false ),
|
|
1485
|
+
);
|
|
1486
|
+
case "Input":
|
|
1487
|
+
widget := Input(
|
|
1488
|
+
id: p.get( "id", null ),
|
|
1489
|
+
value: p.get( "value", "" ),
|
|
1490
|
+
placeholder: p.get( "placeholder", "" ),
|
|
1491
|
+
multiline: p.get( "multiline", false ),
|
|
1492
|
+
readonly: p.get( "readonly", false ),
|
|
1493
|
+
password: p.get( "password", false ),
|
|
1494
|
+
required: p.get( "required", false ),
|
|
1495
|
+
visible: p.get( "visible", true ),
|
|
1496
|
+
enabled: p.get( "enabled", true ),
|
|
1497
|
+
disabled: p.get( "disabled", false ),
|
|
1498
|
+
);
|
|
1499
|
+
case "DatePicker":
|
|
1500
|
+
widget := DatePicker(
|
|
1501
|
+
id: p.get( "id", null ),
|
|
1502
|
+
value: p.get( "value", null ),
|
|
1503
|
+
min: p.get( "min", null ),
|
|
1504
|
+
max: p.get( "max", null ),
|
|
1505
|
+
first_day_of_week: p.get( "first_day_of_week", 0 ),
|
|
1506
|
+
visible: p.get( "visible", true ),
|
|
1507
|
+
enabled: p.get( "enabled", true ),
|
|
1508
|
+
disabled: p.get( "disabled", false ),
|
|
1509
|
+
);
|
|
1510
|
+
case "Checkbox":
|
|
1511
|
+
widget := Checkbox(
|
|
1512
|
+
id: p.get( "id", null ),
|
|
1513
|
+
label: p.get( "label", "" ),
|
|
1514
|
+
checked: p.get( "checked", false ),
|
|
1515
|
+
indeterminate: p.get( "indeterminate", false ),
|
|
1516
|
+
visible: p.get( "visible", true ),
|
|
1517
|
+
enabled: p.get( "enabled", true ),
|
|
1518
|
+
disabled: p.get( "disabled", false ),
|
|
1519
|
+
);
|
|
1520
|
+
case "Radio":
|
|
1521
|
+
widget := Radio(
|
|
1522
|
+
id: p.get( "id", null ),
|
|
1523
|
+
label: p.get( "label", "" ),
|
|
1524
|
+
value: p.get( "value", "" ),
|
|
1525
|
+
group: p.get( "group", null ),
|
|
1526
|
+
checked: p.get( "checked", false ),
|
|
1527
|
+
visible: p.get( "visible", true ),
|
|
1528
|
+
enabled: p.get( "enabled", true ),
|
|
1529
|
+
disabled: p.get( "disabled", false ),
|
|
1530
|
+
);
|
|
1531
|
+
case "RadioGroup":
|
|
1532
|
+
widget := new _RadioGroupClass(
|
|
1533
|
+
id: p.get( "id", null ),
|
|
1534
|
+
name: p.get( "name", "" ),
|
|
1535
|
+
value: p.get( "value", null ),
|
|
1536
|
+
visible: p.get( "visible", true ),
|
|
1537
|
+
enabled: p.get( "enabled", true ),
|
|
1538
|
+
disabled: p.get( "disabled", false ),
|
|
1539
|
+
children: child_widgets,
|
|
1540
|
+
);
|
|
1541
|
+
case "Select":
|
|
1542
|
+
widget := Select(
|
|
1543
|
+
id: p.get( "id", null ),
|
|
1544
|
+
value: p.get( "value", null ),
|
|
1545
|
+
multiple: p.get( "multiple", false ),
|
|
1546
|
+
visible: p.get( "visible", true ),
|
|
1547
|
+
enabled: p.get( "enabled", true ),
|
|
1548
|
+
disabled: p.get( "disabled", false ),
|
|
1549
|
+
);
|
|
1550
|
+
case "Menu":
|
|
1551
|
+
widget := new _MenuClass(
|
|
1552
|
+
id: p.get( "id", null ),
|
|
1553
|
+
text: p.get( "text", "" ),
|
|
1554
|
+
visible: p.get( "visible", true ),
|
|
1555
|
+
enabled: p.get( "enabled", true ),
|
|
1556
|
+
disabled: p.get( "disabled", false ),
|
|
1557
|
+
children: child_widgets,
|
|
1558
|
+
);
|
|
1559
|
+
case "MenuItem":
|
|
1560
|
+
widget := MenuItem(
|
|
1561
|
+
id: p.get( "id", null ),
|
|
1562
|
+
text: p.get( "text", "" ),
|
|
1563
|
+
visible: p.get( "visible", true ),
|
|
1564
|
+
enabled: p.get( "enabled", true ),
|
|
1565
|
+
disabled: p.get( "disabled", false ),
|
|
1566
|
+
);
|
|
1567
|
+
case "Button":
|
|
1568
|
+
widget := Button(
|
|
1569
|
+
id: p.get( "id", null ),
|
|
1570
|
+
text: p.get( "text", "" ),
|
|
1571
|
+
variant: p.get( "variant", "default" ),
|
|
1572
|
+
visible: p.get( "visible", true ),
|
|
1573
|
+
enabled: p.get( "enabled", true ),
|
|
1574
|
+
disabled: p.get( "disabled", false ),
|
|
1575
|
+
);
|
|
1576
|
+
case "Separator":
|
|
1577
|
+
widget := Separator(
|
|
1578
|
+
id: p.get( "id", null ),
|
|
1579
|
+
orientation: p.get( "orientation", "horizontal" ),
|
|
1580
|
+
visible: p.get( "visible", true ),
|
|
1581
|
+
enabled: p.get( "enabled", true ),
|
|
1582
|
+
disabled: p.get( "disabled", false ),
|
|
1583
|
+
);
|
|
1584
|
+
case "Slider":
|
|
1585
|
+
widget := Slider(
|
|
1586
|
+
id: p.get( "id", null ),
|
|
1587
|
+
value: p.get( "value", 0 ),
|
|
1588
|
+
min: p.get( "min", 0 ),
|
|
1589
|
+
max: p.get( "max", 100 ),
|
|
1590
|
+
step: p.get( "step", 1 ),
|
|
1591
|
+
orientation: p.get( "orientation", "horizontal" ),
|
|
1592
|
+
readonly: p.get( "readonly", false ),
|
|
1593
|
+
visible: p.get( "visible", true ),
|
|
1594
|
+
enabled: p.get( "enabled", true ),
|
|
1595
|
+
disabled: p.get( "disabled", false ),
|
|
1596
|
+
);
|
|
1597
|
+
case "Progress":
|
|
1598
|
+
widget := Progress(
|
|
1599
|
+
id: p.get( "id", null ),
|
|
1600
|
+
value: p.get( "value", 0 ),
|
|
1601
|
+
min: p.get( "min", 0 ),
|
|
1602
|
+
max: p.get( "max", 100 ),
|
|
1603
|
+
indeterminate: p.get( "indeterminate", false ),
|
|
1604
|
+
show_text: p.get( "show_text", false ),
|
|
1605
|
+
visible: p.get( "visible", true ),
|
|
1606
|
+
enabled: p.get( "enabled", true ),
|
|
1607
|
+
disabled: p.get( "disabled", false ),
|
|
1608
|
+
);
|
|
1609
|
+
case "Tabs":
|
|
1610
|
+
widget := new _TabsClass(
|
|
1611
|
+
id: p.get( "id", null ),
|
|
1612
|
+
selected: p.get( "selected", null ),
|
|
1613
|
+
placement: p.get( "placement", "top" ),
|
|
1614
|
+
visible: p.get( "visible", true ),
|
|
1615
|
+
enabled: p.get( "enabled", true ),
|
|
1616
|
+
disabled: p.get( "disabled", false ),
|
|
1617
|
+
children: child_widgets,
|
|
1618
|
+
);
|
|
1619
|
+
case "Tab":
|
|
1620
|
+
widget := new _TabClass(
|
|
1621
|
+
id: p.get( "id", null ),
|
|
1622
|
+
title: p.get( "title", "" ),
|
|
1623
|
+
value: p.get( "value", "" ),
|
|
1624
|
+
selected: p.get( "selected", false ),
|
|
1625
|
+
closable: p.get( "closable", false ),
|
|
1626
|
+
icon: p.get( "icon", null ),
|
|
1627
|
+
visible: p.get( "visible", true ),
|
|
1628
|
+
enabled: p.get( "enabled", true ),
|
|
1629
|
+
disabled: p.get( "disabled", false ),
|
|
1630
|
+
children: child_widgets,
|
|
1631
|
+
);
|
|
1632
|
+
case "ListView":
|
|
1633
|
+
widget := ListView(
|
|
1634
|
+
id: p.get( "id", null ),
|
|
1635
|
+
selected_index: p.get( "selected_index", null ),
|
|
1636
|
+
multiple: p.get( "multiple", false ),
|
|
1637
|
+
visible: p.get( "visible", true ),
|
|
1638
|
+
enabled: p.get( "enabled", true ),
|
|
1639
|
+
disabled: p.get( "disabled", false ),
|
|
1640
|
+
);
|
|
1641
|
+
case "TreeView":
|
|
1642
|
+
widget := TreeView(
|
|
1643
|
+
id: p.get( "id", null ),
|
|
1644
|
+
selected_path: p.get( "selected_path", [] ),
|
|
1645
|
+
multiple: p.get( "multiple", false ),
|
|
1646
|
+
visible: p.get( "visible", true ),
|
|
1647
|
+
enabled: p.get( "enabled", true ),
|
|
1648
|
+
disabled: p.get( "disabled", false ),
|
|
1649
|
+
);
|
|
1650
|
+
default:
|
|
1651
|
+
_xml_error(
|
|
1652
|
+
"GUI_XML_STRUCTURE",
|
|
1653
|
+
`unsupported GUI XML element '${tag}'`,
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
_xml_apply_meta( widget, parsed{meta}, parsed{meta_keys} );
|
|
1658
|
+
return _xml_apply_style( widget, parsed{style}, parsed{style_keys} );
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
function gui_from_xml ( String xml ) {
|
|
1662
|
+
return _xml_widget_from_node( XML.parse(xml).documentElement() );
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
function gui_from_xml_file ( path ) {
|
|
1666
|
+
die "XML.load is denied by runtime policy" if __system__{deny_fs};
|
|
1667
|
+
from std/io import Path;
|
|
1668
|
+
let file := path instanceof Path ? path : new Path(path);
|
|
1669
|
+
return _xml_widget_from_node( XML.load(file).documentElement() );
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
function _xml_tag_for_widget ( Widget widget ) {
|
|
1673
|
+
if ( widget instanceof _WindowClass ) { return "Window"; }
|
|
1674
|
+
if ( widget instanceof _VBoxClass ) { return "VBox"; }
|
|
1675
|
+
if ( widget instanceof _HBoxClass ) { return "HBox"; }
|
|
1676
|
+
if ( widget instanceof _FrameClass ) { return "Frame"; }
|
|
1677
|
+
if ( widget instanceof _LabelClass ) { return "Label"; }
|
|
1678
|
+
if ( widget instanceof _TextClass ) { return "Text"; }
|
|
1679
|
+
if ( widget instanceof _RichTextClass ) { return "RichText"; }
|
|
1680
|
+
if ( widget instanceof _ImageClass ) { return "Image"; }
|
|
1681
|
+
if ( widget instanceof _InputClass ) { return "Input"; }
|
|
1682
|
+
if ( widget instanceof _DatePickerClass ) { return "DatePicker"; }
|
|
1683
|
+
if ( widget instanceof _CheckboxClass ) { return "Checkbox"; }
|
|
1684
|
+
if ( widget instanceof _RadioClass ) { return "Radio"; }
|
|
1685
|
+
if ( widget instanceof _RadioGroupClass ) { return "RadioGroup"; }
|
|
1686
|
+
if ( widget instanceof _SelectClass ) { return "Select"; }
|
|
1687
|
+
if ( widget instanceof _MenuClass ) { return "Menu"; }
|
|
1688
|
+
if ( widget instanceof _MenuItemClass ) { return "MenuItem"; }
|
|
1689
|
+
if ( widget instanceof _ButtonClass ) { return "Button"; }
|
|
1690
|
+
if ( widget instanceof _SeparatorClass ) { return "Separator"; }
|
|
1691
|
+
if ( widget instanceof _SliderClass ) { return "Slider"; }
|
|
1692
|
+
if ( widget instanceof _ProgressClass ) { return "Progress"; }
|
|
1693
|
+
if ( widget instanceof _TabsClass ) { return "Tabs"; }
|
|
1694
|
+
if ( widget instanceof _TabClass ) { return "Tab"; }
|
|
1695
|
+
if ( widget instanceof _ListViewClass ) { return "ListView"; }
|
|
1696
|
+
if ( widget instanceof _TreeViewClass ) { return "TreeView"; }
|
|
1697
|
+
_xml_error( "GUI_XML_STRUCTURE", "unsupported widget for gui_to_xml" );
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
function _xml_attr ( String name, value ) {
|
|
1701
|
+
return "" if value ≡ null;
|
|
1702
|
+
return ` ${name}="${escape_xml(value)}"`;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
function _xml_attr_if ( String name, value, fallback ) {
|
|
1706
|
+
return "" if value ≡ fallback;
|
|
1707
|
+
return _xml_attr( name, value );
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
function _xml_bool_attr_if ( String name, value, fallback ) {
|
|
1711
|
+
let normalized := value ? true : false;
|
|
1712
|
+
let normalized_fallback := fallback ? true : false;
|
|
1713
|
+
return "" if normalized ≡ normalized_fallback;
|
|
1714
|
+
return _xml_attr( name, normalized ? "true" : "false" );
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
function _xml_attr_nonempty ( String name, value ) {
|
|
1718
|
+
return "" if value ≡ null or value eq "";
|
|
1719
|
+
return _xml_attr( name, value );
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
function _xml_join_ints ( Array values ) {
|
|
1723
|
+
let out := [];
|
|
1724
|
+
for ( let value in values ) {
|
|
1725
|
+
out.push( "" _ value );
|
|
1726
|
+
}
|
|
1727
|
+
return join( ",", out );
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
function _xml_meta_attrs ( Widget widget ) {
|
|
1731
|
+
let keys := widget.meta( "__xml_meta_keys" ) ?: [];
|
|
1732
|
+
let out := "";
|
|
1733
|
+
for ( let key in keys ) {
|
|
1734
|
+
out _= _xml_attr( "meta." _ key, widget.meta(key) );
|
|
1735
|
+
}
|
|
1736
|
+
return out;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
function _xml_style_attrs ( Widget widget ) {
|
|
1740
|
+
let keys := widget.meta( "__xml_style_keys" ) ?: [];
|
|
1741
|
+
let out := "";
|
|
1742
|
+
for ( let key in keys ) {
|
|
1743
|
+
out _= _xml_attr( "style." _ key, widget.style(key) );
|
|
1744
|
+
}
|
|
1745
|
+
return out;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
function _xml_common_attrs ( Widget widget ) {
|
|
1749
|
+
let out := "";
|
|
1750
|
+
out _= _xml_attr( "id", widget.id() ) if widget.id() ≢ null;
|
|
1751
|
+
out _= _xml_bool_attr_if( "visible", widget.visible(), true );
|
|
1752
|
+
out _= _xml_bool_attr_if( "disabled", not widget.enabled(), false );
|
|
1753
|
+
out _= _xml_meta_attrs(widget);
|
|
1754
|
+
out _= _xml_style_attrs(widget);
|
|
1755
|
+
return out;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
function _xml_widget_attrs ( Widget widget ) {
|
|
1759
|
+
let out := _xml_common_attrs(widget);
|
|
1760
|
+
if ( widget instanceof _WindowClass ) {
|
|
1761
|
+
out _= _xml_attr_if( "title", widget.title(), "" );
|
|
1762
|
+
}
|
|
1763
|
+
else if ( widget instanceof _VBoxClass or widget instanceof _HBoxClass ) {
|
|
1764
|
+
let default_align := widget instanceof _VBoxClass ? "top" : "left";
|
|
1765
|
+
out _= _xml_attr_if( "align", widget.align(), default_align );
|
|
1766
|
+
out _= _xml_attr_if( "gap", widget.gap(), 0 );
|
|
1767
|
+
out _= _xml_attr_if( "padding", widget.padding(), 0 )
|
|
1768
|
+
unless widget.padding() instanceof Array;
|
|
1769
|
+
}
|
|
1770
|
+
else if ( widget instanceof _FrameClass ) {
|
|
1771
|
+
out _= _xml_attr_if( "label", widget.label(), "" );
|
|
1772
|
+
out _= _xml_bool_attr_if( "collapsible", widget.collapsible(), false );
|
|
1773
|
+
out _= _xml_bool_attr_if( "collapsed", widget.collapsed(), false );
|
|
1774
|
+
}
|
|
1775
|
+
else if ( widget instanceof _LabelClass ) {
|
|
1776
|
+
out _= _xml_attr_if( "text", widget.text(), "" );
|
|
1777
|
+
out _= _xml_attr_nonempty( "for", widget.for_id() );
|
|
1778
|
+
}
|
|
1779
|
+
else if ( widget instanceof _TextClass ) {
|
|
1780
|
+
out _= _xml_attr_if( "value", widget.value(), "" );
|
|
1781
|
+
out _= _xml_bool_attr_if( "multiline", widget.multiline(), false );
|
|
1782
|
+
out _= _xml_bool_attr_if( "readonly", widget.readonly(), false );
|
|
1783
|
+
out _= _xml_bool_attr_if( "wrap", widget.wrap(), true );
|
|
1784
|
+
}
|
|
1785
|
+
else if ( widget instanceof _RichTextClass ) {
|
|
1786
|
+
out _= _xml_attr_if( "value", widget.value(), "" );
|
|
1787
|
+
out _= _xml_bool_attr_if( "multiline", widget.multiline(), true );
|
|
1788
|
+
out _= _xml_bool_attr_if( "readonly", widget.readonly(), true );
|
|
1789
|
+
}
|
|
1790
|
+
else if ( widget instanceof _ImageClass ) {
|
|
1791
|
+
out _= _xml_attr_if( "src", widget.src(), "" );
|
|
1792
|
+
out _= _xml_attr_if( "alt", widget.alt(), "" );
|
|
1793
|
+
out _= _xml_attr_if( "fit", widget.fit(), "none" );
|
|
1794
|
+
}
|
|
1795
|
+
else if ( widget instanceof _InputClass ) {
|
|
1796
|
+
out _= _xml_attr_if( "value", widget.value(), "" );
|
|
1797
|
+
out _= _xml_attr_if( "placeholder", widget.placeholder(), "" );
|
|
1798
|
+
out _= _xml_bool_attr_if( "multiline", widget.multiline(), false );
|
|
1799
|
+
out _= _xml_bool_attr_if( "readonly", widget.readonly(), false );
|
|
1800
|
+
out _= _xml_bool_attr_if( "password", widget.password(), false );
|
|
1801
|
+
out _= _xml_bool_attr_if( "required", widget.required(), false );
|
|
1802
|
+
}
|
|
1803
|
+
else if ( widget instanceof _DatePickerClass ) {
|
|
1804
|
+
out _= _xml_attr( "value", widget.value() );
|
|
1805
|
+
out _= _xml_attr( "min", widget.min() ) if widget.min() ≢ null;
|
|
1806
|
+
out _= _xml_attr( "max", widget.max() ) if widget.max() ≢ null;
|
|
1807
|
+
out _= _xml_attr_if(
|
|
1808
|
+
"first_day_of_week",
|
|
1809
|
+
widget.first_day_of_week(),
|
|
1810
|
+
0,
|
|
1811
|
+
);
|
|
1812
|
+
}
|
|
1813
|
+
else if ( widget instanceof _CheckboxClass ) {
|
|
1814
|
+
out _= _xml_attr_if( "label", widget.label(), "" );
|
|
1815
|
+
out _= _xml_bool_attr_if( "checked", widget.checked(), false );
|
|
1816
|
+
out _= _xml_bool_attr_if( "indeterminate", widget.indeterminate(), false );
|
|
1817
|
+
}
|
|
1818
|
+
else if ( widget instanceof _RadioClass ) {
|
|
1819
|
+
out _= _xml_attr_if( "label", widget.label(), "" );
|
|
1820
|
+
out _= _xml_attr_if( "value", widget.value(), "" );
|
|
1821
|
+
out _= _xml_attr_nonempty( "group", widget.group() );
|
|
1822
|
+
out _= _xml_bool_attr_if( "checked", widget.checked(), false );
|
|
1823
|
+
}
|
|
1824
|
+
else if ( widget instanceof _RadioGroupClass ) {
|
|
1825
|
+
out _= _xml_attr_if( "name", widget.name(), "" );
|
|
1826
|
+
out _= _xml_attr( "value", widget.value() ) if widget.value() ≢ null;
|
|
1827
|
+
}
|
|
1828
|
+
else if ( widget instanceof _SelectClass ) {
|
|
1829
|
+
out _= _xml_attr( "value", widget.value() ) if widget.value() ≢ null;
|
|
1830
|
+
out _= _xml_bool_attr_if( "multiple", widget.multiple(), false );
|
|
1831
|
+
}
|
|
1832
|
+
else if ( widget instanceof _MenuClass ) {
|
|
1833
|
+
out _= _xml_attr_if( "text", widget.text(), "" );
|
|
1834
|
+
}
|
|
1835
|
+
else if ( widget instanceof _MenuItemClass ) {
|
|
1836
|
+
out _= _xml_attr_if( "text", widget.text(), "" );
|
|
1837
|
+
}
|
|
1838
|
+
else if ( widget instanceof _ButtonClass ) {
|
|
1839
|
+
out _= _xml_attr_if( "text", widget.text(), "" );
|
|
1840
|
+
out _= _xml_attr_if( "variant", widget.variant(), "default" );
|
|
1841
|
+
}
|
|
1842
|
+
else if ( widget instanceof _SeparatorClass ) {
|
|
1843
|
+
out _= _xml_attr_if( "orientation", widget.orientation(), "horizontal" );
|
|
1844
|
+
}
|
|
1845
|
+
else if ( widget instanceof _SliderClass ) {
|
|
1846
|
+
out _= _xml_attr_if( "value", widget.value(), 0 );
|
|
1847
|
+
out _= _xml_attr_if( "min", widget.min(), 0 );
|
|
1848
|
+
out _= _xml_attr_if( "max", widget.max(), 100 );
|
|
1849
|
+
out _= _xml_attr_if( "step", widget.step(), 1 );
|
|
1850
|
+
out _= _xml_attr_if( "orientation", widget.orientation(), "horizontal" );
|
|
1851
|
+
out _= _xml_bool_attr_if( "readonly", widget.readonly(), false );
|
|
1852
|
+
}
|
|
1853
|
+
else if ( widget instanceof _ProgressClass ) {
|
|
1854
|
+
out _= _xml_attr_if( "value", widget.value(), 0 );
|
|
1855
|
+
out _= _xml_attr_if( "min", widget.min(), 0 );
|
|
1856
|
+
out _= _xml_attr_if( "max", widget.max(), 100 );
|
|
1857
|
+
out _= _xml_bool_attr_if( "indeterminate", widget.indeterminate(), false );
|
|
1858
|
+
out _= _xml_bool_attr_if( "show_text", widget.show_text(), false );
|
|
1859
|
+
}
|
|
1860
|
+
else if ( widget instanceof _TabsClass ) {
|
|
1861
|
+
out _= _xml_attr( "selected", widget.selected() )
|
|
1862
|
+
if widget.selected() ≢ null;
|
|
1863
|
+
out _= _xml_attr_if( "placement", widget.placement(), "top" );
|
|
1864
|
+
}
|
|
1865
|
+
else if ( widget instanceof _TabClass ) {
|
|
1866
|
+
out _= _xml_attr_if( "title", widget.title(), "" );
|
|
1867
|
+
out _= _xml_attr_if( "value", widget.value(), "" );
|
|
1868
|
+
out _= _xml_attr( "icon", widget.icon() ) if widget.icon() ≢ null;
|
|
1869
|
+
out _= _xml_bool_attr_if( "selected", widget.selected(), false );
|
|
1870
|
+
out _= _xml_bool_attr_if( "closable", widget.closable(), false );
|
|
1871
|
+
}
|
|
1872
|
+
else if ( widget instanceof _ListViewClass ) {
|
|
1873
|
+
out _= _xml_attr( "selected_index", widget.selected_index() )
|
|
1874
|
+
if widget.selected_index() ≢ null;
|
|
1875
|
+
out _= _xml_bool_attr_if( "multiple", widget.multiple(), false );
|
|
1876
|
+
}
|
|
1877
|
+
else if ( widget instanceof _TreeViewClass ) {
|
|
1878
|
+
let selected_path := widget.selected_path();
|
|
1879
|
+
out _= _xml_attr( "selected_path", _xml_join_ints(selected_path) )
|
|
1880
|
+
if selected_path.length() > 0;
|
|
1881
|
+
out _= _xml_bool_attr_if( "multiple", widget.multiple(), false );
|
|
1882
|
+
}
|
|
1883
|
+
return out;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
function _xml_serialize_widget ( Widget widget, Number depth ) {
|
|
1887
|
+
let indent := "";
|
|
1888
|
+
let i := 0;
|
|
1889
|
+
while ( i < depth ) {
|
|
1890
|
+
indent _= "\t";
|
|
1891
|
+
i++;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
let tag := _xml_tag_for_widget(widget);
|
|
1895
|
+
let attrs := _xml_widget_attrs(widget);
|
|
1896
|
+
attrs _= _xml_attr( "xmlns", GUI_XML_NS ) if depth = 0;
|
|
1897
|
+
let children := widget.children();
|
|
1898
|
+
if ( children.length() = 0 ) {
|
|
1899
|
+
return indent _ "<" _ tag _ attrs _ " />";
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
let parts := [];
|
|
1903
|
+
for ( let child in children ) {
|
|
1904
|
+
parts.push( _xml_serialize_widget( child, depth + 1 ) );
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
return indent _ "<" _ tag _ attrs _ ">\n"
|
|
1908
|
+
_ join( "\n", parts )
|
|
1909
|
+
_ "\n" _ indent _ "</" _ tag _ ">";
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
function gui_to_xml ( Widget root ) {
|
|
1913
|
+
return _xml_serialize_widget( root, 0 ) _ "\n";
|
|
1914
|
+
}
|