@gtkx/react 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -27
- package/dist/errors.js +3 -0
- package/dist/factory.d.ts +3 -2
- package/dist/factory.js +1 -1
- package/dist/generated/internal.d.ts +28 -1
- package/dist/generated/internal.js +93 -18
- package/dist/generated/jsx.d.ts +1712 -1516
- package/dist/generated/jsx.js +475 -0
- package/dist/host-config.d.ts +3 -1
- package/dist/host-config.js +31 -11
- package/dist/jsx.d.ts +147 -97
- package/dist/jsx.js +89 -21
- package/dist/node.d.ts +3 -1
- package/dist/node.js +5 -3
- package/dist/nodes/abstract/positional-child.d.ts +9 -0
- package/dist/nodes/abstract/positional-child.js +29 -0
- package/dist/nodes/abstract/positional-parent.d.ts +18 -0
- package/dist/nodes/abstract/positional-parent.js +48 -0
- package/dist/nodes/abstract/virtual-container.d.ts +17 -0
- package/dist/nodes/abstract/virtual-container.js +59 -0
- package/dist/nodes/abstract/virtual-single-child.d.ts +18 -0
- package/dist/nodes/abstract/virtual-single-child.js +54 -0
- package/dist/nodes/action-row-child.d.ts +0 -13
- package/dist/nodes/action-row-child.js +14 -12
- package/dist/nodes/action-row.d.ts +6 -1
- package/dist/nodes/action-row.js +4 -37
- package/dist/nodes/adjustable.d.ts +23 -0
- package/dist/nodes/adjustable.js +62 -0
- package/dist/nodes/alert-dialog-response.d.ts +1 -0
- package/dist/nodes/alert-dialog-response.js +86 -0
- package/dist/nodes/animation/animation-controller.d.ts +17 -0
- package/dist/nodes/animation/animation-controller.js +107 -0
- package/dist/nodes/animation/animation-factory.d.ts +15 -0
- package/dist/nodes/animation/animation-factory.js +25 -0
- package/dist/nodes/animation/animation-node.d.ts +9 -0
- package/dist/nodes/animation/animation-node.js +126 -0
- package/dist/nodes/animation/animation-style-sheet.d.ts +16 -0
- package/dist/nodes/animation/animation-style-sheet.js +74 -0
- package/dist/nodes/animation/index.d.ts +4 -0
- package/dist/nodes/animation/index.js +1 -0
- package/dist/nodes/animation/property-mapper.d.ts +11 -0
- package/dist/nodes/animation/property-mapper.js +36 -0
- package/dist/nodes/animation/transform-state.d.ts +11 -0
- package/dist/nodes/animation/transform-state.js +57 -0
- package/dist/nodes/animation/widget-registry.d.ts +5 -0
- package/dist/nodes/animation/widget-registry.js +42 -0
- package/dist/nodes/application.js +17 -7
- package/dist/nodes/autowrapped.js +37 -43
- package/dist/nodes/calendar.js +16 -55
- package/dist/nodes/color-dialog-button.d.ts +1 -0
- package/dist/nodes/color-dialog-button.js +70 -0
- package/dist/nodes/column-view-column.d.ts +4 -3
- package/dist/nodes/column-view-column.js +5 -1
- package/dist/nodes/column-view.js +40 -43
- package/dist/nodes/dialog.d.ts +11 -0
- package/dist/nodes/dialog.js +20 -0
- package/dist/nodes/drawing-area.d.ts +1 -0
- package/dist/nodes/drawing-area.js +36 -0
- package/dist/nodes/event-controller.d.ts +1 -0
- package/dist/nodes/event-controller.js +96 -0
- package/dist/nodes/expander-row-child.d.ts +0 -14
- package/dist/nodes/expander-row-child.js +14 -12
- package/dist/nodes/expander-row.d.ts +6 -1
- package/dist/nodes/expander-row.js +11 -47
- package/dist/nodes/fixed-child.js +48 -36
- package/dist/nodes/font-dialog-button.d.ts +1 -0
- package/dist/nodes/font-dialog-button.js +90 -0
- package/dist/nodes/grid-child.js +39 -45
- package/dist/nodes/grid.d.ts +1 -0
- package/dist/nodes/grid.js +41 -0
- package/dist/nodes/index.d.ts +22 -6
- package/dist/nodes/index.js +22 -6
- package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
- package/dist/nodes/internal/base-item-renderer.js +88 -0
- package/dist/nodes/internal/base-store.d.ts +9 -0
- package/dist/nodes/internal/base-store.js +20 -0
- package/dist/nodes/internal/child-attachment.d.ts +26 -0
- package/dist/nodes/internal/child-attachment.js +48 -0
- package/dist/nodes/internal/deferred-action.d.ts +8 -0
- package/dist/nodes/internal/deferred-action.js +19 -0
- package/dist/nodes/internal/list-item-renderer.d.ts +14 -14
- package/dist/nodes/internal/list-item-renderer.js +49 -70
- package/dist/nodes/internal/list-store.d.ts +7 -6
- package/dist/nodes/internal/list-store.js +20 -24
- package/dist/nodes/internal/predicates.d.ts +28 -1
- package/dist/nodes/internal/predicates.js +53 -38
- package/dist/nodes/internal/selection-model.d.ts +30 -0
- package/dist/nodes/internal/selection-model.js +91 -0
- package/dist/nodes/internal/signal-store.d.ts +5 -3
- package/dist/nodes/internal/signal-store.js +30 -21
- package/dist/nodes/internal/simple-list-store.js +6 -9
- package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
- package/dist/nodes/internal/text-buffer-controller.js +287 -0
- package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
- package/dist/nodes/internal/text-tag-styles.js +52 -0
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +16 -14
- package/dist/nodes/internal/tree-list-item-renderer.js +88 -91
- package/dist/nodes/internal/tree-store.d.ts +10 -9
- package/dist/nodes/internal/tree-store.js +31 -35
- package/dist/nodes/internal/utils.d.ts +7 -4
- package/dist/nodes/internal/utils.js +50 -5
- package/dist/nodes/level-bar.js +18 -66
- package/dist/nodes/list-item.d.ts +6 -3
- package/dist/nodes/list-item.js +7 -4
- package/dist/nodes/list-view.js +19 -11
- package/dist/nodes/menu.d.ts +3 -3
- package/dist/nodes/menu.js +3 -3
- package/dist/nodes/models/list.d.ts +11 -13
- package/dist/nodes/models/list.js +16 -73
- package/dist/nodes/models/menu.d.ts +8 -7
- package/dist/nodes/models/menu.js +43 -50
- package/dist/nodes/models/tree-list.d.ts +6 -12
- package/dist/nodes/models/tree-list.js +30 -93
- package/dist/nodes/navigation-page.d.ts +1 -0
- package/dist/nodes/navigation-page.js +7 -3
- package/dist/nodes/navigation-view.js +17 -28
- package/dist/nodes/notebook-page-tab.d.ts +4 -3
- package/dist/nodes/notebook-page-tab.js +5 -2
- package/dist/nodes/notebook-page.d.ts +7 -5
- package/dist/nodes/notebook-page.js +39 -16
- package/dist/nodes/notebook.js +2 -2
- package/dist/nodes/overlay-child.js +90 -30
- package/dist/nodes/pack-child.d.ts +0 -13
- package/dist/nodes/pack-child.js +14 -12
- package/dist/nodes/pack.d.ts +6 -1
- package/dist/nodes/pack.js +4 -37
- package/dist/nodes/popover-menu.js +2 -2
- package/dist/nodes/scale.js +15 -58
- package/dist/nodes/scrolled-window.js +7 -5
- package/dist/nodes/search-bar.d.ts +1 -0
- package/dist/nodes/search-bar.js +40 -0
- package/dist/nodes/shortcut-controller.d.ts +1 -0
- package/dist/nodes/shortcut-controller.js +90 -0
- package/dist/nodes/shortcut.d.ts +39 -0
- package/dist/nodes/shortcut.js +52 -0
- package/dist/nodes/simple-list-view.js +2 -3
- package/dist/nodes/slot.d.ts +6 -9
- package/dist/nodes/slot.js +27 -42
- package/dist/nodes/source-view.d.ts +1 -0
- package/dist/nodes/source-view.js +93 -0
- package/dist/nodes/stack-page.js +17 -13
- package/dist/nodes/stack.js +19 -5
- package/dist/nodes/text-anchor.d.ts +41 -0
- package/dist/nodes/text-anchor.js +59 -0
- package/dist/nodes/text-content.d.ts +10 -0
- package/dist/nodes/text-content.js +1 -0
- package/dist/nodes/text-paintable.d.ts +17 -0
- package/dist/nodes/text-paintable.js +34 -0
- package/dist/nodes/text-segment.d.ts +15 -0
- package/dist/nodes/text-segment.js +29 -0
- package/dist/nodes/text-tag.d.ts +136 -0
- package/dist/nodes/text-tag.js +202 -0
- package/dist/nodes/text-view.d.ts +31 -0
- package/dist/nodes/text-view.js +73 -0
- package/dist/nodes/toggle-group.js +24 -32
- package/dist/nodes/toggle.d.ts +1 -15
- package/dist/nodes/toggle.js +40 -32
- package/dist/nodes/toolbar-child.js +14 -16
- package/dist/nodes/tree-list-item.d.ts +7 -5
- package/dist/nodes/tree-list-item.js +24 -36
- package/dist/nodes/tree-list-view.js +9 -4
- package/dist/nodes/virtual.d.ts +1 -1
- package/dist/nodes/widget.d.ts +3 -13
- package/dist/nodes/widget.js +117 -231
- package/dist/nodes/window.d.ts +9 -3
- package/dist/nodes/window.js +35 -19
- package/dist/registry.d.ts +1 -1
- package/dist/render.js +8 -6
- package/dist/scheduler.d.ts +11 -1
- package/dist/scheduler.js +16 -4
- package/dist/types.d.ts +2 -110
- package/package.json +3 -3
- package/dist/nodes/calendar-mark.d.ts +0 -15
- package/dist/nodes/calendar-mark.js +0 -29
- package/dist/nodes/internal/constants.d.ts +0 -1
- package/dist/nodes/internal/constants.js +0 -21
- package/dist/nodes/level-bar-offset.d.ts +0 -13
- package/dist/nodes/level-bar-offset.js +0 -35
- package/dist/nodes/scale-mark.d.ts +0 -17
- package/dist/nodes/scale-mark.js +0 -38
- package/dist/nodes/virtual-child.d.ts +0 -18
- package/dist/nodes/virtual-child.js +0 -62
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
-
|
|
2
|
+
import { BaseStore } from "./base-store.js";
|
|
3
|
+
export type TreeItemUpdatedCallback = (id: string) => void;
|
|
4
|
+
export type TreeItemData<T = unknown> = {
|
|
3
5
|
value: T;
|
|
4
6
|
indentForDepth?: boolean;
|
|
5
7
|
indentForIcon?: boolean;
|
|
6
8
|
hideExpander?: boolean;
|
|
7
|
-
}
|
|
8
|
-
export declare class TreeStore {
|
|
9
|
-
private items;
|
|
9
|
+
};
|
|
10
|
+
export declare class TreeStore extends BaseStore<TreeItemData> {
|
|
10
11
|
private rootIds;
|
|
11
12
|
private newRootIds;
|
|
12
13
|
private children;
|
|
13
14
|
private newChildren;
|
|
14
15
|
private rootModel;
|
|
15
16
|
private childModels;
|
|
16
|
-
private
|
|
17
|
+
private onItemUpdated;
|
|
17
18
|
constructor();
|
|
19
|
+
setOnItemUpdated(callback: TreeItemUpdatedCallback | null): void;
|
|
20
|
+
updateItem(id: string, item: TreeItemData): void;
|
|
18
21
|
addItem(id: string, data: TreeItemData, parentId?: string): void;
|
|
19
22
|
removeItem(id: string, parentId?: string): void;
|
|
20
23
|
insertItemBefore(id: string, beforeId: string, data: TreeItemData, parentId?: string): void;
|
|
21
|
-
|
|
22
|
-
getItem(id: string): TreeItemData | null;
|
|
24
|
+
getItem(id: string): TreeItemData | undefined;
|
|
23
25
|
getRootModel(): Gtk.StringList;
|
|
24
26
|
getChildrenModel(parentId: string): Gtk.StringList | null;
|
|
25
27
|
hasChildren(parentId: string): boolean;
|
|
26
|
-
|
|
27
|
-
private sync;
|
|
28
|
+
protected sync(): void;
|
|
28
29
|
}
|
|
@@ -1,18 +1,29 @@
|
|
|
1
|
-
import { batch } from "@gtkx/ffi";
|
|
2
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
-
import {
|
|
4
|
-
export class TreeStore {
|
|
5
|
-
items = new Map();
|
|
2
|
+
import { BaseStore } from "./base-store.js";
|
|
3
|
+
export class TreeStore extends BaseStore {
|
|
6
4
|
rootIds = [];
|
|
7
5
|
newRootIds = [];
|
|
8
6
|
children = new Map();
|
|
9
7
|
newChildren = new Map();
|
|
10
8
|
rootModel;
|
|
11
9
|
childModels = new Map();
|
|
12
|
-
|
|
10
|
+
onItemUpdated = null;
|
|
13
11
|
constructor() {
|
|
12
|
+
super();
|
|
14
13
|
this.rootModel = new Gtk.StringList();
|
|
15
14
|
}
|
|
15
|
+
setOnItemUpdated(callback) {
|
|
16
|
+
this.onItemUpdated = callback;
|
|
17
|
+
}
|
|
18
|
+
updateItem(id, item) {
|
|
19
|
+
if (this.items.has(id)) {
|
|
20
|
+
this.items.set(id, item);
|
|
21
|
+
this.onItemUpdated?.(id);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.addItem(id, item);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
16
27
|
addItem(id, data, parentId) {
|
|
17
28
|
this.items.set(id, data);
|
|
18
29
|
if (parentId === undefined) {
|
|
@@ -94,13 +105,8 @@ export class TreeStore {
|
|
|
94
105
|
}
|
|
95
106
|
this.scheduleSync();
|
|
96
107
|
}
|
|
97
|
-
updateItem(id, data) {
|
|
98
|
-
if (this.items.has(id)) {
|
|
99
|
-
this.items.set(id, data);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
108
|
getItem(id) {
|
|
103
|
-
return this.items.get(id)
|
|
109
|
+
return this.items.get(id);
|
|
104
110
|
}
|
|
105
111
|
getRootModel() {
|
|
106
112
|
return this.rootModel;
|
|
@@ -121,32 +127,22 @@ export class TreeStore {
|
|
|
121
127
|
const childIds = this.children.get(parentId);
|
|
122
128
|
return childIds !== undefined && childIds.length > 0;
|
|
123
129
|
}
|
|
124
|
-
scheduleSync() {
|
|
125
|
-
if (this.shouldSync) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
this.shouldSync = true;
|
|
129
|
-
scheduleAfterCommit(() => this.sync(), CommitPriority.LOW);
|
|
130
|
-
}
|
|
131
130
|
sync() {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
const oldLength = model.getNItems();
|
|
141
|
-
model.splice(0, oldLength, newChildIds.length > 0 ? newChildIds : undefined);
|
|
142
|
-
}
|
|
131
|
+
const oldRootLength = this.rootIds.length;
|
|
132
|
+
this.rootModel.splice(0, oldRootLength, this.newRootIds.length > 0 ? this.newRootIds : undefined);
|
|
133
|
+
this.rootIds = [...this.newRootIds];
|
|
134
|
+
for (const [parentId, newChildIds] of this.newChildren) {
|
|
135
|
+
const model = this.childModels.get(parentId);
|
|
136
|
+
if (model) {
|
|
137
|
+
const oldLength = model.getNItems();
|
|
138
|
+
model.splice(0, oldLength, newChildIds.length > 0 ? newChildIds : undefined);
|
|
143
139
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
}
|
|
141
|
+
for (const [parentId] of this.children) {
|
|
142
|
+
if (!this.newChildren.has(parentId)) {
|
|
143
|
+
this.childModels.delete(parentId);
|
|
148
144
|
}
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
}
|
|
146
|
+
this.children = new Map(this.newChildren);
|
|
151
147
|
}
|
|
152
148
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { Container, ContainerClass, Props } from "../../types.js";
|
|
2
2
|
type AnyClass = new (...args: any[]) => any;
|
|
3
3
|
export declare const matchesAnyClass: (classes: readonly AnyClass[], containerOrClass?: Container | ContainerClass | null) => boolean;
|
|
4
|
-
export declare const isContainerType: (cls: AnyClass, containerOrClass?: Container | ContainerClass | null) => boolean;
|
|
5
4
|
export declare const matchesInterface: (methods: readonly string[], containerOrClass?: Container | ContainerClass | null) => boolean;
|
|
6
|
-
export declare const filterProps: (props: Props, excludeKeys: string[]) => Props;
|
|
7
|
-
export declare const resolvePropMeta: (
|
|
8
|
-
export declare const resolveSignal: (
|
|
5
|
+
export declare const filterProps: (props: Props, excludeKeys: readonly string[]) => Props;
|
|
6
|
+
export declare const resolvePropMeta: (instance: Container, key: string) => [string | null, string] | null;
|
|
7
|
+
export declare const resolveSignal: (instance: Container, signalName: string) => boolean;
|
|
8
|
+
export declare const propNameToSignalName: (propName: string) => string;
|
|
9
|
+
export declare const hasChanged: <T>(oldProps: T | null, newProps: T, key: keyof T) => boolean;
|
|
10
|
+
export declare const shallowArrayEqual: <T extends Record<string, unknown>>(a: T[], b: T[]) => boolean;
|
|
11
|
+
export declare const primitiveArrayEqual: <T extends string | number | boolean>(a: T[] | null | undefined, b: T[] | null | undefined) => boolean;
|
|
9
12
|
export {};
|
|
@@ -7,7 +7,6 @@ export const matchesAnyClass = (classes, containerOrClass) => {
|
|
|
7
7
|
containerOrClass === cls ||
|
|
8
8
|
Object.prototype.isPrototypeOf.call(cls, containerOrClass));
|
|
9
9
|
};
|
|
10
|
-
export const isContainerType = (cls, containerOrClass) => matchesAnyClass([cls], containerOrClass);
|
|
11
10
|
export const matchesInterface = (methods, containerOrClass) => {
|
|
12
11
|
if (!containerOrClass) {
|
|
13
12
|
return false;
|
|
@@ -24,9 +23,9 @@ export const filterProps = (props, excludeKeys) => {
|
|
|
24
23
|
}
|
|
25
24
|
return result;
|
|
26
25
|
};
|
|
27
|
-
const walkPrototypeChain = (
|
|
26
|
+
const walkPrototypeChain = (instance, lookup) => {
|
|
28
27
|
// biome-ignore lint/complexity/noBannedTypes: Walking prototype chain requires Function type
|
|
29
|
-
let current =
|
|
28
|
+
let current = instance.constructor;
|
|
30
29
|
while (current) {
|
|
31
30
|
const typeName = current.glibTypeName;
|
|
32
31
|
if (typeName) {
|
|
@@ -43,5 +42,51 @@ const walkPrototypeChain = (container, lookup) => {
|
|
|
43
42
|
}
|
|
44
43
|
return null;
|
|
45
44
|
};
|
|
46
|
-
export const resolvePropMeta = (
|
|
47
|
-
export const resolveSignal = (
|
|
45
|
+
export const resolvePropMeta = (instance, key) => walkPrototypeChain(instance, (typeName) => PROPS[typeName]?.[key] ?? null);
|
|
46
|
+
export const resolveSignal = (instance, signalName) => {
|
|
47
|
+
if (signalName === "notify")
|
|
48
|
+
return true;
|
|
49
|
+
return walkPrototypeChain(instance, (typeName) => (SIGNALS[typeName]?.has(signalName) ? true : null)) ?? false;
|
|
50
|
+
};
|
|
51
|
+
export const propNameToSignalName = (propName) => {
|
|
52
|
+
if (!propName.startsWith("on"))
|
|
53
|
+
return propName;
|
|
54
|
+
return propName
|
|
55
|
+
.slice(2)
|
|
56
|
+
.replace(/([A-Z])/g, "-$1")
|
|
57
|
+
.toLowerCase()
|
|
58
|
+
.replace(/^-/, "");
|
|
59
|
+
};
|
|
60
|
+
export const hasChanged = (oldProps, newProps, key) => !oldProps || oldProps[key] !== newProps[key];
|
|
61
|
+
export const shallowArrayEqual = (a, b) => {
|
|
62
|
+
if (a.length !== b.length)
|
|
63
|
+
return false;
|
|
64
|
+
for (let i = 0; i < a.length; i++) {
|
|
65
|
+
const itemA = a[i];
|
|
66
|
+
const itemB = b[i];
|
|
67
|
+
if (!itemA || !itemB)
|
|
68
|
+
return false;
|
|
69
|
+
const keysA = Object.keys(itemA);
|
|
70
|
+
const keysB = Object.keys(itemB);
|
|
71
|
+
if (keysA.length !== keysB.length)
|
|
72
|
+
return false;
|
|
73
|
+
for (const key of keysA) {
|
|
74
|
+
if (itemA[key] !== itemB[key])
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
80
|
+
export const primitiveArrayEqual = (a, b) => {
|
|
81
|
+
if (a === b)
|
|
82
|
+
return true;
|
|
83
|
+
if (!a || !b)
|
|
84
|
+
return false;
|
|
85
|
+
if (a.length !== b.length)
|
|
86
|
+
return false;
|
|
87
|
+
for (let i = 0; i < a.length; i++) {
|
|
88
|
+
if (a[i] !== b[i])
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
};
|
package/dist/nodes/level-bar.js
CHANGED
|
@@ -1,82 +1,34 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import { registerNodeClass } from "../registry.js";
|
|
3
|
-
import {
|
|
4
|
-
import { isContainerType } from "./internal/utils.js";
|
|
5
|
-
import { LevelBarOffsetNode } from "./level-bar-offset.js";
|
|
6
|
-
import { SlotNode } from "./slot.js";
|
|
3
|
+
import { filterProps, matchesAnyClass, shallowArrayEqual } from "./internal/utils.js";
|
|
7
4
|
import { WidgetNode } from "./widget.js";
|
|
5
|
+
const OWN_PROPS = ["offsets"];
|
|
8
6
|
class LevelBarNode extends WidgetNode {
|
|
9
7
|
static priority = 1;
|
|
10
|
-
offsetChildren = [];
|
|
11
8
|
appliedOffsetIds = new Set();
|
|
12
9
|
static matches(_type, containerOrClass) {
|
|
13
|
-
return
|
|
10
|
+
return matchesAnyClass([Gtk.LevelBar], containerOrClass);
|
|
14
11
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.offsetChildren.push(child);
|
|
19
|
-
scheduleAfterCommit(() => {
|
|
20
|
-
const id = child.addOffset();
|
|
21
|
-
if (id) {
|
|
22
|
-
this.appliedOffsetIds.add(id);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (child instanceof SlotNode || child instanceof WidgetNode) {
|
|
28
|
-
super.appendChild(child);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
throw new Error(`Cannot append '${child.typeName}' to 'LevelBar': expected x.LevelBarOffset or Widget`);
|
|
12
|
+
updateProps(oldProps, newProps) {
|
|
13
|
+
super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
|
|
14
|
+
this.applyOwnProps(oldProps, newProps);
|
|
32
15
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
child.setLevelBar(this.container, () => this.scheduleRebuildAllOffsets());
|
|
36
|
-
const beforeIndex = this.offsetChildren.indexOf(before);
|
|
37
|
-
if (beforeIndex >= 0) {
|
|
38
|
-
this.offsetChildren.splice(beforeIndex, 0, child);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
this.offsetChildren.push(child);
|
|
42
|
-
}
|
|
43
|
-
this.scheduleRebuildAllOffsets();
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (child instanceof SlotNode || child instanceof WidgetNode) {
|
|
47
|
-
super.insertBefore(child, before);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
throw new Error(`Cannot insert '${child.typeName}' into 'LevelBar': expected x.LevelBarOffset or Widget`);
|
|
16
|
+
applyOwnProps(oldProps, newProps) {
|
|
17
|
+
this.applyOffsets(oldProps, newProps);
|
|
51
18
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (index >= 0) {
|
|
56
|
-
this.offsetChildren.splice(index, 1);
|
|
57
|
-
}
|
|
58
|
-
this.scheduleRebuildAllOffsets(CommitPriority.HIGH);
|
|
19
|
+
applyOffsets(oldProps, newProps) {
|
|
20
|
+
const newOffsets = newProps.offsets ?? [];
|
|
21
|
+
if (shallowArrayEqual(oldProps?.offsets ?? [], newOffsets)) {
|
|
59
22
|
return;
|
|
60
23
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
24
|
+
for (const id of this.appliedOffsetIds) {
|
|
25
|
+
this.container.removeOffsetValue(id);
|
|
26
|
+
}
|
|
27
|
+
this.appliedOffsetIds.clear();
|
|
28
|
+
for (const offset of newOffsets) {
|
|
29
|
+
this.container.addOffsetValue(offset.id, offset.value);
|
|
30
|
+
this.appliedOffsetIds.add(offset.id);
|
|
64
31
|
}
|
|
65
|
-
throw new Error(`Cannot remove '${child.typeName}' from 'LevelBar': expected x.LevelBarOffset or Widget`);
|
|
66
|
-
}
|
|
67
|
-
scheduleRebuildAllOffsets(priority = CommitPriority.NORMAL) {
|
|
68
|
-
scheduleAfterCommit(() => {
|
|
69
|
-
for (const id of this.appliedOffsetIds) {
|
|
70
|
-
this.container.removeOffsetValue(id);
|
|
71
|
-
}
|
|
72
|
-
this.appliedOffsetIds.clear();
|
|
73
|
-
for (const offset of this.offsetChildren) {
|
|
74
|
-
const id = offset.addOffset();
|
|
75
|
-
if (id) {
|
|
76
|
-
this.appliedOffsetIds.add(id);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}, priority);
|
|
80
32
|
}
|
|
81
33
|
}
|
|
82
34
|
registerNodeClass(LevelBarNode);
|
|
@@ -2,11 +2,14 @@ import type { ListItemProps } from "../jsx.js";
|
|
|
2
2
|
import type { ListStore } from "./internal/list-store.js";
|
|
3
3
|
import { VirtualNode } from "./virtual.js";
|
|
4
4
|
type Props = Partial<ListItemProps>;
|
|
5
|
-
export declare class ListItemNode<T extends
|
|
5
|
+
export declare class ListItemNode<T extends {
|
|
6
|
+
updateItem(id: string, value: unknown): void;
|
|
7
|
+
} = ListStore, P extends Props = Props> extends VirtualNode<P> {
|
|
6
8
|
static priority: number;
|
|
7
|
-
private store
|
|
9
|
+
private store;
|
|
8
10
|
static matches(type: string): boolean;
|
|
9
|
-
setStore(store
|
|
11
|
+
setStore(store: T | null): void;
|
|
10
12
|
updateProps(oldProps: P | null, newProps: P): void;
|
|
13
|
+
protected applyOwnProps(oldProps: P | null, newProps: P): void;
|
|
11
14
|
}
|
|
12
15
|
export {};
|
package/dist/nodes/list-item.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { registerNodeClass } from "../registry.js";
|
|
2
|
+
import { hasChanged } from "./internal/utils.js";
|
|
2
3
|
import { VirtualNode } from "./virtual.js";
|
|
3
4
|
export class ListItemNode extends VirtualNode {
|
|
4
5
|
static priority = 1;
|
|
5
|
-
store;
|
|
6
|
+
store = null;
|
|
6
7
|
static matches(type) {
|
|
7
8
|
return type === "ListItem";
|
|
8
9
|
}
|
|
@@ -11,10 +12,12 @@ export class ListItemNode extends VirtualNode {
|
|
|
11
12
|
}
|
|
12
13
|
updateProps(oldProps, newProps) {
|
|
13
14
|
super.updateProps(oldProps, newProps);
|
|
14
|
-
|
|
15
|
+
this.applyOwnProps(oldProps, newProps);
|
|
16
|
+
}
|
|
17
|
+
applyOwnProps(oldProps, newProps) {
|
|
18
|
+
if (!this.store)
|
|
15
19
|
return;
|
|
16
|
-
|
|
17
|
-
if (!oldProps || oldProps.id !== newProps.id || oldProps.value !== newProps.value) {
|
|
20
|
+
if (hasChanged(oldProps, newProps, "id") || hasChanged(oldProps, newProps, "value")) {
|
|
18
21
|
if (newProps.id !== undefined) {
|
|
19
22
|
this.store.updateItem(newProps.id, newProps.value);
|
|
20
23
|
}
|
package/dist/nodes/list-view.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { LIST_WIDGET_CLASSES } from "../generated/internal.js";
|
|
2
2
|
import { registerNodeClass } from "../registry.js";
|
|
3
3
|
import { ListItemRenderer } from "./internal/list-item-renderer.js";
|
|
4
|
-
import { filterProps, matchesAnyClass } from "./internal/utils.js";
|
|
4
|
+
import { filterProps, hasChanged, matchesAnyClass } from "./internal/utils.js";
|
|
5
5
|
import { ListItemNode } from "./list-item.js";
|
|
6
|
-
import {
|
|
6
|
+
import { ListModel } from "./models/list.js";
|
|
7
7
|
import { WidgetNode } from "./widget.js";
|
|
8
|
-
const
|
|
8
|
+
const OWN_PROPS = ["renderItem", "estimatedItemHeight"];
|
|
9
9
|
class ListViewNode extends WidgetNode {
|
|
10
10
|
static priority = 1;
|
|
11
11
|
itemRenderer;
|
|
@@ -15,19 +15,24 @@ class ListViewNode extends WidgetNode {
|
|
|
15
15
|
}
|
|
16
16
|
constructor(typeName, props, container, rootContainer) {
|
|
17
17
|
super(typeName, props, container, rootContainer);
|
|
18
|
-
this.list = new
|
|
18
|
+
this.list = new ListModel({ owner: this, signalStore: this.signalStore }, {
|
|
19
19
|
selectionMode: props.selectionMode,
|
|
20
20
|
selected: props.selected,
|
|
21
21
|
onSelectionChanged: props.onSelectionChanged,
|
|
22
22
|
});
|
|
23
|
-
this.itemRenderer = new ListItemRenderer();
|
|
23
|
+
this.itemRenderer = new ListItemRenderer(this.signalStore);
|
|
24
24
|
this.itemRenderer.setStore(this.list.getStore());
|
|
25
|
+
this.list.getStore().setOnItemUpdated((id) => this.itemRenderer.rebindItem(id));
|
|
25
26
|
this.container.setFactory(this.itemRenderer.getFactory());
|
|
26
27
|
}
|
|
27
28
|
mount() {
|
|
28
29
|
super.mount();
|
|
29
30
|
this.container.setModel(this.list.getSelectionModel());
|
|
30
31
|
}
|
|
32
|
+
unmount() {
|
|
33
|
+
this.itemRenderer.dispose();
|
|
34
|
+
super.unmount();
|
|
35
|
+
}
|
|
31
36
|
appendChild(child) {
|
|
32
37
|
if (!(child instanceof ListItemNode)) {
|
|
33
38
|
throw new Error(`Cannot append '${child.typeName}' to 'ListView': expected x.ListItem`);
|
|
@@ -47,19 +52,22 @@ class ListViewNode extends WidgetNode {
|
|
|
47
52
|
this.list.removeChild(child);
|
|
48
53
|
}
|
|
49
54
|
updateProps(oldProps, newProps) {
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
|
|
56
|
+
this.applyOwnProps(oldProps, newProps);
|
|
57
|
+
}
|
|
58
|
+
applyOwnProps(oldProps, newProps) {
|
|
59
|
+
if (hasChanged(oldProps, newProps, "renderItem")) {
|
|
60
|
+
this.itemRenderer.setRenderFn(newProps.renderItem ?? null);
|
|
52
61
|
}
|
|
53
|
-
if (
|
|
54
|
-
this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight);
|
|
62
|
+
if (hasChanged(oldProps, newProps, "estimatedItemHeight")) {
|
|
63
|
+
this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight ?? null);
|
|
55
64
|
}
|
|
56
65
|
const previousModel = this.list.getSelectionModel();
|
|
57
|
-
this.list.updateProps(oldProps
|
|
66
|
+
this.list.updateProps(oldProps, newProps);
|
|
58
67
|
const currentModel = this.list.getSelectionModel();
|
|
59
68
|
if (previousModel !== currentModel) {
|
|
60
69
|
this.container.setModel(currentModel);
|
|
61
70
|
}
|
|
62
|
-
super.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
73
|
registerNodeClass(ListViewNode);
|
package/dist/nodes/menu.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Container } from "../types.js";
|
|
2
|
-
import {
|
|
3
|
-
export declare class MenuNode extends
|
|
2
|
+
import { MenuModel, type MenuProps } from "./models/menu.js";
|
|
3
|
+
export declare class MenuNode extends MenuModel {
|
|
4
4
|
static priority: number;
|
|
5
5
|
static matches(type: string): boolean;
|
|
6
6
|
private static getType;
|
|
7
|
-
constructor(typeName: string, props: MenuProps, _container: undefined, rootContainer
|
|
7
|
+
constructor(typeName: string, props: MenuProps, _container: undefined, rootContainer: Container);
|
|
8
8
|
}
|
package/dist/nodes/menu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import { registerNodeClass } from "../registry.js";
|
|
3
|
-
import {
|
|
4
|
-
export class MenuNode extends
|
|
3
|
+
import { MenuModel } from "./models/menu.js";
|
|
4
|
+
export class MenuNode extends MenuModel {
|
|
5
5
|
static priority = 1;
|
|
6
6
|
static matches(type) {
|
|
7
7
|
return type === "MenuItem" || type === "MenuSection" || type === "MenuSubmenu";
|
|
@@ -19,7 +19,7 @@ export class MenuNode extends Menu {
|
|
|
19
19
|
throw new Error(`Unable to find menu type '${typeName}'`);
|
|
20
20
|
}
|
|
21
21
|
constructor(typeName, props, _container, rootContainer) {
|
|
22
|
-
super(MenuNode.getType(typeName), props, undefined, rootContainer instanceof Gtk.Application ? rootContainer : undefined);
|
|
22
|
+
super(MenuNode.getType(typeName), props, rootContainer, undefined, rootContainer instanceof Gtk.Application ? rootContainer : undefined);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
registerNodeClass(MenuNode);
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { Node } from "../../node.js";
|
|
3
3
|
import { ListStore } from "../internal/list-store.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { SignalStore } from "../internal/signal-store.js";
|
|
5
5
|
export type ListProps = {
|
|
6
6
|
selectionMode?: Gtk.SelectionMode;
|
|
7
7
|
selected?: string[];
|
|
8
8
|
onSelectionChanged?: (ids: string[]) => void;
|
|
9
9
|
};
|
|
10
|
-
type
|
|
11
|
-
|
|
10
|
+
type ListModelConfig = {
|
|
11
|
+
owner: object;
|
|
12
|
+
signalStore: SignalStore;
|
|
13
|
+
};
|
|
14
|
+
export declare class ListModel {
|
|
15
|
+
private config;
|
|
12
16
|
private store;
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
private pendingSelection?;
|
|
16
|
-
private selectionScheduled;
|
|
17
|
-
constructor(props?: ListProps);
|
|
18
|
-
private initSelectionHandler;
|
|
17
|
+
private selectionManager;
|
|
18
|
+
constructor(config: ListModelConfig, props?: ListProps);
|
|
19
19
|
getStore(): ListStore;
|
|
20
|
-
getSelectionModel():
|
|
20
|
+
getSelectionModel(): Gtk.NoSelection | Gtk.SingleSelection | Gtk.MultiSelection;
|
|
21
21
|
appendChild(child: Node): void;
|
|
22
22
|
insertBefore(child: Node, before: Node): void;
|
|
23
23
|
removeChild(child: Node): void;
|
|
24
24
|
updateProps(oldProps: ListProps | null, newProps: ListProps): void;
|
|
25
|
-
private createSelectionModel;
|
|
26
25
|
private getSelection;
|
|
27
|
-
private
|
|
28
|
-
private applySelection;
|
|
26
|
+
private resolveSelectionIndices;
|
|
29
27
|
}
|
|
30
28
|
export {};
|
|
@@ -1,37 +1,21 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
-
import { CommitPriority, scheduleAfterCommit } from "../../scheduler.js";
|
|
3
2
|
import { ListStore } from "../internal/list-store.js";
|
|
4
|
-
import {
|
|
3
|
+
import { SelectionModelManager } from "../internal/selection-model.js";
|
|
5
4
|
import { ListItemNode } from "../list-item.js";
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export class ListModel {
|
|
6
|
+
config;
|
|
8
7
|
store;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
selectionScheduled = false;
|
|
13
|
-
constructor(props = {}) {
|
|
14
|
-
super("", {}, undefined);
|
|
8
|
+
selectionManager;
|
|
9
|
+
constructor(config, props = {}) {
|
|
10
|
+
this.config = config;
|
|
15
11
|
this.store = new ListStore();
|
|
16
|
-
this.
|
|
17
|
-
this.selectionModel.setModel(this.store.getModel());
|
|
18
|
-
this.initSelectionHandler(props.onSelectionChanged);
|
|
19
|
-
}
|
|
20
|
-
initSelectionHandler(onSelectionChanged) {
|
|
21
|
-
if (!onSelectionChanged) {
|
|
22
|
-
signalStore.set(this, this.selectionModel, "selection-changed", null);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
this.handleSelectionChange = () => {
|
|
26
|
-
onSelectionChanged(this.getSelection());
|
|
27
|
-
};
|
|
28
|
-
signalStore.set(this, this.selectionModel, "selection-changed", this.handleSelectionChange);
|
|
12
|
+
this.selectionManager = new SelectionModelManager({ ...config, ...props }, this.store.getModel(), () => this.getSelection(), (ids) => this.resolveSelectionIndices(ids), () => this.store.getModel().getNItems());
|
|
29
13
|
}
|
|
30
14
|
getStore() {
|
|
31
15
|
return this.store;
|
|
32
16
|
}
|
|
33
17
|
getSelectionModel() {
|
|
34
|
-
return this.
|
|
18
|
+
return this.selectionManager.getSelectionModel();
|
|
35
19
|
}
|
|
36
20
|
appendChild(child) {
|
|
37
21
|
if (!(child instanceof ListItemNode)) {
|
|
@@ -55,39 +39,11 @@ export class List extends VirtualNode {
|
|
|
55
39
|
child.setStore(null);
|
|
56
40
|
}
|
|
57
41
|
updateProps(oldProps, newProps) {
|
|
58
|
-
|
|
59
|
-
if (oldProps && oldProps.selectionMode !== newProps.selectionMode) {
|
|
60
|
-
signalStore.set(this, this.selectionModel, "selection-changed", null);
|
|
61
|
-
this.selectionModel = this.createSelectionModel(newProps.selectionMode);
|
|
62
|
-
this.selectionModel.setModel(this.store.getModel());
|
|
63
|
-
this.initSelectionHandler(newProps.onSelectionChanged);
|
|
64
|
-
this.setSelection(newProps.selected);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (!oldProps || oldProps.onSelectionChanged !== newProps.onSelectionChanged) {
|
|
68
|
-
this.initSelectionHandler(newProps.onSelectionChanged);
|
|
69
|
-
}
|
|
70
|
-
if (!oldProps || oldProps.selected !== newProps.selected) {
|
|
71
|
-
this.setSelection(newProps.selected);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
createSelectionModel(mode) {
|
|
75
|
-
const model = this.store.getModel();
|
|
76
|
-
const selectionMode = mode ?? Gtk.SelectionMode.SINGLE;
|
|
77
|
-
if (selectionMode === Gtk.SelectionMode.NONE) {
|
|
78
|
-
return new Gtk.NoSelection(model);
|
|
79
|
-
}
|
|
80
|
-
if (selectionMode === Gtk.SelectionMode.MULTIPLE) {
|
|
81
|
-
return new Gtk.MultiSelection(model);
|
|
82
|
-
}
|
|
83
|
-
const selectionModel = new Gtk.SingleSelection(model);
|
|
84
|
-
selectionModel.setAutoselect(selectionMode === Gtk.SelectionMode.BROWSE);
|
|
85
|
-
selectionModel.setCanUnselect(selectionMode !== Gtk.SelectionMode.BROWSE);
|
|
86
|
-
return selectionModel;
|
|
42
|
+
this.selectionManager.update(oldProps ? { ...this.config, ...oldProps } : null, { ...this.config, ...newProps }, this.store.getModel());
|
|
87
43
|
}
|
|
88
44
|
getSelection() {
|
|
89
45
|
const model = this.store.getModel();
|
|
90
|
-
const selection = this.
|
|
46
|
+
const selection = this.selectionManager.getSelectionModel().getSelection();
|
|
91
47
|
const size = selection.getSize();
|
|
92
48
|
const ids = [];
|
|
93
49
|
for (let i = 0; i < size; i++) {
|
|
@@ -99,29 +55,16 @@ export class List extends VirtualNode {
|
|
|
99
55
|
}
|
|
100
56
|
return ids;
|
|
101
57
|
}
|
|
102
|
-
|
|
103
|
-
this.pendingSelection = ids;
|
|
104
|
-
if (!this.selectionScheduled) {
|
|
105
|
-
this.selectionScheduled = true;
|
|
106
|
-
scheduleAfterCommit(() => this.applySelection(), CommitPriority.LOW);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
applySelection() {
|
|
110
|
-
this.selectionScheduled = false;
|
|
111
|
-
const ids = this.pendingSelection;
|
|
112
|
-
this.pendingSelection = undefined;
|
|
58
|
+
resolveSelectionIndices(ids) {
|
|
113
59
|
const model = this.store.getModel();
|
|
114
60
|
const nItems = model.getNItems();
|
|
115
61
|
const selected = new Gtk.Bitset();
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (index < nItems) {
|
|
121
|
-
selected.add(index);
|
|
122
|
-
}
|
|
62
|
+
for (const id of ids) {
|
|
63
|
+
const index = model.find(id);
|
|
64
|
+
if (index < nItems) {
|
|
65
|
+
selected.add(index);
|
|
123
66
|
}
|
|
124
67
|
}
|
|
125
|
-
|
|
68
|
+
return selected;
|
|
126
69
|
}
|
|
127
70
|
}
|