@gtkx/react 0.15.0 → 0.17.1

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 (172) hide show
  1. package/README.md +1 -0
  2. package/dist/animation/css-builder.d.ts +3 -0
  3. package/dist/animation/css-builder.js +53 -0
  4. package/dist/animation/types.d.ts +120 -0
  5. package/dist/errors.js +3 -0
  6. package/dist/factory.d.ts +3 -2
  7. package/dist/factory.js +1 -1
  8. package/dist/fiber-root.js +1 -1
  9. package/dist/generated/internal.d.ts +28 -1
  10. package/dist/generated/internal.js +93 -18
  11. package/dist/generated/jsx.d.ts +1672 -1483
  12. package/dist/generated/jsx.js +475 -0
  13. package/dist/host-config.d.ts +3 -1
  14. package/dist/host-config.js +26 -11
  15. package/dist/jsx.d.ts +136 -166
  16. package/dist/jsx.js +58 -69
  17. package/dist/node.d.ts +4 -1
  18. package/dist/node.js +14 -3
  19. package/dist/nodes/abstract/positional-child.d.ts +9 -0
  20. package/dist/nodes/abstract/positional-child.js +29 -0
  21. package/dist/nodes/abstract/virtual-container.d.ts +21 -0
  22. package/dist/nodes/abstract/virtual-container.js +68 -0
  23. package/dist/nodes/abstract/virtual-single-child.d.ts +18 -0
  24. package/dist/nodes/abstract/virtual-single-child.js +55 -0
  25. package/dist/nodes/action-row-child.d.ts +0 -13
  26. package/dist/nodes/action-row-child.js +22 -12
  27. package/dist/nodes/adjustable.d.ts +23 -0
  28. package/dist/nodes/adjustable.js +62 -0
  29. package/dist/nodes/alert-dialog-response.js +86 -0
  30. package/dist/nodes/animation.js +252 -0
  31. package/dist/nodes/application.js +17 -7
  32. package/dist/nodes/autowrapped.js +37 -43
  33. package/dist/nodes/calendar.js +17 -43
  34. package/dist/nodes/color-dialog-button.d.ts +1 -0
  35. package/dist/nodes/color-dialog-button.js +70 -0
  36. package/dist/nodes/column-view-column.d.ts +3 -3
  37. package/dist/nodes/column-view-column.js +1 -1
  38. package/dist/nodes/column-view.js +36 -39
  39. package/dist/nodes/dialog.d.ts +11 -0
  40. package/dist/nodes/dialog.js +20 -0
  41. package/dist/nodes/drawing-area.js +24 -7
  42. package/dist/nodes/event-controller.d.ts +22 -0
  43. package/dist/nodes/event-controller.js +96 -0
  44. package/dist/nodes/expander-row-child.d.ts +0 -14
  45. package/dist/nodes/expander-row-child.js +22 -12
  46. package/dist/nodes/fixed-child.js +52 -36
  47. package/dist/nodes/font-dialog-button.d.ts +1 -0
  48. package/dist/nodes/font-dialog-button.js +90 -0
  49. package/dist/nodes/grid-child.js +43 -45
  50. package/dist/nodes/grid.d.ts +1 -0
  51. package/dist/nodes/grid.js +41 -0
  52. package/dist/nodes/index.d.ts +18 -12
  53. package/dist/nodes/index.js +18 -12
  54. package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
  55. package/dist/nodes/internal/base-item-renderer.js +88 -0
  56. package/dist/nodes/internal/child-attachment.d.ts +26 -0
  57. package/dist/nodes/internal/child-attachment.js +48 -0
  58. package/dist/nodes/internal/deferred-action.d.ts +9 -0
  59. package/dist/nodes/internal/deferred-action.js +22 -0
  60. package/dist/nodes/internal/list-item-renderer.d.ts +14 -15
  61. package/dist/nodes/internal/list-item-renderer.js +51 -77
  62. package/dist/nodes/internal/list-store.d.ts +5 -6
  63. package/dist/nodes/internal/list-store.js +29 -38
  64. package/dist/nodes/internal/predicates.d.ts +25 -2
  65. package/dist/nodes/internal/predicates.js +53 -41
  66. package/dist/nodes/internal/selection-model.d.ts +30 -0
  67. package/dist/nodes/internal/selection-model.js +87 -0
  68. package/dist/nodes/internal/signal-store.d.ts +9 -5
  69. package/dist/nodes/internal/signal-store.js +31 -31
  70. package/dist/nodes/internal/simple-list-store.js +6 -9
  71. package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
  72. package/dist/nodes/internal/text-buffer-controller.js +287 -0
  73. package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
  74. package/dist/nodes/internal/text-tag-styles.js +52 -0
  75. package/dist/nodes/internal/tree-list-item-renderer.d.ts +15 -14
  76. package/dist/nodes/internal/tree-list-item-renderer.js +85 -96
  77. package/dist/nodes/internal/tree-store.d.ts +8 -11
  78. package/dist/nodes/internal/tree-store.js +70 -72
  79. package/dist/nodes/internal/utils.d.ts +7 -4
  80. package/dist/nodes/internal/utils.js +50 -5
  81. package/dist/nodes/level-bar.js +19 -54
  82. package/dist/nodes/list-item.d.ts +6 -3
  83. package/dist/nodes/list-item.js +7 -4
  84. package/dist/nodes/list-view.js +17 -12
  85. package/dist/nodes/menu.d.ts +3 -3
  86. package/dist/nodes/menu.js +3 -3
  87. package/dist/nodes/models/list.d.ts +11 -13
  88. package/dist/nodes/models/list.js +16 -73
  89. package/dist/nodes/models/menu.d.ts +8 -7
  90. package/dist/nodes/models/menu.js +43 -50
  91. package/dist/nodes/models/tree-list.d.ts +6 -12
  92. package/dist/nodes/models/tree-list.js +30 -93
  93. package/dist/nodes/navigation-page.d.ts +1 -0
  94. package/dist/nodes/navigation-page.js +27 -32
  95. package/dist/nodes/navigation-view.js +17 -28
  96. package/dist/nodes/notebook-page-tab.d.ts +3 -3
  97. package/dist/nodes/notebook-page-tab.js +11 -14
  98. package/dist/nodes/notebook-page.d.ts +7 -5
  99. package/dist/nodes/notebook-page.js +45 -25
  100. package/dist/nodes/notebook.js +2 -2
  101. package/dist/nodes/overlay-child.js +90 -30
  102. package/dist/nodes/pack-child.d.ts +0 -13
  103. package/dist/nodes/pack-child.js +22 -12
  104. package/dist/nodes/popover-menu.js +2 -2
  105. package/dist/nodes/scale.js +15 -45
  106. package/dist/nodes/scrolled-window.js +7 -6
  107. package/dist/nodes/search-bar.d.ts +1 -0
  108. package/dist/nodes/search-bar.js +40 -0
  109. package/dist/nodes/shortcut-controller.d.ts +1 -37
  110. package/dist/nodes/shortcut-controller.js +8 -47
  111. package/dist/nodes/shortcut.d.ts +5 -4
  112. package/dist/nodes/shortcut.js +11 -5
  113. package/dist/nodes/simple-list-view.js +2 -3
  114. package/dist/nodes/slot.d.ts +6 -9
  115. package/dist/nodes/slot.js +27 -42
  116. package/dist/nodes/source-view.js +80 -29
  117. package/dist/nodes/stack-page.js +20 -22
  118. package/dist/nodes/stack.js +19 -5
  119. package/dist/nodes/text-anchor.d.ts +41 -0
  120. package/dist/nodes/text-anchor.js +59 -0
  121. package/dist/nodes/text-content.d.ts +10 -0
  122. package/dist/nodes/text-content.js +1 -0
  123. package/dist/nodes/text-paintable.d.ts +17 -0
  124. package/dist/nodes/text-paintable.js +34 -0
  125. package/dist/nodes/text-segment.d.ts +15 -0
  126. package/dist/nodes/text-segment.js +29 -0
  127. package/dist/nodes/text-tag.d.ts +136 -0
  128. package/dist/nodes/text-tag.js +202 -0
  129. package/dist/nodes/text-view.d.ts +30 -0
  130. package/dist/nodes/text-view.js +49 -21
  131. package/dist/nodes/toggle-group.js +24 -32
  132. package/dist/nodes/toggle.d.ts +1 -15
  133. package/dist/nodes/toggle.js +40 -32
  134. package/dist/nodes/toolbar-child.js +22 -31
  135. package/dist/nodes/tree-list-item.d.ts +7 -5
  136. package/dist/nodes/tree-list-item.js +24 -36
  137. package/dist/nodes/tree-list-view.js +9 -7
  138. package/dist/nodes/virtual.d.ts +1 -1
  139. package/dist/nodes/web-view.d.ts +1 -0
  140. package/dist/nodes/web-view.js +29 -0
  141. package/dist/nodes/widget.d.ts +2 -16
  142. package/dist/nodes/widget.js +105 -294
  143. package/dist/nodes/window.d.ts +9 -3
  144. package/dist/nodes/window.js +29 -15
  145. package/dist/registry.d.ts +1 -1
  146. package/dist/render.js +9 -7
  147. package/dist/scheduler.d.ts +11 -1
  148. package/dist/scheduler.js +16 -4
  149. package/dist/types.d.ts +2 -136
  150. package/package.json +4 -4
  151. package/dist/nodes/action-row.js +0 -46
  152. package/dist/nodes/adjustment.d.ts +0 -48
  153. package/dist/nodes/adjustment.js +0 -70
  154. package/dist/nodes/calendar-mark.d.ts +0 -15
  155. package/dist/nodes/calendar-mark.js +0 -29
  156. package/dist/nodes/expander-row.js +0 -55
  157. package/dist/nodes/internal/constants.d.ts +0 -1
  158. package/dist/nodes/internal/constants.js +0 -24
  159. package/dist/nodes/level-bar-offset.d.ts +0 -13
  160. package/dist/nodes/level-bar-offset.js +0 -35
  161. package/dist/nodes/pack.js +0 -46
  162. package/dist/nodes/scale-mark.d.ts +0 -17
  163. package/dist/nodes/scale-mark.js +0 -38
  164. package/dist/nodes/source-buffer.d.ts +0 -73
  165. package/dist/nodes/source-buffer.js +0 -149
  166. package/dist/nodes/text-buffer.d.ts +0 -43
  167. package/dist/nodes/text-buffer.js +0 -81
  168. package/dist/nodes/virtual-child.d.ts +0 -18
  169. package/dist/nodes/virtual-child.js +0 -62
  170. /package/dist/{nodes/action-row.d.ts → animation/types.js} +0 -0
  171. /package/dist/nodes/{expander-row.d.ts → alert-dialog-response.d.ts} +0 -0
  172. /package/dist/nodes/{pack.d.ts → animation.d.ts} +0 -0
