@gtkx/react 0.10.1 → 0.10.3
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/dist/generated/jsx.d.ts +14 -5
- package/dist/host-config.d.ts +0 -1
- package/dist/host-config.js +3 -6
- package/dist/node.d.ts +0 -2
- package/dist/node.js +2 -4
- package/dist/nodes/column-view-column.js +1 -1
- package/dist/nodes/column-view.js +2 -1
- package/dist/nodes/index.d.ts +0 -3
- package/dist/nodes/index.js +0 -3
- package/dist/nodes/internal/list-item-renderer.d.ts +1 -3
- package/dist/nodes/internal/list-item-renderer.js +6 -7
- package/dist/nodes/internal/predicates.d.ts +3 -0
- package/dist/nodes/internal/predicates.js +3 -0
- package/dist/nodes/internal/signal-store.d.ts +11 -5
- package/dist/nodes/internal/signal-store.js +50 -31
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +1 -3
- package/dist/nodes/internal/tree-list-item-renderer.js +6 -7
- package/dist/nodes/list-view.js +1 -1
- package/dist/nodes/models/list.js +3 -2
- package/dist/nodes/models/menu.js +5 -4
- package/dist/nodes/models/tree-list.js +3 -2
- package/dist/nodes/notebook-page-tab.js +0 -3
- package/dist/nodes/notebook-page.js +0 -3
- package/dist/nodes/simple-list-view.js +2 -1
- package/dist/nodes/toast.js +3 -2
- package/dist/nodes/toolbar-child.d.ts +1 -9
- package/dist/nodes/toolbar-child.js +1 -1
- package/dist/nodes/tree-list-view.js +1 -1
- package/dist/nodes/widget.d.ts +1 -0
- package/dist/nodes/widget.js +30 -14
- package/dist/nodes/window.js +0 -10
- package/package.json +3 -3
- package/dist/nodes/navigation-page.d.ts +0 -21
- package/dist/nodes/navigation-page.js +0 -95
- package/dist/nodes/navigation-view.d.ts +0 -1
- package/dist/nodes/navigation-view.js +0 -29
- package/dist/nodes/toolbar.d.ts +0 -1
- package/dist/nodes/toolbar.js +0 -42
package/dist/generated/jsx.d.ts
CHANGED
|
@@ -3186,8 +3186,6 @@ export interface GtkGLAreaProps extends WidgetProps {
|
|
|
3186
3186
|
export interface GtkGraphicsOffloadProps extends WidgetProps {
|
|
3187
3187
|
/** Whether to draw a black background. */
|
|
3188
3188
|
blackBackground?: boolean;
|
|
3189
|
-
/** The child widget. */
|
|
3190
|
-
child?: Gtk.Widget;
|
|
3191
3189
|
/** Whether graphics offload is enabled. */
|
|
3192
3190
|
enabled?: Gtk.GraphicsOffloadEnabled;
|
|
3193
3191
|
children?: ReactNode;
|
|
@@ -12328,7 +12326,6 @@ export type WidgetSlotNames = {
|
|
|
12328
12326
|
GtkExpander: "child" | "labelWidget";
|
|
12329
12327
|
GtkFlowBoxChild: "child";
|
|
12330
12328
|
GtkFrame: "child" | "labelWidget";
|
|
12331
|
-
GtkGraphicsOffload: "child";
|
|
12332
12329
|
GtkHeaderBar: "titleWidget";
|
|
12333
12330
|
GtkLabel: "mnemonicWidget";
|
|
12334
12331
|
GtkListBoxRow: "child";
|
|
@@ -12353,26 +12350,38 @@ export type WidgetSlotNames = {
|
|
|
12353
12350
|
AdwBin: "child";
|
|
12354
12351
|
AdwBottomSheet: "bottomBar" | "content" | "sheet";
|
|
12355
12352
|
AdwBreakpointBin: "child";
|
|
12353
|
+
AdwCarouselIndicatorDots: "carousel";
|
|
12354
|
+
AdwCarouselIndicatorLines: "carousel";
|
|
12356
12355
|
AdwClamp: "child";
|
|
12357
12356
|
AdwClampScrollable: "child";
|
|
12358
12357
|
AdwDialog: "child" | "defaultWidget" | "focusWidget";
|
|
12359
12358
|
AdwFlap: "content" | "flap" | "separator";
|
|
12360
12359
|
AdwHeaderBar: "titleWidget";
|
|
12360
|
+
AdwInlineViewSwitcher: "stack";
|
|
12361
12361
|
AdwLeaflet: "visibleChild";
|
|
12362
12362
|
AdwMessageDialog: "extraChild";
|
|
12363
|
+
AdwNavigationSplitView: "content" | "sidebar";
|
|
12363
12364
|
AdwOverlaySplitView: "content" | "sidebar";
|
|
12364
12365
|
AdwPreferencesDialog: "visiblePage";
|
|
12365
12366
|
AdwPreferencesGroup: "headerSuffix";
|
|
12367
|
+
AdwPreferencesPage: "banner";
|
|
12366
12368
|
AdwPreferencesWindow: "visiblePage";
|
|
12367
12369
|
AdwSplitButton: "child" | "popover";
|
|
12368
12370
|
AdwStatusPage: "child";
|
|
12369
|
-
AdwTabBar: "endActionWidget" | "startActionWidget";
|
|
12370
|
-
|
|
12371
|
+
AdwTabBar: "endActionWidget" | "startActionWidget" | "view";
|
|
12372
|
+
AdwTabButton: "view";
|
|
12373
|
+
AdwTabOverview: "child" | "view";
|
|
12371
12374
|
AdwToastOverlay: "child";
|
|
12372
12375
|
AdwToolbarView: "content";
|
|
12373
12376
|
AdwViewStack: "visibleChild";
|
|
12377
|
+
AdwViewSwitcher: "stack";
|
|
12378
|
+
AdwViewSwitcherBar: "stack";
|
|
12379
|
+
AdwViewSwitcherTitle: "stack";
|
|
12374
12380
|
GtkSourceCompletionCell: "widget";
|
|
12381
|
+
GtkSourceGutter: "view";
|
|
12382
|
+
GtkSourceMap: "view";
|
|
12375
12383
|
VteTerminal: "contextMenu";
|
|
12384
|
+
WebKitWebView: "relatedView";
|
|
12376
12385
|
};
|
|
12377
12386
|
/**
|
|
12378
12387
|
* The base class for all widgets.
|
package/dist/host-config.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ import type { Container, Props } from "./types.js";
|
|
|
5
5
|
declare global {
|
|
6
6
|
var __GTKX_CONTAINER_NODE_CACHE__: Map<number, Node> | undefined;
|
|
7
7
|
}
|
|
8
|
-
export declare const isCommitting: () => boolean;
|
|
9
8
|
type TextInstance = Node;
|
|
10
9
|
type SuspenseInstance = never;
|
|
11
10
|
type HydratableInstance = never;
|
package/dist/host-config.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { beginBatch, endBatch, getObjectId } from "@gtkx/ffi";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { createNode } from "./factory.js";
|
|
4
|
-
import {
|
|
4
|
+
import { signalStore } from "./nodes/internal/signal-store.js";
|
|
5
5
|
import { flushAfterCommit } from "./scheduler.js";
|
|
6
6
|
if (!globalThis.__GTKX_CONTAINER_NODE_CACHE__) {
|
|
7
7
|
globalThis.__GTKX_CONTAINER_NODE_CACHE__ = new Map();
|
|
8
8
|
}
|
|
9
|
-
let committing = false;
|
|
10
|
-
export const isCommitting = () => committing;
|
|
11
9
|
const containerNodeCache = globalThis.__GTKX_CONTAINER_NODE_CACHE__;
|
|
12
10
|
const getOrCreateContainerNode = (container) => {
|
|
13
11
|
const id = getObjectId(container.id);
|
|
@@ -73,15 +71,14 @@ export function createHostConfig() {
|
|
|
73
71
|
parent.insertBefore(child, beforeChild);
|
|
74
72
|
},
|
|
75
73
|
prepareForCommit: () => {
|
|
76
|
-
|
|
74
|
+
signalStore.blockAll();
|
|
77
75
|
beginBatch();
|
|
78
76
|
return null;
|
|
79
77
|
},
|
|
80
78
|
resetAfterCommit: () => {
|
|
81
79
|
endBatch();
|
|
82
|
-
|
|
80
|
+
signalStore.unblockAll();
|
|
83
81
|
flushAfterCommit();
|
|
84
|
-
committing = false;
|
|
85
82
|
},
|
|
86
83
|
commitTextUpdate: (textInstance, oldText, newText) => {
|
|
87
84
|
textInstance.updateProps({ label: oldText }, { label: newText });
|
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { SignalStore } from "./nodes/internal/signal-store.js";
|
|
2
1
|
import type { Container, ContainerClass, Props } from "./types.js";
|
|
3
2
|
export declare class Node<T = unknown, P = Props> {
|
|
4
3
|
static priority: number;
|
|
@@ -6,7 +5,6 @@ export declare class Node<T = unknown, P = Props> {
|
|
|
6
5
|
static createContainer(_props: Props, _containerClass: ContainerClass, _rootContainer?: Container): unknown;
|
|
7
6
|
container: T;
|
|
8
7
|
typeName: string;
|
|
9
|
-
protected signalStore: SignalStore;
|
|
10
8
|
constructor(typeName: string, _props: P | undefined, container: T, _rootContainer?: Container);
|
|
11
9
|
appendChild(_child: Node): void;
|
|
12
10
|
removeChild(_child: Node): void;
|
package/dist/node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { signalStore } from "./nodes/internal/signal-store.js";
|
|
2
2
|
export class Node {
|
|
3
3
|
static priority = 0;
|
|
4
4
|
static matches(_type, _containerOrClass) {
|
|
@@ -9,11 +9,9 @@ export class Node {
|
|
|
9
9
|
}
|
|
10
10
|
container;
|
|
11
11
|
typeName;
|
|
12
|
-
signalStore;
|
|
13
12
|
constructor(typeName, _props = {}, container, _rootContainer) {
|
|
14
13
|
this.typeName = typeName;
|
|
15
14
|
this.container = container;
|
|
16
|
-
this.signalStore = new SignalStore();
|
|
17
15
|
}
|
|
18
16
|
appendChild(_child) { }
|
|
19
17
|
removeChild(_child) { }
|
|
@@ -21,6 +19,6 @@ export class Node {
|
|
|
21
19
|
updateProps(_oldProps, _newProps) { }
|
|
22
20
|
mount() { }
|
|
23
21
|
unmount() {
|
|
24
|
-
|
|
22
|
+
signalStore.clear(this);
|
|
25
23
|
}
|
|
26
24
|
}
|
|
@@ -11,7 +11,7 @@ export class ColumnViewColumnNode extends VirtualNode {
|
|
|
11
11
|
itemRenderer;
|
|
12
12
|
constructor(typeName, props, container, rootContainer) {
|
|
13
13
|
super(typeName, props, container, rootContainer);
|
|
14
|
-
this.itemRenderer = new ListItemRenderer(
|
|
14
|
+
this.itemRenderer = new ListItemRenderer();
|
|
15
15
|
this.column = new Gtk.ColumnViewColumn();
|
|
16
16
|
this.column.setFactory(this.itemRenderer.getFactory());
|
|
17
17
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import { registerNodeClass } from "../registry.js";
|
|
3
3
|
import { ColumnViewColumnNode } from "./column-view-column.js";
|
|
4
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
4
5
|
import { filterProps, isContainerType } from "./internal/utils.js";
|
|
5
6
|
import { ListItemNode } from "./list-item.js";
|
|
6
7
|
import { List } from "./models/list.js";
|
|
@@ -79,7 +80,7 @@ class ColumnViewNode extends WidgetNode {
|
|
|
79
80
|
this.handleSortChange = () => {
|
|
80
81
|
onSortChange?.(sorter.getPrimarySortColumn()?.getId() ?? null, sorter.getPrimarySortOrder());
|
|
81
82
|
};
|
|
82
|
-
|
|
83
|
+
signalStore.set(this, sorter, "changed", this.handleSortChange);
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
if (!oldProps || oldProps.sortColumn !== newProps.sortColumn || oldProps.sortOrder !== newProps.sortOrder) {
|
package/dist/nodes/index.d.ts
CHANGED
|
@@ -9,8 +9,6 @@ import "./grid-child.js";
|
|
|
9
9
|
import "./list-item.js";
|
|
10
10
|
import "./list-view.js";
|
|
11
11
|
import "./menu.js";
|
|
12
|
-
import "./navigation-page.js";
|
|
13
|
-
import "./navigation-view.js";
|
|
14
12
|
import "./notebook-page-tab.js";
|
|
15
13
|
import "./notebook-page.js";
|
|
16
14
|
import "./notebook.js";
|
|
@@ -26,7 +24,6 @@ import "./stack.js";
|
|
|
26
24
|
import "./toast-overlay.js";
|
|
27
25
|
import "./toast.js";
|
|
28
26
|
import "./toolbar-child.js";
|
|
29
|
-
import "./toolbar.js";
|
|
30
27
|
import "./tree-list-item.js";
|
|
31
28
|
import "./tree-list-view.js";
|
|
32
29
|
import "./virtual.js";
|
package/dist/nodes/index.js
CHANGED
|
@@ -9,8 +9,6 @@ import "./grid-child.js";
|
|
|
9
9
|
import "./list-item.js";
|
|
10
10
|
import "./list-view.js";
|
|
11
11
|
import "./menu.js";
|
|
12
|
-
import "./navigation-page.js";
|
|
13
|
-
import "./navigation-view.js";
|
|
14
12
|
import "./notebook-page-tab.js";
|
|
15
13
|
import "./notebook-page.js";
|
|
16
14
|
import "./notebook.js";
|
|
@@ -26,7 +24,6 @@ import "./stack.js";
|
|
|
26
24
|
import "./toast-overlay.js";
|
|
27
25
|
import "./toast.js";
|
|
28
26
|
import "./toolbar-child.js";
|
|
29
|
-
import "./toolbar.js";
|
|
30
27
|
import "./tree-list-item.js";
|
|
31
28
|
import "./tree-list-view.js";
|
|
32
29
|
import "./virtual.js";
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
import type { ListStore } from "./list-store.js";
|
|
4
|
-
import type { SignalStore } from "./signal-store.js";
|
|
5
4
|
export type RenderItemFn<T> = (item: T | null) => ReactNode;
|
|
6
5
|
export declare class ListItemRenderer {
|
|
7
6
|
private factory;
|
|
8
7
|
private store?;
|
|
9
8
|
private fiberRoots;
|
|
10
9
|
private renderFn?;
|
|
11
|
-
|
|
12
|
-
constructor(signalStore: SignalStore);
|
|
10
|
+
constructor();
|
|
13
11
|
getFactory(): Gtk.SignalListItemFactory;
|
|
14
12
|
setRenderFn(renderFn?: RenderItemFn<unknown>): void;
|
|
15
13
|
setStore(store?: ListStore): void;
|
|
@@ -2,14 +2,13 @@ import { getObjectId } from "@gtkx/ffi";
|
|
|
2
2
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
3
|
import { createFiberRoot } from "../../fiber-root.js";
|
|
4
4
|
import { reconciler } from "../../reconciler.js";
|
|
5
|
+
import { signalStore } from "./signal-store.js";
|
|
5
6
|
export class ListItemRenderer {
|
|
6
7
|
factory;
|
|
7
8
|
store;
|
|
8
9
|
fiberRoots = new Map();
|
|
9
10
|
renderFn = () => null;
|
|
10
|
-
|
|
11
|
-
constructor(signalStore) {
|
|
12
|
-
this.signalStore = signalStore;
|
|
11
|
+
constructor() {
|
|
13
12
|
this.factory = new Gtk.SignalListItemFactory();
|
|
14
13
|
this.initialize();
|
|
15
14
|
}
|
|
@@ -29,7 +28,7 @@ export class ListItemRenderer {
|
|
|
29
28
|
return this.store;
|
|
30
29
|
}
|
|
31
30
|
initialize() {
|
|
32
|
-
|
|
31
|
+
signalStore.set(this, this.factory, "setup", (_self, listItem) => {
|
|
33
32
|
const ptr = getObjectId(listItem.id);
|
|
34
33
|
const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
|
|
35
34
|
listItem.setChild(box);
|
|
@@ -38,7 +37,7 @@ export class ListItemRenderer {
|
|
|
38
37
|
const element = this.renderFn?.(null);
|
|
39
38
|
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
|
|
40
39
|
});
|
|
41
|
-
|
|
40
|
+
signalStore.set(this, this.factory, "bind", (_self, listItem) => {
|
|
42
41
|
const ptr = getObjectId(listItem.id);
|
|
43
42
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
44
43
|
if (!fiberRoot)
|
|
@@ -48,14 +47,14 @@ export class ListItemRenderer {
|
|
|
48
47
|
const element = this.renderFn?.(item);
|
|
49
48
|
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
|
|
50
49
|
});
|
|
51
|
-
|
|
50
|
+
signalStore.set(this, this.factory, "unbind", (_self, listItem) => {
|
|
52
51
|
const ptr = getObjectId(listItem.id);
|
|
53
52
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
54
53
|
if (!fiberRoot)
|
|
55
54
|
return;
|
|
56
55
|
reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
|
|
57
56
|
});
|
|
58
|
-
|
|
57
|
+
signalStore.set(this, this.factory, "teardown", (_self, listItem) => {
|
|
59
58
|
const ptr = getObjectId(listItem.id);
|
|
60
59
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
61
60
|
if (fiberRoot) {
|
|
@@ -5,6 +5,9 @@ export declare const isAppendable: (obj: unknown) => obj is Gtk.Widget & {
|
|
|
5
5
|
export declare const isAddable: (obj: unknown) => obj is Gtk.Widget & {
|
|
6
6
|
add: (child: Gtk.Widget) => void;
|
|
7
7
|
};
|
|
8
|
+
export declare const hasSingleContent: (obj: unknown) => obj is Gtk.Widget & {
|
|
9
|
+
setContent: (content: Gtk.Widget | undefined) => void;
|
|
10
|
+
};
|
|
8
11
|
export declare const isSingleChild: (obj: unknown) => obj is Gtk.Widget & {
|
|
9
12
|
setChild: (child: Gtk.Widget | null) => void;
|
|
10
13
|
};
|
|
@@ -5,6 +5,9 @@ export const isAppendable = (obj) => {
|
|
|
5
5
|
export const isAddable = (obj) => {
|
|
6
6
|
return obj instanceof Gtk.Widget && "add" in obj && typeof obj.add === "function";
|
|
7
7
|
};
|
|
8
|
+
export const hasSingleContent = (obj) => {
|
|
9
|
+
return obj instanceof Gtk.Widget && "setContent" in obj && typeof obj.setContent === "function";
|
|
10
|
+
};
|
|
8
11
|
export const isSingleChild = (obj) => {
|
|
9
12
|
return obj instanceof Gtk.Widget && "setChild" in obj && typeof obj.setChild === "function";
|
|
10
13
|
};
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import * as GObject from "@gtkx/ffi/gobject";
|
|
2
|
+
type SignalOwner = object;
|
|
2
3
|
export type SignalHandler = (...args: any[]) => any;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
private
|
|
4
|
+
declare class SignalStore {
|
|
5
|
+
private ownerHandlers;
|
|
6
|
+
private blockedHandlers;
|
|
7
|
+
private getOwnerMap;
|
|
6
8
|
private disconnect;
|
|
7
9
|
private connect;
|
|
8
|
-
set(obj: GObject.GObject, signal: string, handler?: SignalHandler): void;
|
|
9
|
-
clear(): void;
|
|
10
|
+
set(owner: SignalOwner, obj: GObject.GObject, signal: string, handler?: SignalHandler): void;
|
|
11
|
+
clear(owner: SignalOwner): void;
|
|
12
|
+
blockAll(): void;
|
|
13
|
+
unblockAll(): void;
|
|
10
14
|
}
|
|
15
|
+
export declare const signalStore: SignalStore;
|
|
16
|
+
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { getObjectId } from "@gtkx/ffi";
|
|
2
2
|
import * as GObject from "@gtkx/ffi/gobject";
|
|
3
|
-
import { isCommitting } from "../../host-config.js";
|
|
4
3
|
const LIFECYCLE_SIGNALS = new Set([
|
|
5
4
|
"realize",
|
|
6
5
|
"unrealize",
|
|
@@ -16,49 +15,69 @@ const LIFECYCLE_SIGNALS = new Set([
|
|
|
16
15
|
"unbind",
|
|
17
16
|
"teardown",
|
|
18
17
|
]);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
class SignalStore {
|
|
19
|
+
ownerHandlers = new Map();
|
|
20
|
+
blockedHandlers = new Set();
|
|
21
|
+
getOwnerMap(owner) {
|
|
22
|
+
let map = this.ownerHandlers.get(owner);
|
|
23
|
+
if (!map) {
|
|
24
|
+
map = new Map();
|
|
25
|
+
this.ownerHandlers.set(owner, map);
|
|
26
|
+
}
|
|
27
|
+
return map;
|
|
28
|
+
}
|
|
29
|
+
disconnect(owner, obj, signal) {
|
|
26
30
|
const objectId = getObjectId(obj.id);
|
|
27
31
|
const key = `${objectId}:${signal}`;
|
|
28
|
-
const
|
|
32
|
+
const ownerMap = this.ownerHandlers.get(owner);
|
|
33
|
+
const existing = ownerMap?.get(key);
|
|
29
34
|
if (existing) {
|
|
30
35
|
GObject.signalHandlerDisconnect(existing.obj, existing.handlerId);
|
|
31
|
-
|
|
36
|
+
ownerMap?.delete(key);
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
|
-
connect(obj, signal, handler) {
|
|
39
|
+
connect(owner, obj, signal, handler) {
|
|
35
40
|
const objectId = getObjectId(obj.id);
|
|
36
41
|
const key = `${objectId}:${signal}`;
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
const handlerId = obj.connect(signal, handler);
|
|
43
|
+
this.getOwnerMap(owner).set(key, { obj, handlerId });
|
|
44
|
+
}
|
|
45
|
+
set(owner, obj, signal, handler) {
|
|
46
|
+
this.disconnect(owner, obj, signal);
|
|
47
|
+
if (handler) {
|
|
48
|
+
this.connect(owner, obj, signal, handler);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
clear(owner) {
|
|
52
|
+
const ownerMap = this.ownerHandlers.get(owner);
|
|
53
|
+
if (ownerMap) {
|
|
54
|
+
for (const { obj, handlerId } of ownerMap.values()) {
|
|
55
|
+
GObject.signalHandlerDisconnect(obj, handlerId);
|
|
40
56
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
57
|
+
this.ownerHandlers.delete(owner);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
blockAll() {
|
|
61
|
+
this.blockedHandlers.clear();
|
|
62
|
+
for (const ownerMap of this.ownerHandlers.values()) {
|
|
63
|
+
for (const [key, { obj, handlerId }] of ownerMap.entries()) {
|
|
64
|
+
if (LIFECYCLE_SIGNALS.has(key.split(":")[1] ?? "")) {
|
|
65
|
+
continue;
|
|
44
66
|
}
|
|
45
|
-
|
|
67
|
+
GObject.signalHandlerBlock(obj, handlerId);
|
|
68
|
+
this.blockedHandlers.add(handlerId);
|
|
46
69
|
}
|
|
47
|
-
return handler(...args);
|
|
48
|
-
};
|
|
49
|
-
const handlerId = obj.connect(signal, wrappedHandler);
|
|
50
|
-
this.signalHandlers.set(key, { obj, handlerId });
|
|
51
|
-
}
|
|
52
|
-
set(obj, signal, handler) {
|
|
53
|
-
this.disconnect(obj, signal);
|
|
54
|
-
if (handler) {
|
|
55
|
-
this.connect(obj, signal, handler);
|
|
56
70
|
}
|
|
57
71
|
}
|
|
58
|
-
|
|
59
|
-
for (const
|
|
60
|
-
|
|
72
|
+
unblockAll() {
|
|
73
|
+
for (const ownerMap of this.ownerHandlers.values()) {
|
|
74
|
+
for (const { obj, handlerId } of ownerMap.values()) {
|
|
75
|
+
if (this.blockedHandlers.has(handlerId)) {
|
|
76
|
+
GObject.signalHandlerUnblock(obj, handlerId);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
61
79
|
}
|
|
62
|
-
this.
|
|
80
|
+
this.blockedHandlers.clear();
|
|
63
81
|
}
|
|
64
82
|
}
|
|
83
|
+
export const signalStore = new SignalStore();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
|
-
import type { SignalStore } from "./signal-store.js";
|
|
4
3
|
import type { TreeStore } from "./tree-store.js";
|
|
5
4
|
export type TreeRenderItemFn<T> = (item: T | null, row: Gtk.TreeListRow | null) => ReactNode;
|
|
6
5
|
export declare class TreeListItemRenderer {
|
|
@@ -8,8 +7,7 @@ export declare class TreeListItemRenderer {
|
|
|
8
7
|
private store?;
|
|
9
8
|
private fiberRoots;
|
|
10
9
|
private renderFn?;
|
|
11
|
-
|
|
12
|
-
constructor(signalStore: SignalStore);
|
|
10
|
+
constructor();
|
|
13
11
|
getFactory(): Gtk.SignalListItemFactory;
|
|
14
12
|
setRenderFn(renderFn?: TreeRenderItemFn<unknown>): void;
|
|
15
13
|
setStore(store?: TreeStore): void;
|
|
@@ -2,14 +2,13 @@ import { getObjectId } from "@gtkx/ffi";
|
|
|
2
2
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
3
|
import { createFiberRoot } from "../../fiber-root.js";
|
|
4
4
|
import { reconciler } from "../../reconciler.js";
|
|
5
|
+
import { signalStore } from "./signal-store.js";
|
|
5
6
|
export class TreeListItemRenderer {
|
|
6
7
|
factory;
|
|
7
8
|
store;
|
|
8
9
|
fiberRoots = new Map();
|
|
9
10
|
renderFn = () => null;
|
|
10
|
-
|
|
11
|
-
constructor(signalStore) {
|
|
12
|
-
this.signalStore = signalStore;
|
|
11
|
+
constructor() {
|
|
13
12
|
this.factory = new Gtk.SignalListItemFactory();
|
|
14
13
|
this.initialize();
|
|
15
14
|
}
|
|
@@ -29,7 +28,7 @@ export class TreeListItemRenderer {
|
|
|
29
28
|
return this.store;
|
|
30
29
|
}
|
|
31
30
|
initialize() {
|
|
32
|
-
|
|
31
|
+
signalStore.set(this, this.factory, "setup", (_self, listItem) => {
|
|
33
32
|
const ptr = getObjectId(listItem.id);
|
|
34
33
|
const expander = new Gtk.TreeExpander();
|
|
35
34
|
const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
|
|
@@ -40,7 +39,7 @@ export class TreeListItemRenderer {
|
|
|
40
39
|
const element = this.renderFn?.(null, null);
|
|
41
40
|
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
|
|
42
41
|
});
|
|
43
|
-
|
|
42
|
+
signalStore.set(this, this.factory, "bind", (_self, listItem) => {
|
|
44
43
|
const ptr = getObjectId(listItem.id);
|
|
45
44
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
46
45
|
if (!fiberRoot)
|
|
@@ -69,7 +68,7 @@ export class TreeListItemRenderer {
|
|
|
69
68
|
const element = this.renderFn?.(itemData?.value ?? null, treeListRow);
|
|
70
69
|
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
|
|
71
70
|
});
|
|
72
|
-
|
|
71
|
+
signalStore.set(this, this.factory, "unbind", (_self, listItem) => {
|
|
73
72
|
const ptr = getObjectId(listItem.id);
|
|
74
73
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
75
74
|
if (!fiberRoot)
|
|
@@ -78,7 +77,7 @@ export class TreeListItemRenderer {
|
|
|
78
77
|
expander.setListRow(undefined);
|
|
79
78
|
reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
|
|
80
79
|
});
|
|
81
|
-
|
|
80
|
+
signalStore.set(this, this.factory, "teardown", (_self, listItem) => {
|
|
82
81
|
const ptr = getObjectId(listItem.id);
|
|
83
82
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
84
83
|
if (fiberRoot) {
|
package/dist/nodes/list-view.js
CHANGED
|
@@ -16,7 +16,7 @@ class ListViewNode extends WidgetNode {
|
|
|
16
16
|
constructor(typeName, props, container, rootContainer) {
|
|
17
17
|
super(typeName, props, container, rootContainer);
|
|
18
18
|
this.list = new List();
|
|
19
|
-
this.itemRenderer = new ListItemRenderer(
|
|
19
|
+
this.itemRenderer = new ListItemRenderer();
|
|
20
20
|
this.itemRenderer.setStore(this.list.getStore());
|
|
21
21
|
this.container.setFactory(this.itemRenderer.getFactory());
|
|
22
22
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import { ListStore } from "../internal/list-store.js";
|
|
3
|
+
import { signalStore } from "../internal/signal-store.js";
|
|
3
4
|
import { ListItemNode } from "../list-item.js";
|
|
4
5
|
import { VirtualNode } from "../virtual.js";
|
|
5
6
|
export class List extends VirtualNode {
|
|
@@ -42,7 +43,7 @@ export class List extends VirtualNode {
|
|
|
42
43
|
updateProps(oldProps, newProps) {
|
|
43
44
|
super.updateProps(oldProps, newProps);
|
|
44
45
|
if (!oldProps || oldProps.selectionMode !== newProps.selectionMode) {
|
|
45
|
-
|
|
46
|
+
signalStore.set(this, this.selectionModel, "selection-changed", undefined);
|
|
46
47
|
this.selectionModel = this.createSelectionModel(newProps.selectionMode);
|
|
47
48
|
}
|
|
48
49
|
if (!oldProps ||
|
|
@@ -52,7 +53,7 @@ export class List extends VirtualNode {
|
|
|
52
53
|
this.handleSelectionChange = () => {
|
|
53
54
|
onSelectionChanged?.(this.getSelection());
|
|
54
55
|
};
|
|
55
|
-
|
|
56
|
+
signalStore.set(this, this.selectionModel, "selection-changed", newProps.onSelectionChanged ? this.handleSelectionChange : undefined);
|
|
56
57
|
}
|
|
57
58
|
if (!oldProps || oldProps.selected !== newProps.selected || oldProps.selectionMode !== newProps.selectionMode) {
|
|
58
59
|
this.setSelection(newProps.selected);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { batch } from "@gtkx/ffi";
|
|
2
2
|
import * as Gio from "@gtkx/ffi/gio";
|
|
3
3
|
import { scheduleAfterCommit } from "../../scheduler.js";
|
|
4
|
+
import { signalStore } from "../internal/signal-store.js";
|
|
4
5
|
import { VirtualNode } from "../virtual.js";
|
|
5
6
|
export class Menu extends VirtualNode {
|
|
6
7
|
actionMap;
|
|
@@ -66,10 +67,10 @@ export class Menu extends VirtualNode {
|
|
|
66
67
|
createAction() {
|
|
67
68
|
batch(() => {
|
|
68
69
|
if (this.action) {
|
|
69
|
-
|
|
70
|
+
signalStore.set(this, this.action, "activate", undefined);
|
|
70
71
|
}
|
|
71
72
|
this.action = new Gio.SimpleAction(this.getId());
|
|
72
|
-
|
|
73
|
+
signalStore.set(this, this.action, "activate", this.getOnActivate());
|
|
73
74
|
this.getActionMap().addAction(this.action);
|
|
74
75
|
if (this.application && this.props.accels) {
|
|
75
76
|
this.application.setAccelsForAction(this.getActionName(), this.getAccels());
|
|
@@ -83,7 +84,7 @@ export class Menu extends VirtualNode {
|
|
|
83
84
|
}
|
|
84
85
|
if (this.action) {
|
|
85
86
|
this.getActionMap().removeAction(this.getId());
|
|
86
|
-
|
|
87
|
+
signalStore.set(this, this.action, "activate", undefined);
|
|
87
88
|
this.action = undefined;
|
|
88
89
|
}
|
|
89
90
|
});
|
|
@@ -230,7 +231,7 @@ export class Menu extends VirtualNode {
|
|
|
230
231
|
return;
|
|
231
232
|
}
|
|
232
233
|
if (oldProps.onActivate !== newProps.onActivate) {
|
|
233
|
-
|
|
234
|
+
signalStore.set(this, this.getAction(), "activate", newProps.onActivate);
|
|
234
235
|
}
|
|
235
236
|
if (oldProps.accels !== newProps.accels) {
|
|
236
237
|
if (this.application) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { signalStore } from "../internal/signal-store.js";
|
|
2
3
|
import { TreeStore } from "../internal/tree-store.js";
|
|
3
4
|
import { TreeListItemNode } from "../tree-list-item.js";
|
|
4
5
|
import { VirtualNode } from "../virtual.js";
|
|
@@ -77,7 +78,7 @@ export class TreeList extends VirtualNode {
|
|
|
77
78
|
this.treeListModel.setAutoexpand(newProps.autoexpand ?? false);
|
|
78
79
|
}
|
|
79
80
|
if (!oldProps || oldProps.selectionMode !== newProps.selectionMode) {
|
|
80
|
-
|
|
81
|
+
signalStore.set(this, this.selectionModel, "selection-changed", undefined);
|
|
81
82
|
this.selectionModel = this.createSelectionModel(newProps.selectionMode);
|
|
82
83
|
this.selectionModel.setModel(this.treeListModel);
|
|
83
84
|
}
|
|
@@ -88,7 +89,7 @@ export class TreeList extends VirtualNode {
|
|
|
88
89
|
this.handleSelectionChange = () => {
|
|
89
90
|
onSelectionChanged?.(this.getSelection());
|
|
90
91
|
};
|
|
91
|
-
|
|
92
|
+
signalStore.set(this, this.selectionModel, "selection-changed", newProps.onSelectionChanged ? this.handleSelectionChange : undefined);
|
|
92
93
|
}
|
|
93
94
|
if (!oldProps || oldProps.selected !== newProps.selected || oldProps.selectionMode !== newProps.selectionMode) {
|
|
94
95
|
this.setSelection(newProps.selected);
|
|
@@ -30,12 +30,9 @@ export class NotebookPageTabNode extends SlotNode {
|
|
|
30
30
|
}
|
|
31
31
|
const notebook = this.getNotebook();
|
|
32
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
33
|
if (notebook.pageNum(page) === -1) {
|
|
36
34
|
return;
|
|
37
35
|
}
|
|
38
|
-
// setTabLabel accepts undefined to reset to default
|
|
39
36
|
notebook.setTabLabel(page, this.child);
|
|
40
37
|
}
|
|
41
38
|
}
|
|
@@ -54,7 +54,6 @@ export class NotebookPageNode extends SlotNode {
|
|
|
54
54
|
this.tabNode = undefined;
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
// For content widget, use SlotNode's removeChild logic
|
|
58
57
|
super.removeChild();
|
|
59
58
|
}
|
|
60
59
|
unmount() {
|
|
@@ -63,7 +62,6 @@ export class NotebookPageNode extends SlotNode {
|
|
|
63
62
|
}
|
|
64
63
|
updateProps(oldProps, newProps) {
|
|
65
64
|
if (!oldProps || oldProps.label !== newProps.label) {
|
|
66
|
-
// Only update if using text label (no custom tab node)
|
|
67
65
|
if (this.child && this.parent && !this.tabNode?.child) {
|
|
68
66
|
const tabLabel = this.getNotebook().getTabLabel(this.child);
|
|
69
67
|
tabLabel.setLabel(newProps.label ?? "");
|
|
@@ -73,7 +71,6 @@ export class NotebookPageNode extends SlotNode {
|
|
|
73
71
|
attachPage() {
|
|
74
72
|
const child = this.getChild();
|
|
75
73
|
const notebook = this.getNotebook();
|
|
76
|
-
// Use custom tab widget if provided, otherwise create a Label
|
|
77
74
|
let tabLabel;
|
|
78
75
|
if (this.tabNode?.child) {
|
|
79
76
|
tabLabel = this.tabNode.child;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as Adw from "@gtkx/ffi/adw";
|
|
2
2
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
3
|
import { registerNodeClass } from "../registry.js";
|
|
4
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
4
5
|
import { SimpleListStore } from "./internal/simple-list-store.js";
|
|
5
6
|
import { filterProps, isContainerType } from "./internal/utils.js";
|
|
6
7
|
import { SimpleListItemNode } from "./simple-list-item.js";
|
|
@@ -28,7 +29,7 @@ class SimpleListViewNode extends WidgetNode {
|
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
: undefined;
|
|
31
|
-
|
|
32
|
+
signalStore.set(this, this.container, "notify::selected", handleSelectionChange);
|
|
32
33
|
}
|
|
33
34
|
if (!oldProps || oldProps.selectedId !== newProps.selectedId) {
|
|
34
35
|
const index = newProps.selectedId !== undefined ? this.store.getIndexById(newProps.selectedId) : undefined;
|
package/dist/nodes/toast.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Adw from "@gtkx/ffi/adw";
|
|
2
2
|
import { registerNodeClass } from "../registry.js";
|
|
3
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
3
4
|
import { VirtualNode } from "./virtual.js";
|
|
4
5
|
export class ToastNode extends VirtualNode {
|
|
5
6
|
static priority = 1;
|
|
@@ -35,11 +36,11 @@ export class ToastNode extends VirtualNode {
|
|
|
35
36
|
return;
|
|
36
37
|
this.toast = this.createToast();
|
|
37
38
|
if (this.props.onButtonClicked) {
|
|
38
|
-
|
|
39
|
+
signalStore.set(this, this.toast, "button-clicked", () => {
|
|
39
40
|
this.props.onButtonClicked?.();
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
signalStore.set(this, this.toast, "dismissed", () => {
|
|
43
44
|
this.props.onDismissed?.();
|
|
44
45
|
});
|
|
45
46
|
this.parent.addToast(this.toast);
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { SlotNode } from "./slot.js";
|
|
3
|
-
export declare class ToolbarChildNode extends SlotNode {
|
|
4
|
-
static priority: number;
|
|
5
|
-
static matches(type: string): boolean;
|
|
6
|
-
private getToolbar;
|
|
7
|
-
private getPosition;
|
|
8
|
-
protected onChildChange(oldChild: Gtk.Widget | undefined): void;
|
|
9
|
-
}
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { registerNodeClass } from "../registry.js";
|
|
2
2
|
import { SlotNode } from "./slot.js";
|
|
3
|
-
|
|
3
|
+
class ToolbarChildNode extends SlotNode {
|
|
4
4
|
static priority = 1;
|
|
5
5
|
static matches(type) {
|
|
6
6
|
return type === "Toolbar.Top" || type === "Toolbar.Bottom";
|
|
@@ -20,7 +20,7 @@ class TreeListViewNode extends WidgetNode {
|
|
|
20
20
|
const listView = container ?? new Gtk.ListView();
|
|
21
21
|
super(typeName, props, listView, rootContainer);
|
|
22
22
|
this.treeList = new TreeList(props.autoexpand, props.selectionMode);
|
|
23
|
-
this.itemRenderer = new TreeListItemRenderer(
|
|
23
|
+
this.itemRenderer = new TreeListItemRenderer();
|
|
24
24
|
this.itemRenderer.setStore(this.treeList.getStore());
|
|
25
25
|
this.container.setFactory(this.itemRenderer.getFactory());
|
|
26
26
|
}
|
package/dist/nodes/widget.d.ts
CHANGED
package/dist/nodes/widget.js
CHANGED
|
@@ -3,7 +3,8 @@ import * as Gtk from "@gtkx/ffi/gtk";
|
|
|
3
3
|
import { CONSTRUCTOR_PROPS, PROPS, SIGNALS } from "../generated/internal.js";
|
|
4
4
|
import { Node } from "../node.js";
|
|
5
5
|
import { registerNodeClass } from "../registry.js";
|
|
6
|
-
import { isAddable, isAppendable, isEditable, isInsertable, isRemovable, isReorderable, isSingleChild, } from "./internal/predicates.js";
|
|
6
|
+
import { hasSingleContent, isAddable, isAppendable, isEditable, isInsertable, isRemovable, isReorderable, isSingleChild, } from "./internal/predicates.js";
|
|
7
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
7
8
|
import { filterProps, isContainerType } from "./internal/utils.js";
|
|
8
9
|
import { SlotNode } from "./slot.js";
|
|
9
10
|
const EVENT_CONTROLLER_PROPS = new Set([
|
|
@@ -58,6 +59,9 @@ export class WidgetNode extends Node {
|
|
|
58
59
|
}
|
|
59
60
|
this.container.add(child.container);
|
|
60
61
|
}
|
|
62
|
+
else if (hasSingleContent(this.container)) {
|
|
63
|
+
this.container.setContent(child.container);
|
|
64
|
+
}
|
|
61
65
|
else if (isSingleChild(this.container)) {
|
|
62
66
|
this.container.setChild(child.container);
|
|
63
67
|
}
|
|
@@ -80,6 +84,9 @@ export class WidgetNode extends Node {
|
|
|
80
84
|
if (isRemovable(this.container)) {
|
|
81
85
|
this.container.remove(child.container);
|
|
82
86
|
}
|
|
87
|
+
else if (hasSingleContent(this.container)) {
|
|
88
|
+
this.container.setContent(undefined);
|
|
89
|
+
}
|
|
83
90
|
else if (isSingleChild(this.container)) {
|
|
84
91
|
this.container.setChild(null);
|
|
85
92
|
}
|
|
@@ -167,9 +174,16 @@ export class WidgetNode extends Node {
|
|
|
167
174
|
const signalName = this.propNameToSignalName(name);
|
|
168
175
|
if (signals.has(signalName)) {
|
|
169
176
|
const handler = typeof newValue === "function" ? newValue : undefined;
|
|
170
|
-
|
|
177
|
+
signalStore.set(this, this.container, signalName, handler);
|
|
171
178
|
}
|
|
172
179
|
else if (newValue !== undefined) {
|
|
180
|
+
const isEditableText = name === "text" && isEditable(this.container);
|
|
181
|
+
if (isEditableText && oldValue !== undefined) {
|
|
182
|
+
const currentValue = this.getProperty(name);
|
|
183
|
+
if (oldValue !== currentValue) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
173
187
|
this.setProperty(name, newValue);
|
|
174
188
|
}
|
|
175
189
|
}
|
|
@@ -184,7 +198,7 @@ export class WidgetNode extends Node {
|
|
|
184
198
|
this.container.addController(this.motionController);
|
|
185
199
|
}
|
|
186
200
|
const signalName = propName === "onEnter" ? "enter" : propName === "onLeave" ? "leave" : "motion";
|
|
187
|
-
|
|
201
|
+
signalStore.set(this, this.motionController, signalName, handler);
|
|
188
202
|
break;
|
|
189
203
|
}
|
|
190
204
|
case "onPressed":
|
|
@@ -194,7 +208,7 @@ export class WidgetNode extends Node {
|
|
|
194
208
|
this.container.addController(this.clickController);
|
|
195
209
|
}
|
|
196
210
|
const signalName = propName === "onPressed" ? "pressed" : "released";
|
|
197
|
-
|
|
211
|
+
signalStore.set(this, this.clickController, signalName, handler);
|
|
198
212
|
break;
|
|
199
213
|
}
|
|
200
214
|
case "onKeyPressed":
|
|
@@ -204,7 +218,7 @@ export class WidgetNode extends Node {
|
|
|
204
218
|
this.container.addController(this.keyController);
|
|
205
219
|
}
|
|
206
220
|
const signalName = propName === "onKeyPressed" ? "key-pressed" : "key-released";
|
|
207
|
-
|
|
221
|
+
signalStore.set(this, this.keyController, signalName, handler);
|
|
208
222
|
break;
|
|
209
223
|
}
|
|
210
224
|
case "onScroll": {
|
|
@@ -212,7 +226,7 @@ export class WidgetNode extends Node {
|
|
|
212
226
|
this.scrollController = new Gtk.EventControllerScroll(Gtk.EventControllerScrollFlags.BOTH_AXES);
|
|
213
227
|
this.container.addController(this.scrollController);
|
|
214
228
|
}
|
|
215
|
-
|
|
229
|
+
signalStore.set(this, this.scrollController, "scroll", handler);
|
|
216
230
|
break;
|
|
217
231
|
}
|
|
218
232
|
case "onNotify": {
|
|
@@ -221,7 +235,7 @@ export class WidgetNode extends Node {
|
|
|
221
235
|
handler(obj, pspec.getName());
|
|
222
236
|
}
|
|
223
237
|
: undefined;
|
|
224
|
-
|
|
238
|
+
signalStore.set(this, this.container, "notify", wrappedHandler);
|
|
225
239
|
break;
|
|
226
240
|
}
|
|
227
241
|
}
|
|
@@ -233,6 +247,15 @@ export class WidgetNode extends Node {
|
|
|
233
247
|
.toLowerCase()
|
|
234
248
|
.replace(/^-/, "");
|
|
235
249
|
}
|
|
250
|
+
getProperty(key) {
|
|
251
|
+
const WidgetClass = this.container.constructor;
|
|
252
|
+
const [getterName] = PROPS[WidgetClass.glibTypeName]?.[key] || [];
|
|
253
|
+
const getter = getterName ? this.container[getterName] : undefined;
|
|
254
|
+
if (getter && typeof getter === "function") {
|
|
255
|
+
return getter.call(this.container);
|
|
256
|
+
}
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
236
259
|
setProperty(key, value) {
|
|
237
260
|
const WidgetClass = this.container.constructor;
|
|
238
261
|
const [getterName, setterName] = PROPS[WidgetClass.glibTypeName]?.[key] || [];
|
|
@@ -248,14 +271,7 @@ export class WidgetNode extends Node {
|
|
|
248
271
|
}
|
|
249
272
|
}
|
|
250
273
|
if (setter && typeof setter === "function") {
|
|
251
|
-
const editable = isEditable(this.container) ? this.container : null;
|
|
252
|
-
const shouldPreserveCursor = key === "text" && editable !== null;
|
|
253
|
-
const cursorPosition = shouldPreserveCursor ? editable.getPosition() : 0;
|
|
254
274
|
setter.call(this.container, value);
|
|
255
|
-
if (shouldPreserveCursor && editable !== null) {
|
|
256
|
-
const textLength = editable.getText().length;
|
|
257
|
-
editable.setPosition(Math.min(cursorPosition, textLength));
|
|
258
|
-
}
|
|
259
275
|
}
|
|
260
276
|
}
|
|
261
277
|
}
|
package/dist/nodes/window.js
CHANGED
|
@@ -37,11 +37,6 @@ class WindowNode extends WidgetNode {
|
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
this.menu.appendChild(child);
|
|
40
|
-
if (child instanceof WidgetNode &&
|
|
41
|
-
(this.container instanceof Adw.ApplicationWindow || this.container instanceof Adw.Window)) {
|
|
42
|
-
this.container.setContent(child.container);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
40
|
super.appendChild(child);
|
|
46
41
|
}
|
|
47
42
|
removeChild(child) {
|
|
@@ -50,11 +45,6 @@ class WindowNode extends WidgetNode {
|
|
|
50
45
|
return;
|
|
51
46
|
}
|
|
52
47
|
this.menu.removeChild(child);
|
|
53
|
-
if (child instanceof WidgetNode &&
|
|
54
|
-
(this.container instanceof Adw.ApplicationWindow || this.container instanceof Adw.Window)) {
|
|
55
|
-
this.container.setContent(undefined);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
48
|
super.removeChild(child);
|
|
59
49
|
}
|
|
60
50
|
insertBefore(child, before) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/react",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Build GTK4 desktop applications with React and TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtk",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"react-reconciler": "^0.33.0",
|
|
39
|
-
"@gtkx/ffi": "0.10.
|
|
40
|
-
"@gtkx/gir": "0.10.
|
|
39
|
+
"@gtkx/ffi": "0.10.3",
|
|
40
|
+
"@gtkx/gir": "0.10.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/react-reconciler": "^0.32.3",
|
|
@@ -1,21 +0,0 @@
|
|
|
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 {};
|
|
@@ -1,95 +0,0 @@
|
|
|
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);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,29 +0,0 @@
|
|
|
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);
|
package/dist/nodes/toolbar.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/nodes/toolbar.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import * as Adw from "@gtkx/ffi/adw";
|
|
2
|
-
import { registerNodeClass } from "../registry.js";
|
|
3
|
-
import { isContainerType } from "./internal/utils.js";
|
|
4
|
-
import { ToolbarChildNode } from "./toolbar-child.js";
|
|
5
|
-
import { WidgetNode } from "./widget.js";
|
|
6
|
-
class ToolbarNode extends WidgetNode {
|
|
7
|
-
static priority = 0;
|
|
8
|
-
static matches(_type, containerOrClass) {
|
|
9
|
-
return isContainerType(Adw.ToolbarView, containerOrClass);
|
|
10
|
-
}
|
|
11
|
-
appendChild(child) {
|
|
12
|
-
if (child instanceof ToolbarChildNode) {
|
|
13
|
-
child.setParent(this.container);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
if (!(child instanceof WidgetNode)) {
|
|
17
|
-
throw new Error(`Cannot append '${child.typeName}' to 'ToolbarView': expected Widget`);
|
|
18
|
-
}
|
|
19
|
-
this.container.setContent(child.container);
|
|
20
|
-
}
|
|
21
|
-
insertBefore(child) {
|
|
22
|
-
if (child instanceof ToolbarChildNode) {
|
|
23
|
-
child.setParent(this.container);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
if (!(child instanceof WidgetNode)) {
|
|
27
|
-
throw new Error(`Cannot insert '${child.typeName}' to 'ToolbarView': expected Widget`);
|
|
28
|
-
}
|
|
29
|
-
this.container.setContent(child.container);
|
|
30
|
-
}
|
|
31
|
-
removeChild(child) {
|
|
32
|
-
if (child instanceof ToolbarChildNode) {
|
|
33
|
-
child.unmount();
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (!(child instanceof WidgetNode)) {
|
|
37
|
-
throw new Error(`Cannot remove '${child.typeName}' from 'ToolbarView': expected Widget`);
|
|
38
|
-
}
|
|
39
|
-
this.container.setContent(undefined);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
registerNodeClass(ToolbarNode);
|