@gtkx/react 0.6.0 → 0.7.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.
- package/dist/batch.d.ts +4 -1
- package/dist/batch.js +19 -10
- package/dist/codegen/jsx-generator.d.ts +4 -4
- package/dist/codegen/jsx-generator.js +24 -27
- package/dist/container-interfaces.d.ts +19 -6
- package/dist/container-interfaces.js +26 -6
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +38 -0
- package/dist/factory.js +9 -3
- package/dist/generated/jsx.d.ts +38 -26
- package/dist/generated/jsx.js +12 -2
- package/dist/index.js +3 -1
- package/dist/node.d.ts +5 -0
- package/dist/node.js +62 -6
- package/dist/nodes/action-bar.d.ts +2 -6
- package/dist/nodes/action-bar.js +3 -12
- package/dist/nodes/column-view.d.ts +19 -44
- package/dist/nodes/column-view.js +70 -243
- package/dist/nodes/combo-row.d.ts +5 -0
- package/dist/nodes/combo-row.js +6 -0
- package/dist/nodes/drop-down.d.ts +9 -0
- package/dist/nodes/drop-down.js +12 -0
- package/dist/nodes/flow-box.d.ts +4 -6
- package/dist/nodes/flow-box.js +8 -16
- package/dist/nodes/grid.d.ts +15 -15
- package/dist/nodes/grid.js +21 -64
- package/dist/nodes/header-bar.d.ts +34 -11
- package/dist/nodes/header-bar.js +52 -24
- package/dist/nodes/indexed-child-container.d.ts +16 -0
- package/dist/nodes/indexed-child-container.js +22 -0
- package/dist/nodes/list-box.d.ts +3 -6
- package/dist/nodes/list-box.js +6 -14
- package/dist/nodes/list-item-factory.d.ts +19 -0
- package/dist/nodes/list-item-factory.js +58 -0
- package/dist/nodes/list-view.d.ts +24 -0
- package/dist/nodes/list-view.js +46 -0
- package/dist/nodes/menu.d.ts +25 -19
- package/dist/nodes/menu.js +30 -59
- package/dist/nodes/notebook.d.ts +13 -14
- package/dist/nodes/notebook.js +18 -56
- package/dist/nodes/paged-stack.d.ts +39 -0
- package/dist/nodes/paged-stack.js +54 -0
- package/dist/nodes/selectable-list.d.ts +41 -0
- package/dist/nodes/selectable-list.js +228 -0
- package/dist/nodes/stack-page-props.d.ts +11 -0
- package/dist/nodes/stack-page-props.js +23 -0
- package/dist/nodes/stack.d.ts +14 -28
- package/dist/nodes/stack.js +30 -142
- package/dist/nodes/string-list-container.d.ts +41 -0
- package/dist/nodes/string-list-container.js +90 -0
- package/dist/nodes/string-list-item.d.ts +15 -0
- package/dist/nodes/string-list-item.js +48 -0
- package/dist/nodes/string-list-store.d.ts +13 -0
- package/dist/nodes/string-list-store.js +44 -0
- package/dist/nodes/text-view.d.ts +1 -1
- package/dist/nodes/text-view.js +1 -5
- package/dist/nodes/toggle-button.d.ts +1 -1
- package/dist/nodes/toggle-button.js +1 -3
- package/dist/nodes/view-stack.d.ts +9 -0
- package/dist/nodes/view-stack.js +28 -0
- package/dist/nodes/virtual-item.d.ts +20 -0
- package/dist/nodes/virtual-item.js +57 -0
- package/dist/nodes/virtual-slot.d.ts +25 -0
- package/dist/nodes/virtual-slot.js +71 -0
- package/dist/nodes/widget.d.ts +0 -3
- package/dist/nodes/widget.js +0 -28
- package/dist/nodes/window.d.ts +1 -1
- package/dist/nodes/window.js +9 -15
- package/dist/predicates.d.ts +8 -0
- package/dist/predicates.js +8 -0
- package/dist/props.d.ts +7 -5
- package/dist/props.js +11 -9
- package/dist/reconciler/host-config.d.ts +19 -0
- package/dist/reconciler/host-config.js +89 -0
- package/dist/reconciler.d.ts +2 -26
- package/dist/reconciler.js +15 -106
- package/dist/render.d.ts +1 -2
- package/dist/render.js +16 -4
- package/dist/types.d.ts +19 -16
- package/package.json +4 -4
- package/dist/nodes/dropdown.d.ts +0 -39
- package/dist/nodes/dropdown.js +0 -103
- package/dist/nodes/list.d.ts +0 -43
- package/dist/nodes/list.js +0 -153
package/dist/nodes/notebook.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as Gtk from "@gtkx/ffi/gtk";
|
|
|
2
2
|
import { type ChildContainer, type PageContainer } from "../container-interfaces.js";
|
|
3
3
|
import type { Props } from "../factory.js";
|
|
4
4
|
import { Node } from "../node.js";
|
|
5
|
+
import { VirtualSlotNode } from "./virtual-slot.js";
|
|
5
6
|
export declare class NotebookNode extends Node<Gtk.Notebook> implements PageContainer, ChildContainer {
|
|
6
7
|
static matches(type: string): boolean;
|
|
7
8
|
addPage(child: Gtk.Widget, label: string): void;
|
|
@@ -12,20 +13,18 @@ export declare class NotebookNode extends Node<Gtk.Notebook> implements PageCont
|
|
|
12
13
|
insertChildBefore(child: Gtk.Widget, before: Gtk.Widget): void;
|
|
13
14
|
detachChild(child: Gtk.Widget): void;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
type NotebookPageProps = {
|
|
17
|
+
label: string;
|
|
18
|
+
};
|
|
19
|
+
export declare class NotebookPageNode extends VirtualSlotNode<PageContainer, NotebookPageProps> {
|
|
20
|
+
static consumedPropNames: string[];
|
|
16
21
|
static matches(type: string): boolean;
|
|
17
|
-
protected
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
setChildWidget(widget: Gtk.Widget): void;
|
|
24
|
-
getChildWidget(): Gtk.Widget | null;
|
|
25
|
-
appendChild(child: Node): void;
|
|
26
|
-
attachToParent(parent: Node): void;
|
|
27
|
-
attachToParentBefore(parent: Node, before: Node): void;
|
|
28
|
-
detachFromParent(parent: Node): void;
|
|
29
|
-
protected consumedProps(): Set<string>;
|
|
22
|
+
protected isValidContainer(parent: Node): parent is Node & PageContainer;
|
|
23
|
+
protected extractSlotProps(props: Props): NotebookPageProps;
|
|
24
|
+
protected addToContainer(container: PageContainer, child: Gtk.Widget, props: NotebookPageProps): void;
|
|
25
|
+
protected insertBeforeInContainer(container: PageContainer, child: Gtk.Widget, props: NotebookPageProps, before: Gtk.Widget): void;
|
|
26
|
+
protected removeFromContainer(container: PageContainer, child: Gtk.Widget): void;
|
|
27
|
+
protected updateInContainer(container: PageContainer, child: Gtk.Widget, props: NotebookPageProps): void;
|
|
30
28
|
updateProps(oldProps: Props, newProps: Props): void;
|
|
31
29
|
}
|
|
30
|
+
export {};
|
package/dist/nodes/notebook.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
2
|
import { isPageContainer } from "../container-interfaces.js";
|
|
3
3
|
import { Node } from "../node.js";
|
|
4
|
-
import {
|
|
4
|
+
import { VirtualSlotNode } from "./virtual-slot.js";
|
|
5
5
|
export class NotebookNode extends Node {
|
|
6
6
|
static matches(type) {
|
|
7
7
|
return type === "Notebook" || type === "Notebook.Root";
|
|
@@ -49,71 +49,33 @@ export class NotebookNode extends Node {
|
|
|
49
49
|
this.removePage(child);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
export class NotebookPageNode extends
|
|
52
|
+
export class NotebookPageNode extends VirtualSlotNode {
|
|
53
|
+
static consumedPropNames = ["label"];
|
|
53
54
|
static matches(type) {
|
|
54
55
|
return type === "Notebook.Page";
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
-
return
|
|
57
|
+
isValidContainer(parent) {
|
|
58
|
+
return isPageContainer(parent);
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.label = getStringProp(props, "label", "");
|
|
64
|
-
super.initialize(props);
|
|
60
|
+
extractSlotProps(props) {
|
|
61
|
+
return {
|
|
62
|
+
label: props.label ?? "",
|
|
63
|
+
};
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
addToContainer(container, child, props) {
|
|
66
|
+
container.addPage(child, props.label);
|
|
68
67
|
}
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
insertBeforeInContainer(container, child, props, before) {
|
|
69
|
+
container.insertPageBefore(child, props.label, before);
|
|
71
70
|
}
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
removeFromContainer(container, child) {
|
|
72
|
+
container.removePage(child);
|
|
74
73
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (childWidget) {
|
|
78
|
-
this.childWidget = childWidget;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
attachToParent(parent) {
|
|
82
|
-
if (isPageContainer(parent) && this.childWidget) {
|
|
83
|
-
this.parentContainer = parent;
|
|
84
|
-
parent.addPage(this.childWidget, this.label);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
attachToParentBefore(parent, before) {
|
|
88
|
-
if (isPageContainer(parent) && this.childWidget) {
|
|
89
|
-
this.parentContainer = parent;
|
|
90
|
-
const beforePage = before instanceof NotebookPageNode ? before.getChildWidget() : before.getWidget();
|
|
91
|
-
if (beforePage) {
|
|
92
|
-
parent.insertPageBefore(this.childWidget, this.label, beforePage);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
parent.addPage(this.childWidget, this.label);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
detachFromParent(parent) {
|
|
100
|
-
if (isPageContainer(parent) && this.childWidget) {
|
|
101
|
-
parent.removePage(this.childWidget);
|
|
102
|
-
this.parentContainer = null;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
consumedProps() {
|
|
106
|
-
const consumed = super.consumedProps();
|
|
107
|
-
consumed.add("label");
|
|
108
|
-
return consumed;
|
|
74
|
+
updateInContainer(container, child, props) {
|
|
75
|
+
container.updatePageLabel(child, props.label);
|
|
109
76
|
}
|
|
110
77
|
updateProps(oldProps, newProps) {
|
|
111
|
-
|
|
112
|
-
this.label = getStringProp(newProps, "label", "");
|
|
113
|
-
if (this.parentContainer && this.childWidget) {
|
|
114
|
-
this.parentContainer.updatePageLabel(this.childWidget, this.label);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
78
|
+
this.updateSlotPropsIfChanged(oldProps, newProps, ["label"]);
|
|
117
79
|
super.updateProps(oldProps, newProps);
|
|
118
80
|
}
|
|
119
81
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { ChildContainer, StackPageContainer, StackPageProps } from "../container-interfaces.js";
|
|
3
|
+
import type { Props } from "../factory.js";
|
|
4
|
+
import { Node } from "../node.js";
|
|
5
|
+
import { type StackPageLike } from "./stack-page-props.js";
|
|
6
|
+
type StackWidget = Gtk.Widget & {
|
|
7
|
+
getChildByName(name: string): Gtk.Widget | null;
|
|
8
|
+
setVisibleChild(child: Gtk.Widget): void;
|
|
9
|
+
remove(child: Gtk.Widget): void;
|
|
10
|
+
getPage(child: Gtk.Widget): StackPageLike;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Abstract node for paged stack widgets (Gtk.Stack, Adw.ViewStack).
|
|
14
|
+
* Handles visible child deferral and common page operations.
|
|
15
|
+
*/
|
|
16
|
+
export declare abstract class PagedStackNode<T extends StackWidget> extends Node<T> implements StackPageContainer, ChildContainer {
|
|
17
|
+
static consumedPropNames: string[];
|
|
18
|
+
private pendingVisibleChildName;
|
|
19
|
+
/**
|
|
20
|
+
* Add a page to the stack widget. Must be implemented by subclasses
|
|
21
|
+
* due to API differences between Gtk.Stack and Adw.ViewStack.
|
|
22
|
+
*/
|
|
23
|
+
abstract addStackPage(child: Gtk.Widget, props: StackPageProps): void;
|
|
24
|
+
/**
|
|
25
|
+
* Add a child directly to the stack widget (without page props).
|
|
26
|
+
* Must be implemented by subclasses due to API differences.
|
|
27
|
+
*/
|
|
28
|
+
protected abstract addChildToWidget(child: Gtk.Widget): void;
|
|
29
|
+
protected applyPendingVisibleChild(): void;
|
|
30
|
+
insertStackPageBefore(child: Gtk.Widget, props: StackPageProps, _beforeChild: Gtk.Widget): void;
|
|
31
|
+
removeStackPage(child: Gtk.Widget): void;
|
|
32
|
+
updateStackPageProps(child: Gtk.Widget, props: StackPageProps): void;
|
|
33
|
+
attachChild(child: Gtk.Widget): void;
|
|
34
|
+
insertChildBefore(child: Gtk.Widget, _before: Gtk.Widget): void;
|
|
35
|
+
detachChild(child: Gtk.Widget): void;
|
|
36
|
+
private setVisibleChildOrDefer;
|
|
37
|
+
updateProps(oldProps: Props, newProps: Props): void;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Node } from "../node.js";
|
|
2
|
+
import { applyStackPageProps } from "./stack-page-props.js";
|
|
3
|
+
/**
|
|
4
|
+
* Abstract node for paged stack widgets (Gtk.Stack, Adw.ViewStack).
|
|
5
|
+
* Handles visible child deferral and common page operations.
|
|
6
|
+
*/
|
|
7
|
+
export class PagedStackNode extends Node {
|
|
8
|
+
static consumedPropNames = ["visibleChildName"];
|
|
9
|
+
pendingVisibleChildName = null;
|
|
10
|
+
applyPendingVisibleChild() {
|
|
11
|
+
if (this.pendingVisibleChildName !== null) {
|
|
12
|
+
const child = this.widget.getChildByName(this.pendingVisibleChildName);
|
|
13
|
+
if (child) {
|
|
14
|
+
this.widget.setVisibleChild(child);
|
|
15
|
+
this.pendingVisibleChildName = null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
insertStackPageBefore(child, props, _beforeChild) {
|
|
20
|
+
this.addStackPage(child, props);
|
|
21
|
+
}
|
|
22
|
+
removeStackPage(child) {
|
|
23
|
+
this.widget.remove(child);
|
|
24
|
+
}
|
|
25
|
+
updateStackPageProps(child, props) {
|
|
26
|
+
const page = this.widget.getPage(child);
|
|
27
|
+
applyStackPageProps(page, props);
|
|
28
|
+
}
|
|
29
|
+
attachChild(child) {
|
|
30
|
+
this.addChildToWidget(child);
|
|
31
|
+
}
|
|
32
|
+
insertChildBefore(child, _before) {
|
|
33
|
+
this.addChildToWidget(child);
|
|
34
|
+
}
|
|
35
|
+
detachChild(child) {
|
|
36
|
+
this.widget.remove(child);
|
|
37
|
+
}
|
|
38
|
+
setVisibleChildOrDefer(name) {
|
|
39
|
+
const child = this.widget.getChildByName(name);
|
|
40
|
+
if (child) {
|
|
41
|
+
this.widget.setVisibleChild(child);
|
|
42
|
+
this.pendingVisibleChildName = null;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.pendingVisibleChildName = name;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
updateProps(oldProps, newProps) {
|
|
49
|
+
if (newProps.visibleChildName !== undefined) {
|
|
50
|
+
this.setVisibleChildOrDefer(newProps.visibleChildName);
|
|
51
|
+
}
|
|
52
|
+
super.updateProps(oldProps, newProps);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import type { ItemContainer } from "../container-interfaces.js";
|
|
3
|
+
import type { Props } from "../factory.js";
|
|
4
|
+
import { Node } from "../node.js";
|
|
5
|
+
export type SelectableListState = {
|
|
6
|
+
itemsById: Map<string, unknown>;
|
|
7
|
+
itemOrder: string[];
|
|
8
|
+
committedOrder: string[];
|
|
9
|
+
stringList: Gtk.StringList;
|
|
10
|
+
selectionModel: Gtk.SingleSelection | Gtk.MultiSelection;
|
|
11
|
+
selectionMode: Gtk.SelectionMode;
|
|
12
|
+
selected: string[];
|
|
13
|
+
onSelectionChanged?: (ids: string[]) => void;
|
|
14
|
+
selectionHandlerId: number | null;
|
|
15
|
+
needsSync: boolean;
|
|
16
|
+
needsInitialSelection: boolean;
|
|
17
|
+
};
|
|
18
|
+
type SelectableListWidget = Gtk.Widget & {
|
|
19
|
+
setModel(model: Gtk.SelectionModel): void;
|
|
20
|
+
};
|
|
21
|
+
export declare abstract class SelectableListNode<T extends SelectableListWidget, S extends SelectableListState> extends Node<T, S> implements ItemContainer<unknown> {
|
|
22
|
+
protected initializeSelectionState(props: Props): SelectableListState;
|
|
23
|
+
protected applySelectionModel(): void;
|
|
24
|
+
protected cleanupSelection(): void;
|
|
25
|
+
protected updateSelectionProps(oldProps: Props, newProps: Props): void;
|
|
26
|
+
private recreateSelectionModel;
|
|
27
|
+
getItems(): unknown[];
|
|
28
|
+
getItemById(id: string): unknown;
|
|
29
|
+
addItem(id: string, data: unknown): void;
|
|
30
|
+
insertItemBefore(id: string, data: unknown, beforeId: string): void;
|
|
31
|
+
removeItem(id: string): void;
|
|
32
|
+
updateItem(id: string, data: unknown): void;
|
|
33
|
+
protected scheduleSync(): void;
|
|
34
|
+
protected syncModel: () => void;
|
|
35
|
+
protected applyInitialSelection(): void;
|
|
36
|
+
protected applySelection(ids: string[]): void;
|
|
37
|
+
protected getSelectedIds(): string[];
|
|
38
|
+
protected connectSelectionHandler(): void;
|
|
39
|
+
protected disconnectSelectionHandler(): void;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { getInterface } from "@gtkx/ffi";
|
|
2
|
+
import * as Gio from "@gtkx/ffi/gio";
|
|
3
|
+
import * as GObject from "@gtkx/ffi/gobject";
|
|
4
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
5
|
+
import { scheduleFlush } from "../batch.js";
|
|
6
|
+
import { Node } from "../node.js";
|
|
7
|
+
import { getCallbackChange } from "../props.js";
|
|
8
|
+
export class SelectableListNode extends Node {
|
|
9
|
+
initializeSelectionState(props) {
|
|
10
|
+
const selectionMode = props.selectionMode ?? Gtk.SelectionMode.SINGLE;
|
|
11
|
+
const stringList = new Gtk.StringList([]);
|
|
12
|
+
const listModel = getInterface(stringList.id, Gio.ListModel);
|
|
13
|
+
const selectionModel = selectionMode === Gtk.SelectionMode.MULTIPLE
|
|
14
|
+
? new Gtk.MultiSelection(listModel)
|
|
15
|
+
: new Gtk.SingleSelection(listModel);
|
|
16
|
+
if (selectionModel instanceof Gtk.SingleSelection) {
|
|
17
|
+
selectionModel.setAutoselect(false);
|
|
18
|
+
selectionModel.setCanUnselect(true);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
itemsById: new Map(),
|
|
22
|
+
itemOrder: [],
|
|
23
|
+
committedOrder: [],
|
|
24
|
+
stringList,
|
|
25
|
+
selectionModel,
|
|
26
|
+
selectionMode,
|
|
27
|
+
selected: props.selected ?? [],
|
|
28
|
+
onSelectionChanged: props.onSelectionChanged,
|
|
29
|
+
selectionHandlerId: null,
|
|
30
|
+
needsSync: false,
|
|
31
|
+
needsInitialSelection: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
applySelectionModel() {
|
|
35
|
+
this.widget.setModel(this.state.selectionModel);
|
|
36
|
+
}
|
|
37
|
+
cleanupSelection() {
|
|
38
|
+
this.disconnectSelectionHandler();
|
|
39
|
+
}
|
|
40
|
+
updateSelectionProps(oldProps, newProps) {
|
|
41
|
+
const oldSelectionMode = oldProps.selectionMode;
|
|
42
|
+
const newSelectionMode = newProps.selectionMode;
|
|
43
|
+
const effectiveOldMode = oldSelectionMode ?? Gtk.SelectionMode.SINGLE;
|
|
44
|
+
const effectiveNewMode = newSelectionMode ?? Gtk.SelectionMode.SINGLE;
|
|
45
|
+
if (effectiveOldMode !== effectiveNewMode) {
|
|
46
|
+
this.recreateSelectionModel(effectiveNewMode);
|
|
47
|
+
}
|
|
48
|
+
const oldCallback = oldProps.onSelectionChanged;
|
|
49
|
+
const newCallback = newProps.onSelectionChanged;
|
|
50
|
+
const change = getCallbackChange(oldCallback, newCallback);
|
|
51
|
+
if (change.action !== "none") {
|
|
52
|
+
this.state.onSelectionChanged = change.callback;
|
|
53
|
+
if (change.action === "disconnect") {
|
|
54
|
+
this.disconnectSelectionHandler();
|
|
55
|
+
}
|
|
56
|
+
else if (change.action === "connect") {
|
|
57
|
+
this.connectSelectionHandler();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const oldSelected = oldProps.selected;
|
|
61
|
+
const newSelected = newProps.selected;
|
|
62
|
+
if (oldSelected !== newSelected && newSelected !== undefined) {
|
|
63
|
+
this.state.selected = newSelected;
|
|
64
|
+
this.applySelection(newSelected);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
recreateSelectionModel(newSelectionMode) {
|
|
68
|
+
const currentSelection = this.getSelectedIds();
|
|
69
|
+
const hadHandler = this.state.selectionHandlerId !== null;
|
|
70
|
+
this.disconnectSelectionHandler();
|
|
71
|
+
const listModel = getInterface(this.state.stringList.id, Gio.ListModel);
|
|
72
|
+
const newSelectionModel = newSelectionMode === Gtk.SelectionMode.MULTIPLE
|
|
73
|
+
? new Gtk.MultiSelection(listModel)
|
|
74
|
+
: new Gtk.SingleSelection(listModel);
|
|
75
|
+
if (newSelectionModel instanceof Gtk.SingleSelection) {
|
|
76
|
+
newSelectionModel.setAutoselect(false);
|
|
77
|
+
newSelectionModel.setCanUnselect(true);
|
|
78
|
+
}
|
|
79
|
+
this.state.selectionModel = newSelectionModel;
|
|
80
|
+
this.state.selectionMode = newSelectionMode;
|
|
81
|
+
this.applySelectionModel();
|
|
82
|
+
this.applySelection(currentSelection);
|
|
83
|
+
if (hadHandler && this.state.onSelectionChanged) {
|
|
84
|
+
this.connectSelectionHandler();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
getItems() {
|
|
88
|
+
return this.state.itemOrder.map((id) => this.state.itemsById.get(id));
|
|
89
|
+
}
|
|
90
|
+
getItemById(id) {
|
|
91
|
+
return this.state.itemsById.get(id);
|
|
92
|
+
}
|
|
93
|
+
addItem(id, data) {
|
|
94
|
+
this.state.itemsById.set(id, data);
|
|
95
|
+
const existingIndex = this.state.itemOrder.indexOf(id);
|
|
96
|
+
if (existingIndex !== -1) {
|
|
97
|
+
this.state.itemOrder.splice(existingIndex, 1);
|
|
98
|
+
}
|
|
99
|
+
this.state.itemOrder.push(id);
|
|
100
|
+
this.scheduleSync();
|
|
101
|
+
}
|
|
102
|
+
insertItemBefore(id, data, beforeId) {
|
|
103
|
+
this.state.itemsById.set(id, data);
|
|
104
|
+
const existingIndex = this.state.itemOrder.indexOf(id);
|
|
105
|
+
if (existingIndex !== -1) {
|
|
106
|
+
this.state.itemOrder.splice(existingIndex, 1);
|
|
107
|
+
}
|
|
108
|
+
const beforeIndex = this.state.itemOrder.indexOf(beforeId);
|
|
109
|
+
if (beforeIndex === -1) {
|
|
110
|
+
this.state.itemOrder.push(id);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.state.itemOrder.splice(beforeIndex, 0, id);
|
|
114
|
+
}
|
|
115
|
+
this.scheduleSync();
|
|
116
|
+
}
|
|
117
|
+
removeItem(id) {
|
|
118
|
+
const index = this.state.itemOrder.indexOf(id);
|
|
119
|
+
if (index !== -1) {
|
|
120
|
+
this.state.itemOrder.splice(index, 1);
|
|
121
|
+
this.state.itemsById.delete(id);
|
|
122
|
+
this.scheduleSync();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
updateItem(id, data) {
|
|
126
|
+
if (this.state.itemsById.has(id)) {
|
|
127
|
+
this.state.itemsById.set(id, data);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
scheduleSync() {
|
|
131
|
+
if (!this.state.needsSync) {
|
|
132
|
+
this.state.needsSync = true;
|
|
133
|
+
scheduleFlush(this.syncModel);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
syncModel = () => {
|
|
137
|
+
if (!this.state.needsSync)
|
|
138
|
+
return;
|
|
139
|
+
this.state.needsSync = false;
|
|
140
|
+
const oldOrder = this.state.committedOrder;
|
|
141
|
+
const newOrder = this.state.itemOrder;
|
|
142
|
+
let firstDiff = 0;
|
|
143
|
+
const minLen = Math.min(oldOrder.length, newOrder.length);
|
|
144
|
+
while (firstDiff < minLen && oldOrder[firstDiff] === newOrder[firstDiff]) {
|
|
145
|
+
firstDiff++;
|
|
146
|
+
}
|
|
147
|
+
let oldEndOffset = 0;
|
|
148
|
+
let newEndOffset = 0;
|
|
149
|
+
while (oldEndOffset < oldOrder.length - firstDiff &&
|
|
150
|
+
newEndOffset < newOrder.length - firstDiff &&
|
|
151
|
+
oldOrder[oldOrder.length - 1 - oldEndOffset] === newOrder[newOrder.length - 1 - newEndOffset]) {
|
|
152
|
+
oldEndOffset++;
|
|
153
|
+
newEndOffset++;
|
|
154
|
+
}
|
|
155
|
+
const removeCount = oldOrder.length - firstDiff - oldEndOffset;
|
|
156
|
+
const addItems = newOrder.slice(firstDiff, newOrder.length - newEndOffset);
|
|
157
|
+
if (removeCount > 0 || addItems.length > 0) {
|
|
158
|
+
this.state.stringList.splice(firstDiff, removeCount, addItems);
|
|
159
|
+
}
|
|
160
|
+
this.state.committedOrder = [...newOrder];
|
|
161
|
+
if (this.state.needsInitialSelection && this.state.itemOrder.length > 0) {
|
|
162
|
+
this.state.needsInitialSelection = false;
|
|
163
|
+
queueMicrotask(() => {
|
|
164
|
+
if (this.hasParent()) {
|
|
165
|
+
this.applyInitialSelection();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
applyInitialSelection() {
|
|
171
|
+
this.applySelection(this.state.selected);
|
|
172
|
+
if (this.state.onSelectionChanged) {
|
|
173
|
+
this.connectSelectionHandler();
|
|
174
|
+
this.state.onSelectionChanged(this.getSelectedIds());
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
applySelection(ids) {
|
|
178
|
+
if (this.state.selectionMode === Gtk.SelectionMode.MULTIPLE) {
|
|
179
|
+
const multiSelection = this.state.selectionModel;
|
|
180
|
+
multiSelection.unselectAll();
|
|
181
|
+
for (const id of ids) {
|
|
182
|
+
const index = this.state.itemOrder.indexOf(id);
|
|
183
|
+
if (index !== -1) {
|
|
184
|
+
multiSelection.selectItem(index, false);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
const singleSelection = this.state.selectionModel;
|
|
190
|
+
const firstId = ids[0];
|
|
191
|
+
if (firstId !== undefined) {
|
|
192
|
+
const index = this.state.itemOrder.indexOf(firstId);
|
|
193
|
+
if (index !== -1) {
|
|
194
|
+
singleSelection.setSelected(index);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
singleSelection.setSelected(Gtk.INVALID_LIST_POSITION);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
getSelectedIds() {
|
|
203
|
+
const selection = this.state.selectionModel.getSelection();
|
|
204
|
+
const count = Number(selection.getSize());
|
|
205
|
+
const selectedIds = [];
|
|
206
|
+
for (let i = 0; i < count; i++) {
|
|
207
|
+
const position = selection.getNth(i);
|
|
208
|
+
const id = this.state.itemOrder[position];
|
|
209
|
+
if (id !== undefined) {
|
|
210
|
+
selectedIds.push(id);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return selectedIds;
|
|
214
|
+
}
|
|
215
|
+
connectSelectionHandler() {
|
|
216
|
+
if (this.state.selectionHandlerId !== null)
|
|
217
|
+
return;
|
|
218
|
+
this.state.selectionHandlerId = this.state.selectionModel.connect("selection-changed", () => {
|
|
219
|
+
this.state.onSelectionChanged?.(this.getSelectedIds());
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
disconnectSelectionHandler() {
|
|
223
|
+
if (this.state.selectionHandlerId !== null) {
|
|
224
|
+
GObject.signalHandlerDisconnect(this.state.selectionModel, this.state.selectionHandlerId);
|
|
225
|
+
this.state.selectionHandlerId = null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { StackPageProps } from "../container-interfaces.js";
|
|
2
|
+
export type StackPageLike = {
|
|
3
|
+
setName(name: string): void;
|
|
4
|
+
setTitle(title: string): void;
|
|
5
|
+
setIconName(iconName: string): void;
|
|
6
|
+
setNeedsAttention(needsAttention: boolean): void;
|
|
7
|
+
setVisible(visible: boolean): void;
|
|
8
|
+
setUseUnderline(useUnderline: boolean): void;
|
|
9
|
+
setBadgeNumber?(badgeNumber: number): void;
|
|
10
|
+
};
|
|
11
|
+
export declare function applyStackPageProps(page: StackPageLike, props: StackPageProps): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function applyStackPageProps(page, props) {
|
|
2
|
+
if (props.name !== undefined) {
|
|
3
|
+
page.setName(props.name);
|
|
4
|
+
}
|
|
5
|
+
if (props.title !== undefined) {
|
|
6
|
+
page.setTitle(props.title);
|
|
7
|
+
}
|
|
8
|
+
if (props.iconName !== undefined) {
|
|
9
|
+
page.setIconName(props.iconName);
|
|
10
|
+
}
|
|
11
|
+
if (props.needsAttention !== undefined) {
|
|
12
|
+
page.setNeedsAttention(props.needsAttention);
|
|
13
|
+
}
|
|
14
|
+
if (props.visible !== undefined) {
|
|
15
|
+
page.setVisible(props.visible);
|
|
16
|
+
}
|
|
17
|
+
if (props.useUnderline !== undefined) {
|
|
18
|
+
page.setUseUnderline(props.useUnderline);
|
|
19
|
+
}
|
|
20
|
+
if (props.badgeNumber !== undefined && page.setBadgeNumber) {
|
|
21
|
+
page.setBadgeNumber(props.badgeNumber);
|
|
22
|
+
}
|
|
23
|
+
}
|
package/dist/nodes/stack.d.ts
CHANGED
|
@@ -1,36 +1,22 @@
|
|
|
1
1
|
import type * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
-
import { type
|
|
2
|
+
import { type StackPageContainer, type StackPageProps } from "../container-interfaces.js";
|
|
3
3
|
import type { Props } from "../factory.js";
|
|
4
|
-
import { Node } from "../node.js";
|
|
5
|
-
|
|
4
|
+
import type { Node } from "../node.js";
|
|
5
|
+
import { PagedStackNode } from "./paged-stack.js";
|
|
6
|
+
import { VirtualSlotNode } from "./virtual-slot.js";
|
|
7
|
+
export declare class StackNode extends PagedStackNode<Gtk.Stack> {
|
|
6
8
|
static matches(type: string): boolean;
|
|
7
|
-
private pendingVisibleChildName;
|
|
8
9
|
addStackPage(child: Gtk.Widget, props: StackPageProps): void;
|
|
9
|
-
|
|
10
|
-
insertStackPageBefore(child: Gtk.Widget, props: StackPageProps, _beforeChild: Gtk.Widget): void;
|
|
11
|
-
removeStackPage(child: Gtk.Widget): void;
|
|
12
|
-
updateStackPageProps(child: Gtk.Widget, props: StackPageProps): void;
|
|
13
|
-
private applyStackPageProps;
|
|
14
|
-
attachChild(child: Gtk.Widget): void;
|
|
15
|
-
insertChildBefore(child: Gtk.Widget, _before: Gtk.Widget): void;
|
|
16
|
-
detachChild(child: Gtk.Widget): void;
|
|
17
|
-
protected consumedProps(): Set<string>;
|
|
18
|
-
private setVisibleChildOrDefer;
|
|
19
|
-
updateProps(oldProps: Props, newProps: Props): void;
|
|
10
|
+
protected addChildToWidget(child: Gtk.Widget): void;
|
|
20
11
|
}
|
|
21
|
-
export declare class StackPageNode extends
|
|
12
|
+
export declare class StackPageNode extends VirtualSlotNode<StackPageContainer, StackPageProps> {
|
|
13
|
+
static consumedPropNames: string[];
|
|
22
14
|
static matches(type: string): boolean;
|
|
23
|
-
protected
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
getChildWidget(): Gtk.Widget | null;
|
|
30
|
-
appendChild(child: Node): void;
|
|
31
|
-
attachToParent(parent: Node): void;
|
|
32
|
-
attachToParentBefore(parent: Node, before: Node): void;
|
|
33
|
-
detachFromParent(parent: Node): void;
|
|
34
|
-
protected consumedProps(): Set<string>;
|
|
15
|
+
protected isValidContainer(parent: Node): parent is Node & StackPageContainer;
|
|
16
|
+
protected extractSlotProps(props: Props): StackPageProps;
|
|
17
|
+
protected addToContainer(container: StackPageContainer, child: Gtk.Widget, props: StackPageProps): void;
|
|
18
|
+
protected insertBeforeInContainer(container: StackPageContainer, child: Gtk.Widget, props: StackPageProps, before: Gtk.Widget): void;
|
|
19
|
+
protected removeFromContainer(container: StackPageContainer, child: Gtk.Widget): void;
|
|
20
|
+
protected updateInContainer(container: StackPageContainer, child: Gtk.Widget, props: StackPageProps): void;
|
|
35
21
|
updateProps(oldProps: Props, newProps: Props): void;
|
|
36
22
|
}
|