@gtkx/react 0.1.49 → 0.1.51
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 +7 -12
- package/dist/codegen/jsx-generator.d.ts +12 -2
- package/dist/codegen/jsx-generator.js +128 -26
- package/dist/container-interfaces.d.ts +21 -0
- package/dist/container-interfaces.js +1 -0
- package/dist/factory.js +13 -1
- package/dist/generated/internal.d.ts +7 -0
- package/dist/generated/internal.js +7818 -0
- package/dist/generated/jsx.d.ts +68 -17
- package/dist/generated/jsx.js +56 -7820
- package/dist/node.d.ts +11 -2
- package/dist/node.js +24 -5
- package/dist/nodes/column-view.d.ts +36 -26
- package/dist/nodes/column-view.js +122 -125
- package/dist/nodes/dropdown.d.ts +2 -2
- package/dist/nodes/dropdown.js +4 -4
- package/dist/nodes/grid.d.ts +1 -1
- package/dist/nodes/grid.js +6 -6
- package/dist/nodes/list.d.ts +19 -10
- package/dist/nodes/list.js +45 -40
- package/dist/nodes/menu.d.ts +84 -0
- package/dist/nodes/menu.js +279 -0
- package/dist/nodes/notebook.d.ts +1 -1
- package/dist/nodes/notebook.js +3 -3
- package/dist/nodes/root.js +1 -1
- package/dist/nodes/slot.d.ts +1 -2
- package/dist/nodes/slot.js +2 -2
- package/dist/nodes/stack.d.ts +35 -0
- package/dist/nodes/stack.js +178 -0
- package/dist/nodes/text-view.d.ts +0 -1
- package/dist/nodes/text-view.js +0 -7
- package/dist/reconciler.d.ts +4 -1
- package/dist/reconciler.js +4 -1
- package/dist/types.d.ts +76 -0
- package/package.json +3 -3
package/dist/nodes/grid.js
CHANGED
|
@@ -19,18 +19,18 @@ export class GridChildNode extends Node {
|
|
|
19
19
|
isVirtual() {
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
|
-
column;
|
|
23
|
-
row;
|
|
24
|
-
columnSpan;
|
|
25
|
-
rowSpan;
|
|
22
|
+
column = 0;
|
|
23
|
+
row = 0;
|
|
24
|
+
columnSpan = 1;
|
|
25
|
+
rowSpan = 1;
|
|
26
26
|
childWidget = null;
|
|
27
27
|
parentContainer = null;
|
|
28
|
-
|
|
29
|
-
super(type, props);
|
|
28
|
+
initialize(props) {
|
|
30
29
|
this.column = getNumberProp(props, "column", 0);
|
|
31
30
|
this.row = getNumberProp(props, "row", 0);
|
|
32
31
|
this.columnSpan = getNumberProp(props, "columnSpan", 1);
|
|
33
32
|
this.rowSpan = getNumberProp(props, "rowSpan", 1);
|
|
33
|
+
super.initialize(props);
|
|
34
34
|
}
|
|
35
35
|
appendChild(child) {
|
|
36
36
|
const widget = child.getWidget();
|
package/dist/nodes/list.d.ts
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type Reconciler from "react-reconciler";
|
|
2
3
|
import { type ItemContainer } from "../container-interfaces.js";
|
|
3
4
|
import type { Props } from "../factory.js";
|
|
4
5
|
import { Node } from "../node.js";
|
|
5
|
-
|
|
6
|
+
import type { RenderItemFn } from "../types.js";
|
|
7
|
+
interface ListItemInfo {
|
|
8
|
+
box: Gtk.Box;
|
|
9
|
+
fiberRoot: Reconciler.FiberRoot;
|
|
10
|
+
}
|
|
11
|
+
interface ListViewState {
|
|
12
|
+
stringList: Gtk.StringList;
|
|
13
|
+
selectionModel: Gtk.SingleSelection;
|
|
14
|
+
factory: Gtk.SignalListItemFactory;
|
|
15
|
+
renderItem: RenderItemFn<unknown>;
|
|
16
|
+
listItemCache: Map<number, ListItemInfo>;
|
|
17
|
+
items: unknown[];
|
|
18
|
+
committedLength: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView, ListViewState> implements ItemContainer<unknown> {
|
|
6
21
|
static matches(type: string): boolean;
|
|
7
|
-
|
|
8
|
-
private selectionModel;
|
|
9
|
-
private factory;
|
|
10
|
-
private items;
|
|
11
|
-
private renderItem;
|
|
12
|
-
private listItemCache;
|
|
13
|
-
private committedLength;
|
|
14
|
-
constructor(type: string, props: Props);
|
|
22
|
+
initialize(props: Props): void;
|
|
15
23
|
private syncStringList;
|
|
16
24
|
addItem(item: unknown): void;
|
|
17
25
|
insertItemBefore(item: unknown, beforeItem: unknown): void;
|
|
@@ -23,9 +31,10 @@ export declare class ListItemNode extends Node {
|
|
|
23
31
|
static matches(type: string): boolean;
|
|
24
32
|
protected isVirtual(): boolean;
|
|
25
33
|
private item;
|
|
26
|
-
|
|
34
|
+
initialize(props: Props): void;
|
|
27
35
|
getItem(): unknown;
|
|
28
36
|
attachToParent(parent: Node): void;
|
|
29
37
|
attachToParentBefore(parent: Node, before: Node): void;
|
|
30
38
|
detachFromParent(parent: Node): void;
|
|
31
39
|
}
|
|
40
|
+
export {};
|
package/dist/nodes/list.js
CHANGED
|
@@ -9,84 +9,89 @@ export class ListViewNode extends Node {
|
|
|
9
9
|
static matches(type) {
|
|
10
10
|
return type === "ListView.Root" || type === "GridView.Root";
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
initialize(props) {
|
|
13
|
+
// Initialize state before super.initialize() since updateProps accesses this.state
|
|
14
|
+
this.state = {
|
|
15
|
+
stringList: null,
|
|
16
|
+
selectionModel: null,
|
|
17
|
+
factory: null,
|
|
18
|
+
renderItem: props.renderItem,
|
|
19
|
+
listItemCache: new Map(),
|
|
20
|
+
items: [],
|
|
21
|
+
committedLength: 0,
|
|
22
|
+
};
|
|
23
|
+
super.initialize(props);
|
|
24
|
+
const stringList = new Gtk.StringList([]);
|
|
25
|
+
const selectionModel = new Gtk.SingleSelection(stringList);
|
|
26
|
+
const factory = new Gtk.SignalListItemFactory();
|
|
27
|
+
this.state.stringList = stringList;
|
|
28
|
+
this.state.selectionModel = selectionModel;
|
|
29
|
+
this.state.factory = factory;
|
|
30
|
+
factory.connect("setup", (_self, listItemObj) => {
|
|
26
31
|
const listItem = getObject(listItemObj.ptr, Gtk.ListItem);
|
|
27
32
|
const id = getObjectId(listItemObj.ptr);
|
|
28
33
|
const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
|
|
29
34
|
listItem.setChild(box);
|
|
30
35
|
const fiberRoot = createFiberRoot(box);
|
|
31
|
-
this.listItemCache.set(id, { box, fiberRoot });
|
|
32
|
-
const element = this.renderItem(null);
|
|
36
|
+
this.state.listItemCache.set(id, { box, fiberRoot });
|
|
37
|
+
const element = this.state.renderItem(null);
|
|
33
38
|
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
|
|
34
39
|
});
|
|
35
|
-
|
|
40
|
+
factory.connect("bind", (_self, listItemObj) => {
|
|
36
41
|
const listItem = getObject(listItemObj.ptr, Gtk.ListItem);
|
|
37
42
|
const id = getObjectId(listItemObj.ptr);
|
|
38
|
-
const info = this.listItemCache.get(id);
|
|
43
|
+
const info = this.state.listItemCache.get(id);
|
|
39
44
|
if (!info)
|
|
40
45
|
return;
|
|
41
46
|
const position = listItem.getPosition();
|
|
42
|
-
const item = this.items[position];
|
|
43
|
-
const element = this.renderItem(item);
|
|
47
|
+
const item = this.state.items[position];
|
|
48
|
+
const element = this.state.renderItem(item);
|
|
44
49
|
reconciler.getInstance().updateContainer(element, info.fiberRoot, null, () => { });
|
|
45
50
|
});
|
|
46
|
-
|
|
51
|
+
factory.connect("unbind", (_self, listItemObj) => {
|
|
47
52
|
const id = getObjectId(listItemObj.ptr);
|
|
48
|
-
const info = this.listItemCache.get(id);
|
|
53
|
+
const info = this.state.listItemCache.get(id);
|
|
49
54
|
if (!info)
|
|
50
55
|
return;
|
|
51
56
|
reconciler.getInstance().updateContainer(null, info.fiberRoot, null, () => { });
|
|
52
57
|
});
|
|
53
|
-
|
|
58
|
+
factory.connect("teardown", (_self, listItemObj) => {
|
|
54
59
|
const id = getObjectId(listItemObj.ptr);
|
|
55
|
-
const info = this.listItemCache.get(id);
|
|
60
|
+
const info = this.state.listItemCache.get(id);
|
|
56
61
|
if (info) {
|
|
57
62
|
reconciler.getInstance().updateContainer(null, info.fiberRoot, null, () => { });
|
|
58
|
-
this.listItemCache.delete(id);
|
|
63
|
+
this.state.listItemCache.delete(id);
|
|
59
64
|
}
|
|
60
65
|
});
|
|
61
|
-
this.widget.setModel(
|
|
62
|
-
this.widget.setFactory(
|
|
66
|
+
this.widget.setModel(selectionModel);
|
|
67
|
+
this.widget.setFactory(factory);
|
|
63
68
|
}
|
|
64
69
|
syncStringList = () => {
|
|
65
|
-
const newLength = this.items.length;
|
|
66
|
-
if (newLength === this.committedLength)
|
|
70
|
+
const newLength = this.state.items.length;
|
|
71
|
+
if (newLength === this.state.committedLength)
|
|
67
72
|
return;
|
|
68
73
|
const placeholders = Array.from({ length: newLength }, () => "");
|
|
69
|
-
this.stringList.splice(0, this.committedLength, placeholders);
|
|
70
|
-
this.committedLength = newLength;
|
|
74
|
+
this.state.stringList.splice(0, this.state.committedLength, placeholders);
|
|
75
|
+
this.state.committedLength = newLength;
|
|
71
76
|
};
|
|
72
77
|
addItem(item) {
|
|
73
|
-
this.items.push(item);
|
|
78
|
+
this.state.items.push(item);
|
|
74
79
|
scheduleFlush(this.syncStringList);
|
|
75
80
|
}
|
|
76
81
|
insertItemBefore(item, beforeItem) {
|
|
77
|
-
const beforeIndex = this.items.indexOf(beforeItem);
|
|
82
|
+
const beforeIndex = this.state.items.indexOf(beforeItem);
|
|
78
83
|
if (beforeIndex === -1) {
|
|
79
|
-
this.items.push(item);
|
|
84
|
+
this.state.items.push(item);
|
|
80
85
|
}
|
|
81
86
|
else {
|
|
82
|
-
this.items.splice(beforeIndex, 0, item);
|
|
87
|
+
this.state.items.splice(beforeIndex, 0, item);
|
|
83
88
|
}
|
|
84
89
|
scheduleFlush(this.syncStringList);
|
|
85
90
|
}
|
|
86
91
|
removeItem(item) {
|
|
87
|
-
const index = this.items.indexOf(item);
|
|
92
|
+
const index = this.state.items.indexOf(item);
|
|
88
93
|
if (index !== -1) {
|
|
89
|
-
this.items.splice(index, 1);
|
|
94
|
+
this.state.items.splice(index, 1);
|
|
90
95
|
scheduleFlush(this.syncStringList);
|
|
91
96
|
}
|
|
92
97
|
}
|
|
@@ -97,7 +102,7 @@ export class ListViewNode extends Node {
|
|
|
97
102
|
}
|
|
98
103
|
updateProps(oldProps, newProps) {
|
|
99
104
|
if (oldProps.renderItem !== newProps.renderItem) {
|
|
100
|
-
this.renderItem = newProps.renderItem;
|
|
105
|
+
this.state.renderItem = newProps.renderItem;
|
|
101
106
|
}
|
|
102
107
|
super.updateProps(oldProps, newProps);
|
|
103
108
|
}
|
|
@@ -110,9 +115,9 @@ export class ListItemNode extends Node {
|
|
|
110
115
|
return true;
|
|
111
116
|
}
|
|
112
117
|
item;
|
|
113
|
-
|
|
114
|
-
super(type, props);
|
|
118
|
+
initialize(props) {
|
|
115
119
|
this.item = props.item;
|
|
120
|
+
super.initialize(props);
|
|
116
121
|
}
|
|
117
122
|
getItem() {
|
|
118
123
|
return this.item;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as Gio from "@gtkx/ffi/gio";
|
|
2
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
+
import type { Props } from "../factory.js";
|
|
4
|
+
import { Node } from "../node.js";
|
|
5
|
+
interface MenuEntry {
|
|
6
|
+
type: "item" | "section" | "submenu";
|
|
7
|
+
label?: string;
|
|
8
|
+
action?: string;
|
|
9
|
+
menu?: Gio.Menu;
|
|
10
|
+
}
|
|
11
|
+
interface MenuContainer {
|
|
12
|
+
getMenu(): Gio.Menu;
|
|
13
|
+
addMenuEntry(entry: MenuEntry): void;
|
|
14
|
+
removeMenuEntry(entry: MenuEntry): void;
|
|
15
|
+
}
|
|
16
|
+
declare abstract class MenuContainerNode<T extends Gtk.Widget | undefined> extends Node<T> implements MenuContainer {
|
|
17
|
+
protected menu: Gio.Menu;
|
|
18
|
+
protected entries: MenuEntry[];
|
|
19
|
+
private rebuildScheduled;
|
|
20
|
+
getMenu(): Gio.Menu;
|
|
21
|
+
addMenuEntry(entry: MenuEntry): void;
|
|
22
|
+
removeMenuEntry(entry: MenuEntry): void;
|
|
23
|
+
private scheduleRebuild;
|
|
24
|
+
protected rebuildMenu(): void;
|
|
25
|
+
protected onMenuRebuilt(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare class PopoverMenuRootNode extends MenuContainerNode<Gtk.PopoverMenu> {
|
|
28
|
+
static matches(type: string): boolean;
|
|
29
|
+
initialize(props: Props): void;
|
|
30
|
+
protected onMenuRebuilt(): void;
|
|
31
|
+
}
|
|
32
|
+
export declare class PopoverMenuBarNode extends MenuContainerNode<Gtk.PopoverMenuBar> {
|
|
33
|
+
static matches(type: string): boolean;
|
|
34
|
+
initialize(props: Props): void;
|
|
35
|
+
protected onMenuRebuilt(): void;
|
|
36
|
+
}
|
|
37
|
+
export declare class ApplicationMenuNode extends MenuContainerNode<never> {
|
|
38
|
+
static matches(type: string): boolean;
|
|
39
|
+
protected isVirtual(): boolean;
|
|
40
|
+
detachFromParent(_parent: Node): void;
|
|
41
|
+
attachToParent(parent: Node): void;
|
|
42
|
+
mount(): void;
|
|
43
|
+
protected onMenuRebuilt(): void;
|
|
44
|
+
}
|
|
45
|
+
export declare class MenuItemNode extends Node<never> {
|
|
46
|
+
static matches(type: string): boolean;
|
|
47
|
+
protected isVirtual(): boolean;
|
|
48
|
+
private entry;
|
|
49
|
+
private action;
|
|
50
|
+
private actionName;
|
|
51
|
+
private signalHandlerId;
|
|
52
|
+
private onActivateCallback;
|
|
53
|
+
private currentAccels;
|
|
54
|
+
private isAttached;
|
|
55
|
+
initialize(props: Props): void;
|
|
56
|
+
attachToParent(parent: Node): void;
|
|
57
|
+
detachFromParent(parent: Node): void;
|
|
58
|
+
protected consumedProps(): Set<string>;
|
|
59
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
60
|
+
private setupAction;
|
|
61
|
+
private cleanupAction;
|
|
62
|
+
private updateAccels;
|
|
63
|
+
}
|
|
64
|
+
export declare class MenuSectionNode extends MenuContainerNode<never> {
|
|
65
|
+
static matches(type: string): boolean;
|
|
66
|
+
protected isVirtual(): boolean;
|
|
67
|
+
private entry;
|
|
68
|
+
initialize(props: Props): void;
|
|
69
|
+
attachToParent(parent: Node): void;
|
|
70
|
+
detachFromParent(parent: Node): void;
|
|
71
|
+
protected consumedProps(): Set<string>;
|
|
72
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
73
|
+
}
|
|
74
|
+
export declare class MenuSubmenuNode extends MenuContainerNode<never> {
|
|
75
|
+
static matches(type: string): boolean;
|
|
76
|
+
protected isVirtual(): boolean;
|
|
77
|
+
private entry;
|
|
78
|
+
initialize(props: Props): void;
|
|
79
|
+
attachToParent(parent: Node): void;
|
|
80
|
+
detachFromParent(parent: Node): void;
|
|
81
|
+
protected consumedProps(): Set<string>;
|
|
82
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
83
|
+
}
|
|
84
|
+
export {};
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { getCurrentApp } from "@gtkx/ffi";
|
|
2
|
+
import * as Gio from "@gtkx/ffi/gio";
|
|
3
|
+
import * as GObject from "@gtkx/ffi/gobject";
|
|
4
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
5
|
+
import { Node } from "../node.js";
|
|
6
|
+
import { RootNode } from "./root.js";
|
|
7
|
+
let actionCounter = 0;
|
|
8
|
+
const generateActionName = () => `gtkx_menu_action_${actionCounter++}`;
|
|
9
|
+
const isMenuContainer = (node) => "getMenu" in node && "addMenuEntry" in node && "removeMenuEntry" in node;
|
|
10
|
+
class MenuContainerNode extends Node {
|
|
11
|
+
menu = new Gio.Menu();
|
|
12
|
+
entries = [];
|
|
13
|
+
rebuildScheduled = false;
|
|
14
|
+
getMenu() {
|
|
15
|
+
return this.menu;
|
|
16
|
+
}
|
|
17
|
+
addMenuEntry(entry) {
|
|
18
|
+
this.entries.push(entry);
|
|
19
|
+
this.scheduleRebuild();
|
|
20
|
+
}
|
|
21
|
+
removeMenuEntry(entry) {
|
|
22
|
+
const index = this.entries.indexOf(entry);
|
|
23
|
+
if (index !== -1) {
|
|
24
|
+
this.entries.splice(index, 1);
|
|
25
|
+
this.scheduleRebuild();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
scheduleRebuild() {
|
|
29
|
+
if (this.rebuildScheduled)
|
|
30
|
+
return;
|
|
31
|
+
this.rebuildScheduled = true;
|
|
32
|
+
queueMicrotask(() => {
|
|
33
|
+
this.rebuildScheduled = false;
|
|
34
|
+
this.rebuildMenu();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
rebuildMenu() {
|
|
38
|
+
this.menu.removeAll();
|
|
39
|
+
for (const entry of this.entries) {
|
|
40
|
+
if (entry.type === "item") {
|
|
41
|
+
this.menu.append(entry.label ?? null, entry.action ?? null);
|
|
42
|
+
}
|
|
43
|
+
else if (entry.type === "section" && entry.menu) {
|
|
44
|
+
this.menu.appendSection(entry.menu, entry.label ?? null);
|
|
45
|
+
}
|
|
46
|
+
else if (entry.type === "submenu" && entry.menu) {
|
|
47
|
+
this.menu.appendSubmenu(entry.menu, entry.label ?? null);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
this.onMenuRebuilt();
|
|
51
|
+
}
|
|
52
|
+
onMenuRebuilt() { }
|
|
53
|
+
}
|
|
54
|
+
export class PopoverMenuRootNode extends MenuContainerNode {
|
|
55
|
+
static matches(type) {
|
|
56
|
+
return type === "PopoverMenu.Root";
|
|
57
|
+
}
|
|
58
|
+
initialize(props) {
|
|
59
|
+
this.widget = new Gtk.PopoverMenu(this.menu);
|
|
60
|
+
super.initialize(props);
|
|
61
|
+
}
|
|
62
|
+
onMenuRebuilt() {
|
|
63
|
+
this.widget.setMenuModel(this.menu);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export class PopoverMenuBarNode extends MenuContainerNode {
|
|
67
|
+
static matches(type) {
|
|
68
|
+
return type === "PopoverMenuBar";
|
|
69
|
+
}
|
|
70
|
+
initialize(props) {
|
|
71
|
+
this.widget = new Gtk.PopoverMenuBar(this.menu);
|
|
72
|
+
super.initialize(props);
|
|
73
|
+
}
|
|
74
|
+
onMenuRebuilt() {
|
|
75
|
+
this.widget.setMenuModel(this.menu);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export class ApplicationMenuNode extends MenuContainerNode {
|
|
79
|
+
static matches(type) {
|
|
80
|
+
return type === "ApplicationMenu";
|
|
81
|
+
}
|
|
82
|
+
isVirtual() {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
detachFromParent(_parent) {
|
|
86
|
+
getCurrentApp().setMenubar(null);
|
|
87
|
+
}
|
|
88
|
+
attachToParent(parent) {
|
|
89
|
+
if (!(parent instanceof RootNode)) {
|
|
90
|
+
throw new Error("ApplicationMenu must be a direct child of a fragment at the root level");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
mount() {
|
|
94
|
+
getCurrentApp().setMenubar(this.menu);
|
|
95
|
+
}
|
|
96
|
+
onMenuRebuilt() {
|
|
97
|
+
getCurrentApp().setMenubar(this.menu);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export class MenuItemNode extends Node {
|
|
101
|
+
static matches(type) {
|
|
102
|
+
return type === "Menu.Item";
|
|
103
|
+
}
|
|
104
|
+
isVirtual() {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
entry = { type: "item" };
|
|
108
|
+
action = null;
|
|
109
|
+
actionName = null;
|
|
110
|
+
signalHandlerId = null;
|
|
111
|
+
onActivateCallback;
|
|
112
|
+
currentAccels;
|
|
113
|
+
isAttached = false;
|
|
114
|
+
initialize(props) {
|
|
115
|
+
this.onActivateCallback = props.onActivate;
|
|
116
|
+
this.currentAccels = props.accels;
|
|
117
|
+
this.entry.label = props.label;
|
|
118
|
+
super.initialize(props);
|
|
119
|
+
}
|
|
120
|
+
attachToParent(parent) {
|
|
121
|
+
if (!isMenuContainer(parent))
|
|
122
|
+
return;
|
|
123
|
+
this.isAttached = true;
|
|
124
|
+
this.setupAction();
|
|
125
|
+
parent.addMenuEntry(this.entry);
|
|
126
|
+
}
|
|
127
|
+
detachFromParent(parent) {
|
|
128
|
+
if (!isMenuContainer(parent))
|
|
129
|
+
return;
|
|
130
|
+
parent.removeMenuEntry(this.entry);
|
|
131
|
+
this.cleanupAction();
|
|
132
|
+
this.isAttached = false;
|
|
133
|
+
}
|
|
134
|
+
consumedProps() {
|
|
135
|
+
const consumed = super.consumedProps();
|
|
136
|
+
consumed.add("label");
|
|
137
|
+
consumed.add("onActivate");
|
|
138
|
+
consumed.add("accels");
|
|
139
|
+
return consumed;
|
|
140
|
+
}
|
|
141
|
+
updateProps(oldProps, newProps) {
|
|
142
|
+
// If entry doesn't exist yet, fields aren't initialized
|
|
143
|
+
// This happens when base class constructor calls updateProps
|
|
144
|
+
// before derived class field initializers run - skip in that case
|
|
145
|
+
if (!this.entry) {
|
|
146
|
+
super.updateProps(oldProps, newProps);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const labelChanged = oldProps.label !== newProps.label;
|
|
150
|
+
const hadCallback = oldProps.onActivate !== undefined;
|
|
151
|
+
const hasCallback = newProps.onActivate !== undefined;
|
|
152
|
+
const accelsChanged = oldProps.accels !== newProps.accels;
|
|
153
|
+
// Always update the callback reference - the signal handler uses this
|
|
154
|
+
this.onActivateCallback = newProps.onActivate;
|
|
155
|
+
this.currentAccels = newProps.accels;
|
|
156
|
+
if (labelChanged) {
|
|
157
|
+
this.entry.label = newProps.label;
|
|
158
|
+
}
|
|
159
|
+
// Only cleanup/setup action if the presence of a callback changed
|
|
160
|
+
// (not when the callback reference changes - we store the ref and call it)
|
|
161
|
+
if (this.isAttached && hadCallback !== hasCallback) {
|
|
162
|
+
this.cleanupAction();
|
|
163
|
+
this.setupAction();
|
|
164
|
+
}
|
|
165
|
+
if (accelsChanged && this.actionName) {
|
|
166
|
+
this.updateAccels(this.currentAccels);
|
|
167
|
+
}
|
|
168
|
+
super.updateProps(oldProps, newProps);
|
|
169
|
+
}
|
|
170
|
+
setupAction() {
|
|
171
|
+
if (!this.onActivateCallback)
|
|
172
|
+
return;
|
|
173
|
+
this.actionName = generateActionName();
|
|
174
|
+
this.action = new Gio.SimpleAction(this.actionName);
|
|
175
|
+
this.signalHandlerId = this.action.connect("activate", () => {
|
|
176
|
+
// Call the current callback (may have been updated via updateProps)
|
|
177
|
+
this.onActivateCallback?.();
|
|
178
|
+
});
|
|
179
|
+
const app = getCurrentApp();
|
|
180
|
+
app.addAction(this.action);
|
|
181
|
+
this.entry.action = `app.${this.actionName}`;
|
|
182
|
+
if (this.currentAccels) {
|
|
183
|
+
this.updateAccels(this.currentAccels);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
cleanupAction() {
|
|
187
|
+
if (this.actionName) {
|
|
188
|
+
const app = getCurrentApp();
|
|
189
|
+
app.removeAction(this.actionName);
|
|
190
|
+
if (this.currentAccels) {
|
|
191
|
+
app.setAccelsForAction(`app.${this.actionName}`, []);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (this.action && this.signalHandlerId !== null) {
|
|
195
|
+
GObject.signalHandlerDisconnect(this.action, this.signalHandlerId);
|
|
196
|
+
}
|
|
197
|
+
this.action = null;
|
|
198
|
+
this.actionName = null;
|
|
199
|
+
this.signalHandlerId = null;
|
|
200
|
+
this.entry.action = undefined;
|
|
201
|
+
}
|
|
202
|
+
updateAccels(accels) {
|
|
203
|
+
if (!this.actionName)
|
|
204
|
+
return;
|
|
205
|
+
const app = getCurrentApp();
|
|
206
|
+
const accelArray = accels ? (Array.isArray(accels) ? accels : [accels]) : [];
|
|
207
|
+
app.setAccelsForAction(`app.${this.actionName}`, accelArray);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
export class MenuSectionNode extends MenuContainerNode {
|
|
211
|
+
static matches(type) {
|
|
212
|
+
return type === "Menu.Section";
|
|
213
|
+
}
|
|
214
|
+
isVirtual() {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
entry = { type: "section" };
|
|
218
|
+
initialize(props) {
|
|
219
|
+
this.entry.menu = this.menu;
|
|
220
|
+
this.entry.label = props.label;
|
|
221
|
+
super.initialize(props);
|
|
222
|
+
}
|
|
223
|
+
attachToParent(parent) {
|
|
224
|
+
if (!isMenuContainer(parent))
|
|
225
|
+
return;
|
|
226
|
+
parent.addMenuEntry(this.entry);
|
|
227
|
+
}
|
|
228
|
+
detachFromParent(parent) {
|
|
229
|
+
if (!isMenuContainer(parent))
|
|
230
|
+
return;
|
|
231
|
+
parent.removeMenuEntry(this.entry);
|
|
232
|
+
}
|
|
233
|
+
consumedProps() {
|
|
234
|
+
const consumed = super.consumedProps();
|
|
235
|
+
consumed.add("label");
|
|
236
|
+
return consumed;
|
|
237
|
+
}
|
|
238
|
+
updateProps(oldProps, newProps) {
|
|
239
|
+
if (oldProps.label !== newProps.label && this.entry) {
|
|
240
|
+
this.entry.label = newProps.label;
|
|
241
|
+
}
|
|
242
|
+
super.updateProps(oldProps, newProps);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export class MenuSubmenuNode extends MenuContainerNode {
|
|
246
|
+
static matches(type) {
|
|
247
|
+
return type === "Menu.Submenu";
|
|
248
|
+
}
|
|
249
|
+
isVirtual() {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
entry = { type: "submenu" };
|
|
253
|
+
initialize(props) {
|
|
254
|
+
this.entry.menu = this.menu;
|
|
255
|
+
this.entry.label = props.label;
|
|
256
|
+
super.initialize(props);
|
|
257
|
+
}
|
|
258
|
+
attachToParent(parent) {
|
|
259
|
+
if (!isMenuContainer(parent))
|
|
260
|
+
return;
|
|
261
|
+
parent.addMenuEntry(this.entry);
|
|
262
|
+
}
|
|
263
|
+
detachFromParent(parent) {
|
|
264
|
+
if (!isMenuContainer(parent))
|
|
265
|
+
return;
|
|
266
|
+
parent.removeMenuEntry(this.entry);
|
|
267
|
+
}
|
|
268
|
+
consumedProps() {
|
|
269
|
+
const consumed = super.consumedProps();
|
|
270
|
+
consumed.add("label");
|
|
271
|
+
return consumed;
|
|
272
|
+
}
|
|
273
|
+
updateProps(oldProps, newProps) {
|
|
274
|
+
if (oldProps.label !== newProps.label && this.entry) {
|
|
275
|
+
this.entry.label = newProps.label;
|
|
276
|
+
}
|
|
277
|
+
super.updateProps(oldProps, newProps);
|
|
278
|
+
}
|
|
279
|
+
}
|
package/dist/nodes/notebook.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare class NotebookPageNode extends Node {
|
|
|
18
18
|
private label;
|
|
19
19
|
private childWidget;
|
|
20
20
|
private parentContainer;
|
|
21
|
-
|
|
21
|
+
initialize(props: Props): void;
|
|
22
22
|
getLabel(): string;
|
|
23
23
|
setChildWidget(widget: Gtk.Widget): void;
|
|
24
24
|
getChildWidget(): Gtk.Widget | null;
|
package/dist/nodes/notebook.js
CHANGED
|
@@ -56,12 +56,12 @@ export class NotebookPageNode extends Node {
|
|
|
56
56
|
isVirtual() {
|
|
57
57
|
return true;
|
|
58
58
|
}
|
|
59
|
-
label;
|
|
59
|
+
label = "";
|
|
60
60
|
childWidget = null;
|
|
61
61
|
parentContainer = null;
|
|
62
|
-
|
|
63
|
-
super(type, props);
|
|
62
|
+
initialize(props) {
|
|
64
63
|
this.label = getStringProp(props, "label", "");
|
|
64
|
+
super.initialize(props);
|
|
65
65
|
}
|
|
66
66
|
getLabel() {
|
|
67
67
|
return this.label;
|
package/dist/nodes/root.js
CHANGED
package/dist/nodes/slot.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Props } from "../factory.js";
|
|
2
1
|
import { Node } from "../node.js";
|
|
3
2
|
export declare class SlotNode extends Node<never> {
|
|
4
3
|
static matches(type: string): boolean;
|
|
@@ -6,7 +5,7 @@ export declare class SlotNode extends Node<never> {
|
|
|
6
5
|
private child;
|
|
7
6
|
private slotName;
|
|
8
7
|
private parentNode;
|
|
9
|
-
constructor(type: string
|
|
8
|
+
constructor(type: string);
|
|
10
9
|
private updateParentSlot;
|
|
11
10
|
appendChild(child: Node): void;
|
|
12
11
|
removeChild(_child: Node): void;
|
package/dist/nodes/slot.js
CHANGED
|
@@ -15,8 +15,8 @@ export class SlotNode extends Node {
|
|
|
15
15
|
child = null;
|
|
16
16
|
slotName;
|
|
17
17
|
parentNode = null;
|
|
18
|
-
constructor(type
|
|
19
|
-
super(type
|
|
18
|
+
constructor(type) {
|
|
19
|
+
super(type);
|
|
20
20
|
const dotIndex = type.indexOf(".");
|
|
21
21
|
if (dotIndex === -1) {
|
|
22
22
|
throw new Error(`Invalid slot type: ${type}`);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { type ChildContainer, type StackPageContainer, type StackPageProps } from "../container-interfaces.js";
|
|
3
|
+
import type { Props } from "../factory.js";
|
|
4
|
+
import { Node } from "../node.js";
|
|
5
|
+
export declare class StackNode extends Node<Gtk.Stack> implements StackPageContainer, ChildContainer {
|
|
6
|
+
static matches(type: string): boolean;
|
|
7
|
+
private pendingVisibleChildName;
|
|
8
|
+
addStackPage(child: Gtk.Widget, props: StackPageProps): void;
|
|
9
|
+
private applyPendingVisibleChild;
|
|
10
|
+
insertStackPageBefore(child: Gtk.Widget, props: StackPageProps, _beforeChild: Gtk.Widget): void;
|
|
11
|
+
removeStackPage(child: Gtk.Widget): void;
|
|
12
|
+
updateStackPageProps(child: Gtk.Widget, props: StackPageProps): void;
|
|
13
|
+
private applyStackPageProps;
|
|
14
|
+
attachChild(child: Gtk.Widget): void;
|
|
15
|
+
insertChildBefore(child: Gtk.Widget, _before: Gtk.Widget): void;
|
|
16
|
+
detachChild(child: Gtk.Widget): void;
|
|
17
|
+
protected consumedProps(): Set<string>;
|
|
18
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
19
|
+
}
|
|
20
|
+
export declare class StackPageNode extends Node {
|
|
21
|
+
static matches(type: string): boolean;
|
|
22
|
+
protected isVirtual(): boolean;
|
|
23
|
+
private pageProps;
|
|
24
|
+
private childWidget;
|
|
25
|
+
private parentContainer;
|
|
26
|
+
initialize(props: Props): void;
|
|
27
|
+
private extractPageProps;
|
|
28
|
+
getChildWidget(): Gtk.Widget | null;
|
|
29
|
+
appendChild(child: Node): void;
|
|
30
|
+
attachToParent(parent: Node): void;
|
|
31
|
+
attachToParentBefore(parent: Node, before: Node): void;
|
|
32
|
+
detachFromParent(parent: Node): void;
|
|
33
|
+
protected consumedProps(): Set<string>;
|
|
34
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
35
|
+
}
|