@gtkx/react 0.15.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 (186) hide show
  1. package/README.md +1 -0
  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 +1489 -1300
  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 +107 -166
  12. package/dist/jsx.js +58 -69
  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 +17 -43
  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 +3 -3
  53. package/dist/nodes/column-view-column.js +1 -1
  54. package/dist/nodes/column-view.js +36 -39
  55. package/dist/nodes/dialog.d.ts +11 -0
  56. package/dist/nodes/dialog.js +20 -0
  57. package/dist/nodes/drawing-area.js +24 -7
  58. package/dist/nodes/event-controller.d.ts +1 -0
  59. package/dist/nodes/event-controller.js +96 -0
  60. package/dist/nodes/expander-row-child.d.ts +0 -14
  61. package/dist/nodes/expander-row-child.js +14 -12
  62. package/dist/nodes/expander-row.d.ts +6 -1
  63. package/dist/nodes/expander-row.js +11 -48
  64. package/dist/nodes/fixed-child.js +48 -36
  65. package/dist/nodes/font-dialog-button.d.ts +1 -0
  66. package/dist/nodes/font-dialog-button.js +90 -0
  67. package/dist/nodes/grid-child.js +39 -45
  68. package/dist/nodes/grid.d.ts +1 -0
  69. package/dist/nodes/grid.js +41 -0
  70. package/dist/nodes/index.d.ts +17 -9
  71. package/dist/nodes/index.js +17 -9
  72. package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
  73. package/dist/nodes/internal/base-item-renderer.js +88 -0
  74. package/dist/nodes/internal/base-store.d.ts +9 -0
  75. package/dist/nodes/internal/base-store.js +20 -0
  76. package/dist/nodes/internal/child-attachment.d.ts +26 -0
  77. package/dist/nodes/internal/child-attachment.js +48 -0
  78. package/dist/nodes/internal/deferred-action.d.ts +8 -0
  79. package/dist/nodes/internal/deferred-action.js +19 -0
  80. package/dist/nodes/internal/list-item-renderer.d.ts +14 -15
  81. package/dist/nodes/internal/list-item-renderer.js +51 -77
  82. package/dist/nodes/internal/list-store.d.ts +7 -6
  83. package/dist/nodes/internal/list-store.js +20 -24
  84. package/dist/nodes/internal/predicates.d.ts +25 -2
  85. package/dist/nodes/internal/predicates.js +53 -41
  86. package/dist/nodes/internal/selection-model.d.ts +30 -0
  87. package/dist/nodes/internal/selection-model.js +91 -0
  88. package/dist/nodes/internal/signal-store.d.ts +5 -4
  89. package/dist/nodes/internal/signal-store.js +30 -28
  90. package/dist/nodes/internal/simple-list-store.js +6 -9
  91. package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
  92. package/dist/nodes/internal/text-buffer-controller.js +287 -0
  93. package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
  94. package/dist/nodes/internal/text-tag-styles.js +52 -0
  95. package/dist/nodes/internal/tree-list-item-renderer.d.ts +15 -14
  96. package/dist/nodes/internal/tree-list-item-renderer.js +85 -96
  97. package/dist/nodes/internal/tree-store.d.ts +10 -9
  98. package/dist/nodes/internal/tree-store.js +31 -35
  99. package/dist/nodes/internal/utils.d.ts +7 -4
  100. package/dist/nodes/internal/utils.js +50 -5
  101. package/dist/nodes/level-bar.js +19 -54
  102. package/dist/nodes/list-item.d.ts +6 -3
  103. package/dist/nodes/list-item.js +7 -4
  104. package/dist/nodes/list-view.js +15 -11
  105. package/dist/nodes/menu.d.ts +3 -3
  106. package/dist/nodes/menu.js +3 -3
  107. package/dist/nodes/models/list.d.ts +11 -13
  108. package/dist/nodes/models/list.js +16 -73
  109. package/dist/nodes/models/menu.d.ts +8 -7
  110. package/dist/nodes/models/menu.js +43 -50
  111. package/dist/nodes/models/tree-list.d.ts +6 -12
  112. package/dist/nodes/models/tree-list.js +30 -93
  113. package/dist/nodes/navigation-page.d.ts +1 -0
  114. package/dist/nodes/navigation-page.js +27 -32
  115. package/dist/nodes/navigation-view.js +17 -28
  116. package/dist/nodes/notebook-page-tab.d.ts +3 -3
  117. package/dist/nodes/notebook-page-tab.js +11 -14
  118. package/dist/nodes/notebook-page.d.ts +7 -5
  119. package/dist/nodes/notebook-page.js +45 -25
  120. package/dist/nodes/notebook.js +2 -2
  121. package/dist/nodes/overlay-child.js +90 -30
  122. package/dist/nodes/pack-child.d.ts +0 -13
  123. package/dist/nodes/pack-child.js +14 -12
  124. package/dist/nodes/pack.d.ts +6 -1
  125. package/dist/nodes/pack.js +4 -37
  126. package/dist/nodes/popover-menu.js +2 -2
  127. package/dist/nodes/scale.js +15 -45
  128. package/dist/nodes/scrolled-window.js +7 -6
  129. package/dist/nodes/search-bar.d.ts +1 -0
  130. package/dist/nodes/search-bar.js +40 -0
  131. package/dist/nodes/shortcut-controller.d.ts +1 -37
  132. package/dist/nodes/shortcut-controller.js +24 -8
  133. package/dist/nodes/shortcut.d.ts +5 -4
  134. package/dist/nodes/shortcut.js +11 -5
  135. package/dist/nodes/simple-list-view.js +2 -3
  136. package/dist/nodes/slot.d.ts +6 -9
  137. package/dist/nodes/slot.js +27 -42
  138. package/dist/nodes/source-view.js +80 -29
  139. package/dist/nodes/stack-page.js +20 -22
  140. package/dist/nodes/stack.js +19 -5
  141. package/dist/nodes/text-anchor.d.ts +41 -0
  142. package/dist/nodes/text-anchor.js +59 -0
  143. package/dist/nodes/text-content.d.ts +10 -0
  144. package/dist/nodes/text-content.js +1 -0
  145. package/dist/nodes/text-paintable.d.ts +17 -0
  146. package/dist/nodes/text-paintable.js +34 -0
  147. package/dist/nodes/text-segment.d.ts +15 -0
  148. package/dist/nodes/text-segment.js +29 -0
  149. package/dist/nodes/text-tag.d.ts +136 -0
  150. package/dist/nodes/text-tag.js +202 -0
  151. package/dist/nodes/text-view.d.ts +30 -0
  152. package/dist/nodes/text-view.js +49 -21
  153. package/dist/nodes/toggle-group.js +24 -32
  154. package/dist/nodes/toggle.d.ts +1 -15
  155. package/dist/nodes/toggle.js +40 -32
  156. package/dist/nodes/toolbar-child.js +14 -16
  157. package/dist/nodes/tree-list-item.d.ts +7 -5
  158. package/dist/nodes/tree-list-item.js +24 -36
  159. package/dist/nodes/tree-list-view.js +7 -6
  160. package/dist/nodes/virtual.d.ts +1 -1
  161. package/dist/nodes/widget.d.ts +2 -16
  162. package/dist/nodes/widget.js +105 -294
  163. package/dist/nodes/window.d.ts +9 -3
  164. package/dist/nodes/window.js +29 -15
  165. package/dist/registry.d.ts +1 -1
  166. package/dist/render.js +8 -6
  167. package/dist/scheduler.d.ts +11 -1
  168. package/dist/scheduler.js +16 -4
  169. package/dist/types.d.ts +2 -136
  170. package/package.json +3 -3
  171. package/dist/nodes/adjustment.d.ts +0 -48
  172. package/dist/nodes/adjustment.js +0 -70
  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 -24
  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/source-buffer.d.ts +0 -73
  182. package/dist/nodes/source-buffer.js +0 -149
  183. package/dist/nodes/text-buffer.d.ts +0 -43
  184. package/dist/nodes/text-buffer.js +0 -81
  185. package/dist/nodes/virtual-child.d.ts +0 -18
  186. package/dist/nodes/virtual-child.js +0 -62
