1use gpui::{
2 div, prelude::*, px, rgb, size, App, AppContext, Bounds, SharedString, Timer, ViewContext,
3 WindowBounds, WindowContext, WindowKind, WindowOptions,
4};
5
6struct SubWindow {
7 custom_titlebar: bool,
8}
9
10fn button(text: &str, on_click: impl Fn(&mut WindowContext) + 'static) -> impl IntoElement {
11 div()
12 .id(SharedString::from(text.to_string()))
13 .flex_none()
14 .px_2()
15 .bg(rgb(0xf7f7f7))
16 .active(|this| this.opacity(0.85))
17 .border_1()
18 .border_color(rgb(0xe0e0e0))
19 .rounded_md()
20 .cursor_pointer()
21 .child(text.to_string())
22 .on_click(move |_, cx| on_click(cx))
23}
24
25impl Render for SubWindow {
26 fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
27 div()
28 .flex()
29 .flex_col()
30 .bg(rgb(0xffffff))
31 .size_full()
32 .gap_2()
33 .when(self.custom_titlebar, |cx| {
34 cx.child(
35 div()
36 .flex()
37 .h(px(32.))
38 .px_4()
39 .bg(gpui::blue())
40 .text_color(gpui::white())
41 .w_full()
42 .child(
43 div()
44 .flex()
45 .items_center()
46 .justify_center()
47 .size_full()
48 .child("Custom Titlebar"),
49 ),
50 )
51 })
52 .child(
53 div()
54 .p_8()
55 .gap_2()
56 .child("SubWindow")
57 .child(button("Close", |cx| {
58 cx.remove_window();
59 })),
60 )
61 }
62}
63
64struct WindowDemo {}
65
66impl Render for WindowDemo {
67 fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
68 let window_bounds =
69 WindowBounds::Windowed(Bounds::centered(None, size(px(300.0), px(300.0)), cx));
70
71 div()
72 .p_4()
73 .flex()
74 .flex_wrap()
75 .bg(rgb(0xffffff))
76 .size_full()
77 .justify_center()
78 .items_center()
79 .gap_2()
80 .child(button("Normal", move |cx| {
81 cx.open_window(
82 WindowOptions {
83 window_bounds: Some(window_bounds),
84 ..Default::default()
85 },
86 |cx| {
87 cx.new_view(|_cx| SubWindow {
88 custom_titlebar: false,
89 })
90 },
91 )
92 .unwrap();
93 }))
94 .child(button("Popup", move |cx| {
95 cx.open_window(
96 WindowOptions {
97 window_bounds: Some(window_bounds),
98 kind: WindowKind::PopUp,
99 ..Default::default()
100 },
101 |cx| {
102 cx.new_view(|_cx| SubWindow {
103 custom_titlebar: false,
104 })
105 },
106 )
107 .unwrap();
108 }))
109 .child(button("Custom Titlebar", move |cx| {
110 cx.open_window(
111 WindowOptions {
112 titlebar: None,
113 window_bounds: Some(window_bounds),
114 ..Default::default()
115 },
116 |cx| {
117 cx.new_view(|_cx| SubWindow {
118 custom_titlebar: true,
119 })
120 },
121 )
122 .unwrap();
123 }))
124 .child(button("Invisible", move |cx| {
125 cx.open_window(
126 WindowOptions {
127 show: false,
128 window_bounds: Some(window_bounds),
129 ..Default::default()
130 },
131 |cx| {
132 cx.new_view(|_cx| SubWindow {
133 custom_titlebar: false,
134 })
135 },
136 )
137 .unwrap();
138 }))
139 .child(button("Unmovable", move |cx| {
140 cx.open_window(
141 WindowOptions {
142 is_movable: false,
143 titlebar: None,
144 window_bounds: Some(window_bounds),
145 ..Default::default()
146 },
147 |cx| {
148 cx.new_view(|_cx| SubWindow {
149 custom_titlebar: false,
150 })
151 },
152 )
153 .unwrap();
154 }))
155 .child(button("Hide Application", |cx| {
156 cx.hide();
157
158 // Restore the application after 3 seconds
159 cx.spawn(|mut cx| async move {
160 Timer::after(std::time::Duration::from_secs(3)).await;
161 cx.update(|cx| {
162 cx.activate(false);
163 })
164 })
165 .detach();
166 }))
167 }
168}
169
170fn main() {
171 App::new().run(|cx: &mut AppContext| {
172 let bounds = Bounds::centered(None, size(px(800.0), px(600.0)), cx);
173 cx.open_window(
174 WindowOptions {
175 window_bounds: Some(WindowBounds::Windowed(bounds)),
176 ..Default::default()
177 },
178 |cx| cx.new_view(|_cx| WindowDemo {}),
179 )
180 .unwrap();
181 });
182}