opacity.rs

  1use std::{fs, path::PathBuf};
  2
  3use anyhow::Result;
  4use gpui::{
  5    App, Application, AssetSource, Bounds, BoxShadow, ClickEvent, Context, SharedString, Task,
  6    Window, WindowBounds, WindowOptions, div, hsla, img, point, prelude::*, px, rgb, size, svg,
  7};
  8
  9struct Assets {
 10    base: PathBuf,
 11}
 12
 13impl AssetSource for Assets {
 14    fn load(&self, path: &str) -> Result<Option<std::borrow::Cow<'static, [u8]>>> {
 15        fs::read(self.base.join(path))
 16            .map(|data| Some(std::borrow::Cow::Owned(data)))
 17            .map_err(|e| e.into())
 18    }
 19
 20    fn list(&self, path: &str) -> Result<Vec<SharedString>> {
 21        fs::read_dir(self.base.join(path))
 22            .map(|entries| {
 23                entries
 24                    .filter_map(|entry| {
 25                        entry
 26                            .ok()
 27                            .and_then(|entry| entry.file_name().into_string().ok())
 28                            .map(SharedString::from)
 29                    })
 30                    .collect()
 31            })
 32            .map_err(|e| e.into())
 33    }
 34}
 35
 36struct HelloWorld {
 37    _task: Option<Task<()>>,
 38    opacity: f32,
 39    animating: bool,
 40}
 41
 42impl HelloWorld {
 43    fn new(_window: &mut Window, _: &mut Context<Self>) -> Self {
 44        Self {
 45            _task: None,
 46            opacity: 0.5,
 47            animating: false,
 48        }
 49    }
 50
 51    fn start_animation(&mut self, _: &ClickEvent, _: &mut Window, cx: &mut Context<Self>) {
 52        self.opacity = 0.0;
 53        self.animating = true;
 54        cx.notify();
 55    }
 56}
 57
 58impl Render for HelloWorld {
 59    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
 60        if self.animating {
 61            self.opacity += 0.005;
 62            if self.opacity >= 1.0 {
 63                self.animating = false;
 64                self.opacity = 1.0;
 65            } else {
 66                window.request_animation_frame();
 67            }
 68        }
 69
 70        div()
 71            .flex()
 72            .flex_row()
 73            .size_full()
 74            .bg(rgb(0xe0e0e0))
 75            .text_xl()
 76            .child(
 77                div()
 78                    .flex()
 79                    .size_full()
 80                    .justify_center()
 81                    .items_center()
 82                    .border_1()
 83                    .text_color(gpui::blue())
 84                    .child(div().child("This is background text.")),
 85            )
 86            .child(
 87                div()
 88                    .id("panel")
 89                    .on_click(cx.listener(Self::start_animation))
 90                    .absolute()
 91                    .top_8()
 92                    .left_8()
 93                    .right_8()
 94                    .bottom_8()
 95                    .opacity(self.opacity)
 96                    .flex()
 97                    .justify_center()
 98                    .items_center()
 99                    .bg(gpui::white())
100                    .border_3()
101                    .border_color(gpui::red())
102                    .text_color(gpui::yellow())
103                    .child(
104                        div()
105                            .flex()
106                            .flex_col()
107                            .gap_2()
108                            .justify_center()
109                            .items_center()
110                            .size(px(300.))
111                            .bg(gpui::blue())
112                            .border_3()
113                            .border_color(gpui::black())
114                            .shadow(vec![BoxShadow {
115                                color: hsla(0.0, 0.0, 0.0, 0.5),
116                                blur_radius: px(1.0),
117                                spread_radius: px(5.0),
118                                offset: point(px(10.0), px(10.0)),
119                            }])
120                            .child(img("image/app-icon.png").size_8())
121                            .child("Opacity Panel (Click to test)")
122                            .child(
123                                div()
124                                    .id("deep-level-text")
125                                    .flex()
126                                    .justify_center()
127                                    .items_center()
128                                    .p_4()
129                                    .bg(gpui::black())
130                                    .text_color(gpui::white())
131                                    .text_decoration_2()
132                                    .text_decoration_wavy()
133                                    .text_decoration_color(gpui::red())
134                                    .child(format!("opacity: {:.1}", self.opacity)),
135                            )
136                            .child(
137                                svg()
138                                    .path("image/arrow_circle.svg")
139                                    .text_color(gpui::black())
140                                    .text_2xl()
141                                    .size_8(),
142                            )
143                            .child(
144                                div()
145                                    .flex()
146                                    .children(["🎊", "✈️", "🎉", "🎈", "🎁", "🎂"].map(|emoji| {
147                                        div()
148                                            .child(emoji.to_string())
149                                            .hover(|style| style.opacity(0.5))
150                                    })),
151                            )
152                            .child(img("image/black-cat-typing.gif").size_12()),
153                    ),
154            )
155    }
156}
157
158fn main() {
159    Application::new()
160        .with_assets(Assets {
161            base: PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples"),
162        })
163        .run(|cx: &mut App| {
164            let bounds = Bounds::centered(None, size(px(500.0), px(500.0)), cx);
165            cx.open_window(
166                WindowOptions {
167                    window_bounds: Some(WindowBounds::Windowed(bounds)),
168                    ..Default::default()
169                },
170                |window, cx| cx.new(|cx| HelloWorld::new(window, cx)),
171            )
172            .unwrap();
173            cx.activate(true);
174        });
175}