@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.
Files changed (182) hide show
  1. package/README.md +28 -27
  2. package/dist/errors.js +3 -0
  3. package/dist/factory.d.ts +3 -2
  4. package/dist/factory.js +1 -1
  5. package/dist/generated/internal.d.ts +28 -1
  6. package/dist/generated/internal.js +93 -18
  7. package/dist/generated/jsx.d.ts +1712 -1516
  8. package/dist/generated/jsx.js +475 -0
  9. package/dist/host-config.d.ts +3 -1
  10. package/dist/host-config.js +31 -11
  11. package/dist/jsx.d.ts +147 -97
  12. package/dist/jsx.js +89 -21
  13. package/dist/node.d.ts +3 -1
  14. package/dist/node.js +5 -3
  15. package/dist/nodes/abstract/positional-child.d.ts +9 -0
  16. package/dist/nodes/abstract/positional-child.js +29 -0
  17. package/dist/nodes/abstract/positional-parent.d.ts +18 -0
  18. package/dist/nodes/abstract/positional-parent.js +48 -0
  19. package/dist/nodes/abstract/virtual-container.d.ts +17 -0
  20. package/dist/nodes/abstract/virtual-container.js +59 -0
  21. package/dist/nodes/abstract/virtual-single-child.d.ts +18 -0
  22. package/dist/nodes/abstract/virtual-single-child.js +54 -0
  23. package/dist/nodes/action-row-child.d.ts +0 -13
  24. package/dist/nodes/action-row-child.js +14 -12
  25. package/dist/nodes/action-row.d.ts +6 -1
  26. package/dist/nodes/action-row.js +4 -37
  27. package/dist/nodes/adjustable.d.ts +23 -0
  28. package/dist/nodes/adjustable.js +62 -0
  29. package/dist/nodes/alert-dialog-response.d.ts +1 -0
  30. package/dist/nodes/alert-dialog-response.js +86 -0
  31. package/dist/nodes/animation/animation-controller.d.ts +17 -0
  32. package/dist/nodes/animation/animation-controller.js +107 -0
  33. package/dist/nodes/animation/animation-factory.d.ts +15 -0
  34. package/dist/nodes/animation/animation-factory.js +25 -0
  35. package/dist/nodes/animation/animation-node.d.ts +9 -0
  36. package/dist/nodes/animation/animation-node.js +126 -0
  37. package/dist/nodes/animation/animation-style-sheet.d.ts +16 -0
  38. package/dist/nodes/animation/animation-style-sheet.js +74 -0
  39. package/dist/nodes/animation/index.d.ts +4 -0
  40. package/dist/nodes/animation/index.js +1 -0
  41. package/dist/nodes/animation/property-mapper.d.ts +11 -0
  42. package/dist/nodes/animation/property-mapper.js +36 -0
  43. package/dist/nodes/animation/transform-state.d.ts +11 -0
  44. package/dist/nodes/animation/transform-state.js +57 -0
  45. package/dist/nodes/animation/widget-registry.d.ts +5 -0
  46. package/dist/nodes/animation/widget-registry.js +42 -0
  47. package/dist/nodes/application.js +17 -7
  48. package/dist/nodes/autowrapped.js +37 -43
  49. package/dist/nodes/calendar.js +16 -55
  50. package/dist/nodes/color-dialog-button.d.ts +1 -0
  51. package/dist/nodes/color-dialog-button.js +70 -0
  52. package/dist/nodes/column-view-column.d.ts +4 -3
  53. package/dist/nodes/column-view-column.js +5 -1
  54. package/dist/nodes/column-view.js +40 -43
  55. package/dist/nodes/dialog.d.ts +11 -0
  56. package/dist/nodes/dialog.js +20 -0
  57. package/dist/nodes/drawing-area.d.ts +1 -0
  58. package/dist/nodes/drawing-area.js +36 -0
  59. package/dist/nodes/event-controller.d.ts +1 -0
  60. package/dist/nodes/event-controller.js +96 -0
  61. package/dist/nodes/expander-row-child.d.ts +0 -14
  62. package/dist/nodes/expander-row-child.js +14 -12
  63. package/dist/nodes/expander-row.d.ts +6 -1
  64. package/dist/nodes/expander-row.js +11 -47
  65. package/dist/nodes/fixed-child.js +48 -36
  66. package/dist/nodes/font-dialog-button.d.ts +1 -0
  67. package/dist/nodes/font-dialog-button.js +90 -0
  68. package/dist/nodes/grid-child.js +39 -45
  69. package/dist/nodes/grid.d.ts +1 -0
  70. package/dist/nodes/grid.js +41 -0
  71. package/dist/nodes/index.d.ts +22 -6
  72. package/dist/nodes/index.js +22 -6
  73. package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
  74. package/dist/nodes/internal/base-item-renderer.js +88 -0
  75. package/dist/nodes/internal/base-store.d.ts +9 -0
  76. package/dist/nodes/internal/base-store.js +20 -0
  77. package/dist/nodes/internal/child-attachment.d.ts +26 -0
  78. package/dist/nodes/internal/child-attachment.js +48 -0
  79. package/dist/nodes/internal/deferred-action.d.ts +8 -0
  80. package/dist/nodes/internal/deferred-action.js +19 -0
  81. package/dist/nodes/internal/list-item-renderer.d.ts +14 -14
  82. package/dist/nodes/internal/list-item-renderer.js +49 -70
  83. package/dist/nodes/internal/list-store.d.ts +7 -6
  84. package/dist/nodes/internal/list-store.js +20 -24
  85. package/dist/nodes/internal/predicates.d.ts +28 -1
  86. package/dist/nodes/internal/predicates.js +53 -38
  87. package/dist/nodes/internal/selection-model.d.ts +30 -0
  88. package/dist/nodes/internal/selection-model.js +91 -0
  89. package/dist/nodes/internal/signal-store.d.ts +5 -3
  90. package/dist/nodes/internal/signal-store.js +30 -21
  91. package/dist/nodes/internal/simple-list-store.js +6 -9
  92. package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
  93. package/dist/nodes/internal/text-buffer-controller.js +287 -0
  94. package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
  95. package/dist/nodes/internal/text-tag-styles.js +52 -0
  96. package/dist/nodes/internal/tree-list-item-renderer.d.ts +16 -14
  97. package/dist/nodes/internal/tree-list-item-renderer.js +88 -91
  98. package/dist/nodes/internal/tree-store.d.ts +10 -9
  99. package/dist/nodes/internal/tree-store.js +31 -35
  100. package/dist/nodes/internal/utils.d.ts +7 -4
  101. package/dist/nodes/internal/utils.js +50 -5
  102. package/dist/nodes/level-bar.js +18 -66
  103. package/dist/nodes/list-item.d.ts +6 -3
  104. package/dist/nodes/list-item.js +7 -4
  105. package/dist/nodes/list-view.js +19 -11
  106. package/dist/nodes/menu.d.ts +3 -3
  107. package/dist/nodes/menu.js +3 -3
  108. package/dist/nodes/models/list.d.ts +11 -13
  109. package/dist/nodes/models/list.js +16 -73
  110. package/dist/nodes/models/menu.d.ts +8 -7
  111. package/dist/nodes/models/menu.js +43 -50
  112. package/dist/nodes/models/tree-list.d.ts +6 -12
  113. package/dist/nodes/models/tree-list.js +30 -93
  114. package/dist/nodes/navigation-page.d.ts +1 -0
  115. package/dist/nodes/navigation-page.js +7 -3
  116. package/dist/nodes/navigation-view.js +17 -28
  117. package/dist/nodes/notebook-page-tab.d.ts +4 -3
  118. package/dist/nodes/notebook-page-tab.js +5 -2
  119. package/dist/nodes/notebook-page.d.ts +7 -5
  120. package/dist/nodes/notebook-page.js +39 -16
  121. package/dist/nodes/notebook.js +2 -2
  122. package/dist/nodes/overlay-child.js +90 -30
  123. package/dist/nodes/pack-child.d.ts +0 -13
  124. package/dist/nodes/pack-child.js +14 -12
  125. package/dist/nodes/pack.d.ts +6 -1
  126. package/dist/nodes/pack.js +4 -37
  127. package/dist/nodes/popover-menu.js +2 -2
  128. package/dist/nodes/scale.js +15 -58
  129. package/dist/nodes/scrolled-window.js +7 -5
  130. package/dist/nodes/search-bar.d.ts +1 -0
  131. package/dist/nodes/search-bar.js +40 -0
  132. package/dist/nodes/shortcut-controller.d.ts +1 -0
  133. package/dist/nodes/shortcut-controller.js +90 -0
  134. package/dist/nodes/shortcut.d.ts +39 -0
  135. package/dist/nodes/shortcut.js +52 -0
  136. package/dist/nodes/simple-list-view.js +2 -3
  137. package/dist/nodes/slot.d.ts +6 -9
  138. package/dist/nodes/slot.js +27 -42
  139. package/dist/nodes/source-view.d.ts +1 -0
  140. package/dist/nodes/source-view.js +93 -0
  141. package/dist/nodes/stack-page.js +17 -13
  142. package/dist/nodes/stack.js +19 -5
  143. package/dist/nodes/text-anchor.d.ts +41 -0
  144. package/dist/nodes/text-anchor.js +59 -0
  145. package/dist/nodes/text-content.d.ts +10 -0
  146. package/dist/nodes/text-content.js +1 -0
  147. package/dist/nodes/text-paintable.d.ts +17 -0
  148. package/dist/nodes/text-paintable.js +34 -0
  149. package/dist/nodes/text-segment.d.ts +15 -0
  150. package/dist/nodes/text-segment.js +29 -0
  151. package/dist/nodes/text-tag.d.ts +136 -0
  152. package/dist/nodes/text-tag.js +202 -0
  153. package/dist/nodes/text-view.d.ts +31 -0
  154. package/dist/nodes/text-view.js +73 -0
  155. package/dist/nodes/toggle-group.js +24 -32
  156. package/dist/nodes/toggle.d.ts +1 -15
  157. package/dist/nodes/toggle.js +40 -32
  158. package/dist/nodes/toolbar-child.js +14 -16
  159. package/dist/nodes/tree-list-item.d.ts +7 -5
  160. package/dist/nodes/tree-list-item.js +24 -36
  161. package/dist/nodes/tree-list-view.js +9 -4
  162. package/dist/nodes/virtual.d.ts +1 -1
  163. package/dist/nodes/widget.d.ts +3 -13
  164. package/dist/nodes/widget.js +117 -231
  165. package/dist/nodes/window.d.ts +9 -3
  166. package/dist/nodes/window.js +35 -19
  167. package/dist/registry.d.ts +1 -1
  168. package/dist/render.js +8 -6
  169. package/dist/scheduler.d.ts +11 -1
  170. package/dist/scheduler.js +16 -4
  171. package/dist/types.d.ts +2 -110
  172. package/package.json +3 -3
  173. package/dist/nodes/calendar-mark.d.ts +0 -15
  174. package/dist/nodes/calendar-mark.js +0 -29
  175. package/dist/nodes/internal/constants.d.ts +0 -1
  176. package/dist/nodes/internal/constants.js +0 -21
  177. package/dist/nodes/level-bar-offset.d.ts +0 -13
  178. package/dist/nodes/level-bar-offset.js +0 -35
  179. package/dist/nodes/scale-mark.d.ts +0 -17
  180. package/dist/nodes/scale-mark.js +0 -38
  181. package/dist/nodes/virtual-child.d.ts +0 -18
  182. 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 tornDown;
