@gtkx/components 1.0.0-rc.1 → 1.0.0-rc.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/adw/combo-row.d.ts +11 -0
- package/dist/adw/combo-row.d.ts.map +1 -0
- package/dist/adw/combo-row.js +14 -0
- package/dist/adw/combo-row.js.map +1 -0
- package/dist/adw/index.d.ts +4 -0
- package/dist/adw/index.d.ts.map +1 -0
- package/dist/adw/index.js +3 -0
- package/dist/adw/index.js.map +1 -0
- package/dist/adw/toast.d.ts +10 -0
- package/dist/adw/toast.d.ts.map +1 -0
- package/dist/adw/toast.js +51 -0
- package/dist/adw/toast.js.map +1 -0
- package/dist/adw/types.d.ts +35 -0
- package/dist/adw/types.d.ts.map +1 -0
- package/dist/adw/types.js +2 -0
- package/dist/adw/types.js.map +1 -0
- package/dist/column-view.d.ts +7 -29
- package/dist/column-view.d.ts.map +1 -1
- package/dist/column-view.js +98 -70
- package/dist/column-view.js.map +1 -1
- package/dist/drop-down.d.ts +7 -28
- package/dist/drop-down.d.ts.map +1 -1
- package/dist/drop-down.js +10 -86
- package/dist/drop-down.js.map +1 -1
- package/dist/grid-view.d.ts +6 -16
- package/dist/grid-view.d.ts.map +1 -1
- package/dist/grid-view.js +25 -33
- package/dist/grid-view.js.map +1 -1
- package/dist/index.d.ts +6 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -6
- package/dist/index.js.map +1 -1
- package/dist/internal/cells.d.ts +50 -0
- package/dist/internal/cells.d.ts.map +1 -0
- package/dist/internal/cells.js +185 -0
- package/dist/internal/cells.js.map +1 -0
- package/dist/internal/collection-index.d.ts +21 -0
- package/dist/internal/collection-index.d.ts.map +1 -0
- package/dist/internal/collection-index.js +106 -0
- package/dist/internal/collection-index.js.map +1 -0
- package/dist/internal/collection-model.d.ts +12 -0
- package/dist/internal/collection-model.d.ts.map +1 -0
- package/dist/internal/collection-model.js +164 -0
- package/dist/internal/collection-model.js.map +1 -0
- package/dist/internal/collection.d.ts +18 -0
- package/dist/internal/collection.d.ts.map +1 -0
- package/dist/internal/collection.js +64 -0
- package/dist/internal/collection.js.map +1 -0
- package/dist/internal/drop-down.d.ts +16 -0
- package/dist/internal/drop-down.d.ts.map +1 -0
- package/dist/internal/drop-down.js +110 -0
- package/dist/internal/drop-down.js.map +1 -0
- package/dist/internal/expansion.d.ts +9 -0
- package/dist/internal/expansion.d.ts.map +1 -0
- package/dist/internal/expansion.js +74 -0
- package/dist/internal/expansion.js.map +1 -0
- package/dist/internal/selection.d.ts +13 -0
- package/dist/internal/selection.d.ts.map +1 -0
- package/dist/internal/selection.js +100 -0
- package/dist/internal/selection.js.map +1 -0
- package/dist/internal/use-collection.d.ts +17 -0
- package/dist/internal/use-collection.d.ts.map +1 -0
- package/dist/internal/use-collection.js +34 -0
- package/dist/internal/use-collection.js.map +1 -0
- package/dist/internal/use-widget-ref.d.ts +4 -0
- package/dist/internal/use-widget-ref.d.ts.map +1 -0
- package/dist/internal/use-widget-ref.js +8 -0
- package/dist/internal/use-widget-ref.js.map +1 -0
- package/dist/list-view.d.ts +5 -20
- package/dist/list-view.d.ts.map +1 -1
- package/dist/list-view.js +32 -53
- package/dist/list-view.js.map +1 -1
- package/dist/size-group.d.ts +8 -16
- package/dist/size-group.d.ts.map +1 -1
- package/dist/size-group.js +35 -51
- package/dist/size-group.js.map +1 -1
- package/dist/types.d.ts +98 -27
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +17 -6
- package/src/adw/combo-row.tsx +20 -0
- package/src/adw/index.ts +9 -0
- package/src/adw/toast.tsx +74 -0
- package/src/adw/types.ts +45 -0
- package/src/column-view.tsx +176 -160
- package/src/drop-down.tsx +12 -185
- package/src/grid-view.tsx +29 -73
- package/src/index.ts +18 -26
- package/src/internal/cells.tsx +345 -0
- package/src/internal/collection-index.ts +168 -0
- package/src/internal/collection-model.ts +246 -0
- package/src/internal/collection.ts +104 -0
- package/src/internal/drop-down.tsx +186 -0
- package/src/internal/expansion.ts +122 -0
- package/src/internal/selection.tsx +162 -0
- package/src/internal/use-collection.tsx +57 -0
- package/src/internal/use-widget-ref.ts +11 -0
- package/src/list-view.tsx +43 -139
- package/src/size-group.tsx +63 -82
- package/src/types.ts +158 -28
- package/dist/cell.d.ts +0 -30
- package/dist/cell.d.ts.map +0 -1
- package/dist/cell.js +0 -45
- package/dist/cell.js.map +0 -1
- package/dist/column-view-column.d.ts +0 -27
- package/dist/column-view-column.d.ts.map +0 -1
- package/dist/column-view-column.js +0 -30
- package/dist/column-view-column.js.map +0 -1
- package/dist/constraint-layout-apply.d.ts +0 -55
- package/dist/constraint-layout-apply.d.ts.map +0 -1
- package/dist/constraint-layout-apply.js +0 -107
- package/dist/constraint-layout-apply.js.map +0 -1
- package/dist/constraint-layout.d.ts +0 -20
- package/dist/constraint-layout.d.ts.map +0 -1
- package/dist/constraint-layout.js +0 -88
- package/dist/constraint-layout.js.map +0 -1
- package/dist/fixed.d.ts +0 -26
- package/dist/fixed.d.ts.map +0 -1
- package/dist/fixed.js +0 -40
- package/dist/fixed.js.map +0 -1
- package/dist/grid.d.ts +0 -27
- package/dist/grid.d.ts.map +0 -1
- package/dist/grid.js +0 -48
- package/dist/grid.js.map +0 -1
- package/dist/hooks/use-cell-containers.d.ts +0 -18
- package/dist/hooks/use-cell-containers.d.ts.map +0 -1
- package/dist/hooks/use-cell-containers.js +0 -67
- package/dist/hooks/use-cell-containers.js.map +0 -1
- package/dist/hooks/use-collection-model.d.ts +0 -26
- package/dist/hooks/use-collection-model.d.ts.map +0 -1
- package/dist/hooks/use-collection-model.js +0 -35
- package/dist/hooks/use-collection-model.js.map +0 -1
- package/dist/hooks/use-collection-widget.d.ts +0 -28
- package/dist/hooks/use-collection-widget.d.ts.map +0 -1
- package/dist/hooks/use-collection-widget.js +0 -21
- package/dist/hooks/use-collection-widget.js.map +0 -1
- package/dist/hooks/use-drop-down-selection.d.ts +0 -16
- package/dist/hooks/use-drop-down-selection.d.ts.map +0 -1
- package/dist/hooks/use-drop-down-selection.js +0 -35
- package/dist/hooks/use-drop-down-selection.js.map +0 -1
- package/dist/hooks/use-expansion-model.d.ts +0 -12
- package/dist/hooks/use-expansion-model.d.ts.map +0 -1
- package/dist/hooks/use-expansion-model.js +0 -71
- package/dist/hooks/use-expansion-model.js.map +0 -1
- package/dist/hooks/use-header-menu.d.ts +0 -4
- package/dist/hooks/use-header-menu.d.ts.map +0 -1
- package/dist/hooks/use-header-menu.js +0 -20
- package/dist/hooks/use-header-menu.js.map +0 -1
- package/dist/hooks/use-installed-model.d.ts +0 -4
- package/dist/hooks/use-installed-model.d.ts.map +0 -1
- package/dist/hooks/use-installed-model.js +0 -15
- package/dist/hooks/use-installed-model.js.map +0 -1
- package/dist/hooks/use-list-model.d.ts +0 -19
- package/dist/hooks/use-list-model.d.ts.map +0 -1
- package/dist/hooks/use-list-model.js +0 -97
- package/dist/hooks/use-list-model.js.map +0 -1
- package/dist/hooks/use-placed-child.d.ts +0 -18
- package/dist/hooks/use-placed-child.d.ts.map +0 -1
- package/dist/hooks/use-placed-child.js +0 -47
- package/dist/hooks/use-placed-child.js.map +0 -1
- package/dist/hooks/use-selection-model.d.ts +0 -13
- package/dist/hooks/use-selection-model.d.ts.map +0 -1
- package/dist/hooks/use-selection-model.js +0 -103
- package/dist/hooks/use-selection-model.js.map +0 -1
- package/dist/hooks/use-sort-handler.d.ts +0 -17
- package/dist/hooks/use-sort-handler.d.ts.map +0 -1
- package/dist/hooks/use-sort-handler.js +0 -87
- package/dist/hooks/use-sort-handler.js.map +0 -1
- package/dist/menu-items.d.ts +0 -5
- package/dist/menu-items.d.ts.map +0 -1
- package/dist/menu-items.js +0 -48
- package/dist/menu-items.js.map +0 -1
- package/dist/menu.d.ts +0 -14
- package/dist/menu.d.ts.map +0 -1
- package/dist/menu.js +0 -24
- package/dist/menu.js.map +0 -1
- package/dist/overlay.d.ts +0 -24
- package/dist/overlay.d.ts.map +0 -1
- package/dist/overlay.js +0 -49
- package/dist/overlay.js.map +0 -1
- package/dist/utils/cell-container-store.d.ts +0 -28
- package/dist/utils/cell-container-store.d.ts.map +0 -1
- package/dist/utils/cell-container-store.js +0 -98
- package/dist/utils/cell-container-store.js.map +0 -1
- package/dist/utils/item-models.d.ts +0 -10
- package/dist/utils/item-models.d.ts.map +0 -1
- package/dist/utils/item-models.js +0 -82
- package/dist/utils/item-models.js.map +0 -1
- package/dist/utils/item-resolver.d.ts +0 -25
- package/dist/utils/item-resolver.d.ts.map +0 -1
- package/dist/utils/item-resolver.js +0 -102
- package/dist/utils/item-resolver.js.map +0 -1
- package/dist/utils/list-item-flatten.d.ts +0 -24
- package/dist/utils/list-item-flatten.d.ts.map +0 -1
- package/dist/utils/list-item-flatten.js +0 -68
- package/dist/utils/list-item-flatten.js.map +0 -1
- package/src/cell.tsx +0 -144
- package/src/column-view-column.tsx +0 -82
- package/src/constraint-layout-apply.ts +0 -173
- package/src/constraint-layout.tsx +0 -135
- package/src/fixed.tsx +0 -86
- package/src/grid.tsx +0 -88
- package/src/hooks/use-cell-containers.ts +0 -93
- package/src/hooks/use-collection-model.ts +0 -60
- package/src/hooks/use-collection-widget.ts +0 -47
- package/src/hooks/use-drop-down-selection.ts +0 -52
- package/src/hooks/use-expansion-model.ts +0 -82
- package/src/hooks/use-header-menu.ts +0 -34
- package/src/hooks/use-installed-model.ts +0 -20
- package/src/hooks/use-list-model.ts +0 -161
- package/src/hooks/use-placed-child.ts +0 -79
- package/src/hooks/use-selection-model.ts +0 -114
- package/src/hooks/use-sort-handler.ts +0 -107
- package/src/menu-items.ts +0 -48
- package/src/menu.tsx +0 -32
- package/src/overlay.tsx +0 -88
- package/src/utils/cell-container-store.ts +0 -114
- package/src/utils/item-models.ts +0 -113
- package/src/utils/item-resolver.ts +0 -138
- package/src/utils/list-item-flatten.ts +0 -90
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import type * as GObject from "@gtkx/gi/gobject";
|
|
2
|
-
import type * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
-
|
|
4
|
-
export type CellEntry = {
|
|
5
|
-
position: number;
|
|
6
|
-
treeRow: Gtk.TreeListRow | null;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
let nextKey = 0;
|
|
10
|
-
|
|
11
|
-
export class CellContainerStore {
|
|
12
|
-
private entries = new Map<GObject.Object, CellEntry>();
|
|
13
|
-
|
|
14
|
-
private published = new Map<GObject.Object, CellEntry>();
|
|
15
|
-
|
|
16
|
-
private setListeners = new Set<() => void>();
|
|
17
|
-
|
|
18
|
-
private positionListeners = new Map<GObject.Object, Set<() => void>>();
|
|
19
|
-
|
|
20
|
-
private positionFlushers = new Map<GObject.Object, () => void>();
|
|
21
|
-
|
|
22
|
-
private keys = new WeakMap<GObject.Object, string>();
|
|
23
|
-
|
|
24
|
-
private snapshot: GObject.Object[] = [];
|
|
25
|
-
|
|
26
|
-
subscribeSet = (onChange: () => void): (() => void) => {
|
|
27
|
-
this.setListeners.add(onChange);
|
|
28
|
-
return () => {
|
|
29
|
-
this.setListeners.delete(onChange);
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
getContainersSnapshot = (): GObject.Object[] => this.snapshot;
|
|
34
|
-
|
|
35
|
-
subscribePosition = (container: GObject.Object, onChange: () => void): (() => void) => {
|
|
36
|
-
let listeners = this.positionListeners.get(container);
|
|
37
|
-
if (listeners === undefined) {
|
|
38
|
-
listeners = new Set();
|
|
39
|
-
this.positionListeners.set(container, listeners);
|
|
40
|
-
}
|
|
41
|
-
listeners.add(onChange);
|
|
42
|
-
return () => {
|
|
43
|
-
const current = this.positionListeners.get(container);
|
|
44
|
-
if (current === undefined) return;
|
|
45
|
-
current.delete(onChange);
|
|
46
|
-
if (current.size === 0) this.positionListeners.delete(container);
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
getPosition = (container: GObject.Object): CellEntry => {
|
|
51
|
-
let entry = this.published.get(container);
|
|
52
|
-
if (entry === undefined) {
|
|
53
|
-
entry = { position: -1, treeRow: null };
|
|
54
|
-
this.published.set(container, entry);
|
|
55
|
-
}
|
|
56
|
-
return entry;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
keyFor = (container: GObject.Object): string => {
|
|
60
|
-
const existing = this.keys.get(container);
|
|
61
|
-
if (existing !== undefined) return existing;
|
|
62
|
-
const key = `cell-${nextKey++}`;
|
|
63
|
-
this.keys.set(container, key);
|
|
64
|
-
return key;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
addContainer = (container: GObject.Object): void => {
|
|
68
|
-
if (this.entries.has(container)) return;
|
|
69
|
-
this.entries.set(container, { position: -1, treeRow: null });
|
|
70
|
-
this.notifySet();
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
bind = (container: GObject.Object, position: number, treeRow: Gtk.TreeListRow | null): void => {
|
|
74
|
-
this.entries.set(container, { position, treeRow });
|
|
75
|
-
this.notifyPosition(container);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
unbind = (container: GObject.Object): void => {
|
|
79
|
-
if (!this.entries.has(container)) return;
|
|
80
|
-
this.entries.set(container, { position: -1, treeRow: null });
|
|
81
|
-
this.notifyPosition(container);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
removeContainer = (container: GObject.Object): void => {
|
|
85
|
-
if (!this.entries.delete(container)) return;
|
|
86
|
-
this.published.delete(container);
|
|
87
|
-
this.positionFlushers.delete(container);
|
|
88
|
-
this.notifySet();
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
private flushSet = (): void => {
|
|
92
|
-
this.snapshot = [...this.entries.keys()];
|
|
93
|
-
for (const listener of [...this.setListeners]) listener();
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
private notifySet(): void {
|
|
97
|
-
this.flushSet();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private notifyPosition(container: GObject.Object): void {
|
|
101
|
-
let flush = this.positionFlushers.get(container);
|
|
102
|
-
if (flush === undefined) {
|
|
103
|
-
flush = (): void => {
|
|
104
|
-
const live = this.entries.get(container);
|
|
105
|
-
if (live !== undefined) this.published.set(container, live);
|
|
106
|
-
const listeners = this.positionListeners.get(container);
|
|
107
|
-
if (listeners === undefined) return;
|
|
108
|
-
for (const listener of [...listeners]) listener();
|
|
109
|
-
};
|
|
110
|
-
this.positionFlushers.set(container, flush);
|
|
111
|
-
}
|
|
112
|
-
flush();
|
|
113
|
-
}
|
|
114
|
-
}
|
package/src/utils/item-models.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import * as Gio from "@gtkx/gi/gio";
|
|
2
|
-
import type * as GObject from "@gtkx/gi/gobject";
|
|
3
|
-
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
-
import type { ItemNode, SectionNode } from "../types.js";
|
|
5
|
-
import type { RowValue } from "./item-resolver.js";
|
|
6
|
-
import { countDescendants, treeItemMetadata } from "./list-item-flatten.js";
|
|
7
|
-
|
|
8
|
-
const emptyStrings = (count: number): string[] => new Array<string>(Math.max(0, count)).fill("");
|
|
9
|
-
|
|
10
|
-
export const retagRows = <T>(
|
|
11
|
-
items: ItemNode<T>[],
|
|
12
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
13
|
-
placeholdersById: Map<string, GObject.Object>,
|
|
14
|
-
): void => {
|
|
15
|
-
const walk = (list: ItemNode<T>[]): void => {
|
|
16
|
-
for (const item of list) {
|
|
17
|
-
const placeholder = placeholdersById.get(item.id);
|
|
18
|
-
if (placeholder !== undefined) {
|
|
19
|
-
rowValues.set(placeholder, {
|
|
20
|
-
id: item.id,
|
|
21
|
-
value: item.value,
|
|
22
|
-
metadata: treeItemMetadata(item),
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
if (item.children !== undefined && item.children.length > 0) walk(item.children);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
walk(items);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const createFlatModel = (count: number): Gtk.StringList => Gtk.StringList.new(emptyStrings(count));
|
|
32
|
-
|
|
33
|
-
export const resizeFlatModel = (model: Gtk.StringList, count: number): void => {
|
|
34
|
-
const target = Math.max(0, count);
|
|
35
|
-
const current = model.getNItems();
|
|
36
|
-
if (current === target) return;
|
|
37
|
-
if (target > current) {
|
|
38
|
-
model.splice(current, 0, emptyStrings(target - current));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
model.splice(target, current - target, null);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const createTaggedRow = <T>(
|
|
45
|
-
row: RowValue<T>,
|
|
46
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
47
|
-
placeholdersById?: Map<string, GObject.Object>,
|
|
48
|
-
): GObject.Object => {
|
|
49
|
-
const placeholder = Gtk.StringObject.new("");
|
|
50
|
-
rowValues.set(placeholder, row);
|
|
51
|
-
if (placeholdersById !== undefined) placeholdersById.set(row.id, placeholder);
|
|
52
|
-
return placeholder;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const childModelOf = <T>(
|
|
56
|
-
children: ItemNode<T>[],
|
|
57
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
58
|
-
placeholdersById: Map<string, GObject.Object>,
|
|
59
|
-
): Gio.ListStore => {
|
|
60
|
-
const store = Gio.ListStore.new(Gtk.StringObject.prototype.__type__);
|
|
61
|
-
for (const child of children) {
|
|
62
|
-
store.append(
|
|
63
|
-
createTaggedRow(
|
|
64
|
-
{ id: child.id, value: child.value, metadata: treeItemMetadata(child) },
|
|
65
|
-
rowValues,
|
|
66
|
-
placeholdersById,
|
|
67
|
-
),
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
return store;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export const createTreeModel = <T>(
|
|
74
|
-
items: ItemNode<T>[],
|
|
75
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
76
|
-
placeholdersById: Map<string, GObject.Object>,
|
|
77
|
-
): Gtk.TreeListModel => {
|
|
78
|
-
const childrenByRow = new WeakMap<GObject.Object, ItemNode<T>[]>();
|
|
79
|
-
const root = Gio.ListStore.new(Gtk.StringObject.prototype.__type__);
|
|
80
|
-
for (const item of items) {
|
|
81
|
-
const placeholder = createTaggedRow(
|
|
82
|
-
{ id: item.id, value: item.value, metadata: treeItemMetadata(item) },
|
|
83
|
-
rowValues,
|
|
84
|
-
placeholdersById,
|
|
85
|
-
);
|
|
86
|
-
if (item.children !== undefined && item.children.length > 0) {
|
|
87
|
-
childrenByRow.set(placeholder, item.children);
|
|
88
|
-
}
|
|
89
|
-
root.append(placeholder);
|
|
90
|
-
}
|
|
91
|
-
const createFunc = (rowItem: GObject.Object): Gio.ListModel | null => {
|
|
92
|
-
const children = childrenByRow.get(rowItem);
|
|
93
|
-
if (children === undefined) return null;
|
|
94
|
-
const store = childModelOf(children, rowValues, placeholdersById);
|
|
95
|
-
for (let index = 0; index < children.length; index++) {
|
|
96
|
-
const child = children[index];
|
|
97
|
-
if (child !== undefined && child.children !== undefined && child.children.length > 0) {
|
|
98
|
-
const placeholder = store.getItem(index);
|
|
99
|
-
if (placeholder !== null) childrenByRow.set(placeholder, child.children);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return store;
|
|
103
|
-
};
|
|
104
|
-
return Gtk.TreeListModel.new(root, false, false, createFunc);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
export const createSectionModel = <S, T>(sections: SectionNode<S, T>[]): Gtk.FlattenListModel => {
|
|
108
|
-
const store = Gio.ListStore.new(Gtk.StringList.prototype.__type__);
|
|
109
|
-
for (const section of sections) {
|
|
110
|
-
store.append(Gtk.StringList.new(emptyStrings(countDescendants(section.data))));
|
|
111
|
-
}
|
|
112
|
-
return Gtk.FlattenListModel.new(store);
|
|
113
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import type * as GObject from "@gtkx/gi/gobject";
|
|
2
|
-
import type * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
-
import type { ItemNode, SectionNode } from "../types.js";
|
|
4
|
-
import { countDescendants, flattenListItems, type TreeItemMetadata } from "./list-item-flatten.js";
|
|
5
|
-
|
|
6
|
-
const NO_TREE_METADATA: TreeItemMetadata = { hideExpander: false, indentForDepth: true, indentForIcon: true };
|
|
7
|
-
|
|
8
|
-
const treeItemCache = new WeakMap<Gtk.TreeListRow, GObject.Object>();
|
|
9
|
-
|
|
10
|
-
const treeRowItem = (treeRow: Gtk.TreeListRow): GObject.Object | null => {
|
|
11
|
-
const cached = treeItemCache.get(treeRow);
|
|
12
|
-
if (cached !== undefined) return cached;
|
|
13
|
-
const item = treeRow.getItem();
|
|
14
|
-
if (item !== null) treeItemCache.set(treeRow, item);
|
|
15
|
-
return item;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type Resolved<T = unknown, S = unknown> = {
|
|
19
|
-
value: T | S | undefined;
|
|
20
|
-
present: boolean;
|
|
21
|
-
isHeader: boolean;
|
|
22
|
-
metadata: TreeItemMetadata;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type ItemResolver<T = unknown, S = unknown> = {
|
|
26
|
-
resolve(position: number, treeRow: Gtk.TreeListRow | null): Resolved<T, S>;
|
|
27
|
-
positionOfId(id: string): number;
|
|
28
|
-
idOf(position: number): string | undefined;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type RowValue<T = unknown> = {
|
|
32
|
-
id: string;
|
|
33
|
-
value: T;
|
|
34
|
-
metadata: TreeItemMetadata;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const rowIdOf = <T>(
|
|
38
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
39
|
-
row: Gtk.TreeListRow,
|
|
40
|
-
): string | undefined => {
|
|
41
|
-
const item = row.getItem();
|
|
42
|
-
return item === null ? undefined : rowValues.get(item)?.id;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const createItemResolver = <T, S>(
|
|
46
|
-
items: ItemNode<T>[] | undefined,
|
|
47
|
-
flattenTreeChildren: boolean,
|
|
48
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
49
|
-
): ItemResolver<T, S> => {
|
|
50
|
-
const flattened = flattenListItems(items, flattenTreeChildren);
|
|
51
|
-
return {
|
|
52
|
-
positionOfId(id: string): number {
|
|
53
|
-
const position = flattened.idToPosition.get(id);
|
|
54
|
-
return position === undefined ? -1 : position;
|
|
55
|
-
},
|
|
56
|
-
idOf(position: number): string | undefined {
|
|
57
|
-
return flattened.positionToId.get(position);
|
|
58
|
-
},
|
|
59
|
-
resolve(position: number, treeRow: Gtk.TreeListRow | null): Resolved<T, S> {
|
|
60
|
-
if (treeRow !== null && !flattenTreeChildren) {
|
|
61
|
-
const rowItem = treeRowItem(treeRow);
|
|
62
|
-
if (rowItem !== null) {
|
|
63
|
-
const tagged = rowValues.get(rowItem);
|
|
64
|
-
if (tagged !== undefined) {
|
|
65
|
-
return {
|
|
66
|
-
value: tagged.value,
|
|
67
|
-
present: true,
|
|
68
|
-
isHeader: false,
|
|
69
|
-
metadata: tagged.metadata,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const record = flattened.records[position];
|
|
75
|
-
if (record === undefined) {
|
|
76
|
-
return {
|
|
77
|
-
value: undefined,
|
|
78
|
-
present: false,
|
|
79
|
-
isHeader: false,
|
|
80
|
-
metadata: NO_TREE_METADATA,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
return {
|
|
84
|
-
value: record.value,
|
|
85
|
-
present: true,
|
|
86
|
-
isHeader: false,
|
|
87
|
-
metadata: record.metadata,
|
|
88
|
-
};
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
export const createSectionHeaderResolver = <T, S>(sections: SectionNode<S, T>[] | undefined): ItemResolver<T, S> => {
|
|
94
|
-
const valueByStart = new Map<number, S>();
|
|
95
|
-
let start = 0;
|
|
96
|
-
for (const section of sections ?? []) {
|
|
97
|
-
valueByStart.set(start, section.value);
|
|
98
|
-
start += countDescendants(section.data);
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
positionOfId: () => -1,
|
|
102
|
-
idOf: () => undefined,
|
|
103
|
-
resolve(position: number): Resolved<T, S> {
|
|
104
|
-
if (!valueByStart.has(position)) {
|
|
105
|
-
return { value: undefined, present: false, isHeader: true, metadata: NO_TREE_METADATA };
|
|
106
|
-
}
|
|
107
|
-
return {
|
|
108
|
-
value: valueByStart.get(position),
|
|
109
|
-
present: true,
|
|
110
|
-
isHeader: true,
|
|
111
|
-
metadata: NO_TREE_METADATA,
|
|
112
|
-
};
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export const createTreeResolver = <T, S>(
|
|
118
|
-
items: ItemNode<T>[] | undefined,
|
|
119
|
-
rowValues: WeakMap<GObject.Object, RowValue<T>>,
|
|
120
|
-
model: Gtk.TreeListModel,
|
|
121
|
-
): ItemResolver<T, S> => {
|
|
122
|
-
const base = createItemResolver<T, S>(items, false, rowValues);
|
|
123
|
-
return {
|
|
124
|
-
resolve: base.resolve,
|
|
125
|
-
idOf: (position: number): string | undefined => {
|
|
126
|
-
const row = model.getRow(position);
|
|
127
|
-
return row === null ? undefined : rowIdOf(rowValues, row);
|
|
128
|
-
},
|
|
129
|
-
positionOfId: (id: string): number => {
|
|
130
|
-
const count = model.getNItems();
|
|
131
|
-
for (let position = 0; position < count; position++) {
|
|
132
|
-
const row = model.getRow(position);
|
|
133
|
-
if (row !== null && rowIdOf(rowValues, row) === id) return position;
|
|
134
|
-
}
|
|
135
|
-
return -1;
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import type { ItemNode } from "../types.js";
|
|
2
|
-
|
|
3
|
-
export type TreeItemMetadata = {
|
|
4
|
-
hideExpander: boolean;
|
|
5
|
-
indentForDepth: boolean;
|
|
6
|
-
indentForIcon: boolean;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
type FlattenedRecord<T = unknown> = {
|
|
10
|
-
id: string;
|
|
11
|
-
value: T;
|
|
12
|
-
metadata: TreeItemMetadata;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
type FlattenResult<T = unknown> = {
|
|
16
|
-
records: FlattenedRecord<T>[];
|
|
17
|
-
idToPosition: Map<string, number>;
|
|
18
|
-
positionToId: Map<number, string>;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type ListStructure = "flat" | "tree";
|
|
22
|
-
|
|
23
|
-
export const detectStructure = <T>(items: ItemNode<T>[] | undefined): ListStructure => {
|
|
24
|
-
if (items === undefined) return "flat";
|
|
25
|
-
for (const item of items) {
|
|
26
|
-
if (item.children !== undefined && item.children.length > 0) return "tree";
|
|
27
|
-
}
|
|
28
|
-
return "flat";
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const structuralSignature = <T>(items: ItemNode<T>[] | undefined): string => {
|
|
32
|
-
if (items === undefined) return "";
|
|
33
|
-
const parts: string[] = [];
|
|
34
|
-
const walk = (list: ItemNode<T>[]): void => {
|
|
35
|
-
parts.push("[");
|
|
36
|
-
for (const item of list) {
|
|
37
|
-
const hidden = item.hideExpander === true;
|
|
38
|
-
parts.push(`${item.id}|${hidden ? 1 : 0}`);
|
|
39
|
-
if (item.children !== undefined && item.children.length > 0) walk(item.children);
|
|
40
|
-
}
|
|
41
|
-
parts.push("]");
|
|
42
|
-
};
|
|
43
|
-
walk(items);
|
|
44
|
-
return parts.join(",");
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const countDescendants = <T>(items: ItemNode<T>[]): number => {
|
|
48
|
-
let total = 0;
|
|
49
|
-
for (const item of items) {
|
|
50
|
-
total += 1;
|
|
51
|
-
if (item.children !== undefined && item.children.length > 0) total += countDescendants(item.children);
|
|
52
|
-
}
|
|
53
|
-
return total;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const treeItemMetadata = <T>(item: ItemNode<T>): TreeItemMetadata => ({
|
|
57
|
-
hideExpander: item.hideExpander ?? false,
|
|
58
|
-
indentForDepth: item.indentForDepth ?? true,
|
|
59
|
-
indentForIcon: item.indentForIcon ?? true,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const appendRecord = <T>(item: ItemNode<T>, result: FlattenResult<T>, includeChildren: boolean): void => {
|
|
63
|
-
const position = result.records.length;
|
|
64
|
-
result.idToPosition.set(item.id, position);
|
|
65
|
-
result.positionToId.set(position, item.id);
|
|
66
|
-
result.records.push({
|
|
67
|
-
id: item.id,
|
|
68
|
-
value: item.value,
|
|
69
|
-
metadata: treeItemMetadata(item),
|
|
70
|
-
});
|
|
71
|
-
if (includeChildren && item.children !== undefined) {
|
|
72
|
-
for (const child of item.children) appendRecord(child, result, includeChildren);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export const flattenListItems = <T>(
|
|
77
|
-
items: ItemNode<T>[] | undefined,
|
|
78
|
-
flattenTreeChildren: boolean,
|
|
79
|
-
): FlattenResult<T> => {
|
|
80
|
-
const result: FlattenResult<T> = {
|
|
81
|
-
records: [],
|
|
82
|
-
idToPosition: new Map(),
|
|
83
|
-
positionToId: new Map(),
|
|
84
|
-
};
|
|
85
|
-
if (items === undefined) return result;
|
|
86
|
-
for (const item of items) {
|
|
87
|
-
appendRecord(item, result, flattenTreeChildren);
|
|
88
|
-
}
|
|
89
|
-
return result;
|
|
90
|
-
};
|