@@ -2,24 +2,23 @@ import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import { COLUMN_VIEW_CLASSES } from "../generated/internal.js";
3
3
  import { registerNodeClass } from "../registry.js";
4
4
  import { ColumnViewColumnNode } from "./column-view-column.js";
5
- import { signalStore } from "./internal/signal-store.js";
6
5
  import { filterProps, matchesAnyClass } from "./internal/utils.js";
7
6
  import { ListItemNode } from "./list-item.js";
8
- import { List } from "./models/list.js";
7
+ import { ListModel } from "./models/list.js";
9
8
  import { WidgetNode } from "./widget.js";
10
9
  const PROP_NAMES = ["sortColumn", "sortOrder", "onSortChanged", "estimatedRowHeight"];
11
10
  class ColumnViewNode extends WidgetNode {
12
11
  static priority = 1;
13
- handleSortChange;
12
+ handleSortChange = null;
14
13
  list;
15
14
  columnNodes = new Set();
16
- estimatedRowHeight;
15
+ estimatedRowHeight = null;
17
16
  static matches(_type, containerOrClass) {
18
17
  return matchesAnyClass(COLUMN_VIEW_CLASSES, containerOrClass);
19
18
  }
20
19
  constructor(typeName, props, container, rootContainer) {
21
20
  super(typeName, props, container, rootContainer);
22
- this.list = new List({
21
+ this.list = new ListModel({ owner: this, signalStore: this.signalStore }, {
23
22
  selectionMode: props.selectionMode,
24
23
  selected: props.selected,
25
24
  onSelectionChanged: props.onSelectionChanged,
@@ -41,9 +40,9 @@ class ColumnViewNode extends WidgetNode {
41
40
  if (existingColumn) {
42
41
  this.container.removeColumn(existingColumn);
43
42
  }
44
- this.container.appendColumn(child.column);
45
43
  child.setStore(this.list.getStore());
46
44
  child.setEstimatedRowHeight(this.estimatedRowHeight);
45
+ this.container.appendColumn(child.column);
47
46
  this.columnNodes.add(child);
48
47
  }
49
48
  insertBefore(child, before) {
@@ -58,6 +57,8 @@ class ColumnViewNode extends WidgetNode {
58
57
  if (existingColumn) {
59
58
  this.container.removeColumn(existingColumn);
60
59
  }
60
+ child.setStore(this.list.getStore());
61
+ child.setEstimatedRowHeight(this.estimatedRowHeight);
61
62
  if (before instanceof ColumnViewColumnNode) {
62
63
  const beforeIndex = this.getColumnIndex(before.column);
63
64
  this.container.insertColumn(beforeIndex, child.column);
@@ -65,8 +66,6 @@ class ColumnViewNode extends WidgetNode {
65
66
  else {
66
67
  this.container.appendColumn(child.column);
67
68
  }
68
- child.setStore(this.list.getStore());
69
- child.setEstimatedRowHeight(this.estimatedRowHeight);
70
69
  this.columnNodes.add(child);
71
70
  }
72
71
  removeChild(child) {
@@ -81,10 +80,15 @@ class ColumnViewNode extends WidgetNode {
81
80
  if (existingColumn) {
82
81
  this.container.removeColumn(existingColumn);
83
82
  }
84
- child.setStore(undefined);
83
+ child.setStore(null);
85
84
  this.columnNodes.delete(child);
86
85
  }
87
86
  updateProps(oldProps, newProps) {
87
+ super.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
88
+ this.applyOwnProps(oldProps, newProps);
89
+ this.list.updateProps(oldProps, newProps);
90
+ }
91
+ applyOwnProps(oldProps, newProps) {
88
92
  if (!oldProps || oldProps.onSortChanged !== newProps.onSortChanged) {
89
93
  const sorter = this.container.getSorter();
90
94
  const onSortChanged = newProps.onSortChanged;
@@ -92,7 +96,7 @@ class ColumnViewNode extends WidgetNode {
92
96
  this.handleSortChange = () => {
93
97
  onSortChanged?.(sorter.getPrimarySortColumn()?.getId() ?? null, sorter.getPrimarySortOrder());
94
98
  };
95
- signalStore.set(this, sorter, "changed", this.handleSortChange);
99
+ this.signalStore.set(this, sorter, "changed", this.handleSortChange);
96
100
  }
97
101
  }
98
102
  if (!oldProps || oldProps.sortColumn !== newProps.sortColumn || oldProps.sortOrder !== newProps.sortOrder) {
@@ -106,51 +110,44 @@ class ColumnViewNode extends WidgetNode {
106
110
  }
107
111
  }
108
112
  if (!oldProps || oldProps.estimatedRowHeight !== newProps.estimatedRowHeight) {
109
- this.estimatedRowHeight = newProps.estimatedRowHeight;
113
+ this.estimatedRowHeight = newProps.estimatedRowHeight ?? null;
110
114
  for (const column of this.columnNodes) {
111
115
  column.setEstimatedRowHeight(this.estimatedRowHeight);
112
116
  }
113
117
  }
114
- this.list.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
115
- super.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
116
118
  }
117
- getColumn(columnId) {
119
+ findColumn(predicate) {
118
120
  const columns = this.container.getColumns();
119
121
  for (let i = 0; i < columns.getNItems(); i++) {
120
122
  const column = columns.getObject(i);
121
- if (column.getId() === columnId) {
122
- return column;
123
- }
123
+ const result = predicate(column, i);
124
+ if (result !== null)
125
+ return result;
124
126
  }
125
- throw new Error(`Unable to find column '${columnId}' in ColumnView`);
127
+ return null;
126
128
  }
127
- getColumnIndex(column) {
128
- const index = this.findColumnIndex(column);
129
- if (index === -1) {
130
- throw new Error(`Unable to find column '${column.getId()}' in ColumnView`);
129
+ getColumn(columnId) {
130
+ const column = this.findColumn((col) => (col.getId() === columnId ? col : null));
131
+ if (!column) {
132
+ throw new Error(`Unable to find column '${columnId}' in ColumnView`);
131
133
  }
132
- return index;
134
+ return column;
133
135
  }
134
- findColumnIndex(column) {
135
- const columns = this.container.getColumns();
136
- for (let i = 0; i < columns.getNItems(); i++) {
137
- const col = columns.getObject(i);
138
- if (col.getId() === column.getId()) {
139
- return i;
140
- }
136
+ getColumnIndex(column) {
137
+ const targetId = column.getId();
138
+ const index = this.findColumn((col, i) => (col.getId() === targetId ? i : null));
139
+ if (index === null) {
140
+ throw new Error(`Unable to find column '${targetId}' in ColumnView`);
141
141
  }
142
- return -1;
142
+ return index;
143
143
  }
144
144
  findColumnInView(column) {
145
- const columns = this.container.getColumns();
146
145
  const targetId = column.getId();
147
- for (let i = 0; i < columns.getNItems(); i++) {
148
- const col = columns.getObject(i);
149
- if (col.getId() === targetId) {
150
- return col;
151
- }
152
- }
153
- return null;
146
+ return this.findColumn((col) => (col.getId() === targetId ? col : null));
147
+ }
148
+ unmount() {
149
+ this.columnNodes.clear();
150
+ super.unmount();
154
151
  }
155
152
  }
156
153
  registerNodeClass(ColumnViewNode);
@@ -0,0 +1,11 @@
1
+ import * as Adw from "@gtkx/ffi/adw";
2
+ import type * as Gtk from "@gtkx/ffi/gtk";
3
+ import type { Container, ContainerClass } from "../types.js";
4
+ import { WidgetNode } from "./widget.js";
5
+ export declare class DialogNode extends WidgetNode<Adw.Dialog> {
6
+ static priority: number;
7
+ parent: Gtk.Window | null;
8
+ static matches(_type: string, containerOrClass?: Container | ContainerClass | null): boolean;
9
+ mount(): void;
10
+ unmount(): void;
11
+ }
@@ -0,0 +1,20 @@
1
+ import * as Adw from "@gtkx/ffi/adw";
2
+ import { registerNodeClass } from "../registry.js";
3
+ import { matchesAnyClass } from "./internal/utils.js";
4
+ import { WidgetNode } from "./widget.js";
5
+ export class DialogNode extends WidgetNode {
6
+ static priority = 1;
7
+ parent = null;
8
+ static matches(_type, containerOrClass) {
9
+ return matchesAnyClass([Adw.Dialog], containerOrClass);
10
+ }
11
+ mount() {
12
+ this.container.present(this.parent ?? undefined);
13
+ super.mount();
14
+ }
15
+ unmount() {
16
+ this.container.forceClose();
17
+ super.unmount();
18
+ }
19
+ }
20
+ registerNodeClass(DialogNode);
@@ -1,19 +1,36 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import { registerNodeClass } from "../registry.js";
3
- import { filterProps, isContainerType } from "./internal/utils.js";
3
+ import { filterProps, hasChanged, matchesAnyClass } from "./internal/utils.js";
4
4
  import { WidgetNode } from "./widget.js";
5
- const PROPS = ["onDraw"];
5
+ const OWN_PROPS = ["onDraw"];
6
6
  class DrawingAreaNode extends WidgetNode {
7
7
  static priority = 1;
8
+ pendingDrawFunc = null;
8
9
  static matches(_type, containerOrClass) {
9
- return isContainerType(Gtk.DrawingArea, containerOrClass);
10
+ return matchesAnyClass([Gtk.DrawingArea], containerOrClass);
10
11
  }
11
12
  updateProps(oldProps, newProps) {
12
- if (newProps.onDraw && (!oldProps || oldProps.onDraw !== newProps.onDraw)) {
13
- this.container.setDrawFunc(newProps.onDraw);
14
- this.container.queueDraw();
13
+ super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
14
+ this.applyOwnProps(oldProps, newProps);
15
+ }
16
+ applyOwnProps(oldProps, newProps) {
17
+ if (hasChanged(oldProps, newProps, "onDraw") && newProps.onDraw) {
18
+ if (this.container.getRealized()) {
19
+ this.container.setDrawFunc(newProps.onDraw);
20
+ }
21
+ else {
22
+ this.pendingDrawFunc = newProps.onDraw;
23
+ this.signalStore.set(this, this.container, "realize", this.onRealize.bind(this));
24
+ }
25
+ }
26
+ }
27
+ onRealize() {
28
+ if (this.pendingDrawFunc) {
29
+ const drawFunc = this.pendingDrawFunc;
30
+ this.pendingDrawFunc = null;
31
+ queueMicrotask(() => this.container.setDrawFunc(drawFunc));
15
32
  }
16
- super.updateProps(filterProps(oldProps ?? {}, PROPS), filterProps(newProps, PROPS));
33
+ this.signalStore.set(this, this.container, "realize", null);
17
34
  }
18
35
  }
19
36
  registerNodeClass(DrawingAreaNode);
@@ -0,0 +1,22 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { Node } from "../node.js";
3
+ import type { Container, Props } from "../types.js";
4
+ import type { Attachable } from "./internal/predicates.js";
5
+ export declare class EventControllerNode<T extends Gtk.EventController = Gtk.EventController> extends Node<T, Props> implements Attachable {
6
+ static priority: number;
7
+ static matches(type: string): boolean;
8
+ static createContainer(props: Props, containerClass: typeof Gtk.EventController): Gtk.EventController;
9
+ props: Props;
10
+ protected parentWidget: Gtk.Widget | null;
11
+ constructor(typeName: string, props: Props, container: T, rootContainer: Container);
12
+ canBeChildOf(parent: Node): boolean;
13
+ appendChild(_child: Node): void;
14
+ removeChild(_child: Node): void;
15
+ insertBefore(_child: Node, _before: Node): void;
16
+ attachTo(parent: Node): void;
17
+ detachFrom(_parent: Node): void;
18
+ updateProps(oldProps: Props | null, newProps: Props): void;
19
+ unmount(): void;
20
+ private applyProps;
21
+ private setProperty;
22
+ }
@@ -0,0 +1,96 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { CONTROLLER_CLASSES, CONTROLLER_CONSTRUCTOR_PROPS } from "../generated/internal.js";
3
+ import { Node } from "../node.js";
4
+ import { registerNodeClass } from "../registry.js";
5
+ import { propNameToSignalName, resolvePropMeta, resolveSignal } from "./internal/utils.js";
6
+ import { WidgetNode } from "./widget.js";
7
+ const G_TYPE_INVALID = 0;
8
+ export class EventControllerNode extends Node {
9
+ static priority = 1;
10
+ static matches(type) {
11
+ return type in CONTROLLER_CLASSES;
12
+ }
13
+ static createContainer(props, containerClass) {
14
+ const typeName = containerClass.glibTypeName;
15
+ if (typeName === "GtkDropTarget") {
16
+ const actions = props.actions ?? 0;
17
+ return new Gtk.DropTarget(G_TYPE_INVALID, actions);
18
+ }
19
+ const args = (CONTROLLER_CONSTRUCTOR_PROPS[typeName] ?? []).map((name) => props[name]);
20
+ // biome-ignore lint/suspicious/noExplicitAny: Dynamic constructor invocation
21
+ return new containerClass(...args);
22
+ }
23
+ props;
24
+ parentWidget = null;
25
+ constructor(typeName, props, container, rootContainer) {
26
+ super(typeName, props, container, rootContainer);
27
+ this.props = props;
28
+ }
29
+ canBeChildOf(parent) {
30
+ return parent instanceof WidgetNode;
31
+ }
32
+ appendChild(_child) { }
33
+ removeChild(_child) { }
34
+ insertBefore(_child, _before) { }
35
+ attachTo(parent) {
36
+ if (parent instanceof WidgetNode) {
37
+ this.parentWidget = parent.container;
38
+ parent.container.addController(this.container);
39
+ }
40
+ }
41
+ detachFrom(_parent) {
42
+ if (this.parentWidget) {
43
+ this.parentWidget.removeController(this.container);
44
+ }
45
+ this.parentWidget = null;
46
+ }
47
+ updateProps(oldProps, newProps) {
48
+ this.props = newProps;
49
+ this.applyProps(oldProps, newProps);
50
+ }
51
+ unmount() {
52
+ if (this.parentWidget) {
53
+ this.parentWidget.removeController(this.container);
54
+ }
55
+ this.parentWidget = null;
56
+ super.unmount();
57
+ }
58
+ applyProps(oldProps, newProps) {
59
+ if (!this.container) {
60
+ throw new Error(`EventControllerNode.applyProps: container is undefined for ${this.typeName}`);
61
+ }
62
+ const propNames = new Set([...Object.keys(oldProps ?? {}), ...Object.keys(newProps ?? {})]);
63
+ for (const name of propNames) {
64
+ if (name === "children")
65
+ continue;
66
+ const oldValue = oldProps?.[name];
67
+ const newValue = newProps[name];
68
+ if (oldValue === newValue)
69
+ continue;
70
+ const signalName = propNameToSignalName(name);
71
+ if (resolveSignal(this.container, signalName)) {
72
+ const handler = typeof newValue === "function" ? newValue : undefined;
73
+ this.signalStore.set(this, this.container, signalName, handler, { blockable: false });
74
+ }
75
+ else if (newValue !== undefined) {
76
+ this.setProperty(name, newValue);
77
+ }
78
+ }
79
+ }
80
+ setProperty(name, value) {
81
+ if (name === "types" && this.container instanceof Gtk.DropTarget) {
82
+ const types = value;
83
+ this.container.setGtypes(types.length, types);
84
+ return;
85
+ }
86
+ const propMeta = resolvePropMeta(this.container, name);
87
+ if (propMeta) {
88
+ const [, setterName] = propMeta;
89
+ const setterFn = this.container[setterName];
90
+ if (typeof setterFn === "function") {
91
+ setterFn.call(this.container, value);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ registerNodeClass(EventControllerNode);
@@ -1,15 +1 @@
1
- import type * as Adw from "@gtkx/ffi/adw";
2
- import type * as Gtk from "@gtkx/ffi/gtk";
3
- import { VirtualChildNode } from "./virtual-child.js";
4
- type ExpanderRowWidget = Adw.ExpanderRow & {
5
- addRow(child: Gtk.Widget): void;
6
- addAction(widget: Gtk.Widget): void;
7
- remove(child: Gtk.Widget): void;
8
- };
9
- export declare class ExpanderRowChild extends VirtualChildNode<ExpanderRowWidget> {
10
- static priority: number;
11
- static matches(type: string): boolean;
12
- protected getPositionLabel(): string;
13
- protected attachChild(parent: ExpanderRowWidget, widget: Gtk.Widget): void;
14
- }
15
1
  export {};
@@ -1,20 +1,30 @@
1
1
  import { registerNodeClass } from "../registry.js";
2
- import { VirtualChildNode } from "./virtual-child.js";
3
- export class ExpanderRowChild extends VirtualChildNode {
2
+ import { VirtualContainerNode } from "./abstract/virtual-container.js";
3
+ import { matchesInterface } from "./internal/utils.js";
4
+ const EXPANDER_ROW_INTERFACE_METHODS = ["addRow", "addAction", "remove"];
5
+ class ExpanderRowRowNode extends VirtualContainerNode {
4
6
  static priority = 1;
5
7
  static matches(type) {
6
- return type === "ExpanderRowRow" || type === "ExpanderRowAction";
8
+ return type === "ExpanderRowRow";
7
9
  }
8
- getPositionLabel() {
9
- return this.typeName === "ExpanderRowRow" ? "row" : "action";
10
+ canBeChildOf(parent) {
11
+ return matchesInterface(EXPANDER_ROW_INTERFACE_METHODS, parent.container);
10
12
  }
11
13
  attachChild(parent, widget) {
12
- if (this.getPositionLabel() === "row") {
13
- parent.addRow(widget);
14
- }
15
- else {
16
- parent.addAction(widget);
17
- }
14
+ parent.addRow(widget);
18
15
  }
19
16
  }
20
- registerNodeClass(ExpanderRowChild);
17
+ class ExpanderRowActionNode extends VirtualContainerNode {
18
+ static priority = 1;
19
+ static matches(type) {
20
+ return type === "ExpanderRowAction";
21
+ }
22
+ canBeChildOf(parent) {
23
+ return matchesInterface(EXPANDER_ROW_INTERFACE_METHODS, parent.container);
24
+ }
25
+ attachChild(parent, widget) {
26
+ parent.addAction(widget);
27
+ }
28
+ }
29
+ registerNodeClass(ExpanderRowRowNode);
30
+ registerNodeClass(ExpanderRowActionNode);
@@ -1,53 +1,69 @@
1
- import { batch, isObjectEqual } from "@gtkx/ffi";
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import { registerNodeClass } from "../registry.js";
3
- import { SlotNode } from "./slot.js";
4
- class FixedChildNode extends SlotNode {
3
+ import { PositionalChildNode } from "./abstract/positional-child.js";
4
+ import { hasChanged } from "./internal/utils.js";
5
+ class FixedChildNode extends PositionalChildNode {
5
6
  static priority = 1;
6
7
  static matches(type) {
7
8
  return type === "FixedChild";
8
9
  }
9
- getFixed() {
10
- if (!this.parent) {
11
- throw new Error("Expected Fixed reference to be set on FixedChildNode");
10
+ canBeChildOf(parent) {
11
+ return parent.container instanceof Gtk.Fixed;
12
+ }
13
+ onChildChange(oldChild) {
14
+ super.onChildChange(oldChild);
15
+ if (this.child) {
16
+ this.applyTransform();
12
17
  }
13
- return this.parent;
18
+ }
19
+ attachToParent(parent, child) {
20
+ const fixed = parent;
21
+ const x = this.props.x ?? 0;
22
+ const y = this.props.y ?? 0;
23
+ fixed.put(child, x, y);
24
+ }
25
+ detachFromParent(parent, child) {
26
+ parent.remove(child);
14
27
  }
15
28
  updateProps(oldProps, newProps) {
16
29
  super.updateProps(oldProps, newProps);
17
- if (!oldProps || oldProps.x !== newProps.x || oldProps.y !== newProps.y) {
18
- if (this.parent && this.child) {
19
- this.positionChild();
20
- }
30
+ this.applyOwnProps(oldProps, newProps);
31
+ }
32
+ applyOwnProps(oldProps, newProps) {
33
+ if (!this.parent || !this.child) {
34
+ return;
35
+ }
36
+ const positionChanged = hasChanged(oldProps, newProps, "x") || hasChanged(oldProps, newProps, "y");
37
+ if (positionChanged) {
38
+ this.repositionChild();
39
+ }
40
+ else if (hasChanged(oldProps, newProps, "transform")) {
41
+ this.applyTransform();
21
42
  }
22
43
  }
23
- positionChild() {
24
- const fixed = this.getFixed();
44
+ repositionChild() {
45
+ const fixed = this.getTypedParent();
46
+ const child = this.child;
47
+ if (!child) {
48
+ return;
49
+ }
25
50
  const x = this.props.x ?? 0;
26
51
  const y = this.props.y ?? 0;
27
- if (this.child) {
28
- const child = this.child;
29
- batch(() => {
30
- const currentParent = child.getParent();
31
- if (currentParent && isObjectEqual(currentParent, fixed)) {
32
- fixed.remove(child);
33
- }
34
- fixed.put(child, x, y);
35
- });
36
- }
52
+ fixed.remove(child);
53
+ fixed.put(child, x, y);
54
+ this.applyTransform();
37
55
  }
38
- onChildChange(oldChild) {
39
- const fixed = this.getFixed();
40
- batch(() => {
41
- if (oldChild) {
42
- const parent = oldChild.getParent();
43
- if (parent && isObjectEqual(parent, fixed)) {
44
- fixed.remove(oldChild);
45
- }
46
- }
47
- if (this.child) {
48
- this.positionChild();
49
- }
50
- });
56
+ applyTransform() {
57
+ if (!this.child || !this.props.transform) {
58
+ return;
59
+ }
60
+ const fixed = this.getTypedParent();
61
+ const layoutManager = fixed.getLayoutManager();
62
+ if (!layoutManager) {
63
+ return;
64
+ }
65
+ const layoutChild = layoutManager.getLayoutChild(this.child);
66
+ layoutChild.setTransform(this.props.transform);
51
67
  }
52
68
  }
53
69
  registerNodeClass(FixedChildNode);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,90 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { registerNodeClass } from "../registry.js";
3
+ import { filterProps, hasChanged, matchesAnyClass } from "./internal/utils.js";
4
+ import { WidgetNode } from "./widget.js";
5
+ const OWN_PROPS = [
6
+ "fontDesc",
7
+ "onFontDescChanged",
8
+ "title",
9
+ "modal",
10
+ "language",
11
+ "useFont",
12
+ "useSize",
13
+ "level",
14
+ ];
15
+ class FontDialogButtonNode extends WidgetNode {
16
+ static priority = 1;
17
+ dialog;
18
+ notifyHandler = null;
19
+ static matches(_type, containerOrClass) {
20
+ return matchesAnyClass([Gtk.FontDialogButton], containerOrClass);
21
+ }
22
+ static createContainer(_props, containerClass) {
23
+ const dialog = new Gtk.FontDialog();
24
+ const button = new containerClass(dialog);
25
+ return button;
26
+ }
27
+ constructor(type, props, container, rootContainer) {
28
+ super(type, props, container, rootContainer);
29
+ const dialog = container.getDialog();
30
+ if (!dialog) {
31
+ throw new Error("FontDialogButton must have a dialog");
32
+ }
33
+ this.dialog = dialog;
34
+ }
35
+ updateProps(oldProps, newProps) {
36
+ super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
37
+ this.applyOwnProps(oldProps, newProps);
38
+ }
39
+ applyOwnProps(oldProps, newProps) {
40
+ if (hasChanged(oldProps, newProps, "title") && newProps.title !== undefined) {
41
+ this.dialog.setTitle(newProps.title);
42
+ }
43
+ if (hasChanged(oldProps, newProps, "modal")) {
44
+ this.dialog.setModal(newProps.modal ?? true);
45
+ }
46
+ if (hasChanged(oldProps, newProps, "language") && newProps.language) {
47
+ this.dialog.setLanguage(newProps.language);
48
+ }
49
+ if (hasChanged(oldProps, newProps, "useFont")) {
50
+ this.container.setUseFont(newProps.useFont ?? false);
51
+ }
52
+ if (hasChanged(oldProps, newProps, "useSize")) {
53
+ this.container.setUseSize(newProps.useSize ?? false);
54
+ }
55
+ if (hasChanged(oldProps, newProps, "level")) {
56
+ this.container.setLevel(newProps.level ?? Gtk.FontLevel.FONT);
57
+ }
58
+ if (hasChanged(oldProps, newProps, "fontDesc") && newProps.fontDesc) {
59
+ this.container.setFontDesc(newProps.fontDesc);
60
+ }
61
+ if (hasChanged(oldProps, newProps, "onFontDescChanged")) {
62
+ this.setupNotifyHandler(newProps.onFontDescChanged);
63
+ }
64
+ }
65
+ setupNotifyHandler(callback) {
66
+ if (this.notifyHandler) {
67
+ this.signalStore.set(this, this.container, "notify", undefined);
68
+ this.notifyHandler = null;
69
+ }
70
+ if (callback) {
71
+ this.notifyHandler = (_button, pspec) => {
72
+ if (pspec.getName() === "font-desc") {
73
+ const fontDesc = this.container.getFontDesc();
74
+ if (fontDesc) {
75
+ callback(fontDesc);
76
+ }
77
+ }
78
+ };
79
+ this.signalStore.set(this, this.container, "notify", this.notifyHandler);
80
+ }
81
+ }
82
+ unmount() {
83
+ if (this.notifyHandler) {
84
+ this.signalStore.set(this, this.container, "notify", undefined);
85
+ this.notifyHandler = null;
86
+ }
87
+ super.unmount();
88
+ }
89
+ }
90
+ registerNodeClass(FontDialogButtonNode);