13
- private renderFn?;
14
- private estimatedItemHeight?;
15
- constructor();
16
- getFactory(): Gtk.SignalListItemFactory;
17
- setRenderFn(renderFn?: TreeRenderItemFn<unknown>): void;
18
- setStore(store?: TreeStore | null): void;
19
- setEstimatedItemHeight(height?: number): void;
20
- private getStore;
21
- private initialize;
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 { signalStore } from "./signal-store.js";
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
- estimatedItemHeight;
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
- setStore(store) {
27
- this.store = store;
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
- setEstimatedItemHeight(height) {
30
- this.estimatedItemHeight = height;
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
- getStore() {
33
- if (!this.store) {
34
- throw new Error("Expected tree store to be set on TreeListItemRenderer");
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
- return this.store;
76
+ this.renderBind(ptr, expander, treeListRow, id, fiberRoot);
37
77
  }
38
- initialize() {
39
- signalStore.set(this, this.factory, "setup", (_self, listItem) => {
40
- const ptr = getNativeId(listItem.handle);
41
- const expander = new Gtk.TreeExpander();
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 (!(treeListRow instanceof Gtk.TreeListRow))
67
- return;
68
- expander.setListRow(treeListRow);
69
- const stringObject = treeListRow.getItem();
70
- if (!(stringObject instanceof Gtk.StringObject))
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
- signalStore.set(this, this.factory, "teardown", (_self, listItem) => {
86
- const ptr = getNativeId(listItem.handle);
87
- const fiberRoot = this.fiberRoots.get(ptr);
88
- if (fiberRoot) {
89
- this.tornDown.add(ptr);
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 (!fiberRoot)
111
- return;
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 instanceof Gtk.Box) {
133
- box.setSizeRequest(-1, -1);
129
+ if (box) {
130
+ this.clearBoxSizeRequest(box);
134
131
  }
135
132
  });
136
133
  }