summaryrefslogtreecommitdiff
path: root/docs/guide/ags/faq.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/guide/ags/faq.md')
-rw-r--r--docs/guide/ags/faq.md189
1 files changed, 38 insertions, 151 deletions
diff --git a/docs/guide/ags/faq.md b/docs/guide/ags/faq.md
index cb5d609..76d8e72 100644
--- a/docs/guide/ags/faq.md
+++ b/docs/guide/ags/faq.md
@@ -2,22 +2,22 @@
## Monitor id does not match compositor
-The monitor property that windows expect is mapped by Gdk, which is not always
+The monitor id property that windows expect is mapped by Gdk, which is not always
the same as the compositor. Instead use the `gdkmonitor` property which expects
-a `Gdk.Monitor` object which you can get from compositor libraries.
-
-Example with Hyprland
+a `Gdk.Monitor` object.
```tsx
-import Hyprland from "gi://AstalHyprland"
+import { App } from "astal"
function Bar(gdkmonitor) {
return <window gdkmonitor={gdkmonitor} />
}
function main() {
- for (const m of Hyprland.get_default().get_monitors()) {
- Bar(m.gdk_monitor)
+ for (const monitor of App.get_monitors()) {
+ if (monitor.model == "your-desired-model") {
+ Bar(monitor)
+ }
}
}
@@ -53,7 +53,7 @@ import GLib from "gi://GLib"
const HOME = GLib.getenv("HOME")
```
-## Custom svg symbolic icons
+## Custom SVG symbolic icons
Put the svgs in a directory, named `<icon-name>-symbolic.svg`
and use `App.add_icons` or `icons` parameter in `App.start`
@@ -90,74 +90,6 @@ print("print this line to stdout")
printerr("print this line to stderr")
```
-## Binding custom structures
-
-The `bind` function can take two types of objects.
-
-```ts
-interface Subscribable<T = unknown> {
- subscribe(callback: (value: T) => void): () => void
- get(): T
-}
-
-interface Connectable {
- connect(signal: string, callback: (...args: any[]) => unknown): number
- disconnect(id: number): void
-}
-```
-
-`Connectable` is for mostly gobjects, while `Subscribable` is for `Variables`
-and custom objects.
-
-For example you can compose `Variables` in using a class.
-
-```ts
-type MyVariableValue = {
- number: number
- string: string
-}
-
-class MyVariable {
- number = Variable(0)
- string = Variable("")
-
- get(): MyVariableValue {
- return {
- number: this.number.get(),
- string: this.string.get(),
- }
- }
-
- subscribe(callback: (v: MyVariableValue) => void) {
- const unsub1 = this.number.subscribe((value) => {
- callback({ string: value, number: this.number.get() })
- })
-
- const unsub2 = this.string.subscribe((value) => {
- callback({ number: value, string: this.string.get() })
- })
-
- return () => {
- unsub1()
- unsub2()
- }
- }
-}
-```
-
-Then it can be used with `bind`.
-
-```tsx
-function MyWidget() {
- const myvar = new MyVariable()
- const label = bind(myvar).as(({ string, number }) => {
- return `${string} ${number}`
- })
-
- return <label label={label} />
-}
-```
-
## Populate the global scope with frequently accessed variables
It might be annoying to always import Gtk only for `Gtk.Align` enums.
@@ -289,91 +221,46 @@ return <RegularWindow
</RegularWindow>
```
-## Avoiding unnecessary re-rendering
-
-As mentioned before, any object can be bound that implements the `Subscribable` interface.
-
-```ts
-interface Subscribable<T = unknown> {
- subscribe(callback: (value: T) => void): () => void
- get(): T
-}
-```
-
-This can be used to our advantage to create a reactive `Map` object.
-
-```ts
-import { type Subscribable } from "astal/binding"
-import { Gtk } from "astal"
-
-export class VarMap<K, T = Gtk.Widget> implements Subscribable {
- #subs = new Set<(v: Array<[K, T]>) => void>()
- #map: Map<K, T>
-
- #notifiy() {
- const value = this.get()
- for (const sub of this.#subs) {
- sub(value)
- }
- }
-
- #delete(key: K) {
- const v = this.#map.get(key)
-
- if (v instanceof Gtk.Widget) {
- v.destroy()
- }
-
- this.#map.delete(key)
- }
+## Is there a way to limit the width/height of a widget?
- constructor(initial?: Iterable<[K, T]>) {
- this.#map = new Map(initial)
- }
+Unfortunately not. You can set a minimum size with `min-width` and `min-heigth` css attributes,
+but you can not set max size.
- add(key: K, value: T) {
- this.#delete(key)
- this.#map.set(key, value)
- this.#notifiy()
- }
+## Custom widgets with bindable properties
- delete(key: K) {
- this.#delete(key)
- this.#notifiy()
- }
+In function components you can wrap any primitive to handle both
+binding and value cases as one.
- get() {
- return [...this.#map.entries()]
+```tsx
+function MyWidget(props: { prop: string | Binding<string> }) {
+ const prop = props.prop instanceof Binding
+ ? props.prop
+ : bind({ get: () => props.prop, subscribe: () => () => {} })
+
+ function setup(self: Widget.Box) {
+ self.hook(prop, () => {
+ const value = prop.get()
+ // handler
+ })
}
- subscribe(callback: (v: Array<[K, T]>) => void) {
- this.#subs.add(callback)
- return () => this.#subs.delete(callback)
- }
+ return <box setup={setup}>
+ </box>
}
```
-And this `VarMap<key, Widget>` can be used as an alternative to `Variable<Array<Widget>>`.
+You can pass the prop the super constructor in subclasses
```tsx
-function MappedBox() {
- const map = new VarMap([
- [1, <MyWidget id={id} />]
- [2, <MyWidget id={id} />]
- ])
-
- const conns = [
- gobject.connect("added", (_, id) => map.set(id, MyWidget({ id }))),
- gobject.connect("removed", (_, id) => map.delete(id, MyWidget({ id }))),
- ]
-
- return <box onDestroy={() => conns.map(id => gobject.disconnect(id))}>
- {bind(map).as(arr => arr.sort(([a], [b]) => a - b).map(([,w]) => w))}
- </box>
+@register()
+class MyWidget extends Widget.Box {
+ @property(String)
+ set prop(v: string) {
+ // handler
+ }
+
+ constructor(props: { prop: string | Binding<string> }) {
+ super(props)
+ }
}
```
-
-## Is there a way to limit the width/height of a widget?
-
-Unfortunately not. You can set a minimum size with `min-width` and `min-heigth` css attributes,
-but you can not set max size.