@gtkx/react 0.17.2 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +7 -7
  2. package/dist/factory.d.ts +0 -1
  3. package/dist/factory.js +21 -8
  4. package/dist/generated/internal.d.ts +4 -51
  5. package/dist/generated/internal.js +626 -412
  6. package/dist/generated/jsx.d.ts +453 -958
  7. package/dist/host-config.d.ts +1 -1
  8. package/dist/host-config.js +18 -23
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/jsx.d.ts +579 -302
  12. package/dist/jsx.js +37 -179
  13. package/dist/metadata.d.ts +3 -0
  14. package/dist/metadata.js +26 -0
  15. package/dist/node.d.ts +20 -12
  16. package/dist/node.js +72 -17
  17. package/dist/nodes/adjustable.d.ts +3 -16
  18. package/dist/nodes/adjustable.js +5 -22
  19. package/dist/nodes/alert-dialog-response.d.ts +14 -1
  20. package/dist/nodes/alert-dialog-response.js +36 -62
  21. package/dist/nodes/animation.d.ts +37 -1
  22. package/dist/nodes/animation.js +162 -105
  23. package/dist/nodes/application.d.ts +11 -1
  24. package/dist/nodes/application.js +17 -38
  25. package/dist/nodes/calendar.d.ts +13 -0
  26. package/dist/nodes/calendar.js +10 -16
  27. package/dist/nodes/color-dialog-button.d.ts +13 -0
  28. package/dist/nodes/color-dialog-button.js +10 -38
  29. package/dist/nodes/column-view-column.d.ts +13 -11
  30. package/dist/nodes/column-view-column.js +27 -23
  31. package/dist/nodes/column-view.d.ts +31 -0
  32. package/dist/nodes/column-view.js +44 -44
  33. package/dist/nodes/container-slot.d.ts +15 -0
  34. package/dist/nodes/container-slot.js +68 -0
  35. package/dist/nodes/dialog.d.ts +6 -8
  36. package/dist/nodes/dialog.js +12 -13
  37. package/dist/nodes/drawing-area.d.ts +12 -0
  38. package/dist/nodes/drawing-area.js +24 -24
  39. package/dist/nodes/drop-down.d.ts +22 -0
  40. package/dist/nodes/drop-down.js +72 -0
  41. package/dist/nodes/event-controller.d.ts +8 -17
  42. package/dist/nodes/event-controller.js +20 -42
  43. package/dist/nodes/fixed-child.d.ts +18 -1
  44. package/dist/nodes/fixed-child.js +52 -36
  45. package/dist/nodes/font-dialog-button.d.ts +13 -0
  46. package/dist/nodes/font-dialog-button.js +12 -35
  47. package/dist/nodes/grid-child.d.ts +17 -1
  48. package/dist/nodes/grid-child.js +57 -37
  49. package/dist/nodes/grid-view.d.ts +24 -0
  50. package/dist/nodes/grid-view.js +73 -0
  51. package/dist/nodes/internal/base-item-renderer.d.ts +7 -9
  52. package/dist/nodes/internal/base-item-renderer.js +15 -18
  53. package/dist/nodes/internal/grid-item-renderer.d.ts +17 -0
  54. package/dist/nodes/internal/grid-item-renderer.js +59 -0
  55. package/dist/nodes/internal/list-item-renderer.d.ts +14 -9
  56. package/dist/nodes/internal/list-item-renderer.js +96 -35
  57. package/dist/nodes/internal/list-store.d.ts +5 -0
  58. package/dist/nodes/internal/list-store.js +39 -9
  59. package/dist/nodes/internal/predicates.d.ts +4 -19
  60. package/dist/nodes/internal/predicates.js +1 -20
  61. package/dist/nodes/internal/props.d.ts +5 -0
  62. package/dist/nodes/internal/props.js +42 -0
  63. package/dist/nodes/internal/{selection-model.d.ts → selection-model-controller.d.ts} +4 -9
  64. package/dist/nodes/internal/{selection-model.js → selection-model-controller.js} +6 -15
  65. package/dist/nodes/internal/signal-store.js +12 -5
  66. package/dist/nodes/internal/simple-list-store.d.ts +5 -0
  67. package/dist/nodes/internal/simple-list-store.js +42 -13
  68. package/dist/nodes/internal/text-buffer-controller.d.ts +4 -12
  69. package/dist/nodes/internal/text-buffer-controller.js +32 -33
  70. package/dist/nodes/internal/tree-store.d.ts +7 -0
  71. package/dist/nodes/internal/tree-store.js +75 -18
  72. package/dist/nodes/internal/widget.d.ts +7 -0
  73. package/dist/nodes/internal/widget.js +68 -0
  74. package/dist/nodes/level-bar.d.ts +10 -0
  75. package/dist/nodes/level-bar.js +11 -22
  76. package/dist/nodes/list-item.d.ts +17 -9
  77. package/dist/nodes/list-item.js +67 -12
  78. package/dist/nodes/list-view.d.ts +23 -0
  79. package/dist/nodes/list-view.js +27 -31
  80. package/dist/nodes/menu.d.ts +2 -4
  81. package/dist/nodes/menu.js +0 -6
  82. package/dist/nodes/models/grid.d.ts +27 -0
  83. package/dist/nodes/models/grid.js +68 -0
  84. package/dist/nodes/models/list.d.ts +15 -13
  85. package/dist/nodes/models/list.js +48 -26
  86. package/dist/nodes/models/menu.d.ts +15 -16
  87. package/dist/nodes/models/menu.js +63 -93
  88. package/dist/nodes/navigation-page.d.ts +16 -10
  89. package/dist/nodes/navigation-page.js +108 -31
  90. package/dist/nodes/navigation-view.d.ts +15 -0
  91. package/dist/nodes/navigation-view.js +15 -65
  92. package/dist/nodes/notebook-page-tab.d.ts +10 -12
  93. package/dist/nodes/notebook-page-tab.js +24 -27
  94. package/dist/nodes/notebook-page.d.ts +19 -16
  95. package/dist/nodes/notebook-page.js +75 -56
  96. package/dist/nodes/notebook.d.ts +10 -1
  97. package/dist/nodes/notebook.js +10 -22
  98. package/dist/nodes/overlay-child.d.ts +17 -1
  99. package/dist/nodes/overlay-child.js +53 -75
  100. package/dist/nodes/popover-menu.d.ts +15 -0
  101. package/dist/nodes/popover-menu.js +13 -26
  102. package/dist/nodes/scale.d.ts +8 -0
  103. package/dist/nodes/scale.js +2 -11
  104. package/dist/nodes/scrolled-window.d.ts +9 -0
  105. package/dist/nodes/scrolled-window.js +5 -11
  106. package/dist/nodes/search-bar.d.ts +9 -0
  107. package/dist/nodes/search-bar.js +8 -33
  108. package/dist/nodes/shortcut-controller.d.ts +9 -1
  109. package/dist/nodes/shortcut-controller.js +12 -25
  110. package/dist/nodes/shortcut.d.ts +11 -33
  111. package/dist/nodes/shortcut.js +19 -15
  112. package/dist/nodes/slot.d.ts +16 -15
  113. package/dist/nodes/slot.js +63 -57
  114. package/dist/nodes/source-view.d.ts +16 -0
  115. package/dist/nodes/source-view.js +44 -44
  116. package/dist/nodes/stack-page.d.ts +21 -1
  117. package/dist/nodes/stack-page.js +68 -17
  118. package/dist/nodes/stack.d.ts +11 -0
  119. package/dist/nodes/stack.js +8 -26
  120. package/dist/nodes/text-anchor.d.ts +11 -30
  121. package/dist/nodes/text-anchor.js +20 -22
  122. package/dist/nodes/text-content.d.ts +1 -0
  123. package/dist/nodes/text-content.js +1 -1
  124. package/dist/nodes/text-paintable.d.ts +10 -15
  125. package/dist/nodes/text-paintable.js +16 -9
  126. package/dist/nodes/text-segment.d.ts +12 -10
  127. package/dist/nodes/text-segment.js +19 -11
  128. package/dist/nodes/text-tag.d.ts +20 -119
  129. package/dist/nodes/text-tag.js +153 -119
  130. package/dist/nodes/text-view.d.ts +13 -18
  131. package/dist/nodes/text-view.js +17 -17
  132. package/dist/nodes/toggle-group.d.ts +9 -0
  133. package/dist/nodes/toggle-group.js +8 -33
  134. package/dist/nodes/toggle.d.ts +15 -1
  135. package/dist/nodes/toggle.js +34 -52
  136. package/dist/nodes/virtual.d.ts +3 -10
  137. package/dist/nodes/virtual.js +1 -14
  138. package/dist/nodes/web-view.d.ts +9 -0
  139. package/dist/nodes/web-view.js +10 -24
  140. package/dist/nodes/widget.d.ts +17 -13
  141. package/dist/nodes/widget.js +185 -112
  142. package/dist/nodes/window.d.ts +20 -21
  143. package/dist/nodes/window.js +54 -35
  144. package/dist/registry.d.ts +17 -6
  145. package/dist/registry.js +104 -5
  146. package/dist/render.d.ts +1 -10
  147. package/dist/render.js +1 -13
  148. package/package.json +6 -6
  149. package/dist/animation/css-builder.d.ts +0 -3
  150. package/dist/animation/css-builder.js +0 -53
  151. package/dist/animation/types.d.ts +0 -120
  152. package/dist/animation/types.js +0 -1
  153. package/dist/nodes/abstract/positional-child.d.ts +0 -9
  154. package/dist/nodes/abstract/positional-child.js +0 -29
  155. package/dist/nodes/abstract/virtual-container.d.ts +0 -21
  156. package/dist/nodes/abstract/virtual-container.js +0 -68
  157. package/dist/nodes/abstract/virtual-single-child.d.ts +0 -18
  158. package/dist/nodes/abstract/virtual-single-child.js +0 -55
  159. package/dist/nodes/action-row-child.d.ts +0 -1
  160. package/dist/nodes/action-row-child.js +0 -30
  161. package/dist/nodes/autowrapped.d.ts +0 -1
  162. package/dist/nodes/autowrapped.js +0 -115
  163. package/dist/nodes/expander-row-child.d.ts +0 -1
  164. package/dist/nodes/expander-row-child.js +0 -30
  165. package/dist/nodes/grid.d.ts +0 -1
  166. package/dist/nodes/grid.js +0 -41
  167. package/dist/nodes/index.d.ts +0 -56
  168. package/dist/nodes/index.js +0 -56
  169. package/dist/nodes/internal/child-attachment.d.ts +0 -26
  170. package/dist/nodes/internal/child-attachment.js +0 -48
  171. package/dist/nodes/internal/deferred-action.d.ts +0 -9
  172. package/dist/nodes/internal/deferred-action.js +0 -22
  173. package/dist/nodes/internal/text-tag-styles.d.ts +0 -43
  174. package/dist/nodes/internal/text-tag-styles.js +0 -52
  175. package/dist/nodes/internal/tree-list-item-renderer.d.ts +0 -26
  176. package/dist/nodes/internal/tree-list-item-renderer.js +0 -134
  177. package/dist/nodes/internal/utils.d.ts +0 -12
  178. package/dist/nodes/internal/utils.js +0 -92
  179. package/dist/nodes/models/tree-list.d.ts +0 -28
  180. package/dist/nodes/models/tree-list.js +0 -113
  181. package/dist/nodes/pack-child.d.ts +0 -1
  182. package/dist/nodes/pack-child.js +0 -30
  183. package/dist/nodes/simple-list-item.d.ts +0 -9
  184. package/dist/nodes/simple-list-item.js +0 -9
  185. package/dist/nodes/simple-list-view.d.ts +0 -1
  186. package/dist/nodes/simple-list-view.js +0 -74
  187. package/dist/nodes/toolbar-child.d.ts +0 -1
  188. package/dist/nodes/toolbar-child.js +0 -30
  189. package/dist/nodes/tree-list-item.d.ts +0 -22
  190. package/dist/nodes/tree-list-item.js +0 -90
  191. package/dist/nodes/tree-list-view.d.ts +0 -1
  192. package/dist/nodes/tree-list-view.js +0 -77
  193. package/dist/scheduler.d.ts +0 -26
  194. package/dist/scheduler.js +0 -42
