slint-ui 1.9.0-nightly.2024092723 → 1.9.0-nightly.2024100207
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/Cargo.toml +5 -4
- package/README.md +1 -0
- package/biome.json +2 -2
- package/{index.d.ts → dist/index.d.ts} +147 -309
- package/{index.js → dist/index.js} +167 -384
- package/dist/models.d.ts +169 -0
- package/dist/models.js +235 -0
- package/package.json +12 -10
- package/{src → rust}/interpreter/component_instance.rs +52 -12
- package/{src → rust}/interpreter/value.rs +22 -2
- package/{src → rust}/lib.rs +40 -2
- package/{src → rust}/types/model.rs +13 -3
- package/tsconfig.json +2 -1
- package/{index.ts → typescript/index.ts} +166 -431
- package/typescript/models.ts +278 -0
- /package/{src → rust}/interpreter/component_compiler.rs +0 -0
- /package/{src → rust}/interpreter/component_definition.rs +0 -0
- /package/{src → rust}/interpreter/diagnostic.rs +0 -0
- /package/{src → rust}/interpreter/window.rs +0 -0
- /package/{src → rust}/interpreter.rs +0 -0
- /package/{src → rust}/types/brush.rs +0 -0
- /package/{src → rust}/types/image_data.rs +0 -0
- /package/{src → rust}/types/point.rs +0 -0
- /package/{src → rust}/types/size.rs +0 -0
- /package/{src → rust}/types.rs +0 -0
package/dist/models.d.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as napi from "../rust-module.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Model<T> is the interface for feeding dynamic data into
|
|
4
|
+
* `.slint` views.
|
|
5
|
+
*
|
|
6
|
+
* A model is organized like a table with rows of data. The
|
|
7
|
+
* fields of the data type T behave like columns.
|
|
8
|
+
*
|
|
9
|
+
* @template T the type of the model's items.
|
|
10
|
+
*
|
|
11
|
+
* ### Example
|
|
12
|
+
* As an example let's see the implementation of {@link ArrayModel}
|
|
13
|
+
*
|
|
14
|
+
* ```js
|
|
15
|
+
* export class ArrayModel<T> extends Model<T> {
|
|
16
|
+
* private a: Array<T>
|
|
17
|
+
*
|
|
18
|
+
* constructor(arr: Array<T>) {
|
|
19
|
+
* super();
|
|
20
|
+
* this.a = arr;
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* rowCount() {
|
|
24
|
+
* return this.a.length;
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* rowData(row: number) {
|
|
28
|
+
* return this.a[row];
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* setRowData(row: number, data: T) {
|
|
32
|
+
* this.a[row] = data;
|
|
33
|
+
* this.notifyRowDataChanged(row);
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* push(...values: T[]) {
|
|
37
|
+
* let size = this.a.length;
|
|
38
|
+
* Array.prototype.push.apply(this.a, values);
|
|
39
|
+
* this.notifyRowAdded(size, arguments.length);
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* remove(index: number, size: number) {
|
|
43
|
+
* let r = this.a.splice(index, size);
|
|
44
|
+
* this.notifyRowRemoved(index, size);
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* get length(): number {
|
|
48
|
+
* return this.a.length;
|
|
49
|
+
* }
|
|
50
|
+
*
|
|
51
|
+
* values(): IterableIterator<T> {
|
|
52
|
+
* return this.a.values();
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* entries(): IterableIterator<[number, T]> {
|
|
56
|
+
* return this.a.entries()
|
|
57
|
+
* }
|
|
58
|
+
*}
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare abstract class Model<T> implements Iterable<T> {
|
|
62
|
+
/**
|
|
63
|
+
* @hidden
|
|
64
|
+
*/
|
|
65
|
+
modelNotify: napi.ExternalObject<napi.SharedModelNotify>;
|
|
66
|
+
/**
|
|
67
|
+
* @hidden
|
|
68
|
+
*/
|
|
69
|
+
constructor(modelNotify?: napi.ExternalObject<napi.SharedModelNotify>);
|
|
70
|
+
/**
|
|
71
|
+
* Implementations of this function must return the current number of rows.
|
|
72
|
+
*/
|
|
73
|
+
abstract rowCount(): number;
|
|
74
|
+
/**
|
|
75
|
+
* Implementations of this function must return the data at the specified row.
|
|
76
|
+
* @param row index in range 0..(rowCount() - 1).
|
|
77
|
+
* @returns undefined if row is out of range otherwise the data.
|
|
78
|
+
*/
|
|
79
|
+
abstract rowData(row: number): T | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Implementations of this function must store the provided data parameter
|
|
82
|
+
* in the model at the specified row.
|
|
83
|
+
* @param _row index in range 0..(rowCount() - 1).
|
|
84
|
+
* @param _data new data item to store on the given row index
|
|
85
|
+
*/
|
|
86
|
+
setRowData(_row: number, _data: T): void;
|
|
87
|
+
[Symbol.iterator](): Iterator<T>;
|
|
88
|
+
/**
|
|
89
|
+
* Notifies the view that the data of the current row is changed.
|
|
90
|
+
* @param row index of the changed row.
|
|
91
|
+
*/
|
|
92
|
+
protected notifyRowDataChanged(row: number): void;
|
|
93
|
+
/**
|
|
94
|
+
* Notifies the view that multiple rows are added to the model.
|
|
95
|
+
* @param row index of the first added row.
|
|
96
|
+
* @param count the number of added items.
|
|
97
|
+
*/
|
|
98
|
+
protected notifyRowAdded(row: number, count: number): void;
|
|
99
|
+
/**
|
|
100
|
+
* Notifies the view that multiple rows are removed to the model.
|
|
101
|
+
* @param row index of the first removed row.
|
|
102
|
+
* @param count the number of removed items.
|
|
103
|
+
*/
|
|
104
|
+
protected notifyRowRemoved(row: number, count: number): void;
|
|
105
|
+
/**
|
|
106
|
+
* Notifies the view that the complete data must be reload.
|
|
107
|
+
*/
|
|
108
|
+
protected notifyReset(): void;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* ArrayModel wraps a JavaScript array for use in `.slint` views. The underlying
|
|
112
|
+
* array can be modified with the [[ArrayModel.push]] and [[ArrayModel.remove]] methods.
|
|
113
|
+
*/
|
|
114
|
+
export declare class ArrayModel<T> extends Model<T> {
|
|
115
|
+
#private;
|
|
116
|
+
/**
|
|
117
|
+
* Creates a new ArrayModel.
|
|
118
|
+
*
|
|
119
|
+
* @param arr
|
|
120
|
+
*/
|
|
121
|
+
constructor(arr: Array<T>);
|
|
122
|
+
/**
|
|
123
|
+
* Returns the number of entries in the array model.
|
|
124
|
+
*/
|
|
125
|
+
get length(): number;
|
|
126
|
+
/**
|
|
127
|
+
* Returns the number of entries in the array model.
|
|
128
|
+
*/
|
|
129
|
+
rowCount(): number;
|
|
130
|
+
/**
|
|
131
|
+
* Returns the data at the specified row.
|
|
132
|
+
* @param row index in range 0..(rowCount() - 1).
|
|
133
|
+
* @returns undefined if row is out of range otherwise the data.
|
|
134
|
+
*/
|
|
135
|
+
rowData(row: number): T;
|
|
136
|
+
/**
|
|
137
|
+
* Stores the given data on the given row index and notifies run-time about the changed row.
|
|
138
|
+
* @param row index in range 0..(rowCount() - 1).
|
|
139
|
+
* @param data new data item to store on the given row index
|
|
140
|
+
*/
|
|
141
|
+
setRowData(row: number, data: T): void;
|
|
142
|
+
/**
|
|
143
|
+
* Pushes new values to the array that's backing the model and notifies
|
|
144
|
+
* the run-time about the added rows.
|
|
145
|
+
* @param values list of values that will be pushed to the array.
|
|
146
|
+
*/
|
|
147
|
+
push(...values: T[]): void;
|
|
148
|
+
/**
|
|
149
|
+
* Removes the last element from the array and returns it.
|
|
150
|
+
*
|
|
151
|
+
* @returns The removed element or undefined if the array is empty.
|
|
152
|
+
*/
|
|
153
|
+
pop(): T | undefined;
|
|
154
|
+
/**
|
|
155
|
+
* Removes the specified number of element from the array that's backing
|
|
156
|
+
* the model, starting at the specified index.
|
|
157
|
+
* @param index index of first row to remove.
|
|
158
|
+
* @param size number of rows to remove.
|
|
159
|
+
*/
|
|
160
|
+
remove(index: number, size: number): void;
|
|
161
|
+
/**
|
|
162
|
+
* Returns an iterable of values in the array.
|
|
163
|
+
*/
|
|
164
|
+
values(): IterableIterator<T>;
|
|
165
|
+
/**
|
|
166
|
+
* Returns an iterable of key, value pairs for every entry in the array.
|
|
167
|
+
*/
|
|
168
|
+
entries(): IterableIterator<[number, T]>;
|
|
169
|
+
}
|
package/dist/models.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
3
|
+
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.ArrayModel = exports.Model = void 0;
|
|
6
|
+
const napi = require("../rust-module.cjs");
|
|
7
|
+
class ModelIterator {
|
|
8
|
+
row;
|
|
9
|
+
model;
|
|
10
|
+
constructor(model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
this.row = 0;
|
|
13
|
+
}
|
|
14
|
+
next() {
|
|
15
|
+
if (this.row < this.model.rowCount()) {
|
|
16
|
+
const row = this.row;
|
|
17
|
+
this.row++;
|
|
18
|
+
return {
|
|
19
|
+
done: false,
|
|
20
|
+
value: this.model.rowData(row),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
done: true,
|
|
25
|
+
value: undefined,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Model<T> is the interface for feeding dynamic data into
|
|
31
|
+
* `.slint` views.
|
|
32
|
+
*
|
|
33
|
+
* A model is organized like a table with rows of data. The
|
|
34
|
+
* fields of the data type T behave like columns.
|
|
35
|
+
*
|
|
36
|
+
* @template T the type of the model's items.
|
|
37
|
+
*
|
|
38
|
+
* ### Example
|
|
39
|
+
* As an example let's see the implementation of {@link ArrayModel}
|
|
40
|
+
*
|
|
41
|
+
* ```js
|
|
42
|
+
* export class ArrayModel<T> extends Model<T> {
|
|
43
|
+
* private a: Array<T>
|
|
44
|
+
*
|
|
45
|
+
* constructor(arr: Array<T>) {
|
|
46
|
+
* super();
|
|
47
|
+
* this.a = arr;
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* rowCount() {
|
|
51
|
+
* return this.a.length;
|
|
52
|
+
* }
|
|
53
|
+
*
|
|
54
|
+
* rowData(row: number) {
|
|
55
|
+
* return this.a[row];
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* setRowData(row: number, data: T) {
|
|
59
|
+
* this.a[row] = data;
|
|
60
|
+
* this.notifyRowDataChanged(row);
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* push(...values: T[]) {
|
|
64
|
+
* let size = this.a.length;
|
|
65
|
+
* Array.prototype.push.apply(this.a, values);
|
|
66
|
+
* this.notifyRowAdded(size, arguments.length);
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* remove(index: number, size: number) {
|
|
70
|
+
* let r = this.a.splice(index, size);
|
|
71
|
+
* this.notifyRowRemoved(index, size);
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* get length(): number {
|
|
75
|
+
* return this.a.length;
|
|
76
|
+
* }
|
|
77
|
+
*
|
|
78
|
+
* values(): IterableIterator<T> {
|
|
79
|
+
* return this.a.values();
|
|
80
|
+
* }
|
|
81
|
+
*
|
|
82
|
+
* entries(): IterableIterator<[number, T]> {
|
|
83
|
+
* return this.a.entries()
|
|
84
|
+
* }
|
|
85
|
+
*}
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
class Model {
|
|
89
|
+
/**
|
|
90
|
+
* @hidden
|
|
91
|
+
*/
|
|
92
|
+
modelNotify;
|
|
93
|
+
/**
|
|
94
|
+
* @hidden
|
|
95
|
+
*/
|
|
96
|
+
constructor(modelNotify) {
|
|
97
|
+
this.modelNotify = modelNotify ?? napi.jsModelNotifyNew(this);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Implementations of this function must store the provided data parameter
|
|
101
|
+
* in the model at the specified row.
|
|
102
|
+
* @param _row index in range 0..(rowCount() - 1).
|
|
103
|
+
* @param _data new data item to store on the given row index
|
|
104
|
+
*/
|
|
105
|
+
setRowData(_row, _data) {
|
|
106
|
+
console.log("setRowData called on a model which does not re-implement this method. This happens when trying to modify a read-only model");
|
|
107
|
+
}
|
|
108
|
+
[Symbol.iterator]() {
|
|
109
|
+
return new ModelIterator(this);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Notifies the view that the data of the current row is changed.
|
|
113
|
+
* @param row index of the changed row.
|
|
114
|
+
*/
|
|
115
|
+
notifyRowDataChanged(row) {
|
|
116
|
+
napi.jsModelNotifyRowDataChanged(this.modelNotify, row);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Notifies the view that multiple rows are added to the model.
|
|
120
|
+
* @param row index of the first added row.
|
|
121
|
+
* @param count the number of added items.
|
|
122
|
+
*/
|
|
123
|
+
notifyRowAdded(row, count) {
|
|
124
|
+
napi.jsModelNotifyRowAdded(this.modelNotify, row, count);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Notifies the view that multiple rows are removed to the model.
|
|
128
|
+
* @param row index of the first removed row.
|
|
129
|
+
* @param count the number of removed items.
|
|
130
|
+
*/
|
|
131
|
+
notifyRowRemoved(row, count) {
|
|
132
|
+
napi.jsModelNotifyRowRemoved(this.modelNotify, row, count);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Notifies the view that the complete data must be reload.
|
|
136
|
+
*/
|
|
137
|
+
notifyReset() {
|
|
138
|
+
napi.jsModelNotifyReset(this.modelNotify);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.Model = Model;
|
|
142
|
+
/**
|
|
143
|
+
* ArrayModel wraps a JavaScript array for use in `.slint` views. The underlying
|
|
144
|
+
* array can be modified with the [[ArrayModel.push]] and [[ArrayModel.remove]] methods.
|
|
145
|
+
*/
|
|
146
|
+
class ArrayModel extends Model {
|
|
147
|
+
/**
|
|
148
|
+
* @hidden
|
|
149
|
+
*/
|
|
150
|
+
#array;
|
|
151
|
+
/**
|
|
152
|
+
* Creates a new ArrayModel.
|
|
153
|
+
*
|
|
154
|
+
* @param arr
|
|
155
|
+
*/
|
|
156
|
+
constructor(arr) {
|
|
157
|
+
super();
|
|
158
|
+
this.#array = arr;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Returns the number of entries in the array model.
|
|
162
|
+
*/
|
|
163
|
+
get length() {
|
|
164
|
+
return this.#array.length;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns the number of entries in the array model.
|
|
168
|
+
*/
|
|
169
|
+
rowCount() {
|
|
170
|
+
return this.#array.length;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Returns the data at the specified row.
|
|
174
|
+
* @param row index in range 0..(rowCount() - 1).
|
|
175
|
+
* @returns undefined if row is out of range otherwise the data.
|
|
176
|
+
*/
|
|
177
|
+
rowData(row) {
|
|
178
|
+
return this.#array[row];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Stores the given data on the given row index and notifies run-time about the changed row.
|
|
182
|
+
* @param row index in range 0..(rowCount() - 1).
|
|
183
|
+
* @param data new data item to store on the given row index
|
|
184
|
+
*/
|
|
185
|
+
setRowData(row, data) {
|
|
186
|
+
this.#array[row] = data;
|
|
187
|
+
this.notifyRowDataChanged(row);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Pushes new values to the array that's backing the model and notifies
|
|
191
|
+
* the run-time about the added rows.
|
|
192
|
+
* @param values list of values that will be pushed to the array.
|
|
193
|
+
*/
|
|
194
|
+
push(...values) {
|
|
195
|
+
const size = this.#array.length;
|
|
196
|
+
Array.prototype.push.apply(this.#array, values);
|
|
197
|
+
this.notifyRowAdded(size, arguments.length);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Removes the last element from the array and returns it.
|
|
201
|
+
*
|
|
202
|
+
* @returns The removed element or undefined if the array is empty.
|
|
203
|
+
*/
|
|
204
|
+
pop() {
|
|
205
|
+
const last = this.#array.pop();
|
|
206
|
+
if (last !== undefined) {
|
|
207
|
+
this.notifyRowRemoved(this.#array.length, 1);
|
|
208
|
+
}
|
|
209
|
+
return last;
|
|
210
|
+
}
|
|
211
|
+
// FIXME: should this be named splice and have the splice api?
|
|
212
|
+
/**
|
|
213
|
+
* Removes the specified number of element from the array that's backing
|
|
214
|
+
* the model, starting at the specified index.
|
|
215
|
+
* @param index index of first row to remove.
|
|
216
|
+
* @param size number of rows to remove.
|
|
217
|
+
*/
|
|
218
|
+
remove(index, size) {
|
|
219
|
+
const r = this.#array.splice(index, size);
|
|
220
|
+
this.notifyRowRemoved(index, size);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Returns an iterable of values in the array.
|
|
224
|
+
*/
|
|
225
|
+
values() {
|
|
226
|
+
return this.#array.values();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Returns an iterable of key, value pairs for every entry in the array.
|
|
230
|
+
*/
|
|
231
|
+
entries() {
|
|
232
|
+
return this.#array.entries();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
exports.ArrayModel = ArrayModel;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slint-ui",
|
|
3
|
-
"version": "1.9.0-nightly.
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"types": "index.d.ts",
|
|
3
|
+
"version": "1.9.0-nightly.2024100207",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
6
|
"homepage": "https://github.com/slint-ui/slint",
|
|
7
7
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
8
8
|
"repository": {
|
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
],
|
|
21
21
|
"description": "Slint is a declarative GUI toolkit to build native user interfaces for desktop and embedded applications.",
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@biomejs/biome": "1.8.3",
|
|
24
23
|
"@ava/typescript": "^4.1.0",
|
|
24
|
+
"@biomejs/biome": "1.8.3",
|
|
25
|
+
"@types/capture-console": "^1.0.5",
|
|
25
26
|
"@types/node": "^20.8.6",
|
|
26
27
|
"@types/node-fetch": "^2.6.7",
|
|
27
28
|
"ava": "^5.3.0",
|
|
29
|
+
"capture-console": "^1.0.2",
|
|
28
30
|
"jimp": "^0.22.8",
|
|
29
31
|
"ts-node": "^10.9.1",
|
|
30
32
|
"typedoc": "^0.25.2",
|
|
@@ -40,7 +42,7 @@
|
|
|
40
42
|
"build:debug": "napi build --platform --js rust-module.cjs --dts rust-module.d.ts -c binaries.json && npm run compile",
|
|
41
43
|
"build:testing": "napi build --platform --js rust-module.cjs --dts rust-module.d.ts -c binaries.json --features testing && npm run compile",
|
|
42
44
|
"install": "node build-on-demand.mjs",
|
|
43
|
-
"docs": "npm run build && typedoc --hideGenerator --treatWarningsAsErrors --readme cover.md index.ts",
|
|
45
|
+
"docs": "npm run build && typedoc --hideGenerator --treatWarningsAsErrors --readme cover.md typescript/index.ts",
|
|
44
46
|
"check": "biome check",
|
|
45
47
|
"format": "biome format",
|
|
46
48
|
"format:fix": "biome format --write",
|
|
@@ -65,10 +67,10 @@
|
|
|
65
67
|
"@napi-rs/cli": "^2.16.5"
|
|
66
68
|
},
|
|
67
69
|
"optionalDependencies": {
|
|
68
|
-
"@slint-ui/slint-ui-binary-linux-x64-gnu": "1.9.0-nightly.
|
|
69
|
-
"@slint-ui/slint-ui-binary-darwin-x64": "1.9.0-nightly.
|
|
70
|
-
"@slint-ui/slint-ui-binary-darwin-arm64": "1.9.0-nightly.
|
|
71
|
-
"@slint-ui/slint-ui-binary-win32-x64-msvc": "1.9.0-nightly.
|
|
72
|
-
"@slint-ui/slint-ui-binary-win32-ia32-msvc": "1.9.0-nightly.
|
|
70
|
+
"@slint-ui/slint-ui-binary-linux-x64-gnu": "1.9.0-nightly.2024100207",
|
|
71
|
+
"@slint-ui/slint-ui-binary-darwin-x64": "1.9.0-nightly.2024100207",
|
|
72
|
+
"@slint-ui/slint-ui-binary-darwin-arm64": "1.9.0-nightly.2024100207",
|
|
73
|
+
"@slint-ui/slint-ui-binary-win32-x64-msvc": "1.9.0-nightly.2024100207",
|
|
74
|
+
"@slint-ui/slint-ui-binary-win32-ia32-msvc": "1.9.0-nightly.2024100207"
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -137,21 +137,39 @@ impl JsComponentInstance {
|
|
|
137
137
|
self.inner
|
|
138
138
|
.set_callback(callback_name.as_str(), {
|
|
139
139
|
let return_type = return_type.clone();
|
|
140
|
+
let callback_name = callback_name.clone();
|
|
140
141
|
|
|
141
142
|
move |args| {
|
|
142
|
-
let callback
|
|
143
|
-
|
|
143
|
+
let Ok(callback) = function_ref.get::<JsFunction>() else {
|
|
144
|
+
eprintln!("Node.js: cannot get reference of callback {} because it has the wrong type", callback_name);
|
|
145
|
+
return Value::Void;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
let result = match callback
|
|
144
149
|
.call(
|
|
145
150
|
None,
|
|
146
151
|
args.iter()
|
|
147
152
|
.map(|v| super::value::to_js_unknown(&env, v).unwrap())
|
|
148
153
|
.collect::<Vec<JsUnknown>>()
|
|
149
|
-
.as_ref()
|
|
150
|
-
)
|
|
151
|
-
|
|
154
|
+
.as_ref()
|
|
155
|
+
) {
|
|
156
|
+
Ok(result) => result,
|
|
157
|
+
Err(err) => {
|
|
158
|
+
crate::console_err!(env, "Node.js: Invoking callback '{callback_name}' failed: {err}");
|
|
159
|
+
return Value::Void;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
152
162
|
|
|
153
163
|
if let Some(return_type) = &return_type {
|
|
154
|
-
super::to_value(&env, result, return_type)
|
|
164
|
+
if let Ok(value) = super::to_value(&env, result, return_type) {
|
|
165
|
+
return value;
|
|
166
|
+
} else {
|
|
167
|
+
eprintln!(
|
|
168
|
+
"Node.js: cannot convert return type of callback {}",
|
|
169
|
+
callback_name
|
|
170
|
+
);
|
|
171
|
+
return slint_interpreter::default_value_for_type(return_type);
|
|
172
|
+
}
|
|
155
173
|
} else {
|
|
156
174
|
Value::Void
|
|
157
175
|
}
|
|
@@ -192,21 +210,43 @@ impl JsComponentInstance {
|
|
|
192
210
|
self.inner
|
|
193
211
|
.set_global_callback(global_name.as_str(), callback_name.as_str(), {
|
|
194
212
|
let return_type = return_type.clone();
|
|
213
|
+
let global_name = global_name.clone();
|
|
214
|
+
let callback_name = callback_name.clone();
|
|
195
215
|
|
|
196
216
|
move |args| {
|
|
197
|
-
let callback
|
|
198
|
-
|
|
217
|
+
let Ok(callback) = function_ref.get::<JsFunction>() else {
|
|
218
|
+
eprintln!(
|
|
219
|
+
"Node.js: cannot get reference of callback {} of global {} because it has the wrong type",
|
|
220
|
+
callback_name, global_name
|
|
221
|
+
);
|
|
222
|
+
return Value::Void;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
let result = match callback
|
|
199
226
|
.call(
|
|
200
227
|
None,
|
|
201
228
|
args.iter()
|
|
202
229
|
.map(|v| super::value::to_js_unknown(&env, v).unwrap())
|
|
203
230
|
.collect::<Vec<JsUnknown>>()
|
|
204
|
-
.as_ref()
|
|
205
|
-
)
|
|
206
|
-
|
|
231
|
+
.as_ref()
|
|
232
|
+
) {
|
|
233
|
+
Ok(result) => result,
|
|
234
|
+
Err(err) => {
|
|
235
|
+
crate::console_err!(env, "Node.js: Invoking global callback '{callback_name}' failed: {err}");
|
|
236
|
+
return Value::Void;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
207
239
|
|
|
208
240
|
if let Some(return_type) = &return_type {
|
|
209
|
-
super::to_value(&env, result, return_type)
|
|
241
|
+
if let Ok(value) = super::to_value(&env, result, return_type) {
|
|
242
|
+
return value;
|
|
243
|
+
} else {
|
|
244
|
+
eprintln!(
|
|
245
|
+
"Node.js: cannot convert return type of callback {}",
|
|
246
|
+
callback_name
|
|
247
|
+
);
|
|
248
|
+
return slint_interpreter::default_value_for_type(return_type);
|
|
249
|
+
}
|
|
210
250
|
} else {
|
|
211
251
|
Value::Void
|
|
212
252
|
}
|
|
@@ -78,6 +78,7 @@ pub fn to_js_unknown(env: &Env, value: &Value) -> Result<JsUnknown> {
|
|
|
78
78
|
model_wrapper.into_js(env)
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
Value::EnumerationValue(_, value) => env.create_string(value).map(|v| v.into_unknown()),
|
|
81
82
|
_ => env.get_undefined().map(|v| v.into_unknown()),
|
|
82
83
|
}
|
|
83
84
|
}
|
|
@@ -239,7 +240,14 @@ pub fn to_value(env: &Env, unknown: JsUnknown, typ: &Type) -> Result<Value> {
|
|
|
239
240
|
let mut vec = vec![];
|
|
240
241
|
|
|
241
242
|
for i in 0..array.len() {
|
|
242
|
-
vec.push(to_value(
|
|
243
|
+
vec.push(to_value(
|
|
244
|
+
env,
|
|
245
|
+
array.get(i)?.ok_or(napi::Error::from_reason(format!(
|
|
246
|
+
"Cannot access array element at index {}",
|
|
247
|
+
i
|
|
248
|
+
)))?,
|
|
249
|
+
a,
|
|
250
|
+
)?);
|
|
243
251
|
}
|
|
244
252
|
Ok(Value::Model(ModelRc::new(SharedVectorModel::from(SharedVector::from_slice(
|
|
245
253
|
&vec,
|
|
@@ -250,7 +258,19 @@ pub fn to_value(env: &Env, unknown: JsUnknown, typ: &Type) -> Result<Value> {
|
|
|
250
258
|
Ok(Value::Model(rust_model))
|
|
251
259
|
}
|
|
252
260
|
}
|
|
253
|
-
Type::Enumeration(
|
|
261
|
+
Type::Enumeration(e) => {
|
|
262
|
+
let js_string: JsString = unknown.try_into()?;
|
|
263
|
+
let value: String = js_string.into_utf8()?.as_str()?.into();
|
|
264
|
+
|
|
265
|
+
if !e.values.contains(&value) {
|
|
266
|
+
return Err(napi::Error::from_reason(format!(
|
|
267
|
+
"{value} is not a value of enum {}",
|
|
268
|
+
e.name
|
|
269
|
+
)));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
Ok(Value::EnumerationValue(e.name.clone(), value))
|
|
273
|
+
}
|
|
254
274
|
Type::Invalid
|
|
255
275
|
| Type::Model
|
|
256
276
|
| Type::Void
|
package/{src → rust}/lib.rs
RENAMED
|
@@ -7,7 +7,7 @@ pub use interpreter::*;
|
|
|
7
7
|
mod types;
|
|
8
8
|
pub use types::*;
|
|
9
9
|
|
|
10
|
-
use napi::{Env, JsFunction};
|
|
10
|
+
use napi::{Env, JsFunction, JsObject};
|
|
11
11
|
|
|
12
12
|
#[macro_use]
|
|
13
13
|
extern crate napi_derive;
|
|
@@ -54,7 +54,10 @@ pub fn invoke_from_event_loop(env: Env, callback: JsFunction) -> napi::Result<na
|
|
|
54
54
|
let function_ref = send_wrapper::SendWrapper::new(function_ref);
|
|
55
55
|
i_slint_core::api::invoke_from_event_loop(move || {
|
|
56
56
|
let function_ref = function_ref.take();
|
|
57
|
-
let callback
|
|
57
|
+
let Ok(callback) = function_ref.get::<JsFunction>() else {
|
|
58
|
+
eprintln!("Node.js: JavaScript invoke_from_event_loop threw an exception");
|
|
59
|
+
return;
|
|
60
|
+
};
|
|
58
61
|
callback.call_without_args(None).ok();
|
|
59
62
|
})
|
|
60
63
|
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
|
@@ -82,3 +85,38 @@ pub fn init_testing() {
|
|
|
82
85
|
#[cfg(feature = "testing")]
|
|
83
86
|
i_slint_backend_testing::init_integration_test_with_mock_time();
|
|
84
87
|
}
|
|
88
|
+
|
|
89
|
+
pub fn print_to_console(env: Env, function: &str, arguments: core::fmt::Arguments) {
|
|
90
|
+
let Ok(global) = env.get_global() else {
|
|
91
|
+
eprintln!("Unable to obtain global object");
|
|
92
|
+
return;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
let Ok(console_object) = global
|
|
96
|
+
.get_named_property::<JsObject>("console")
|
|
97
|
+
.and_then(|console| console.coerce_to_object())
|
|
98
|
+
else {
|
|
99
|
+
eprintln!("Unable to obtain console object for logging");
|
|
100
|
+
return;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
let Ok(Some(log_fn)) = console_object.get::<&str, JsFunction>(function) else {
|
|
104
|
+
eprintln!("Unable to obtain console.{function}");
|
|
105
|
+
return;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
let message = arguments.to_string();
|
|
109
|
+
let Ok(js_message) = env.create_string(&message) else {
|
|
110
|
+
eprintln!("Unable to provide log message to JS env");
|
|
111
|
+
return;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
if let Err(err) = log_fn.call(None, &vec![js_message.into_unknown()]) {
|
|
115
|
+
eprintln!("Unable to invoke console.{function}: {err}");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#[macro_export]
|
|
120
|
+
macro_rules! console_err {
|
|
121
|
+
($env:expr, $($t:tt)*) => ($crate::print_to_console($env, "error", format_args!($($t)*)))
|
|
122
|
+
}
|
|
@@ -90,7 +90,10 @@ impl Model for JsModel {
|
|
|
90
90
|
type Data = slint_interpreter::Value;
|
|
91
91
|
|
|
92
92
|
fn row_count(&self) -> usize {
|
|
93
|
-
let model
|
|
93
|
+
let Ok(model) = self.js_impl.get::<Object>() else {
|
|
94
|
+
eprintln!("Node.js: JavaScript Model<T>'s rowCount threw an exception");
|
|
95
|
+
return 0;
|
|
96
|
+
};
|
|
94
97
|
|
|
95
98
|
let Ok(row_count_property) = model.get::<&str, JsFunction>("rowCount") else {
|
|
96
99
|
eprintln!("Node.js: JavaScript Model<T> implementation is missing rowCount property");
|
|
@@ -121,7 +124,11 @@ impl Model for JsModel {
|
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
fn row_data(&self, row: usize) -> Option<Self::Data> {
|
|
124
|
-
let model
|
|
127
|
+
let Ok(model) = self.js_impl.get::<Object>() else {
|
|
128
|
+
eprintln!("Node.js: JavaScript Model<T>'s rowData threw an exception");
|
|
129
|
+
return None;
|
|
130
|
+
};
|
|
131
|
+
|
|
125
132
|
let Ok(row_data_property) = model.get::<&str, JsFunction>("rowData") else {
|
|
126
133
|
eprintln!("Node.js: JavaScript Model<T> implementation is missing rowData property");
|
|
127
134
|
return None;
|
|
@@ -152,7 +159,10 @@ impl Model for JsModel {
|
|
|
152
159
|
}
|
|
153
160
|
|
|
154
161
|
fn set_row_data(&self, row: usize, data: Self::Data) {
|
|
155
|
-
let model
|
|
162
|
+
let Ok(model) = self.js_impl.get::<Object>() else {
|
|
163
|
+
eprintln!("Node.js: JavaScript Model<T>'s setRowData threw an exception");
|
|
164
|
+
return;
|
|
165
|
+
};
|
|
156
166
|
|
|
157
167
|
let Ok(set_row_data_property) = model.get::<&str, JsFunction>("setRowData") else {
|
|
158
168
|
eprintln!("Node.js: JavaScript Model<T> implementation is missing setRowData property");
|