@gtkx/react 0.1.35 → 0.1.36
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/codegen/jsx-generator.js +31 -7
- package/dist/factory.d.ts +3 -1
- package/dist/factory.js +11 -1
- package/dist/flush-sync.d.ts +4 -0
- package/dist/flush-sync.js +27 -0
- package/dist/generated/jsx.d.ts +12 -7
- package/dist/generated/jsx.js +5 -1
- package/dist/index.js +3 -1
- package/dist/node.d.ts +2 -3
- package/dist/node.js +1 -2
- package/dist/nodes/column-view.d.ts +45 -0
- package/dist/nodes/column-view.js +227 -0
- package/dist/nodes/list.d.ts +2 -3
- package/dist/nodes/list.js +46 -30
- package/dist/nodes/notebook.d.ts +27 -0
- package/dist/nodes/notebook.js +102 -0
- package/dist/nodes/root.d.ts +9 -0
- package/dist/nodes/root.js +13 -0
- package/dist/nodes/widget.d.ts +0 -1
- package/dist/nodes/widget.js +53 -5
- package/dist/portal.js +2 -2
- package/dist/reconciler.d.ts +3 -2
- package/dist/reconciler.js +2 -8
- package/dist/render.js +3 -2
- package/dist/types.d.ts +19 -3
- package/package.json +3 -3
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { toCamelCase, toPascalCase } from "@gtkx/gir";
|
|
2
2
|
import { format } from "prettier";
|
|
3
|
-
const LIST_WIDGETS = new Set(["ListView", "
|
|
3
|
+
const LIST_WIDGETS = new Set(["ListView", "GridView"]);
|
|
4
|
+
const COLUMN_VIEW_WIDGET = "ColumnView";
|
|
4
5
|
const DROPDOWN_WIDGETS = new Set(["DropDown"]);
|
|
5
6
|
const GRID_WIDGETS = new Set(["Grid"]);
|
|
7
|
+
const NOTEBOOK_WIDGET = "Notebook";
|
|
6
8
|
const INTERNALLY_PROVIDED_PARAMS = {
|
|
7
9
|
ApplicationWindow: new Set(["application"]),
|
|
8
10
|
};
|
|
@@ -27,8 +29,10 @@ const toJsxPropertyType = (tsType) => {
|
|
|
27
29
|
return `Gtk.${result}`;
|
|
28
30
|
};
|
|
29
31
|
const isListWidget = (widgetName) => LIST_WIDGETS.has(widgetName);
|
|
32
|
+
const isColumnViewWidget = (widgetName) => widgetName === COLUMN_VIEW_WIDGET;
|
|
30
33
|
const isDropDownWidget = (widgetName) => DROPDOWN_WIDGETS.has(widgetName);
|
|
31
34
|
const isGridWidget = (widgetName) => GRID_WIDGETS.has(widgetName);
|
|
35
|
+
const isNotebookWidget = (widgetName) => widgetName === NOTEBOOK_WIDGET;
|
|
32
36
|
const sanitizeDoc = (doc) => {
|
|
33
37
|
let result = doc;
|
|
34
38
|
result = result.replace(/<picture>[\s\S]*?<\/picture>/gi, "");
|
|
@@ -113,14 +117,14 @@ export class JsxGenerator {
|
|
|
113
117
|
`import type { ReactNode, Ref } from "react";`,
|
|
114
118
|
...externalImports,
|
|
115
119
|
`import type * as Gtk from "@gtkx/ffi/gtk";`,
|
|
116
|
-
`import type { GridChildProps, ListItemProps, SlotProps } from "../types.js";`,
|
|
120
|
+
`import type { ColumnViewColumnProps, GridChildProps, ListItemProps, ListViewRenderProps, NotebookPageProps, SlotProps } from "../types.js";`,
|
|
117
121
|
"",
|
|
118
122
|
].join("\n");
|
|
119
123
|
}
|
|
120
124
|
generateCommonTypes(widgetClass) {
|
|
121
125
|
const widgetPropsContent = this.generateWidgetPropsContent(widgetClass);
|
|
122
126
|
return `
|
|
123
|
-
export {
|
|
127
|
+
export { ColumnViewColumnProps, GridChildProps, ListItemProps, ListViewRenderProps, NotebookPageProps, SlotProps };
|
|
124
128
|
|
|
125
129
|
${widgetPropsContent}
|
|
126
130
|
`;
|
|
@@ -309,8 +313,13 @@ ${widgetPropsContent}
|
|
|
309
313
|
}
|
|
310
314
|
if (isListWidget(widget.name)) {
|
|
311
315
|
lines.push("");
|
|
312
|
-
lines.push(`\t
|
|
313
|
-
lines.push(`\
|
|
316
|
+
lines.push(`\t/**`);
|
|
317
|
+
lines.push(`\t * Render function for list items.`);
|
|
318
|
+
lines.push(`\t * Called with null during setup/unbind and with the actual item during bind.`);
|
|
319
|
+
lines.push(`\t * The ref callback must be attached to the root widget to set it as the list item's child.`);
|
|
320
|
+
lines.push(`\t */`);
|
|
321
|
+
lines.push(`\t// biome-ignore lint/suspicious/noExplicitAny: allows typed renderItem callbacks`);
|
|
322
|
+
lines.push(`\trenderItem: (item: any, ref: import("react").RefCallback<Gtk.Widget>) => import("react").ReactElement;`);
|
|
314
323
|
}
|
|
315
324
|
if (isDropDownWidget(widget.name)) {
|
|
316
325
|
lines.push("");
|
|
@@ -523,16 +532,22 @@ ${widgetPropsContent}
|
|
|
523
532
|
const nonChildSlots = metadata.namedChildSlots.filter((slot) => slot.slotName !== "Child");
|
|
524
533
|
const hasMeaningfulSlots = nonChildSlots.length > 0 ||
|
|
525
534
|
isListWidget(widget.name) ||
|
|
535
|
+
isColumnViewWidget(widget.name) ||
|
|
526
536
|
isDropDownWidget(widget.name) ||
|
|
527
|
-
isGridWidget(widget.name)
|
|
537
|
+
isGridWidget(widget.name) ||
|
|
538
|
+
isNotebookWidget(widget.name);
|
|
528
539
|
const docComment = widget.doc ? formatDoc(widget.doc).trimEnd() : "";
|
|
529
540
|
if (hasMeaningfulSlots) {
|
|
530
541
|
const valueMembers = [
|
|
531
542
|
`Root: "${widgetName}.Root" as const`,
|
|
532
543
|
...metadata.namedChildSlots.map((slot) => `${slot.slotName}: "${widgetName}.${slot.slotName}" as const`),
|
|
533
544
|
...(isListWidget(widget.name) ? [`Item: "${widgetName}.Item" as const`] : []),
|
|
545
|
+
...(isColumnViewWidget(widget.name)
|
|
546
|
+
? [`Column: "${widgetName}.Column" as const`, `Item: "${widgetName}.Item" as const`]
|
|
547
|
+
: []),
|
|
534
548
|
...(isDropDownWidget(widget.name) ? [`Item: "${widgetName}.Item" as const`] : []),
|
|
535
549
|
...(isGridWidget(widget.name) ? [`Child: "${widgetName}.Child" as const`] : []),
|
|
550
|
+
...(isNotebookWidget(widget.name) ? [`Page: "${widgetName}.Page" as const`] : []),
|
|
536
551
|
];
|
|
537
552
|
if (docComment) {
|
|
538
553
|
lines.push(`${docComment}\nexport const ${widgetName} = {\n\t${valueMembers.join(",\n\t")},\n};`);
|
|
@@ -565,8 +580,10 @@ ${widgetPropsContent}
|
|
|
565
580
|
const nonChildSlots = metadata.namedChildSlots.filter((slot) => slot.slotName !== "Child");
|
|
566
581
|
const hasMeaningfulSlots = nonChildSlots.length > 0 ||
|
|
567
582
|
isListWidget(widget.name) ||
|
|
583
|
+
isColumnViewWidget(widget.name) ||
|
|
568
584
|
isDropDownWidget(widget.name) ||
|
|
569
|
-
isGridWidget(widget.name)
|
|
585
|
+
isGridWidget(widget.name) ||
|
|
586
|
+
isNotebookWidget(widget.name);
|
|
570
587
|
if (hasMeaningfulSlots) {
|
|
571
588
|
elements.push(`"${widgetName}.Root": ${propsName};`);
|
|
572
589
|
}
|
|
@@ -579,12 +596,19 @@ ${widgetPropsContent}
|
|
|
579
596
|
if (isListWidget(widget.name)) {
|
|
580
597
|
elements.push(`"${widgetName}.Item": ListItemProps;`);
|
|
581
598
|
}
|
|
599
|
+
if (isColumnViewWidget(widget.name)) {
|
|
600
|
+
elements.push(`"${widgetName}.Column": ColumnViewColumnProps;`);
|
|
601
|
+
elements.push(`"${widgetName}.Item": ListItemProps;`);
|
|
602
|
+
}
|
|
582
603
|
if (isDropDownWidget(widget.name)) {
|
|
583
604
|
elements.push(`"${widgetName}.Item": ListItemProps;`);
|
|
584
605
|
}
|
|
585
606
|
if (isGridWidget(widget.name)) {
|
|
586
607
|
elements.push(`"${widgetName}.Child": GridChildProps;`);
|
|
587
608
|
}
|
|
609
|
+
if (isNotebookWidget(widget.name)) {
|
|
610
|
+
elements.push(`"${widgetName}.Page": NotebookPageProps;`);
|
|
611
|
+
}
|
|
588
612
|
}
|
|
589
613
|
return `
|
|
590
614
|
declare global {
|
package/dist/factory.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { Node } from "./node.js";
|
|
3
|
+
import { type ROOT_NODE_CONTAINER } from "./nodes/root.js";
|
|
3
4
|
export type Props = Record<string, unknown>;
|
|
4
|
-
export
|
|
5
|
+
export { ROOT_NODE_CONTAINER } from "./nodes/root.js";
|
|
6
|
+
export declare const createNode: (type: string, props: Props, app: Gtk.Application, existingWidget?: Gtk.Widget | typeof ROOT_NODE_CONTAINER) => Node;
|
package/dist/factory.js
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
|
+
import { ColumnViewColumnNode, ColumnViewItemNode, ColumnViewNode } from "./nodes/column-view.js";
|
|
1
2
|
import { DropDownItemNode, DropDownNode } from "./nodes/dropdown.js";
|
|
2
3
|
import { GridChildNode, GridNode } from "./nodes/grid.js";
|
|
3
4
|
import { ListItemNode, ListViewNode } from "./nodes/list.js";
|
|
5
|
+
import { NotebookNode, NotebookPageNode } from "./nodes/notebook.js";
|
|
4
6
|
import { OverlayNode } from "./nodes/overlay.js";
|
|
7
|
+
import { RootNode } from "./nodes/root.js";
|
|
5
8
|
import { SlotNode } from "./nodes/slot.js";
|
|
6
9
|
import { WidgetNode } from "./nodes/widget.js";
|
|
10
|
+
export { ROOT_NODE_CONTAINER } from "./nodes/root.js";
|
|
7
11
|
const NODE_CLASSES = [
|
|
12
|
+
RootNode,
|
|
13
|
+
ColumnViewColumnNode,
|
|
14
|
+
ColumnViewItemNode,
|
|
8
15
|
ListItemNode,
|
|
9
16
|
DropDownItemNode,
|
|
10
17
|
GridChildNode,
|
|
18
|
+
NotebookPageNode,
|
|
11
19
|
SlotNode,
|
|
12
20
|
DropDownNode,
|
|
13
21
|
GridNode,
|
|
14
22
|
OverlayNode,
|
|
23
|
+
ColumnViewNode,
|
|
15
24
|
ListViewNode,
|
|
25
|
+
NotebookNode,
|
|
16
26
|
WidgetNode,
|
|
17
27
|
];
|
|
18
28
|
export const createNode = (type, props, app, existingWidget) => {
|
|
19
29
|
for (const NodeClass of NODE_CLASSES) {
|
|
20
|
-
if (NodeClass.matches(type)) {
|
|
30
|
+
if (NodeClass.matches(type, props, existingWidget)) {
|
|
21
31
|
return new NodeClass(type, props, app, existingWidget);
|
|
22
32
|
}
|
|
23
33
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ROOT_NODE_CONTAINER } from "./factory.js";
|
|
2
|
+
import { reconciler } from "./reconciler.js";
|
|
3
|
+
export const updateSync = (element, fiberRoot) => {
|
|
4
|
+
const instance = reconciler.getInstance();
|
|
5
|
+
const instanceAny = instance;
|
|
6
|
+
if (typeof instanceAny.flushSync === "function") {
|
|
7
|
+
instanceAny.flushSync(() => {
|
|
8
|
+
instance.updateContainer(element, fiberRoot, null, () => { });
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
if (typeof instanceAny.updateContainerSync === "function") {
|
|
13
|
+
instanceAny.updateContainerSync(element, fiberRoot, null, () => { });
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
instance.updateContainer(element, fiberRoot, null, () => { });
|
|
17
|
+
}
|
|
18
|
+
if (typeof instanceAny.flushSyncWork === "function") {
|
|
19
|
+
instanceAny.flushSyncWork();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
instance.flushPassiveEffects();
|
|
23
|
+
};
|
|
24
|
+
export const createFiberRoot = () => {
|
|
25
|
+
const instance = reconciler.getInstance();
|
|
26
|
+
return instance.createContainer(ROOT_NODE_CONTAINER, 0, null, false, null, "", (error) => console.error("List item render error:", error), () => { }, () => { }, () => { }, null);
|
|
27
|
+
};
|
package/dist/generated/jsx.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { ReactNode, Ref } from "react";
|
|
|
3
3
|
import type * as Gdk from "@gtkx/ffi/gdk";
|
|
4
4
|
import type * as Gio from "@gtkx/ffi/gio";
|
|
5
5
|
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
6
|
-
import type { GridChildProps, ListItemProps, SlotProps } from "../types.js";
|
|
7
|
-
export {
|
|
6
|
+
import type { ColumnViewColumnProps, GridChildProps, ListItemProps, ListViewRenderProps, NotebookPageProps, SlotProps } from "../types.js";
|
|
7
|
+
export { ColumnViewColumnProps, GridChildProps, ListItemProps, ListViewRenderProps, NotebookPageProps, SlotProps, };
|
|
8
8
|
export interface WidgetProps {
|
|
9
9
|
canFocus?: boolean;
|
|
10
10
|
canTarget?: boolean;
|
|
@@ -268,7 +268,6 @@ export interface ColumnViewProps extends WidgetProps {
|
|
|
268
268
|
vadjustment?: Gtk.Adjustment;
|
|
269
269
|
vscrollPolicy?: Gtk.ScrollablePolicy;
|
|
270
270
|
onActivate?: (self: Gtk.ColumnView, position: number) => void;
|
|
271
|
-
renderItem?: (item: any) => Gtk.Widget;
|
|
272
271
|
ref?: Ref<Gtk.ColumnView>;
|
|
273
272
|
}
|
|
274
273
|
export interface ComboBoxProps extends WidgetProps {
|
|
@@ -567,7 +566,7 @@ export interface GridViewProps extends ListBaseProps {
|
|
|
567
566
|
singleClickActivate?: boolean;
|
|
568
567
|
tabBehavior?: Gtk.ListTabBehavior;
|
|
569
568
|
onActivate?: (self: Gtk.GridView, position: number) => void;
|
|
570
|
-
renderItem
|
|
569
|
+
renderItem: (item: any, ref: import("react").RefCallback<Gtk.Widget>) => import("react").ReactElement;
|
|
571
570
|
ref?: Ref<Gtk.GridView>;
|
|
572
571
|
}
|
|
573
572
|
export interface HeaderBarProps extends WidgetProps {
|
|
@@ -725,7 +724,7 @@ export interface ListViewProps extends ListBaseProps {
|
|
|
725
724
|
singleClickActivate?: boolean;
|
|
726
725
|
tabBehavior?: Gtk.ListTabBehavior;
|
|
727
726
|
onActivate?: (self: Gtk.ListView, position: number) => void;
|
|
728
|
-
renderItem
|
|
727
|
+
renderItem: (item: any, ref: import("react").RefCallback<Gtk.Widget>) => import("react").ReactElement;
|
|
729
728
|
ref?: Ref<Gtk.ListView>;
|
|
730
729
|
}
|
|
731
730
|
export interface LockButtonProps extends ButtonProps {
|
|
@@ -1305,6 +1304,7 @@ export declare const ColorChooserWidget: "ColorChooserWidget";
|
|
|
1305
1304
|
export declare const ColorDialogButton: "ColorDialogButton";
|
|
1306
1305
|
export declare const ColumnView: {
|
|
1307
1306
|
Root: "ColumnView.Root";
|
|
1307
|
+
Column: "ColumnView.Column";
|
|
1308
1308
|
Item: "ColumnView.Item";
|
|
1309
1309
|
};
|
|
1310
1310
|
export declare const ComboBox: "ComboBox";
|
|
@@ -1377,7 +1377,10 @@ export declare const MenuButton: {
|
|
|
1377
1377
|
Popover: "MenuButton.Popover";
|
|
1378
1378
|
};
|
|
1379
1379
|
export declare const MessageDialog: "MessageDialog";
|
|
1380
|
-
export declare const Notebook:
|
|
1380
|
+
export declare const Notebook: {
|
|
1381
|
+
Root: "Notebook.Root";
|
|
1382
|
+
Page: "Notebook.Page";
|
|
1383
|
+
};
|
|
1381
1384
|
export declare const Overlay: "Overlay";
|
|
1382
1385
|
export declare const PageSetupUnixDialog: "PageSetupUnixDialog";
|
|
1383
1386
|
export declare const Paned: {
|
|
@@ -1479,6 +1482,7 @@ declare global {
|
|
|
1479
1482
|
ColorChooserWidget: ColorChooserWidgetProps;
|
|
1480
1483
|
ColorDialogButton: ColorDialogButtonProps;
|
|
1481
1484
|
"ColumnView.Root": ColumnViewProps;
|
|
1485
|
+
"ColumnView.Column": ColumnViewColumnProps;
|
|
1482
1486
|
"ColumnView.Item": ListItemProps;
|
|
1483
1487
|
ComboBox: ComboBoxProps;
|
|
1484
1488
|
"ComboBox.Child": SlotProps;
|
|
@@ -1537,7 +1541,8 @@ declare global {
|
|
|
1537
1541
|
"MenuButton.Child": SlotProps;
|
|
1538
1542
|
"MenuButton.Popover": SlotProps;
|
|
1539
1543
|
MessageDialog: MessageDialogProps;
|
|
1540
|
-
Notebook: NotebookProps;
|
|
1544
|
+
"Notebook.Root": NotebookProps;
|
|
1545
|
+
"Notebook.Page": NotebookPageProps;
|
|
1541
1546
|
Overlay: OverlayProps;
|
|
1542
1547
|
"Overlay.Child": SlotProps;
|
|
1543
1548
|
PageSetupUnixDialog: PageSetupUnixDialogProps;
|
package/dist/generated/jsx.js
CHANGED
|
@@ -3969,6 +3969,7 @@ export const ColorChooserWidget = "ColorChooserWidget";
|
|
|
3969
3969
|
export const ColorDialogButton = "ColorDialogButton";
|
|
3970
3970
|
export const ColumnView = {
|
|
3971
3971
|
Root: "ColumnView.Root",
|
|
3972
|
+
Column: "ColumnView.Column",
|
|
3972
3973
|
Item: "ColumnView.Item",
|
|
3973
3974
|
};
|
|
3974
3975
|
export const ComboBox = "ComboBox";
|
|
@@ -4041,7 +4042,10 @@ export const MenuButton = {
|
|
|
4041
4042
|
Popover: "MenuButton.Popover",
|
|
4042
4043
|
};
|
|
4043
4044
|
export const MessageDialog = "MessageDialog";
|
|
4044
|
-
export const Notebook =
|
|
4045
|
+
export const Notebook = {
|
|
4046
|
+
Root: "Notebook.Root",
|
|
4047
|
+
Page: "Notebook.Page",
|
|
4048
|
+
};
|
|
4045
4049
|
export const Overlay = "Overlay";
|
|
4046
4050
|
export const PageSetupUnixDialog = "PageSetupUnixDialog";
|
|
4047
4051
|
export const Paned = {
|
package/dist/index.js
CHANGED
package/dist/node.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
-
import type { Props } from "./factory.js";
|
|
2
|
+
import type { Props, ROOT_NODE_CONTAINER } from "./factory.js";
|
|
3
3
|
export declare abstract class Node<T extends Gtk.Widget | undefined = Gtk.Widget | undefined> {
|
|
4
|
-
static matches(_type: string): boolean;
|
|
4
|
+
static matches(_type: string, _props: Props, _existingWidget?: Gtk.Widget | typeof ROOT_NODE_CONTAINER): boolean;
|
|
5
5
|
protected signalHandlers: Map<string, number>;
|
|
6
6
|
protected widget: T;
|
|
7
7
|
protected widgetType: string;
|
|
@@ -22,5 +22,4 @@ export declare abstract class Node<T extends Gtk.Widget | undefined = Gtk.Widget
|
|
|
22
22
|
protected connectSignal(widget: Gtk.Widget, eventName: string, handler: (...args: unknown[]) => unknown): void;
|
|
23
23
|
protected setProperty(widget: Gtk.Widget, key: string, value: unknown): void;
|
|
24
24
|
mount(_app: Gtk.Application): void;
|
|
25
|
-
dispose(_app: Gtk.Application): void;
|
|
26
25
|
}
|
package/dist/node.js
CHANGED
|
@@ -9,7 +9,7 @@ const extractConstructorArgs = (type, props) => {
|
|
|
9
9
|
return params.map((p) => props[p.name]);
|
|
10
10
|
};
|
|
11
11
|
export class Node {
|
|
12
|
-
static matches(_type) {
|
|
12
|
+
static matches(_type, _props, _existingWidget) {
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
signalHandlers = new Map();
|
|
@@ -162,5 +162,4 @@ export class Node {
|
|
|
162
162
|
setter.call(widget, value);
|
|
163
163
|
}
|
|
164
164
|
mount(_app) { }
|
|
165
|
-
dispose(_app) { }
|
|
166
165
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { Props } from "../factory.js";
|
|
3
|
+
import { Node } from "../node.js";
|
|
4
|
+
export declare class ColumnViewNode extends Node<Gtk.ColumnView> {
|
|
5
|
+
static matches(type: string): boolean;
|
|
6
|
+
private stringList;
|
|
7
|
+
private selectionModel;
|
|
8
|
+
private items;
|
|
9
|
+
private columns;
|
|
10
|
+
constructor(type: string, props: Props, app: Gtk.Application);
|
|
11
|
+
getItems(): unknown[];
|
|
12
|
+
addColumn(column: ColumnViewColumnNode): void;
|
|
13
|
+
removeColumn(column: ColumnViewColumnNode): void;
|
|
14
|
+
insertColumnBefore(column: ColumnViewColumnNode, before: ColumnViewColumnNode): void;
|
|
15
|
+
addItem(item: unknown): void;
|
|
16
|
+
insertItemBefore(item: unknown, beforeItem: unknown): void;
|
|
17
|
+
removeItem(item: unknown): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class ColumnViewColumnNode extends Node {
|
|
20
|
+
static matches(type: string): boolean;
|
|
21
|
+
protected isVirtual(): boolean;
|
|
22
|
+
private gtkColumn;
|
|
23
|
+
private factory;
|
|
24
|
+
private renderCell;
|
|
25
|
+
private columnView;
|
|
26
|
+
private fiberRoots;
|
|
27
|
+
constructor(type: string, props: Props, app: Gtk.Application);
|
|
28
|
+
getGtkColumn(): Gtk.ColumnViewColumn;
|
|
29
|
+
setColumnView(columnView: ColumnViewNode | null): 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
|
+
}
|
|
36
|
+
export declare class ColumnViewItemNode extends Node {
|
|
37
|
+
static matches(type: string): boolean;
|
|
38
|
+
protected isVirtual(): boolean;
|
|
39
|
+
private item;
|
|
40
|
+
constructor(type: string, props: Props, app: Gtk.Application);
|
|
41
|
+
getItem(): unknown;
|
|
42
|
+
attachToParent(parent: Node): void;
|
|
43
|
+
attachToParentBefore(parent: Node, before: Node): void;
|
|
44
|
+
detachFromParent(parent: Node): void;
|
|
45
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { getObject, getObjectId } from "@gtkx/ffi";
|
|
2
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
+
import { createFiberRoot, updateSync } from "../flush-sync.js";
|
|
4
|
+
import { Node } from "../node.js";
|
|
5
|
+
export class ColumnViewNode extends Node {
|
|
6
|
+
static matches(type) {
|
|
7
|
+
return type === "ColumnView.Root";
|
|
8
|
+
}
|
|
9
|
+
stringList;
|
|
10
|
+
selectionModel;
|
|
11
|
+
items = [];
|
|
12
|
+
columns = [];
|
|
13
|
+
constructor(type, props, app) {
|
|
14
|
+
super(type, props, app);
|
|
15
|
+
this.stringList = new Gtk.StringList([]);
|
|
16
|
+
this.selectionModel = new Gtk.SingleSelection(this.stringList);
|
|
17
|
+
this.widget.setModel(this.selectionModel);
|
|
18
|
+
}
|
|
19
|
+
getItems() {
|
|
20
|
+
return this.items;
|
|
21
|
+
}
|
|
22
|
+
addColumn(column) {
|
|
23
|
+
this.columns.push(column);
|
|
24
|
+
const gtkColumn = column.getGtkColumn();
|
|
25
|
+
this.widget.appendColumn(gtkColumn);
|
|
26
|
+
column.setColumnView(this);
|
|
27
|
+
}
|
|
28
|
+
removeColumn(column) {
|
|
29
|
+
const index = this.columns.indexOf(column);
|
|
30
|
+
if (index !== -1) {
|
|
31
|
+
this.columns.splice(index, 1);
|
|
32
|
+
this.widget.removeColumn(column.getGtkColumn());
|
|
33
|
+
column.setColumnView(null);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
insertColumnBefore(column, before) {
|
|
37
|
+
const beforeIndex = this.columns.indexOf(before);
|
|
38
|
+
if (beforeIndex === -1) {
|
|
39
|
+
this.addColumn(column);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.columns.splice(beforeIndex, 0, column);
|
|
43
|
+
this.widget.insertColumn(beforeIndex, column.getGtkColumn());
|
|
44
|
+
column.setColumnView(this);
|
|
45
|
+
}
|
|
46
|
+
addItem(item) {
|
|
47
|
+
this.items.push(item);
|
|
48
|
+
this.stringList.append("");
|
|
49
|
+
}
|
|
50
|
+
insertItemBefore(item, beforeItem) {
|
|
51
|
+
const beforeIndex = this.items.indexOf(beforeItem);
|
|
52
|
+
if (beforeIndex === -1) {
|
|
53
|
+
this.addItem(item);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.items.splice(beforeIndex, 0, item);
|
|
57
|
+
this.stringList.splice(beforeIndex, 0, [""]);
|
|
58
|
+
}
|
|
59
|
+
removeItem(item) {
|
|
60
|
+
const index = this.items.indexOf(item);
|
|
61
|
+
if (index !== -1) {
|
|
62
|
+
this.items.splice(index, 1);
|
|
63
|
+
this.stringList.remove(index);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export class ColumnViewColumnNode extends Node {
|
|
68
|
+
static matches(type) {
|
|
69
|
+
return type === "ColumnView.Column";
|
|
70
|
+
}
|
|
71
|
+
isVirtual() {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
gtkColumn;
|
|
75
|
+
factory;
|
|
76
|
+
renderCell;
|
|
77
|
+
columnView = null;
|
|
78
|
+
fiberRoots = new Map();
|
|
79
|
+
constructor(type, props, app) {
|
|
80
|
+
super(type, props, app);
|
|
81
|
+
this.factory = new Gtk.SignalListItemFactory();
|
|
82
|
+
this.gtkColumn = new Gtk.ColumnViewColumn(props.title, this.factory);
|
|
83
|
+
this.renderCell = props.renderCell;
|
|
84
|
+
if (props.expand !== undefined) {
|
|
85
|
+
this.gtkColumn.setExpand(props.expand);
|
|
86
|
+
}
|
|
87
|
+
if (props.resizable !== undefined) {
|
|
88
|
+
this.gtkColumn.setResizable(props.resizable);
|
|
89
|
+
}
|
|
90
|
+
if (props.fixedWidth !== undefined) {
|
|
91
|
+
this.gtkColumn.setFixedWidth(props.fixedWidth);
|
|
92
|
+
}
|
|
93
|
+
this.factory.connect("setup", (_self, listItemObj) => {
|
|
94
|
+
const listItem = getObject(listItemObj, Gtk.ListItem);
|
|
95
|
+
const id = getObjectId(listItemObj);
|
|
96
|
+
const fiberRoot = createFiberRoot();
|
|
97
|
+
this.fiberRoots.set(id, fiberRoot);
|
|
98
|
+
let rootWidget = null;
|
|
99
|
+
const ref = (widget) => {
|
|
100
|
+
if (widget && !rootWidget) {
|
|
101
|
+
rootWidget = widget;
|
|
102
|
+
listItem.setChild(widget);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const element = this.renderCell(null, ref);
|
|
106
|
+
updateSync(element, fiberRoot);
|
|
107
|
+
});
|
|
108
|
+
this.factory.connect("bind", (_self, listItemObj) => {
|
|
109
|
+
const listItem = getObject(listItemObj, Gtk.ListItem);
|
|
110
|
+
const id = getObjectId(listItemObj);
|
|
111
|
+
const fiberRoot = this.fiberRoots.get(id);
|
|
112
|
+
if (!fiberRoot)
|
|
113
|
+
return;
|
|
114
|
+
const position = listItem.getPosition();
|
|
115
|
+
if (this.columnView) {
|
|
116
|
+
const items = this.columnView.getItems();
|
|
117
|
+
const item = items[position];
|
|
118
|
+
const ref = () => { };
|
|
119
|
+
const element = this.renderCell(item ?? null, ref);
|
|
120
|
+
updateSync(element, fiberRoot);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
this.factory.connect("unbind", (_self, listItemObj) => {
|
|
124
|
+
const id = getObjectId(listItemObj);
|
|
125
|
+
const fiberRoot = this.fiberRoots.get(id);
|
|
126
|
+
if (!fiberRoot)
|
|
127
|
+
return;
|
|
128
|
+
const ref = () => { };
|
|
129
|
+
const element = this.renderCell(null, ref);
|
|
130
|
+
updateSync(element, fiberRoot);
|
|
131
|
+
});
|
|
132
|
+
this.factory.connect("teardown", (_self, listItemObj) => {
|
|
133
|
+
const id = getObjectId(listItemObj);
|
|
134
|
+
const fiberRoot = this.fiberRoots.get(id);
|
|
135
|
+
if (!fiberRoot)
|
|
136
|
+
return;
|
|
137
|
+
updateSync(null, fiberRoot);
|
|
138
|
+
this.fiberRoots.delete(id);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
getGtkColumn() {
|
|
142
|
+
return this.gtkColumn;
|
|
143
|
+
}
|
|
144
|
+
setColumnView(columnView) {
|
|
145
|
+
this.columnView = columnView;
|
|
146
|
+
}
|
|
147
|
+
attachToParent(parent) {
|
|
148
|
+
if (parent instanceof ColumnViewNode) {
|
|
149
|
+
parent.addColumn(this);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
attachToParentBefore(parent, before) {
|
|
153
|
+
if (parent instanceof ColumnViewNode && before instanceof ColumnViewColumnNode) {
|
|
154
|
+
parent.insertColumnBefore(this, before);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this.attachToParent(parent);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
detachFromParent(parent) {
|
|
161
|
+
if (parent instanceof ColumnViewNode) {
|
|
162
|
+
parent.removeColumn(this);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
consumedProps() {
|
|
166
|
+
const consumed = super.consumedProps();
|
|
167
|
+
consumed.add("renderCell");
|
|
168
|
+
consumed.add("title");
|
|
169
|
+
consumed.add("expand");
|
|
170
|
+
consumed.add("resizable");
|
|
171
|
+
consumed.add("fixedWidth");
|
|
172
|
+
return consumed;
|
|
173
|
+
}
|
|
174
|
+
updateProps(oldProps, newProps) {
|
|
175
|
+
if (oldProps.renderCell !== newProps.renderCell) {
|
|
176
|
+
this.renderCell = newProps.renderCell;
|
|
177
|
+
}
|
|
178
|
+
if (!this.gtkColumn)
|
|
179
|
+
return;
|
|
180
|
+
if (oldProps.title !== newProps.title) {
|
|
181
|
+
this.gtkColumn.setTitle(newProps.title);
|
|
182
|
+
}
|
|
183
|
+
if (oldProps.expand !== newProps.expand) {
|
|
184
|
+
this.gtkColumn.setExpand(newProps.expand);
|
|
185
|
+
}
|
|
186
|
+
if (oldProps.resizable !== newProps.resizable) {
|
|
187
|
+
this.gtkColumn.setResizable(newProps.resizable);
|
|
188
|
+
}
|
|
189
|
+
if (oldProps.fixedWidth !== newProps.fixedWidth) {
|
|
190
|
+
this.gtkColumn.setFixedWidth(newProps.fixedWidth);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
export class ColumnViewItemNode extends Node {
|
|
195
|
+
static matches(type) {
|
|
196
|
+
return type === "ColumnView.Item";
|
|
197
|
+
}
|
|
198
|
+
isVirtual() {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
item;
|
|
202
|
+
constructor(type, props, app) {
|
|
203
|
+
super(type, props, app);
|
|
204
|
+
this.item = props.item;
|
|
205
|
+
}
|
|
206
|
+
getItem() {
|
|
207
|
+
return this.item;
|
|
208
|
+
}
|
|
209
|
+
attachToParent(parent) {
|
|
210
|
+
if (parent instanceof ColumnViewNode) {
|
|
211
|
+
parent.addItem(this.item);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
attachToParentBefore(parent, before) {
|
|
215
|
+
if (parent instanceof ColumnViewNode && before instanceof ColumnViewItemNode) {
|
|
216
|
+
parent.insertItemBefore(this.item, before.getItem());
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.attachToParent(parent);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
detachFromParent(parent) {
|
|
223
|
+
if (parent instanceof ColumnViewNode) {
|
|
224
|
+
parent.removeItem(this.item);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
package/dist/nodes/list.d.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { Props } from "../factory.js";
|
|
3
3
|
import { Node } from "../node.js";
|
|
4
|
-
export declare class ListViewNode extends Node<Gtk.ListView> {
|
|
4
|
+
export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView> {
|
|
5
5
|
static matches(type: string): boolean;
|
|
6
6
|
private stringList;
|
|
7
7
|
private selectionModel;
|
|
8
8
|
private factory;
|
|
9
9
|
private items;
|
|
10
10
|
private renderItem;
|
|
11
|
-
private
|
|
11
|
+
private fiberRoots;
|
|
12
12
|
constructor(type: string, props: Props, app: Gtk.Application);
|
|
13
13
|
addItem(item: unknown): void;
|
|
14
14
|
insertItemBefore(item: unknown, beforeItem: unknown): void;
|
|
15
15
|
removeItem(item: unknown): void;
|
|
16
16
|
protected consumedProps(): Set<string>;
|
|
17
17
|
updateProps(oldProps: Props, newProps: Props): void;
|
|
18
|
-
dispose(app: Gtk.Application): void;
|
|
19
18
|
}
|
|
20
19
|
export declare class ListItemNode extends Node {
|
|
21
20
|
static matches(type: string): boolean;
|
package/dist/nodes/list.js
CHANGED
|
@@ -1,41 +1,67 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getObject, getObjectId } from "@gtkx/ffi";
|
|
2
2
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
+
import { createFiberRoot, updateSync } from "../flush-sync.js";
|
|
3
4
|
import { Node } from "../node.js";
|
|
4
|
-
const LIST_WIDGETS = ["ListView", "ColumnView", "GridView"];
|
|
5
5
|
export class ListViewNode extends Node {
|
|
6
6
|
static matches(type) {
|
|
7
|
-
return
|
|
7
|
+
return type === "ListView.Root" || type === "GridView.Root";
|
|
8
8
|
}
|
|
9
9
|
stringList;
|
|
10
10
|
selectionModel;
|
|
11
11
|
factory;
|
|
12
12
|
items = [];
|
|
13
|
-
renderItem
|
|
14
|
-
|
|
13
|
+
renderItem;
|
|
14
|
+
fiberRoots = new Map();
|
|
15
15
|
constructor(type, props, app) {
|
|
16
16
|
super(type, props, app);
|
|
17
17
|
this.stringList = new Gtk.StringList([]);
|
|
18
18
|
this.selectionModel = new Gtk.SingleSelection(this.stringList);
|
|
19
19
|
this.factory = new Gtk.SignalListItemFactory();
|
|
20
20
|
this.renderItem = props.renderItem;
|
|
21
|
-
|
|
22
|
-
const listItem =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
this.factory.connect("setup", (_self, listItemObj) => {
|
|
22
|
+
const listItem = getObject(listItemObj, Gtk.ListItem);
|
|
23
|
+
const id = getObjectId(listItemObj);
|
|
24
|
+
const fiberRoot = createFiberRoot();
|
|
25
|
+
this.fiberRoots.set(id, fiberRoot);
|
|
26
|
+
let rootWidget = null;
|
|
27
|
+
const ref = (widget) => {
|
|
28
|
+
if (widget && !rootWidget) {
|
|
29
|
+
rootWidget = widget;
|
|
30
|
+
listItem.setChild(widget);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const element = this.renderItem(null, ref);
|
|
34
|
+
updateSync(element, fiberRoot);
|
|
27
35
|
});
|
|
28
|
-
this.
|
|
29
|
-
|
|
30
|
-
const
|
|
36
|
+
this.factory.connect("bind", (_self, listItemObj) => {
|
|
37
|
+
const listItem = getObject(listItemObj, Gtk.ListItem);
|
|
38
|
+
const id = getObjectId(listItemObj);
|
|
39
|
+
const fiberRoot = this.fiberRoots.get(id);
|
|
40
|
+
if (!fiberRoot)
|
|
41
|
+
return;
|
|
31
42
|
const position = listItem.getPosition();
|
|
32
43
|
const item = this.items[position];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
const ref = () => { };
|
|
45
|
+
const element = this.renderItem(item ?? null, ref);
|
|
46
|
+
updateSync(element, fiberRoot);
|
|
47
|
+
});
|
|
48
|
+
this.factory.connect("unbind", (_self, listItemObj) => {
|
|
49
|
+
const id = getObjectId(listItemObj);
|
|
50
|
+
const fiberRoot = this.fiberRoots.get(id);
|
|
51
|
+
if (!fiberRoot)
|
|
52
|
+
return;
|
|
53
|
+
const ref = () => { };
|
|
54
|
+
const element = this.renderItem(null, ref);
|
|
55
|
+
updateSync(element, fiberRoot);
|
|
56
|
+
});
|
|
57
|
+
this.factory.connect("teardown", (_self, listItemObj) => {
|
|
58
|
+
const id = getObjectId(listItemObj);
|
|
59
|
+
const fiberRoot = this.fiberRoots.get(id);
|
|
60
|
+
if (!fiberRoot)
|
|
61
|
+
return;
|
|
62
|
+
updateSync(null, fiberRoot);
|
|
63
|
+
this.fiberRoots.delete(id);
|
|
37
64
|
});
|
|
38
|
-
this.factorySignalHandlers.set("bind", bindHandlerId);
|
|
39
65
|
this.widget.setModel(this.selectionModel);
|
|
40
66
|
this.widget.setFactory(this.factory);
|
|
41
67
|
}
|
|
@@ -70,20 +96,10 @@ export class ListViewNode extends Node {
|
|
|
70
96
|
}
|
|
71
97
|
super.updateProps(oldProps, newProps);
|
|
72
98
|
}
|
|
73
|
-
dispose(app) {
|
|
74
|
-
super.dispose(app);
|
|
75
|
-
this.widget.setModel(undefined);
|
|
76
|
-
this.widget.setFactory(undefined);
|
|
77
|
-
}
|
|
78
99
|
}
|
|
79
100
|
export class ListItemNode extends Node {
|
|
80
101
|
static matches(type) {
|
|
81
|
-
|
|
82
|
-
if (dotIndex === -1)
|
|
83
|
-
return false;
|
|
84
|
-
const widgetType = type.slice(0, dotIndex);
|
|
85
|
-
const suffix = type.slice(dotIndex + 1);
|
|
86
|
-
return suffix === "Item" && LIST_WIDGETS.includes(widgetType);
|
|
102
|
+
return type === "ListView.Item" || type === "GridView.Item";
|
|
87
103
|
}
|
|
88
104
|
isVirtual() {
|
|
89
105
|
return true;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { Props } from "../factory.js";
|
|
3
|
+
import { Node } from "../node.js";
|
|
4
|
+
export declare class NotebookNode extends Node<Gtk.Notebook> {
|
|
5
|
+
static matches(type: string): boolean;
|
|
6
|
+
addPage(child: Gtk.Widget, label: string): void;
|
|
7
|
+
insertPageBefore(child: Gtk.Widget, label: string, beforeChild: Gtk.Widget): void;
|
|
8
|
+
removePage(child: Gtk.Widget): void;
|
|
9
|
+
updatePageLabel(child: Gtk.Widget, label: string): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class NotebookPageNode extends Node {
|
|
12
|
+
static matches(type: string): boolean;
|
|
13
|
+
protected isVirtual(): boolean;
|
|
14
|
+
private label;
|
|
15
|
+
private childWidget;
|
|
16
|
+
private parentNotebook;
|
|
17
|
+
constructor(type: string, props: Props, app: Gtk.Application);
|
|
18
|
+
getLabel(): string;
|
|
19
|
+
setChildWidget(widget: Gtk.Widget): void;
|
|
20
|
+
getChildWidget(): Gtk.Widget | null;
|
|
21
|
+
appendChild(child: Node): void;
|
|
22
|
+
attachToParent(parent: Node): void;
|
|
23
|
+
attachToParentBefore(parent: Node, before: Node): void;
|
|
24
|
+
detachFromParent(parent: Node): void;
|
|
25
|
+
protected consumedProps(): Set<string>;
|
|
26
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { Node } from "../node.js";
|
|
3
|
+
export class NotebookNode extends Node {
|
|
4
|
+
static matches(type) {
|
|
5
|
+
return type === "Notebook.Root";
|
|
6
|
+
}
|
|
7
|
+
addPage(child, label) {
|
|
8
|
+
const tabLabel = new Gtk.Label();
|
|
9
|
+
tabLabel.setLabel(label);
|
|
10
|
+
this.widget.appendPage(child, tabLabel);
|
|
11
|
+
}
|
|
12
|
+
insertPageBefore(child, label, beforeChild) {
|
|
13
|
+
const beforePageNum = this.widget.pageNum(beforeChild);
|
|
14
|
+
const tabLabel = new Gtk.Label();
|
|
15
|
+
tabLabel.setLabel(label);
|
|
16
|
+
if (beforePageNum >= 0) {
|
|
17
|
+
this.widget.insertPage(child, beforePageNum, tabLabel);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.widget.appendPage(child, tabLabel);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
removePage(child) {
|
|
24
|
+
const pageNum = this.widget.pageNum(child);
|
|
25
|
+
if (pageNum >= 0) {
|
|
26
|
+
this.widget.removePage(pageNum);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
updatePageLabel(child, label) {
|
|
30
|
+
const tabLabel = new Gtk.Label();
|
|
31
|
+
tabLabel.setLabel(label);
|
|
32
|
+
this.widget.setTabLabel(child, tabLabel);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class NotebookPageNode extends Node {
|
|
36
|
+
static matches(type) {
|
|
37
|
+
return type === "Notebook.Page";
|
|
38
|
+
}
|
|
39
|
+
isVirtual() {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
label;
|
|
43
|
+
childWidget = null;
|
|
44
|
+
parentNotebook = null;
|
|
45
|
+
constructor(type, props, app) {
|
|
46
|
+
super(type, props, app);
|
|
47
|
+
this.label = props.label ?? "";
|
|
48
|
+
}
|
|
49
|
+
getLabel() {
|
|
50
|
+
return this.label;
|
|
51
|
+
}
|
|
52
|
+
setChildWidget(widget) {
|
|
53
|
+
this.childWidget = widget;
|
|
54
|
+
}
|
|
55
|
+
getChildWidget() {
|
|
56
|
+
return this.childWidget;
|
|
57
|
+
}
|
|
58
|
+
appendChild(child) {
|
|
59
|
+
const childWidget = child.getWidget();
|
|
60
|
+
if (childWidget) {
|
|
61
|
+
this.childWidget = childWidget;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
attachToParent(parent) {
|
|
65
|
+
if (parent instanceof NotebookNode && this.childWidget) {
|
|
66
|
+
this.parentNotebook = parent;
|
|
67
|
+
parent.addPage(this.childWidget, this.label);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
attachToParentBefore(parent, before) {
|
|
71
|
+
if (parent instanceof NotebookNode && this.childWidget) {
|
|
72
|
+
this.parentNotebook = parent;
|
|
73
|
+
const beforePage = before instanceof NotebookPageNode ? before.getChildWidget() : before.getWidget();
|
|
74
|
+
if (beforePage) {
|
|
75
|
+
parent.insertPageBefore(this.childWidget, this.label, beforePage);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
parent.addPage(this.childWidget, this.label);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
detachFromParent(parent) {
|
|
83
|
+
if (parent instanceof NotebookNode && this.childWidget) {
|
|
84
|
+
parent.removePage(this.childWidget);
|
|
85
|
+
this.parentNotebook = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
consumedProps() {
|
|
89
|
+
const consumed = super.consumedProps();
|
|
90
|
+
consumed.add("label");
|
|
91
|
+
return consumed;
|
|
92
|
+
}
|
|
93
|
+
updateProps(oldProps, newProps) {
|
|
94
|
+
if (oldProps.label !== newProps.label) {
|
|
95
|
+
this.label = newProps.label ?? "";
|
|
96
|
+
if (this.parentNotebook && this.childWidget) {
|
|
97
|
+
this.parentNotebook.updatePageLabel(this.childWidget, this.label);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
super.updateProps(oldProps, newProps);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { Props } from "../factory.js";
|
|
3
|
+
import { Node } from "../node.js";
|
|
4
|
+
export declare const ROOT_NODE_CONTAINER: unique symbol;
|
|
5
|
+
export declare class RootNode extends Node<never> {
|
|
6
|
+
static matches(_type: string, _props: Props, existingWidget?: Gtk.Widget | typeof ROOT_NODE_CONTAINER): boolean;
|
|
7
|
+
protected isVirtual(): boolean;
|
|
8
|
+
constructor(app: Gtk.Application);
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Node } from "../node.js";
|
|
2
|
+
export const ROOT_NODE_CONTAINER = Symbol.for("ROOT_NODE_CONTAINER");
|
|
3
|
+
export class RootNode extends Node {
|
|
4
|
+
static matches(_type, _props, existingWidget) {
|
|
5
|
+
return existingWidget === ROOT_NODE_CONTAINER;
|
|
6
|
+
}
|
|
7
|
+
isVirtual() {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
constructor(app) {
|
|
11
|
+
super("", {}, app);
|
|
12
|
+
}
|
|
13
|
+
}
|
package/dist/nodes/widget.d.ts
CHANGED
package/dist/nodes/widget.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { getObjectId } from "@gtkx/ffi";
|
|
2
|
+
import * as GObject from "@gtkx/ffi/gobject";
|
|
1
3
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
4
|
import { Node } from "../node.js";
|
|
3
5
|
import { OverlayNode } from "./overlay.js";
|
|
6
|
+
const isFlowBox = (widget) => widget instanceof Gtk.FlowBox;
|
|
7
|
+
const isFlowBoxChild = (widget) => GObject.typeNameFromInstance(getObjectId(widget.ptr)) === "GtkFlowBoxChild";
|
|
8
|
+
const isListBox = (widget) => widget instanceof Gtk.ListBox;
|
|
9
|
+
const isListBoxRow = (widget) => GObject.typeNameFromInstance(getObjectId(widget.ptr)) === "GtkListBoxRow";
|
|
4
10
|
const COMBINED_PROPS = [
|
|
5
11
|
{
|
|
6
12
|
props: ["defaultWidth", "defaultHeight"],
|
|
@@ -36,6 +42,14 @@ export class WidgetNode extends Node {
|
|
|
36
42
|
parentWidget.appendPage(this.widget);
|
|
37
43
|
return;
|
|
38
44
|
}
|
|
45
|
+
if (isFlowBox(parentWidget)) {
|
|
46
|
+
parentWidget.append(this.widget);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (isListBox(parentWidget)) {
|
|
50
|
+
parentWidget.append(this.widget);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
39
53
|
super.attachToParent(parent);
|
|
40
54
|
}
|
|
41
55
|
attachToParentBefore(parent, before) {
|
|
@@ -70,9 +84,37 @@ export class WidgetNode extends Node {
|
|
|
70
84
|
}
|
|
71
85
|
return;
|
|
72
86
|
}
|
|
87
|
+
if (isFlowBox(parentWidget)) {
|
|
88
|
+
if (beforeWidget) {
|
|
89
|
+
const beforeChild = beforeWidget.getParent();
|
|
90
|
+
if (beforeChild && isFlowBoxChild(beforeChild)) {
|
|
91
|
+
parentWidget.insert(this.widget, beforeChild.getIndex());
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
parentWidget.append(this.widget);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
parentWidget.append(this.widget);
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (isListBox(parentWidget)) {
|
|
103
|
+
if (beforeWidget && isListBoxRow(beforeWidget)) {
|
|
104
|
+
parentWidget.insert(this.widget, beforeWidget.getIndex());
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
parentWidget.append(this.widget);
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
73
111
|
super.attachToParentBefore(parent, before);
|
|
74
112
|
}
|
|
75
113
|
detachFromParent(parent) {
|
|
114
|
+
if (this.widget instanceof Gtk.Window) {
|
|
115
|
+
this.widget.destroy();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
76
118
|
if (this.widget instanceof Gtk.AboutDialog) {
|
|
77
119
|
return;
|
|
78
120
|
}
|
|
@@ -94,6 +136,17 @@ export class WidgetNode extends Node {
|
|
|
94
136
|
}
|
|
95
137
|
return;
|
|
96
138
|
}
|
|
139
|
+
if (isFlowBox(parentWidget)) {
|
|
140
|
+
const flowBoxChild = this.widget.getParent();
|
|
141
|
+
if (flowBoxChild) {
|
|
142
|
+
parentWidget.remove(flowBoxChild);
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (isListBox(parentWidget)) {
|
|
147
|
+
parentWidget.remove(this.widget);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
97
150
|
super.detachFromParent(parent);
|
|
98
151
|
}
|
|
99
152
|
consumedProps() {
|
|
@@ -123,9 +176,4 @@ export class WidgetNode extends Node {
|
|
|
123
176
|
this.widget.present();
|
|
124
177
|
}
|
|
125
178
|
}
|
|
126
|
-
dispose(_app) {
|
|
127
|
-
if (this.widget instanceof Gtk.Window) {
|
|
128
|
-
this.widget.destroy();
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
179
|
}
|
package/dist/portal.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ROOT_NODE_CONTAINER } from "./factory.js";
|
|
2
2
|
export const createPortal = (children, container, key) => {
|
|
3
3
|
return {
|
|
4
4
|
$$typeof: Symbol.for("react.portal"),
|
|
5
5
|
key: key ?? null,
|
|
6
6
|
children,
|
|
7
|
-
containerInfo: container ??
|
|
7
|
+
containerInfo: container ?? ROOT_NODE_CONTAINER,
|
|
8
8
|
implementation: null,
|
|
9
9
|
};
|
|
10
10
|
};
|
package/dist/reconciler.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import * as Gtk from "@gtkx/ffi/gtk";
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import ReactReconciler from "react-reconciler";
|
|
3
|
+
import { type ROOT_NODE_CONTAINER } from "./factory.js";
|
|
3
4
|
import type { Node } from "./node.js";
|
|
4
|
-
type Container = Gtk.
|
|
5
|
+
type Container = Gtk.Widget | typeof ROOT_NODE_CONTAINER;
|
|
5
6
|
type TextInstance = Node;
|
|
6
7
|
type SuspenseInstance = never;
|
|
7
8
|
type PublicInstance = Gtk.Widget;
|
package/dist/reconciler.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getCurrentApp } from "@gtkx/ffi";
|
|
2
|
-
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import ReactReconciler from "react-reconciler";
|
|
5
4
|
import { createNode } from "./factory.js";
|
|
@@ -71,9 +70,7 @@ class Reconciler {
|
|
|
71
70
|
afterActiveInstanceBlur: () => { },
|
|
72
71
|
prepareScopeUpdate: () => { },
|
|
73
72
|
getInstanceFromScope: () => null,
|
|
74
|
-
detachDeletedInstance: (
|
|
75
|
-
instance.dispose(getCurrentApp());
|
|
76
|
-
},
|
|
73
|
+
detachDeletedInstance: () => { },
|
|
77
74
|
resetFormInstance: () => { },
|
|
78
75
|
requestPostPaintCallback: () => { },
|
|
79
76
|
shouldAttemptEagerTransition: () => false,
|
|
@@ -92,10 +89,7 @@ class Reconciler {
|
|
|
92
89
|
return context;
|
|
93
90
|
}
|
|
94
91
|
createNodeFromContainer(container) {
|
|
95
|
-
|
|
96
|
-
return createNode(container.constructor.name, {}, getCurrentApp(), container);
|
|
97
|
-
}
|
|
98
|
-
return createNode("Application", {}, getCurrentApp(), container);
|
|
92
|
+
return createNode(container.constructor.name, {}, getCurrentApp(), container);
|
|
99
93
|
}
|
|
100
94
|
}
|
|
101
95
|
export const reconciler = new Reconciler();
|
package/dist/render.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { start } from "@gtkx/ffi";
|
|
2
|
+
import { ROOT_NODE_CONTAINER } from "./factory.js";
|
|
2
3
|
import { reconciler } from "./reconciler.js";
|
|
3
4
|
export let container = null;
|
|
4
5
|
export const render = (element, appId, flags) => {
|
|
5
|
-
|
|
6
|
+
start(appId, flags);
|
|
6
7
|
const instance = reconciler.getInstance();
|
|
7
|
-
container = instance.createContainer(
|
|
8
|
+
container = instance.createContainer(ROOT_NODE_CONTAINER, 0, null, false, null, "", (error, info) => {
|
|
8
9
|
console.error("Uncaught error in GTKX application:", error, info);
|
|
9
10
|
}, (_error, _info) => { }, (_error, _info) => { }, () => { }, null);
|
|
10
11
|
instance.updateContainer(element, container, null, () => { });
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { ReactElement, ReactNode, RefCallback } from "react";
|
|
2
3
|
export interface SlotProps {
|
|
3
4
|
children?: ReactNode;
|
|
4
5
|
}
|
|
5
|
-
export interface ListItemProps {
|
|
6
|
-
item:
|
|
6
|
+
export interface ListItemProps<I = unknown> {
|
|
7
|
+
item: I;
|
|
7
8
|
}
|
|
8
9
|
export interface GridChildProps extends SlotProps {
|
|
9
10
|
column?: number;
|
|
@@ -11,3 +12,18 @@ export interface GridChildProps extends SlotProps {
|
|
|
11
12
|
columnSpan?: number;
|
|
12
13
|
rowSpan?: number;
|
|
13
14
|
}
|
|
15
|
+
export type RenderItemFn<T> = (item: T | null, ref: RefCallback<Gtk.Widget>) => ReactElement;
|
|
16
|
+
export interface ListViewRenderProps<T = unknown> {
|
|
17
|
+
renderItem: RenderItemFn<T>;
|
|
18
|
+
}
|
|
19
|
+
export type RenderCellFn<T> = (item: T | null, ref: RefCallback<Gtk.Widget>) => ReactElement;
|
|
20
|
+
export interface ColumnViewColumnProps {
|
|
21
|
+
title?: string;
|
|
22
|
+
expand?: boolean;
|
|
23
|
+
resizable?: boolean;
|
|
24
|
+
fixedWidth?: number;
|
|
25
|
+
renderCell: (item: any, ref: RefCallback<Gtk.Widget>) => ReactElement;
|
|
26
|
+
}
|
|
27
|
+
export interface NotebookPageProps extends SlotProps {
|
|
28
|
+
label: string;
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
4
4
|
"description": "Build GTK4 desktop applications with React and TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtk",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"react-reconciler": "0.33.0",
|
|
39
|
-
"@gtkx/ffi": "0.1.
|
|
39
|
+
"@gtkx/ffi": "0.1.36"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@gtkx/gir": "0.1.
|
|
42
|
+
"@gtkx/gir": "0.1.36"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"react": "^19"
|