diff --git a/src/ags.src.gresource.xml b/src/ags.src.gresource.xml index 4064319..188e5d1 100644 --- a/src/ags.src.gresource.xml +++ b/src/ags.src.gresource.xml @@ -1,13 +1,15 @@ - main.js app.js client.js - utils.js - widget.js + main.js service.js + utils.js + variable.js + widget.js + widgets/constructor.js widgets/overrides.js widgets/box.js widgets/button.js @@ -21,7 +23,6 @@ widgets/progressbar.js widgets/revealer.js widgets/scrollable.js - widgets/shared.js widgets/slider.js widgets/stack.js widgets/window.js diff --git a/src/main.ts b/src/main.ts index 42edd9f..3d357b1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,6 +4,7 @@ import * as Utils from './utils.js'; import App from './app.js'; import client from './client.js'; import Service from './service.js'; +import Variable from './variable.js'; import Widget from './widget.js'; const APP_BUS = (name: string) => 'com.github.Aylur.ags.' + name; @@ -130,6 +131,7 @@ export function main(args: string[]) { Utils, Widget, Service, + Variable, }; const bus = APP_BUS(flags.busName); diff --git a/src/utils.ts b/src/utils.ts index 2a97ea0..0b234a8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,7 +2,7 @@ import Gtk from 'gi://Gtk?version=3.0'; import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; -import { Command } from './widgets/shared.js'; +import { Command } from './widgets/constructor.js'; export const USER = GLib.get_user_name(); export const CACHE_DIR = `${GLib.get_user_cache_dir()}/${pkg.name}`; @@ -113,15 +113,16 @@ export function connect( export function interval( interval: number, - callback: () => void, widget: Gtk.Widget, + callback: () => void, + bind?: Gtk.Widget, ) { callback(); const id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, interval, () => { callback(); return true; }); - if (widget) - widget.connect('destroy', () => GLib.source_remove(id)); + if (bind) + bind.connect('destroy', () => GLib.source_remove(id)); return id; } @@ -211,6 +212,7 @@ export function subprocess( cmd: string | string[], callback: (out: string) => void, onError = logError, + bind?: Gtk.Widget, ) { try { const read = (stdout: Gio.DataInputStream) => { @@ -245,6 +247,10 @@ export function subprocess( }); read(stdout); + + if (bind) + bind.connect('destroy', () => proc.force_exit()); + return proc; } catch (e) { onError(e as Error); diff --git a/src/variable.ts b/src/variable.ts new file mode 100644 index 0000000..9ebd017 --- /dev/null +++ b/src/variable.ts @@ -0,0 +1,62 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import { execAsync, interval, subprocess } from './utils.js'; + +interface Options { + poll?: [interval: number, cmd: string[] | string | (() => unknown)], + listen?: string[] | string, +} + +class AgsVariable extends GObject.Object { + static { + GObject.registerClass({ + GTypeName: 'AgsVariable', + Signals: { 'changed': {} }, + }, this); + } + + _inerval?: number; + _subprocess?: Gio.Subprocess | null; + + constructor(value: any, option: Options) { + super(); + this.value = value; + + if (option.poll) { + const [time, cmd] = option.poll; + if (Array.isArray(cmd) || typeof cmd === 'string') { + this._inerval = interval(time, () => execAsync(cmd) + .catch(logError) + .then(this.setValue.bind(this))); + } + if (typeof cmd === 'function') + this._inerval = interval(time, () => this.setValue(cmd())); + } + + if (option.listen) + this._subprocess = subprocess(option.listen, this.setValue.bind(this), logError); + } + + dispose() { + if (this._inerval) + GLib.source_remove(this._inerval); + + this._subprocess?.force_exit(); + this.run_dispose(); + } + + private _value: any; + + getValue() { return this._value; } + setValue(value: any) { + this._value = value; + this.emit('changed'); + } + + get value() { return this._value; } + set value(value: any) { this.setValue(value); } +} + +export default (value: any, options: Options) => new AgsVariable(value, options); diff --git a/src/widget.ts b/src/widget.ts index 10f7076..340e9e2 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -14,8 +14,7 @@ import AgsProgressBar from './widgets/progressbar.js'; import AgsEntry from './widgets/entry.js'; import { AgsMenu, AgsMenuItem } from './widgets/menu.js'; import AgsWindow from './widgets/window.js'; -import constructor from './widgets/shared.js'; -import { ctor } from './widgets/shared.js'; +import { constructor, type ctor } from './widgets/constructor.js'; export default function Widget({ type, ...params }: { type: ctor }) { return constructor(type, params); diff --git a/src/widgets/button.ts b/src/widgets/button.ts index c900666..e048561 100644 --- a/src/widgets/button.ts +++ b/src/widgets/button.ts @@ -2,7 +2,7 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk?version=3.0'; import Gdk from 'gi://Gdk?version=3.0'; import { runCmd } from '../utils.js'; -import { Command } from './shared.js'; +import { Command } from './constructor.js'; export default class AgsButton extends Gtk.Button { static { diff --git a/src/widgets/shared.ts b/src/widgets/constructor.ts similarity index 78% rename from src/widgets/shared.ts rename to src/widgets/constructor.ts index 34dccff..9c8f6ea 100644 --- a/src/widgets/shared.ts +++ b/src/widgets/constructor.ts @@ -25,16 +25,17 @@ interface CommonParams { [number, (...args: unknown[]) => unknown] | [Connectable, (...args: unknown[]) => unknown, string] )[] - properties?: [string, unknown][] + properties?: [prop: string, value: unknown][] + binds?: [prop: string, obj: Connectable, objProp?: string, signal?: string][], setup?: (widget: Gtk.Widget) => void } function separateCommon({ - className, style, halign, valign, connections, properties, setup, + className, style, halign, valign, connections, properties, binds, setup, ...rest }: CommonParams) { return [ - { className, style, halign, valign, connections, properties, setup }, + { className, style, halign, valign, connections, properties, binds, setup }, rest, ]; } @@ -42,7 +43,7 @@ function separateCommon({ function parseCommon(widget: Gtk.Widget, { className, style, halign, valign, - connections, properties, setup, + connections = [], properties, binds, setup, }: CommonParams) { if (className !== undefined) // @ts-expect-error @@ -84,8 +85,28 @@ function parseCommon(widget: Gtk.Widget, { }); } + if (binds) { + binds.forEach(([prop, obj, value = 'value', signal = 'changed']) => { + if (!prop || !obj) { + logError(new Error('missing arguments to connections')); + return; + } + + const callback = () => { + // @ts-expect-error + widget[prop] = obj[value]; + }; + connections.push([obj, callback, signal]); + }); + } + if (connections) { connections.forEach(([s, callback, event]) => { + if (!s || !callback) { + logError(new Error('missing arguments to connections')); + return; + } + if (typeof s === 'string') widget.connect(s, callback); @@ -112,7 +133,7 @@ function parseCommon(widget: Gtk.Widget, { // eslint-disable-next-line @typescript-eslint/no-explicit-any export type ctor = { new(...args: any[]): Gtk.Widget } -export default function constructor( +export function constructor( ctor: ctor, params: CommonParams | string = {}, ) { diff --git a/src/widgets/entry.ts b/src/widgets/entry.ts index b1f4554..59752eb 100644 --- a/src/widgets/entry.ts +++ b/src/widgets/entry.ts @@ -1,7 +1,7 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk?version=3.0'; import { runCmd } from '../utils.js'; -import { Command } from './shared.js'; +import { Command } from './constructor.js'; export default class AgsEntry extends Gtk.Entry { static { diff --git a/src/widgets/eventbox.ts b/src/widgets/eventbox.ts index 33a084f..17c1a11 100644 --- a/src/widgets/eventbox.ts +++ b/src/widgets/eventbox.ts @@ -2,7 +2,7 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk?version=3.0'; import Gdk from 'gi://Gdk?version=3.0'; import { runCmd } from '../utils.js'; -import { Command } from './shared.js'; +import { Command } from './constructor.js'; export default class AgsEventBox extends Gtk.EventBox { static { diff --git a/src/widgets/menu.ts b/src/widgets/menu.ts index 1919e14..b7ff65e 100644 --- a/src/widgets/menu.ts +++ b/src/widgets/menu.ts @@ -1,7 +1,7 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk?version=3.0'; import { runCmd } from '../utils.js'; -import { Command } from './shared.js'; +import { Command } from './constructor.js'; interface Params { children?: Gtk.Widget[] diff --git a/src/widgets/slider.ts b/src/widgets/slider.ts index f902b01..e7056a4 100644 --- a/src/widgets/slider.ts +++ b/src/widgets/slider.ts @@ -2,7 +2,7 @@ import GObject from 'gi://GObject'; import Gtk from 'gi://Gtk?version=3.0'; import { runCmd } from '../utils.js'; import { EventButton, EventScroll, EventKey } from 'gi-types/gdk3'; -import { Command } from './shared.js'; +import { Command } from './constructor.js'; interface Params { onChange?: Command