@@ -14,11 +14,12 @@ const LIFECYCLE_SIGNALS = new Set([
14
14
  "bind",
15
15
  "unbind",
16
16
  "teardown",
17
+ "load-changed",
18
+ "notify",
17
19
  ]);
18
- class SignalStore {
20
+ export class SignalStore {
19
21
  ownerHandlers = new Map();
20
- blockedHandlers = new Set();
21
- isBlocking = false;
22
+ blockDepth = 0;
22
23
  getOwnerMap(owner) {
23
24
  let map = this.ownerHandlers.get(owner);
24
25
  if (!map) {
@@ -27,6 +28,15 @@ class SignalStore {
27
28
  }
28
29
  return map;
29
30
  }
31
+ wrapHandler(handler, signal) {
32
+ return (...args) => {
33
+ if (this.blockDepth > 0 && !LIFECYCLE_SIGNALS.has(signal)) {
34
+ return;
35
+ }
36
+ const [self, ...rest] = args;
37
+ return handler(...rest, self);
38
+ };
39
+ }
30
40
  disconnect(owner, obj, signal) {
31
41
  const objectId = getNativeId(obj.handle);
32
42
  const key = `${objectId}:${signal}`;
@@ -40,12 +50,9 @@ class SignalStore {
40
50
  connect(owner, obj, signal, handler) {
41
51
  const objectId = getNativeId(obj.handle);
42
52
  const key = `${objectId}:${signal}`;
43
- const handlerId = obj.connect(signal, handler);
53
+ const wrappedHandler = this.wrapHandler(handler, signal);
54
+ const handlerId = obj.connect(signal, wrappedHandler);
44
55
  this.getOwnerMap(owner).set(key, { obj, handlerId });
45
- if (this.isBlocking && !LIFECYCLE_SIGNALS.has(signal)) {
46
- GObject.signalHandlerBlock(obj, handlerId);
47
- this.blockedHandlers.add(handlerId);
48
- }
49
56
  }
50
57
  set(owner, obj, signal, handler) {
51
58
  this.disconnect(owner, obj, signal);
@@ -63,28 +70,23 @@ class SignalStore {
63
70
  }
64
71
  }
65
72
  blockAll() {
66
- this.isBlocking = true;
67
- this.blockedHandlers.clear();
68
- for (const ownerMap of this.ownerHandlers.values()) {
69
- for (const [key, { obj, handlerId }] of ownerMap.entries()) {
70
- if (LIFECYCLE_SIGNALS.has(key.split(":")[1] ?? "")) {
71
- continue;
72
- }
73
- GObject.signalHandlerBlock(obj, handlerId);
74
- this.blockedHandlers.add(handlerId);
75
- }
76
- }
73
+ this.blockDepth++;
77
74
  }
78
75
  unblockAll() {
79
- this.isBlocking = false;
80
- for (const ownerMap of this.ownerHandlers.values()) {
81
- for (const { obj, handlerId } of ownerMap.values()) {
82
- if (this.blockedHandlers.has(handlerId)) {
83
- GObject.signalHandlerUnblock(obj, handlerId);
84
- }
85
- }
76
+ if (this.blockDepth > 0) {
77
+ this.blockDepth--;
86
78
  }
87
- this.blockedHandlers.clear();
88
79
  }
80
+ forceUnblockAll() {
81
+ this.blockDepth = 0;
82
+ }
83
+ }
84
+ const signalStores = new WeakMap();
85
+ export function getSignalStore(rootContainer) {
86
+ let store = signalStores.get(rootContainer);
87
+ if (!store) {
88
+ store = new SignalStore();
89
+ signalStores.set(rootContainer, store);
90
+ }
91
+ return store;
89
92
  }
90
- export const signalStore = new SignalStore();
@@ -1,4 +1,3 @@
1
- import { batch } from "@gtkx/ffi";
2
1
  import * as Gtk from "@gtkx/ffi/gtk";
3
2
  export class SimpleListStore {
4
3
  ids = [];
@@ -9,14 +8,12 @@ export class SimpleListStore {
9
8
  }
10
9
  appendItem(id, label) {
11
10
  const existingIndex = this.ids.indexOf(id);
12
- batch(() => {
13
- if (existingIndex >= 0) {
14
- this.model.remove(existingIndex);
15
- this.ids.splice(existingIndex, 1);
16
- }
17
- this.ids.push(id);
18
- this.model.append(label);
19
- });
11
+ if (existingIndex >= 0) {
12
+ this.model.remove(existingIndex);
13
+ this.ids.splice(existingIndex, 1);
14
+ }
15
+ this.ids.push(id);
16
+ this.model.append(label);
20
17
  }
21
18
  removeItem(id) {
22
19
  const index = this.ids.indexOf(id);
@@ -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,25 +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;
11
+ private renderFn;
12
+ private boundItems;
13
+ setRenderFn(renderFn: TreeRenderItemFn<unknown> | null): void;
14
+ rebindItem(id: string): void;
15
+ protected getStoreTypeName(): string;
21
16
  dispose(): void;
22
- private initialize;
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;
23
24
  private processPendingBind;
24
25
  private renderBind;
25
26
  }