@gtkx/components 1.0.0-rc.4 → 1.1.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 +5 -5
- package/dist/column-view.d.ts +2 -2
- package/dist/column-view.d.ts.map +1 -1
- package/dist/column-view.js +14 -12
- package/dist/column-view.js.map +1 -1
- package/dist/grid-view.js +1 -1
- package/dist/grid-view.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/cells.d.ts +31 -23
- package/dist/internal/cells.d.ts.map +1 -1
- package/dist/internal/cells.js +168 -77
- package/dist/internal/cells.js.map +1 -1
- package/dist/internal/collection-index.d.ts +8 -11
- package/dist/internal/collection-index.d.ts.map +1 -1
- package/dist/internal/collection-index.js +53 -73
- package/dist/internal/collection-index.js.map +1 -1
- package/dist/internal/collection-model.d.ts +24 -4
- package/dist/internal/collection-model.d.ts.map +1 -1
- package/dist/internal/collection-model.js +247 -96
- package/dist/internal/collection-model.js.map +1 -1
- package/dist/internal/collection.d.ts +8 -10
- package/dist/internal/collection.d.ts.map +1 -1
- package/dist/internal/collection.js +38 -48
- package/dist/internal/collection.js.map +1 -1
- package/dist/internal/controlled-sync.d.ts +11 -0
- package/dist/internal/controlled-sync.d.ts.map +1 -0
- package/dist/internal/controlled-sync.js +19 -0
- package/dist/internal/controlled-sync.js.map +1 -0
- package/dist/internal/drop-down.d.ts.map +1 -1
- package/dist/internal/drop-down.js +27 -15
- package/dist/internal/drop-down.js.map +1 -1
- package/dist/internal/expansion.d.ts +3 -2
- package/dist/internal/expansion.d.ts.map +1 -1
- package/dist/internal/expansion.js +73 -48
- package/dist/internal/expansion.js.map +1 -1
- package/dist/internal/keys.d.ts +5 -0
- package/dist/internal/keys.d.ts.map +1 -0
- package/dist/internal/keys.js +13 -0
- package/dist/internal/keys.js.map +1 -0
- package/dist/internal/selection.d.ts +3 -2
- package/dist/internal/selection.d.ts.map +1 -1
- package/dist/internal/selection.js +68 -35
- package/dist/internal/selection.js.map +1 -1
- package/dist/internal/slots.d.ts +10 -0
- package/dist/internal/slots.d.ts.map +1 -0
- package/dist/internal/slots.js +43 -0
- package/dist/internal/slots.js.map +1 -0
- package/dist/internal/tree-expansion.d.ts +19 -0
- package/dist/internal/tree-expansion.d.ts.map +1 -0
- package/dist/internal/tree-expansion.js +72 -0
- package/dist/internal/tree-expansion.js.map +1 -0
- package/dist/internal/tree-order.d.ts +26 -0
- package/dist/internal/tree-order.d.ts.map +1 -0
- package/dist/internal/tree-order.js +109 -0
- package/dist/internal/tree-order.js.map +1 -0
- package/dist/internal/use-collection.d.ts +1 -1
- package/dist/internal/use-collection.d.ts.map +1 -1
- package/dist/internal/use-collection.js +4 -4
- package/dist/internal/use-collection.js.map +1 -1
- package/dist/list-view.d.ts.map +1 -1
- package/dist/list-view.js +6 -6
- package/dist/list-view.js.map +1 -1
- package/dist/types.d.ts +72 -22
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +17 -9
- package/src/column-view.tsx +28 -25
- package/src/grid-view.tsx +1 -1
- package/src/index.ts +3 -0
- package/src/internal/cells.tsx +339 -117
- package/src/internal/collection-index.ts +68 -92
- package/src/internal/collection-model.ts +327 -112
- package/src/internal/collection.ts +45 -65
- package/src/internal/controlled-sync.ts +34 -0
- package/src/internal/drop-down.tsx +41 -20
- package/src/internal/expansion.ts +95 -70
- package/src/internal/keys.ts +18 -0
- package/src/internal/selection.tsx +100 -51
- package/src/internal/slots.ts +67 -0
- package/src/internal/tree-expansion.ts +115 -0
- package/src/internal/tree-order.ts +208 -0
- package/src/internal/use-collection.tsx +5 -5
- package/src/list-view.tsx +14 -10
- package/src/types.ts +78 -20
|
@@ -1,109 +1,224 @@
|
|
|
1
1
|
import * as Gio from "@gtkx/gi/gio";
|
|
2
2
|
import * as GObject from "@gtkx/gi/gobject";
|
|
3
3
|
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
import { registerClass } from "@gtkx/runtime";
|
|
5
|
+
import { createCollectionIndex, emptyLevel } from "./collection-index.js";
|
|
6
|
+
import { encodePart } from "./keys.js";
|
|
7
|
+
import { adoptIndex, createTreeExpansion, pruneSlots } from "./tree-expansion.js";
|
|
8
|
+
const STORE_CLASS_KEY = Symbol.for("gtkx.components.lazy-level-store");
|
|
9
|
+
const SLOTS_KEY = Symbol.for("gtkx.components.lazy-level-store.slots");
|
|
10
|
+
const EMPTY_INDEX = createCollectionIndex(undefined, undefined, true);
|
|
11
|
+
const SLOTS = sharedSlots();
|
|
12
|
+
const newRootStore = () => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });
|
|
13
|
+
function sharedSlots() {
|
|
14
|
+
const cached = Reflect.get(globalThis, SLOTS_KEY);
|
|
15
|
+
if (cached instanceof WeakMap) {
|
|
16
|
+
return cached;
|
|
15
17
|
}
|
|
16
|
-
const created =
|
|
17
|
-
|
|
18
|
+
const created = new WeakMap();
|
|
19
|
+
Reflect.set(globalThis, SLOTS_KEY, created);
|
|
18
20
|
return created;
|
|
19
21
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
return count;
|
|
26
|
-
}
|
|
27
|
-
function commonSuffix(previous, next, max) {
|
|
28
|
-
let count = 0;
|
|
29
|
-
while (count < max && previous[previous.length - 1 - count] === next[next.length - 1 - count]) {
|
|
30
|
-
count += 1;
|
|
22
|
+
function registeredStoreClass() {
|
|
23
|
+
const cached = Reflect.get(globalThis, STORE_CLASS_KEY);
|
|
24
|
+
if (typeof cached === "function") {
|
|
25
|
+
return cached;
|
|
31
26
|
}
|
|
32
|
-
|
|
27
|
+
registerClass(LazyLevelStore, { typeName: "GtkxLazyLevelStore", implements: [Gio.ListModel] });
|
|
28
|
+
Reflect.set(globalThis, STORE_CLASS_KEY, LazyLevelStore);
|
|
29
|
+
return LazyLevelStore;
|
|
33
30
|
}
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
if (start === previous.length && start === next.length) {
|
|
31
|
+
function slotRefFor(value) {
|
|
32
|
+
const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;
|
|
33
|
+
if (item === null) {
|
|
38
34
|
return null;
|
|
39
35
|
}
|
|
40
|
-
const
|
|
41
|
-
return
|
|
36
|
+
const ref = SLOTS.get(item);
|
|
37
|
+
return ref === undefined || ref.slot === -1 ? null : ref;
|
|
42
38
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
function slotPathAt(store, slot) {
|
|
40
|
+
return store.level.path + encodePart(String(slot));
|
|
41
|
+
}
|
|
42
|
+
function growStore(store) {
|
|
43
|
+
for (let slot = store.refs.length; slot < store.level.items.length; slot++) {
|
|
44
|
+
store.refs.push({ store, slot });
|
|
45
|
+
store.objects.push(null);
|
|
46
|
+
store.childStores.push(null);
|
|
47
47
|
}
|
|
48
|
-
const created = { store: newStore(), ids: [], canExpand: new Map() };
|
|
49
|
-
state.levels.set(key, created);
|
|
50
|
-
return created;
|
|
51
48
|
}
|
|
52
|
-
function
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
function newLevelStore(level) {
|
|
50
|
+
const store = new (registeredStoreClass())();
|
|
51
|
+
store.level = level;
|
|
52
|
+
growStore(store);
|
|
53
|
+
return store;
|
|
54
|
+
}
|
|
55
|
+
function collectFlips(previous, next, overlap) {
|
|
56
|
+
const flipped = new Set();
|
|
57
|
+
for (let slot = 0; slot < overlap; slot++) {
|
|
58
|
+
if ((previous.expandableFlags[slot] ?? false) !== (next.expandableFlags[slot] ?? false)) {
|
|
59
|
+
flipped.add(slot);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
return flipped;
|
|
63
63
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
function pruneFlips(context, store, flipped) {
|
|
65
|
+
if (flipped.size === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
pruneSlots(context.expansion, store.level.path, (slot) => flipped.has(slot));
|
|
69
|
+
for (const slot of flipped) {
|
|
70
|
+
store.childStores[slot] = null;
|
|
69
71
|
}
|
|
70
|
-
current.store.splice(range.start, range.removed, range.added.map((id) => objectFor(state, id)));
|
|
71
|
-
current.ids = [...level.ids];
|
|
72
|
-
return true;
|
|
73
72
|
}
|
|
74
|
-
function
|
|
75
|
-
for (
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
function detachRefs(store, nextLength) {
|
|
74
|
+
for (let slot = nextLength; slot < store.refs.length; slot++) {
|
|
75
|
+
const ref = store.refs[slot];
|
|
76
|
+
if (ref !== undefined) {
|
|
77
|
+
ref.slot = -1;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
function
|
|
82
|
-
if (
|
|
81
|
+
function shrinkStore(context, store, nextLength) {
|
|
82
|
+
if (store.refs.length <= nextLength) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
detachRefs(store, nextLength);
|
|
86
|
+
pruneSlots(context.expansion, store.level.path, (slot) => slot >= nextLength);
|
|
87
|
+
store.refs.length = nextLength;
|
|
88
|
+
store.objects.length = nextLength;
|
|
89
|
+
store.childStores.length = nextLength;
|
|
90
|
+
}
|
|
91
|
+
function emitTailSplice(store, previousLength, nextLength) {
|
|
92
|
+
if (nextLength < previousLength) {
|
|
93
|
+
store.itemsChanged(nextLength, previousLength - nextLength, 0);
|
|
83
94
|
return;
|
|
84
95
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
96
|
+
if (nextLength > previousLength) {
|
|
97
|
+
store.itemsChanged(previousLength, 0, nextLength - previousLength);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function extendRuns(runs, slot) {
|
|
101
|
+
const last = runs.at(-1);
|
|
102
|
+
if (last !== undefined && last.start + last.length === slot) {
|
|
103
|
+
last.length += 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
runs.push({ start: slot, length: 1 });
|
|
107
|
+
}
|
|
108
|
+
function collectFlipRuns(flipped) {
|
|
109
|
+
const runs = [];
|
|
110
|
+
for (const slot of flipped) {
|
|
111
|
+
extendRuns(runs, slot);
|
|
112
|
+
}
|
|
113
|
+
return runs;
|
|
114
|
+
}
|
|
115
|
+
function emitFlips(store, flipped) {
|
|
116
|
+
for (const run of collectFlipRuns(flipped)) {
|
|
117
|
+
store.itemsChanged(run.start, run.length, run.length);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function childSync(context, store, slot, flipped) {
|
|
121
|
+
const child = store.childStores[slot] ?? null;
|
|
122
|
+
if (child === null || flipped.has(slot)) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
const level = context.index.childLevel(store.level, slot);
|
|
126
|
+
return level === undefined ? undefined : { store: child, level };
|
|
127
|
+
}
|
|
128
|
+
function childSyncs(context, store, overlap, flipped) {
|
|
129
|
+
const syncs = [];
|
|
130
|
+
for (let slot = 0; slot < overlap; slot++) {
|
|
131
|
+
const sync = childSync(context, store, slot, flipped);
|
|
132
|
+
if (sync !== undefined) {
|
|
133
|
+
syncs.push(sync);
|
|
88
134
|
}
|
|
89
135
|
}
|
|
136
|
+
return syncs;
|
|
137
|
+
}
|
|
138
|
+
function syncEntry(context, entry) {
|
|
139
|
+
const { store, level } = entry;
|
|
140
|
+
const previousLength = store.refs.length;
|
|
141
|
+
const overlap = Math.min(previousLength, level.items.length);
|
|
142
|
+
const flipped = collectFlips(store.level, level, overlap);
|
|
143
|
+
store.level = level;
|
|
144
|
+
pruneFlips(context, store, flipped);
|
|
145
|
+
shrinkStore(context, store, level.items.length);
|
|
146
|
+
growStore(store);
|
|
147
|
+
emitTailSplice(store, previousLength, level.items.length);
|
|
148
|
+
emitFlips(store, flipped);
|
|
149
|
+
return childSyncs(context, store, overlap, flipped);
|
|
150
|
+
}
|
|
151
|
+
function pushSyncs(pending, syncs) {
|
|
152
|
+
for (const sync of syncs) {
|
|
153
|
+
pending.push(sync);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function syncLevel(context, store, level) {
|
|
157
|
+
const pending = [{ store, level }];
|
|
158
|
+
while (pending.length > 0) {
|
|
159
|
+
const entry = pending.pop();
|
|
160
|
+
if (entry !== undefined) {
|
|
161
|
+
pushSyncs(pending, syncEntry(context, entry).toReversed());
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function ensureChildStore(index, store, slot) {
|
|
166
|
+
const existing = store.childStores[slot] ?? null;
|
|
167
|
+
if (existing !== null || !(store.level.expandableFlags[slot] ?? false)) {
|
|
168
|
+
return existing;
|
|
169
|
+
}
|
|
170
|
+
const level = index.childLevel(store.level, slot);
|
|
171
|
+
if (level === undefined) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const created = newLevelStore(level);
|
|
175
|
+
store.childStores[slot] = created;
|
|
176
|
+
return created;
|
|
90
177
|
}
|
|
91
178
|
function childStoreFor(state, object) {
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
179
|
+
const ref = slotRefFor(object);
|
|
180
|
+
if (ref === null) {
|
|
94
181
|
return null;
|
|
95
182
|
}
|
|
96
|
-
return state.
|
|
183
|
+
return ensureChildStore(state.index, ref.store, ref.slot);
|
|
184
|
+
}
|
|
185
|
+
function treeFor(state, store) {
|
|
186
|
+
return (state.trees.get(store) ?? Gtk.TreeListModel.new(store, false, false, (object) => childStoreFor(state, object)));
|
|
187
|
+
}
|
|
188
|
+
function nextTrees(state, index) {
|
|
189
|
+
if (!index.isTree) {
|
|
190
|
+
return new Map();
|
|
191
|
+
}
|
|
192
|
+
return new Map(state.groupStores.map((store) => [store, treeFor(state, store)]));
|
|
193
|
+
}
|
|
194
|
+
function pruneRebuiltLevels(state, next) {
|
|
195
|
+
const stores = new Set([...state.trees.keys(), ...next.keys()]);
|
|
196
|
+
for (const store of stores) {
|
|
197
|
+
if (state.trees.get(store) !== next.get(store)) {
|
|
198
|
+
pruneSlots(state.expansion, store.level.path, () => true);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
97
201
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
202
|
+
function adoptTrees(state, index) {
|
|
203
|
+
const next = nextTrees(state, index);
|
|
204
|
+
pruneRebuiltLevels(state, next);
|
|
205
|
+
state.trees = next;
|
|
206
|
+
state.treeModels = next.values().toArray();
|
|
101
207
|
}
|
|
102
208
|
function desiredRootModels(state, index) {
|
|
103
|
-
|
|
104
|
-
|
|
209
|
+
adoptTrees(state, index);
|
|
210
|
+
return index.isTree ? [...state.treeModels] : [...state.groupStores];
|
|
211
|
+
}
|
|
212
|
+
function rowAt(state, position) {
|
|
213
|
+
let offset = position;
|
|
214
|
+
for (const tree of state.treeModels) {
|
|
215
|
+
const count = tree.getNItems();
|
|
216
|
+
if (offset < count) {
|
|
217
|
+
return tree.getRow(offset);
|
|
218
|
+
}
|
|
219
|
+
offset -= count;
|
|
105
220
|
}
|
|
106
|
-
return
|
|
221
|
+
return null;
|
|
107
222
|
}
|
|
108
223
|
function hasSameModels(previous, next) {
|
|
109
224
|
return previous.length === next.length && next.every((model, index) => previous[index] === model);
|
|
@@ -116,46 +231,82 @@ function syncRoot(state, index) {
|
|
|
116
231
|
state.root.splice(0, state.rootModels.length, next);
|
|
117
232
|
state.rootModels = next;
|
|
118
233
|
}
|
|
119
|
-
function
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
didChange = didSpliceLevel(state, level) || didChange;
|
|
125
|
-
visited.add(level.key);
|
|
234
|
+
function adjustGroupStores(state, context) {
|
|
235
|
+
const { groups } = context.index;
|
|
236
|
+
state.groupStores.length = Math.min(state.groupStores.length, groups.length);
|
|
237
|
+
for (const level of groups.slice(state.groupStores.length)) {
|
|
238
|
+
state.groupStores.push(newLevelStore(level));
|
|
126
239
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
240
|
+
}
|
|
241
|
+
function stepGroupStores(state, context, surviving) {
|
|
242
|
+
for (const [group, level] of context.index.groups.entries()) {
|
|
243
|
+
const store = state.groupStores[group];
|
|
244
|
+
if (store !== undefined && group < surviving) {
|
|
245
|
+
syncLevel(context, store, level);
|
|
246
|
+
}
|
|
130
247
|
}
|
|
131
|
-
syncRoot(state, index);
|
|
132
|
-
refreshExpandableLevels(state, index, levels);
|
|
133
248
|
}
|
|
134
|
-
function
|
|
135
|
-
|
|
136
|
-
|
|
249
|
+
function syncModel(state, index) {
|
|
250
|
+
const context = { index, expansion: state.expansion };
|
|
251
|
+
const surviving = Math.min(state.groupStores.length, index.groups.length);
|
|
252
|
+
state.index = index;
|
|
253
|
+
state.expansion.isSyncing = true;
|
|
254
|
+
try {
|
|
255
|
+
adjustGroupStores(state, context);
|
|
256
|
+
syncRoot(state, index);
|
|
257
|
+
stepGroupStores(state, context, surviving);
|
|
137
258
|
}
|
|
138
|
-
|
|
139
|
-
|
|
259
|
+
finally {
|
|
260
|
+
state.expansion.isSyncing = false;
|
|
140
261
|
}
|
|
262
|
+
adoptIndex(state.expansion, index);
|
|
141
263
|
}
|
|
142
264
|
function createCollectionModel() {
|
|
143
|
-
|
|
265
|
+
registeredStoreClass();
|
|
266
|
+
const root = newRootStore();
|
|
144
267
|
const state = {
|
|
145
268
|
root,
|
|
146
269
|
rootModels: [],
|
|
147
270
|
model: Gtk.FlattenListModel.new(root),
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
271
|
+
groupStores: [],
|
|
272
|
+
trees: new Map(),
|
|
273
|
+
treeModels: [],
|
|
274
|
+
expansion: createTreeExpansion(EMPTY_INDEX),
|
|
275
|
+
index: EMPTY_INDEX,
|
|
151
276
|
};
|
|
152
277
|
return {
|
|
153
278
|
model: state.model,
|
|
154
|
-
|
|
279
|
+
expansion: state.expansion,
|
|
280
|
+
rowAt: (position) => rowAt(state, position),
|
|
155
281
|
sync: (index) => {
|
|
156
282
|
syncModel(state, index);
|
|
157
283
|
},
|
|
158
284
|
};
|
|
159
285
|
}
|
|
160
|
-
|
|
286
|
+
class LazyLevelStore extends GObject.Object {
|
|
287
|
+
level = emptyLevel();
|
|
288
|
+
refs = [];
|
|
289
|
+
objects = [];
|
|
290
|
+
childStores = [];
|
|
291
|
+
createItem(position, ref) {
|
|
292
|
+
const created = Gtk.StringObject.new("");
|
|
293
|
+
this.objects[position] = created;
|
|
294
|
+
SLOTS.set(created, ref);
|
|
295
|
+
return created;
|
|
296
|
+
}
|
|
297
|
+
vfuncGetItemType() {
|
|
298
|
+
return GObject.TYPE_OBJECT;
|
|
299
|
+
}
|
|
300
|
+
vfuncGetNItems() {
|
|
301
|
+
return this.refs.length;
|
|
302
|
+
}
|
|
303
|
+
vfuncGetItem(position) {
|
|
304
|
+
const ref = this.refs[position];
|
|
305
|
+
if (ref === undefined) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
return this.objects[position] ?? this.createItem(position, ref);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
export { createCollectionModel, slotPathAt, slotRefFor };
|
|
161
312
|
//# sourceMappingURL=collection-model.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-model.js","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport { childLevelKey, ROOT_LEVEL_KEY } from \"./collection-index.js\";\n\ntype LevelState = {\n store: Gio.ListStore;\n ids: string[];\n canExpand: Map<string, boolean>;\n};\n\ntype SpliceRange = {\n start: number;\n removed: number;\n added: string[];\n};\n\ntype ModelState = {\n root: Gio.ListStore;\n rootModels: GObject.Object[];\n model: Gtk.FlattenListModel;\n objects: Map<string, Gtk.StringObject>;\n levels: Map<string, LevelState>;\n tree: Gtk.TreeListModel | null;\n};\n\ntype CollectionModel = {\n model: Gtk.FlattenListModel;\n treeModel: () => Gtk.TreeListModel | null;\n sync: (index: CollectionIndex) => void;\n};\n\nconst OBJECT_CACHE_MAX = 1 << 20;\n\nconst newStore = (): Gio.ListStore => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });\n\nfunction getId(value: GObject.Object | null): string | null {\n const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;\n\n return item instanceof Gtk.StringObject ? item.getString() : null;\n}\n\nfunction objectFor(state: ModelState, id: string): Gtk.StringObject {\n const existing = state.objects.get(id);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const created = Gtk.StringObject.new(id);\n state.objects.set(id, created);\n\n return created;\n}\n\nfunction commonPrefix(previous: string[], next: string[], max: number): number {\n let count = 0;\n\n while (count < max && previous[count] === next[count]) {\n count += 1;\n }\n\n return count;\n}\n\nfunction commonSuffix(previous: string[], next: string[], max: number): number {\n let count = 0;\n\n while (count < max && previous[previous.length - 1 - count] === next[next.length - 1 - count]) {\n count += 1;\n }\n\n return count;\n}\n\nfunction spliceRange(previous: string[], next: string[]): SpliceRange | null {\n const shared = Math.min(previous.length, next.length);\n const start = commonPrefix(previous, next, shared);\n\n if (start === previous.length && start === next.length) {\n return null;\n }\n\n const tail = commonSuffix(previous, next, shared - start);\n\n return { start, removed: previous.length - start - tail, added: next.slice(start, next.length - tail) };\n}\n\nfunction levelFor(state: ModelState, key: string): LevelState {\n const existing = state.levels.get(key);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const created: LevelState = { store: newStore(), ids: [], canExpand: new Map() };\n state.levels.set(key, created);\n\n return created;\n}\n\nfunction refreshExpandable(current: LevelState, level: Level): void {\n const next: Map<string, boolean> = new Map();\n\n for (const [index, id] of level.ids.entries()) {\n const isWanted = level.expandableFlags[index] ?? false;\n const previous = current.canExpand.get(id);\n next.set(id, isWanted);\n\n if (previous !== undefined && previous !== isWanted) {\n current.store.itemsChanged(index, 1, 1);\n }\n }\n\n current.canExpand = next;\n}\n\nfunction didSpliceLevel(state: ModelState, level: Level): boolean {\n const current = levelFor(state, level.key);\n const range = spliceRange(current.ids, level.ids);\n\n if (range === null) {\n return false;\n }\n\n current.store.splice(range.start, range.removed, range.added.map((id) => objectFor(state, id)));\n current.ids = [...level.ids];\n\n return true;\n}\n\nfunction dropUnvisited(state: ModelState, visited: Set<string>): void {\n for (const key of state.levels.keys()) {\n if (!visited.has(key)) {\n state.levels.delete(key);\n }\n }\n}\n\nfunction pruneObjects(state: ModelState, index: CollectionIndex): void {\n if (state.objects.size <= OBJECT_CACHE_MAX) {\n return;\n }\n\n for (const id of state.objects.keys()) {\n if (!index.hasId(id)) {\n state.objects.delete(id);\n }\n }\n}\n\nfunction childStoreFor(state: ModelState, object: GObject.Object): Gio.ListStore | null {\n const id = getId(object);\n\n if (id === null) {\n return null;\n }\n\n return state.levels.get(childLevelKey(id))?.store ?? null;\n}\n\nfunction ensureTree(state: ModelState): Gtk.TreeListModel {\n state.tree ??= Gtk.TreeListModel.new(levelFor(state, ROOT_LEVEL_KEY).store, false, false, (object) =>\n childStoreFor(state, object));\n\n return state.tree;\n}\n\nfunction desiredRootModels(state: ModelState, index: CollectionIndex): GObject.Object[] {\n if (index.isTree) {\n return [ensureTree(state)];\n }\n\n return index.groups.map((level) => levelFor(state, level.key).store);\n}\n\nfunction hasSameModels(previous: GObject.Object[], next: GObject.Object[]): boolean {\n return previous.length === next.length && next.every((model, index) => previous[index] === model);\n}\n\nfunction syncRoot(state: ModelState, index: CollectionIndex): void {\n const next = desiredRootModels(state, index);\n\n if (hasSameModels(state.rootModels, next)) {\n return;\n }\n\n state.root.splice(0, state.rootModels.length, next);\n state.rootModels = next;\n}\n\nfunction syncModel(state: ModelState, index: CollectionIndex): void {\n const levels = [...index.groups, ...index.children.values()];\n const visited: Set<string> = new Set();\n let didChange = false;\n\n for (const level of levels) {\n didChange = didSpliceLevel(state, level) || didChange;\n visited.add(level.key);\n }\n\n if (didChange || visited.size !== state.levels.size) {\n dropUnvisited(state, visited);\n pruneObjects(state, index);\n }\n\n syncRoot(state, index);\n refreshExpandableLevels(state, index, levels);\n}\n\nfunction refreshExpandableLevels(state: ModelState, index: CollectionIndex, levels: Level[]): void {\n if (!index.isTree) {\n return;\n }\n\n for (const level of levels) {\n refreshExpandable(levelFor(state, level.key), level);\n }\n}\n\nfunction createCollectionModel(): CollectionModel {\n const root = newStore();\n\n const state: ModelState = {\n root,\n rootModels: [],\n model: Gtk.FlattenListModel.new(root),\n objects: new Map(),\n levels: new Map(),\n tree: null,\n };\n\n return {\n model: state.model,\n treeModel: () => state.tree,\n sync: (index) => {\n syncModel(state, index);\n },\n };\n}\n\nexport { createCollectionModel, getId, type CollectionModel };\n"]}
|
|
1
|
+
{"version":3,"file":"collection-model.js","sourceRoot":"","sources":["../../src/internal/collection-model.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { registerClass } from \"@gtkx/runtime\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport type { TreeExpansion } from \"./tree-expansion.js\";\nimport { createCollectionIndex, emptyLevel } from \"./collection-index.js\";\nimport { encodePart } from \"./keys.js\";\nimport { adoptIndex, createTreeExpansion, pruneSlots } from \"./tree-expansion.js\";\n\ntype LevelStore = Gio.ListModel & LazyLevelStore;\n\ntype SlotRef = {\n store: LevelStore;\n slot: number;\n};\n\ntype SyncContext = {\n index: CollectionIndex;\n expansion: TreeExpansion;\n};\n\ntype SlotRun = {\n start: number;\n length: number;\n};\n\ntype LevelSync = {\n store: LevelStore;\n level: Level;\n};\n\ntype ModelState = {\n root: Gio.ListStore;\n rootModels: GObject.Object[];\n model: Gtk.FlattenListModel;\n groupStores: LevelStore[];\n trees: Map<LevelStore, Gtk.TreeListModel>;\n treeModels: Gtk.TreeListModel[];\n expansion: TreeExpansion;\n index: CollectionIndex;\n};\n\ntype CollectionModel = {\n model: Gtk.FlattenListModel;\n expansion: TreeExpansion;\n rowAt: (position: number) => Gtk.TreeListRow | null;\n sync: (index: CollectionIndex) => void;\n};\n\nconst STORE_CLASS_KEY = Symbol.for(\"gtkx.components.lazy-level-store\");\nconst SLOTS_KEY = Symbol.for(\"gtkx.components.lazy-level-store.slots\");\nconst EMPTY_INDEX = createCollectionIndex(undefined, undefined, true);\nconst SLOTS = sharedSlots();\n\nconst newRootStore = (): Gio.ListStore => new Gio.ListStore({ itemType: GObject.TYPE_OBJECT });\n\nfunction sharedSlots(): WeakMap<GObject.Object, SlotRef> {\n const cached: unknown = Reflect.get(globalThis, SLOTS_KEY);\n\n if (cached instanceof WeakMap) {\n return cached as WeakMap<GObject.Object, SlotRef>;\n }\n\n const created: WeakMap<GObject.Object, SlotRef> = new WeakMap();\n Reflect.set(globalThis, SLOTS_KEY, created);\n\n return created;\n}\n\nfunction registeredStoreClass(): typeof LazyLevelStore {\n const cached: unknown = Reflect.get(globalThis, STORE_CLASS_KEY);\n\n if (typeof cached === \"function\") {\n return cached as typeof LazyLevelStore;\n }\n\n registerClass(LazyLevelStore, { typeName: \"GtkxLazyLevelStore\", implements: [Gio.ListModel] });\n Reflect.set(globalThis, STORE_CLASS_KEY, LazyLevelStore);\n\n return LazyLevelStore;\n}\n\nfunction slotRefFor(value: GObject.Object | null): SlotRef | null {\n const item = value instanceof Gtk.TreeListRow ? value.getItem() : value;\n\n if (item === null) {\n return null;\n }\n\n const ref = SLOTS.get(item);\n\n return ref === undefined || ref.slot === -1 ? null : ref;\n}\n\nfunction slotPathAt(store: LevelStore, slot: number): string {\n return store.level.path + encodePart(String(slot));\n}\n\nfunction growStore(store: LevelStore): void {\n for (let slot = store.refs.length; slot < store.level.items.length; slot++) {\n store.refs.push({ store, slot });\n store.objects.push(null);\n store.childStores.push(null);\n }\n}\n\nfunction newLevelStore(level: Level): LevelStore {\n const store = new (registeredStoreClass())() as LevelStore;\n store.level = level;\n growStore(store);\n\n return store;\n}\n\nfunction collectFlips(previous: Level, next: Level, overlap: number): Set<number> {\n const flipped: Set<number> = new Set();\n\n for (let slot = 0; slot < overlap; slot++) {\n if ((previous.expandableFlags[slot] ?? false) !== (next.expandableFlags[slot] ?? false)) {\n flipped.add(slot);\n }\n }\n\n return flipped;\n}\n\nfunction pruneFlips(context: SyncContext, store: LevelStore, flipped: Set<number>): void {\n if (flipped.size === 0) {\n return;\n }\n\n pruneSlots(context.expansion, store.level.path, (slot) => flipped.has(slot));\n\n for (const slot of flipped) {\n store.childStores[slot] = null;\n }\n}\n\nfunction detachRefs(store: LevelStore, nextLength: number): void {\n for (let slot = nextLength; slot < store.refs.length; slot++) {\n const ref = store.refs[slot];\n\n if (ref !== undefined) {\n ref.slot = -1;\n }\n }\n}\n\nfunction shrinkStore(context: SyncContext, store: LevelStore, nextLength: number): void {\n if (store.refs.length <= nextLength) {\n return;\n }\n\n detachRefs(store, nextLength);\n pruneSlots(context.expansion, store.level.path, (slot) => slot >= nextLength);\n store.refs.length = nextLength;\n store.objects.length = nextLength;\n store.childStores.length = nextLength;\n}\n\nfunction emitTailSplice(store: LevelStore, previousLength: number, nextLength: number): void {\n if (nextLength < previousLength) {\n store.itemsChanged(nextLength, previousLength - nextLength, 0);\n\n return;\n }\n\n if (nextLength > previousLength) {\n store.itemsChanged(previousLength, 0, nextLength - previousLength);\n }\n}\n\nfunction extendRuns(runs: SlotRun[], slot: number): void {\n const last = runs.at(-1);\n\n if (last !== undefined && last.start + last.length === slot) {\n last.length += 1;\n\n return;\n }\n\n runs.push({ start: slot, length: 1 });\n}\n\nfunction collectFlipRuns(flipped: Set<number>): SlotRun[] {\n const runs: SlotRun[] = [];\n\n for (const slot of flipped) {\n extendRuns(runs, slot);\n }\n\n return runs;\n}\n\nfunction emitFlips(store: LevelStore, flipped: Set<number>): void {\n for (const run of collectFlipRuns(flipped)) {\n store.itemsChanged(run.start, run.length, run.length);\n }\n}\n\nfunction childSync(\n context: SyncContext,\n store: LevelStore,\n slot: number,\n flipped: Set<number>,\n): LevelSync | undefined {\n const child = store.childStores[slot] ?? null;\n\n if (child === null || flipped.has(slot)) {\n return undefined;\n }\n\n const level = context.index.childLevel(store.level, slot);\n\n return level === undefined ? undefined : { store: child, level };\n}\n\nfunction childSyncs(context: SyncContext, store: LevelStore, overlap: number, flipped: Set<number>): LevelSync[] {\n const syncs: LevelSync[] = [];\n\n for (let slot = 0; slot < overlap; slot++) {\n const sync = childSync(context, store, slot, flipped);\n\n if (sync !== undefined) {\n syncs.push(sync);\n }\n }\n\n return syncs;\n}\n\nfunction syncEntry(context: SyncContext, entry: LevelSync): LevelSync[] {\n const { store, level } = entry;\n const previousLength = store.refs.length;\n const overlap = Math.min(previousLength, level.items.length);\n const flipped = collectFlips(store.level, level, overlap);\n store.level = level;\n pruneFlips(context, store, flipped);\n shrinkStore(context, store, level.items.length);\n growStore(store);\n emitTailSplice(store, previousLength, level.items.length);\n emitFlips(store, flipped);\n\n return childSyncs(context, store, overlap, flipped);\n}\n\nfunction pushSyncs(pending: LevelSync[], syncs: LevelSync[]): void {\n for (const sync of syncs) {\n pending.push(sync);\n }\n}\n\nfunction syncLevel(context: SyncContext, store: LevelStore, level: Level): void {\n const pending: LevelSync[] = [{ store, level }];\n\n while (pending.length > 0) {\n const entry = pending.pop();\n\n if (entry !== undefined) {\n pushSyncs(pending, syncEntry(context, entry).toReversed());\n }\n }\n}\n\nfunction ensureChildStore(index: CollectionIndex, store: LevelStore, slot: number): LevelStore | null {\n const existing = store.childStores[slot] ?? null;\n\n if (existing !== null || !(store.level.expandableFlags[slot] ?? false)) {\n return existing;\n }\n\n const level = index.childLevel(store.level, slot);\n\n if (level === undefined) {\n return null;\n }\n\n const created = newLevelStore(level);\n store.childStores[slot] = created;\n\n return created;\n}\n\nfunction childStoreFor(state: ModelState, object: GObject.Object): Gio.ListModel | null {\n const ref = slotRefFor(object);\n\n if (ref === null) {\n return null;\n }\n\n return ensureChildStore(state.index, ref.store, ref.slot);\n}\n\nfunction treeFor(state: ModelState, store: LevelStore): Gtk.TreeListModel {\n return (\n state.trees.get(store) ?? Gtk.TreeListModel.new(store, false, false, (object) => childStoreFor(state, object))\n );\n}\n\nfunction nextTrees(state: ModelState, index: CollectionIndex): Map<LevelStore, Gtk.TreeListModel> {\n if (!index.isTree) {\n return new Map();\n }\n\n return new Map(state.groupStores.map((store) => [store, treeFor(state, store)]));\n}\n\nfunction pruneRebuiltLevels(state: ModelState, next: Map<LevelStore, Gtk.TreeListModel>): void {\n const stores: Set<LevelStore> = new Set([...state.trees.keys(), ...next.keys()]);\n\n for (const store of stores) {\n if (state.trees.get(store) !== next.get(store)) {\n pruneSlots(state.expansion, store.level.path, () => true);\n }\n }\n}\n\nfunction adoptTrees(state: ModelState, index: CollectionIndex): void {\n const next = nextTrees(state, index);\n pruneRebuiltLevels(state, next);\n state.trees = next;\n state.treeModels = next.values().toArray();\n}\n\nfunction desiredRootModels(state: ModelState, index: CollectionIndex): GObject.Object[] {\n adoptTrees(state, index);\n\n return index.isTree ? [...state.treeModels] : [...state.groupStores];\n}\n\nfunction rowAt(state: ModelState, position: number): Gtk.TreeListRow | null {\n let offset = position;\n\n for (const tree of state.treeModels) {\n const count = tree.getNItems();\n\n if (offset < count) {\n return tree.getRow(offset);\n }\n\n offset -= count;\n }\n\n return null;\n}\n\nfunction hasSameModels(previous: GObject.Object[], next: GObject.Object[]): boolean {\n return previous.length === next.length && next.every((model, index) => previous[index] === model);\n}\n\nfunction syncRoot(state: ModelState, index: CollectionIndex): void {\n const next = desiredRootModels(state, index);\n\n if (hasSameModels(state.rootModels, next)) {\n return;\n }\n\n state.root.splice(0, state.rootModels.length, next);\n state.rootModels = next;\n}\n\nfunction adjustGroupStores(state: ModelState, context: SyncContext): void {\n const { groups } = context.index;\n state.groupStores.length = Math.min(state.groupStores.length, groups.length);\n\n for (const level of groups.slice(state.groupStores.length)) {\n state.groupStores.push(newLevelStore(level));\n }\n}\n\nfunction stepGroupStores(state: ModelState, context: SyncContext, surviving: number): void {\n for (const [group, level] of context.index.groups.entries()) {\n const store = state.groupStores[group];\n\n if (store !== undefined && group < surviving) {\n syncLevel(context, store, level);\n }\n }\n}\n\nfunction syncModel(state: ModelState, index: CollectionIndex): void {\n const context: SyncContext = { index, expansion: state.expansion };\n const surviving = Math.min(state.groupStores.length, index.groups.length);\n state.index = index;\n state.expansion.isSyncing = true;\n\n try {\n adjustGroupStores(state, context);\n syncRoot(state, index);\n stepGroupStores(state, context, surviving);\n } finally {\n state.expansion.isSyncing = false;\n }\n\n adoptIndex(state.expansion, index);\n}\n\nfunction createCollectionModel(): CollectionModel {\n registeredStoreClass();\n const root = newRootStore();\n\n const state: ModelState = {\n root,\n rootModels: [],\n model: Gtk.FlattenListModel.new(root),\n groupStores: [],\n trees: new Map(),\n treeModels: [],\n expansion: createTreeExpansion(EMPTY_INDEX),\n index: EMPTY_INDEX,\n };\n\n return {\n model: state.model,\n expansion: state.expansion,\n rowAt: (position) => rowAt(state, position),\n sync: (index) => {\n syncModel(state, index);\n },\n };\n}\n\nclass LazyLevelStore extends GObject.Object implements Gio.ListModelImpl {\n declare itemsChanged: Gio.ListModel[\"itemsChanged\"];\n level: Level = emptyLevel();\n refs: SlotRef[] = [];\n objects: (Gtk.StringObject | null)[] = [];\n childStores: (LevelStore | null)[] = [];\n\n private createItem(position: number, ref: SlotRef): Gtk.StringObject {\n const created = Gtk.StringObject.new(\"\");\n this.objects[position] = created;\n SLOTS.set(created, ref);\n\n return created;\n }\n\n vfuncGetItemType(): bigint {\n return GObject.TYPE_OBJECT;\n }\n\n vfuncGetNItems(): number {\n return this.refs.length;\n }\n\n vfuncGetItem(position: number): GObject.Object | null {\n const ref = this.refs[position];\n\n if (ref === undefined) {\n return null;\n }\n\n return this.objects[position] ?? this.createItem(position, ref);\n }\n}\n\nexport { createCollectionModel, slotPathAt, slotRefFor, type CollectionModel, type SlotRef };\n"]}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
1
|
import type { ListItem } from "../types.js";
|
|
3
2
|
import type { CollectionIndex } from "./collection-index.js";
|
|
4
|
-
import type { CollectionModel } from "./collection-model.js";
|
|
5
|
-
type Collection = {
|
|
3
|
+
import type { CollectionModel, SlotRef } from "./collection-model.js";
|
|
4
|
+
type Collection = Pick<CollectionModel, "model" | "expansion" | "rowAt"> & {
|
|
6
5
|
isTree: boolean;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
itemFor: (id: string) => ListItem | undefined;
|
|
10
|
-
sectionFor: (id: string) => unknown;
|
|
6
|
+
itemAt: (ref: SlotRef) => ListItem | undefined;
|
|
7
|
+
sectionFor: (levelPath: string) => unknown;
|
|
11
8
|
idAt: (position: number) => string | null;
|
|
9
|
+
pathAt: (position: number) => string | null;
|
|
12
10
|
positionFor: (id: string) => number;
|
|
13
11
|
positionsFor: (ids: string[]) => number[];
|
|
14
12
|
};
|
|
15
|
-
declare function
|
|
16
|
-
declare function createCollection(
|
|
17
|
-
export { createCollection,
|
|
13
|
+
declare function isCollectionIdle(collection: Collection): boolean;
|
|
14
|
+
declare function createCollection(collectionModel: CollectionModel, index: CollectionIndex): Collection;
|
|
15
|
+
export { createCollection, isCollectionIdle, type Collection };
|
|
18
16
|
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../src/internal/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAItE,KAAK,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC,GAAG;IACvE,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,CAAC;IAC/C,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;CAC7C,CAAC;AAgDF,iBAAS,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAIzD;AAED,iBAAS,gBAAgB,CAAC,eAAe,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,UAAU,CAa9F;AAED,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,CAAC"}
|
|
@@ -1,64 +1,54 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (
|
|
6
|
-
return;
|
|
1
|
+
import { slotPathAt, slotRefFor } from "./collection-model.js";
|
|
2
|
+
import { findPositions } from "./tree-order.js";
|
|
3
|
+
const NO_POSITIONS = [];
|
|
4
|
+
function positionsFor(collectionModel, ids) {
|
|
5
|
+
if (ids.length === 0) {
|
|
6
|
+
return NO_POSITIONS;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
const { expansion } = collectionModel;
|
|
9
|
+
return findPositions(expansion.index, expansion.slots, new Set(ids));
|
|
9
10
|
}
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
11
|
+
function positionFor(collectionModel, id) {
|
|
12
|
+
const [first = -1] = positionsFor(collectionModel, [id]);
|
|
13
|
+
return first;
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
out.push(position);
|
|
15
|
+
function refAt(collectionModel, position) {
|
|
16
|
+
if (position < 0) {
|
|
17
|
+
return null;
|
|
19
18
|
}
|
|
19
|
+
return slotRefFor(collectionModel.model.getItem(position));
|
|
20
20
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
const positions = [];
|
|
24
|
-
const count = tree.getNItems();
|
|
25
|
-
for (let position = 0; position < count; position++) {
|
|
26
|
-
collectWanted(tree.getItem(position), position, wanted, positions);
|
|
27
|
-
}
|
|
28
|
-
return positions;
|
|
21
|
+
function itemAt(index, ref) {
|
|
22
|
+
return index.itemAt(ref.store.level.path, ref.slot);
|
|
29
23
|
}
|
|
30
|
-
function
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const position = index.positionFor(id);
|
|
34
|
-
if (position >= 0) {
|
|
35
|
-
positions.push(position);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return positions.toSorted(ascending);
|
|
24
|
+
function idAt(collectionModel, index, position) {
|
|
25
|
+
const ref = refAt(collectionModel, position);
|
|
26
|
+
return ref === null ? null : (itemAt(index, ref)?.id ?? null);
|
|
39
27
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
28
|
+
function pathAt(collectionModel, position) {
|
|
29
|
+
const ref = refAt(collectionModel, position);
|
|
30
|
+
if (ref === null) {
|
|
31
|
+
return null;
|
|
43
32
|
}
|
|
44
|
-
|
|
45
|
-
return tree === null ? [] : scanPositions(tree, ids);
|
|
33
|
+
return slotPathAt(ref.store, ref.slot);
|
|
46
34
|
}
|
|
47
|
-
function
|
|
48
|
-
const
|
|
49
|
-
return
|
|
35
|
+
function isCollectionIdle(collection) {
|
|
36
|
+
const { expansion } = collection;
|
|
37
|
+
return !expansion.isApplying && !expansion.isSyncing;
|
|
50
38
|
}
|
|
51
|
-
function createCollection(
|
|
39
|
+
function createCollection(collectionModel, index) {
|
|
52
40
|
return {
|
|
41
|
+
model: collectionModel.model,
|
|
42
|
+
expansion: collectionModel.expansion,
|
|
53
43
|
isTree: index.isTree,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
itemFor: index.itemFor,
|
|
44
|
+
rowAt: collectionModel.rowAt,
|
|
45
|
+
itemAt: (ref) => itemAt(index, ref),
|
|
57
46
|
sectionFor: index.sectionFor,
|
|
58
|
-
idAt: (position) =>
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
idAt: (position) => idAt(collectionModel, index, position),
|
|
48
|
+
pathAt: (position) => pathAt(collectionModel, position),
|
|
49
|
+
positionFor: (id) => positionFor(collectionModel, id),
|
|
50
|
+
positionsFor: (ids) => positionsFor(collectionModel, ids),
|
|
61
51
|
};
|
|
62
52
|
}
|
|
63
|
-
export { createCollection,
|
|
53
|
+
export { createCollection, isCollectionIdle };
|
|
64
54
|
//# sourceMappingURL=collection.js.map
|