image.rs

  1use std::path::PathBuf;
  2use std::str::FromStr;
  3use std::sync::Arc;
  4
  5use gpui::*;
  6use std::fs;
  7
  8struct Assets {
  9    base: PathBuf,
 10}
 11
 12impl AssetSource for Assets {
 13    fn load(&self, path: &str) -> Result<Option<std::borrow::Cow<'static, [u8]>>> {
 14        fs::read(self.base.join(path))
 15            .map(|data| Some(std::borrow::Cow::Owned(data)))
 16            .map_err(|e| e.into())
 17    }
 18
 19    fn list(&self, path: &str) -> Result<Vec<SharedString>> {
 20        fs::read_dir(self.base.join(path))
 21            .map(|entries| {
 22                entries
 23                    .filter_map(|entry| {
 24                        entry
 25                            .ok()
 26                            .and_then(|entry| entry.file_name().into_string().ok())
 27                            .map(SharedString::from)
 28                    })
 29                    .collect()
 30            })
 31            .map_err(|e| e.into())
 32    }
 33}
 34
 35#[derive(IntoElement)]
 36struct ImageContainer {
 37    text: SharedString,
 38    src: ImageSource,
 39}
 40
 41impl ImageContainer {
 42    pub fn new(text: impl Into<SharedString>, src: impl Into<ImageSource>) -> Self {
 43        Self {
 44            text: text.into(),
 45            src: src.into(),
 46        }
 47    }
 48}
 49
 50impl RenderOnce for ImageContainer {
 51    fn render(self, _: &mut WindowContext) -> impl IntoElement {
 52        div().child(
 53            div()
 54                .flex_row()
 55                .size_full()
 56                .gap_4()
 57                .child(self.text)
 58                .child(img(self.src).w(px(256.0)).h(px(256.0))),
 59        )
 60    }
 61}
 62
 63struct ImageShowcase {
 64    local_resource: Arc<std::path::Path>,
 65    remote_resource: SharedUri,
 66    asset_resource: SharedString,
 67}
 68
 69impl Render for ImageShowcase {
 70    fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
 71        div()
 72            .size_full()
 73            .flex()
 74            .flex_col()
 75            .justify_center()
 76            .items_center()
 77            .gap_8()
 78            .bg(rgb(0xFFFFFF))
 79            .child(
 80                div()
 81                    .flex()
 82                    .flex_row()
 83                    .justify_center()
 84                    .items_center()
 85                    .gap_8()
 86                    .child(ImageContainer::new(
 87                        "Image loaded from a local file",
 88                        self.local_resource.clone(),
 89                    ))
 90                    .child(ImageContainer::new(
 91                        "Image loaded from a remote resource",
 92                        self.remote_resource.clone(),
 93                    ))
 94                    .child(ImageContainer::new(
 95                        "Image loaded from an asset",
 96                        self.asset_resource.clone(),
 97                    )),
 98            )
 99            .child(
100                div()
101                    .flex()
102                    .flex_row()
103                    .gap_8()
104                    .child(
105                        div()
106                            .flex_col()
107                            .child("Auto Width")
108                            .child(img("https://picsum.photos/800/400").h(px(180.))),
109                    )
110                    .child(
111                        div()
112                            .flex_col()
113                            .child("Auto Height")
114                            .child(img("https://picsum.photos/480/640").w(px(180.))),
115                    ),
116            )
117    }
118}
119
120actions!(image, [Quit]);
121
122fn main() {
123    env_logger::init();
124
125    App::new()
126        .with_assets(Assets {
127            base: PathBuf::from("crates/gpui/examples"),
128        })
129        .run(|cx: &mut AppContext| {
130            cx.activate(true);
131            cx.on_action(|_: &Quit, cx| cx.quit());
132            cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]);
133            cx.set_menus(vec![Menu {
134                name: "Image".into(),
135                items: vec![MenuItem::action("Quit", Quit)],
136            }]);
137
138            let window_options = WindowOptions {
139                titlebar: Some(TitlebarOptions {
140                    title: Some(SharedString::from("Image Example")),
141                    appears_transparent: false,
142                    ..Default::default()
143                }),
144
145                window_bounds: Some(WindowBounds::Windowed(Bounds {
146                    size: size(px(1100.), px(600.)),
147                    origin: Point::new(px(200.), px(200.)),
148                })),
149
150                ..Default::default()
151            };
152
153            cx.open_window(window_options, |cx| {
154                cx.new_view(|_cx| ImageShowcase {
155                    // Relative path to your root project path
156                    local_resource: PathBuf::from_str("crates/gpui/examples/image/app-icon.png")
157                        .unwrap()
158                        .into(),
159
160                    remote_resource: "https://picsum.photos/512/512".into(),
161
162                    asset_resource: "image/color.svg".into(),
163                })
164            })
165            .unwrap();
166        });
167}