opacity.rs

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