@gtkx/react 0.9.4 → 0.10.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/README.md +55 -67
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +8 -8
- package/dist/factory.d.ts +3 -5
- package/dist/factory.js +18 -71
- package/dist/fiber-root.d.ts +1 -1
- package/dist/fiber-root.js +1 -2
- package/dist/generated/internal.d.ts +3 -6
- package/dist/generated/internal.js +10386 -13577
- package/dist/generated/jsx.d.ts +914 -808
- package/dist/generated/jsx.js +123 -358
- package/dist/generated/registry.d.ts +4 -0
- package/dist/generated/registry.js +13 -0
- package/dist/host-config.d.ts +7 -4
- package/dist/host-config.js +53 -18
- package/dist/index.d.ts +2 -22
- package/dist/index.js +2 -40
- package/dist/jsx.d.ts +719 -0
- package/dist/jsx.js +392 -0
- package/dist/node.d.ts +15 -32
- package/dist/node.js +20 -240
- package/dist/nodes/action-row-child.d.ts +21 -0
- package/dist/nodes/action-row-child.js +69 -0
- package/dist/nodes/action-row.js +33 -0
- package/dist/nodes/application.d.ts +1 -0
- package/dist/nodes/application.js +38 -0
- package/dist/nodes/autowrapped.d.ts +1 -0
- package/dist/nodes/autowrapped.js +109 -0
- package/dist/nodes/column-view-column.d.ts +16 -0
- package/dist/nodes/column-view-column.js +54 -0
- package/dist/nodes/column-view.d.ts +0 -59
- package/dist/nodes/column-view.js +107 -226
- package/dist/nodes/fixed-child.d.ts +1 -0
- package/dist/nodes/fixed-child.js +45 -0
- package/dist/nodes/grid-child.d.ts +1 -0
- package/dist/nodes/grid-child.js +54 -0
- package/dist/nodes/index.d.ts +34 -0
- package/dist/nodes/index.js +34 -0
- package/dist/nodes/internal/list-item-renderer.d.ts +18 -0
- package/dist/nodes/internal/list-item-renderer.js +67 -0
- package/dist/nodes/internal/list-store.d.ts +16 -0
- package/dist/nodes/internal/list-store.js +69 -0
- package/dist/nodes/internal/predicates.d.ts +26 -0
- package/dist/nodes/internal/predicates.js +36 -0
- package/dist/nodes/internal/signal-store.d.ts +9 -0
- package/dist/nodes/internal/signal-store.js +54 -0
- package/dist/nodes/internal/simple-list-store.d.ts +14 -0
- package/dist/nodes/internal/simple-list-store.js +60 -0
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +18 -0
- package/dist/nodes/internal/tree-list-item-renderer.js +90 -0
- package/dist/nodes/internal/tree-store.d.ts +28 -0
- package/dist/nodes/internal/tree-store.js +153 -0
- package/dist/nodes/internal/utils.d.ts +3 -0
- package/dist/nodes/internal/utils.js +20 -0
- package/dist/nodes/list-item.d.ts +12 -0
- package/dist/nodes/list-item.js +24 -0
- package/dist/nodes/list-view.d.ts +0 -22
- package/dist/nodes/list-view.js +45 -38
- package/dist/nodes/menu.d.ts +6 -106
- package/dist/nodes/menu.js +16 -268
- package/dist/nodes/models/list.d.ts +24 -0
- package/dist/nodes/models/list.js +102 -0
- package/dist/nodes/models/menu.d.ts +45 -0
- package/dist/nodes/models/menu.js +265 -0
- package/dist/nodes/models/tree-list.d.ts +28 -0
- package/dist/nodes/models/tree-list.js +141 -0
- package/dist/nodes/navigation-page.d.ts +21 -0
- package/dist/nodes/navigation-page.js +95 -0
- package/dist/nodes/navigation-view.d.ts +1 -0
- package/dist/nodes/navigation-view.js +29 -0
- package/dist/nodes/notebook-page-tab.d.ts +15 -0
- package/dist/nodes/notebook-page-tab.js +42 -0
- package/dist/nodes/notebook-page.d.ts +23 -0
- package/dist/nodes/notebook-page.js +106 -0
- package/dist/nodes/notebook.d.ts +0 -32
- package/dist/nodes/notebook.js +20 -113
- package/dist/nodes/overlay-child.d.ts +1 -0
- package/dist/nodes/overlay-child.js +30 -0
- package/dist/nodes/pack-child.d.ts +21 -0
- package/dist/nodes/pack-child.js +68 -0
- package/dist/nodes/pack.d.ts +1 -0
- package/dist/nodes/pack.js +33 -0
- package/dist/nodes/popover-menu.d.ts +1 -0
- package/dist/nodes/popover-menu.js +58 -0
- package/dist/nodes/simple-list-item.d.ts +9 -0
- package/dist/nodes/simple-list-item.js +9 -0
- package/dist/nodes/simple-list-view.d.ts +1 -0
- package/dist/nodes/simple-list-view.js +75 -0
- package/dist/nodes/slot.d.ts +18 -10
- package/dist/nodes/slot.js +83 -51
- package/dist/nodes/stack-page.d.ts +1 -0
- package/dist/nodes/stack-page.js +80 -0
- package/dist/nodes/stack.d.ts +1 -22
- package/dist/nodes/stack.js +21 -60
- package/dist/nodes/toast-overlay.d.ts +1 -0
- package/dist/nodes/toast-overlay.js +35 -0
- package/dist/nodes/toast.d.ts +17 -0
- package/dist/nodes/toast.js +77 -0
- package/dist/nodes/toolbar-child.d.ts +9 -0
- package/dist/nodes/toolbar-child.js +33 -0
- package/dist/nodes/toolbar.d.ts +1 -0
- package/dist/nodes/toolbar.js +42 -0
- package/dist/nodes/tree-list-item.d.ts +20 -0
- package/dist/nodes/tree-list-item.js +102 -0
- package/dist/nodes/tree-list-view.d.ts +1 -0
- package/dist/nodes/tree-list-view.js +57 -0
- package/dist/nodes/virtual.d.ts +13 -0
- package/dist/nodes/virtual.js +21 -0
- package/dist/nodes/widget.d.ts +17 -3
- package/dist/nodes/widget.js +258 -2
- package/dist/nodes/window.d.ts +1 -12
- package/dist/nodes/window.js +66 -27
- package/dist/portal.d.ts +18 -13
- package/dist/portal.js +17 -14
- package/dist/reconciler.d.ts +0 -4
- package/dist/reconciler.js +1 -9
- package/dist/registry.d.ts +8 -0
- package/dist/registry.js +5 -0
- package/dist/render.d.ts +108 -12
- package/dist/render.js +140 -16
- package/dist/scheduler.d.ts +4 -0
- package/dist/scheduler.js +10 -0
- package/dist/types.d.ts +3 -136
- package/package.json +6 -6
- package/dist/batch.d.ts +0 -5
- package/dist/batch.js +0 -31
- package/dist/codegen/jsx-generator.d.ts +0 -56
- package/dist/codegen/jsx-generator.js +0 -959
- package/dist/containers.d.ts +0 -58
- package/dist/nodes/about-dialog.d.ts +0 -8
- package/dist/nodes/about-dialog.js +0 -16
- package/dist/nodes/action-bar.d.ts +0 -5
- package/dist/nodes/action-bar.js +0 -6
- package/dist/nodes/combo-row.d.ts +0 -5
- package/dist/nodes/combo-row.js +0 -6
- package/dist/nodes/drop-down.d.ts +0 -9
- package/dist/nodes/drop-down.js +0 -12
- package/dist/nodes/flow-box.d.ts +0 -10
- package/dist/nodes/flow-box.js +0 -41
- package/dist/nodes/grid.d.ts +0 -30
- package/dist/nodes/grid.js +0 -84
- package/dist/nodes/header-bar.d.ts +0 -43
- package/dist/nodes/header-bar.js +0 -116
- package/dist/nodes/indexed-child-container.d.ts +0 -16
- package/dist/nodes/indexed-child-container.js +0 -22
- package/dist/nodes/list-box.d.ts +0 -10
- package/dist/nodes/list-box.js +0 -48
- package/dist/nodes/list-item-factory.d.ts +0 -19
- package/dist/nodes/list-item-factory.js +0 -58
- package/dist/nodes/overlay.d.ts +0 -11
- package/dist/nodes/overlay.js +0 -50
- package/dist/nodes/paged-stack.d.ts +0 -31
- package/dist/nodes/paged-stack.js +0 -95
- package/dist/nodes/root.d.ts +0 -8
- package/dist/nodes/root.js +0 -13
- package/dist/nodes/selectable-list.d.ts +0 -45
- package/dist/nodes/selectable-list.js +0 -260
- package/dist/nodes/stack-page-props.d.ts +0 -11
- package/dist/nodes/stack-page-props.js +0 -23
- package/dist/nodes/string-list-container.d.ts +0 -34
- package/dist/nodes/string-list-container.js +0 -118
- package/dist/nodes/string-list-item.d.ts +0 -19
- package/dist/nodes/string-list-item.js +0 -50
- package/dist/nodes/string-list-store.d.ts +0 -13
- package/dist/nodes/string-list-store.js +0 -44
- package/dist/nodes/text-view.d.ts +0 -8
- package/dist/nodes/text-view.js +0 -16
- package/dist/nodes/toggle-button.d.ts +0 -14
- package/dist/nodes/toggle-button.js +0 -39
- package/dist/nodes/toolbar-view.d.ts +0 -14
- package/dist/nodes/toolbar-view.js +0 -78
- package/dist/nodes/view-stack.d.ts +0 -9
- package/dist/nodes/view-stack.js +0 -28
- package/dist/nodes/virtual-item.d.ts +0 -19
- package/dist/nodes/virtual-item.js +0 -48
- package/dist/nodes/virtual-slot.d.ts +0 -25
- package/dist/nodes/virtual-slot.js +0 -57
- package/dist/predicates.d.ts +0 -29
- package/dist/predicates.js +0 -37
- package/dist/props.d.ts +0 -7
- package/dist/props.js +0 -12
- /package/dist/{containers.js → nodes/action-row.d.ts} +0 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { batch } from "@gtkx/ffi";
|
|
2
|
+
import * as Gio from "@gtkx/ffi/gio";
|
|
3
|
+
import { scheduleAfterCommit } from "../../scheduler.js";
|
|
4
|
+
import { VirtualNode } from "../virtual.js";
|
|
5
|
+
export class Menu extends VirtualNode {
|
|
6
|
+
actionMap;
|
|
7
|
+
actionPrefix;
|
|
8
|
+
parent;
|
|
9
|
+
menu;
|
|
10
|
+
type;
|
|
11
|
+
application;
|
|
12
|
+
action;
|
|
13
|
+
children = [];
|
|
14
|
+
constructor(type, props, actionMap, application) {
|
|
15
|
+
super("", props, undefined);
|
|
16
|
+
this.type = type;
|
|
17
|
+
this.actionMap = actionMap;
|
|
18
|
+
this.actionPrefix = application ? "app" : "menu";
|
|
19
|
+
this.application = application;
|
|
20
|
+
this.menu = new Gio.Menu();
|
|
21
|
+
}
|
|
22
|
+
setActionMap(actionMap, prefix) {
|
|
23
|
+
this.actionMap = actionMap;
|
|
24
|
+
this.actionPrefix = prefix;
|
|
25
|
+
for (const child of this.children) {
|
|
26
|
+
child.setActionMap(actionMap, prefix);
|
|
27
|
+
if (child.type === "item") {
|
|
28
|
+
child.createAction();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
getAccels() {
|
|
33
|
+
const accels = this.props.accels;
|
|
34
|
+
if (!accels) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return Array.isArray(accels) ? accels : [accels];
|
|
38
|
+
}
|
|
39
|
+
getActionName() {
|
|
40
|
+
return `${this.actionPrefix}.${this.props.id}`;
|
|
41
|
+
}
|
|
42
|
+
getOnActivate() {
|
|
43
|
+
if (!this.props.onActivate) {
|
|
44
|
+
throw new Error("Expected 'onActivate' prop to be present on MenuItem");
|
|
45
|
+
}
|
|
46
|
+
return this.props.onActivate;
|
|
47
|
+
}
|
|
48
|
+
getId() {
|
|
49
|
+
if (!this.props.id) {
|
|
50
|
+
throw new Error("Expected 'id' prop to be present on MenuItem");
|
|
51
|
+
}
|
|
52
|
+
return this.props.id;
|
|
53
|
+
}
|
|
54
|
+
getParent() {
|
|
55
|
+
if (!this.parent) {
|
|
56
|
+
throw new Error("Expected parent menu to be set on MenuNode");
|
|
57
|
+
}
|
|
58
|
+
return this.parent;
|
|
59
|
+
}
|
|
60
|
+
getActionMap() {
|
|
61
|
+
if (!this.actionMap) {
|
|
62
|
+
throw new Error("Expected actionMap to be set on MenuNode");
|
|
63
|
+
}
|
|
64
|
+
return this.actionMap;
|
|
65
|
+
}
|
|
66
|
+
createAction() {
|
|
67
|
+
batch(() => {
|
|
68
|
+
if (this.action) {
|
|
69
|
+
this.signalStore.set(this.action, "activate", undefined);
|
|
70
|
+
}
|
|
71
|
+
this.action = new Gio.SimpleAction(this.getId());
|
|
72
|
+
this.signalStore.set(this.action, "activate", this.getOnActivate());
|
|
73
|
+
this.getActionMap().addAction(this.action);
|
|
74
|
+
if (this.application && this.props.accels) {
|
|
75
|
+
this.application.setAccelsForAction(this.getActionName(), this.getAccels());
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
removeAction() {
|
|
80
|
+
batch(() => {
|
|
81
|
+
if (this.application && this.props.accels) {
|
|
82
|
+
this.application.setAccelsForAction(this.getActionName(), []);
|
|
83
|
+
}
|
|
84
|
+
if (this.action) {
|
|
85
|
+
this.getActionMap().removeAction(this.getId());
|
|
86
|
+
this.signalStore.set(this.action, "activate", undefined);
|
|
87
|
+
this.action = undefined;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
getPosition() {
|
|
92
|
+
const parent = this.getParent();
|
|
93
|
+
for (let i = 0; i < parent.getNItems(); i++) {
|
|
94
|
+
if (this.type === "item") {
|
|
95
|
+
const actionName = parent.getItemAttributeValue(i, "action")?.getString();
|
|
96
|
+
if (actionName === this.getActionName()) {
|
|
97
|
+
return i;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const link = parent.getItemLink(i, this.type);
|
|
102
|
+
if (link?.equals(this.menu)) {
|
|
103
|
+
return i;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
setParent(parent) {
|
|
110
|
+
this.parent = parent;
|
|
111
|
+
}
|
|
112
|
+
getMenu() {
|
|
113
|
+
return this.menu;
|
|
114
|
+
}
|
|
115
|
+
getAction() {
|
|
116
|
+
if (!this.action) {
|
|
117
|
+
throw new Error("Expected action to be created on MenuItem");
|
|
118
|
+
}
|
|
119
|
+
return this.action;
|
|
120
|
+
}
|
|
121
|
+
removeFromParent() {
|
|
122
|
+
if (!this.parent)
|
|
123
|
+
return;
|
|
124
|
+
const position = this.getPosition();
|
|
125
|
+
const parent = this.parent;
|
|
126
|
+
this.parent = undefined;
|
|
127
|
+
batch(() => parent.remove(position));
|
|
128
|
+
}
|
|
129
|
+
insertInParentBefore(before) {
|
|
130
|
+
if (this.type === "item" && this.actionMap) {
|
|
131
|
+
this.createAction();
|
|
132
|
+
}
|
|
133
|
+
scheduleAfterCommit(() => {
|
|
134
|
+
const parent = this.getParent();
|
|
135
|
+
const beforePosition = before.getPosition();
|
|
136
|
+
switch (this.type) {
|
|
137
|
+
case "item": {
|
|
138
|
+
parent.insert(beforePosition, this.props.label, this.getActionName());
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case "section":
|
|
142
|
+
parent.insertSection(beforePosition, this.menu, this.props.label);
|
|
143
|
+
break;
|
|
144
|
+
case "submenu":
|
|
145
|
+
parent.insertSubmenu(beforePosition, this.menu, this.props.label);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
appendToParent() {
|
|
151
|
+
if (this.type === "item" && this.actionMap) {
|
|
152
|
+
this.createAction();
|
|
153
|
+
}
|
|
154
|
+
scheduleAfterCommit(() => {
|
|
155
|
+
const parent = this.getParent();
|
|
156
|
+
switch (this.type) {
|
|
157
|
+
case "item":
|
|
158
|
+
parent.append(this.props.label, this.getActionName());
|
|
159
|
+
break;
|
|
160
|
+
case "section":
|
|
161
|
+
parent.appendSection(this.menu, this.props.label);
|
|
162
|
+
break;
|
|
163
|
+
case "submenu":
|
|
164
|
+
parent.appendSubmenu(this.menu, this.props.label);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
appendChild(child) {
|
|
170
|
+
if (!(child instanceof Menu)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
this.children.push(child);
|
|
174
|
+
if (this.actionMap) {
|
|
175
|
+
child.setActionMap(this.actionMap, this.actionPrefix);
|
|
176
|
+
}
|
|
177
|
+
child.setParent(this.menu);
|
|
178
|
+
child.appendToParent();
|
|
179
|
+
}
|
|
180
|
+
insertBefore(child, before) {
|
|
181
|
+
if (!(child instanceof Menu) || !(before instanceof Menu)) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const beforeIndex = this.children.indexOf(before);
|
|
185
|
+
if (beforeIndex >= 0) {
|
|
186
|
+
this.children.splice(beforeIndex, 0, child);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
this.children.push(child);
|
|
190
|
+
}
|
|
191
|
+
if (this.actionMap) {
|
|
192
|
+
child.setActionMap(this.actionMap, this.actionPrefix);
|
|
193
|
+
}
|
|
194
|
+
child.setParent(this.menu);
|
|
195
|
+
child.insertInParentBefore(before);
|
|
196
|
+
}
|
|
197
|
+
removeChild(child) {
|
|
198
|
+
if (!(child instanceof Menu)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const index = this.children.indexOf(child);
|
|
202
|
+
if (index >= 0) {
|
|
203
|
+
this.children.splice(index, 1);
|
|
204
|
+
}
|
|
205
|
+
child.removeFromParent();
|
|
206
|
+
}
|
|
207
|
+
updateProps(oldProps, newProps) {
|
|
208
|
+
super.updateProps(oldProps, newProps);
|
|
209
|
+
if (this.type === "item") {
|
|
210
|
+
this.updateItemProps(oldProps, newProps);
|
|
211
|
+
}
|
|
212
|
+
else if (this.type === "section" || this.type === "submenu") {
|
|
213
|
+
this.updateContainerProps(oldProps, newProps);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
updateItemProps(oldProps, newProps) {
|
|
217
|
+
if (!this.parent || !this.actionMap) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (!oldProps) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (oldProps.id !== newProps.id || oldProps.label !== newProps.label) {
|
|
224
|
+
const parent = this.parent;
|
|
225
|
+
this.removeAction();
|
|
226
|
+
this.removeFromParent();
|
|
227
|
+
this.parent = parent;
|
|
228
|
+
this.createAction();
|
|
229
|
+
this.appendToParent();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (oldProps.onActivate !== newProps.onActivate) {
|
|
233
|
+
this.signalStore.set(this.getAction(), "activate", newProps.onActivate);
|
|
234
|
+
}
|
|
235
|
+
if (oldProps.accels !== newProps.accels) {
|
|
236
|
+
if (this.application) {
|
|
237
|
+
this.application.setAccelsForAction(this.getActionName(), this.getAccels());
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
updateContainerProps(oldProps, newProps) {
|
|
242
|
+
if (!this.parent) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!oldProps || oldProps.label !== newProps.label) {
|
|
246
|
+
const position = this.getPosition();
|
|
247
|
+
const parent = this.parent;
|
|
248
|
+
this.removeFromParent();
|
|
249
|
+
if (this.type === "section") {
|
|
250
|
+
parent.insertSection(position, this.menu, newProps.label);
|
|
251
|
+
}
|
|
252
|
+
else if (this.type === "submenu") {
|
|
253
|
+
parent.insertSubmenu(position, this.menu, newProps.label);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
unmount() {
|
|
258
|
+
this.removeAction();
|
|
259
|
+
if (this.parent) {
|
|
260
|
+
this.removeFromParent();
|
|
261
|
+
this.parent = undefined;
|
|
262
|
+
}
|
|
263
|
+
super.unmount();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { Node } from "../../node.js";
|
|
3
|
+
import { TreeStore } from "../internal/tree-store.js";
|
|
4
|
+
import { VirtualNode } from "../virtual.js";
|
|
5
|
+
export type TreeListProps = {
|
|
6
|
+
autoexpand?: boolean;
|
|
7
|
+
selectionMode?: Gtk.SelectionMode;
|
|
8
|
+
selected?: string[];
|
|
9
|
+
onSelectionChanged?: (ids: string[]) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare class TreeList extends VirtualNode<TreeListProps> {
|
|
12
|
+
private store;
|
|
13
|
+
private treeListModel;
|
|
14
|
+
private selectionModel;
|
|
15
|
+
private handleSelectionChange?;
|
|
16
|
+
constructor(autoexpand?: boolean, selectionMode?: Gtk.SelectionMode);
|
|
17
|
+
private createChildModel;
|
|
18
|
+
getStore(): TreeStore;
|
|
19
|
+
getTreeListModel(): Gtk.TreeListModel;
|
|
20
|
+
getSelectionModel(): Gtk.SingleSelection | Gtk.MultiSelection;
|
|
21
|
+
appendChild(child: Node): void;
|
|
22
|
+
insertBefore(child: Node, before: Node): void;
|
|
23
|
+
removeChild(child: Node): void;
|
|
24
|
+
updateProps(oldProps: TreeListProps | null, newProps: TreeListProps): void;
|
|
25
|
+
private createSelectionModel;
|
|
26
|
+
private getSelection;
|
|
27
|
+
private setSelection;
|
|
28
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { TreeStore } from "../internal/tree-store.js";
|
|
3
|
+
import { TreeListItemNode } from "../tree-list-item.js";
|
|
4
|
+
import { VirtualNode } from "../virtual.js";
|
|
5
|
+
export class TreeList extends VirtualNode {
|
|
6
|
+
store;
|
|
7
|
+
treeListModel;
|
|
8
|
+
selectionModel;
|
|
9
|
+
handleSelectionChange;
|
|
10
|
+
constructor(autoexpand = false, selectionMode) {
|
|
11
|
+
super("", {}, undefined);
|
|
12
|
+
this.store = new TreeStore();
|
|
13
|
+
this.treeListModel = new Gtk.TreeListModel(this.store.getRootModel(), false, autoexpand, (item) => this.createChildModel(item));
|
|
14
|
+
this.selectionModel = this.createSelectionModel(selectionMode);
|
|
15
|
+
this.selectionModel.setModel(this.treeListModel);
|
|
16
|
+
}
|
|
17
|
+
createChildModel(item) {
|
|
18
|
+
const stringObject = item;
|
|
19
|
+
const parentId = stringObject.getString();
|
|
20
|
+
return this.store.getChildrenModel(parentId);
|
|
21
|
+
}
|
|
22
|
+
getStore() {
|
|
23
|
+
return this.store;
|
|
24
|
+
}
|
|
25
|
+
getTreeListModel() {
|
|
26
|
+
return this.treeListModel;
|
|
27
|
+
}
|
|
28
|
+
getSelectionModel() {
|
|
29
|
+
return this.selectionModel;
|
|
30
|
+
}
|
|
31
|
+
appendChild(child) {
|
|
32
|
+
if (!(child instanceof TreeListItemNode)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!child.props.id) {
|
|
36
|
+
throw new Error("Cannot append 'TreeListItem' to 'TreeList': missing required 'id' prop");
|
|
37
|
+
}
|
|
38
|
+
child.setStore(this.store);
|
|
39
|
+
this.store.addItem(child.props.id, {
|
|
40
|
+
value: child.props.value,
|
|
41
|
+
indentForDepth: child.props.indentForDepth,
|
|
42
|
+
indentForIcon: child.props.indentForIcon,
|
|
43
|
+
hideExpander: child.props.hideExpander,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
insertBefore(child, before) {
|
|
47
|
+
if (!(child instanceof TreeListItemNode) || !(before instanceof TreeListItemNode)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!child.props.id) {
|
|
51
|
+
throw new Error("Cannot insert 'TreeListItem' into 'TreeList': missing required 'id' prop");
|
|
52
|
+
}
|
|
53
|
+
if (!before.props.id) {
|
|
54
|
+
throw new Error("Cannot insert 'TreeListItem' into 'TreeList': 'before' node missing required 'id' prop");
|
|
55
|
+
}
|
|
56
|
+
child.setStore(this.store);
|
|
57
|
+
this.store.insertItemBefore(child.props.id, before.props.id, {
|
|
58
|
+
value: child.props.value,
|
|
59
|
+
indentForDepth: child.props.indentForDepth,
|
|
60
|
+
indentForIcon: child.props.indentForIcon,
|
|
61
|
+
hideExpander: child.props.hideExpander,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
removeChild(child) {
|
|
65
|
+
if (!(child instanceof TreeListItemNode)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!child.props.id) {
|
|
69
|
+
throw new Error("Cannot remove 'TreeListItem' from 'TreeList': missing required 'id' prop");
|
|
70
|
+
}
|
|
71
|
+
this.store.removeItem(child.props.id);
|
|
72
|
+
child.setStore(undefined);
|
|
73
|
+
}
|
|
74
|
+
updateProps(oldProps, newProps) {
|
|
75
|
+
super.updateProps(oldProps, newProps);
|
|
76
|
+
if (!oldProps || oldProps.autoexpand !== newProps.autoexpand) {
|
|
77
|
+
this.treeListModel.setAutoexpand(newProps.autoexpand ?? false);
|
|
78
|
+
}
|
|
79
|
+
if (!oldProps || oldProps.selectionMode !== newProps.selectionMode) {
|
|
80
|
+
this.signalStore.set(this.selectionModel, "selection-changed", undefined);
|
|
81
|
+
this.selectionModel = this.createSelectionModel(newProps.selectionMode);
|
|
82
|
+
this.selectionModel.setModel(this.treeListModel);
|
|
83
|
+
}
|
|
84
|
+
if (!oldProps ||
|
|
85
|
+
oldProps.onSelectionChanged !== newProps.onSelectionChanged ||
|
|
86
|
+
oldProps.selectionMode !== newProps.selectionMode) {
|
|
87
|
+
const onSelectionChanged = newProps.onSelectionChanged;
|
|
88
|
+
this.handleSelectionChange = () => {
|
|
89
|
+
onSelectionChanged?.(this.getSelection());
|
|
90
|
+
};
|
|
91
|
+
this.signalStore.set(this.selectionModel, "selection-changed", newProps.onSelectionChanged ? this.handleSelectionChange : undefined);
|
|
92
|
+
}
|
|
93
|
+
if (!oldProps || oldProps.selected !== newProps.selected || oldProps.selectionMode !== newProps.selectionMode) {
|
|
94
|
+
this.setSelection(newProps.selected);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
createSelectionModel(mode) {
|
|
98
|
+
const selectionMode = mode ?? Gtk.SelectionMode.SINGLE;
|
|
99
|
+
const selectionModel = selectionMode === Gtk.SelectionMode.MULTIPLE
|
|
100
|
+
? new Gtk.MultiSelection(this.treeListModel)
|
|
101
|
+
: new Gtk.SingleSelection(this.treeListModel);
|
|
102
|
+
if (selectionModel instanceof Gtk.SingleSelection) {
|
|
103
|
+
selectionModel.setAutoselect(false);
|
|
104
|
+
selectionModel.setCanUnselect(true);
|
|
105
|
+
}
|
|
106
|
+
return selectionModel;
|
|
107
|
+
}
|
|
108
|
+
getSelection() {
|
|
109
|
+
const selection = this.selectionModel.getSelection();
|
|
110
|
+
const size = selection.getSize();
|
|
111
|
+
const ids = [];
|
|
112
|
+
for (let i = 0; i < size; i++) {
|
|
113
|
+
const index = selection.getNth(i);
|
|
114
|
+
const row = this.treeListModel.getRow(index);
|
|
115
|
+
if (!row)
|
|
116
|
+
continue;
|
|
117
|
+
const stringObject = row.getItem();
|
|
118
|
+
if (stringObject) {
|
|
119
|
+
ids.push(stringObject.getString());
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return ids;
|
|
123
|
+
}
|
|
124
|
+
setSelection(ids) {
|
|
125
|
+
const nItems = this.treeListModel.getNItems();
|
|
126
|
+
const selected = new Gtk.Bitset();
|
|
127
|
+
const mask = Gtk.Bitset.newRange(0, nItems);
|
|
128
|
+
if (ids) {
|
|
129
|
+
for (let i = 0; i < nItems; i++) {
|
|
130
|
+
const row = this.treeListModel.getRow(i);
|
|
131
|
+
if (!row)
|
|
132
|
+
continue;
|
|
133
|
+
const stringObject = row.getItem();
|
|
134
|
+
if (stringObject && ids.includes(stringObject.getString())) {
|
|
135
|
+
selected.add(i);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
this.selectionModel.setSelection(selected, mask);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Adw from "@gtkx/ffi/adw";
|
|
2
|
+
import type { AdwNavigationPageProps } from "../jsx.js";
|
|
3
|
+
import type { Node } from "../node.js";
|
|
4
|
+
import { VirtualNode } from "./virtual.js";
|
|
5
|
+
type Props = Partial<AdwNavigationPageProps>;
|
|
6
|
+
export declare class NavigationPageNode extends VirtualNode<Props> {
|
|
7
|
+
static priority: number;
|
|
8
|
+
private parent?;
|
|
9
|
+
private child?;
|
|
10
|
+
private page?;
|
|
11
|
+
static matches(type: string): boolean;
|
|
12
|
+
setParent(parent?: Adw.NavigationView): void;
|
|
13
|
+
appendChild(child: Node): void;
|
|
14
|
+
removeChild(): void;
|
|
15
|
+
unmount(): void;
|
|
16
|
+
updateProps(oldProps: Props | null, newProps: Props): void;
|
|
17
|
+
private onChildChange;
|
|
18
|
+
private addPage;
|
|
19
|
+
private removePage;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as Adw from "@gtkx/ffi/adw";
|
|
2
|
+
import { registerNodeClass } from "../registry.js";
|
|
3
|
+
import { scheduleAfterCommit } from "../scheduler.js";
|
|
4
|
+
import { VirtualNode } from "./virtual.js";
|
|
5
|
+
import { WidgetNode } from "./widget.js";
|
|
6
|
+
export class NavigationPageNode extends VirtualNode {
|
|
7
|
+
static priority = -1;
|
|
8
|
+
parent;
|
|
9
|
+
child;
|
|
10
|
+
page;
|
|
11
|
+
static matches(type) {
|
|
12
|
+
return type === "AdwNavigationPage";
|
|
13
|
+
}
|
|
14
|
+
setParent(parent) {
|
|
15
|
+
this.parent = parent;
|
|
16
|
+
}
|
|
17
|
+
appendChild(child) {
|
|
18
|
+
if (!(child instanceof WidgetNode)) {
|
|
19
|
+
throw new Error(`Cannot append '${child.typeName}' to 'NavigationPage': expected Widget`);
|
|
20
|
+
}
|
|
21
|
+
const oldChild = this.child;
|
|
22
|
+
this.child = child.container;
|
|
23
|
+
scheduleAfterCommit(() => {
|
|
24
|
+
if (this.parent) {
|
|
25
|
+
this.onChildChange(oldChild);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
removeChild() {
|
|
30
|
+
const oldChild = this.child;
|
|
31
|
+
scheduleAfterCommit(() => {
|
|
32
|
+
if (oldChild === this.child) {
|
|
33
|
+
this.child = undefined;
|
|
34
|
+
}
|
|
35
|
+
if (this.parent) {
|
|
36
|
+
this.onChildChange(oldChild);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
unmount() {
|
|
41
|
+
if (this.parent && this.child) {
|
|
42
|
+
const oldChild = this.child;
|
|
43
|
+
this.child = undefined;
|
|
44
|
+
this.onChildChange(oldChild);
|
|
45
|
+
}
|
|
46
|
+
this.parent = undefined;
|
|
47
|
+
super.unmount();
|
|
48
|
+
}
|
|
49
|
+
updateProps(oldProps, newProps) {
|
|
50
|
+
super.updateProps(oldProps, newProps);
|
|
51
|
+
if (!this.page) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (newProps.title && (!oldProps || oldProps.title !== newProps.title)) {
|
|
55
|
+
this.page.setTitle(newProps.title);
|
|
56
|
+
}
|
|
57
|
+
if (!oldProps || oldProps.tag !== newProps.tag) {
|
|
58
|
+
this.page.setTag(newProps.tag);
|
|
59
|
+
}
|
|
60
|
+
if (!oldProps || oldProps.canPop !== newProps.canPop) {
|
|
61
|
+
this.page.setCanPop(newProps.canPop ?? true);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
onChildChange(oldChild) {
|
|
65
|
+
if (oldChild) {
|
|
66
|
+
this.removePage();
|
|
67
|
+
}
|
|
68
|
+
if (this.child) {
|
|
69
|
+
this.addPage();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
addPage() {
|
|
73
|
+
if (!this.child || !this.parent) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
let page;
|
|
77
|
+
if (this.props.tag) {
|
|
78
|
+
page = Adw.NavigationPage.pageNewWithTag(this.child, this.props.title ?? "", this.props.tag);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
page = new Adw.NavigationPage(this.child, this.props.title ?? "");
|
|
82
|
+
}
|
|
83
|
+
this.page = page;
|
|
84
|
+
this.parent.add(page);
|
|
85
|
+
this.updateProps(null, this.props);
|
|
86
|
+
}
|
|
87
|
+
removePage() {
|
|
88
|
+
if (!this.page || !this.parent) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.parent.remove(this.page);
|
|
92
|
+
this.page = undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
registerNodeClass(NavigationPageNode);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Adw from "@gtkx/ffi/adw";
|
|
2
|
+
import { registerNodeClass } from "../registry.js";
|
|
3
|
+
import { isContainerType } from "./internal/utils.js";
|
|
4
|
+
import { NavigationPageNode } from "./navigation-page.js";
|
|
5
|
+
import { WidgetNode } from "./widget.js";
|
|
6
|
+
class NavigationViewNode extends WidgetNode {
|
|
7
|
+
static priority = -1;
|
|
8
|
+
static matches(_type, containerOrClass) {
|
|
9
|
+
return isContainerType(Adw.NavigationView, containerOrClass);
|
|
10
|
+
}
|
|
11
|
+
appendChild(child) {
|
|
12
|
+
if (child instanceof NavigationPageNode) {
|
|
13
|
+
child.setParent(this.container);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
super.appendChild(child);
|
|
17
|
+
}
|
|
18
|
+
insertBefore(child, _before) {
|
|
19
|
+
this.appendChild(child);
|
|
20
|
+
}
|
|
21
|
+
removeChild(child) {
|
|
22
|
+
if (child instanceof NavigationPageNode) {
|
|
23
|
+
child.unmount();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
super.removeChild(child);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
registerNodeClass(NavigationViewNode);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { SlotProps } from "../jsx.js";
|
|
3
|
+
import { SlotNode } from "./slot.js";
|
|
4
|
+
type Props = Partial<SlotProps>;
|
|
5
|
+
export declare class NotebookPageTabNode extends SlotNode<Props> {
|
|
6
|
+
static priority: number;
|
|
7
|
+
private notebook?;
|
|
8
|
+
private page?;
|
|
9
|
+
static matches(type: string): boolean;
|
|
10
|
+
setPage(notebook?: Gtk.Notebook, page?: Gtk.Widget): void;
|
|
11
|
+
private getNotebook;
|
|
12
|
+
private getPage;
|
|
13
|
+
protected onChildChange(_oldChild: Gtk.Widget | undefined): void;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { registerNodeClass } from "../registry.js";
|
|
2
|
+
import { SlotNode } from "./slot.js";
|
|
3
|
+
export class NotebookPageTabNode extends SlotNode {
|
|
4
|
+
static priority = 1;
|
|
5
|
+
notebook;
|
|
6
|
+
page;
|
|
7
|
+
static matches(type) {
|
|
8
|
+
return type === "Notebook.PageTab";
|
|
9
|
+
}
|
|
10
|
+
setPage(notebook, page) {
|
|
11
|
+
this.notebook = notebook;
|
|
12
|
+
this.page = page;
|
|
13
|
+
this.setParent(notebook);
|
|
14
|
+
}
|
|
15
|
+
getNotebook() {
|
|
16
|
+
if (!this.notebook) {
|
|
17
|
+
throw new Error("Expected Notebook reference to be set on NotebookPageTabNode");
|
|
18
|
+
}
|
|
19
|
+
return this.notebook;
|
|
20
|
+
}
|
|
21
|
+
getPage() {
|
|
22
|
+
if (!this.page) {
|
|
23
|
+
throw new Error("Expected page reference to be set on NotebookPageTabNode");
|
|
24
|
+
}
|
|
25
|
+
return this.page;
|
|
26
|
+
}
|
|
27
|
+
onChildChange(_oldChild) {
|
|
28
|
+
if (!this.notebook || !this.page) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const notebook = this.getNotebook();
|
|
32
|
+
const page = this.getPage();
|
|
33
|
+
// Only call setTabLabel if the page is actually in the notebook
|
|
34
|
+
// (pageNum returns -1 if not found)
|
|
35
|
+
if (notebook.pageNum(page) === -1) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// setTabLabel accepts undefined to reset to default
|
|
39
|
+
notebook.setTabLabel(page, this.child);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
registerNodeClass(NotebookPageTabNode);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { NotebookPageProps } from "../jsx.js";
|
|
3
|
+
import type { Node } from "../node.js";
|
|
4
|
+
import { SlotNode } from "./slot.js";
|
|
5
|
+
type Props = Partial<NotebookPageProps>;
|
|
6
|
+
export declare class NotebookPageNode extends SlotNode<Props> {
|
|
7
|
+
static priority: number;
|
|
8
|
+
position?: number;
|
|
9
|
+
private tabNode?;
|
|
10
|
+
static matches(type: string): boolean;
|
|
11
|
+
setNotebook(notebook?: Gtk.Notebook): void;
|
|
12
|
+
setPosition(position?: number): void;
|
|
13
|
+
private getNotebook;
|
|
14
|
+
private updateTabNode;
|
|
15
|
+
appendChild(child: Node): void;
|
|
16
|
+
removeChild(child?: Node): void;
|
|
17
|
+
unmount(): void;
|
|
18
|
+
updateProps(oldProps: Props | null, newProps: Props): void;
|
|
19
|
+
private attachPage;
|
|
20
|
+
private detachPage;
|
|
21
|
+
protected onChildChange(oldChild: Gtk.Widget | undefined): void;
|
|
22
|
+
}
|
|
23
|
+
export {};
|