@gtkx/react 0.19.0 → 0.21.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 (289) hide show
  1. package/README.md +26 -62
  2. package/dist/components/compound.d.ts +40 -0
  3. package/dist/components/compound.d.ts.map +1 -0
  4. package/dist/components/compound.js +46 -0
  5. package/dist/components/compound.js.map +1 -0
  6. package/dist/components/list.d.ts +75 -0
  7. package/dist/components/list.d.ts.map +1 -0
  8. package/dist/components/list.js +81 -0
  9. package/dist/components/list.js.map +1 -0
  10. package/dist/components/slot-widget.d.ts +15 -0
  11. package/dist/components/slot-widget.d.ts.map +1 -0
  12. package/dist/components/slot-widget.js +37 -0
  13. package/dist/components/slot-widget.js.map +1 -0
  14. package/dist/errors.d.ts +6 -0
  15. package/dist/errors.d.ts.map +1 -1
  16. package/dist/errors.js +8 -6
  17. package/dist/errors.js.map +1 -1
  18. package/dist/generated/compounds.d.ts +2672 -0
  19. package/dist/generated/compounds.d.ts.map +1 -0
  20. package/dist/generated/compounds.js +2624 -0
  21. package/dist/generated/compounds.js.map +1 -0
  22. package/dist/generated/internal.d.ts +6 -7
  23. package/dist/generated/internal.d.ts.map +1 -1
  24. package/dist/generated/internal.js +3054 -1838
  25. package/dist/generated/internal.js.map +1 -1
  26. package/dist/generated/jsx.d.ts +2096 -4970
  27. package/dist/generated/jsx.d.ts.map +1 -1
  28. package/dist/generated/jsx.js +979 -3862
  29. package/dist/generated/jsx.js.map +1 -1
  30. package/dist/generated/registry.d.ts +1 -0
  31. package/dist/generated/registry.d.ts.map +1 -1
  32. package/dist/generated/registry.js +0 -1
  33. package/dist/generated/registry.js.map +1 -1
  34. package/dist/host-config.d.ts.map +1 -1
  35. package/dist/host-config.js +2 -0
  36. package/dist/host-config.js.map +1 -1
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/jsx.d.ts +157 -518
  42. package/dist/jsx.d.ts.map +1 -1
  43. package/dist/jsx.js +6 -393
  44. package/dist/jsx.js.map +1 -1
  45. package/dist/metadata.d.ts +1 -1
  46. package/dist/metadata.d.ts.map +1 -1
  47. package/dist/metadata.js +7 -3
  48. package/dist/metadata.js.map +1 -1
  49. package/dist/node.d.ts +0 -4
  50. package/dist/node.d.ts.map +1 -1
  51. package/dist/node.js +19 -41
  52. package/dist/node.js.map +1 -1
  53. package/dist/nodes/alert-dialog.d.ts +14 -0
  54. package/dist/nodes/alert-dialog.d.ts.map +1 -0
  55. package/dist/nodes/alert-dialog.js +41 -0
  56. package/dist/nodes/alert-dialog.js.map +1 -0
  57. package/dist/nodes/animation.d.ts +5 -4
  58. package/dist/nodes/animation.d.ts.map +1 -1
  59. package/dist/nodes/animation.js +65 -49
  60. package/dist/nodes/animation.js.map +1 -1
  61. package/dist/nodes/application.d.ts.map +1 -1
  62. package/dist/nodes/application.js +4 -0
  63. package/dist/nodes/application.js.map +1 -1
  64. package/dist/nodes/column-view-column.d.ts +19 -19
  65. package/dist/nodes/column-view-column.d.ts.map +1 -1
  66. package/dist/nodes/column-view-column.js +130 -119
  67. package/dist/nodes/column-view-column.js.map +1 -1
  68. package/dist/nodes/container-slot.d.ts +3 -1
  69. package/dist/nodes/container-slot.d.ts.map +1 -1
  70. package/dist/nodes/container-slot.js +28 -16
  71. package/dist/nodes/container-slot.js.map +1 -1
  72. package/dist/nodes/drawing-area.d.ts +3 -1
  73. package/dist/nodes/drawing-area.d.ts.map +1 -1
  74. package/dist/nodes/drawing-area.js +20 -22
  75. package/dist/nodes/drawing-area.js.map +1 -1
  76. package/dist/nodes/event-controller.d.ts.map +1 -1
  77. package/dist/nodes/event-controller.js +6 -16
  78. package/dist/nodes/event-controller.js.map +1 -1
  79. package/dist/nodes/fixed-child.d.ts +1 -0
  80. package/dist/nodes/fixed-child.d.ts.map +1 -1
  81. package/dist/nodes/fixed-child.js +13 -0
  82. package/dist/nodes/fixed-child.js.map +1 -1
  83. package/dist/nodes/grid-child.d.ts +1 -0
  84. package/dist/nodes/grid-child.d.ts.map +1 -1
  85. package/dist/nodes/grid-child.js +13 -0
  86. package/dist/nodes/grid-child.js.map +1 -1
  87. package/dist/nodes/internal/accessible.d.ts.map +1 -1
  88. package/dist/nodes/internal/accessible.js.map +1 -1
  89. package/dist/nodes/internal/bound-item.d.ts +4 -0
  90. package/dist/nodes/internal/bound-item.d.ts.map +1 -0
  91. package/dist/nodes/internal/bound-item.js +2 -0
  92. package/dist/nodes/internal/bound-item.js.map +1 -0
  93. package/dist/nodes/internal/construct.d.ts +1 -8
  94. package/dist/nodes/internal/construct.d.ts.map +1 -1
  95. package/dist/nodes/internal/construct.js +30 -54
  96. package/dist/nodes/internal/construct.js.map +1 -1
  97. package/dist/nodes/internal/widget.d.ts.map +1 -1
  98. package/dist/nodes/internal/widget.js +9 -10
  99. package/dist/nodes/internal/widget.js.map +1 -1
  100. package/dist/nodes/list-item-node.d.ts +12 -0
  101. package/dist/nodes/list-item-node.d.ts.map +1 -0
  102. package/dist/nodes/list-item-node.js +45 -0
  103. package/dist/nodes/list-item-node.js.map +1 -0
  104. package/dist/nodes/list.d.ts +100 -0
  105. package/dist/nodes/list.d.ts.map +1 -0
  106. package/dist/nodes/list.js +950 -0
  107. package/dist/nodes/list.js.map +1 -0
  108. package/dist/nodes/notebook-page.d.ts.map +1 -1
  109. package/dist/nodes/notebook-page.js +6 -2
  110. package/dist/nodes/notebook-page.js.map +1 -1
  111. package/dist/nodes/overlay-child.d.ts +2 -0
  112. package/dist/nodes/overlay-child.d.ts.map +1 -1
  113. package/dist/nodes/overlay-child.js +29 -8
  114. package/dist/nodes/overlay-child.js.map +1 -1
  115. package/dist/nodes/spin-row.d.ts +14 -0
  116. package/dist/nodes/spin-row.d.ts.map +1 -0
  117. package/dist/nodes/spin-row.js +46 -0
  118. package/dist/nodes/spin-row.js.map +1 -0
  119. package/dist/nodes/switch-row.d.ts +11 -0
  120. package/dist/nodes/switch-row.d.ts.map +1 -0
  121. package/dist/nodes/switch-row.js +15 -0
  122. package/dist/nodes/switch-row.js.map +1 -0
  123. package/dist/nodes/text-anchor.d.ts.map +1 -1
  124. package/dist/nodes/text-anchor.js +10 -0
  125. package/dist/nodes/text-anchor.js.map +1 -1
  126. package/dist/nodes/text-tag.d.ts.map +1 -1
  127. package/dist/nodes/text-tag.js +45 -39
  128. package/dist/nodes/text-tag.js.map +1 -1
  129. package/dist/nodes/toggle-group.d.ts +12 -6
  130. package/dist/nodes/toggle-group.d.ts.map +1 -1
  131. package/dist/nodes/toggle-group.js +53 -4
  132. package/dist/nodes/toggle-group.js.map +1 -1
  133. package/dist/nodes/widget.d.ts.map +1 -1
  134. package/dist/nodes/widget.js +16 -22
  135. package/dist/nodes/widget.js.map +1 -1
  136. package/dist/nodes/window.d.ts.map +1 -1
  137. package/dist/nodes/window.js +2 -2
  138. package/dist/nodes/window.js.map +1 -1
  139. package/dist/registry.d.ts +0 -2
  140. package/dist/registry.d.ts.map +1 -1
  141. package/dist/registry.js +11 -18
  142. package/dist/registry.js.map +1 -1
  143. package/dist/types.d.ts +3 -2
  144. package/dist/types.d.ts.map +1 -1
  145. package/dist/use-property.d.ts +29 -0
  146. package/dist/use-property.d.ts.map +1 -0
  147. package/dist/use-property.js +44 -0
  148. package/dist/use-property.js.map +1 -0
  149. package/dist/use-setting.d.ts +36 -0
  150. package/dist/use-setting.d.ts.map +1 -0
  151. package/dist/use-setting.js +68 -0
  152. package/dist/use-setting.js.map +1 -0
  153. package/package.json +5 -4
  154. package/src/components/compound.tsx +57 -0
  155. package/src/components/list.tsx +140 -0
  156. package/src/components/slot-widget.tsx +46 -0
  157. package/src/errors.ts +8 -7
  158. package/src/generated/compounds.ts +2741 -0
  159. package/src/generated/internal.ts +3059 -1840
  160. package/src/generated/jsx.ts +2509 -5350
  161. package/src/generated/registry.ts +2 -1
  162. package/src/host-config.ts +2 -0
  163. package/src/index.ts +2 -0
  164. package/src/jsx.ts +167 -581
  165. package/src/metadata.ts +7 -4
  166. package/src/node.ts +23 -39
  167. package/src/nodes/alert-dialog.ts +55 -0
  168. package/src/nodes/animation.ts +67 -60
  169. package/src/nodes/application.ts +5 -0
  170. package/src/nodes/column-view-column.ts +125 -128
  171. package/src/nodes/container-slot.ts +30 -17
  172. package/src/nodes/drawing-area.ts +23 -32
  173. package/src/nodes/event-controller.ts +6 -18
  174. package/src/nodes/fixed-child.ts +13 -0
  175. package/src/nodes/grid-child.ts +13 -0
  176. package/src/nodes/internal/accessible.ts +0 -1
  177. package/src/nodes/internal/bound-item.ts +4 -0
  178. package/src/nodes/internal/construct.ts +38 -68
  179. package/src/nodes/internal/widget.ts +9 -13
  180. package/src/nodes/list-item-node.ts +53 -0
  181. package/src/nodes/list.ts +1082 -0
  182. package/src/nodes/notebook-page.ts +6 -2
  183. package/src/nodes/overlay-child.ts +30 -9
  184. package/src/nodes/spin-row.ts +72 -0
  185. package/src/nodes/switch-row.ts +26 -0
  186. package/src/nodes/text-anchor.ts +9 -0
  187. package/src/nodes/text-tag.ts +45 -40
  188. package/src/nodes/toggle-group.ts +63 -9
  189. package/src/nodes/widget.ts +14 -26
  190. package/src/nodes/window.ts +2 -2
  191. package/src/registry.ts +18 -24
  192. package/src/types.ts +8 -2
  193. package/src/use-property.ts +58 -0
  194. package/src/use-setting.ts +96 -0
  195. package/dist/fiber-root.d.ts +0 -4
  196. package/dist/fiber-root.d.ts.map +0 -1
  197. package/dist/fiber-root.js +0 -6
  198. package/dist/fiber-root.js.map +0 -1
  199. package/dist/nodes/column-view.d.ts +0 -37
  200. package/dist/nodes/column-view.d.ts.map +0 -1
  201. package/dist/nodes/column-view.js +0 -205
  202. package/dist/nodes/column-view.js.map +0 -1
  203. package/dist/nodes/drop-down.d.ts +0 -37
  204. package/dist/nodes/drop-down.d.ts.map +0 -1
  205. package/dist/nodes/drop-down.js +0 -231
  206. package/dist/nodes/drop-down.js.map +0 -1
  207. package/dist/nodes/grid-view.d.ts +0 -30
  208. package/dist/nodes/grid-view.d.ts.map +0 -1
  209. package/dist/nodes/grid-view.js +0 -90
  210. package/dist/nodes/grid-view.js.map +0 -1
  211. package/dist/nodes/internal/base-item-renderer.d.ts +0 -28
  212. package/dist/nodes/internal/base-item-renderer.d.ts.map +0 -1
  213. package/dist/nodes/internal/base-item-renderer.js +0 -85
  214. package/dist/nodes/internal/base-item-renderer.js.map +0 -1
  215. package/dist/nodes/internal/grid-item-renderer.d.ts +0 -20
  216. package/dist/nodes/internal/grid-item-renderer.d.ts.map +0 -1
  217. package/dist/nodes/internal/grid-item-renderer.js +0 -66
  218. package/dist/nodes/internal/grid-item-renderer.js.map +0 -1
  219. package/dist/nodes/internal/header-item-renderer.d.ts +0 -23
  220. package/dist/nodes/internal/header-item-renderer.d.ts.map +0 -1
  221. package/dist/nodes/internal/header-item-renderer.js +0 -87
  222. package/dist/nodes/internal/header-item-renderer.js.map +0 -1
  223. package/dist/nodes/internal/header-renderer-manager.d.ts +0 -13
  224. package/dist/nodes/internal/header-renderer-manager.d.ts.map +0 -1
  225. package/dist/nodes/internal/header-renderer-manager.js +0 -20
  226. package/dist/nodes/internal/header-renderer-manager.js.map +0 -1
  227. package/dist/nodes/internal/list-item-renderer.d.ts +0 -27
  228. package/dist/nodes/internal/list-item-renderer.d.ts.map +0 -1
  229. package/dist/nodes/internal/list-item-renderer.js +0 -131
  230. package/dist/nodes/internal/list-item-renderer.js.map +0 -1
  231. package/dist/nodes/internal/list-store.d.ts +0 -21
  232. package/dist/nodes/internal/list-store.d.ts.map +0 -1
  233. package/dist/nodes/internal/list-store.js +0 -90
  234. package/dist/nodes/internal/list-store.js.map +0 -1
  235. package/dist/nodes/internal/sectioned-list-store.d.ts +0 -50
  236. package/dist/nodes/internal/sectioned-list-store.d.ts.map +0 -1
  237. package/dist/nodes/internal/sectioned-list-store.js +0 -250
  238. package/dist/nodes/internal/sectioned-list-store.js.map +0 -1
  239. package/dist/nodes/internal/selection-helpers.d.ts +0 -12
  240. package/dist/nodes/internal/selection-helpers.d.ts.map +0 -1
  241. package/dist/nodes/internal/selection-helpers.js +0 -25
  242. package/dist/nodes/internal/selection-helpers.js.map +0 -1
  243. package/dist/nodes/internal/selection-model-controller.d.ts +0 -26
  244. package/dist/nodes/internal/selection-model-controller.d.ts.map +0 -1
  245. package/dist/nodes/internal/selection-model-controller.js +0 -82
  246. package/dist/nodes/internal/selection-model-controller.js.map +0 -1
  247. package/dist/nodes/internal/simple-list-store.d.ts +0 -15
  248. package/dist/nodes/internal/simple-list-store.d.ts.map +0 -1
  249. package/dist/nodes/internal/simple-list-store.js +0 -110
  250. package/dist/nodes/internal/simple-list-store.js.map +0 -1
  251. package/dist/nodes/internal/tree-store.d.ts +0 -37
  252. package/dist/nodes/internal/tree-store.d.ts.map +0 -1
  253. package/dist/nodes/internal/tree-store.js +0 -253
  254. package/dist/nodes/internal/tree-store.js.map +0 -1
  255. package/dist/nodes/list-item.d.ts +0 -24
  256. package/dist/nodes/list-item.d.ts.map +0 -1
  257. package/dist/nodes/list-item.js +0 -83
  258. package/dist/nodes/list-item.js.map +0 -1
  259. package/dist/nodes/list-section.d.ts +0 -27
  260. package/dist/nodes/list-section.d.ts.map +0 -1
  261. package/dist/nodes/list-section.js +0 -43
  262. package/dist/nodes/list-section.js.map +0 -1
  263. package/dist/nodes/list-view.d.ts +0 -32
  264. package/dist/nodes/list-view.d.ts.map +0 -1
  265. package/dist/nodes/list-view.js +0 -123
  266. package/dist/nodes/list-view.js.map +0 -1
  267. package/dist/nodes/models/list.d.ts +0 -39
  268. package/dist/nodes/models/list.d.ts.map +0 -1
  269. package/dist/nodes/models/list.js +0 -207
  270. package/dist/nodes/models/list.js.map +0 -1
  271. package/src/fiber-root.ts +0 -20
  272. package/src/nodes/column-view.ts +0 -262
  273. package/src/nodes/drop-down.ts +0 -284
  274. package/src/nodes/grid-view.ts +0 -119
  275. package/src/nodes/internal/base-item-renderer.ts +0 -107
  276. package/src/nodes/internal/grid-item-renderer.ts +0 -78
  277. package/src/nodes/internal/header-item-renderer.ts +0 -105
  278. package/src/nodes/internal/header-renderer-manager.ts +0 -33
  279. package/src/nodes/internal/list-item-renderer.ts +0 -162
  280. package/src/nodes/internal/list-store.ts +0 -107
  281. package/src/nodes/internal/sectioned-list-store.ts +0 -287
  282. package/src/nodes/internal/selection-helpers.ts +0 -35
  283. package/src/nodes/internal/selection-model-controller.ts +0 -119
  284. package/src/nodes/internal/simple-list-store.ts +0 -116
  285. package/src/nodes/internal/tree-store.ts +0 -289
  286. package/src/nodes/list-item.ts +0 -107
  287. package/src/nodes/list-section.ts +0 -64
  288. package/src/nodes/list-view.ts +0 -164
  289. package/src/nodes/models/list.ts +0 -250
