summaryrefslogtreecommitdiff
path: root/gjs/src
diff options
context:
space:
mode:
Diffstat (limited to 'gjs/src')
-rw-r--r--gjs/src/astalify.ts100
-rw-r--r--gjs/src/jsx/jsx-runtime.ts51
2 files changed, 75 insertions, 76 deletions
diff --git a/gjs/src/astalify.ts b/gjs/src/astalify.ts
index f986716..ecd52d4 100644
--- a/gjs/src/astalify.ts
+++ b/gjs/src/astalify.ts
@@ -1,12 +1,61 @@
import Binding, { kebabify, snakeify, type Connectable, type Subscribable } from "./binding.js"
import { Astal, Gtk } from "./imports.js"
import { execAsync } from "./process.js"
+import Variable from "./variable.js"
Object.defineProperty(Astal.Box.prototype, "children", {
get() { return this.get_children() },
set(v) { this.set_children(v) },
})
+function setChildren(parent: Gtk.Widget, children: Gtk.Widget[]) {
+ children = children.flat(Infinity).map(ch => ch instanceof Gtk.Widget
+ ? ch
+ : new Gtk.Label({ visible: true, label: String(ch) }))
+
+ // remove
+ if (parent instanceof Gtk.Bin) {
+ const ch = parent.get_child()
+ if (ch)
+ parent.remove(ch)
+ }
+
+ // FIXME: add rest of the edge cases like Stack
+ if (parent instanceof Astal.Box) {
+ parent.set_children(children)
+ }
+
+ else if (parent instanceof Astal.CenterBox) {
+ parent.startWidget = children[0]
+ parent.centerWidget = children[1]
+ parent.endWidget = children[2]
+ }
+
+ else if (parent instanceof Astal.Overlay) {
+ const [child, ...overlays] = children
+ parent.set_child(child)
+ parent.set_overlays(overlays)
+ }
+
+ else if (parent instanceof Gtk.Container) {
+ for (const ch of children)
+ parent.add(ch)
+ }
+}
+
+function mergeBindings(array: any[]) {
+ const getValues = () => array.map(i => i instanceof Binding ? i.get() : i)
+ const bindings = array.filter(i => i instanceof Binding)
+
+ if (bindings.length === 0)
+ return array
+
+ if (bindings.length === 1)
+ return bindings[0].as(getValues)
+
+ return Variable.derive(bindings, getValues)()
+}
+
export type Widget<C extends { new(...args: any): Gtk.Widget }> = InstanceType<C> & {
className: string
css: string
@@ -47,7 +96,7 @@ function hook(
return self
}
-function ctor(self: any, config: any = {}, ...children: Gtk.Widget[]) {
+function ctor(self: any, config: any = {}, children: any[] = []) {
const { setup, ...props } = config
props.visible ??= true
@@ -71,9 +120,6 @@ function ctor(self: any, config: any = {}, ...children: Gtk.Widget[]) {
return acc
}, [])
- const pchildren = props.children
- delete props.children
-
Object.assign(self, props)
Object.assign(self, {
hook(obj: any, sig: any, callback: any) {
@@ -91,23 +137,28 @@ function ctor(self: any, config: any = {}, ...children: Gtk.Widget[]) {
}
}
- if (self instanceof Gtk.Container) {
- if (children) {
- for (const child of children)
- self.add(child)
- }
- if (pchildren && Array.isArray(pchildren)) {
- for (const child of pchildren)
- self.add(child)
- }
- }
-
for (const [prop, bind] of bindings) {
+ if (prop === "child" || prop === "children") {
+ self.connect("destroy", bind.subscribe((v: any) => {
+ setChildren(self, v)
+ }))
+ }
self.connect("destroy", bind.subscribe((v: any) => {
self[`set_${snakeify(prop)}`](v)
}))
}
+ children = mergeBindings(children.flat(Infinity))
+ if (children instanceof Binding) {
+ setChildren(self, children.get())
+ self.connect("destroy", children.subscribe(v => {
+ setChildren(self, v)
+ }))
+ }
+ else {
+ setChildren(self, children)
+ }
+
setup?.(self)
return self
}
@@ -130,29 +181,14 @@ function proxify<
set(v) { Astal.widget_set_cursor(this, v) },
})
- klass.prototype.set_child = function(widget: Gtk.Widget) {
- if (this instanceof Gtk.Bin) {
- const rm = this.get_child()
- if (rm)
- this.remove(rm)
- }
- if (this instanceof Gtk.Container)
- this.add(widget)
- }
-
- Object.defineProperty(klass.prototype, "child", {
- get() { return this.get_child?.() },
- set(v) { this.set_child(v) },
- })
-
const proxy = new Proxy(klass, {
construct(_, [conf, ...children]) {
const self = new klass
- return ctor(self, conf, ...children)
+ return ctor(self, conf, children)
},
apply(_t, _a, [conf, ...children]) {
const self = new klass
- return ctor(self, conf, ...children)
+ return ctor(self, conf, children)
},
})
diff --git a/gjs/src/jsx/jsx-runtime.ts b/gjs/src/jsx/jsx-runtime.ts
index 5e7f23b..e96f7c2 100644
--- a/gjs/src/jsx/jsx-runtime.ts
+++ b/gjs/src/jsx/jsx-runtime.ts
@@ -1,12 +1,5 @@
import { Gtk } from "../imports.js"
import * as Widget from "../widgets.js"
-import Binding from "../binding.js"
-
-function w(e: any) {
- return e instanceof Gtk.Widget || e instanceof Binding
- ? e
- : Widget.Label({ label: String(e) })
-}
export function jsx(
ctor: keyof typeof ctors | typeof Gtk.Widget,
@@ -16,46 +9,16 @@ export function jsx(
if (!Array.isArray(children))
children = [children]
- else
- children = children.flat()
-
- // <box children={Binding} /> and <box>{Binding}</box>
- if (ctor === "box" && children.length === 1 && children[0] instanceof Binding) {
- props.children = children[0]
- }
-
- // TODO: handle array of Binding
- // is there a usecase?
-
- else if (ctor === "centerbox") {
- if (children[0])
- props.startWidget = w(children[0])
- if (children[1])
- props.centerWidget = w(children[1])
- if (children[2])
- props.endWidget = w(children[2])
- }
-
- else if (ctor === "overlay") {
- const [child, ...overlays] = children
- if (child)
- props.child = child
-
- props.overlays = overlays
- }
- else if (children.length === 1) {
- props.child = w(children[0])
- delete props.children
- }
+ if (typeof ctor === "string")
+ return (ctors as any)[ctor](props, children)
- else {
- props.children = children.map(w)
- }
+ if (children.length === 1)
+ props.child = children[0]
+ else if (children.length > 1)
+ props.children = children
- return typeof ctor === "string"
- ? (ctors as any)[ctor](props)
- : new ctor(props)
+ return new ctor(props)
}
const ctors = {