use crate::prelude::*;
use crate::image_map;
use crate::widget::types::scale_mode::ScaleMode;
use crate::render::primitive_kind::PrimitiveKind;
use crate::render::util::new_primitive;
#[derive(Debug, Clone, Widget)]
pub struct Image {
pub image_id: image_map::Id,
pub src_rect: Option<Rect>,
pub style: Style,
position: Point,
dimension: Dimensions,
scale_mode: ScaleMode,
resizeable: bool,
requested_size: Dimensions
}
impl<GS: GlobalState> WidgetExt<GS> for Image {}
impl<S: GlobalState> Layout<S> for Image {
fn flexibility(&self) -> u32 {
10
}
fn calculate_size(&mut self, requested_size: Dimensions, env: &Environment<S>) -> Dimensions {
self.requested_size = requested_size;
let image_information = env.get_image_information(&self.image_id).unwrap();
if !self.resizeable {
self.dimension = [image_information.width as f64, image_information.height as f64];
} else {
let width_factor = requested_size[0] / (image_information.width as f64) ;
let height_factor = requested_size[1] / (image_information.height as f64);
match self.scale_mode {
ScaleMode::Fit => {
let scale_factor = width_factor.min(height_factor);
self.dimension = [(image_information.width as f64) * scale_factor, (image_information.height as f64) * scale_factor]
}
ScaleMode::Fill => {
let scale_factor = width_factor.max(height_factor);
self.dimension = [(image_information.width as f64) * scale_factor, (image_information.height as f64) * scale_factor]
}
ScaleMode::Stretch => {
self.dimension = requested_size
}
}
}
self.dimension
}
fn position_children(&mut self) {
}
}
impl<S: GlobalState> Render<S> for Image {
fn get_primitives(&mut self, _: &text::font::Map) -> Vec<Primitive> {
let kind = PrimitiveKind::Image {
color: None,
image_id: self.image_id,
source_rect: self.src_rect,
};
let rect = Rect::new(self.position, self.dimension);
let mut prims: Vec<Primitive> = vec![new_primitive(kind, rect)];
prims.extend(Rectangle::<S>::debug_outline(rect.clone(), 1.0));
return prims;
}
}
impl<S: GlobalState> CommonWidget<S> for Image {
fn get_id(&self) -> Uuid {
unimplemented!()
}
fn get_flag(&self) -> Flags {
Flags::EMPTY
}
fn get_children(&self) -> WidgetIter<S> {
WidgetIter::Empty
}
fn get_children_mut(&mut self) -> WidgetIterMut<S> {
WidgetIterMut::Empty
}
fn get_proxied_children(&mut self) -> WidgetIterMut<S> {
WidgetIterMut::Empty
}
fn get_position(&self) -> Point {
self.position
}
fn set_position(&mut self, position: Dimensions) {
self.position = position;
}
fn get_dimension(&self) -> Dimensions {
self.dimension
}
fn set_dimension(&mut self, dimensions: Dimensions) {
self.dimension = dimensions
}
}
#[derive(Copy, Clone)]
pub struct State {
pub src_rect: Option<Rect>,
pub image_id: image_map::Id,
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Style {
pub maybe_color: Option<Option<Color>>,
}
impl Image {
pub fn old_new(image_id: image_map::Id) -> Self {
Image {
image_id,
src_rect: None,
style: Style::default(),
position: [0.0, 0.0],
dimension: [0.0, 0.0],
scale_mode: ScaleMode::Fit,
resizeable: false,
requested_size: [0.0, 0.0]
}
}
pub fn new(id: image_map::Id) -> Box<Self> {
Box::new(Image {
image_id: id,
src_rect: None,
style: Default::default(),
position: [0.0, 0.0],
dimension: [0.0, 0.0],
scale_mode: ScaleMode::Fit,
resizeable: false,
requested_size: [0.0, 0.0]
})
}
pub fn source_rectangle(mut self, rect: Rect) -> Self {
self.src_rect = Some(rect);
self
}
pub fn resizeable(mut self) -> Box<Self> {
self.resizeable = true;
Box::new(self)
}
pub fn scaled_to_fit(mut self) -> Box<Self> {
self.resizeable = true;
self.scale_mode = ScaleMode::Fit;
Box::new(self)
}
pub fn scaled_to_fill(mut self) -> Box<Self> {
self.resizeable = true;
self.scale_mode = ScaleMode::Fill;
Box::new(self)
}
pub fn aspect_ratio(mut self, mode: ScaleMode) -> Box<Self> {
self.scale_mode = mode;
Box::new(self)
}
}