@@ -1,19 +1,34 @@
1
+ import { getNativeId } from "@gtkx/ffi";
1
2
  import * as Gio from "@gtkx/ffi/gio";
3
+ import type * as GObject from "@gtkx/ffi/gobject";
2
4
  import * as Gtk from "@gtkx/ffi/gtk";
3
- import type { ColumnViewColumnProps } from "../jsx.js";
5
+ import type { ColumnViewColumnProps, ListItem } from "../jsx.js";
4
6
  import type { Node } from "../node.js";
5
7
  import type { Container } from "../types.js";
6
- import { GridItemRenderer } from "./internal/grid-item-renderer.js";
7
- import { ListItemRenderer } from "./internal/list-item-renderer.js";
8
- import type { ListStore } from "./internal/list-store.js";
8
+ import type { BoundItem } from "./internal/bound-item.js";
9
9
  import { hasChanged } from "./internal/props.js";
10
- import type { TreeStore } from "./internal/tree-store.js";
11
10
  import { MenuNode } from "./menu.js";
12
11
  import { MenuModel } from "./models/menu.js";
13
12
  import { VirtualNode } from "./virtual.js";
14
13
  import { WidgetNode } from "./widget.js";
15
14
 
16
- export class ColumnViewColumnNode extends VirtualNode<ColumnViewColumnProps, WidgetNode<Gtk.ColumnView>, MenuNode> {
15
+ const UNBOUND_POSITION = -1;
16
+
17
+ export class ColumnViewColumnNode extends VirtualNode<ColumnViewColumnProps, WidgetNode, MenuNode> {
18
+ private column: Gtk.ColumnViewColumn | null = null;
19
+ private columnFactory: Gtk.SignalListItemFactory | null = null;
20
+ private containers = new Map<Gtk.ListItem, number>();
21
+ private containerKeys = new Map<Gtk.ListItem, string>();
22
+ private menu: MenuModel;
23
+ private actionGroup: Gio.SimpleActionGroup;
24
+
25
+ constructor(typeName: string, props: ColumnViewColumnProps, container: undefined, rootContainer: Container) {
26
+ super(typeName, props, container, rootContainer);
27
+ this.actionGroup = new Gio.SimpleActionGroup();
28
+ this.menu = new MenuModel("root", {}, rootContainer, this.actionGroup);
29
+ this.menu.setActionMap(this.actionGroup, props.id);
30
+ }
31
+
17
32
  public override isValidChild(child: Node): boolean {
18
33
  return child instanceof MenuNode;
19
34
  }
@@ -21,172 +36,154 @@ export class ColumnViewColumnNode extends VirtualNode<ColumnViewColumnProps, Wid
21
36
  public override isValidParent(parent: Node): boolean {
22
37
  return parent instanceof WidgetNode && parent.container instanceof Gtk.ColumnView;
23
38
  }
24
- private column: Gtk.ColumnViewColumn;
25
- private treeRenderer: ListItemRenderer | null;
26
- private flatRenderer: GridItemRenderer | null = null;
27
- private menu: MenuModel | null = null;
28
- private actionGroup: Gio.SimpleActionGroup | null = null;
29
- private columnView: Gtk.ColumnView | null = null;
30
39
 
31
- constructor(typeName: string, props: ColumnViewColumnProps, container: undefined, rootContainer: Container) {
32
- super(typeName, props, container, rootContainer);
33
- this.treeRenderer = new ListItemRenderer(this.signalStore);
34
- this.column = new Gtk.ColumnViewColumn();
35
- this.column.setFactory(this.treeRenderer.getFactory());
40
+ public override finalizeInitialChildren(props: ColumnViewColumnProps): boolean {
41
+ this.setupFactory();
42
+ this.setupColumn(props);
43
+ this.updateHeaderMenu();
44
+ return false;
45
+ }
46
+
47
+ public override commitUpdate(oldProps: ColumnViewColumnProps | null, newProps: ColumnViewColumnProps): void {
48
+ super.commitUpdate(oldProps, newProps);
49
+ if (oldProps === null) return;
50
+ this.applyColumnProps(oldProps, newProps);
36
51
  }
37
52
 
38
53
  public override appendChild(child: MenuNode): void {
39
- this.initMenu();
40
- this.menu?.appendChild(child);
54
+ this.menu.appendChild(child);
55
+ this.updateHeaderMenu();
41
56
  }
42
57
 
43
58
  public override insertBefore(child: MenuNode, before: MenuNode): void {
44
- this.initMenu();
45
- if (before instanceof MenuNode) {
46
- this.menu?.insertBefore(child, before);
47
- } else {
48
- this.menu?.appendChild(child);
49
- }
59
+ this.menu.insertBefore(child, before);
60
+ this.updateHeaderMenu();
50
61
  }
51
62
 
52
63
  public override removeChild(child: MenuNode): void {
53
- this.menu?.removeChild(child);
54
-
55
- if (this.menu && this.menu.getMenu().getNItems() === 0) {
56
- this.cleanupMenu();
57
- }
58
- }
59
-
60
- public override commitUpdate(oldProps: ColumnViewColumnProps | null, newProps: ColumnViewColumnProps): void {
61
- super.commitUpdate(oldProps, newProps);
62
- this.applyOwnProps(oldProps, newProps);
64
+ this.menu.removeChild(child);
65
+ this.updateHeaderMenu();
63
66
  }
64
67
 
65
68
  public override detachDeletedInstance(): void {
66
- this.cleanupMenu();
67
- this.treeRenderer?.dispose();
68
- this.flatRenderer?.dispose();
69
69
  super.detachDeletedInstance();
70
70
  }
71
71
 
72
72
  public getColumn(): Gtk.ColumnViewColumn {
73
+ if (!this.column) throw new Error("ColumnViewColumn not initialized");
73
74
  return this.column;
74
75
  }
75
76
 
76
- public rebindItem(id: string): void {
77
- this.treeRenderer?.rebindItem(id);
78
- this.flatRenderer?.rebindItem(id);
79
- }
80
-
81
- public setStore(model: TreeStore | null): void {
82
- this.treeRenderer?.setStore(model);
83
- }
84
-
85
- public setFlatStore(store: ListStore): void {
86
- if (this.treeRenderer) {
87
- this.treeRenderer.dispose();
88
- this.treeRenderer = null;
89
- }
90
- if (!this.flatRenderer) {
91
- this.flatRenderer = new GridItemRenderer(this.signalStore);
92
- this.flatRenderer.setRenderFn(this.props.renderCell);
93
- this.column.setFactory(this.flatRenderer.getFactory());
94
- }
95
- this.flatRenderer.setStore(store);
96
- }
77
+ public collectBoundItems(flatItems: ListItem[]): BoundItem[] {
78
+ const { renderCell } = this.props;
79
+ if (!renderCell) return [];
97
80
 
98
- public setEstimatedRowHeight(height: number | null): void {
99
- this.treeRenderer?.setEstimatedItemHeight(height);
100
- this.flatRenderer?.setEstimatedItemHeight(height);
101
- }
81
+ const items: BoundItem[] = [];
102
82
 
103
- public attachToColumnView(columnView: Gtk.ColumnView): void {
104
- this.columnView = columnView;
83
+ for (const [container, position] of this.containers) {
84
+ if (position === UNBOUND_POSITION) continue;
105
85
 
106
- if (this.actionGroup) {
107
- this.columnView.insertActionGroup(this.props.id, this.actionGroup);
108
- }
109
- }
86
+ const key = this.containerKeys.get(container);
87
+ if (!key) continue;
110
88
 
111
- public detachFromColumnView(): void {
112
- if (this.columnView && this.actionGroup) {
113
- this.columnView.insertActionGroup(this.props.id, null);
89
+ const item = flatItems[position];
90
+ if (!item) continue;
91
+ const content = renderCell(item.value);
92
+ items.push([content, container, key]);
114
93
  }
115
94
 
116
- this.columnView = null;
95
+ return items;
117
96
  }
118
97
 
119
- private initMenu(): void {
120
- if (this.menu) return;
121
-
122
- this.actionGroup = new Gio.SimpleActionGroup();
123
- this.menu = new MenuModel("root", {}, this.rootContainer);
124
- this.menu.setActionMap(this.actionGroup, this.props.id);
125
- this.column.setHeaderMenu(this.menu.getMenu());
98
+ public installActionGroup(widget: Gtk.Widget): void {
99
+ widget.insertActionGroup(this.props.id, this.actionGroup);
100
+ }
126
101
 
127
- if (this.columnView) {
128
- this.columnView.insertActionGroup(this.props.id, this.actionGroup);
129
- }
102
+ public uninstallActionGroup(widget: Gtk.Widget): void {
103
+ widget.insertActionGroup(this.props.id, null);
130
104
  }
131
105
 
132
- private cleanupMenu(): void {
133
- if (!this.menu) return;
106
+ private setupFactory(): void {
107
+ this.columnFactory = new Gtk.SignalListItemFactory();
134
108
 
135
- this.column.setHeaderMenu(null);
109
+ this.columnFactory.connect("setup", (_self: GObject.Object, obj: GObject.Object) => {
110
+ const listItem = obj as unknown as Gtk.ListItem;
111
+ const key = String(getNativeId(listItem.handle));
112
+ const placeholder = new Gtk.Box();
113
+ const { width, height } = this.getParentEstimatedItemSize();
114
+ placeholder.setSizeRequest(width, height);
115
+ listItem.setChild(placeholder);
116
+ this.containers.set(listItem, UNBOUND_POSITION);
117
+ this.containerKeys.set(listItem, key);
118
+ });
136
119
 
137
- if (this.columnView && this.actionGroup) {
138
- this.columnView.insertActionGroup(this.props.id, null);
139
- }
120
+ this.columnFactory.connect("bind", (_self: GObject.Object, obj: GObject.Object) => {
121
+ const listItem = obj as unknown as Gtk.ListItem;
122
+ this.containers.set(listItem, listItem.getPosition());
123
+ this.scheduleParentUpdate();
124
+ });
140
125
 
141
- this.menu = null;
142
- this.actionGroup = null;
126
+ this.columnFactory.connect("unbind", (_self: GObject.Object, obj: GObject.Object) => {
127
+ const listItem = obj as unknown as Gtk.ListItem;
128
+ this.containers.set(listItem, UNBOUND_POSITION);
129
+ this.scheduleParentUpdate();
130
+ });
131
+
132
+ this.columnFactory.connect("teardown", (_self: GObject.Object, obj: GObject.Object) => {
133
+ const listItem = obj as unknown as Gtk.ListItem;
134
+ this.containers.delete(listItem);
135
+ this.containerKeys.delete(listItem);
136
+ listItem.setChild(null);
137
+ });
143
138
  }
144
139
 
145
- private applyOwnProps(oldProps: ColumnViewColumnProps | null, newProps: ColumnViewColumnProps): void {
146
- if (hasChanged(oldProps, newProps, "renderCell")) {
147
- this.treeRenderer?.setRenderFn(newProps.renderCell);
148
- this.flatRenderer?.setRenderFn(newProps.renderCell);
149
- }
140
+ private setupColumn(props: ColumnViewColumnProps): void {
141
+ this.column = new Gtk.ColumnViewColumn(props.title, this.columnFactory);
142
+ this.column.setId(props.id);
150
143
 
151
- if (hasChanged(oldProps, newProps, "title")) {
152
- this.column.setTitle(newProps.title);
153
- }
154
-
155
- if (hasChanged(oldProps, newProps, "expand")) {
156
- this.column.setExpand(newProps.expand ?? false);
157
- }
144
+ if (props.expand !== undefined) this.column.setExpand(props.expand);
145
+ if (props.resizable !== undefined) this.column.setResizable(props.resizable);
146
+ if (props.fixedWidth !== undefined) this.column.setFixedWidth(props.fixedWidth);
147
+ if (props.visible !== undefined) this.column.setVisible(props.visible);
148
+ if (props.sortable) this.column.setSorter(new Gtk.CustomSorter());
149
+ }
158
150
 
159
- if (hasChanged(oldProps, newProps, "resizable")) {
160
- this.column.setResizable(newProps.resizable ?? false);
161
- }
151
+ private applyColumnProps(oldProps: ColumnViewColumnProps, newProps: ColumnViewColumnProps): void {
152
+ if (!this.column) return;
162
153
 
163
- if (hasChanged(oldProps, newProps, "fixedWidth")) {
164
- this.column.setFixedWidth(newProps.fixedWidth ?? -1);
154
+ if (hasChanged(oldProps, newProps, "title")) this.column.setTitle(newProps.title);
155
+ if (hasChanged(oldProps, newProps, "expand")) this.column.setExpand(newProps.expand ?? false);
156
+ if (hasChanged(oldProps, newProps, "resizable")) this.column.setResizable(newProps.resizable ?? false);
157
+ if (hasChanged(oldProps, newProps, "fixedWidth")) this.column.setFixedWidth(newProps.fixedWidth ?? -1);
158
+ if (hasChanged(oldProps, newProps, "visible")) this.column.setVisible(newProps.visible ?? true);
159
+ if (hasChanged(oldProps, newProps, "sortable")) {
160
+ this.column.setSorter(newProps.sortable ? new Gtk.CustomSorter() : null);
165
161
  }
162
+ if (hasChanged(oldProps, newProps, "renderCell")) this.scheduleParentUpdate();
163
+ }
166
164
 
167
- if (hasChanged(oldProps, newProps, "id")) {
168
- if (this.columnView && this.actionGroup && oldProps?.id) {
169
- this.columnView.insertActionGroup(oldProps.id, null);
170
- this.columnView.insertActionGroup(newProps.id, this.actionGroup);
171
- }
172
-
173
- this.column.setId(newProps.id);
174
-
175
- if (oldProps && this.menu && this.actionGroup) {
176
- this.menu.setActionMap(this.actionGroup, newProps.id);
177
- }
178
- }
165
+ private updateHeaderMenu(): void {
166
+ if (!this.column) return;
167
+ const menu = this.menu.getMenu();
168
+ this.column.setHeaderMenu(menu.getNItems() > 0 ? menu : null);
169
+ }
179
170
 
180
- if (hasChanged(oldProps, newProps, "visible")) {
181
- this.column.setVisible(newProps.visible ?? true);
171
+ private getParentEstimatedItemSize(): { width: number; height: number } {
172
+ if (this.parent && "getEstimatedItemSize" in this.parent) {
173
+ return (
174
+ this.parent as { getEstimatedItemSize(): { width: number; height: number } }
175
+ ).getEstimatedItemSize();
182
176
  }
177
+ return { width: -1, height: -1 };
178
+ }
183
179
 
184
- if (hasChanged(oldProps, newProps, "sortable")) {
185
- if (newProps.sortable) {
186
- this.column.setSorter(new Gtk.StringSorter());
187
- } else {
188
- this.column.setSorter(null);
189
- }
180
+ private scheduleParentUpdate(): void {
181
+ if (
182
+ this.parent &&
183
+ "scheduleBoundItemsUpdate" in this.parent &&
184
+ typeof this.parent.scheduleBoundItemsUpdate === "function"
185
+ ) {
186
+ (this.parent as { scheduleBoundItemsUpdate(): void }).scheduleBoundItemsUpdate();
190
187
  }
191
188
  }
192
189
  }
@@ -16,7 +16,7 @@ export class ContainerSlotNode extends VirtualNode<ContainerSlotProps, WidgetNod
16
16
 
17
17
  public override setParent(parent: WidgetNode | null): void {
18
18
  if (!parent && this.parent) {
19
- this.detachAllChildren(this.parent.container);
19
+ this.detachAllFromGtkParent();
20
20
  }
21
21
 
22
22
  super.setParent(parent);
@@ -32,6 +32,7 @@ export class ContainerSlotNode extends VirtualNode<ContainerSlotProps, WidgetNod
32
32
  super.appendChild(child);
33
33
 
34
34
  if (this.parent) {
35
+ this.detachFromGtkParent(child);
35
36
  this.attachToParent(this.parent.container, child.container);
36
37
  }
37
38
  }
@@ -40,25 +41,18 @@ export class ContainerSlotNode extends VirtualNode<ContainerSlotProps, WidgetNod
40
41
  super.insertBefore(child, before);
41
42
 
42
43
  if (this.parent) {
43
- this.attachToParent(this.parent.container, child.container);
44
+ this.reinsertAllChildren();
44
45
  }
45
46
  }
46
47
 
47
48
  public override removeChild(child: WidgetNode): void {
48
- if (this.parent && isRemovable(this.parent.container)) {
49
- const widget = child.container;
50
- const currentParent = widget.getParent();
51
- if (currentParent && currentParent === this.parent.container) {
52
- this.parent.container.remove(widget);
53
- }
54
- }
55
-
49
+ this.detachFromGtkParent(child);
56
50
  super.removeChild(child);
57
51
  }
58
52
 
59
53
  public override detachDeletedInstance(): void {
60
54
  if (this.parent) {
61
- this.detachAllChildren(this.parent.container);
55
+ this.detachAllFromGtkParent();
62
56
  }
63
57
  super.detachDeletedInstance();
64
58
  }
@@ -74,14 +68,33 @@ export class ContainerSlotNode extends VirtualNode<ContainerSlotProps, WidgetNod
74
68
  (method as (child: Gtk.Widget) => void).call(parent, child);
75
69
  }
76
70
 
77
- private detachAllChildren(parent: Gtk.Widget): void {
78
- if (!isRemovable(parent)) return;
71
+ private detachFromGtkParent(child: WidgetNode): void {
72
+ const currentParent = child.container.getParent();
73
+ if (currentParent !== null) {
74
+ if (isRemovable(currentParent)) {
75
+ currentParent.remove(child.container);
76
+ } else {
77
+ child.container.unparent();
78
+ }
79
+ }
80
+ }
81
+
82
+ private reinsertAllChildren(): void {
83
+ if (!this.parent) return;
84
+ const parent = this.parent.container;
79
85
 
80
86
  for (const child of this.children) {
81
- const currentParent = child.container.getParent();
82
- if (currentParent && currentParent === parent) {
83
- parent.remove(child.container);
84
- }
87
+ this.detachFromGtkParent(child);
88
+ }
89
+
90
+ for (const child of this.children) {
91
+ this.attachToParent(parent, child.container);
92
+ }
93
+ }
94
+
95
+ private detachAllFromGtkParent(): void {
96
+ for (const child of this.children) {
97
+ this.detachFromGtkParent(child);
85
98
  }
86
99
  }
87
100
  }
@@ -7,40 +7,16 @@ import { filterProps, hasChanged } from "./internal/props.js";
7
7
  import { SlotNode } from "./slot.js";
8
8
  import { WidgetNode } from "./widget.js";
9
9
 
10
- const OWN_PROPS = ["onDraw"] as const;
10
+ const OWN_PROPS = ["render"] as const;
11
11
 
12
12
  type DrawFunc = (cr: import("@gtkx/ffi/cairo").Context, width: number, height: number, self: Gtk.DrawingArea) => void;
13
13
  type DrawingAreaProps = Pick<GtkDrawingAreaProps, (typeof OWN_PROPS)[number]>;
14
14
 
15
- type PendingDrawFuncEntry = { container: Gtk.DrawingArea; fn: DrawFunc };
16
-
17
- const pendingDrawFuncs: PendingDrawFuncEntry[] = [];
18
-
19
- function wrapDrawFunc(
20
- fn: DrawFunc,
21
- ): (self: Gtk.DrawingArea, cr: import("@gtkx/ffi/cairo").Context, width: number, height: number) => void {
22
- return (self, cr, width, height) => fn(cr, width, height, self);
23
- }
24
-
25
- function ensurePendingBatch(): PendingDrawFuncEntry[] {
26
- if (pendingDrawFuncs.length === 0) {
27
- queueMicrotask(flushPendingDrawFuncs);
28
- }
29
-
30
- return pendingDrawFuncs;
31
- }
32
-
33
- function flushPendingDrawFuncs(): void {
34
- const batch = pendingDrawFuncs.splice(0);
35
-
36
- for (const { container, fn } of batch) {
37
- container.setDrawFunc(wrapDrawFunc(fn));
38
- }
39
- }
40
-
41
15
  type DrawingAreaChild = EventControllerNode | SlotNode | ContainerSlotNode;
42
16
 
43
17
  export class DrawingAreaNode extends WidgetNode<Gtk.DrawingArea, DrawingAreaProps, DrawingAreaChild> {
18
+ private currentDrawFunc: DrawFunc | null = null;
19
+
44
20
  public override isValidChild(child: Node): boolean {
45
21
  return child instanceof EventControllerNode || child instanceof SlotNode || child instanceof ContainerSlotNode;
46
22
  }
@@ -50,12 +26,27 @@ export class DrawingAreaNode extends WidgetNode<Gtk.DrawingArea, DrawingAreaProp
50
26
  this.applyOwnProps(oldProps, newProps);
51
27
  }
52
28
 
29
+ public override detachDeletedInstance(): void {
30
+ this.currentDrawFunc = null;
31
+ this.container.setDrawFunc(undefined);
32
+ super.detachDeletedInstance();
33
+ }
34
+
53
35
  private applyOwnProps(oldProps: DrawingAreaProps | null, newProps: DrawingAreaProps): void {
54
- if (hasChanged(oldProps, newProps, "onDraw")) {
55
- if (this.container.getAllocatedWidth() > 0) {
56
- this.container.setDrawFunc(newProps.onDraw ? wrapDrawFunc(newProps.onDraw) : null);
57
- } else if (newProps.onDraw) {
58
- ensurePendingBatch().push({ container: this.container, fn: newProps.onDraw });
36
+ if (hasChanged(oldProps, newProps, "render")) {
37
+ const hadDraw = !!oldProps?.render;
38
+ const hasDraw = !!newProps.render;
39
+
40
+ this.currentDrawFunc = newProps.render ?? null;
41
+
42
+ if (hasDraw && !hadDraw) {
43
+ this.container.setDrawFunc((self, cr, width, height) => {
44
+ this.currentDrawFunc?.(cr, width, height, self);
45
+ });
46
+ } else if (!hasDraw && hadDraw) {
47
+ this.container.setDrawFunc(undefined);
48
+ } else if (hasDraw) {
49
+ this.container.queueDraw();
59
50
  }
60
51
  }
61
52
  }
@@ -1,9 +1,8 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
- import { CONSTRUCTOR_PROPS } from "../generated/internal.js";
3
2
  import { isConstructOnlyProp, resolvePropMeta, resolveSignal } from "../metadata.js";
4
3
  import { Node } from "../node.js";
5
4
  import type { Props } from "../types.js";
6
- import { createContainerWithConstructOnly } from "./internal/construct.js";
5
+ import { createContainerWithProperties } from "./internal/construct.js";
7
6
  import type { SignalHandler } from "./internal/signal-store.js";
8
7
  import { WidgetNode } from "./widget.js";
9
8
 
@@ -18,19 +17,12 @@ export class EventControllerNode<
18
17
  props: Props,
19
18
  containerClass: typeof Gtk.EventController,
20
19
  ): Gtk.EventController {
21
- const typeName = containerClass.glibTypeName;
22
-
23
- if (typeName === "GtkDropTarget") {
20
+ if (containerClass.glibTypeName === "GtkDropTarget") {
24
21
  const actions = (props.actions as number | undefined) ?? 0;
25
22
  return new Gtk.DropTarget(G_TYPE_INVALID, actions);
26
23
  }
27
24
 
28
- const args = (CONSTRUCTOR_PROPS[typeName] ?? []).map((name) => props[name]);
29
-
30
- return createContainerWithConstructOnly(containerClass, props, () => {
31
- // biome-ignore lint/suspicious/noExplicitAny: Dynamic constructor invocation
32
- return new (containerClass as any)(...args);
33
- }) as Gtk.EventController;
25
+ return createContainerWithProperties(containerClass, props) as Gtk.EventController;
34
26
  }
35
27
 
36
28
  public override isValidChild(child: Node): boolean {
@@ -95,14 +87,10 @@ export class EventControllerNode<
95
87
  return;
96
88
  }
97
89
 
98
- const propMeta = resolvePropMeta(this.container, name);
90
+ const propName = resolvePropMeta(this.container, name);
99
91
 
100
- if (propMeta) {
101
- const [, setterName] = propMeta;
102
- const setterFn = (this.container as unknown as Record<string, (v: unknown) => void>)[setterName];
103
- if (typeof setterFn === "function") {
104
- setterFn.call(this.container, value);
105
- }
92
+ if (propName) {
93
+ (this.container as unknown as Record<string, unknown>)[propName] = value;
106
94
  }
107
95
  }
108
96
  }
@@ -3,6 +3,7 @@ import * as Gsk from "@gtkx/ffi/gsk";
3
3
  import * as Gtk from "@gtkx/ffi/gtk";
4
4
  import type { FixedChildProps } from "../jsx.js";
5
5
  import type { Node } from "../node.js";
6
+ import { isRemovable } from "./internal/predicates.js";
6
7
  import { hasChanged } from "./internal/props.js";
7
8
  import { VirtualNode } from "./virtual.js";
8
9
  import { WidgetNode } from "./widget.js";
@@ -33,6 +34,7 @@ export class FixedChildNode extends VirtualNode<FixedChildProps, WidgetNode<Gtk.
33
34
  super.appendChild(child);
34
35
 
35
36
  if (this.parent) {
37
+ this.detachFromGtkParent(child.container);
36
38
  this.attachToParent(this.parent.container, child.container);
37
39
  this.applyLayoutTransform();
38
40
  }
@@ -82,6 +84,17 @@ export class FixedChildNode extends VirtualNode<FixedChildProps, WidgetNode<Gtk.
82
84
  }
83
85
  }
84
86
 
87
+ private detachFromGtkParent(child: Gtk.Widget): void {
88
+ const currentParent = child.getParent();
89
+ if (currentParent !== null) {
90
+ if (isRemovable(currentParent)) {
91
+ currentParent.remove(child);
92
+ } else {
93
+ child.unparent();
94
+ }
95
+ }
96
+ }
97
+
85
98
  private applyLayoutTransform(): void {
86
99
  if (!this.parent || !this.children[0]) return;
87
100
 
@@ -1,6 +1,7 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import type { GridChildProps } from "../jsx.js";
3
3
  import type { Node } from "../node.js";
4
+ import { isRemovable } from "./internal/predicates.js";
4
5
  import { hasChanged } from "./internal/props.js";
5
6
  import { VirtualNode } from "./virtual.js";
6
7
  import { WidgetNode } from "./widget.js";
@@ -30,6 +31,7 @@ export class GridChildNode extends VirtualNode<GridChildProps, WidgetNode<Gtk.Gr
30
31
  super.appendChild(child);
31
32
 
32
33
  if (this.parent) {
34
+ this.detachFromGtkParent(child.container);
33
35
  this.attachToParent(this.parent.container, child.container);
34
36
  }
35
37
  }
@@ -84,6 +86,17 @@ export class GridChildNode extends VirtualNode<GridChildProps, WidgetNode<Gtk.Gr
84
86
  }
85
87
  }
86
88
 
89
+ private detachFromGtkParent(child: Gtk.Widget): void {
90
+ const currentParent = child.getParent();
91
+ if (currentParent !== null) {
92
+ if (isRemovable(currentParent)) {
93
+ currentParent.remove(child);
94
+ } else {
95
+ child.unparent();
96
+ }
97
+ }
98
+ }
99
+
87
100
  private reattachChild(): void {
88
101
  if (!this.parent || !this.children[0]) return;
89
102
 
@@ -29,7 +29,6 @@ const fromString: CreateValue = (val) => Value.newFromString(val as string);
29
29
  const fromBoolean: CreateValue = (val) => Value.newFromBoolean(val as boolean);
30
30
  const fromInt: CreateValue = (val) => Value.newFromInt(val as number);
31
31
  const fromDouble: CreateValue = (val) => Value.newFromDouble(val as number);
32
-
33
32
  const fromObject: CreateValue = (val) => Value.newFromObject((val as GObject.Object) ?? null);
34
33
 
35
34
  const fromRefList: CreateValue = (val) => {
@@ -0,0 +1,4 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Container } from "../../types.js";
3
+
4
+ export type BoundItem = [ReactNode, Container, string];