Components / content
ImageViewer builder
A framed viewer for one image at a time.
A builder is RenderOnce. Construct and mount it in one expression.
use gpui_kit::content::ImageViewer;
Reviewed in image-viewer.
Construct
new(ident: impl Into<Ident>, frames: impl IntoIterator<Item = ImageFrame>) -> Self
Options
Chain onto the value.
showing(id: impl Into<SharedString>) -> Self
fit(fit: FitMode) -> Self
zoom_range(min: f32, max: f32) -> Self
height(height: f32) -> Self
image(supplier: impl Fn(&ImageFrame, &mut Window, &mut App) -> Option<AnyElement> + 'static) -> Self
on_event(handler: impl Fn(&ImageViewerEvent, &mut Window, &mut App) + 'static) -> Self
Reports
The variants of the event it emits. It never applies the change itself.
- FitChanged
- Stepped
- ImageRequested
Example · image-viewer
fn image_viewer(window: &mut Window, cx: &mut App) -> AnyElement {
let theme = cx.theme().clone();
let state = crate::motion::keyed::slot::<(FitMode, Option<SharedString>)>(
&"scene.image.controlled".into(),
window.window_handle().window_id(),
cx,
);
let (fit, showing) = state.borrow().clone();
stack(&theme)
.w(px(860.0))
.child(
div()
.row()
.items_start()
.gap(px(theme.spacing.lg))
.child(
div().w(px(396.0)).child(
ImageViewer::new(
"scene.image.ready",
[
ImageFrame::new("graph", "The run graph")
.source("runs/graph.png")
.natural(1600, 900),
ImageFrame::new("trace", "The failing trace")
.source("runs/trace.png")
.natural(1200, 1200),
],
)
.showing(showing.unwrap_or_else(|| "graph".into()))
.fit(fit)
.control_size(gpui_kit_theme::ControlSize::Touch)
.height(200.0)
.image(|_, _, cx| Some(run_graph_picture(cx)))
.on_event(move |event, window, _| {
match event {
ImageViewerEvent::FitChanged(fit) => state.borrow_mut().0 = *fit,
ImageViewerEvent::Stepped { id } => state.borrow_mut().1 = Some(id.clone()),
_ => return,
}
window.refresh();
}),
),
)
.child(
div().w(px(396.0)).child(
ImageViewer::new(
"scene.image.refused",
[ImageFrame::new("scan", "Page 4 of the scan")
.source("scans/page-4.tiff")
.natural(2480, 3508)
.unavailable("The workspace is frozen for the release.")],
)
.height(200.0)
.image(|_, _, cx| Some(scene_picture("Supplied by the host", cx)))
.on_event(|_, _, _| {}),
),
),
)
.child(
Divider::new()
.id("scene.image.rule.unmeasured")
.label("A size the host never stated"),
)
.child(
div().row().items_start().gap(px(theme.spacing.lg)).child(div().w(px(396.0)).child(
ImageViewer::new(
"scene.image.unmeasured",
[ImageFrame::new("sketch", "A pasted sketch").source("clipboard")],
)
.height(200.0)
.image(|_, _, cx| Some(pasted_workflow_picture(cx)))
.on_event(|_, _, _| {}),
)).child(div().w(px(396.0)).child(
ImageViewer::new("scene.image.zoom-refused", [ImageFrame::new("graph", "Zoom retained by host").natural(1600, 900)])
.fit(FitMode::Zoom(0.5))
.control_size(gpui_kit_theme::ControlSize::Touch)
.height(200.0)
.image(|_, _, cx| Some(pasted_workflow_picture(cx)))
.on_event(|_, _, _| {}),
)),
)
.child(caption(&theme, "Fixture: the run graph accepts zoom and stepping; Zoom retained by host refuses fit changes; the scan refuses image access."))
.into_any_element()
}