@@ -1,34 +1,23 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
2
- import { registerNodeClass } from "../registry.js";
3
- import { filterProps, matchesAnyClass, shallowArrayEqual } from "./internal/utils.js";
1
+ import { filterProps, shallowArrayEqual } from "./internal/props.js";
4
2
  import { WidgetNode } from "./widget.js";
5
3
  const OWN_PROPS = ["offsets"];
6
- class LevelBarNode extends WidgetNode {
7
- static priority = 1;
8
- appliedOffsetIds = new Set();
9
- static matches(_type, containerOrClass) {
10
- return matchesAnyClass([Gtk.LevelBar], containerOrClass);
4
+ export class LevelBarNode extends WidgetNode {
5
+ appliedOffsets = [];
6
+ commitUpdate(oldProps, newProps) {
7
+ super.commitUpdate(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
8
+ this.applyOwnProps(newProps);
11
9
  }
12
- updateProps(oldProps, newProps) {
13
- super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
14
- this.applyOwnProps(oldProps, newProps);
15
- }
16
- applyOwnProps(oldProps, newProps) {
17
- this.applyOffsets(oldProps, newProps);
18
- }
19
- applyOffsets(oldProps, newProps) {
10
+ applyOwnProps(newProps) {
20
11
  const newOffsets = newProps.offsets ?? [];
21
- if (shallowArrayEqual(oldProps?.offsets ?? [], newOffsets)) {
12
+ if (shallowArrayEqual(this.appliedOffsets, newOffsets)) {
22
13
  return;
23
14
  }
24
- for (const id of this.appliedOffsetIds) {
25
- this.container.removeOffsetValue(id);
15
+ for (const offset of this.appliedOffsets) {
16
+ this.container.removeOffsetValue(offset.id);
26
17
  }
27
- this.appliedOffsetIds.clear();
28
18
  for (const offset of newOffsets) {
29
19
  this.container.addOffsetValue(offset.id, offset.value);
30
- this.appliedOffsetIds.add(offset.id);
31
20
  }
21
+ this.appliedOffsets = [...newOffsets];
32
22
  }
33
23
  }
34
- registerNodeClass(LevelBarNode);
@@ -1,15 +1,23 @@
1
1
  import type { ListItemProps } from "../jsx.js";
2
- import type { ListStore } from "./internal/list-store.js";
2
+ import type { Node } from "../node.js";
3
+ import { type TreeItemData } from "./internal/tree-store.js";
3
4
  import { VirtualNode } from "./virtual.js";
4
- type Props = Partial<ListItemProps>;
5
- export declare class ListItemNode<T extends {
5
+ type ItemStore = {
6
6
  updateItem(id: string, value: unknown): void;
7
- } = ListStore, P extends Props = Props> extends VirtualNode<P> {
8
- static priority: number;
7
+ };
8
+ export declare class ListItemNode extends VirtualNode<ListItemProps, Node, ListItemNode> {
9
9
  private store;
10
- static matches(type: string): boolean;
11
- setStore(store: T | null): void;
12
- updateProps(oldProps: P | null, newProps: P): void;
13
- protected applyOwnProps(oldProps: P | null, newProps: P): void;
10
+ private parentItemId;
11
+ static createItemData(props: ListItemProps): TreeItemData;
12
+ isValidChild(child: Node): boolean;
13
+ appendChild(child: ListItemNode): void;
14
+ insertBefore(child: ListItemNode, before: ListItemNode): void;
15
+ removeChild(child: ListItemNode): void;
16
+ commitUpdate(oldProps: ListItemProps | null, newProps: ListItemProps): void;
17
+ private applyOwnProps;
18
+ setStore(store: ItemStore | null): void;
19
+ getChildNodes(): readonly ListItemNode[];
20
+ setParentItemId(parentId: string | null): void;
21
+ getParentItemId(): string | null;
14
22
  }
15
23
  export {};
@@ -1,27 +1,82 @@
1
- import { registerNodeClass } from "../registry.js";
2
- import { hasChanged } from "./internal/utils.js";
1
+ import { hasChanged } from "./internal/props.js";
2
+ import { TreeStore } from "./internal/tree-store.js";
3
3
  import { VirtualNode } from "./virtual.js";
4
4
  export class ListItemNode extends VirtualNode {
5
- static priority = 1;
6
5
  store = null;
7
- static matches(type) {
8
- return type === "ListItem";
6
+ parentItemId = null;
7
+ static createItemData(props) {
8
+ return {
9
+ value: props.value,
10
+ indentForDepth: props.indentForDepth,
11
+ indentForIcon: props.indentForIcon,
12
+ hideExpander: props.hideExpander,
13
+ };
9
14
  }
10
- setStore(store) {
11
- this.store = store;
15
+ isValidChild(child) {
16
+ return child instanceof ListItemNode;
12
17
  }
13
- updateProps(oldProps, newProps) {
14
- super.updateProps(oldProps, newProps);
18
+ appendChild(child) {
19
+ super.appendChild(child);
20
+ child.setParentItemId(this.props.id);
21
+ if (this.store instanceof TreeStore) {
22
+ this.store.addItem(child.props.id, ListItemNode.createItemData(child.props), this.props.id);
23
+ child.setStore(this.store);
24
+ }
25
+ }
26
+ insertBefore(child, before) {
27
+ super.insertBefore(child, before);
28
+ child.setParentItemId(this.props.id);
29
+ if (this.store instanceof TreeStore) {
30
+ this.store.insertItemBefore(child.props.id, before.props.id, ListItemNode.createItemData(child.props), this.props.id);
31
+ child.setStore(this.store);
32
+ }
33
+ }
34
+ removeChild(child) {
35
+ if (this.store instanceof TreeStore) {
36
+ this.store.removeItem(child.props.id, this.props.id);
37
+ }
38
+ child.setStore(null);
39
+ child.setParentItemId(null);
40
+ super.removeChild(child);
41
+ }
42
+ commitUpdate(oldProps, newProps) {
43
+ super.commitUpdate(oldProps, newProps);
15
44
  this.applyOwnProps(oldProps, newProps);
16
45
  }
17
46
  applyOwnProps(oldProps, newProps) {
18
47
  if (!this.store)
19
48
  return;
20
- if (hasChanged(oldProps, newProps, "id") || hasChanged(oldProps, newProps, "value")) {
21
- if (newProps.id !== undefined) {
49
+ if (this.store instanceof TreeStore) {
50
+ const propsChanged = hasChanged(oldProps, newProps, "id") ||
51
+ hasChanged(oldProps, newProps, "value") ||
52
+ hasChanged(oldProps, newProps, "indentForDepth") ||
53
+ hasChanged(oldProps, newProps, "indentForIcon") ||
54
+ hasChanged(oldProps, newProps, "hideExpander");
55
+ if (propsChanged) {
56
+ this.store.updateItem(newProps.id, ListItemNode.createItemData(newProps));
57
+ }
58
+ }
59
+ else {
60
+ if (hasChanged(oldProps, newProps, "id") || hasChanged(oldProps, newProps, "value")) {
22
61
  this.store.updateItem(newProps.id, newProps.value);
23
62
  }
24
63
  }
25
64
  }
65
+ setStore(store) {
66
+ this.store = store;
67
+ if (store === null || store instanceof TreeStore) {
68
+ for (const child of this.children) {
69
+ child.setStore(store);
70
+ }
71
+ }
72
+ }
73
+ getChildNodes() {
74
+ return this.children;
75
+ }
76
+ setParentItemId(parentId) {
77
+ this.parentItemId = parentId;
78
+ }
79
+ getParentItemId() {
80
+ return this.parentItemId;
81
+ }
26
82
  }
27
- registerNodeClass(ListItemNode);
@@ -1 +1,24 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { GtkListViewProps } from "../jsx.js";
3
+ import type { Node } from "../node.js";
4
+ import type { Container } from "../types.js";
5
+ import { ListItemNode } from "./list-item.js";
6
+ import { type ListModelProps } from "./models/list.js";
7
+ import { WidgetNode } from "./widget.js";
8
+ declare const RENDERER_PROPS: readonly ["renderItem", "estimatedItemHeight"];
9
+ type ListViewProps = Pick<GtkListViewProps, (typeof RENDERER_PROPS)[number]> & ListModelProps;
10
+ export declare class ListViewNode extends WidgetNode<Gtk.ListView, ListViewProps, ListItemNode> {
11
+ private itemRenderer;
12
+ private list;
13
+ isValidChild(child: Node): boolean;
14
+ constructor(typeName: string, props: ListViewProps, container: Gtk.ListView, rootContainer: Container);
15
+ appendChild(child: ListItemNode): void;
16
+ insertBefore(child: ListItemNode, before: ListItemNode): void;
17
+ removeChild(child: ListItemNode): void;
18
+ finalizeInitialChildren(props: ListViewProps): boolean;
19
+ commitUpdate(oldProps: ListViewProps | null, newProps: ListViewProps): void;
20
+ commitMount(): void;
21
+ detachDeletedInstance(): void;
22
+ private applyOwnProps;
23
+ }
1
24
  export {};
@@ -1,22 +1,20 @@
1
- import { isObjectEqual } from "@gtkx/ffi";
2
- import { LIST_WIDGET_CLASSES } from "../generated/internal.js";
3
- import { registerNodeClass } from "../registry.js";
4
1
  import { ListItemRenderer } from "./internal/list-item-renderer.js";
5
- import { filterProps, hasChanged, matchesAnyClass } from "./internal/utils.js";
2
+ import { filterProps, hasChanged } from "./internal/props.js";
6
3
  import { ListItemNode } from "./list-item.js";
7
4
  import { ListModel } from "./models/list.js";
8
5
  import { WidgetNode } from "./widget.js";
9
- const OWN_PROPS = ["renderItem", "estimatedItemHeight"];
10
- class ListViewNode extends WidgetNode {
11
- static priority = 1;
6
+ const RENDERER_PROPS = ["renderItem", "estimatedItemHeight"];
7
+ const OWN_PROPS = [...RENDERER_PROPS, "autoexpand", "selectionMode", "selected", "onSelectionChanged"];
8
+ export class ListViewNode extends WidgetNode {
12
9
  itemRenderer;
13
10
  list;
14
- static matches(_type, containerOrClass) {
15
- return matchesAnyClass(LIST_WIDGET_CLASSES, containerOrClass);
11
+ isValidChild(child) {
12
+ return child instanceof ListItemNode;
16
13
  }
17
14
  constructor(typeName, props, container, rootContainer) {
18
15
  super(typeName, props, container, rootContainer);
19
16
  this.list = new ListModel({ owner: this, signalStore: this.signalStore }, {
17
+ autoexpand: props.autoexpand,
20
18
  selectionMode: props.selectionMode,
21
19
  selected: props.selected,
22
20
  onSelectionChanged: props.onSelectionChanged,
@@ -26,36 +24,35 @@ class ListViewNode extends WidgetNode {
26
24
  this.list.getStore().setOnItemUpdated((id) => this.itemRenderer.rebindItem(id));
27
25
  this.container.setFactory(this.itemRenderer.getFactory());
28
26
  }
29
- mount() {
30
- super.mount();
31
- this.container.setModel(this.list.getSelectionModel());
32
- }
33
- unmount() {
34
- this.itemRenderer.dispose();
35
- super.unmount();
36
- }
37
27
  appendChild(child) {
38
- if (!(child instanceof ListItemNode)) {
39
- throw new Error(`Cannot append '${child.typeName}' to 'ListView': expected x.ListItem`);
40
- }
28
+ super.appendChild(child);
41
29
  this.list.appendChild(child);
42
30
  }
43
31
  insertBefore(child, before) {
44
- if (!(child instanceof ListItemNode) || !(before instanceof ListItemNode)) {
45
- throw new Error(`Cannot insert '${child.typeName}' into 'ListView': expected x.ListItem`);
46
- }
32
+ super.insertBefore(child, before);
47
33
  this.list.insertBefore(child, before);
48
34
  }
49
35
  removeChild(child) {
50
- if (!(child instanceof ListItemNode)) {
51
- throw new Error(`Cannot remove '${child.typeName}' from 'ListView': expected x.ListItem`);
52
- }
53
36
  this.list.removeChild(child);
37
+ super.removeChild(child);
38
+ }
39
+ finalizeInitialChildren(props) {
40
+ super.finalizeInitialChildren(props);
41
+ return true;
54
42
  }
55
- updateProps(oldProps, newProps) {
56
- super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
43
+ commitUpdate(oldProps, newProps) {
44
+ super.commitUpdate(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
57
45
  this.applyOwnProps(oldProps, newProps);
58
46
  }
47
+ commitMount() {
48
+ super.commitMount();
49
+ this.list.flushBatch();
50
+ this.container.setModel(this.list.getSelectionModel());
51
+ }
52
+ detachDeletedInstance() {
53
+ this.itemRenderer.dispose();
54
+ super.detachDeletedInstance();
55
+ }
59
56
  applyOwnProps(oldProps, newProps) {
60
57
  if (hasChanged(oldProps, newProps, "renderItem")) {
61
58
  this.itemRenderer.setRenderFn(newProps.renderItem ?? null);
@@ -64,11 +61,10 @@ class ListViewNode extends WidgetNode {
64
61
  this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight ?? null);
65
62
  }
66
63
  const previousModel = this.list.getSelectionModel();
67
- this.list.updateProps(oldProps, newProps);
64
+ this.list.updateProps(oldProps ? filterProps(oldProps, RENDERER_PROPS) : null, filterProps(newProps, RENDERER_PROPS));
68
65
  const currentModel = this.list.getSelectionModel();
69
- if (!isObjectEqual(previousModel, currentModel)) {
66
+ if (previousModel !== currentModel) {
70
67
  this.container.setModel(currentModel);
71
68
  }
72
69
  }
73
70
  }
74
- registerNodeClass(ListViewNode);
@@ -1,8 +1,6 @@
1
1
  import type { Container } from "../types.js";
2
- import { MenuModel, type MenuProps } from "./models/menu.js";
2
+ import { MenuModel, type MenuModelProps } from "./models/menu.js";
3
3
  export declare class MenuNode extends MenuModel {
4
- static priority: number;
5
- static matches(type: string): boolean;
6
4
  private static getType;
7
- constructor(typeName: string, props: MenuProps, _container: undefined, rootContainer: Container);
5
+ constructor(typeName: string, props: MenuModelProps, _container: undefined, rootContainer: Container);
8
6
  }
@@ -1,11 +1,6 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
- import { registerNodeClass } from "../registry.js";
3
2
  import { MenuModel } from "./models/menu.js";
4
3
  export class MenuNode extends MenuModel {
5
- static priority = 1;
6
- static matches(type) {
7
- return type === "MenuItem" || type === "MenuSection" || type === "MenuSubmenu";
8
- }
9
4
  static getType(typeName) {
10
5
  if (typeName === "MenuItem") {
11
6
  return "item";
@@ -22,4 +17,3 @@ export class MenuNode extends MenuModel {
22
17
  super(MenuNode.getType(typeName), props, rootContainer, undefined, rootContainer instanceof Gtk.Application ? rootContainer : undefined);
23
18
  }
24
19
  }
25
- registerNodeClass(MenuNode);
@@ -0,0 +1,27 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { GtkGridViewProps } from "../../jsx.js";
3
+ import { ListStore } from "../internal/list-store.js";
4
+ import type { SignalStore } from "../internal/signal-store.js";
5
+ import type { ListItemNode } from "../list-item.js";
6
+ export type GridModelProps = Pick<GtkGridViewProps, "selectionMode" | "selected" | "onSelectionChanged">;
7
+ type GridModelConfig = {
8
+ owner: object;
9
+ signalStore: SignalStore;
10
+ };
11
+ export declare class GridModel {
12
+ private config;
13
+ private store;
14
+ private selectionManager;
15
+ private initialSelected;
16
+ constructor(config: GridModelConfig, props?: GridModelProps);
17
+ flushBatch(): void;
18
+ getStore(): ListStore;
19
+ getSelectionModel(): Gtk.NoSelection | Gtk.SingleSelection | Gtk.MultiSelection;
20
+ appendChild(child: ListItemNode): void;
21
+ insertBefore(child: ListItemNode, before: ListItemNode): void;
22
+ removeChild(child: ListItemNode): void;
23
+ updateProps(oldProps: GridModelProps | null, newProps: GridModelProps): void;
24
+ private getSelection;
25
+ private resolveSelectionIndices;
26
+ }
27
+ export {};
@@ -0,0 +1,68 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { ListStore } from "../internal/list-store.js";
3
+ import { SelectionModelController } from "../internal/selection-model-controller.js";
4
+ export class GridModel {
5
+ config;
6
+ store;
7
+ selectionManager;
8
+ initialSelected;
9
+ constructor(config, props = {}) {
10
+ this.config = config;
11
+ this.store = new ListStore();
12
+ this.store.beginBatch();
13
+ this.initialSelected = props.selected;
14
+ this.selectionManager = new SelectionModelController({ ...config, ...props }, this.store.getModel(), () => this.getSelection(), (ids) => this.resolveSelectionIndices(ids), () => this.store.getModel().getNItems());
15
+ }
16
+ flushBatch() {
17
+ this.store.flushBatch();
18
+ this.selectionManager.reapplySelection(this.initialSelected);
19
+ this.initialSelected = undefined;
20
+ }
21
+ getStore() {
22
+ return this.store;
23
+ }
24
+ getSelectionModel() {
25
+ return this.selectionManager.getSelectionModel();
26
+ }
27
+ appendChild(child) {
28
+ child.setStore(this.store);
29
+ this.store.addItem(child.props.id, child.props.value);
30
+ }
31
+ insertBefore(child, before) {
32
+ child.setStore(this.store);
33
+ this.store.insertItemBefore(child.props.id, before.props.id, child.props.value);
34
+ }
35
+ removeChild(child) {
36
+ this.store.removeItem(child.props.id);
37
+ child.setStore(null);
38
+ }
39
+ updateProps(oldProps, newProps) {
40
+ this.selectionManager.update(oldProps ? { ...this.config, ...oldProps } : null, { ...this.config, ...newProps }, this.store.getModel());
41
+ }
42
+ getSelection() {
43
+ const model = this.store.getModel();
44
+ const selection = this.selectionManager.getSelectionModel().getSelection();
45
+ const size = selection.getSize();
46
+ const ids = [];
47
+ for (let i = 0; i < size; i++) {
48
+ const index = selection.getNth(i);
49
+ const id = model.getString(index);
50
+ if (id !== null) {
51
+ ids.push(id);
52
+ }
53
+ }
54
+ return ids;
55
+ }
56
+ resolveSelectionIndices(ids) {
57
+ const model = this.store.getModel();
58
+ const nItems = model.getNItems();
59
+ const selected = new Gtk.Bitset();
60
+ for (const id of ids) {
61
+ const index = model.find(id);
62
+ if (index < nItems) {
63
+ selected.add(index);
64
+ }
65
+ }
66
+ return selected;
67
+ }
68
+ }
@@ -1,12 +1,9 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
- import type { Node } from "../../node.js";
3
- import { ListStore } from "../internal/list-store.js";
2
+ import type { GtkListViewProps } from "../../jsx.js";
4
3
  import type { SignalStore } from "../internal/signal-store.js";
5
- export type ListProps = {
6
- selectionMode?: Gtk.SelectionMode;
7
- selected?: string[];
8
- onSelectionChanged?: (ids: string[]) => void;
9
- };
4
+ import { TreeStore } from "../internal/tree-store.js";
5
+ import { ListItemNode } from "../list-item.js";
6
+ export type ListModelProps = Pick<GtkListViewProps, "autoexpand" | "selectionMode" | "selected" | "onSelectionChanged">;
10
7
  type ListModelConfig = {
11
8
  owner: object;
12
9
  signalStore: SignalStore;
@@ -14,14 +11,19 @@ type ListModelConfig = {
14
11
  export declare class ListModel {
15
12
  private config;
16
13
  private store;
14
+ private treeListModel;
17
15
  private selectionManager;
18
- constructor(config: ListModelConfig, props?: ListProps);
19
- getStore(): ListStore;
16
+ private initialSelected;
17
+ constructor(config: ListModelConfig, props?: ListModelProps);
18
+ flushBatch(): void;
19
+ private createChildModel;
20
+ getStore(): TreeStore;
20
21
  getSelectionModel(): Gtk.NoSelection | Gtk.SingleSelection | Gtk.MultiSelection;
21
- appendChild(child: Node): void;
22
- insertBefore(child: Node, before: Node): void;
23
- removeChild(child: Node): void;
24
- updateProps(oldProps: ListProps | null, newProps: ListProps): void;
22
+ appendChild(child: ListItemNode): void;
23
+ private addItemWithChildren;
24
+ insertBefore(child: ListItemNode, before: ListItemNode): void;
25
+ removeChild(child: ListItemNode): void;
26
+ updateProps(oldProps: ListModelProps | null, newProps: ListModelProps): void;
25
27
  private getSelection;
26
28
  private resolveSelectionIndices;
27
29
  }
@@ -1,15 +1,31 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
- import { ListStore } from "../internal/list-store.js";
3
- import { SelectionModelManager } from "../internal/selection-model.js";
2
+ import { SelectionModelController } from "../internal/selection-model-controller.js";
3
+ import { TreeStore } from "../internal/tree-store.js";
4
4
  import { ListItemNode } from "../list-item.js";
5
5
  export class ListModel {
6
6
  config;
7
7
  store;
8
+ treeListModel;
8
9
  selectionManager;
10
+ initialSelected;
9
11
  constructor(config, props = {}) {
10
12
  this.config = config;
11
- this.store = new ListStore();
12
- this.selectionManager = new SelectionModelManager({ ...config, ...props }, this.store.getModel(), () => this.getSelection(), (ids) => this.resolveSelectionIndices(ids), () => this.store.getModel().getNItems());
13
+ this.store = new TreeStore();
14
+ this.store.beginBatch();
15
+ this.initialSelected = props.selected;
16
+ this.treeListModel = new Gtk.TreeListModel(this.store.getRootModel(), false, props.autoexpand ?? false, (item) => this.createChildModel(item));
17
+ this.selectionManager = new SelectionModelController({ ...config, ...props }, this.treeListModel, () => this.getSelection(), (ids) => this.resolveSelectionIndices(ids), () => this.treeListModel.getNItems());
18
+ }
19
+ flushBatch() {
20
+ this.store.flushBatch();
21
+ this.selectionManager.reapplySelection(this.initialSelected);
22
+ this.initialSelected = undefined;
23
+ }
24
+ createChildModel(item) {
25
+ if (!(item instanceof Gtk.StringObject))
26
+ return null;
27
+ const parentId = item.getString();
28
+ return this.store.getChildrenModel(parentId);
13
29
  }
14
30
  getStore() {
15
31
  return this.store;
@@ -18,51 +34,57 @@ export class ListModel {
18
34
  return this.selectionManager.getSelectionModel();
19
35
  }
20
36
  appendChild(child) {
21
- if (!(child instanceof ListItemNode)) {
22
- return;
23
- }
24
37
  child.setStore(this.store);
25
- this.store.addItem(child.props.id, child.props.value);
38
+ this.addItemWithChildren(child);
26
39
  }
27
- insertBefore(child, before) {
28
- if (!(child instanceof ListItemNode) || !(before instanceof ListItemNode)) {
29
- return;
40
+ addItemWithChildren(node, parentId) {
41
+ const id = node.props.id;
42
+ for (const child of node.getChildNodes()) {
43
+ this.addItemWithChildren(child, id);
30
44
  }
45
+ this.store.addItem(id, ListItemNode.createItemData(node.props), parentId);
46
+ }
47
+ insertBefore(child, before) {
31
48
  child.setStore(this.store);
32
- this.store.insertItemBefore(child.props.id, before.props.id, child.props.value);
49
+ this.store.insertItemBefore(child.props.id, before.props.id, ListItemNode.createItemData(child.props));
33
50
  }
34
51
  removeChild(child) {
35
- if (!(child instanceof ListItemNode)) {
36
- return;
37
- }
38
52
  this.store.removeItem(child.props.id);
39
53
  child.setStore(null);
40
54
  }
41
55
  updateProps(oldProps, newProps) {
42
- this.selectionManager.update(oldProps ? { ...this.config, ...oldProps } : null, { ...this.config, ...newProps }, this.store.getModel());
56
+ if (!oldProps || oldProps.autoexpand !== newProps.autoexpand) {
57
+ this.treeListModel.setAutoexpand(newProps.autoexpand ?? false);
58
+ }
59
+ this.selectionManager.update(oldProps ? { ...this.config, ...oldProps } : null, { ...this.config, ...newProps }, this.treeListModel);
43
60
  }
44
61
  getSelection() {
45
- const model = this.store.getModel();
46
62
  const selection = this.selectionManager.getSelectionModel().getSelection();
47
63
  const size = selection.getSize();
48
64
  const ids = [];
49
65
  for (let i = 0; i < size; i++) {
50
66
  const index = selection.getNth(i);
51
- const id = model.getString(index);
52
- if (id !== null) {
53
- ids.push(id);
67
+ const row = this.treeListModel.getRow(index);
68
+ if (!row)
69
+ continue;
70
+ const item = row.getItem();
71
+ if (item instanceof Gtk.StringObject) {
72
+ ids.push(item.getString());
54
73
  }
55
74
  }
56
75
  return ids;
57
76
  }
58
77
  resolveSelectionIndices(ids) {
59
- const model = this.store.getModel();
60
- const nItems = model.getNItems();
78
+ const nItems = this.treeListModel.getNItems();
61
79
  const selected = new Gtk.Bitset();
62
- for (const id of ids) {
63
- const index = model.find(id);
64
- if (index < nItems) {
65
- selected.add(index);
80
+ const idSet = new Set(ids);
81
+ for (let i = 0; i < nItems; i++) {
82
+ const row = this.treeListModel.getRow(i);
83
+ if (!row)
84
+ continue;
85
+ const item = row.getItem();
86
+ if (item instanceof Gtk.StringObject && idSet.has(item.getString())) {
87
+ selected.add(i);
66
88
  }
67
89
  }
68
90
  return selected;
@@ -3,45 +3,44 @@ import type * as Gtk from "@gtkx/ffi/gtk";
3
3
  import type { Node } from "../../node.js";
4
4
  import type { Container } from "../../types.js";
5
5
  import { VirtualNode } from "../virtual.js";
6
- export type MenuType = "root" | "item" | "section" | "submenu";
7
- export type MenuProps = {
6
+ export type MenuModelProps = {
8
7
  id?: string;
9
8
  label?: string;
10
9
  accels?: string | string[];
11
- onActivate?: () => void;
10
+ onActivate?: () => boolean | undefined;
12
11
  };
13
- export declare class MenuModel extends VirtualNode<MenuProps> {
12
+ export type MenuType = "root" | "item" | "section" | "submenu";
13
+ export declare class MenuModel extends VirtualNode<MenuModelProps, MenuModel, MenuModel> {
14
14
  private actionMap;
15
15
  private actionPrefix;
16
- private parent;
17
16
  private menu;
18
17
  private type;
19
18
  private application;
20
19
  private action;
21
- private children;
22
- constructor(type: MenuType, props: MenuProps, rootContainer: Container, actionMap?: Gio.ActionMap, application?: Gtk.Application);
20
+ constructor(type: MenuType, props: MenuModelProps, rootContainer: Container, actionMap?: Gio.ActionMap, application?: Gtk.Application);
21
+ isValidChild(child: Node): boolean;
22
+ isValidParent(parent: Node): boolean;
23
23
  setActionMap(actionMap: Gio.ActionMap, prefix: string): void;
24
24
  private getAccels;
25
25
  private getActionName;
26
26
  private getOnActivate;
27
27
  private getId;
28
- private getParent;
28
+ private getParentMenu;
29
29
  private getActionMap;
30
30
  createAction(): void;
31
31
  private removeAction;
32
32
  private getPosition;
33
33
  private findPositionIn;
34
- private setParent;
35
34
  getMenu(): Gio.Menu;
36
35
  private getAction;
37
- removeFromParent(): void;
36
+ removeFromParentMenu(): void;
38
37
  insertInParentBefore(before: MenuModel): void;
39
- appendToParent(): void;
40
- appendChild(child: Node): void;
41
- insertBefore(child: Node, before: Node): void;
42
- removeChild(child: Node): void;
43
- updateProps(oldProps: MenuProps | null, newProps: MenuProps): void;
38
+ appendToParentMenu(): void;
39
+ appendChild(child: MenuModel): void;
40
+ insertBefore(child: MenuModel, before: MenuModel): void;
41
+ removeChild(child: MenuModel): void;
42
+ commitUpdate(oldProps: MenuModelProps | null, newProps: MenuModelProps): void;
44
43
  private updateItemProps;
45
44
  private updateContainerProps;
46
- unmount(): void;
45
+ detachDeletedInstance(): void;
47
46
  }