@gtkx/react 0.13.3 → 0.15.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 (62) hide show
  1. package/README.md +8 -7
  2. package/dist/generated/internal.js +98 -0
  3. package/dist/generated/jsx.d.ts +908 -1572
  4. package/dist/host-config.js +2 -2
  5. package/dist/jsx.d.ts +176 -36
  6. package/dist/jsx.js +96 -5
  7. package/dist/nodes/adjustment.d.ts +48 -0
  8. package/dist/nodes/adjustment.js +70 -0
  9. package/dist/nodes/application.js +6 -6
  10. package/dist/nodes/calendar.js +3 -16
  11. package/dist/nodes/column-view-column.d.ts +1 -0
  12. package/dist/nodes/column-view-column.js +4 -0
  13. package/dist/nodes/column-view.js +6 -6
  14. package/dist/nodes/drawing-area.d.ts +1 -0
  15. package/dist/nodes/drawing-area.js +19 -0
  16. package/dist/nodes/expander-row.js +1 -0
  17. package/dist/nodes/index.d.ts +9 -0
  18. package/dist/nodes/index.js +9 -0
  19. package/dist/nodes/internal/constants.js +14 -0
  20. package/dist/nodes/internal/list-item-renderer.d.ts +1 -0
  21. package/dist/nodes/internal/list-item-renderer.js +6 -1
  22. package/dist/nodes/internal/predicates.d.ts +4 -0
  23. package/dist/nodes/internal/predicates.js +3 -0
  24. package/dist/nodes/internal/signal-store.d.ts +1 -0
  25. package/dist/nodes/internal/signal-store.js +7 -0
  26. package/dist/nodes/internal/tree-list-item-renderer.d.ts +1 -0
  27. package/dist/nodes/internal/tree-list-item-renderer.js +9 -1
  28. package/dist/nodes/level-bar.js +3 -16
  29. package/dist/nodes/list-view.js +11 -2
  30. package/dist/nodes/models/list.d.ts +6 -1
  31. package/dist/nodes/models/list.js +21 -6
  32. package/dist/nodes/models/tree-list.d.ts +6 -1
  33. package/dist/nodes/models/tree-list.js +21 -7
  34. package/dist/nodes/navigation-page.js +32 -23
  35. package/dist/nodes/notebook-page-tab.d.ts +1 -0
  36. package/dist/nodes/notebook-page-tab.js +15 -9
  37. package/dist/nodes/notebook-page.js +9 -6
  38. package/dist/nodes/scale.js +3 -16
  39. package/dist/nodes/scrolled-window.d.ts +1 -0
  40. package/dist/nodes/scrolled-window.js +22 -0
  41. package/dist/nodes/shortcut-controller.d.ts +37 -0
  42. package/dist/nodes/shortcut-controller.js +74 -0
  43. package/dist/nodes/shortcut.d.ts +38 -0
  44. package/dist/nodes/shortcut.js +46 -0
  45. package/dist/nodes/slot.js +11 -2
  46. package/dist/nodes/source-buffer.d.ts +73 -0
  47. package/dist/nodes/source-buffer.js +149 -0
  48. package/dist/nodes/source-view.d.ts +1 -0
  49. package/dist/nodes/source-view.js +42 -0
  50. package/dist/nodes/stack-page.js +15 -9
  51. package/dist/nodes/text-buffer.d.ts +43 -0
  52. package/dist/nodes/text-buffer.js +81 -0
  53. package/dist/nodes/text-view.d.ts +1 -0
  54. package/dist/nodes/text-view.js +45 -0
  55. package/dist/nodes/tree-list-view.js +11 -2
  56. package/dist/nodes/widget.d.ts +9 -0
  57. package/dist/nodes/widget.js +166 -13
  58. package/dist/nodes/window.js +7 -5
  59. package/dist/render.d.ts +14 -14
  60. package/dist/render.js +14 -14
  61. package/dist/types.d.ts +110 -1
  62. package/package.json +3 -3
@@ -3,7 +3,6 @@ import { registerNodeClass } from "../registry.js";
3
3
  import { CommitPriority, scheduleAfterCommit } from "../scheduler.js";
4
4
  import { CalendarMarkNode } from "./calendar-mark.js";
5
5
  import { isContainerType } from "./internal/utils.js";
