@gtkx/react 0.14.0 → 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.
- package/README.md +27 -27
- package/dist/generated/jsx.d.ts +235 -228
- package/dist/host-config.js +2 -2
- package/dist/jsx.d.ts +111 -2
- package/dist/jsx.js +79 -0
- package/dist/nodes/adjustment.d.ts +48 -0
- package/dist/nodes/adjustment.js +70 -0
- package/dist/nodes/calendar.js +3 -16
- package/dist/nodes/column-view-column.d.ts +1 -0
- package/dist/nodes/column-view-column.js +4 -0
- package/dist/nodes/column-view.js +6 -6
- package/dist/nodes/drawing-area.d.ts +1 -0
- package/dist/nodes/drawing-area.js +19 -0
- package/dist/nodes/expander-row.js +1 -0
- package/dist/nodes/index.d.ts +8 -0
- package/dist/nodes/index.js +8 -0
- package/dist/nodes/internal/constants.js +3 -0
- package/dist/nodes/internal/list-item-renderer.d.ts +1 -0
- package/dist/nodes/internal/list-item-renderer.js +5 -0
- package/dist/nodes/internal/predicates.d.ts +4 -0
- package/dist/nodes/internal/predicates.js +3 -0
- package/dist/nodes/internal/signal-store.d.ts +1 -0
- package/dist/nodes/internal/signal-store.js +7 -0
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +1 -0
- package/dist/nodes/internal/tree-list-item-renderer.js +8 -0
- package/dist/nodes/level-bar.js +3 -16
- package/dist/nodes/list-view.js +6 -2
- package/dist/nodes/navigation-page.js +32 -23
- package/dist/nodes/notebook-page-tab.d.ts +1 -0
- package/dist/nodes/notebook-page-tab.js +15 -9
- package/dist/nodes/notebook-page.js +9 -6
- package/dist/nodes/scale.js +3 -16
- package/dist/nodes/scrolled-window.js +3 -2
- package/dist/nodes/shortcut-controller.d.ts +37 -0
- package/dist/nodes/shortcut-controller.js +74 -0
- package/dist/nodes/shortcut.d.ts +38 -0
- package/dist/nodes/shortcut.js +46 -0
- package/dist/nodes/source-buffer.d.ts +73 -0
- package/dist/nodes/source-buffer.js +149 -0
- package/dist/nodes/source-view.d.ts +1 -0
- package/dist/nodes/source-view.js +42 -0
- package/dist/nodes/stack-page.js +15 -9
- package/dist/nodes/text-buffer.d.ts +43 -0
- package/dist/nodes/text-buffer.js +81 -0
- package/dist/nodes/text-view.d.ts +1 -0
- package/dist/nodes/text-view.js +45 -0
- package/dist/nodes/tree-list-view.js +6 -2
- package/dist/nodes/widget.d.ts +4 -0
- package/dist/nodes/widget.js +85 -10
- package/dist/nodes/window.js +7 -5
- package/dist/types.d.ts +26 -0
- package/package.json +3 -3
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { batch } from "@gtkx/ffi";
|
|
2
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
+
import * as GtkSource from "@gtkx/ffi/gtksource";
|
|
4
|
+
import { registerNodeClass } from "../registry.js";
|
|
5
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
6
|
+
import { VirtualNode } from "./virtual.js";
|
|
7
|
+
export class SourceBufferNode extends VirtualNode {
|
|
8
|
+
static priority = 1;
|
|
9
|
+
sourceView;
|
|
10
|
+
buffer;
|
|
11
|
+
static matches(type) {
|
|
12
|
+
return type === "SourceBuffer";
|
|
13
|
+
}
|
|
14
|
+
setSourceView(sourceView) {
|
|
15
|
+
this.sourceView = sourceView;
|
|
16
|
+
this.setupBuffer();
|
|
17
|
+
}
|
|
18
|
+
resolveLanguage(language) {
|
|
19
|
+
if (typeof language === "string") {
|
|
20
|
+
const langManager = GtkSource.LanguageManager.getDefault();
|
|
21
|
+
return langManager.getLanguage(language);
|
|
22
|
+
}
|
|
23
|
+
return language;
|
|
24
|
+
}
|
|
25
|
+
resolveStyleScheme(scheme) {
|
|
26
|
+
if (typeof scheme === "string") {
|
|
27
|
+
const schemeManager = GtkSource.StyleSchemeManager.getDefault();
|
|
28
|
+
return schemeManager.getScheme(scheme);
|
|
29
|
+
}
|
|
30
|
+
return scheme;
|
|
31
|
+
}
|
|
32
|
+
setupBuffer() {
|
|
33
|
+
if (!this.sourceView)
|
|
34
|
+
return;
|
|
35
|
+
this.buffer = new GtkSource.Buffer();
|
|
36
|
+
this.sourceView.setBuffer(this.buffer);
|
|
37
|
+
if (this.props.enableUndo !== undefined) {
|
|
38
|
+
this.buffer.setEnableUndo(this.props.enableUndo);
|
|
39
|
+
}
|
|
40
|
+
if (this.props.text !== undefined) {
|
|
41
|
+
this.buffer.setText(this.props.text, -1);
|
|
42
|
+
}
|
|
43
|
+
this.applySourceProps();
|
|
44
|
+
this.updateSignalHandlers();
|
|
45
|
+
}
|
|
46
|
+
applySourceProps() {
|
|
47
|
+
if (!this.buffer)
|
|
48
|
+
return;
|
|
49
|
+
if (this.props.language !== undefined) {
|
|
50
|
+
const language = this.resolveLanguage(this.props.language);
|
|
51
|
+
this.buffer.setLanguage(language);
|
|
52
|
+
}
|
|
53
|
+
if (this.props.styleScheme !== undefined) {
|
|
54
|
+
const scheme = this.resolveStyleScheme(this.props.styleScheme);
|
|
55
|
+
this.buffer.setStyleScheme(scheme);
|
|
56
|
+
}
|
|
57
|
+
const highlightSyntax = this.props.highlightSyntax ?? this.props.language !== undefined;
|
|
58
|
+
this.buffer.setHighlightSyntax(highlightSyntax);
|
|
59
|
+
const highlightMatchingBrackets = this.props.highlightMatchingBrackets ?? true;
|
|
60
|
+
this.buffer.setHighlightMatchingBrackets(highlightMatchingBrackets);
|
|
61
|
+
if (this.props.implicitTrailingNewline !== undefined) {
|
|
62
|
+
this.buffer.setImplicitTrailingNewline(this.props.implicitTrailingNewline);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
getBufferText() {
|
|
66
|
+
const buffer = this.buffer;
|
|
67
|
+
if (!buffer)
|
|
68
|
+
return "";
|
|
69
|
+
const startIter = new Gtk.TextIter();
|
|
70
|
+
const endIter = new Gtk.TextIter();
|
|
71
|
+
batch(() => {
|
|
72
|
+
buffer.getStartIter(startIter);
|
|
73
|
+
buffer.getEndIter(endIter);
|
|
74
|
+
});
|
|
75
|
+
return buffer.getText(startIter, endIter, true);
|
|
76
|
+
}
|
|
77
|
+
updateSignalHandlers() {
|
|
78
|
+
if (!this.buffer)
|
|
79
|
+
return;
|
|
80
|
+
const buffer = this.buffer;
|
|
81
|
+
const { onTextChanged, onCanUndoChanged, onCanRedoChanged, onCursorMoved, onHighlightUpdated } = this.props;
|
|
82
|
+
signalStore.set(this, buffer, "changed", onTextChanged ? () => onTextChanged(this.getBufferText()) : null);
|
|
83
|
+
signalStore.set(this, buffer, "notify::can-undo", onCanUndoChanged ? () => onCanUndoChanged(buffer.getCanUndo()) : null);
|
|
84
|
+
signalStore.set(this, buffer, "notify::can-redo", onCanRedoChanged ? () => onCanRedoChanged(buffer.getCanRedo()) : null);
|
|
85
|
+
signalStore.set(this, buffer, "cursor-moved", onCursorMoved ?? null);
|
|
86
|
+
signalStore.set(this, buffer, "highlight-updated", onHighlightUpdated
|
|
87
|
+
? (_buffer, start, end) => onHighlightUpdated(start, end)
|
|
88
|
+
: null);
|
|
89
|
+
}
|
|
90
|
+
updateProps(oldProps, newProps) {
|
|
91
|
+
super.updateProps(oldProps, newProps);
|
|
92
|
+
if (!this.buffer)
|
|
93
|
+
return;
|
|
94
|
+
if (!oldProps || oldProps.enableUndo !== newProps.enableUndo) {
|
|
95
|
+
if (newProps.enableUndo !== undefined) {
|
|
96
|
+
this.buffer.setEnableUndo(newProps.enableUndo);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!oldProps || oldProps.text !== newProps.text) {
|
|
100
|
+
if (newProps.text !== undefined) {
|
|
101
|
+
const currentText = this.getBufferText();
|
|
102
|
+
if (currentText !== newProps.text) {
|
|
103
|
+
this.buffer.setText(newProps.text, -1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (!oldProps || oldProps.language !== newProps.language) {
|
|
108
|
+
if (newProps.language !== undefined) {
|
|
109
|
+
const language = this.resolveLanguage(newProps.language);
|
|
110
|
+
this.buffer.setLanguage(language);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!oldProps || oldProps.styleScheme !== newProps.styleScheme) {
|
|
114
|
+
if (newProps.styleScheme !== undefined) {
|
|
115
|
+
const scheme = this.resolveStyleScheme(newProps.styleScheme);
|
|
116
|
+
this.buffer.setStyleScheme(scheme);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!oldProps ||
|
|
120
|
+
oldProps.highlightSyntax !== newProps.highlightSyntax ||
|
|
121
|
+
oldProps.language !== newProps.language) {
|
|
122
|
+
const highlightSyntax = newProps.highlightSyntax ?? newProps.language !== undefined;
|
|
123
|
+
this.buffer.setHighlightSyntax(highlightSyntax);
|
|
124
|
+
}
|
|
125
|
+
if (!oldProps || oldProps.highlightMatchingBrackets !== newProps.highlightMatchingBrackets) {
|
|
126
|
+
const highlightMatchingBrackets = newProps.highlightMatchingBrackets ?? true;
|
|
127
|
+
this.buffer.setHighlightMatchingBrackets(highlightMatchingBrackets);
|
|
128
|
+
}
|
|
129
|
+
if (!oldProps || oldProps.implicitTrailingNewline !== newProps.implicitTrailingNewline) {
|
|
130
|
+
if (newProps.implicitTrailingNewline !== undefined) {
|
|
131
|
+
this.buffer.setImplicitTrailingNewline(newProps.implicitTrailingNewline);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (!oldProps ||
|
|
135
|
+
oldProps.onTextChanged !== newProps.onTextChanged ||
|
|
136
|
+
oldProps.onCanUndoChanged !== newProps.onCanUndoChanged ||
|
|
137
|
+
oldProps.onCanRedoChanged !== newProps.onCanRedoChanged ||
|
|
138
|
+
oldProps.onCursorMoved !== newProps.onCursorMoved ||
|
|
139
|
+
oldProps.onHighlightUpdated !== newProps.onHighlightUpdated) {
|
|
140
|
+
this.updateSignalHandlers();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
unmount() {
|
|
144
|
+
this.buffer = undefined;
|
|
145
|
+
this.sourceView = undefined;
|
|
146
|
+
super.unmount();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
registerNodeClass(SourceBufferNode);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as GtkSource from "@gtkx/ffi/gtksource";
|
|
2
|
+
import { registerNodeClass } from "../registry.js";
|
|
3
|
+
import { isContainerType } from "./internal/utils.js";
|
|
4
|
+
import { SourceBufferNode } from "./source-buffer.js";
|
|
5
|
+
import { WidgetNode } from "./widget.js";
|
|
6
|
+
class SourceViewNode extends WidgetNode {
|
|
7
|
+
static priority = 1;
|
|
8
|
+
bufferChild;
|
|
9
|
+
static matches(_type, containerOrClass) {
|
|
10
|
+
return isContainerType(GtkSource.View, containerOrClass);
|
|
11
|
+
}
|
|
12
|
+
appendChild(child) {
|
|
13
|
+
if (this.tryAttachSourceBuffer(child))
|
|
14
|
+
return;
|
|
15
|
+
super.appendChild(child);
|
|
16
|
+
}
|
|
17
|
+
insertBefore(child, before) {
|
|
18
|
+
if (this.tryAttachSourceBuffer(child))
|
|
19
|
+
return;
|
|
20
|
+
super.insertBefore(child, before);
|
|
21
|
+
}
|
|
22
|
+
removeChild(child) {
|
|
23
|
+
if (child instanceof SourceBufferNode) {
|
|
24
|
+
if (this.bufferChild === child) {
|
|
25
|
+
this.bufferChild = undefined;
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
super.removeChild(child);
|
|
30
|
+
}
|
|
31
|
+
tryAttachSourceBuffer(child) {
|
|
32
|
+
if (!(child instanceof SourceBufferNode))
|
|
33
|
+
return false;
|
|
34
|
+
if (this.bufferChild) {
|
|
35
|
+
throw new Error("SourceView can only have one SourceBuffer child");
|
|
36
|
+
}
|
|
37
|
+
this.bufferChild = child;
|
|
38
|
+
child.setSourceView(this.container);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
registerNodeClass(SourceViewNode);
|
package/dist/nodes/stack-page.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isObjectEqual } from "@gtkx/ffi";
|
|
1
|
+
import { batch, isObjectEqual } from "@gtkx/ffi";
|
|
2
2
|
import * as Adw from "@gtkx/ffi/adw";
|
|
3
3
|
import { registerNodeClass } from "../registry.js";
|
|
4
4
|
import { SlotNode } from "./slot.js";
|
|
@@ -13,11 +13,15 @@ class StackPageNode extends SlotNode {
|
|
|
13
13
|
if (!this.page) {
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
-
if (
|
|
17
|
-
|
|
16
|
+
if (!oldProps || oldProps.title !== newProps.title) {
|
|
17
|
+
if (newProps.title !== undefined) {
|
|
18
|
+
this.page.setTitle(newProps.title);
|
|
19
|
+
}
|
|
18
20
|
}
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
+
if (!oldProps || oldProps.iconName !== newProps.iconName) {
|
|
22
|
+
if (newProps.iconName !== undefined) {
|
|
23
|
+
this.page.setIconName(newProps.iconName);
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
if (!oldProps || oldProps.needsAttention !== newProps.needsAttention) {
|
|
23
27
|
this.page.setNeedsAttention(newProps.needsAttention ?? false);
|
|
@@ -75,10 +79,12 @@ class StackPageNode extends SlotNode {
|
|
|
75
79
|
}
|
|
76
80
|
}
|
|
77
81
|
onChildChange(oldChild) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
this.
|
|
81
|
-
|
|
82
|
+
batch(() => {
|
|
83
|
+
this.removePage(oldChild);
|
|
84
|
+
if (this.child) {
|
|
85
|
+
this.addPage();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
90
|
registerNodeClass(StackPageNode);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { VirtualNode } from "./virtual.js";
|
|
3
|
+
/**
|
|
4
|
+
* Props for the TextBuffer virtual element.
|
|
5
|
+
*
|
|
6
|
+
* Used to declaratively configure the text buffer for a GtkTextView.
|
|
7
|
+
* For GtkSourceView with syntax highlighting, use {@link SourceBufferProps} instead.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <GtkTextView>
|
|
12
|
+
* <x.TextBuffer
|
|
13
|
+
* text="Hello, World!"
|
|
14
|
+
* enableUndo
|
|
15
|
+
* onTextChanged={(text) => console.log("Text:", text)}
|
|
16
|
+
* />
|
|
17
|
+
* </GtkTextView>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export type TextBufferProps = {
|
|
21
|
+
/** Text content */
|
|
22
|
+
text?: string;
|
|
23
|
+
/** Whether to enable undo/redo */
|
|
24
|
+
enableUndo?: boolean;
|
|
25
|
+
/** Callback when the text content changes */
|
|
26
|
+
onTextChanged?: (text: string) => void;
|
|
27
|
+
/** Callback when can-undo state changes */
|
|
28
|
+
onCanUndoChanged?: (canUndo: boolean) => void;
|
|
29
|
+
/** Callback when can-redo state changes */
|
|
30
|
+
onCanRedoChanged?: (canRedo: boolean) => void;
|
|
31
|
+
};
|
|
32
|
+
export declare class TextBufferNode extends VirtualNode<TextBufferProps> {
|
|
33
|
+
static priority: number;
|
|
34
|
+
private textView?;
|
|
35
|
+
private buffer?;
|
|
36
|
+
static matches(type: string): boolean;
|
|
37
|
+
setTextView(textView: Gtk.TextView): void;
|
|
38
|
+
private setupBuffer;
|
|
39
|
+
private getBufferText;
|
|
40
|
+
private updateSignalHandlers;
|
|
41
|
+
updateProps(oldProps: TextBufferProps | null, newProps: TextBufferProps): void;
|
|
42
|
+
unmount(): void;
|
|
43
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { batch } from "@gtkx/ffi";
|
|
2
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
+
import { registerNodeClass } from "../registry.js";
|
|
4
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
5
|
+
import { VirtualNode } from "./virtual.js";
|
|
6
|
+
export class TextBufferNode extends VirtualNode {
|
|
7
|
+
static priority = 1;
|
|
8
|
+
textView;
|
|
9
|
+
buffer;
|
|
10
|
+
static matches(type) {
|
|
11
|
+
return type === "TextBuffer";
|
|
12
|
+
}
|
|
13
|
+
setTextView(textView) {
|
|
14
|
+
this.textView = textView;
|
|
15
|
+
this.setupBuffer();
|
|
16
|
+
}
|
|
17
|
+
setupBuffer() {
|
|
18
|
+
if (!this.textView)
|
|
19
|
+
return;
|
|
20
|
+
this.buffer = new Gtk.TextBuffer();
|
|
21
|
+
this.textView.setBuffer(this.buffer);
|
|
22
|
+
if (this.props.enableUndo !== undefined) {
|
|
23
|
+
this.buffer.setEnableUndo(this.props.enableUndo);
|
|
24
|
+
}
|
|
25
|
+
if (this.props.text !== undefined) {
|
|
26
|
+
this.buffer.setText(this.props.text, -1);
|
|
27
|
+
}
|
|
28
|
+
this.updateSignalHandlers();
|
|
29
|
+
}
|
|
30
|
+
getBufferText() {
|
|
31
|
+
const buffer = this.buffer;
|
|
32
|
+
if (!buffer)
|
|
33
|
+
return "";
|
|
34
|
+
const startIter = new Gtk.TextIter();
|
|
35
|
+
const endIter = new Gtk.TextIter();
|
|
36
|
+
batch(() => {
|
|
37
|
+
buffer.getStartIter(startIter);
|
|
38
|
+
buffer.getEndIter(endIter);
|
|
39
|
+
});
|
|
40
|
+
return buffer.getText(startIter, endIter, true);
|
|
41
|
+
}
|
|
42
|
+
updateSignalHandlers() {
|
|
43
|
+
if (!this.buffer)
|
|
44
|
+
return;
|
|
45
|
+
const buffer = this.buffer;
|
|
46
|
+
const { onTextChanged, onCanUndoChanged, onCanRedoChanged } = this.props;
|
|
47
|
+
signalStore.set(this, buffer, "changed", onTextChanged ? () => onTextChanged(this.getBufferText()) : null);
|
|
48
|
+
signalStore.set(this, buffer, "notify::can-undo", onCanUndoChanged ? () => onCanUndoChanged(buffer.getCanUndo()) : null);
|
|
49
|
+
signalStore.set(this, buffer, "notify::can-redo", onCanRedoChanged ? () => onCanRedoChanged(buffer.getCanRedo()) : null);
|
|
50
|
+
}
|
|
51
|
+
updateProps(oldProps, newProps) {
|
|
52
|
+
super.updateProps(oldProps, newProps);
|
|
53
|
+
if (!this.buffer)
|
|
54
|
+
return;
|
|
55
|
+
if (!oldProps || oldProps.enableUndo !== newProps.enableUndo) {
|
|
56
|
+
if (newProps.enableUndo !== undefined) {
|
|
57
|
+
this.buffer.setEnableUndo(newProps.enableUndo);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!oldProps || oldProps.text !== newProps.text) {
|
|
61
|
+
if (newProps.text !== undefined) {
|
|
62
|
+
const currentText = this.getBufferText();
|
|
63
|
+
if (currentText !== newProps.text) {
|
|
64
|
+
this.buffer.setText(newProps.text, -1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!oldProps ||
|
|
69
|
+
oldProps.onTextChanged !== newProps.onTextChanged ||
|
|
70
|
+
oldProps.onCanUndoChanged !== newProps.onCanUndoChanged ||
|
|
71
|
+
oldProps.onCanRedoChanged !== newProps.onCanRedoChanged) {
|
|
72
|
+
this.updateSignalHandlers();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
unmount() {
|
|
76
|
+
this.buffer = undefined;
|
|
77
|
+
this.textView = undefined;
|
|
78
|
+
super.unmount();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
registerNodeClass(TextBufferNode);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import * as GtkSource from "@gtkx/ffi/gtksource";
|
|
3
|
+
import { registerNodeClass } from "../registry.js";
|
|
4
|
+
import { isContainerType } from "./internal/utils.js";
|
|
5
|
+
import { TextBufferNode } from "./text-buffer.js";
|
|
6
|
+
import { WidgetNode } from "./widget.js";
|
|
7
|
+
class TextViewNode extends WidgetNode {
|
|
8
|
+
static priority = 1;
|
|
9
|
+
bufferChild;
|
|
10
|
+
static matches(_type, containerOrClass) {
|
|
11
|
+
if (isContainerType(GtkSource.View, containerOrClass))
|
|
12
|
+
return false;
|
|
13
|
+
return isContainerType(Gtk.TextView, containerOrClass);
|
|
14
|
+
}
|
|
15
|
+
appendChild(child) {
|
|
16
|
+
if (this.tryAttachTextBuffer(child))
|
|
17
|
+
return;
|
|
18
|
+
super.appendChild(child);
|
|
19
|
+
}
|
|
20
|
+
insertBefore(child, before) {
|
|
21
|
+
if (this.tryAttachTextBuffer(child))
|
|
22
|
+
return;
|
|
23
|
+
super.insertBefore(child, before);
|
|
24
|
+
}
|
|
25
|
+
removeChild(child) {
|
|
26
|
+
if (child instanceof TextBufferNode) {
|
|
27
|
+
if (this.bufferChild === child) {
|
|
28
|
+
this.bufferChild = undefined;
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
super.removeChild(child);
|
|
33
|
+
}
|
|
34
|
+
tryAttachTextBuffer(child) {
|
|
35
|
+
if (!(child instanceof TextBufferNode))
|
|
36
|
+
return false;
|
|
37
|
+
if (this.bufferChild) {
|
|
38
|
+
throw new Error("TextView can only have one TextBuffer child");
|
|
39
|
+
}
|
|
40
|
+
this.bufferChild = child;
|
|
41
|
+
child.setTextView(this.container);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
registerNodeClass(TextViewNode);
|
|
@@ -34,6 +34,10 @@ class TreeListViewNode extends WidgetNode {
|
|
|
34
34
|
super.mount();
|
|
35
35
|
this.container.setModel(this.treeList.getSelectionModel());
|
|
36
36
|
}
|
|
37
|
+
unmount() {
|
|
38
|
+
this.itemRenderer.dispose();
|
|
39
|
+
super.unmount();
|
|
40
|
+
}
|
|
37
41
|
appendChild(child) {
|
|
38
42
|
if (!(child instanceof TreeListItemNode)) {
|
|
39
43
|
throw new Error(`Cannot append '${child.typeName}' to 'TreeListView': expected x.TreeListItem`);
|
|
@@ -60,12 +64,12 @@ class TreeListViewNode extends WidgetNode {
|
|
|
60
64
|
this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight);
|
|
61
65
|
}
|
|
62
66
|
const previousModel = this.treeList.getSelectionModel();
|
|
63
|
-
this.treeList.updateProps(oldProps
|
|
67
|
+
this.treeList.updateProps(filterProps(oldProps ?? {}, RENDERER_PROP_NAMES), filterProps(newProps, RENDERER_PROP_NAMES));
|
|
64
68
|
const currentModel = this.treeList.getSelectionModel();
|
|
65
69
|
if (previousModel !== currentModel) {
|
|
66
70
|
this.container.setModel(currentModel);
|
|
67
71
|
}
|
|
68
|
-
super.updateProps(oldProps
|
|
72
|
+
super.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
registerNodeClass(TreeListViewNode);
|
package/dist/nodes/widget.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export declare class WidgetNode<T extends Gtk.Widget = Gtk.Widget, P extends Pro
|
|
|
9
9
|
private scrollController?;
|
|
10
10
|
private dragSourceController?;
|
|
11
11
|
private dropTargetController?;
|
|
12
|
+
private gestureDragController?;
|
|
13
|
+
private adjustmentChild?;
|
|
12
14
|
static matches(_type: string, containerOrClass?: Container | ContainerClass | null): boolean;
|
|
13
15
|
static createContainer(props: Props, containerClass: typeof Gtk.Widget): Container | null;
|
|
14
16
|
appendChild(child: Node): void;
|
|
@@ -18,9 +20,11 @@ export declare class WidgetNode<T extends Gtk.Widget = Gtk.Widget, P extends Pro
|
|
|
18
20
|
private insertBeforeInsertable;
|
|
19
21
|
updateProps(oldProps: P | null, newProps: P): void;
|
|
20
22
|
private updateSizeRequest;
|
|
23
|
+
private updateGrabFocus;
|
|
21
24
|
private updateEventControllerProp;
|
|
22
25
|
private ensureDragSource;
|
|
23
26
|
private ensureDropTarget;
|
|
27
|
+
private ensureGestureDrag;
|
|
24
28
|
private updateNotifyHandler;
|
|
25
29
|
private propNameToSignalName;
|
|
26
30
|
private getProperty;
|
package/dist/nodes/widget.js
CHANGED
|
@@ -4,12 +4,14 @@ import * as Gtk from "@gtkx/ffi/gtk";
|
|
|
4
4
|
import { CONSTRUCTOR_PROPS } from "../generated/internal.js";
|
|
5
5
|
import { Node } from "../node.js";
|
|
6
6
|
import { registerNodeClass } from "../registry.js";
|
|
7
|
+
import { AdjustmentNode } from "./adjustment.js";
|
|
7
8
|
import { EVENT_CONTROLLER_PROPS } from "./internal/constants.js";
|
|
8
|
-
import { hasSingleContent, isAddable, isAppendable, isEditable, isInsertable, isRemovable, isReorderable, isSingleChild, } from "./internal/predicates.js";
|
|
9
|
+
import { hasSingleContent, isAddable, isAdjustable, isAppendable, isEditable, isInsertable, isRemovable, isReorderable, isSingleChild, } from "./internal/predicates.js";
|
|
9
10
|
import { signalStore } from "./internal/signal-store.js";
|
|
10
11
|
import { filterProps, isContainerType, resolvePropMeta, resolveSignal } from "./internal/utils.js";
|
|
12
|
+
import { ShortcutControllerNode } from "./shortcut-controller.js";
|
|
11
13
|
import { SlotNode } from "./slot.js";
|
|
12
|
-
const PROPS = ["children", "widthRequest", "heightRequest"];
|
|
14
|
+
const PROPS = ["children", "widthRequest", "heightRequest", "grabFocus"];
|
|
13
15
|
export class WidgetNode extends Node {
|
|
14
16
|
static priority = 3;
|
|
15
17
|
motionController;
|
|
@@ -18,6 +20,8 @@ export class WidgetNode extends Node {
|
|
|
18
20
|
scrollController;
|
|
19
21
|
dragSourceController;
|
|
20
22
|
dropTargetController;
|
|
23
|
+
gestureDragController;
|
|
24
|
+
adjustmentChild;
|
|
21
25
|
static matches(_type, containerOrClass) {
|
|
22
26
|
return isContainerType(Gtk.Widget, containerOrClass);
|
|
23
27
|
}
|
|
@@ -28,10 +32,25 @@ export class WidgetNode extends Node {
|
|
|
28
32
|
return new WidgetClass(...args);
|
|
29
33
|
}
|
|
30
34
|
appendChild(child) {
|
|
35
|
+
if (child instanceof ShortcutControllerNode) {
|
|
36
|
+
child.setParent(this.container);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
31
39
|
if (child instanceof SlotNode) {
|
|
32
40
|
child.setParent(this.container);
|
|
33
41
|
return;
|
|
34
42
|
}
|
|
43
|
+
if (child instanceof AdjustmentNode) {
|
|
44
|
+
if (!isAdjustable(this.container)) {
|
|
45
|
+
throw new Error(`Cannot add Adjustment to '${this.typeName}': widget does not support adjustments`);
|
|
46
|
+
}
|
|
47
|
+
if (this.adjustmentChild) {
|
|
48
|
+
throw new Error(`${this.typeName} can only have one Adjustment child`);
|
|
49
|
+
}
|
|
50
|
+
this.adjustmentChild = child;
|
|
51
|
+
child.setWidget(this.container);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
35
54
|
if (!(child instanceof WidgetNode)) {
|
|
36
55
|
throw new Error(`Cannot append '${child.typeName}' to 'Widget': expected WidgetNode child`);
|
|
37
56
|
}
|
|
@@ -41,9 +60,19 @@ export class WidgetNode extends Node {
|
|
|
41
60
|
batch(() => this.attachChild(child));
|
|
42
61
|
}
|
|
43
62
|
removeChild(child) {
|
|
63
|
+
if (child instanceof ShortcutControllerNode) {
|
|
64
|
+
child.setParent(undefined);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
44
67
|
if (child instanceof SlotNode) {
|
|
45
68
|
return;
|
|
46
69
|
}
|
|
70
|
+
if (child instanceof AdjustmentNode) {
|
|
71
|
+
if (this.adjustmentChild === child) {
|
|
72
|
+
this.adjustmentChild = undefined;
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
47
76
|
if (!(child instanceof WidgetNode)) {
|
|
48
77
|
throw new Error(`Cannot remove '${child.typeName}' from 'Widget': expected WidgetNode child`);
|
|
49
78
|
}
|
|
@@ -53,10 +82,25 @@ export class WidgetNode extends Node {
|
|
|
53
82
|
batch(() => this.detachChild(child));
|
|
54
83
|
}
|
|
55
84
|
insertBefore(child, before) {
|
|
85
|
+
if (child instanceof ShortcutControllerNode) {
|
|
86
|
+
child.setParent(this.container);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
56
89
|
if (child instanceof SlotNode) {
|
|
57
90
|
child.setParent(this.container);
|
|
58
91
|
return;
|
|
59
92
|
}
|
|
93
|
+
if (child instanceof AdjustmentNode) {
|
|
94
|
+
if (!isAdjustable(this.container)) {
|
|
95
|
+
throw new Error(`Cannot add Adjustment to '${this.typeName}': widget does not support adjustments`);
|
|
96
|
+
}
|
|
97
|
+
if (this.adjustmentChild) {
|
|
98
|
+
throw new Error(`${this.typeName} can only have one Adjustment child`);
|
|
99
|
+
}
|
|
100
|
+
this.adjustmentChild = child;
|
|
101
|
+
child.setWidget(this.container);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
60
104
|
if (!(child instanceof WidgetNode) || !(before instanceof WidgetNode)) {
|
|
61
105
|
throw new Error(`Cannot insert '${child.typeName}' before '${before.typeName}': expected WidgetNode children`);
|
|
62
106
|
}
|
|
@@ -94,11 +138,13 @@ export class WidgetNode extends Node {
|
|
|
94
138
|
}
|
|
95
139
|
updateProps(oldProps, newProps) {
|
|
96
140
|
this.updateSizeRequest(oldProps, newProps);
|
|
141
|
+
this.updateGrabFocus(oldProps, newProps);
|
|
97
142
|
const propNames = new Set([
|
|
98
143
|
...Object.keys(filterProps(oldProps ?? {}, PROPS)),
|
|
99
144
|
...Object.keys(filterProps(newProps ?? {}, PROPS)),
|
|
100
145
|
]);
|
|
101
146
|
const pendingSignals = [];
|
|
147
|
+
const pendingProperties = [];
|
|
102
148
|
for (const name of propNames) {
|
|
103
149
|
const oldValue = oldProps?.[name];
|
|
104
150
|
const newValue = newProps[name];
|
|
@@ -117,14 +163,7 @@ export class WidgetNode extends Node {
|
|
|
117
163
|
pendingSignals.push({ name, newValue });
|
|
118
164
|
}
|
|
119
165
|
else if (newValue !== undefined) {
|
|
120
|
-
|
|
121
|
-
if (isEditableText && oldValue !== undefined) {
|
|
122
|
-
const currentValue = this.getProperty(name);
|
|
123
|
-
if (oldValue !== currentValue) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
this.setProperty(name, newValue);
|
|
166
|
+
pendingProperties.push({ name, oldValue, newValue });
|
|
128
167
|
}
|
|
129
168
|
}
|
|
130
169
|
for (const { name, newValue } of pendingSignals) {
|
|
@@ -140,6 +179,16 @@ export class WidgetNode extends Node {
|
|
|
140
179
|
signalStore.set(this, this.container, signalName, handler);
|
|
141
180
|
}
|
|
142
181
|
}
|
|
182
|
+
for (const { name, oldValue, newValue } of pendingProperties) {
|
|
183
|
+
const isEditableText = name === "text" && isEditable(this.container);
|
|
184
|
+
if (isEditableText && oldValue !== undefined) {
|
|
185
|
+
const currentValue = this.getProperty(name);
|
|
186
|
+
if (oldValue !== currentValue) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
this.setProperty(name, newValue);
|
|
191
|
+
}
|
|
143
192
|
}
|
|
144
193
|
updateSizeRequest(oldProps, newProps) {
|
|
145
194
|
const oldWidth = oldProps?.widthRequest;
|
|
@@ -150,6 +199,13 @@ export class WidgetNode extends Node {
|
|
|
150
199
|
this.container.setSizeRequest(newWidth ?? -1, newHeight ?? -1);
|
|
151
200
|
}
|
|
152
201
|
}
|
|
202
|
+
updateGrabFocus(oldProps, newProps) {
|
|
203
|
+
const oldGrabFocus = oldProps?.grabFocus;
|
|
204
|
+
const newGrabFocus = newProps.grabFocus;
|
|
205
|
+
if (!oldGrabFocus && newGrabFocus) {
|
|
206
|
+
this.container.grabFocus();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
153
209
|
updateEventControllerProp(propName, handlerOrValue) {
|
|
154
210
|
const wrappedHandler = typeof handlerOrValue === "function"
|
|
155
211
|
? (_self, ...args) => handlerOrValue(...args)
|
|
@@ -241,6 +297,18 @@ export class WidgetNode extends Node {
|
|
|
241
297
|
}
|
|
242
298
|
break;
|
|
243
299
|
}
|
|
300
|
+
case "onGestureDragBegin":
|
|
301
|
+
case "onGestureDragUpdate":
|
|
302
|
+
case "onGestureDragEnd": {
|
|
303
|
+
const gestureDrag = this.ensureGestureDrag();
|
|
304
|
+
const signalName = propName === "onGestureDragBegin"
|
|
305
|
+
? "drag-begin"
|
|
306
|
+
: propName === "onGestureDragUpdate"
|
|
307
|
+
? "drag-update"
|
|
308
|
+
: "drag-end";
|
|
309
|
+
signalStore.set(this, gestureDrag, signalName, wrappedHandler);
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
244
312
|
}
|
|
245
313
|
}
|
|
246
314
|
ensureDragSource() {
|
|
@@ -258,6 +326,13 @@ export class WidgetNode extends Node {
|
|
|
258
326
|
}
|
|
259
327
|
return this.dropTargetController;
|
|
260
328
|
}
|
|
329
|
+
ensureGestureDrag() {
|
|
330
|
+
if (!this.gestureDragController) {
|
|
331
|
+
this.gestureDragController = new Gtk.GestureDrag();
|
|
332
|
+
this.container.addController(this.gestureDragController);
|
|
333
|
+
}
|
|
334
|
+
return this.gestureDragController;
|
|
335
|
+
}
|
|
261
336
|
updateNotifyHandler(handler) {
|
|
262
337
|
const wrappedHandler = handler
|
|
263
338
|
? (obj, pspec) => {
|
package/dist/nodes/window.js
CHANGED
|
@@ -68,12 +68,14 @@ export class WindowNode extends WidgetNode {
|
|
|
68
68
|
const height = newProps.defaultHeight ?? -1;
|
|
69
69
|
this.container.setDefaultSize(width, height);
|
|
70
70
|
}
|
|
71
|
-
if (oldProps
|
|
71
|
+
if (!oldProps || oldProps.onClose !== newProps.onClose) {
|
|
72
72
|
const userHandler = newProps.onClose;
|
|
73
|
-
const wrappedHandler =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const wrappedHandler = userHandler
|
|
74
|
+
? () => {
|
|
75
|
+
userHandler();
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
: undefined;
|
|
77
79
|
signalStore.set(this, this.container, "close-request", wrappedHandler);
|
|
78
80
|
}
|
|
79
81
|
super.updateProps(filterProps(oldProps ?? {}, PROPS), filterProps(newProps, PROPS));
|