mirror of
https://github.com/danbulant/mangui
synced 2026-06-20 23:01:11 +00:00
add image node
This commit is contained in:
parent
f7ad523459
commit
866a526605
3 changed files with 62 additions and 17 deletions
|
|
@ -1,16 +1,27 @@
|
|||
use std::fmt::Debug;
|
||||
use femtovg::{ImageId, Paint, Path};
|
||||
use std::{fmt::Debug, mem, path::PathBuf};
|
||||
use femtovg::{Color, ErrorKind, ImageFlags, ImageId, Paint, Path};
|
||||
use crate::{events::handler::EventHandlerDatabase, SharedNode, WeakNode};
|
||||
use super::{Node, NodeChildren, Style};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Simple image node.
|
||||
/// This is basically just a wrapper around Rectangle node with a fill of type Paint::image.
|
||||
/// Use that if you need more options.
|
||||
/// Status of the image - when rendering, image node attempts to load the image and sets this status accordingly.
|
||||
/// Changes this if you want to change the image. If the previous status was loaded, free the image.
|
||||
/// In case the loading fails, image load status changes to Error and the node doesn't render.
|
||||
pub enum ImageLoad {
|
||||
LoadFile(PathBuf, ImageFlags),
|
||||
// LoadArray(&[u8]),
|
||||
LoadVec(Vec<u8>, ImageFlags),
|
||||
Loaded(ImageId),
|
||||
Error(ErrorKind)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Image node.
|
||||
/// Sadly doesn't implement `Default` because of the `ImageLoad` enum.
|
||||
pub struct Image {
|
||||
pub style: Style,
|
||||
/// The image to be rendered. You are responsible for freeing the image data.
|
||||
pub image: ImageId,
|
||||
/// The image to be rendered.
|
||||
pub image: ImageLoad,
|
||||
/// Image width - note that you also have to set the style accordingly for it to render correctly, this is more about scaling the image
|
||||
pub width: f32,
|
||||
/// Image height - note that you also have to set the style accordingly for it to render correctly, this is more about scaling the image
|
||||
|
|
@ -30,7 +41,33 @@ impl Node for Image {
|
|||
None
|
||||
}
|
||||
|
||||
fn render_pre_children(&self, context: &mut super::RenderContext, layout: taffy::prelude::Layout) {
|
||||
fn render_pre_children(&mut self, context: &mut super::RenderContext, layout: taffy::prelude::Layout) {
|
||||
match &self.image {
|
||||
ImageLoad::LoadFile(_, _) => {
|
||||
let image = mem::replace(&mut self.image, ImageLoad::Error(ErrorKind::UnknownError));
|
||||
if let ImageLoad::LoadFile(path, flags) = image {
|
||||
match context.canvas.load_image_file(path, flags) {
|
||||
Ok(image) => {
|
||||
self.image = ImageLoad::Loaded(image);
|
||||
},
|
||||
Err(e) => {
|
||||
self.image = ImageLoad::Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ImageLoad::LoadVec(data, flags) => {
|
||||
match context.canvas.load_image_mem(data, *flags) {
|
||||
Ok(image) => {
|
||||
self.image = ImageLoad::Loaded(image);
|
||||
},
|
||||
Err(e) => {
|
||||
self.image = ImageLoad::Error(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
let mut path = Path::new();
|
||||
path.rounded_rect(
|
||||
0.,
|
||||
|
|
@ -39,10 +76,18 @@ impl Node for Image {
|
|||
layout.size.height,
|
||||
self.radius
|
||||
);
|
||||
context.canvas.fill_path(
|
||||
&path,
|
||||
&Paint::image(self.image, 0., 0., self.width, self.height, 0., 1.)
|
||||
);
|
||||
match &self.image {
|
||||
ImageLoad::Loaded(image) => {
|
||||
context.canvas.fill_path(
|
||||
&path,
|
||||
&Paint::image(*image, 0., 0., self.width, self.height, 0., 1.)
|
||||
);
|
||||
},
|
||||
ImageLoad::Error(_) => {
|
||||
context.canvas.fill_path(&path, &Paint::color(Color::rgb(255, 0, 0)))
|
||||
},
|
||||
_ => unreachable!("We just loaded the image before, so it's either loaded or errored out.")
|
||||
}
|
||||
}
|
||||
|
||||
fn event_handlers(&self) -> Option<crate::events::handler::InnerEventHandlerDataset> {
|
||||
|
|
|
|||
|
|
@ -110,10 +110,10 @@ pub trait Node: Debug {
|
|||
|
||||
/// Render the node, called before rendering it's children
|
||||
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
|
||||
fn render_pre_children(&self, _context: &mut RenderContext, _layout: Layout) {}
|
||||
fn render_pre_children(&mut self, _context: &mut RenderContext, _layout: Layout) {}
|
||||
/// Render the node, called after rendering it's children
|
||||
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
|
||||
fn render_post_children(&self, _context: &mut RenderContext, _layout: Layout) {}
|
||||
fn render_post_children(&mut self, _context: &mut RenderContext, _layout: Layout) {}
|
||||
|
||||
/// Sets the parent node.
|
||||
/// May be called multiple times with the same value.
|
||||
|
|
@ -340,12 +340,12 @@ pub(crate) fn render_recursively(node: &SharedNode, context: &mut RenderContext)
|
|||
}
|
||||
}
|
||||
drop(read_node);
|
||||
sself.read().unwrap().render_pre_children(context, layout);
|
||||
sself.write().unwrap().render_pre_children(context, layout);
|
||||
if let Some(children) = sself.read().unwrap().children() {
|
||||
for child in children {
|
||||
render_recursively(child, context);
|
||||
}
|
||||
}
|
||||
sself.read().unwrap().render_post_children(context, layout);
|
||||
sself.write().unwrap().render_post_children(context, layout);
|
||||
context.canvas.restore();
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ impl Node for Rectangle {
|
|||
fn children(&self) -> Option<&NodeChildren> {
|
||||
None
|
||||
}
|
||||
fn render_pre_children(&self, context: &mut RenderContext, layout: Layout) {
|
||||
fn render_pre_children(&mut self, context: &mut RenderContext, layout: Layout) {
|
||||
let mut path = Path::new();
|
||||
path.rounded_rect(
|
||||
0.,
|
||||
|
|
|
|||
Loading…
Reference in a new issue