Skip to content

Commit 9cadfed

Browse files
committed
update popover example
1 parent 9a83bcd commit 9cadfed

File tree

3 files changed

+116
-84
lines changed

3 files changed

+116
-84
lines changed

examples/gtk3/js/applauncher/widget/Applauncher.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ function AppButton({ app }: { app: Apps.Application }) {
3535
export default function Applauncher() {
3636
const { CENTER } = Gtk.Align
3737
const apps = new Apps.Apps()
38+
const width = Variable(1000)
3839

3940
const text = Variable("")
4041
const list = text(text => apps.fuzzy_query(text).slice(0, MAX_ITEMS))
@@ -49,13 +50,16 @@ export default function Applauncher() {
4950
exclusivity={Astal.Exclusivity.IGNORE}
5051
keymode={Astal.Keymode.ON_DEMAND}
5152
application={App}
52-
onShow={() => text.set("")}
53+
onShow={(self) => {
54+
text.set("")
55+
width.set(self.get_current_monitor().workarea.width)
56+
}}
5357
onKeyPressEvent={function (self, event: Gdk.Event) {
5458
if (event.get_keyval()[1] === Gdk.KEY_Escape)
5559
self.hide()
5660
}}>
5761
<box>
58-
<eventbox widthRequest={4000} expand onClick={hide} />
62+
<eventbox widthRequest={width(w => w / 2)} expand onClick={hide} />
5963
<box hexpand={false} vertical>
6064
<eventbox heightRequest={100} onClick={hide} />
6165
<box widthRequest={500} className="Applauncher" vertical>
@@ -81,7 +85,7 @@ export default function Applauncher() {
8185
</box>
8286
<eventbox expand onClick={hide} />
8387
</box>
84-
<eventbox widthRequest={4000} expand onClick={hide} />
88+
<eventbox widthRequest={width(w => w / 2)} expand onClick={hide} />
8589
</box>
8690
</window>
8791
}

examples/gtk3/js/popover/Popover.tsx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { Astal, Gdk, Gtk, Widget } from "astal/gtk3"
2+
3+
const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor
4+
5+
type PopoverProps = Pick<
6+
Widget.WindowProps,
7+
| "name"
8+
| "namespace"
9+
| "className"
10+
| "visible"
11+
| "child"
12+
| "marginBottom"
13+
| "marginTop"
14+
| "marginLeft"
15+
| "marginRight"
16+
| "halign"
17+
| "valign"
18+
> & {
19+
onClose?(self: Widget.Window): void
20+
}
21+
22+
export default function Popover({
23+
child,
24+
visible = false,
25+
marginBottom,
26+
marginTop,
27+
marginLeft,
28+
marginRight,
29+
halign = Gtk.Align.CENTER,
30+
valign = Gtk.Align.CENTER,
31+
onClose,
32+
...props
33+
}: PopoverProps) {
34+
return (
35+
<window
36+
{...props}
37+
css="background-color: transparent"
38+
keymode={Astal.Keymode.EXCLUSIVE}
39+
anchor={TOP | BOTTOM | LEFT | RIGHT}
40+
exclusivity={Astal.Exclusivity.IGNORE}
41+
onNotifyVisible={(self) => {
42+
// instead of anchoring to all sides we set the width explicitly
43+
// otherwise label wrapping won't work correctly without setting their width
44+
if (self.visible) {
45+
self.widthRequest = self.get_current_monitor().workarea.width
46+
} else {
47+
onClose?.(self)
48+
}
49+
}}
50+
// close when click occurs otside of child
51+
onButtonPressEvent={(self, event) => {
52+
const [, _x, _y] = event.get_coords()
53+
const { x, y, width, height } = self
54+
.get_child()!
55+
.get_allocation()
56+
57+
const xOut = _x < x || _x > x + width
58+
const yOut = _y < y || _y > y + height
59+
60+
// clicked outside
61+
if (xOut || yOut) {
62+
self.visible = false
63+
}
64+
}}
65+
// close when hitting Escape
66+
onKeyPressEvent={(self, event: Gdk.Event) => {
67+
if (event.get_keyval()[1] === Gdk.KEY_Escape) {
68+
self.visible = false
69+
}
70+
}}
71+
>
72+
<box
73+
// make sure click event does not bubble up
74+
onButtonPressEvent={() => true}
75+
// child can be positioned with `halign` `valign` and margins
76+
expand
77+
halign={halign}
78+
valign={valign}
79+
marginBottom={marginBottom}
80+
marginTop={marginTop}
81+
marginStart={marginLeft}
82+
marginEnd={marginRight}
83+
>
84+
{child}
85+
</box>
86+
</window>
87+
)
88+
}

examples/gtk3/js/popover/app.tsx

Lines changed: 21 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,41 @@
1-
import { App, Astal, Gdk, Gtk } from "astal/gtk3"
2-
3-
const { TOP, RIGHT, BOTTOM, LEFT } = Astal.WindowAnchor
4-
5-
type PopupProps = {
6-
child?: unknown
7-
marginBottom?: number
8-
marginTop?: number
9-
marginLeft?: number
10-
marginRight?: number
11-
halign?: Gtk.Align
12-
valign?: Gtk.Align
13-
}
14-
15-
function Popup({
16-
child,
17-
marginBottom,
18-
marginTop,
19-
marginLeft,
20-
marginRight,
21-
halign = Gtk.Align.CENTER,
22-
valign = Gtk.Align.CENTER,
23-
}: PopupProps) {
24-
return (
25-
<window
26-
visible={false}
27-
css="background-color: transparent"
28-
keymode={Astal.Keymode.EXCLUSIVE}
29-
anchor={TOP | RIGHT | BOTTOM | LEFT}
30-
exclusivity={Astal.Exclusivity.IGNORE}
31-
// close when click occurs otside of child
32-
onButtonPressEvent={(self, event) => {
33-
const [, _x, _y] = event.get_coords()
34-
const { x, y, width, height } = self
35-
.get_child()!
36-
.get_allocation()
37-
38-
const xOut = _x < x || _x > x + width
39-
const yOut = _y < y || _y > y + height
40-
41-
// clicked outside
42-
if (xOut || yOut) self.hide()
43-
}}
44-
// close when hitting Escape
45-
onKeyPressEvent={(self, event: Gdk.Event) => {
46-
if (event.get_keyval()[1] === Gdk.KEY_Escape) {
47-
self.hide()
48-
}
49-
}}
50-
>
51-
<box
52-
className="Popup"
53-
onButtonPressEvent={() => true} // make sure click event does not bubble up
54-
// child can be positioned with `halign` `valign` and margins
55-
expand
56-
halign={halign}
57-
valign={valign}
58-
marginBottom={marginBottom}
59-
marginTop={marginTop}
60-
marginStart={marginLeft}
61-
marginEnd={marginRight}
62-
>
63-
{child}
64-
</box>
65-
</window>
66-
)
67-
}
1+
import { App, Astal, Gtk } from "astal/gtk3"
2+
import { Variable } from "astal"
3+
import Popup from "./Popover"
4+
const { TOP, RIGHT, LEFT } = Astal.WindowAnchor
685

696
App.start({
707
instanceName: "popup-example",
718
css: `
72-
.Popup {
9+
.Popup>box {
7310
background-color: @theme_bg_color;
7411
box-shadow: 2px 3px 7px 0 rgba(0,0,0,0.4);
7512
border-radius: 12px;
7613
padding: 12px;
7714
}
7815
`,
7916
main() {
80-
const popup = (
81-
<Popup
82-
marginTop={36}
83-
marginRight={60}
84-
valign={Gtk.Align.START}
85-
halign={Gtk.Align.END}
86-
>
87-
<button onClicked={() => popup.hide()}>
88-
Click me to close the popup
89-
</button>
90-
</Popup>
91-
)
17+
const visible = Variable(false);
18+
19+
<Popup
20+
className="Popup"
21+
onClose={() => visible.set(false)}
22+
visible={visible()}
23+
marginTop={36}
24+
marginRight={60}
25+
valign={Gtk.Align.START}
26+
halign={Gtk.Align.END}
27+
>
28+
<button onClicked={() => visible.set(false)}>
29+
Click me to close the popup
30+
</button>
31+
</Popup>
9232

9333
return (
9434
<window
9535
anchor={TOP | LEFT | RIGHT}
9636
exclusivity={Astal.Exclusivity.EXCLUSIVE}
9737
>
98-
<button onClicked={() => popup.show()} halign={Gtk.Align.END}>
38+
<button onClicked={() => visible.set(true)} halign={Gtk.Align.END}>
9939
Click to open popup
10040
</button>
10141
</window>

0 commit comments

Comments
 (0)