@gtkx/react 0.17.2 → 0.18.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 +7 -7
- package/dist/factory.d.ts +0 -1
- package/dist/factory.js +21 -8
- package/dist/generated/internal.d.ts +4 -51
- package/dist/generated/internal.js +626 -412
- package/dist/generated/jsx.d.ts +453 -958
- package/dist/host-config.d.ts +1 -1
- package/dist/host-config.js +18 -23
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/jsx.d.ts +579 -302
- package/dist/jsx.js +37 -179
- package/dist/metadata.d.ts +3 -0
- package/dist/metadata.js +26 -0
- package/dist/node.d.ts +20 -12
- package/dist/node.js +72 -17
- package/dist/nodes/adjustable.d.ts +3 -16
- package/dist/nodes/adjustable.js +5 -22
- package/dist/nodes/alert-dialog-response.d.ts +14 -1
- package/dist/nodes/alert-dialog-response.js +36 -62
- package/dist/nodes/animation.d.ts +37 -1
- package/dist/nodes/animation.js +162 -105
- package/dist/nodes/application.d.ts +11 -1
- package/dist/nodes/application.js +17 -38
- package/dist/nodes/calendar.d.ts +13 -0
- package/dist/nodes/calendar.js +10 -16
- package/dist/nodes/color-dialog-button.d.ts +13 -0
- package/dist/nodes/color-dialog-button.js +10 -38
- package/dist/nodes/column-view-column.d.ts +13 -11
- package/dist/nodes/column-view-column.js +27 -23
- package/dist/nodes/column-view.d.ts +31 -0
- package/dist/nodes/column-view.js +44 -44
- package/dist/nodes/container-slot.d.ts +15 -0
- package/dist/nodes/container-slot.js +68 -0
- package/dist/nodes/dialog.d.ts +6 -8
- package/dist/nodes/dialog.js +12 -13
- package/dist/nodes/drawing-area.d.ts +12 -0
- package/dist/nodes/drawing-area.js +24 -24
- package/dist/nodes/drop-down.d.ts +22 -0
- package/dist/nodes/drop-down.js +72 -0
- package/dist/nodes/event-controller.d.ts +8 -17
- package/dist/nodes/event-controller.js +20 -42
- package/dist/nodes/fixed-child.d.ts +18 -1
- package/dist/nodes/fixed-child.js +52 -36
- package/dist/nodes/font-dialog-button.d.ts +13 -0
- package/dist/nodes/font-dialog-button.js +12 -35
- package/dist/nodes/grid-child.d.ts +17 -1
- package/dist/nodes/grid-child.js +57 -37
- package/dist/nodes/grid-view.d.ts +24 -0
- package/dist/nodes/grid-view.js +73 -0
- package/dist/nodes/internal/base-item-renderer.d.ts +7 -9
- package/dist/nodes/internal/base-item-renderer.js +15 -18
- package/dist/nodes/internal/grid-item-renderer.d.ts +17 -0
- package/dist/nodes/internal/grid-item-renderer.js +59 -0
- package/dist/nodes/internal/list-item-renderer.d.ts +14 -9
- package/dist/nodes/internal/list-item-renderer.js +96 -35
- package/dist/nodes/internal/list-store.d.ts +5 -0
- package/dist/nodes/internal/list-store.js +39 -9
- package/dist/nodes/internal/predicates.d.ts +4 -19
- package/dist/nodes/internal/predicates.js +1 -20
- package/dist/nodes/internal/props.d.ts +5 -0
- package/dist/nodes/internal/props.js +42 -0
- package/dist/nodes/internal/{selection-model.d.ts → selection-model-controller.d.ts} +4 -9
- package/dist/nodes/internal/{selection-model.js → selection-model-controller.js} +6 -15
- package/dist/nodes/internal/signal-store.js +12 -5
- package/dist/nodes/internal/simple-list-store.d.ts +5 -0
- package/dist/nodes/internal/simple-list-store.js +42 -13
- package/dist/nodes/internal/text-buffer-controller.d.ts +4 -12
- package/dist/nodes/internal/text-buffer-controller.js +32 -33
- package/dist/nodes/internal/tree-store.d.ts +7 -0
- package/dist/nodes/internal/tree-store.js +75 -18
- package/dist/nodes/internal/widget.d.ts +7 -0
- package/dist/nodes/internal/widget.js +68 -0
- package/dist/nodes/level-bar.d.ts +10 -0
- package/dist/nodes/level-bar.js +11 -22
- package/dist/nodes/list-item.d.ts +17 -9
- package/dist/nodes/list-item.js +67 -12
- package/dist/nodes/list-view.d.ts +23 -0
- package/dist/nodes/list-view.js +27 -31
- package/dist/nodes/menu.d.ts +2 -4
- package/dist/nodes/menu.js +0 -6
- package/dist/nodes/models/grid.d.ts +27 -0
- package/dist/nodes/models/grid.js +68 -0
- package/dist/nodes/models/list.d.ts +15 -13
- package/dist/nodes/models/list.js +48 -26
- package/dist/nodes/models/menu.d.ts +15 -16
- package/dist/nodes/models/menu.js +63 -93
- package/dist/nodes/navigation-page.d.ts +16 -10
- package/dist/nodes/navigation-page.js +108 -31
- package/dist/nodes/navigation-view.d.ts +15 -0
- package/dist/nodes/navigation-view.js +15 -65
- package/dist/nodes/notebook-page-tab.d.ts +10 -12
- package/dist/nodes/notebook-page-tab.js +24 -27
- package/dist/nodes/notebook-page.d.ts +19 -16
- package/dist/nodes/notebook-page.js +75 -56
- package/dist/nodes/notebook.d.ts +10 -1
- package/dist/nodes/notebook.js +10 -22
- package/dist/nodes/overlay-child.d.ts +17 -1
- package/dist/nodes/overlay-child.js +53 -75
- package/dist/nodes/popover-menu.d.ts +15 -0
- package/dist/nodes/popover-menu.js +13 -26
- package/dist/nodes/scale.d.ts +8 -0
- package/dist/nodes/scale.js +2 -11
- package/dist/nodes/scrolled-window.d.ts +9 -0
- package/dist/nodes/scrolled-window.js +5 -11
- package/dist/nodes/search-bar.d.ts +9 -0
- package/dist/nodes/search-bar.js +8 -33
- package/dist/nodes/shortcut-controller.d.ts +9 -1
- package/dist/nodes/shortcut-controller.js +12 -25
- package/dist/nodes/shortcut.d.ts +11 -33
- package/dist/nodes/shortcut.js +19 -15
- package/dist/nodes/slot.d.ts +16 -15
- package/dist/nodes/slot.js +63 -57
- package/dist/nodes/source-view.d.ts +16 -0
- package/dist/nodes/source-view.js +44 -44
- package/dist/nodes/stack-page.d.ts +21 -1
- package/dist/nodes/stack-page.js +68 -17
- package/dist/nodes/stack.d.ts +11 -0
- package/dist/nodes/stack.js +8 -26
- package/dist/nodes/text-anchor.d.ts +11 -30
- package/dist/nodes/text-anchor.js +20 -22
- package/dist/nodes/text-content.d.ts +1 -0
- package/dist/nodes/text-content.js +1 -1
- package/dist/nodes/text-paintable.d.ts +10 -15
- package/dist/nodes/text-paintable.js +16 -9
- package/dist/nodes/text-segment.d.ts +12 -10
- package/dist/nodes/text-segment.js +19 -11
- package/dist/nodes/text-tag.d.ts +20 -119
- package/dist/nodes/text-tag.js +153 -119
- package/dist/nodes/text-view.d.ts +13 -18
- package/dist/nodes/text-view.js +17 -17
- package/dist/nodes/toggle-group.d.ts +9 -0
- package/dist/nodes/toggle-group.js +8 -33
- package/dist/nodes/toggle.d.ts +15 -1
- package/dist/nodes/toggle.js +34 -52
- package/dist/nodes/virtual.d.ts +3 -10
- package/dist/nodes/virtual.js +1 -14
- package/dist/nodes/web-view.d.ts +9 -0
- package/dist/nodes/web-view.js +10 -24
- package/dist/nodes/widget.d.ts +17 -13
- package/dist/nodes/widget.js +185 -112
- package/dist/nodes/window.d.ts +20 -21
- package/dist/nodes/window.js +54 -35
- package/dist/registry.d.ts +17 -6
- package/dist/registry.js +104 -5
- package/dist/render.d.ts +1 -10
- package/dist/render.js +1 -13
- package/package.json +6 -6
- package/dist/animation/css-builder.d.ts +0 -3
- package/dist/animation/css-builder.js +0 -53
- package/dist/animation/types.d.ts +0 -120
- package/dist/animation/types.js +0 -1
- package/dist/nodes/abstract/positional-child.d.ts +0 -9
- package/dist/nodes/abstract/positional-child.js +0 -29
- package/dist/nodes/abstract/virtual-container.d.ts +0 -21
- package/dist/nodes/abstract/virtual-container.js +0 -68
- package/dist/nodes/abstract/virtual-single-child.d.ts +0 -18
- package/dist/nodes/abstract/virtual-single-child.js +0 -55
- package/dist/nodes/action-row-child.d.ts +0 -1
- package/dist/nodes/action-row-child.js +0 -30
- package/dist/nodes/autowrapped.d.ts +0 -1
- package/dist/nodes/autowrapped.js +0 -115
- package/dist/nodes/expander-row-child.d.ts +0 -1
- package/dist/nodes/expander-row-child.js +0 -30
- package/dist/nodes/grid.d.ts +0 -1
- package/dist/nodes/grid.js +0 -41
- package/dist/nodes/index.d.ts +0 -56
- package/dist/nodes/index.js +0 -56
- package/dist/nodes/internal/child-attachment.d.ts +0 -26
- package/dist/nodes/internal/child-attachment.js +0 -48
- package/dist/nodes/internal/deferred-action.d.ts +0 -9
- package/dist/nodes/internal/deferred-action.js +0 -22
- package/dist/nodes/internal/text-tag-styles.d.ts +0 -43
- package/dist/nodes/internal/text-tag-styles.js +0 -52
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +0 -26
- package/dist/nodes/internal/tree-list-item-renderer.js +0 -134
- package/dist/nodes/internal/utils.d.ts +0 -12
- package/dist/nodes/internal/utils.js +0 -92
- package/dist/nodes/models/tree-list.d.ts +0 -28
- package/dist/nodes/models/tree-list.js +0 -113
- package/dist/nodes/pack-child.d.ts +0 -1
- package/dist/nodes/pack-child.js +0 -30
- package/dist/nodes/simple-list-item.d.ts +0 -9
- package/dist/nodes/simple-list-item.js +0 -9
- package/dist/nodes/simple-list-view.d.ts +0 -1
- package/dist/nodes/simple-list-view.js +0 -74
- package/dist/nodes/toolbar-child.d.ts +0 -1
- package/dist/nodes/toolbar-child.js +0 -30
- package/dist/nodes/tree-list-item.d.ts +0 -22
- package/dist/nodes/tree-list-item.js +0 -90
- package/dist/nodes/tree-list-view.d.ts +0 -1
- package/dist/nodes/tree-list-view.js +0 -77
- package/dist/scheduler.d.ts +0 -26
- package/dist/scheduler.js +0 -42
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getNativeId } from "@gtkx/ffi";
|
|
2
1
|
import * as GObject from "@gtkx/ffi/gobject";
|
|
3
2
|
const LIFECYCLE_SIGNALS = new Set([
|
|
4
3
|
"realize",
|
|
@@ -15,6 +14,16 @@ const LIFECYCLE_SIGNALS = new Set([
|
|
|
15
14
|
"unbind",
|
|
16
15
|
"teardown",
|
|
17
16
|
]);
|
|
17
|
+
const signalKeyCache = new WeakMap();
|
|
18
|
+
let nextSignalObjId = 0;
|
|
19
|
+
function getSignalKey(obj, signal) {
|
|
20
|
+
let objKey = signalKeyCache.get(obj);
|
|
21
|
+
if (!objKey) {
|
|
22
|
+
objKey = String(nextSignalObjId++);
|
|
23
|
+
signalKeyCache.set(obj, objKey);
|
|
24
|
+
}
|
|
25
|
+
return `${objKey}:${signal}`;
|
|
26
|
+
}
|
|
18
27
|
export class SignalStore {
|
|
19
28
|
ownerHandlers = new Map();
|
|
20
29
|
blockDepth = 0;
|
|
@@ -36,8 +45,7 @@ export class SignalStore {
|
|
|
36
45
|
};
|
|
37
46
|
}
|
|
38
47
|
disconnect(owner, obj, signal) {
|
|
39
|
-
const
|
|
40
|
-
const key = `${objectId}:${signal}`;
|
|
48
|
+
const key = getSignalKey(obj, signal);
|
|
41
49
|
const ownerMap = this.ownerHandlers.get(owner);
|
|
42
50
|
const existing = ownerMap?.get(key);
|
|
43
51
|
if (existing) {
|
|
@@ -46,8 +54,7 @@ export class SignalStore {
|
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
connect(owner, obj, signal, handler, blockable) {
|
|
49
|
-
const
|
|
50
|
-
const key = `${objectId}:${signal}`;
|
|
57
|
+
const key = getSignalKey(obj, signal);
|
|
51
58
|
const wrappedHandler = this.wrapHandler(handler, signal, blockable);
|
|
52
59
|
const handlerId = obj.connect(signal, wrappedHandler);
|
|
53
60
|
this.getOwnerMap(owner).set(key, { obj, handlerId });
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
export declare class SimpleListStore {
|
|
3
3
|
private ids;
|
|
4
|
+
private idToIndex;
|
|
4
5
|
private model;
|
|
6
|
+
private pendingBatch;
|
|
7
|
+
beginBatch(): void;
|
|
8
|
+
flushBatch(): void;
|
|
5
9
|
addItem(id: string, label: string): void;
|
|
6
10
|
appendItem(id: string, label: string): void;
|
|
7
11
|
removeItem(id: string): void;
|
|
@@ -11,4 +15,5 @@ export declare class SimpleListStore {
|
|
|
11
15
|
getIdAtIndex(index: number): string | null;
|
|
12
16
|
getIndexById(id: string): number | null;
|
|
13
17
|
getModel(): Gtk.StringList;
|
|
18
|
+
private rebuildIndices;
|
|
14
19
|
}
|
|
@@ -1,57 +1,86 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
export class SimpleListStore {
|
|
3
3
|
ids = [];
|
|
4
|
+
idToIndex = new Map();
|
|
4
5
|
model = new Gtk.StringList();
|
|
6
|
+
pendingBatch = null;
|
|
7
|
+
beginBatch() {
|
|
8
|
+
this.pendingBatch = [];
|
|
9
|
+
}
|
|
10
|
+
flushBatch() {
|
|
11
|
+
const batch = this.pendingBatch;
|
|
12
|
+
this.pendingBatch = null;
|
|
13
|
+
if (batch && batch.length > 0) {
|
|
14
|
+
this.model.splice(0, 0, batch);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
5
17
|
addItem(id, label) {
|
|
18
|
+
this.idToIndex.set(id, this.ids.length);
|
|
6
19
|
this.ids.push(id);
|
|
7
|
-
this.
|
|
20
|
+
if (this.pendingBatch) {
|
|
21
|
+
this.pendingBatch.push(label);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.model.append(label);
|
|
25
|
+
}
|
|
8
26
|
}
|
|
9
27
|
appendItem(id, label) {
|
|
10
|
-
const existingIndex = this.
|
|
11
|
-
if (existingIndex
|
|
28
|
+
const existingIndex = this.idToIndex.get(id);
|
|
29
|
+
if (existingIndex !== undefined) {
|
|
12
30
|
this.model.remove(existingIndex);
|
|
13
31
|
this.ids.splice(existingIndex, 1);
|
|
32
|
+
this.rebuildIndices(existingIndex);
|
|
14
33
|
}
|
|
34
|
+
this.idToIndex.set(id, this.ids.length);
|
|
15
35
|
this.ids.push(id);
|
|
16
36
|
this.model.append(label);
|
|
17
37
|
}
|
|
18
38
|
removeItem(id) {
|
|
19
|
-
const index = this.
|
|
20
|
-
if (index
|
|
39
|
+
const index = this.idToIndex.get(id);
|
|
40
|
+
if (index === undefined)
|
|
21
41
|
return;
|
|
22
|
-
}
|
|
23
42
|
this.model.remove(index);
|
|
24
43
|
this.ids.splice(index, 1);
|
|
44
|
+
this.idToIndex.delete(id);
|
|
45
|
+
this.rebuildIndices(index);
|
|
25
46
|
}
|
|
26
47
|
insertItemBefore(id, beforeId, label) {
|
|
27
|
-
const beforeIndex = this.
|
|
28
|
-
if (beforeIndex
|
|
48
|
+
const beforeIndex = this.idToIndex.get(beforeId);
|
|
49
|
+
if (beforeIndex === undefined) {
|
|
29
50
|
this.addItem(id, label);
|
|
30
51
|
}
|
|
31
52
|
else {
|
|
32
53
|
this.ids.splice(beforeIndex, 0, id);
|
|
54
|
+
this.rebuildIndices(beforeIndex);
|
|
33
55
|
this.model.splice(beforeIndex, 0, [label]);
|
|
34
56
|
}
|
|
35
57
|
}
|
|
36
58
|
updateItem(id, label) {
|
|
37
|
-
const index = this.
|
|
38
|
-
if (index
|
|
59
|
+
const index = this.idToIndex.get(id);
|
|
60
|
+
if (index === undefined) {
|
|
39
61
|
this.addItem(id, label);
|
|
40
62
|
return;
|
|
41
63
|
}
|
|
42
64
|
this.model.splice(index, 1, [label]);
|
|
43
65
|
}
|
|
44
66
|
getItem(id) {
|
|
45
|
-
|
|
67
|
+
const index = this.idToIndex.get(id);
|
|
68
|
+
if (index === undefined)
|
|
69
|
+
return null;
|
|
70
|
+
return this.model.getString(index);
|
|
46
71
|
}
|
|
47
72
|
getIdAtIndex(index) {
|
|
48
73
|
return this.ids[index] ?? null;
|
|
49
74
|
}
|
|
50
75
|
getIndexById(id) {
|
|
51
|
-
|
|
52
|
-
return index >= 0 ? index : null;
|
|
76
|
+
return this.idToIndex.get(id) ?? null;
|
|
53
77
|
}
|
|
54
78
|
getModel() {
|
|
55
79
|
return this.model;
|
|
56
80
|
}
|
|
81
|
+
rebuildIndices(fromIndex) {
|
|
82
|
+
for (let i = fromIndex; i < this.ids.length; i++) {
|
|
83
|
+
this.idToIndex.set(this.ids[i], i);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
57
86
|
}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { GtkTextViewProps } from "../../jsx.js";
|
|
2
3
|
import type { Node } from "../../node.js";
|
|
3
4
|
import type { TextContentChild, TextContentParent } from "../text-content.js";
|
|
4
5
|
import { TextSegmentNode } from "../text-segment.js";
|
|
5
|
-
type BufferCallbackProps =
|
|
6
|
-
|
|
7
|
-
onTextInserted?: ((buffer: Gtk.TextBuffer, offset: number, text: string) => void) | null;
|
|
8
|
-
onTextDeleted?: ((buffer: Gtk.TextBuffer, startOffset: number, endOffset: number) => void) | null;
|
|
9
|
-
onCanUndoChanged?: ((canUndo: boolean) => void) | null;
|
|
10
|
-
onCanRedoChanged?: ((canRedo: boolean) => void) | null;
|
|
11
|
-
};
|
|
12
|
-
type BufferProps = {
|
|
13
|
-
enableUndo?: boolean;
|
|
14
|
-
} & BufferCallbackProps;
|
|
6
|
+
type BufferCallbackProps = Pick<GtkTextViewProps, "onBufferChanged" | "onTextInserted" | "onTextDeleted" | "onCanUndoChanged" | "onCanRedoChanged">;
|
|
7
|
+
type BufferProps = Pick<GtkTextViewProps, "enableUndo"> & BufferCallbackProps;
|
|
15
8
|
export declare class TextBufferController<TBuffer extends Gtk.TextBuffer = Gtk.TextBuffer> {
|
|
16
9
|
private readonly owner;
|
|
17
10
|
private readonly container;
|
|
@@ -23,12 +16,11 @@ export declare class TextBufferController<TBuffer extends Gtk.TextBuffer = Gtk.T
|
|
|
23
16
|
hasTextChildren(): boolean;
|
|
24
17
|
ensureBuffer(): TBuffer;
|
|
25
18
|
applyOwnProps(oldProps: BufferProps | null, newProps: BufferProps): void;
|
|
26
|
-
private
|
|
19
|
+
private setSignalHandlersChanged;
|
|
27
20
|
isTextContentChild(child: Node): child is TextContentChild;
|
|
28
21
|
appendChild(child: TextContentChild): void;
|
|
29
22
|
insertBefore(child: TextContentChild, before: TextContentChild): void;
|
|
30
23
|
removeChild(child: TextContentChild): void;
|
|
31
|
-
private setChildParent;
|
|
32
24
|
private getTotalLength;
|
|
33
25
|
private insertTextAtOffset;
|
|
34
26
|
private deleteTextAtRange;
|
|
@@ -3,7 +3,7 @@ import { TextAnchorNode } from "../text-anchor.js";
|
|
|
3
3
|
import { TextPaintableNode } from "../text-paintable.js";
|
|
4
4
|
import { TextSegmentNode } from "../text-segment.js";
|
|
5
5
|
import { TextTagNode } from "../text-tag.js";
|
|
6
|
-
import { hasChanged } from "./
|
|
6
|
+
import { hasChanged } from "./props.js";
|
|
7
7
|
export class TextBufferController {
|
|
8
8
|
owner;
|
|
9
9
|
container;
|
|
@@ -48,10 +48,10 @@ export class TextBufferController {
|
|
|
48
48
|
hasChanged(oldProps, newProps, "onCanUndoChanged") ||
|
|
49
49
|
hasChanged(oldProps, newProps, "onCanRedoChanged");
|
|
50
50
|
if (signalHandlersChanged) {
|
|
51
|
-
this.
|
|
51
|
+
this.setSignalHandlersChanged(newProps);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
setSignalHandlersChanged(callbacks) {
|
|
55
55
|
if (!this.buffer)
|
|
56
56
|
return;
|
|
57
57
|
const buffer = this.buffer;
|
|
@@ -77,7 +77,7 @@ export class TextBufferController {
|
|
|
77
77
|
const wasMoved = this.textChildren.indexOf(child) !== -1;
|
|
78
78
|
if (wasMoved) {
|
|
79
79
|
const existingIndex = this.textChildren.indexOf(child);
|
|
80
|
-
const oldOffset = child.
|
|
80
|
+
const oldOffset = child.getBufferOffset();
|
|
81
81
|
const oldLength = child.getLength();
|
|
82
82
|
this.textChildren.splice(existingIndex, 1);
|
|
83
83
|
if (oldLength > 0) {
|
|
@@ -87,8 +87,7 @@ export class TextBufferController {
|
|
|
87
87
|
}
|
|
88
88
|
const offset = this.getTotalLength();
|
|
89
89
|
this.textChildren.push(child);
|
|
90
|
-
child.
|
|
91
|
-
this.setChildParent(child);
|
|
90
|
+
child.setBufferOffset(offset);
|
|
92
91
|
if (child instanceof TextSegmentNode) {
|
|
93
92
|
this.insertTextAtOffset(child.getText(), offset);
|
|
94
93
|
}
|
|
@@ -114,7 +113,7 @@ export class TextBufferController {
|
|
|
114
113
|
const buffer = this.ensureBuffer();
|
|
115
114
|
const existingIndex = this.textChildren.indexOf(child);
|
|
116
115
|
if (existingIndex !== -1) {
|
|
117
|
-
const oldOffset = child.
|
|
116
|
+
const oldOffset = child.getBufferOffset();
|
|
118
117
|
const oldLength = child.getLength();
|
|
119
118
|
this.textChildren.splice(existingIndex, 1);
|
|
120
119
|
if (oldLength > 0) {
|
|
@@ -131,8 +130,7 @@ export class TextBufferController {
|
|
|
131
130
|
offset += c.getLength();
|
|
132
131
|
}
|
|
133
132
|
this.textChildren.splice(insertIndex, 0, child);
|
|
134
|
-
child.
|
|
135
|
-
this.setChildParent(child);
|
|
133
|
+
child.setBufferOffset(offset);
|
|
136
134
|
if (child instanceof TextSegmentNode) {
|
|
137
135
|
this.insertTextAtOffset(child.getText(), offset);
|
|
138
136
|
}
|
|
@@ -156,7 +154,7 @@ export class TextBufferController {
|
|
|
156
154
|
const index = this.textChildren.indexOf(child);
|
|
157
155
|
if (index === -1)
|
|
158
156
|
return;
|
|
159
|
-
const offset = child.
|
|
157
|
+
const offset = child.getBufferOffset();
|
|
160
158
|
const length = child.getLength();
|
|
161
159
|
this.textChildren.splice(index, 1);
|
|
162
160
|
if (this.buffer && length > 0) {
|
|
@@ -165,11 +163,6 @@ export class TextBufferController {
|
|
|
165
163
|
this.updateChildOffsets(index);
|
|
166
164
|
this.reapplyTagsFromOffset(offset);
|
|
167
165
|
}
|
|
168
|
-
setChildParent(child) {
|
|
169
|
-
if (child instanceof TextSegmentNode || child instanceof TextTagNode) {
|
|
170
|
-
child.setParent(this.owner);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
166
|
getTotalLength() {
|
|
174
167
|
let length = 0;
|
|
175
168
|
for (const child of this.textChildren) {
|
|
@@ -205,7 +198,7 @@ export class TextBufferController {
|
|
|
205
198
|
for (let i = startIndex; i < this.textChildren.length; i++) {
|
|
206
199
|
const child = this.textChildren[i];
|
|
207
200
|
if (child) {
|
|
208
|
-
child.
|
|
201
|
+
child.setBufferOffset(offset);
|
|
209
202
|
offset += child.getLength();
|
|
210
203
|
}
|
|
211
204
|
}
|
|
@@ -214,20 +207,20 @@ export class TextBufferController {
|
|
|
214
207
|
for (const child of children) {
|
|
215
208
|
if (child instanceof TextTagNode) {
|
|
216
209
|
child.reapplyTag();
|
|
217
|
-
this.reapplyAllTagsRecursive(child.
|
|
210
|
+
this.reapplyAllTagsRecursive(child.children);
|
|
218
211
|
}
|
|
219
212
|
}
|
|
220
213
|
}
|
|
221
214
|
reapplyTagsFromOffset(fromOffset) {
|
|
222
215
|
for (const child of this.textChildren) {
|
|
223
216
|
if (child instanceof TextTagNode) {
|
|
224
|
-
if (child.
|
|
217
|
+
if (child.getBufferOffset() >= fromOffset) {
|
|
225
218
|
child.reapplyTag();
|
|
226
|
-
this.reapplyAllTagsRecursive(child.
|
|
219
|
+
this.reapplyAllTagsRecursive(child.children);
|
|
227
220
|
}
|
|
228
|
-
else if (child.
|
|
221
|
+
else if (child.getBufferOffset() + child.getLength() > fromOffset) {
|
|
229
222
|
child.reapplyTag();
|
|
230
|
-
this.reapplyAllTagsRecursive(child.
|
|
223
|
+
this.reapplyAllTagsRecursive(child.children);
|
|
231
224
|
}
|
|
232
225
|
}
|
|
233
226
|
}
|
|
@@ -236,7 +229,7 @@ export class TextBufferController {
|
|
|
236
229
|
for (let i = 0; i < this.textChildren.length; i++) {
|
|
237
230
|
const child = this.textChildren[i];
|
|
238
231
|
if (child) {
|
|
239
|
-
const start = child.
|
|
232
|
+
const start = child.getBufferOffset();
|
|
240
233
|
const end = start + child.getLength();
|
|
241
234
|
if (offset >= start && offset <= end) {
|
|
242
235
|
return i;
|
|
@@ -250,18 +243,18 @@ export class TextBufferController {
|
|
|
250
243
|
return;
|
|
251
244
|
const text = child.getText();
|
|
252
245
|
if (text.length > 0) {
|
|
253
|
-
this.insertTextAtOffset(text, child.
|
|
246
|
+
this.insertTextAtOffset(text, child.getBufferOffset());
|
|
254
247
|
}
|
|
255
|
-
const containingIndex = this.findDirectChildContaining(child.
|
|
248
|
+
const containingIndex = this.findDirectChildContaining(child.getBufferOffset());
|
|
256
249
|
if (containingIndex !== -1) {
|
|
257
250
|
this.updateChildOffsets(containingIndex + 1);
|
|
258
251
|
}
|
|
259
|
-
this.reapplyTagsFromOffset(child.
|
|
252
|
+
this.reapplyTagsFromOffset(child.getBufferOffset());
|
|
260
253
|
}
|
|
261
254
|
onChildRemoved(child) {
|
|
262
255
|
if (!this.buffer)
|
|
263
256
|
return;
|
|
264
|
-
const offset = child.
|
|
257
|
+
const offset = child.getBufferOffset();
|
|
265
258
|
const length = child.getLength();
|
|
266
259
|
if (length > 0) {
|
|
267
260
|
this.deleteTextAtRange(offset, offset + length);
|
|
@@ -275,13 +268,19 @@ export class TextBufferController {
|
|
|
275
268
|
onChildTextChanged(child, oldLength, _newLength) {
|
|
276
269
|
if (!this.buffer)
|
|
277
270
|
return;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this.
|
|
271
|
+
this.owner.signalStore.blockAll();
|
|
272
|
+
try {
|
|
273
|
+
const offset = child.getBufferOffset();
|
|
274
|
+
this.deleteTextAtRange(offset, offset + oldLength);
|
|
275
|
+
this.insertTextAtOffset(child.getText(), offset);
|
|
276
|
+
const containingIndex = this.findDirectChildContaining(offset);
|
|
277
|
+
if (containingIndex !== -1) {
|
|
278
|
+
this.updateChildOffsets(containingIndex + 1);
|
|
279
|
+
}
|
|
280
|
+
this.reapplyTagsFromOffset(offset);
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
this.owner.signalStore.unblockAll();
|
|
284
284
|
}
|
|
285
|
-
this.reapplyTagsFromOffset(offset);
|
|
286
285
|
}
|
|
287
286
|
}
|
|
@@ -8,12 +8,17 @@ export type TreeItemData<T = unknown> = {
|
|
|
8
8
|
};
|
|
9
9
|
export declare class TreeStore {
|
|
10
10
|
private rootIds;
|
|
11
|
+
private rootIdToIndex;
|
|
11
12
|
private children;
|
|
13
|
+
private childIdToIndex;
|
|
12
14
|
private rootModel;
|
|
13
15
|
private childModels;
|
|
14
16
|
private items;
|
|
15
17
|
private onItemUpdated;
|
|
18
|
+
private pendingBatch;
|
|
16
19
|
setOnItemUpdated(callback: TreeItemUpdatedCallback | null): void;
|
|
20
|
+
beginBatch(): void;
|
|
21
|
+
flushBatch(): void;
|
|
17
22
|
updateItem(id: string, item: TreeItemData): void;
|
|
18
23
|
addItem(id: string, data: TreeItemData, parentId?: string): void;
|
|
19
24
|
removeItem(id: string, parentId?: string): void;
|
|
@@ -22,4 +27,6 @@ export declare class TreeStore {
|
|
|
22
27
|
getRootModel(): Gtk.StringList;
|
|
23
28
|
getChildrenModel(parentId: string): Gtk.StringList | null;
|
|
24
29
|
hasChildren(parentId: string): boolean;
|
|
30
|
+
private rebuildRootIndices;
|
|
31
|
+
private rebuildChildIndices;
|
|
25
32
|
}
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
export class TreeStore {
|
|
3
3
|
rootIds = [];
|
|
4
|
+
rootIdToIndex = new Map();
|
|
4
5
|
children = new Map();
|
|
6
|
+
childIdToIndex = new Map();
|
|
5
7
|
rootModel = new Gtk.StringList();
|
|
6
8
|
childModels = new Map();
|
|
7
9
|
items = new Map();
|
|
8
10
|
onItemUpdated = null;
|
|
11
|
+
pendingBatch = null;
|
|
9
12
|
setOnItemUpdated(callback) {
|
|
10
13
|
this.onItemUpdated = callback;
|
|
11
14
|
}
|
|
15
|
+
beginBatch() {
|
|
16
|
+
this.pendingBatch = [];
|
|
17
|
+
}
|
|
18
|
+
flushBatch() {
|
|
19
|
+
const batch = this.pendingBatch;
|
|
20
|
+
this.pendingBatch = null;
|
|
21
|
+
if (batch && batch.length > 0) {
|
|
22
|
+
this.rootModel.splice(0, 0, batch);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
12
25
|
updateItem(id, item) {
|
|
13
26
|
if (this.items.has(id)) {
|
|
14
27
|
this.items.set(id, item);
|
|
@@ -21,28 +34,42 @@ export class TreeStore {
|
|
|
21
34
|
addItem(id, data, parentId) {
|
|
22
35
|
this.items.set(id, data);
|
|
23
36
|
if (parentId === undefined) {
|
|
24
|
-
const existingIndex = this.
|
|
25
|
-
if (existingIndex
|
|
37
|
+
const existingIndex = this.rootIdToIndex.get(id);
|
|
38
|
+
if (existingIndex !== undefined) {
|
|
26
39
|
this.rootModel.remove(existingIndex);
|
|
27
40
|
this.rootIds.splice(existingIndex, 1);
|
|
41
|
+
this.rebuildRootIndices(existingIndex);
|
|
28
42
|
}
|
|
43
|
+
this.rootIdToIndex.set(id, this.rootIds.length);
|
|
29
44
|
this.rootIds.push(id);
|
|
30
|
-
this.
|
|
45
|
+
if (this.pendingBatch) {
|
|
46
|
+
this.pendingBatch.push(id);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.rootModel.append(id);
|
|
50
|
+
}
|
|
31
51
|
}
|
|
32
52
|
else {
|
|
33
53
|
let siblings = this.children.get(parentId);
|
|
54
|
+
let indexMap = this.childIdToIndex.get(parentId);
|
|
34
55
|
if (!siblings) {
|
|
35
56
|
siblings = [];
|
|
36
57
|
this.children.set(parentId, siblings);
|
|
37
58
|
}
|
|
38
|
-
|
|
39
|
-
|
|
59
|
+
if (!indexMap) {
|
|
60
|
+
indexMap = new Map();
|
|
61
|
+
this.childIdToIndex.set(parentId, indexMap);
|
|
62
|
+
}
|
|
63
|
+
const existingIndex = indexMap.get(id);
|
|
64
|
+
if (existingIndex !== undefined) {
|
|
40
65
|
const model = this.childModels.get(parentId);
|
|
41
66
|
if (model) {
|
|
42
67
|
model.remove(existingIndex);
|
|
43
68
|
}
|
|
44
69
|
siblings.splice(existingIndex, 1);
|
|
70
|
+
this.rebuildChildIndices(siblings, indexMap, existingIndex);
|
|
45
71
|
}
|
|
72
|
+
indexMap.set(id, siblings.length);
|
|
46
73
|
siblings.push(id);
|
|
47
74
|
let model = this.childModels.get(parentId);
|
|
48
75
|
if (!model) {
|
|
@@ -55,20 +82,26 @@ export class TreeStore {
|
|
|
55
82
|
removeItem(id, parentId) {
|
|
56
83
|
this.items.delete(id);
|
|
57
84
|
this.children.delete(id);
|
|
85
|
+
this.childIdToIndex.delete(id);
|
|
58
86
|
this.childModels.delete(id);
|
|
59
87
|
if (parentId === undefined) {
|
|
60
|
-
const index = this.
|
|
61
|
-
if (index
|
|
88
|
+
const index = this.rootIdToIndex.get(id);
|
|
89
|
+
if (index !== undefined) {
|
|
62
90
|
this.rootIds.splice(index, 1);
|
|
91
|
+
this.rootIdToIndex.delete(id);
|
|
92
|
+
this.rebuildRootIndices(index);
|
|
63
93
|
this.rootModel.remove(index);
|
|
64
94
|
}
|
|
65
95
|
}
|
|
66
96
|
else {
|
|
67
97
|
const siblings = this.children.get(parentId);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
98
|
+
const indexMap = this.childIdToIndex.get(parentId);
|
|
99
|
+
if (siblings && indexMap) {
|
|
100
|
+
const index = indexMap.get(id);
|
|
101
|
+
if (index !== undefined) {
|
|
71
102
|
siblings.splice(index, 1);
|
|
103
|
+
indexMap.delete(id);
|
|
104
|
+
this.rebuildChildIndices(siblings, indexMap, index);
|
|
72
105
|
const model = this.childModels.get(parentId);
|
|
73
106
|
if (model) {
|
|
74
107
|
model.remove(index);
|
|
@@ -76,6 +109,7 @@ export class TreeStore {
|
|
|
76
109
|
}
|
|
77
110
|
if (siblings.length === 0) {
|
|
78
111
|
this.children.delete(parentId);
|
|
112
|
+
this.childIdToIndex.delete(parentId);
|
|
79
113
|
}
|
|
80
114
|
}
|
|
81
115
|
}
|
|
@@ -83,44 +117,57 @@ export class TreeStore {
|
|
|
83
117
|
insertItemBefore(id, beforeId, data, parentId) {
|
|
84
118
|
this.items.set(id, data);
|
|
85
119
|
if (parentId === undefined) {
|
|
86
|
-
const existingIndex = this.
|
|
87
|
-
if (existingIndex
|
|
120
|
+
const existingIndex = this.rootIdToIndex.get(id);
|
|
121
|
+
if (existingIndex !== undefined) {
|
|
88
122
|
this.rootModel.remove(existingIndex);
|
|
89
123
|
this.rootIds.splice(existingIndex, 1);
|
|
124
|
+
this.rootIdToIndex.delete(id);
|
|
125
|
+
this.rebuildRootIndices(existingIndex);
|
|
90
126
|
}
|
|
91
|
-
const beforeIndex = this.
|
|
92
|
-
if (beforeIndex
|
|
127
|
+
const beforeIndex = this.rootIdToIndex.get(beforeId);
|
|
128
|
+
if (beforeIndex === undefined) {
|
|
129
|
+
this.rootIdToIndex.set(id, this.rootIds.length);
|
|
93
130
|
this.rootIds.push(id);
|
|
94
131
|
this.rootModel.append(id);
|
|
95
132
|
}
|
|
96
133
|
else {
|
|
97
134
|
this.rootIds.splice(beforeIndex, 0, id);
|
|
135
|
+
this.rebuildRootIndices(beforeIndex);
|
|
98
136
|
this.rootModel.splice(beforeIndex, 0, [id]);
|
|
99
137
|
}
|
|
100
138
|
}
|
|
101
139
|
else {
|
|
102
140
|
let siblings = this.children.get(parentId);
|
|
141
|
+
let indexMap = this.childIdToIndex.get(parentId);
|
|
103
142
|
if (!siblings) {
|
|
104
143
|
siblings = [];
|
|
105
144
|
this.children.set(parentId, siblings);
|
|
106
145
|
}
|
|
146
|
+
if (!indexMap) {
|
|
147
|
+
indexMap = new Map();
|
|
148
|
+
this.childIdToIndex.set(parentId, indexMap);
|
|
149
|
+
}
|
|
107
150
|
let model = this.childModels.get(parentId);
|
|
108
151
|
if (!model) {
|
|
109
152
|
model = new Gtk.StringList();
|
|
110
153
|
this.childModels.set(parentId, model);
|
|
111
154
|
}
|
|
112
|
-
const existingIndex =
|
|
113
|
-
if (existingIndex
|
|
155
|
+
const existingIndex = indexMap.get(id);
|
|
156
|
+
if (existingIndex !== undefined) {
|
|
114
157
|
model.remove(existingIndex);
|
|
115
158
|
siblings.splice(existingIndex, 1);
|
|
159
|
+
indexMap.delete(id);
|
|
160
|
+
this.rebuildChildIndices(siblings, indexMap, existingIndex);
|
|
116
161
|
}
|
|
117
|
-
const beforeIndex =
|
|
118
|
-
if (beforeIndex
|
|
162
|
+
const beforeIndex = indexMap.get(beforeId);
|
|
163
|
+
if (beforeIndex === undefined) {
|
|
164
|
+
indexMap.set(id, siblings.length);
|
|
119
165
|
siblings.push(id);
|
|
120
166
|
model.append(id);
|
|
121
167
|
}
|
|
122
168
|
else {
|
|
123
169
|
siblings.splice(beforeIndex, 0, id);
|
|
170
|
+
this.rebuildChildIndices(siblings, indexMap, beforeIndex);
|
|
124
171
|
model.splice(beforeIndex, 0, [id]);
|
|
125
172
|
}
|
|
126
173
|
}
|
|
@@ -147,4 +194,14 @@ export class TreeStore {
|
|
|
147
194
|
const childIds = this.children.get(parentId);
|
|
148
195
|
return childIds !== undefined && childIds.length > 0;
|
|
149
196
|
}
|
|
197
|
+
rebuildRootIndices(fromIndex) {
|
|
198
|
+
for (let i = fromIndex; i < this.rootIds.length; i++) {
|
|
199
|
+
this.rootIdToIndex.set(this.rootIds[i], i);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
rebuildChildIndices(siblings, indexMap, fromIndex) {
|
|
203
|
+
for (let i = fromIndex; i < siblings.length; i++) {
|
|
204
|
+
indexMap.set(siblings[i], i);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
150
207
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
export declare function detachChild(child: Gtk.Widget, container: Gtk.Widget): void;
|
|
3
|
+
export declare function attachChild(child: Gtk.Widget, container: Gtk.Widget): void;
|
|
4
|
+
export declare function isAttachedTo(child: Gtk.Widget | null, parent: Gtk.Widget | null): boolean;
|
|
5
|
+
export declare function getFocusWidget(widget: Gtk.Widget): Gtk.Widget | null;
|
|
6
|
+
export declare function isDescendantOf(widget: Gtk.Widget, ancestor: Gtk.Widget): boolean;
|
|
7
|
+
export declare function resolvePropertySetter(parentWidget: Gtk.Widget, propId: string): ((child: Gtk.Widget | null) => void) | null;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { resolvePropMeta } from "../../metadata.js";
|
|
2
|
+
import { isAddable, isAppendable, isContentWidget, isRemovable, isSingleChild } from "./predicates.js";
|
|
3
|
+
export function detachChild(child, container) {
|
|
4
|
+
if (isAppendable(container) || isAddable(container)) {
|
|
5
|
+
if (isRemovable(container)) {
|
|
6
|
+
container.remove(child);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
else if (isContentWidget(container)) {
|
|
10
|
+
container.setContent(null);
|
|
11
|
+
}
|
|
12
|
+
else if (isSingleChild(container)) {
|
|
13
|
+
container.setChild(null);
|
|
14
|
+
}
|
|
15
|
+
else if (isRemovable(container)) {
|
|
16
|
+
container.remove(child);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function attachChild(child, container) {
|
|
20
|
+
if (isAppendable(container)) {
|
|
21
|
+
container.append(child);
|
|
22
|
+
}
|
|
23
|
+
else if (isAddable(container)) {
|
|
24
|
+
container.add(child);
|
|
25
|
+
}
|
|
26
|
+
else if (isContentWidget(container)) {
|
|
27
|
+
container.setContent(child);
|
|
28
|
+
}
|
|
29
|
+
else if (isSingleChild(container)) {
|
|
30
|
+
container.setChild(child);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
throw new Error(`Cannot attach child to '${container.constructor.name}': container does not support children`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function isAttachedTo(child, parent) {
|
|
37
|
+
if (!child || !parent)
|
|
38
|
+
return false;
|
|
39
|
+
const childParent = child.getParent();
|
|
40
|
+
return childParent !== null && childParent === parent;
|
|
41
|
+
}
|
|
42
|
+
export function getFocusWidget(widget) {
|
|
43
|
+
const root = widget.getRoot();
|
|
44
|
+
return root?.getFocus?.() ?? null;
|
|
45
|
+
}
|
|
46
|
+
export function isDescendantOf(widget, ancestor) {
|
|
47
|
+
let current = widget;
|
|
48
|
+
while (current) {
|
|
49
|
+
if (current === ancestor) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
current = current.getParent();
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
export function resolvePropertySetter(parentWidget, propId) {
|
|
57
|
+
const propMeta = resolvePropMeta(parentWidget, propId);
|
|
58
|
+
if (!propMeta) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const [, setterName] = propMeta;
|
|
62
|
+
const setter = parentWidget[setterName];
|
|
63
|
+
if (typeof setter !== "function") {
|
|
64
|
+
const parentType = parentWidget.constructor.glibTypeName;
|
|
65
|
+
throw new Error(`Expected setter function for property '${propId}' on type '${parentType}'`);
|
|
66
|
+
}
|
|
67
|
+
return setter.bind(parentWidget);
|
|
68
|
+
}
|
|
@@ -1 +1,11 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { GtkLevelBarProps } from "../jsx.js";
|
|
3
|
+
import { WidgetNode } from "./widget.js";
|
|
4
|
+
declare const OWN_PROPS: readonly ["offsets"];
|
|
5
|
+
type LevelBarProps = Pick<GtkLevelBarProps, (typeof OWN_PROPS)[number]>;
|
|
6
|
+
export declare class LevelBarNode extends WidgetNode<Gtk.LevelBar, LevelBarProps> {
|
|
7
|
+
private appliedOffsets;
|
|
8
|
+
commitUpdate(oldProps: LevelBarProps | null, newProps: LevelBarProps): void;
|
|
9
|
+
private applyOwnProps;
|
|
10
|
+
}
|
|
1
11
|
export {};
|