6
- import { SlotNode } from "./slot.js";
7
6
  import { WidgetNode } from "./widget.js";
8
7
  class CalendarNode extends WidgetNode {
9
8
  static priority = 1;
@@ -18,11 +17,7 @@ class CalendarNode extends WidgetNode {
18
17
  scheduleAfterCommit(() => child.addMark());
19
18
  return;
20
19
  }
21
- if (child instanceof SlotNode || child instanceof WidgetNode) {
22
- super.appendChild(child);
23
- return;
24
- }
25
- throw new Error(`Cannot append '${child.typeName}' to 'Calendar': expected x.CalendarMark or Widget`);
20
+ super.appendChild(child);
26
21
  }
27
22
  insertBefore(child, before) {
28
23
  if (child instanceof CalendarMarkNode) {
@@ -37,11 +32,7 @@ class CalendarNode extends WidgetNode {
37
32
  this.scheduleRebuildAllMarks();
38
33
  return;
39
34
  }
40
- if (child instanceof SlotNode || child instanceof WidgetNode) {
41
- super.insertBefore(child, before);
42
- return;
43
- }
44
- throw new Error(`Cannot insert '${child.typeName}' into 'Calendar': expected x.CalendarMark or Widget`);
35
+ super.insertBefore(child, before);
45
36
  }
46
37
  removeChild(child) {
47
38
  if (child instanceof CalendarMarkNode) {
@@ -52,11 +43,7 @@ class CalendarNode extends WidgetNode {
52
43
  this.scheduleRebuildAllMarks(CommitPriority.HIGH);
53
44
  return;
54
45
  }
55
- if (child instanceof SlotNode || child instanceof WidgetNode) {
56
- super.removeChild(child);
57
- return;
58
- }
59
- throw new Error(`Cannot remove '${child.typeName}' from 'Calendar': expected x.CalendarMark or Widget`);
46
+ super.removeChild(child);
60
47
  }
61
48
  scheduleRebuildAllMarks(priority = CommitPriority.NORMAL) {
62
49
  scheduleAfterCommit(() => {
@@ -10,6 +10,7 @@ export declare class ColumnViewColumnNode extends VirtualNode<Props> {
10
10
  column: Gtk.ColumnViewColumn;
11
11
  private itemRenderer;
12
12
  constructor(typeName: string, props: Props, container: undefined, rootContainer?: Container);
13
+ unmount(): void;
13
14
  setStore(model?: ListStore): void;
14
15
  setEstimatedRowHeight(height?: number): void;
15
16
  updateProps(oldProps: Props | null, newProps: Props): void;
@@ -15,6 +15,10 @@ export class ColumnViewColumnNode extends VirtualNode {
15
15
  this.column = new Gtk.ColumnViewColumn();
16
16
  this.column.setFactory(this.itemRenderer.getFactory());
17
17
  }
18
+ unmount() {
19
+ this.itemRenderer.dispose();
20
+ super.unmount();
21
+ }
18
22
  setStore(model) {
19
23
  this.itemRenderer.setStore(model);
20
24
  }
@@ -7,7 +7,7 @@ import { filterProps, matchesAnyClass } from "./internal/utils.js";
7
7
  import { ListItemNode } from "./list-item.js";
8
8
  import { List } from "./models/list.js";
9
9
  import { WidgetNode } from "./widget.js";
10
- const PROP_NAMES = ["sortColumn", "sortOrder", "onSortChange", "estimatedRowHeight"];
10
+ const PROP_NAMES = ["sortColumn", "sortOrder", "onSortChanged", "estimatedRowHeight"];
11
11
  class ColumnViewNode extends WidgetNode {
12
12
  static priority = 1;
13
13
  handleSortChange;
@@ -85,12 +85,12 @@ class ColumnViewNode extends WidgetNode {
85
85
  this.columnNodes.delete(child);
86
86
  }
87
87
  updateProps(oldProps, newProps) {
88
- if (!oldProps || oldProps.onSortChange !== newProps.onSortChange) {
88
+ if (!oldProps || oldProps.onSortChanged !== newProps.onSortChanged) {
89
89
  const sorter = this.container.getSorter();
90
- const onSortChange = newProps.onSortChange;
90
+ const onSortChanged = newProps.onSortChanged;
91
91
  if (sorter) {
92
92
  this.handleSortChange = () => {
93
- onSortChange?.(sorter.getPrimarySortColumn()?.getId() ?? null, sorter.getPrimarySortOrder());
93
+ onSortChanged?.(sorter.getPrimarySortColumn()?.getId() ?? null, sorter.getPrimarySortOrder());
94
94
  };
95
95
  signalStore.set(this, sorter, "changed", this.handleSortChange);
96
96
  }
@@ -111,8 +111,8 @@ class ColumnViewNode extends WidgetNode {
111
111
  column.setEstimatedRowHeight(this.estimatedRowHeight);
112
112
  }
113
113
  }
114
- this.list.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
115
- super.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
114
+ this.list.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
115
+ super.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
116
116
  }
117
117
  getColumn(columnId) {
118
118
  const columns = this.container.getColumns();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { registerNodeClass } from "../registry.js";
3
+ import { filterProps, isContainerType } from "./internal/utils.js";
4
+ import { WidgetNode } from "./widget.js";
5
+ const PROPS = ["onDraw"];
6
+ class DrawingAreaNode extends WidgetNode {
7
+ static priority = 1;
8
+ static matches(_type, containerOrClass) {
9
+ return isContainerType(Gtk.DrawingArea, containerOrClass);
10
+ }
11
+ updateProps(oldProps, newProps) {
12
+ if (newProps.onDraw && (!oldProps || oldProps.onDraw !== newProps.onDraw)) {
13
+ this.container.setDrawFunc(newProps.onDraw);
14
+ this.container.queueDraw();
15
+ }
16
+ super.updateProps(filterProps(oldProps ?? {}, PROPS), filterProps(newProps, PROPS));
17
+ }
18
+ }
19
+ registerNodeClass(DrawingAreaNode);
@@ -42,6 +42,7 @@ class ExpanderRowNode extends WidgetNode {
42
42
  }
43
43
  removeChild(child) {
44
44
  if (child instanceof ExpanderRowChild || child instanceof ActionRowChild) {
45
+ child.unmount();
45
46
  return;
46
47
  }
47
48
  if (child instanceof SlotNode || child instanceof WidgetNode) {
@@ -6,6 +6,7 @@ import "./calendar-mark.js";
6
6
  import "./calendar.js";
7
7
  import "./column-view-column.js";
8
8
  import "./column-view.js";
9
+ import "./drawing-area.js";
9
10
  import "./expander-row-child.js";
10
11
  import "./expander-row.js";
11
12
  import "./fixed-child.js";
@@ -24,13 +25,21 @@ import "./overlay-child.js";
24
25
  import "./pack-child.js";
25
26
  import "./pack.js";
26
27
  import "./popover-menu.js";
28
+ import "./adjustment.js";
27
29
  import "./scale-mark.js";
28
30
  import "./scale.js";
31
+ import "./scrolled-window.js";
32
+ import "./shortcut-controller.js";
33
+ import "./shortcut.js";
29
34
  import "./simple-list-item.js";
30
35
  import "./simple-list-view.js";
31
36
  import "./slot.js";
37
+ import "./source-buffer.js";
38
+ import "./source-view.js";
32
39
  import "./stack-page.js";
33
40
  import "./stack.js";
41
+ import "./text-buffer.js";
42
+ import "./text-view.js";
34
43
  import "./toggle.js";
35
44
  import "./toggle-group.js";
36
45
  import "./toolbar-child.js";
@@ -6,6 +6,7 @@ import "./calendar-mark.js";
6
6
  import "./calendar.js";
7
7
  import "./column-view-column.js";
8
8
  import "./column-view.js";
9
+ import "./drawing-area.js";
9
10
  import "./expander-row-child.js";
10
11
  import "./expander-row.js";
11
12
  import "./fixed-child.js";
@@ -24,13 +25,21 @@ import "./overlay-child.js";
24
25
  import "./pack-child.js";
25
26
  import "./pack.js";
26
27
  import "./popover-menu.js";
28
+ import "./adjustment.js";
27
29
  import "./scale-mark.js";
28
30
  import "./scale.js";
31
+ import "./scrolled-window.js";
32
+ import "./shortcut-controller.js";
33
+ import "./shortcut.js";
29
34
  import "./simple-list-item.js";
30
35
  import "./simple-list-view.js";
31
36
  import "./slot.js";
37
+ import "./source-buffer.js";
38
+ import "./source-view.js";
32
39
  import "./stack-page.js";
33
40
  import "./stack.js";
41
+ import "./text-buffer.js";
42
+ import "./text-view.js";
34
43
  import "./toggle.js";
35
44
  import "./toggle-group.js";
36
45
  import "./toolbar-child.js";
@@ -7,4 +7,18 @@ export const EVENT_CONTROLLER_PROPS = new Set([
7
7
  "onKeyPressed",
8
8
  "onKeyReleased",
9
9
  "onScroll",
10
+ "onDragPrepare",
11
+ "onDragBegin",
12
+ "onDragEnd",
13
+ "onDragCancel",
14
+ "dragActions",
15
+ "onDrop",
16
+ "onDropEnter",
17
+ "onDropLeave",
18
+ "onDropMotion",
19
+ "dropActions",
20
+ "dropTypes",
21
+ "onGestureDragBegin",
22
+ "onGestureDragUpdate",
23
+ "onGestureDragEnd",
10
24
  ]);
@@ -15,5 +15,6 @@ export declare class ListItemRenderer {
15
15
  setStore(store?: ListStore | null): void;
16
16
  setEstimatedItemHeight(height?: number): void;
17
17
  private getStore;
18
+ dispose(): void;
18
19
  private initialize;
19
20
  }
@@ -32,10 +32,15 @@ export class ListItemRenderer {
32
32
  }
33
33
  return this.store;
34
34
  }
35
+ dispose() {
36
+ signalStore.clear(this);
37
+ this.fiberRoots.clear();
38
+ this.tornDown.clear();
39
+ }
35
40
  initialize() {
36
41
  signalStore.set(this, this.factory, "setup", (_self, listItem) => {
37
42
  const ptr = getNativeId(listItem.handle);
38
- const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
43
+ const box = new Gtk.Box(Gtk.Orientation.VERTICAL);
39
44
  if (this.estimatedItemHeight !== undefined) {
40
45
  box.setSizeRequest(-1, this.estimatedItemHeight);
41
46
  }
@@ -27,6 +27,9 @@ type EditableWidget = Gtk.Widget & {
27
27
  setPosition: (position: number) => void;
28
28
  getText: () => string;
29
29
  };
30
+ export type AdjustableWidget = Gtk.Widget & {
31
+ setAdjustment: (adjustment: Gtk.Adjustment) => void;
32
+ };
30
33
  export declare const isAppendable: (obj: unknown) => obj is AppendableWidget;
31
34
  export declare const isAddable: (obj: unknown) => obj is AddableWidget;
32
35
  export declare const hasSingleContent: (obj: unknown) => obj is ContentWidget;
@@ -35,4 +38,5 @@ export declare const isRemovable: (obj: unknown) => obj is RemovableWidget;
35
38
  export declare const isReorderable: (obj: unknown) => obj is ReorderableWidget;
36
39
  export declare const isInsertable: (obj: unknown) => obj is InsertableWidget;
37
40
  export declare const isEditable: (obj: unknown) => obj is EditableWidget;
41
+ export declare const isAdjustable: (obj: unknown) => obj is AdjustableWidget;
38
42
  export {};
@@ -37,3 +37,6 @@ export const isEditable = (obj) => {
37
37
  "getText" in obj &&
38
38
  typeof obj.getText === "function");
39
39
  };
40
+ export const isAdjustable = (obj) => {
41
+ return obj instanceof Gtk.Widget && "setAdjustment" in obj && typeof obj.setAdjustment === "function";
42
+ };
@@ -4,6 +4,7 @@ export type SignalHandler = (...args: any[]) => any;
4
4
  declare class SignalStore {
5
5
  private ownerHandlers;
6
6
  private blockedHandlers;
7
+ private isBlocking;
7
8
  private getOwnerMap;
8
9
  private disconnect;
9
10
  private connect;
@@ -18,6 +18,7 @@ const LIFECYCLE_SIGNALS = new Set([
18
18
  class SignalStore {
19
19
  ownerHandlers = new Map();
20
20
  blockedHandlers = new Set();
21
+ isBlocking = false;
21
22
  getOwnerMap(owner) {
22
23
  let map = this.ownerHandlers.get(owner);
23
24
  if (!map) {
@@ -41,6 +42,10 @@ class SignalStore {
41
42
  const key = `${objectId}:${signal}`;
42
43
  const handlerId = obj.connect(signal, handler);
43
44
  this.getOwnerMap(owner).set(key, { obj, handlerId });
45
+ if (this.isBlocking && !LIFECYCLE_SIGNALS.has(signal)) {
46
+ GObject.signalHandlerBlock(obj, handlerId);
47
+ this.blockedHandlers.add(handlerId);
48
+ }
44
49
  }
45
50
  set(owner, obj, signal, handler) {
46
51
  this.disconnect(owner, obj, signal);
@@ -58,6 +63,7 @@ class SignalStore {
58
63
  }
59
64
  }
60
65
  blockAll() {
66
+ this.isBlocking = true;
61
67
  this.blockedHandlers.clear();
62
68
  for (const ownerMap of this.ownerHandlers.values()) {
63
69
  for (const [key, { obj, handlerId }] of ownerMap.entries()) {
@@ -70,6 +76,7 @@ class SignalStore {
70
76
  }
71
77
  }
72
78
  unblockAll() {
79
+ this.isBlocking = false;
73
80
  for (const ownerMap of this.ownerHandlers.values()) {
74
81
  for (const { obj, handlerId } of ownerMap.values()) {
75
82
  if (this.blockedHandlers.has(handlerId)) {
@@ -18,6 +18,7 @@ export declare class TreeListItemRenderer {
18
18
  setStore(store?: TreeStore | null): void;
19
19
  setEstimatedItemHeight(height?: number): void;
20
20
  private getStore;
21
+ dispose(): void;
21
22
  private initialize;
22
23
  private processPendingBind;
23
24
  private renderBind;
@@ -35,11 +35,19 @@ export class TreeListItemRenderer {
35
35
  }
36
36
  return this.store;
37
37
  }
38
+ dispose() {
39
+ signalStore.clear(this);
40
+ this.fiberRoots.clear();
41
+ this.expanders.clear();
42
+ this.setupComplete.clear();
43
+ this.pendingBinds.clear();
44
+ this.tornDown.clear();
45
+ }
38
46
  initialize() {
39
47
  signalStore.set(this, this.factory, "setup", (_self, listItem) => {
40
48
  const ptr = getNativeId(listItem.handle);
41
49
  const expander = new Gtk.TreeExpander();
42
- const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
50
+ const box = new Gtk.Box(Gtk.Orientation.VERTICAL);
43
51
  if (this.estimatedItemHeight !== undefined) {
44
52
  box.setSizeRequest(-1, this.estimatedItemHeight);
45
53
  }
@@ -3,7 +3,6 @@ import { registerNodeClass } from "../registry.js";
3
3
  import { CommitPriority, scheduleAfterCommit } from "../scheduler.js";
4
4
  import { isContainerType } from "./internal/utils.js";
5
5
  import { LevelBarOffsetNode } from "./level-bar-offset.js";
6
- import { SlotNode } from "./slot.js";
7
6
  import { WidgetNode } from "./widget.js";
8
7
  class LevelBarNode extends WidgetNode {
9
8
  static priority = 1;
@@ -24,11 +23,7 @@ class LevelBarNode extends WidgetNode {
24
23
  });
25
24
  return;
26
25
  }
27
- if (child instanceof SlotNode || child instanceof WidgetNode) {
28
- super.appendChild(child);
29
- return;
30
- }
31
- throw new Error(`Cannot append '${child.typeName}' to 'LevelBar': expected x.LevelBarOffset or Widget`);
26
+ super.appendChild(child);
32
27
  }
33
28
  insertBefore(child, before) {
34
29
  if (child instanceof LevelBarOffsetNode) {
@@ -43,11 +38,7 @@ class LevelBarNode extends WidgetNode {
43
38
  this.scheduleRebuildAllOffsets();
44
39
  return;
45
40
  }
46
- if (child instanceof SlotNode || child instanceof WidgetNode) {
47
- super.insertBefore(child, before);
48
- return;
49
- }
50
- throw new Error(`Cannot insert '${child.typeName}' into 'LevelBar': expected x.LevelBarOffset or Widget`);
41
+ super.insertBefore(child, before);
51
42
  }
52
43
  removeChild(child) {
53
44
  if (child instanceof LevelBarOffsetNode) {
@@ -58,11 +49,7 @@ class LevelBarNode extends WidgetNode {
58
49
  this.scheduleRebuildAllOffsets(CommitPriority.HIGH);
59
50
  return;
60
51
  }
61
- if (child instanceof SlotNode || child instanceof WidgetNode) {
62
- super.removeChild(child);
63
- return;
64
- }
65
- throw new Error(`Cannot remove '${child.typeName}' from 'LevelBar': expected x.LevelBarOffset or Widget`);
52
+ super.removeChild(child);
66
53
  }
67
54
  scheduleRebuildAllOffsets(priority = CommitPriority.NORMAL) {
68
55
  scheduleAfterCommit(() => {
@@ -28,6 +28,10 @@ class ListViewNode extends WidgetNode {
28
28
  super.mount();
29
29
  this.container.setModel(this.list.getSelectionModel());
30
30
  }
31
+ unmount() {
32
+ this.itemRenderer.dispose();
33
+ super.unmount();
34
+ }
31
35
  appendChild(child) {
32
36
  if (!(child instanceof ListItemNode)) {
33
37
  throw new Error(`Cannot append '${child.typeName}' to 'ListView': expected x.ListItem`);
@@ -53,8 +57,13 @@ class ListViewNode extends WidgetNode {
53
57
  if (!oldProps || oldProps.estimatedItemHeight !== newProps.estimatedItemHeight) {
54
58
  this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight);
55
59
  }
56
- this.list.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
57
- super.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
60
+ const previousModel = this.list.getSelectionModel();
61
+ this.list.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
62
+ const currentModel = this.list.getSelectionModel();
63
+ if (previousModel !== currentModel) {
64
+ this.container.setModel(currentModel);
65
+ }
66
+ super.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
58
67
  }
59
68
  }
60
69
  registerNodeClass(ListViewNode);
@@ -7,14 +7,17 @@ export type ListProps = {
7
7
  selected?: string[];
8
8
  onSelectionChanged?: (ids: string[]) => void;
9
9
  };
10
+ type SelectionModel = Gtk.NoSelection | Gtk.SingleSelection | Gtk.MultiSelection;
10
11
  export declare class List extends VirtualNode<ListProps> {
11
12
  private store;
12
13
  private selectionModel;
13
14
  private handleSelectionChange?;
15
+ private pendingSelection?;
16
+ private selectionScheduled;
14
17
  constructor(props?: ListProps);
15
18
  private initSelectionHandler;
16
19
  getStore(): ListStore;
17
- getSelectionModel(): Gtk.SingleSelection | Gtk.MultiSelection;
20
+ getSelectionModel(): SelectionModel;
18
21
  appendChild(child: Node): void;
19
22
  insertBefore(child: Node, before: Node): void;
20
23
  removeChild(child: Node): void;
@@ -22,4 +25,6 @@ export declare class List extends VirtualNode<ListProps> {
22
25
  private createSelectionModel;
23
26
  private getSelection;
24
27
  private setSelection;
28
+ private applySelection;
25
29
  }
30
+ export {};
@@ -1,4 +1,5 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { CommitPriority, scheduleAfterCommit } from "../../scheduler.js";
2
3
  import { ListStore } from "../internal/list-store.js";
3
4
  import { signalStore } from "../internal/signal-store.js";
4
5
  import { ListItemNode } from "../list-item.js";
@@ -7,6 +8,8 @@ export class List extends VirtualNode {
7
8
  store;
8
9
  selectionModel;
9
10
  handleSelectionChange;
11
+ pendingSelection;
12
+ selectionScheduled = false;
10
13
  constructor(props = {}) {
11
14
  super("", {}, undefined);
12
15
  this.store = new ListStore();
@@ -71,13 +74,15 @@ export class List extends VirtualNode {
71
74
  createSelectionModel(mode) {
72
75
  const model = this.store.getModel();
73
76
  const selectionMode = mode ?? Gtk.SelectionMode.SINGLE;
74
- const selectionModel = selectionMode === Gtk.SelectionMode.MULTIPLE
75
- ? new Gtk.MultiSelection(model)
76
- : new Gtk.SingleSelection(model);
77
- if (selectionModel instanceof Gtk.SingleSelection) {
78
- selectionModel.setAutoselect(false);
79
- selectionModel.setCanUnselect(true);
77
+ if (selectionMode === Gtk.SelectionMode.NONE) {
78
+ return new Gtk.NoSelection(model);
80
79
  }
80
+ if (selectionMode === Gtk.SelectionMode.MULTIPLE) {
81
+ return new Gtk.MultiSelection(model);
82
+ }
83
+ const selectionModel = new Gtk.SingleSelection(model);
84
+ selectionModel.setAutoselect(selectionMode === Gtk.SelectionMode.BROWSE);
85
+ selectionModel.setCanUnselect(selectionMode !== Gtk.SelectionMode.BROWSE);
81
86
  return selectionModel;
82
87
  }
83
88
  getSelection() {
@@ -95,6 +100,16 @@ export class List extends VirtualNode {
95
100
  return ids;
96
101
  }
97
102
  setSelection(ids) {
103
+ this.pendingSelection = ids;
104
+ if (!this.selectionScheduled) {
105
+ this.selectionScheduled = true;
106
+ scheduleAfterCommit(() => this.applySelection(), CommitPriority.LOW);
107
+ }
108
+ }
109
+ applySelection() {
110
+ this.selectionScheduled = false;
111
+ const ids = this.pendingSelection;
112
+ this.pendingSelection = undefined;
98
113
  const model = this.store.getModel();
99
114
  const nItems = model.getNItems();
100
115
  const selected = new Gtk.Bitset();
@@ -8,17 +8,20 @@ export type TreeListProps = {
8
8
  selected?: string[];
9
9
  onSelectionChanged?: (ids: string[]) => void;
10
10
  };
11
+ type SelectionModel = Gtk.NoSelection | Gtk.SingleSelection | Gtk.MultiSelection;
11
12
  export declare class TreeList extends VirtualNode<TreeListProps> {
12
13
  private store;
13
14
  private treeListModel;
14
15
  private selectionModel;
15
16
  private handleSelectionChange?;
17
+ private pendingSelection?;
18
+ private selectionScheduled;
16
19
  constructor(props?: TreeListProps);
17
20
  private initSelectionHandler;
18
21
  private createChildModel;
19
22
  getStore(): TreeStore;
20
23
  getTreeListModel(): Gtk.TreeListModel;
21
- getSelectionModel(): Gtk.SingleSelection | Gtk.MultiSelection;
24
+ getSelectionModel(): SelectionModel;
22
25
  appendChild(child: Node): void;
23
26
  insertBefore(child: Node, before: Node): void;
24
27
  removeChild(child: Node): void;
@@ -26,4 +29,6 @@ export declare class TreeList extends VirtualNode<TreeListProps> {
26
29
  private createSelectionModel;
27
30
  private getSelection;
28
31
  private setSelection;
32
+ private applySelection;
29
33
  }
34
+ export {};
@@ -1,5 +1,5 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
- import { scheduleAfterCommit } from "../../scheduler.js";
2
+ import { CommitPriority, scheduleAfterCommit } from "../../scheduler.js";
3
3
  import { signalStore } from "../internal/signal-store.js";
4
4
  import { TreeStore } from "../internal/tree-store.js";
5
5
  import { TreeListItemNode } from "../tree-list-item.js";
@@ -9,6 +9,8 @@ export class TreeList extends VirtualNode {
9
9
  treeListModel;
10
10
  selectionModel;
11
11
  handleSelectionChange;
12
+ pendingSelection;
13
+ selectionScheduled = false;
12
14
  constructor(props = {}) {
13
15
  super("", {}, undefined);
14
16
  this.store = new TreeStore();
@@ -117,13 +119,15 @@ export class TreeList extends VirtualNode {
117
119
  }
118
120
  createSelectionModel(mode) {
119
121
  const selectionMode = mode ?? Gtk.SelectionMode.SINGLE;
120
- const selectionModel = selectionMode === Gtk.SelectionMode.MULTIPLE
121
- ? new Gtk.MultiSelection(this.treeListModel)
122
- : new Gtk.SingleSelection(this.treeListModel);
123
- if (selectionModel instanceof Gtk.SingleSelection) {
124
- selectionModel.setAutoselect(false);
125
- selectionModel.setCanUnselect(true);
122
+ if (selectionMode === Gtk.SelectionMode.NONE) {
123
+ return new Gtk.NoSelection(this.treeListModel);
126
124
  }
125
+ if (selectionMode === Gtk.SelectionMode.MULTIPLE) {
126
+ return new Gtk.MultiSelection(this.treeListModel);
127
+ }
128
+ const selectionModel = new Gtk.SingleSelection(this.treeListModel);
129
+ selectionModel.setAutoselect(selectionMode === Gtk.SelectionMode.BROWSE);
130
+ selectionModel.setCanUnselect(selectionMode !== Gtk.SelectionMode.BROWSE);
127
131
  return selectionModel;
128
132
  }
129
133
  getSelection() {
@@ -143,6 +147,16 @@ export class TreeList extends VirtualNode {
143
147
  return ids;
144
148
  }
145
149
  setSelection(ids) {
150
+ this.pendingSelection = ids;
151
+ if (!this.selectionScheduled) {
152
+ this.selectionScheduled = true;
153
+ scheduleAfterCommit(() => this.applySelection(), CommitPriority.LOW);
154
+ }
155
+ }
156
+ applySelection() {
157
+ this.selectionScheduled = false;
158
+ const ids = this.pendingSelection;
159
+ this.pendingSelection = undefined;
146
160
  const nItems = this.treeListModel.getNItems();
147
161
  const selected = new Gtk.Bitset();
148
162
  const mask = Gtk.Bitset.newRange(0, nItems);
@@ -1,3 +1,4 @@
1
+ import { batch } from "@gtkx/ffi";
1
2
  import * as Adw from "@gtkx/ffi/adw";
2
3
  import { registerNodeClass } from "../registry.js";
3
4
  import { SlotNode } from "./slot.js";
@@ -12,36 +13,44 @@ export class NavigationPageNode extends SlotNode {
12
13
  if (!(child instanceof Adw.NavigationPage)) {
13
14
  return;
14
15
  }
15
- if (newProps.id !== undefined && (!oldProps || oldProps.id !== newProps.id)) {
16
- child.setTag(newProps.id);
16
+ if (!oldProps || oldProps.id !== newProps.id) {
17
+ if (newProps.id !== undefined) {
18
+ child.setTag(newProps.id);
19
+ }
17
20
  }
18
- if (newProps.title !== undefined && (!oldProps || oldProps.title !== newProps.title)) {
19
- child.setTitle(newProps.title);
21
+ if (!oldProps || oldProps.title !== newProps.title) {
22
+ if (newProps.title !== undefined) {
23
+ child.setTitle(newProps.title);
24
+ }
20
25
  }
21
- if (newProps.canPop !== undefined && (!oldProps || oldProps.canPop !== newProps.canPop)) {
22
- child.setCanPop(newProps.canPop);
26
+ if (!oldProps || oldProps.canPop !== newProps.canPop) {
27
+ if (newProps.canPop !== undefined) {
28
+ child.setCanPop(newProps.canPop);
29
+ }
23
30
  }
24
31
  }
25
32
  onChildChange(oldChild) {
26
- const navigationView = this.getParent();
27
- const title = this.props.title ?? "";
28
- if (this.child) {
29
- this.child = this.props.id
30
- ? Adw.NavigationPage.newWithTag(this.child, title, this.props.id)
31
- : new Adw.NavigationPage(this.child, title);
32
- this.updateProps(null, this.props);
33
- }
34
- if (navigationView instanceof Adw.NavigationView) {
35
- if (oldChild instanceof Adw.NavigationPage) {
36
- navigationView.remove(oldChild);
37
- }
33
+ batch(() => {
34
+ const navigationView = this.getParent();
35
+ const title = this.props.title ?? "";
38
36
  if (this.child) {
39
- navigationView.add(this.child);
37
+ this.child = this.props.id
38
+ ? Adw.NavigationPage.newWithTag(this.child, title, this.props.id)
39
+ : new Adw.NavigationPage(this.child, title);
40
+ this.updateProps(null, this.props);
40
41
  }
41
- }
42
- else {
43
- super.onChildChange(oldChild);
44
- }
42
+ if (navigationView instanceof Adw.NavigationView) {
43
+ if (oldChild instanceof Adw.NavigationPage) {
44
+ navigationView.remove(oldChild);
45
+ }
46
+ if (this.child) {
47
+ navigationView.add(this.child);
48
+ }
49
+ }
50
+ else {
51
+ super.onChildChange(oldChild);
52
+ }
53
+ });
45
54
  }
46
55
  }
47
56
  registerNodeClass(NavigationPageNode);