1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use appy::{*, types::*, hooks::*};
use std::rc::Rc;

/// Show an image in the current block.
///
/// Example:
/// ```rust
/// #[main_window]
/// fn main()->Elements {
///     let img_src=use_state(||ImageSource::from_memory(include_bytes!("myimage.png")));
///
///     apx!{
///         <img src=img_src.as_rc()/>
///     }
/// }
/// ```
#[derive_component(ComponentBuilder,Default,SnakeFactory)]
pub struct Img {
	src: Option<Rc<ImageSource>>,
	scale_mode: ScaleMode,
	align: Align,
	valign: VAlign,
}

#[function_component]
fn _img_render(props:Img)->Elements {
	let app_context=use_context::<AppContext>();
	if props.src.is_none() {
		return apx!{}
	}

	let tx=props.src.unwrap();
	let r=&app_context.rect;

	let target_aspect=r.w as f32/r.h as f32;
	let src_aspect=tx.width as f32/tx.height as f32;

	let size=match props.scale_mode {
		ScaleMode::Fit=>
			if src_aspect>target_aspect {
				(r.w as f32,r.w as f32/src_aspect)
			} else {
				(r.h as f32*src_aspect,r.h as f32)
			},

		ScaleMode::Fill=>
			if src_aspect<target_aspect {
				(r.w as f32,r.w as f32/src_aspect)
			} else {
				(r.h as f32*src_aspect,r.h as f32)
			},

		ScaleMode::None=>
			(tx.width as f32*app_context.pixel_ratio,tx.height as f32*app_context.pixel_ratio)
	};

	let x=match props.align {
		Align::Left => r.x,
		Align::Center => r.x+(r.w-size.0 as i32)/2,
		Align::Right => r.x+r.w-size.0 as i32,
	};

	let y=match props.valign {
		VAlign::Top => r.y,
		VAlign::Middle => r.y+(r.h-size.1 as i32)/2,
		VAlign::Bottom => r.y+r.h-size.1 as i32,
	};

	let r=Rect{x,y,w:size.0 as i32,h:size.1 as i32};

	app_context.image_renderer.borrow().draw(&r,&*tx);

	apx!{}
}