summaryrefslogtreecommitdiff
path: root/node/src/astalify.ts
diff options
context:
space:
mode:
Diffstat (limited to 'node/src/astalify.ts')
-rw-r--r--node/src/astalify.ts227
1 files changed, 0 insertions, 227 deletions
diff --git a/node/src/astalify.ts b/node/src/astalify.ts
deleted file mode 100644
index 9f83e71..0000000
--- a/node/src/astalify.ts
+++ /dev/null
@@ -1,227 +0,0 @@
-import { Astal, Gtk } from "./imports.js"
-import Binding, { kebabify, type Connectable, type Subscribable } from "./binding.js"
-
-export type Widget<C extends { new(...args: any): any }> = InstanceType<C> & {
- className: string
- css: string
- cursor: Cursor
- hook(
- object: Connectable,
- signal: string,
- callback: (self: Widget<C>, ...args: any[]) => void,
- ): Widget<C>
- hook(
- object: Subscribable,
- callback: (self: Widget<C>, ...args: any[]) => void,
- ): Widget<C>
-}
-
-
-function setter(prop: string) {
- return `set${prop.charAt(0).toUpperCase() + prop.slice(1)}`
-}
-
-function hook(
- self: any,
- object: Connectable | Subscribable,
- signalOrCallback: string | ((self: any, ...args: any[]) => void),
- callback?: (self: any, ...args: any[]) => void,
-) {
- if (typeof object.connect === "function" && callback) {
- const id = object.connect(signalOrCallback, (_: any, ...args: unknown[]) => {
- callback(self, ...args)
- })
- self.connect("destroy", () => {
- (object.disconnect as Connectable["disconnect"])(id)
- })
- }
-
- else if (typeof object.subscribe === "function" && typeof signalOrCallback === "function") {
- const unsub = object.subscribe((...args: unknown[]) => {
- signalOrCallback(self, ...args)
- })
- self.connect("destroy", unsub)
- }
-
- return self
-}
-
-function setChild(parent: any, child: any) {
- if (parent instanceof Gtk.Bin) {
- if (parent.getChild())
- parent.remove(parent.getChild()!)
- }
- if (parent instanceof Gtk.Container)
- parent.add(child)
-}
-
-function ctor(self: any, config: any, ...children: any[]) {
- const { setup, child, ...props } = config
- props.visible ??= true
-
- const bindings = Object.keys(props).reduce((acc: any, prop) => {
- if (props[prop] instanceof Binding) {
- const bind = [prop, props[prop]]
- prop === "child"
- ? setChild(self, props[prop].get())
- : self[setter(prop)](props[prop].get())
-
- delete props[prop]
- return [...acc, bind]
- }
- return acc
- }, [])
-
- const onHandlers = Object.keys(props).reduce((acc: any, key) => {
- if (key.startsWith("on")) {
- const sig = kebabify(key).split("-").slice(1).join("-")
- const handler = [sig, props[key]]
- delete props[key]
- return [...acc, handler]
- }
- return acc
- }, [])
-
- Object.assign(self, props)
- Object.assign(self, {
- hook(obj: any, sig: any, callback: any) {
- return hook(self, obj, sig, callback)
- },
- })
-
- if (child instanceof Binding) {
- setChild(self, child.get())
- self.connect("destroy", child.subscribe(v => {
- setChild(self, v)
- }))
- } else if (self instanceof Gtk.Container && child instanceof Gtk.Widget) {
- self.add(child)
- }
-
- for (const [signal, callback] of onHandlers)
- self.connect(signal, callback)
-
- if (self instanceof Gtk.Container && children) {
- for (const child of children)
- self.add(child)
- }
-
- for (const [prop, bind] of bindings) {
- self.connect("destroy", bind.subscribe((v: any) => {
- self[`${setter(prop)}`](v)
- }))
- }
-
- setup?.(self)
- return self
-}
-
-function proxify<
- C extends { new(...args: any[]): any },
->(klass: C) {
- Object.defineProperty(klass.prototype, "className", {
- get() { return Astal.widgetGetClassNames(this).join(" ") },
- set(v) { Astal.widgetSetClassNames(this, v.split(/\s+/)) },
- })
-
- Object.defineProperty(klass.prototype, "css", {
- get() { return Astal.widgetGetCss(this) },
- set(v) { Astal.widgetSetCss(this, v) },
- })
-
- Object.defineProperty(klass.prototype, "cursor", {
- get() { return Astal.widgetGetCursor(this) },
- set(v) { Astal.widgetSetCursor(this, v) },
- })
-
- const proxy = new Proxy(klass, {
- construct(_, [conf, ...children]) {
- const self = new klass
- return ctor(self, conf, ...children)
- },
- apply(_t, _a, [conf, ...children]) {
- const self = new klass
- return ctor(self, conf, ...children)
- },
- })
-
- return proxy
-}
-
-export default function astalify<
- C extends typeof Gtk.Widget,
- P extends Record<string, any>,
- N extends string = "Widget",
->(klass: C) {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- type Astal<N> = Omit<C, "new"> & {
- new(props: P, ...children: InstanceType<typeof Gtk.Widget>[]): Widget<C>
- (props: P, ...children: InstanceType<typeof Gtk.Widget>[]): Widget<C>
- }
-
- return proxify(klass) as unknown as Astal<N>
-}
-
-
-type BindableProps<T> = {
- [K in keyof T]: Binding<NonNullable<T[K]>> | T[K];
-}
-
-type SigHandler<
- W extends { new(...args: any): Gtk.Widget },
- Args extends Array<unknown>,
-> = ((self: Widget<W>, ...args: Args) => unknown) | string | string[]
-
-export type ConstructProps<
- Self extends { new(...args: any[]): any },
- Props = unknown,
- Signals extends Record<`on${string}`, Array<unknown>> = Record<`on${string}`, any[]>
-> = Partial<{
- [S in keyof Signals]: SigHandler<Self, Signals[S]>
-}> & Partial<{
- [Key in `on${string}`]: SigHandler<Self, any[]>
-}> & BindableProps<Props & {
- className?: string
- css?: string
- cursor?: string
-}> & {
- onDestroy?: (self: Widget<Self>) => unknown
- onDraw?: (self: Widget<Self>) => unknown
- setup?: (self: Widget<Self>) => void
-}
-
-type Cursor =
- | "default"
- | "help"
- | "pointer"
- | "context-menu"
- | "progress"
- | "wait"
- | "cell"
- | "crosshair"
- | "text"
- | "vertical-text"
- | "alias"
- | "copy"
- | "no-drop"
- | "move"
- | "not-allowed"
- | "grab"
- | "grabbing"
- | "all-scroll"
- | "col-resize"
- | "row-resize"
- | "n-resize"
- | "e-resize"
- | "s-resize"
- | "w-resize"
- | "ne-resize"
- | "nw-resize"
- | "sw-resize"
- | "se-resize"
- | "ew-resize"
- | "ns-resize"
- | "nesw-resize"
- | "nwse-resize"
- | "zoom-in"
- | "zoom-out"