@gtkx/react 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -27
- package/dist/errors.js +3 -0
- package/dist/factory.d.ts +3 -2
- package/dist/factory.js +1 -1
- package/dist/generated/internal.d.ts +28 -1
- package/dist/generated/internal.js +93 -18
- package/dist/generated/jsx.d.ts +1712 -1516
- package/dist/generated/jsx.js +475 -0
- package/dist/host-config.d.ts +3 -1
- package/dist/host-config.js +31 -11
- package/dist/jsx.d.ts +147 -97
- package/dist/jsx.js +89 -21
- package/dist/node.d.ts +3 -1
- package/dist/node.js +5 -3
- package/dist/nodes/abstract/positional-child.d.ts +9 -0
- package/dist/nodes/abstract/positional-child.js +29 -0
- package/dist/nodes/abstract/positional-parent.d.ts +18 -0
- package/dist/nodes/abstract/positional-parent.js +48 -0
- package/dist/nodes/abstract/virtual-container.d.ts +17 -0
- package/dist/nodes/abstract/virtual-container.js +59 -0
- package/dist/nodes/abstract/virtual-single-child.d.ts +18 -0
- package/dist/nodes/abstract/virtual-single-child.js +54 -0
- package/dist/nodes/action-row-child.d.ts +0 -13
- package/dist/nodes/action-row-child.js +14 -12
- package/dist/nodes/action-row.d.ts +6 -1
- package/dist/nodes/action-row.js +4 -37
- package/dist/nodes/adjustable.d.ts +23 -0
- package/dist/nodes/adjustable.js +62 -0
- package/dist/nodes/alert-dialog-response.d.ts +1 -0
- package/dist/nodes/alert-dialog-response.js +86 -0
- package/dist/nodes/animation/animation-controller.d.ts +17 -0
- package/dist/nodes/animation/animation-controller.js +107 -0
- package/dist/nodes/animation/animation-factory.d.ts +15 -0
- package/dist/nodes/animation/animation-factory.js +25 -0
- package/dist/nodes/animation/animation-node.d.ts +9 -0
- package/dist/nodes/animation/animation-node.js +126 -0
- package/dist/nodes/animation/animation-style-sheet.d.ts +16 -0
- package/dist/nodes/animation/animation-style-sheet.js +74 -0
- package/dist/nodes/animation/index.d.ts +4 -0
- package/dist/nodes/animation/index.js +1 -0
- package/dist/nodes/animation/property-mapper.d.ts +11 -0
- package/dist/nodes/animation/property-mapper.js +36 -0
- package/dist/nodes/animation/transform-state.d.ts +11 -0
- package/dist/nodes/animation/transform-state.js +57 -0
- package/dist/nodes/animation/widget-registry.d.ts +5 -0
- package/dist/nodes/animation/widget-registry.js +42 -0
- package/dist/nodes/application.js +17 -7
- package/dist/nodes/autowrapped.js +37 -43
- package/dist/nodes/calendar.js +16 -55
- package/dist/nodes/color-dialog-button.d.ts +1 -0
- package/dist/nodes/color-dialog-button.js +70 -0
- package/dist/nodes/column-view-column.d.ts +4 -3
- package/dist/nodes/column-view-column.js +5 -1
- package/dist/nodes/column-view.js +40 -43
- package/dist/nodes/dialog.d.ts +11 -0
- package/dist/nodes/dialog.js +20 -0
- package/dist/nodes/drawing-area.d.ts +1 -0
- package/dist/nodes/drawing-area.js +36 -0
- package/dist/nodes/event-controller.d.ts +1 -0
- package/dist/nodes/event-controller.js +96 -0
- package/dist/nodes/expander-row-child.d.ts +0 -14
- package/dist/nodes/expander-row-child.js +14 -12
- package/dist/nodes/expander-row.d.ts +6 -1
- package/dist/nodes/expander-row.js +11 -47
- package/dist/nodes/fixed-child.js +48 -36
- package/dist/nodes/font-dialog-button.d.ts +1 -0
- package/dist/nodes/font-dialog-button.js +90 -0
- package/dist/nodes/grid-child.js +39 -45
- package/dist/nodes/grid.d.ts +1 -0
- package/dist/nodes/grid.js +41 -0
- package/dist/nodes/index.d.ts +22 -6
- package/dist/nodes/index.js +22 -6
- package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
- package/dist/nodes/internal/base-item-renderer.js +88 -0
- package/dist/nodes/internal/base-store.d.ts +9 -0
- package/dist/nodes/internal/base-store.js +20 -0
- package/dist/nodes/internal/child-attachment.d.ts +26 -0
- package/dist/nodes/internal/child-attachment.js +48 -0
- package/dist/nodes/internal/deferred-action.d.ts +8 -0
- package/dist/nodes/internal/deferred-action.js +19 -0
- package/dist/nodes/internal/list-item-renderer.d.ts +14 -14
- package/dist/nodes/internal/list-item-renderer.js +49 -70
- package/dist/nodes/internal/list-store.d.ts +7 -6
- package/dist/nodes/internal/list-store.js +20 -24
- package/dist/nodes/internal/predicates.d.ts +28 -1
- package/dist/nodes/internal/predicates.js +53 -38
- package/dist/nodes/internal/selection-model.d.ts +30 -0
- package/dist/nodes/internal/selection-model.js +91 -0
- package/dist/nodes/internal/signal-store.d.ts +5 -3
- package/dist/nodes/internal/signal-store.js +30 -21
- package/dist/nodes/internal/simple-list-store.js +6 -9
- package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
- package/dist/nodes/internal/text-buffer-controller.js +287 -0
- package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
- package/dist/nodes/internal/text-tag-styles.js +52 -0
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +16 -14
- package/dist/nodes/internal/tree-list-item-renderer.js +88 -91
- package/dist/nodes/internal/tree-store.d.ts +10 -9
- package/dist/nodes/internal/tree-store.js +31 -35
- package/dist/nodes/internal/utils.d.ts +7 -4
- package/dist/nodes/internal/utils.js +50 -5
- package/dist/nodes/level-bar.js +18 -66
- package/dist/nodes/list-item.d.ts +6 -3
- package/dist/nodes/list-item.js +7 -4
- package/dist/nodes/list-view.js +19 -11
- package/dist/nodes/menu.d.ts +3 -3
- package/dist/nodes/menu.js +3 -3
- package/dist/nodes/models/list.d.ts +11 -13
- package/dist/nodes/models/list.js +16 -73
- package/dist/nodes/models/menu.d.ts +8 -7
- package/dist/nodes/models/menu.js +43 -50
- package/dist/nodes/models/tree-list.d.ts +6 -12
- package/dist/nodes/models/tree-list.js +30 -93
- package/dist/nodes/navigation-page.d.ts +1 -0
- package/dist/nodes/navigation-page.js +7 -3
- package/dist/nodes/navigation-view.js +17 -28
- package/dist/nodes/notebook-page-tab.d.ts +4 -3
- package/dist/nodes/notebook-page-tab.js +5 -2
- package/dist/nodes/notebook-page.d.ts +7 -5
- package/dist/nodes/notebook-page.js +39 -16
- package/dist/nodes/notebook.js +2 -2
- package/dist/nodes/overlay-child.js +90 -30
- package/dist/nodes/pack-child.d.ts +0 -13
- package/dist/nodes/pack-child.js +14 -12
- package/dist/nodes/pack.d.ts +6 -1
- package/dist/nodes/pack.js +4 -37
- package/dist/nodes/popover-menu.js +2 -2
- package/dist/nodes/scale.js +15 -58
- package/dist/nodes/scrolled-window.js +7 -5
- package/dist/nodes/search-bar.d.ts +1 -0
- package/dist/nodes/search-bar.js +40 -0
- package/dist/nodes/shortcut-controller.d.ts +1 -0
- package/dist/nodes/shortcut-controller.js +90 -0
- package/dist/nodes/shortcut.d.ts +39 -0
- package/dist/nodes/shortcut.js +52 -0
- package/dist/nodes/simple-list-view.js +2 -3
- package/dist/nodes/slot.d.ts +6 -9
- package/dist/nodes/slot.js +27 -42
- package/dist/nodes/source-view.d.ts +1 -0
- package/dist/nodes/source-view.js +93 -0
- package/dist/nodes/stack-page.js +17 -13
- package/dist/nodes/stack.js +19 -5
- package/dist/nodes/text-anchor.d.ts +41 -0
- package/dist/nodes/text-anchor.js +59 -0
- package/dist/nodes/text-content.d.ts +10 -0
- package/dist/nodes/text-content.js +1 -0
- package/dist/nodes/text-paintable.d.ts +17 -0
- package/dist/nodes/text-paintable.js +34 -0
- package/dist/nodes/text-segment.d.ts +15 -0
- package/dist/nodes/text-segment.js +29 -0
- package/dist/nodes/text-tag.d.ts +136 -0
- package/dist/nodes/text-tag.js +202 -0
- package/dist/nodes/text-view.d.ts +31 -0
- package/dist/nodes/text-view.js +73 -0
- package/dist/nodes/toggle-group.js +24 -32
- package/dist/nodes/toggle.d.ts +1 -15
- package/dist/nodes/toggle.js +40 -32
- package/dist/nodes/toolbar-child.js +14 -16
- package/dist/nodes/tree-list-item.d.ts +7 -5
- package/dist/nodes/tree-list-item.js +24 -36
- package/dist/nodes/tree-list-view.js +9 -4
- package/dist/nodes/virtual.d.ts +1 -1
- package/dist/nodes/widget.d.ts +3 -13
- package/dist/nodes/widget.js +117 -231
- package/dist/nodes/window.d.ts +9 -3
- package/dist/nodes/window.js +35 -19
- package/dist/registry.d.ts +1 -1
- package/dist/render.js +8 -6
- package/dist/scheduler.d.ts +11 -1
- package/dist/scheduler.js +16 -4
- package/dist/types.d.ts +2 -110
- package/package.json +3 -3
- package/dist/nodes/calendar-mark.d.ts +0 -15
- package/dist/nodes/calendar-mark.js +0 -29
- package/dist/nodes/internal/constants.d.ts +0 -1
- package/dist/nodes/internal/constants.js +0 -21
- package/dist/nodes/level-bar-offset.d.ts +0 -13
- package/dist/nodes/level-bar-offset.js +0 -35
- package/dist/nodes/scale-mark.d.ts +0 -17
- package/dist/nodes/scale-mark.js +0 -38
- package/dist/nodes/virtual-child.d.ts +0 -18
- package/dist/nodes/virtual-child.js +0 -62
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { Node } from "../../node.js";
|
|
3
|
+
import type { TextContentChild, TextContentParent } from "../text-content.js";
|
|
4
|
+
import { TextSegmentNode } from "../text-segment.js";
|
|
5
|
+
type BufferCallbackProps = {
|
|
6
|
+
onBufferChanged?: ((buffer: Gtk.TextBuffer) => void) | null;
|
|
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;
|
|
15
|
+
export declare class TextBufferController<TBuffer extends Gtk.TextBuffer = Gtk.TextBuffer> {
|
|
16
|
+
private readonly owner;
|
|
17
|
+
private readonly container;
|
|
18
|
+
private readonly createBuffer;
|
|
19
|
+
private buffer;
|
|
20
|
+
private textChildren;
|
|
21
|
+
constructor(owner: Node & TextContentParent, container: Gtk.TextView, createBuffer: () => TBuffer);
|
|
22
|
+
getBuffer(): TBuffer | null;
|
|
23
|
+
hasTextChildren(): boolean;
|
|
24
|
+
ensureBuffer(): TBuffer;
|
|
25
|
+
applyOwnProps(oldProps: BufferProps | null, newProps: BufferProps): void;
|
|
26
|
+
private updateSignalHandlers;
|
|
27
|
+
isTextContentChild(child: Node): child is TextContentChild;
|
|
28
|
+
appendChild(child: TextContentChild): void;
|
|
29
|
+
insertBefore(child: TextContentChild, before: TextContentChild): void;
|
|
30
|
+
removeChild(child: TextContentChild): void;
|
|
31
|
+
private setChildParent;
|
|
32
|
+
private getTotalLength;
|
|
33
|
+
private insertTextAtOffset;
|
|
34
|
+
private deleteTextAtRange;
|
|
35
|
+
private updateChildOffsets;
|
|
36
|
+
private reapplyAllTagsRecursive;
|
|
37
|
+
private reapplyTagsFromOffset;
|
|
38
|
+
private findDirectChildContaining;
|
|
39
|
+
onChildInserted(child: TextContentChild): void;
|
|
40
|
+
onChildRemoved(child: TextContentChild): void;
|
|
41
|
+
onChildTextChanged(child: TextSegmentNode, oldLength: number, _newLength: number): void;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { TextAnchorNode } from "../text-anchor.js";
|
|
3
|
+
import { TextPaintableNode } from "../text-paintable.js";
|
|
4
|
+
import { TextSegmentNode } from "../text-segment.js";
|
|
5
|
+
import { TextTagNode } from "../text-tag.js";
|
|
6
|
+
import { hasChanged } from "./utils.js";
|
|
7
|
+
export class TextBufferController {
|
|
8
|
+
owner;
|
|
9
|
+
container;
|
|
10
|
+
createBuffer;
|
|
11
|
+
buffer = null;
|
|
12
|
+
textChildren = [];
|
|
13
|
+
constructor(owner, container, createBuffer) {
|
|
14
|
+
this.owner = owner;
|
|
15
|
+
this.container = container;
|
|
16
|
+
this.createBuffer = createBuffer;
|
|
17
|
+
}
|
|
18
|
+
getBuffer() {
|
|
19
|
+
return this.buffer;
|
|
20
|
+
}
|
|
21
|
+
hasTextChildren() {
|
|
22
|
+
return this.textChildren.length > 0;
|
|
23
|
+
}
|
|
24
|
+
ensureBuffer() {
|
|
25
|
+
if (!this.buffer) {
|
|
26
|
+
this.buffer = this.createBuffer();
|
|
27
|
+
this.container.setBuffer(this.buffer);
|
|
28
|
+
}
|
|
29
|
+
return this.buffer;
|
|
30
|
+
}
|
|
31
|
+
applyOwnProps(oldProps, newProps) {
|
|
32
|
+
const hasBufferProps = newProps.enableUndo !== undefined ||
|
|
33
|
+
newProps.onBufferChanged !== undefined ||
|
|
34
|
+
newProps.onTextInserted !== undefined ||
|
|
35
|
+
newProps.onTextDeleted !== undefined ||
|
|
36
|
+
newProps.onCanUndoChanged !== undefined ||
|
|
37
|
+
newProps.onCanRedoChanged !== undefined;
|
|
38
|
+
if (!hasBufferProps && this.textChildren.length === 0) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const buffer = this.ensureBuffer();
|
|
42
|
+
if (hasChanged(oldProps, newProps, "enableUndo") && newProps.enableUndo !== undefined) {
|
|
43
|
+
buffer.setEnableUndo(newProps.enableUndo);
|
|
44
|
+
}
|
|
45
|
+
const signalHandlersChanged = hasChanged(oldProps, newProps, "onBufferChanged") ||
|
|
46
|
+
hasChanged(oldProps, newProps, "onTextInserted") ||
|
|
47
|
+
hasChanged(oldProps, newProps, "onTextDeleted") ||
|
|
48
|
+
hasChanged(oldProps, newProps, "onCanUndoChanged") ||
|
|
49
|
+
hasChanged(oldProps, newProps, "onCanRedoChanged");
|
|
50
|
+
if (signalHandlersChanged) {
|
|
51
|
+
this.updateSignalHandlers(newProps);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
updateSignalHandlers(callbacks) {
|
|
55
|
+
if (!this.buffer)
|
|
56
|
+
return;
|
|
57
|
+
const buffer = this.buffer;
|
|
58
|
+
const { onBufferChanged, onTextInserted, onTextDeleted, onCanUndoChanged, onCanRedoChanged } = callbacks;
|
|
59
|
+
this.owner.signalStore.set(this.owner, buffer, "changed", onBufferChanged ? () => onBufferChanged(buffer) : null);
|
|
60
|
+
this.owner.signalStore.set(this.owner, buffer, "insert-text", onTextInserted
|
|
61
|
+
? (location, text, _len) => onTextInserted(buffer, location.getOffset(), text)
|
|
62
|
+
: null);
|
|
63
|
+
this.owner.signalStore.set(this.owner, buffer, "delete-range", onTextDeleted
|
|
64
|
+
? (start, end) => onTextDeleted(buffer, start.getOffset(), end.getOffset())
|
|
65
|
+
: null);
|
|
66
|
+
this.owner.signalStore.set(this.owner, buffer, "notify::can-undo", onCanUndoChanged ? () => onCanUndoChanged(buffer.getCanUndo()) : null);
|
|
67
|
+
this.owner.signalStore.set(this.owner, buffer, "notify::can-redo", onCanRedoChanged ? () => onCanRedoChanged(buffer.getCanRedo()) : null);
|
|
68
|
+
}
|
|
69
|
+
isTextContentChild(child) {
|
|
70
|
+
return (child instanceof TextSegmentNode ||
|
|
71
|
+
child instanceof TextTagNode ||
|
|
72
|
+
child instanceof TextAnchorNode ||
|
|
73
|
+
child instanceof TextPaintableNode);
|
|
74
|
+
}
|
|
75
|
+
appendChild(child) {
|
|
76
|
+
const buffer = this.ensureBuffer();
|
|
77
|
+
const wasMoved = this.textChildren.indexOf(child) !== -1;
|
|
78
|
+
if (wasMoved) {
|
|
79
|
+
const existingIndex = this.textChildren.indexOf(child);
|
|
80
|
+
const oldOffset = child.bufferOffset;
|
|
81
|
+
const oldLength = child.getLength();
|
|
82
|
+
this.textChildren.splice(existingIndex, 1);
|
|
83
|
+
if (oldLength > 0) {
|
|
84
|
+
this.deleteTextAtRange(oldOffset, oldOffset + oldLength);
|
|
85
|
+
}
|
|
86
|
+
this.updateChildOffsets(existingIndex);
|
|
87
|
+
}
|
|
88
|
+
const offset = this.getTotalLength();
|
|
89
|
+
this.textChildren.push(child);
|
|
90
|
+
child.bufferOffset = offset;
|
|
91
|
+
this.setChildParent(child);
|
|
92
|
+
if (child instanceof TextSegmentNode) {
|
|
93
|
+
this.insertTextAtOffset(child.getText(), offset);
|
|
94
|
+
}
|
|
95
|
+
else if (child instanceof TextTagNode) {
|
|
96
|
+
const text = child.getText();
|
|
97
|
+
this.insertTextAtOffset(text, offset);
|
|
98
|
+
if (!child.hasBuffer()) {
|
|
99
|
+
child.setBuffer(buffer);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (child instanceof TextAnchorNode) {
|
|
103
|
+
child.setTextViewAndBuffer(this.container, buffer);
|
|
104
|
+
}
|
|
105
|
+
else if (child instanceof TextPaintableNode) {
|
|
106
|
+
child.setTextViewAndBuffer(this.container, buffer);
|
|
107
|
+
}
|
|
108
|
+
if (wasMoved) {
|
|
109
|
+
this.updateChildOffsets(0);
|
|
110
|
+
this.reapplyTagsFromOffset(0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
insertBefore(child, before) {
|
|
114
|
+
const buffer = this.ensureBuffer();
|
|
115
|
+
const existingIndex = this.textChildren.indexOf(child);
|
|
116
|
+
if (existingIndex !== -1) {
|
|
117
|
+
const oldOffset = child.bufferOffset;
|
|
118
|
+
const oldLength = child.getLength();
|
|
119
|
+
this.textChildren.splice(existingIndex, 1);
|
|
120
|
+
if (oldLength > 0) {
|
|
121
|
+
this.deleteTextAtRange(oldOffset, oldOffset + oldLength);
|
|
122
|
+
}
|
|
123
|
+
this.updateChildOffsets(existingIndex);
|
|
124
|
+
}
|
|
125
|
+
const beforeIndex = this.textChildren.indexOf(before);
|
|
126
|
+
const insertIndex = beforeIndex !== -1 ? beforeIndex : this.textChildren.length;
|
|
127
|
+
let offset = 0;
|
|
128
|
+
for (let i = 0; i < insertIndex; i++) {
|
|
129
|
+
const c = this.textChildren[i];
|
|
130
|
+
if (c)
|
|
131
|
+
offset += c.getLength();
|
|
132
|
+
}
|
|
133
|
+
this.textChildren.splice(insertIndex, 0, child);
|
|
134
|
+
child.bufferOffset = offset;
|
|
135
|
+
this.setChildParent(child);
|
|
136
|
+
if (child instanceof TextSegmentNode) {
|
|
137
|
+
this.insertTextAtOffset(child.getText(), offset);
|
|
138
|
+
}
|
|
139
|
+
else if (child instanceof TextTagNode) {
|
|
140
|
+
const text = child.getText();
|
|
141
|
+
this.insertTextAtOffset(text, offset);
|
|
142
|
+
if (!child.hasBuffer()) {
|
|
143
|
+
child.setBuffer(buffer);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else if (child instanceof TextAnchorNode) {
|
|
147
|
+
child.setTextViewAndBuffer(this.container, buffer);
|
|
148
|
+
}
|
|
149
|
+
else if (child instanceof TextPaintableNode) {
|
|
150
|
+
child.setTextViewAndBuffer(this.container, buffer);
|
|
151
|
+
}
|
|
152
|
+
this.updateChildOffsets(0);
|
|
153
|
+
this.reapplyTagsFromOffset(0);
|
|
154
|
+
}
|
|
155
|
+
removeChild(child) {
|
|
156
|
+
const index = this.textChildren.indexOf(child);
|
|
157
|
+
if (index === -1)
|
|
158
|
+
return;
|
|
159
|
+
const offset = child.bufferOffset;
|
|
160
|
+
const length = child.getLength();
|
|
161
|
+
this.textChildren.splice(index, 1);
|
|
162
|
+
if (this.buffer && length > 0) {
|
|
163
|
+
this.deleteTextAtRange(offset, offset + length);
|
|
164
|
+
}
|
|
165
|
+
this.updateChildOffsets(index);
|
|
166
|
+
this.reapplyTagsFromOffset(offset);
|
|
167
|
+
}
|
|
168
|
+
setChildParent(child) {
|
|
169
|
+
if (child instanceof TextSegmentNode || child instanceof TextTagNode) {
|
|
170
|
+
child.setParent(this.owner);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
getTotalLength() {
|
|
174
|
+
let length = 0;
|
|
175
|
+
for (const child of this.textChildren) {
|
|
176
|
+
length += child.getLength();
|
|
177
|
+
}
|
|
178
|
+
return length;
|
|
179
|
+
}
|
|
180
|
+
insertTextAtOffset(text, offset) {
|
|
181
|
+
const buffer = this.buffer;
|
|
182
|
+
if (!buffer || text.length === 0)
|
|
183
|
+
return;
|
|
184
|
+
const iter = new Gtk.TextIter();
|
|
185
|
+
buffer.getIterAtOffset(iter, offset);
|
|
186
|
+
buffer.insert(iter, text, text.length);
|
|
187
|
+
}
|
|
188
|
+
deleteTextAtRange(start, end) {
|
|
189
|
+
const buffer = this.buffer;
|
|
190
|
+
if (!buffer || start >= end)
|
|
191
|
+
return;
|
|
192
|
+
const startIter = new Gtk.TextIter();
|
|
193
|
+
const endIter = new Gtk.TextIter();
|
|
194
|
+
buffer.getIterAtOffset(startIter, start);
|
|
195
|
+
buffer.getIterAtOffset(endIter, end);
|
|
196
|
+
buffer.delete(startIter, endIter);
|
|
197
|
+
}
|
|
198
|
+
updateChildOffsets(startIndex) {
|
|
199
|
+
let offset = 0;
|
|
200
|
+
for (let i = 0; i < startIndex; i++) {
|
|
201
|
+
const child = this.textChildren[i];
|
|
202
|
+
if (child)
|
|
203
|
+
offset += child.getLength();
|
|
204
|
+
}
|
|
205
|
+
for (let i = startIndex; i < this.textChildren.length; i++) {
|
|
206
|
+
const child = this.textChildren[i];
|
|
207
|
+
if (child) {
|
|
208
|
+
child.bufferOffset = offset;
|
|
209
|
+
offset += child.getLength();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
reapplyAllTagsRecursive(children) {
|
|
214
|
+
for (const child of children) {
|
|
215
|
+
if (child instanceof TextTagNode) {
|
|
216
|
+
child.reapplyTag();
|
|
217
|
+
this.reapplyAllTagsRecursive(child.getChildren());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
reapplyTagsFromOffset(fromOffset) {
|
|
222
|
+
for (const child of this.textChildren) {
|
|
223
|
+
if (child instanceof TextTagNode) {
|
|
224
|
+
if (child.bufferOffset >= fromOffset) {
|
|
225
|
+
child.reapplyTag();
|
|
226
|
+
this.reapplyAllTagsRecursive(child.getChildren());
|
|
227
|
+
}
|
|
228
|
+
else if (child.bufferOffset + child.getLength() > fromOffset) {
|
|
229
|
+
child.reapplyTag();
|
|
230
|
+
this.reapplyAllTagsRecursive(child.getChildren());
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
findDirectChildContaining(offset) {
|
|
236
|
+
for (let i = 0; i < this.textChildren.length; i++) {
|
|
237
|
+
const child = this.textChildren[i];
|
|
238
|
+
if (child) {
|
|
239
|
+
const start = child.bufferOffset;
|
|
240
|
+
const end = start + child.getLength();
|
|
241
|
+
if (offset >= start && offset <= end) {
|
|
242
|
+
return i;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return -1;
|
|
247
|
+
}
|
|
248
|
+
onChildInserted(child) {
|
|
249
|
+
if (!this.buffer)
|
|
250
|
+
return;
|
|
251
|
+
const text = child.getText();
|
|
252
|
+
if (text.length > 0) {
|
|
253
|
+
this.insertTextAtOffset(text, child.bufferOffset);
|
|
254
|
+
}
|
|
255
|
+
const containingIndex = this.findDirectChildContaining(child.bufferOffset);
|
|
256
|
+
if (containingIndex !== -1) {
|
|
257
|
+
this.updateChildOffsets(containingIndex + 1);
|
|
258
|
+
}
|
|
259
|
+
this.reapplyTagsFromOffset(child.bufferOffset);
|
|
260
|
+
}
|
|
261
|
+
onChildRemoved(child) {
|
|
262
|
+
if (!this.buffer)
|
|
263
|
+
return;
|
|
264
|
+
const offset = child.bufferOffset;
|
|
265
|
+
const length = child.getLength();
|
|
266
|
+
if (length > 0) {
|
|
267
|
+
this.deleteTextAtRange(offset, offset + length);
|
|
268
|
+
}
|
|
269
|
+
const containingIndex = this.findDirectChildContaining(offset);
|
|
270
|
+
if (containingIndex !== -1) {
|
|
271
|
+
this.updateChildOffsets(containingIndex + 1);
|
|
272
|
+
}
|
|
273
|
+
this.reapplyTagsFromOffset(offset);
|
|
274
|
+
}
|
|
275
|
+
onChildTextChanged(child, oldLength, _newLength) {
|
|
276
|
+
if (!this.buffer)
|
|
277
|
+
return;
|
|
278
|
+
const offset = child.bufferOffset;
|
|
279
|
+
this.deleteTextAtRange(offset, offset + oldLength);
|
|
280
|
+
this.insertTextAtOffset(child.getText(), offset);
|
|
281
|
+
const containingIndex = this.findDirectChildContaining(offset);
|
|
282
|
+
if (containingIndex !== -1) {
|
|
283
|
+
this.updateChildOffsets(containingIndex + 1);
|
|
284
|
+
}
|
|
285
|
+
this.reapplyTagsFromOffset(offset);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type * as Pango from "@gtkx/ffi/pango";
|
|
3
|
+
export type TagStyleProps = {
|
|
4
|
+
background?: string;
|
|
5
|
+
backgroundFullHeight?: boolean;
|
|
6
|
+
foreground?: string;
|
|
7
|
+
family?: string;
|
|
8
|
+
font?: string;
|
|
9
|
+
sizePoints?: number;
|
|
10
|
+
size?: number;
|
|
11
|
+
scale?: number;
|
|
12
|
+
weight?: Pango.Weight | number;
|
|
13
|
+
style?: Pango.Style;
|
|
14
|
+
stretch?: Pango.Stretch;
|
|
15
|
+
variant?: Pango.Variant;
|
|
16
|
+
strikethrough?: boolean;
|
|
17
|
+
underline?: Pango.Underline;
|
|
18
|
+
overline?: Pango.Overline;
|
|
19
|
+
rise?: number;
|
|
20
|
+
letterSpacing?: number;
|
|
21
|
+
lineHeight?: number;
|
|
22
|
+
leftMargin?: number;
|
|
23
|
+
rightMargin?: number;
|
|
24
|
+
indent?: number;
|
|
25
|
+
pixelsAboveLines?: number;
|
|
26
|
+
pixelsBelowLines?: number;
|
|
27
|
+
pixelsInsideWrap?: number;
|
|
28
|
+
justification?: Gtk.Justification;
|
|
29
|
+
direction?: Gtk.TextDirection;
|
|
30
|
+
wrapMode?: Gtk.WrapMode;
|
|
31
|
+
editable?: boolean;
|
|
32
|
+
invisible?: boolean;
|
|
33
|
+
allowBreaks?: boolean;
|
|
34
|
+
insertHyphens?: boolean;
|
|
35
|
+
fallback?: boolean;
|
|
36
|
+
accumulativeMargin?: boolean;
|
|
37
|
+
paragraphBackground?: string;
|
|
38
|
+
showSpaces?: Pango.ShowFlags;
|
|
39
|
+
textTransform?: Pango.TextTransform;
|
|
40
|
+
fontFeatures?: string;
|
|
41
|
+
language?: string;
|
|
42
|
+
};
|
|
43
|
+
export declare function applyStyleChanges(tag: Gtk.TextTag, oldProps: TagStyleProps | null, newProps: TagStyleProps): void;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { hasChanged } from "./utils.js";
|
|
2
|
+
const STYLE_PROPS = {
|
|
3
|
+
background: "setBackground",
|
|
4
|
+
backgroundFullHeight: "setBackgroundFullHeight",
|
|
5
|
+
foreground: "setForeground",
|
|
6
|
+
family: "setFamily",
|
|
7
|
+
font: "setFont",
|
|
8
|
+
sizePoints: "setSizePoints",
|
|
9
|
+
size: "setSize",
|
|
10
|
+
scale: "setScale",
|
|
11
|
+
weight: "setWeight",
|
|
12
|
+
style: "setStyle",
|
|
13
|
+
stretch: "setStretch",
|
|
14
|
+
variant: "setVariant",
|
|
15
|
+
strikethrough: "setStrikethrough",
|
|
16
|
+
underline: "setUnderline",
|
|
17
|
+
overline: "setOverline",
|
|
18
|
+
rise: "setRise",
|
|
19
|
+
letterSpacing: "setLetterSpacing",
|
|
20
|
+
lineHeight: "setLineHeight",
|
|
21
|
+
leftMargin: "setLeftMargin",
|
|
22
|
+
rightMargin: "setRightMargin",
|
|
23
|
+
indent: "setIndent",
|
|
24
|
+
pixelsAboveLines: "setPixelsAboveLines",
|
|
25
|
+
pixelsBelowLines: "setPixelsBelowLines",
|
|
26
|
+
pixelsInsideWrap: "setPixelsInsideWrap",
|
|
27
|
+
justification: "setJustification",
|
|
28
|
+
direction: "setDirection",
|
|
29
|
+
wrapMode: "setWrapMode",
|
|
30
|
+
editable: "setEditable",
|
|
31
|
+
invisible: "setInvisible",
|
|
32
|
+
allowBreaks: "setAllowBreaks",
|
|
33
|
+
insertHyphens: "setInsertHyphens",
|
|
34
|
+
fallback: "setFallback",
|
|
35
|
+
accumulativeMargin: "setAccumulativeMargin",
|
|
36
|
+
paragraphBackground: "setParagraphBackground",
|
|
37
|
+
showSpaces: "setShowSpaces",
|
|
38
|
+
textTransform: "setTextTransform",
|
|
39
|
+
fontFeatures: "setFontFeatures",
|
|
40
|
+
language: "setLanguage",
|
|
41
|
+
};
|
|
42
|
+
export function applyStyleChanges(tag, oldProps, newProps) {
|
|
43
|
+
for (const prop of Object.keys(STYLE_PROPS)) {
|
|
44
|
+
if (hasChanged(oldProps, newProps, prop)) {
|
|
45
|
+
const value = newProps[prop];
|
|
46
|
+
if (value !== undefined) {
|
|
47
|
+
const setter = tag[STYLE_PROPS[prop]];
|
|
48
|
+
setter.call(tag, value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
|
+
import type Reconciler from "react-reconciler";
|
|
4
|
+
import { BaseItemRenderer } from "./base-item-renderer.js";
|
|
3
5
|
import type { TreeStore } from "./tree-store.js";
|
|
4
6
|
export type TreeRenderItemFn<T> = (item: T | null, row: Gtk.TreeListRow | null) => ReactNode;
|
|
5
|
-
export declare class TreeListItemRenderer {
|
|
6
|
-
private factory;
|
|
7
|
-
private store?;
|
|
8
|
-
private fiberRoots;
|
|
7
|
+
export declare class TreeListItemRenderer extends BaseItemRenderer<TreeStore> {
|
|
9
8
|
private expanders;
|
|
10
9
|
private setupComplete;
|
|
11
10
|
private pendingBinds;
|
|
12
|
-
private
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
private renderFn;
|
|
12
|
+
private boundItems;
|
|
13
|
+
setRenderFn(renderFn: TreeRenderItemFn<unknown> | null): void;
|
|
14
|
+
rebindItem(id: string): void;
|
|
15
|
+
protected getStoreTypeName(): string;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
protected renderItem(_ptr: number): ReactNode;
|
|
18
|
+
protected getItemFromListItem(listItem: Gtk.ListItem): unknown;
|
|
19
|
+
protected onSetup(listItem: Gtk.ListItem, ptr: number): Gtk.Widget;
|
|
20
|
+
protected onSetupComplete(ptr: number): void;
|
|
21
|
+
protected onBind(listItem: Gtk.ListItem, ptr: number, fiberRoot: Reconciler.FiberRoot): void;
|
|
22
|
+
protected onUnbind(listItem: Gtk.ListItem): void;
|
|
23
|
+
protected onTeardown(_listItem: Gtk.ListItem, ptr: number): void;
|
|
22
24
|
private processPendingBind;
|
|
23
25
|
private renderBind;
|
|
24
26
|
}
|
|
@@ -1,114 +1,109 @@
|
|
|
1
|
-
import { getNativeId } from "@gtkx/ffi";
|
|
2
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
-
import { createFiberRoot } from "../../fiber-root.js";
|
|
4
2
|
import { reconciler } from "../../reconciler.js";
|
|
5
|
-
import {
|
|
6
|
-
export class TreeListItemRenderer {
|
|
7
|
-
factory;
|
|
8
|
-
store;
|
|
9
|
-
fiberRoots = new Map();
|
|
3
|
+
import { BaseItemRenderer } from "./base-item-renderer.js";
|
|
4
|
+
export class TreeListItemRenderer extends BaseItemRenderer {
|
|
10
5
|
expanders = new Map();
|
|
11
6
|
setupComplete = new Set();
|
|
12
7
|
pendingBinds = new Map();
|
|
13
|
-
tornDown = new Set();
|
|
14
8
|
renderFn = () => null;
|
|
15
|
-
|
|
16
|
-
constructor() {
|
|
17
|
-
this.factory = new Gtk.SignalListItemFactory();
|
|
18
|
-
this.initialize();
|
|
19
|
-
}
|
|
20
|
-
getFactory() {
|
|
21
|
-
return this.factory;
|
|
22
|
-
}
|
|
9
|
+
boundItems = new Map();
|
|
23
10
|
setRenderFn(renderFn) {
|
|
24
11
|
this.renderFn = renderFn;
|
|
25
12
|
}
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
rebindItem(id) {
|
|
14
|
+
const binding = this.boundItems.get(id);
|
|
15
|
+
if (!binding)
|
|
16
|
+
return;
|
|
17
|
+
const fiberRoot = this.fiberRoots.get(binding.ptr);
|
|
18
|
+
if (!fiberRoot)
|
|
19
|
+
return;
|
|
20
|
+
const expander = this.expanders.get(binding.ptr);
|
|
21
|
+
if (!expander)
|
|
22
|
+
return;
|
|
23
|
+
this.renderBind(binding.ptr, expander, binding.treeListRow, id, fiberRoot);
|
|
24
|
+
}
|
|
25
|
+
getStoreTypeName() {
|
|
26
|
+
return "tree store";
|
|
27
|
+
}
|
|
28
|
+
dispose() {
|
|
29
|
+
super.dispose();
|
|
30
|
+
this.expanders.clear();
|
|
31
|
+
this.setupComplete.clear();
|
|
32
|
+
this.pendingBinds.clear();
|
|
33
|
+
this.boundItems.clear();
|
|
34
|
+
}
|
|
35
|
+
renderItem(_ptr) {
|
|
36
|
+
return this.renderFn?.(null, null);
|
|
28
37
|
}
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
getItemFromListItem(listItem) {
|
|
39
|
+
const treeListRow = listItem.getItem();
|
|
40
|
+
if (!(treeListRow instanceof Gtk.TreeListRow))
|
|
41
|
+
return null;
|
|
42
|
+
const stringObject = treeListRow.getItem();
|
|
43
|
+
if (!(stringObject instanceof Gtk.StringObject))
|
|
44
|
+
return null;
|
|
45
|
+
return this.getStore().getItem(stringObject.getString());
|
|
31
46
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
onSetup(listItem, ptr) {
|
|
48
|
+
const expander = new Gtk.TreeExpander();
|
|
49
|
+
const box = this.createBox();
|
|
50
|
+
expander.setChild(box);
|
|
51
|
+
listItem.setChild(expander);
|
|
52
|
+
this.expanders.set(ptr, expander);
|
|
53
|
+
return box;
|
|
54
|
+
}
|
|
55
|
+
onSetupComplete(ptr) {
|
|
56
|
+
this.setupComplete.add(ptr);
|
|
57
|
+
this.processPendingBind(ptr);
|
|
58
|
+
}
|
|
59
|
+
onBind(listItem, ptr, fiberRoot) {
|
|
60
|
+
const expander = this.expanders.get(ptr);
|
|
61
|
+
if (!expander)
|
|
62
|
+
return;
|
|
63
|
+
const treeListRow = listItem.getItem();
|
|
64
|
+
if (!(treeListRow instanceof Gtk.TreeListRow))
|
|
65
|
+
return;
|
|
66
|
+
expander.setListRow(treeListRow);
|
|
67
|
+
const stringObject = treeListRow.getItem();
|
|
68
|
+
if (!(stringObject instanceof Gtk.StringObject))
|
|
69
|
+
return;
|
|
70
|
+
const id = stringObject.getString();
|
|
71
|
+
this.boundItems.set(id, { ptr, treeListRow });
|
|
72
|
+
if (!this.setupComplete.has(ptr)) {
|
|
73
|
+
this.pendingBinds.set(ptr, { treeListRow, expander, id });
|
|
74
|
+
return;
|
|
35
75
|
}
|
|
36
|
-
|
|
76
|
+
this.renderBind(ptr, expander, treeListRow, id, fiberRoot);
|
|
37
77
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const box = new Gtk.Box(Gtk.Orientation.VERTICAL);
|
|
43
|
-
if (this.estimatedItemHeight !== undefined) {
|
|
44
|
-
box.setSizeRequest(-1, this.estimatedItemHeight);
|
|
45
|
-
}
|
|
46
|
-
expander.setChild(box);
|
|
47
|
-
listItem.setChild(expander);
|
|
48
|
-
const fiberRoot = createFiberRoot(box);
|
|
49
|
-
this.fiberRoots.set(ptr, fiberRoot);
|
|
50
|
-
this.expanders.set(ptr, expander);
|
|
51
|
-
const element = this.renderFn?.(null, null);
|
|
52
|
-
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
|
|
53
|
-
if (this.tornDown.has(ptr))
|
|
54
|
-
return;
|
|
55
|
-
this.setupComplete.add(ptr);
|
|
56
|
-
this.processPendingBind(ptr);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
signalStore.set(this, this.factory, "bind", (_self, listItem) => {
|
|
60
|
-
const ptr = getNativeId(listItem.handle);
|
|
61
|
-
const fiberRoot = this.fiberRoots.get(ptr);
|
|
62
|
-
const expander = this.expanders.get(ptr);
|
|
63
|
-
if (!fiberRoot || !expander)
|
|
64
|
-
return;
|
|
78
|
+
onUnbind(listItem) {
|
|
79
|
+
const expander = listItem.getChild();
|
|
80
|
+
if (expander instanceof Gtk.TreeExpander) {
|
|
81
|
+
expander.setListRow(null);
|
|
65
82
|
const treeListRow = listItem.getItem();
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return;
|
|
72
|
-
const id = stringObject.getString();
|
|
73
|
-
if (!this.setupComplete.has(ptr)) {
|
|
74
|
-
this.pendingBinds.set(ptr, { treeListRow, expander, id });
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
this.renderBind(ptr, expander, treeListRow, id);
|
|
78
|
-
});
|
|
79
|
-
signalStore.set(this, this.factory, "unbind", (_self, listItem) => {
|
|
80
|
-
const expander = listItem.getChild();
|
|
81
|
-
if (expander instanceof Gtk.TreeExpander) {
|
|
82
|
-
expander.setListRow(null);
|
|
83
|
+
if (treeListRow instanceof Gtk.TreeListRow) {
|
|
84
|
+
const stringObject = treeListRow.getItem();
|
|
85
|
+
if (stringObject instanceof Gtk.StringObject) {
|
|
86
|
+
this.boundItems.delete(stringObject.getString());
|
|
87
|
+
}
|
|
83
88
|
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
|
|
91
|
-
queueMicrotask(() => {
|
|
92
|
-
this.fiberRoots.delete(ptr);
|
|
93
|
-
this.expanders.delete(ptr);
|
|
94
|
-
this.setupComplete.delete(ptr);
|
|
95
|
-
this.pendingBinds.delete(ptr);
|
|
96
|
-
this.tornDown.delete(ptr);
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
onTeardown(_listItem, ptr) {
|
|
92
|
+
this.expanders.delete(ptr);
|
|
93
|
+
this.setupComplete.delete(ptr);
|
|
94
|
+
this.pendingBinds.delete(ptr);
|
|
100
95
|
}
|
|
101
96
|
processPendingBind(ptr) {
|
|
102
97
|
const pending = this.pendingBinds.get(ptr);
|
|
103
98
|
if (!pending)
|
|
104
99
|
return;
|
|
105
100
|
this.pendingBinds.delete(ptr);
|
|
106
|
-
this.renderBind(ptr, pending.expander, pending.treeListRow, pending.id);
|
|
107
|
-
}
|
|
108
|
-
renderBind(ptr, expander, treeListRow, id) {
|
|
109
101
|
const fiberRoot = this.fiberRoots.get(ptr);
|
|
110
|
-
if (
|
|
111
|
-
|
|
102
|
+
if (fiberRoot) {
|
|
103
|
+
this.renderBind(ptr, pending.expander, pending.treeListRow, pending.id, fiberRoot);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
renderBind(ptr, expander, treeListRow, id, fiberRoot) {
|
|
112
107
|
const itemData = this.getStore().getItem(id);
|
|
113
108
|
if (itemData) {
|
|
114
109
|
if (itemData.indentForDepth !== undefined) {
|
|
@@ -125,12 +120,14 @@ export class TreeListItemRenderer {
|
|
|
125
120
|
reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
|
|
126
121
|
if (this.tornDown.has(ptr))
|
|
127
122
|
return;
|
|
123
|
+
if (this.estimatedItemHeight !== null)
|
|
124
|
+
return;
|
|
128
125
|
const currentExpander = this.expanders.get(ptr);
|
|
129
126
|
if (!currentExpander)
|
|
130
127
|
return;
|
|
131
128
|
const box = currentExpander.getChild();
|
|
132
|
-
if (box
|
|
133
|
-
|
|
129
|
+
if (box) {
|
|
130
|
+
this.clearBoxSizeRequest(box);
|
|
134
131
|
}
|
|
135
132
|
});
|
|
136
133
|
}
|