use crate::element::{ElementProps, ElementWidget};
use crate::parser::color::parse_color;
use crate::parser::values::parse_attribute;
use crate::parser::values::{parse_bool, parse_matches, parse_rect};
use crate::widgets::Widget;
use bevy::asset::AssetServer;
use bevy::color::Color;
use bevy::math::Rect;
use bevy::prelude::{
Component, Entity, EntityCommands, ImageNode, NodeImageMode, TextureSlicer, VisualBox,
};
use roxmltree::Node;
#[derive(Clone, Debug, Component)]
pub struct ImageWidget {
pub src: String,
pub color: Option<Color>,
pub flip_x: Option<bool>,
pub flip_y: Option<bool>,
pub rect: Option<Rect>,
pub mode: Option<NodeImageMode>,
pub visual_box: Option<VisualBox>,
}
impl Widget for ImageWidget {
fn spawn(&self, commands: &mut EntityCommands, assets: &AssetServer) -> Entity {
let image = ImageNode {
color: self.color.unwrap_or(Color::WHITE),
image: assets.load(&self.src),
texture_atlas: None,
flip_x: self.flip_x.unwrap_or_default(),
flip_y: self.flip_y.unwrap_or_default(),
rect: self.rect,
image_mode: self.mode.clone().unwrap_or_default(),
visual_box: self.visual_box.unwrap_or_default(),
};
commands.insert(image);
commands.id()
}
fn parse(
node: &Node,
prefix: Option<&str>,
base: Option<&ElementWidget>,
) -> Result<Self, String>
where
Self: Sized,
{
let base_img = match base {
Some(ElementWidget::Image(ImageWidget {
src,
color,
flip_x,
flip_y,
rect,
mode,
visual_box,
})) => Some((src, color, flip_x, flip_y, rect, mode, visual_box)),
_ => None,
};
let src = parse_attribute(node, "src", prefix, |s| Ok(s.to_string()))?
.or_else(|| base_img.map(|b| b.0.clone()))
.ok_or_else(|| "Must provide a 'src' attribute for widget <Image>".to_string())?;
let color = parse_attribute(node, "color", prefix, parse_color)?
.or_else(|| base_img.and_then(|b| *b.1));
let flip_x = parse_attribute(node, "flip-x", prefix, parse_bool)?
.or_else(|| base_img.and_then(|b| *b.2));
let flip_y = parse_attribute(node, "flip-y", prefix, parse_bool)?
.or_else(|| base_img.and_then(|b| *b.3));
let rect = parse_attribute(node, "rect", prefix, parse_rect)?
.or_else(|| base_img.and_then(|b| *b.4));
let mode = parse_attribute(node, "mode", prefix, |s| {
parse_matches(
s,
&[
("auto", || Ok(NodeImageMode::Auto)),
("sliced", || {
Ok(NodeImageMode::Sliced(TextureSlicer::default()))
}),
("tiled", || {
Ok(NodeImageMode::Tiled {
tile_x: true,
tile_y: true,
stretch_value: 1.0,
})
}),
("stretch", || Ok(NodeImageMode::Stretch)),
],
)
})?
.or_else(|| base_img.and_then(|b| b.5.clone()));
Ok(Self {
src,
color,
flip_x,
flip_y,
rect,
mode,
visual_box: None,
})
}
fn apply_defaults(_: &Node, _: &mut ElementProps, _: &mut ElementProps, _: &mut ElementProps) {}
}