summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/widgets.tsx139
1 files changed, 25 insertions, 114 deletions
diff --git a/utils/widgets.tsx b/utils/widgets.tsx
index 033a4e2..1065fae 100644
--- a/utils/widgets.tsx
+++ b/utils/widgets.tsx
@@ -1,5 +1,5 @@
-import { Binding, property, register, timeout } from "astal";
-import { App, Astal, Gdk, Gtk, Widget } from "astal/gtk3";
+import { Binding } from "astal";
+import { App, Astal, Gdk, Widget } from "astal/gtk3";
import AstalHyprland from "gi://AstalHyprland";
export const setupCustomTooltip = (self: any, text: string | Binding<string>) => {
@@ -47,118 +47,29 @@ export const setupCustomTooltip = (self: any, text: string | Binding<string>) =>
export const setupChildClickthrough = (self: any) =>
self.connect("size-allocate", () => self.get_window()?.set_child_input_shapes());
-export enum TransitionType {
- FADE = "",
- SLIDE_DOWN = "margin-top: -${height}px; margin-bottom: ${height}px;",
- SLIDE_UP = "margin-top: ${height}px; margin-bottom: -${height}px;",
- SLIDE_RIGHT = "margin-left: -${width}px; margin-right: ${width}px;",
- SLIDE_LEFT = "margin-left: ${width}px; margin-right: -${width}px;",
-}
+const overrideProp = <T,>(
+ prop: T | Binding<T | undefined> | undefined,
+ override: (prop: T | undefined) => T | undefined
+) => prop && (prop instanceof Binding ? prop.as(override) : override(prop));
-@register()
-export class PopupWindow extends Widget.Window {
- readonly transitionType: TransitionType;
- readonly transitionInDuration: number;
- readonly transitionOutDuration: number;
- readonly transitionAmount: number;
+export const convertPopupWindowProps = (props: Widget.WindowProps): Widget.WindowProps => ({
+ keymode: Astal.Keymode.ON_DEMAND,
+ exclusivity: Astal.Exclusivity.IGNORE,
+ ...props,
+ visible: false,
+ application: App,
+ namespace: overrideProp(props.name, n => `caelestia-${n}`),
+ className: overrideProp(props.className, c => `popup ${c}`),
+ onKeyPressEvent: (self, event) => {
+ // Close window on escape
+ if (event.get_keyval()[1] === Gdk.KEY_Escape) self.hide();
- readonly #content: Widget.Box;
- #visible: boolean = false;
+ return props.onKeyPressEvent?.(self, event);
+ },
+ setup: self => {
+ self.connect("notify::visible", () => self.toggleClassName("visible", self.visible));
+ props.setup?.(self);
+ },
+});
- @property(Boolean)
- get realVisible() {
- return this.#visible;
- }
-
- set realVisible(v: boolean) {
- if (v) this.show();
- else this.hide();
- }
-
- constructor(
- props: Widget.WindowProps & {
- transitionType?: TransitionType;
- transitionInDuration?: number;
- transitionOutDuration?: number;
- transitionAmount?: number;
- }
- ) {
- const {
- clickThrough,
- child,
- halign = Gtk.Align.START,
- valign = Gtk.Align.START,
- transitionType = TransitionType.FADE,
- transitionInDuration = 300,
- transitionOutDuration = 200,
- transitionAmount = 0.2,
- ...sProps
- } = props;
-
- sProps.visible = false;
- sProps.application = App;
- sProps.namespace = `caelestia-${props.name}`;
- sProps.anchor =
- Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.BOTTOM | Astal.WindowAnchor.RIGHT;
- sProps.exclusivity = Astal.Exclusivity.IGNORE;
- if (!sProps.keymode) sProps.keymode = Astal.Keymode.ON_DEMAND;
- sProps.onKeyPressEvent = (self, event) => {
- // Close window on escape
- if (event.get_keyval()[1] === Gdk.KEY_Escape) self.hide();
-
- return props.onKeyPressEvent?.(self, event);
- };
- super(sProps);
-
- this.transitionType = transitionType;
- this.transitionInDuration = transitionInDuration;
- this.transitionOutDuration = transitionOutDuration;
- this.transitionAmount = transitionAmount;
-
- // Wrapper box for animations
- this.#content = (
- <box halign={halign} valign={valign} className={`${props.name}-wrapper`}>
- {clickThrough ? <eventbox>{child}</eventbox> : child}
- </box>
- ) as Widget.Box;
- this.#content.css = this.#getTransitionCss(false);
- this.add(this.#content);
-
- if (clickThrough) setupChildClickthrough(this);
- }
-
- #getTransitionCss(visible: boolean) {
- return (
- `transition-duration: ${visible ? this.transitionInDuration : this.transitionOutDuration}ms;` +
- (visible
- ? "opacity: 1;" + this.transitionType.replaceAll("${width}", "0").replaceAll("${height}", "0")
- : "opacity: 0;" +
- this.transitionType
- .replaceAll("${width}", String(this.#content.get_preferred_width()[1] * this.transitionAmount))
- .replaceAll("${height}", String(this.#content.get_preferred_height()[1] * this.transitionAmount)))
- );
- }
-
- show() {
- this.#visible = true;
- this.notify("real-visible");
-
- super.show();
- this.#content.toggleClassName("visible", true);
- this.#content.css = this.#getTransitionCss(true);
- }
-
- hide() {
- this.#visible = false;
- this.notify("real-visible");
-
- this.#content.toggleClassName("visible", false);
- this.#content.css = this.#getTransitionCss(false);
- timeout(this.transitionOutDuration, () => !this.#visible && super.hide());
- }
-
- toggle() {
- if (this.#visible) this.hide();
- else this.show();
- }
-}
+export const PopupWindow = (props: Widget.WindowProps) => <window {...convertPopupWindowProps(props)} />;