image_gallery.rs

  1use gpui::{
  2    App, AppContext, Application, Bounds, ClickEvent, Context, Entity, HashMapImageCache,
  3    KeyBinding, Menu, MenuItem, SharedString, TitlebarOptions, Window, WindowBounds, WindowOptions,
  4    actions, div, image_cache, img, prelude::*, px, rgb, size,
  5};
  6use reqwest_client::ReqwestClient;
  7use std::sync::Arc;
  8
  9struct ImageGallery {
 10    image_key: String,
 11    items_count: usize,
 12    total_count: usize,
 13    image_cache: Entity<HashMapImageCache>,
 14}
 15
 16impl ImageGallery {
 17    fn on_next_image(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
 18        self.image_cache
 19            .update(cx, |image_cache, cx| image_cache.clear(window, cx));
 20
 21        let t = std::time::SystemTime::now()
 22            .duration_since(std::time::UNIX_EPOCH)
 23            .unwrap()
 24            .as_millis();
 25
 26        self.image_key = format!("{}", t);
 27        self.total_count += self.items_count;
 28        cx.notify();
 29    }
 30}
 31
 32impl Render for ImageGallery {
 33    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
 34        let image_url: SharedString =
 35            format!("https://picsum.photos/400/200?t={}", self.image_key).into();
 36
 37        image_cache(&self.image_cache).child(
 38            div()
 39                .id("main")
 40                .font_family(".SystemUIFont")
 41                .bg(rgb(0xE9E9E9))
 42                .overflow_y_scroll()
 43                .p_4()
 44                .size_full()
 45                .flex()
 46                .flex_col()
 47                .items_center()
 48                .gap_2()
 49                .child(
 50                    div()
 51                        .w_full()
 52                        .flex()
 53                        .flex_row()
 54                        .justify_between()
 55                        .child(format!(
 56                            "Example to show images and test memory usage (Rendered: {} images).",
 57                            self.total_count
 58                        ))
 59                        .child(
 60                            div()
 61                                .id("btn")
 62                                .py_1()
 63                                .px_4()
 64                                .bg(gpui::black())
 65                                .hover(|this| this.opacity(0.8))
 66                                .text_color(gpui::white())
 67                                .text_center()
 68                                .w_40()
 69                                .child("Next Photos")
 70                                .on_click(cx.listener(Self::on_next_image)),
 71                        ),
 72                )
 73                .child(
 74                    div()
 75                        .id("image-gallery")
 76                        .flex()
 77                        .flex_row()
 78                        .flex_wrap()
 79                        .gap_x_4()
 80                        .gap_y_2()
 81                        .justify_around()
 82                        .children(
 83                            (0..self.items_count)
 84                                .map(|ix| img(format!("{}-{}", image_url, ix)).size_20()),
 85                        ),
 86                ),
 87        )
 88    }
 89}
 90
 91actions!(image, [Quit]);
 92
 93fn main() {
 94    env_logger::init();
 95
 96    Application::new().run(move |cx: &mut App| {
 97        let http_client = ReqwestClient::user_agent("gpui example").unwrap();
 98        cx.set_http_client(Arc::new(http_client));
 99
100        cx.activate(true);
101        cx.on_action(|_: &Quit, cx| cx.quit());
102        cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]);
103        cx.set_menus(vec![Menu {
104            name: "Image Gallery".into(),
105            items: vec![MenuItem::action("Quit", Quit)],
106        }]);
107
108        let window_options = WindowOptions {
109            titlebar: Some(TitlebarOptions {
110                title: Some(SharedString::from("Image Gallery")),
111                appears_transparent: false,
112                ..Default::default()
113            }),
114
115            window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
116                None,
117                size(px(1100.), px(860.)),
118                cx,
119            ))),
120
121            ..Default::default()
122        };
123
124        cx.open_window(window_options, |_, cx| {
125            cx.new(|ctx| ImageGallery {
126                image_key: "".into(),
127                items_count: 99,
128                total_count: 0,
129                image_cache: HashMapImageCache::new(ctx),
130            })
131        })
132        .unwrap();
133    });
134}