image.rs

  1use super::constrain_size_preserving_aspect_ratio;
  2use crate::{
  3    geometry::{
  4        rect::RectF,
  5        vector::{vec2f, Vector2F},
  6    },
  7    json::{json, ToJson},
  8    presenter::MeasurementContext,
  9    scene, Border, DebugContext, Element, Event, EventContext, ImageData, LayoutContext,
 10    PaintContext, SizeConstraint,
 11};
 12use serde::Deserialize;
 13use std::{ops::Range, sync::Arc};
 14
 15pub struct Image {
 16    data: Arc<ImageData>,
 17    style: ImageStyle,
 18}
 19
 20#[derive(Copy, Clone, Default, Deserialize)]
 21pub struct ImageStyle {
 22    #[serde(default)]
 23    pub border: Border,
 24    #[serde(default)]
 25    pub corner_radius: f32,
 26    #[serde(default)]
 27    pub height: Option<f32>,
 28    #[serde(default)]
 29    pub width: Option<f32>,
 30}
 31
 32impl Image {
 33    pub fn new(data: Arc<ImageData>) -> Self {
 34        Self {
 35            data,
 36            style: Default::default(),
 37        }
 38    }
 39
 40    pub fn with_style(mut self, style: ImageStyle) -> Self {
 41        self.style = style;
 42        self
 43    }
 44}
 45
 46impl Element for Image {
 47    type LayoutState = ();
 48    type PaintState = ();
 49
 50    fn layout(
 51        &mut self,
 52        constraint: SizeConstraint,
 53        _: &mut LayoutContext,
 54    ) -> (Vector2F, Self::LayoutState) {
 55        let desired_size = vec2f(
 56            self.style.width.unwrap_or_else(|| constraint.max.x()),
 57            self.style.height.unwrap_or_else(|| constraint.max.y()),
 58        );
 59        let size = constrain_size_preserving_aspect_ratio(
 60            constraint.constrain(desired_size),
 61            self.data.size().to_f32(),
 62        );
 63        (size, ())
 64    }
 65
 66    fn paint(
 67        &mut self,
 68        bounds: RectF,
 69        _: RectF,
 70        _: &mut Self::LayoutState,
 71        cx: &mut PaintContext,
 72    ) -> Self::PaintState {
 73        cx.scene.push_image(scene::Image {
 74            bounds,
 75            border: self.style.border,
 76            corner_radius: self.style.corner_radius,
 77            data: self.data.clone(),
 78        });
 79    }
 80
 81    fn dispatch_event(
 82        &mut self,
 83        _: &Event,
 84        _: RectF,
 85        _: RectF,
 86        _: &mut Self::LayoutState,
 87        _: &mut Self::PaintState,
 88        _: &mut EventContext,
 89    ) -> bool {
 90        false
 91    }
 92
 93    fn rect_for_text_range(
 94        &self,
 95        _: Range<usize>,
 96        _: RectF,
 97        _: RectF,
 98        _: &Self::LayoutState,
 99        _: &Self::PaintState,
100        _: &MeasurementContext,
101    ) -> Option<RectF> {
102        None
103    }
104
105    fn debug(
106        &self,
107        bounds: RectF,
108        _: &Self::LayoutState,
109        _: &Self::PaintState,
110        _: &DebugContext,
111    ) -> serde_json::Value {
112        json!({
113            "type": "Image",
114            "bounds": bounds.to_json(),
115        })
116    }
117}