use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;
use crate::color::Color;
use crate::draw_ctx::DrawCtx;
use crate::event::{Event, EventResult};
use crate::geometry::{Rect, Size};
use crate::layout_props::{HAnchor, Insets, VAnchor, WidgetBase};
use crate::text::Font;
use crate::widget::Widget;
pub struct ImageView {
bounds: Rect,
children: Vec<Box<dyn Widget>>, base: WidgetBase,
font: Arc<Font>,
source: Rc<RefCell<Option<(Vec<u8>, u32, u32)>>>,
placeholder: String,
min_height: f64,
outline: bool,
fill_background: bool,
}
impl ImageView {
pub fn new(font: Arc<Font>, source: Rc<RefCell<Option<(Vec<u8>, u32, u32)>>>) -> Self {
Self {
bounds: Rect::default(),
children: Vec::new(),
base: WidgetBase::new(),
font,
source,
placeholder: "No image yet.".into(),
min_height: 120.0,
outline: true,
fill_background: true,
}
}
pub fn with_placeholder(mut self, text: impl Into<String>) -> Self {
self.placeholder = text.into();
self
}
pub fn with_min_height(mut self, h: f64) -> Self {
self.min_height = h;
self
}
pub fn with_outline(mut self, on: bool) -> Self {
self.outline = on;
self
}
pub fn with_fill_background(mut self, on: bool) -> Self {
self.fill_background = on;
self
}
pub fn with_margin(mut self, m: Insets) -> Self {
self.base.margin = m;
self
}
pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
self.base.h_anchor = h;
self
}
pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
self.base.v_anchor = v;
self
}
pub fn with_min_size(mut self, s: Size) -> Self {
self.base.min_size = s;
self
}
pub fn with_max_size(mut self, s: Size) -> Self {
self.base.max_size = s;
self
}
}
impl Widget for ImageView {
fn type_name(&self) -> &'static str {
"ImageView"
}
fn bounds(&self) -> Rect {
self.bounds
}
fn set_bounds(&mut self, b: Rect) {
self.bounds = b;
}
fn children(&self) -> &[Box<dyn Widget>] {
&self.children
}
fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
&mut self.children
}
fn margin(&self) -> Insets {
self.base.margin
}
fn widget_base(&self) -> Option<&WidgetBase> {
Some(&self.base)
}
fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
Some(&mut self.base)
}
fn h_anchor(&self) -> HAnchor {
self.base.h_anchor
}
fn v_anchor(&self) -> VAnchor {
self.base.v_anchor
}
fn min_size(&self) -> Size {
self.base.min_size
}
fn max_size(&self) -> Size {
self.base.max_size
}
fn layout(&mut self, available: Size) -> Size {
let h = available.height.max(self.min_height);
self.bounds = Rect::new(0.0, 0.0, available.width, h);
Size::new(self.bounds.width, self.bounds.height)
}
fn paint(&mut self, ctx: &mut dyn DrawCtx) {
let v = ctx.visuals();
let w = self.bounds.width;
let h = self.bounds.height;
if self.fill_background {
ctx.set_fill_color(v.bg_color);
ctx.begin_path();
ctx.rounded_rect(0.0, 0.0, w, h, 4.0);
ctx.fill();
}
let src = self.source.borrow();
if let Some((pixels, iw, ih)) = src.as_ref() {
let iwf = *iw as f64;
let ihf = *ih as f64;
let scale = (w / iwf).min(h / ihf).max(0.0);
let dw = iwf * scale;
let dh = ihf * scale;
let dx = (w - dw) * 0.5;
let dy = (h - dh) * 0.5;
ctx.draw_image_rgba(pixels, *iw, *ih, dx, dy, dw, dh);
if self.outline {
ctx.set_stroke_color(v.text_color);
ctx.set_line_width(1.0);
ctx.begin_path();
ctx.rect(dx, dy, dw, dh);
ctx.stroke();
}
} else {
ctx.set_font(Arc::clone(&self.font));
ctx.set_font_size(13.0);
ctx.set_fill_color(v.text_dim);
if let Some(m) = ctx.measure_text(&self.placeholder) {
let tx = (w - m.width) * 0.5;
let ty = h * 0.5 - (m.ascent - m.descent) * 0.5;
ctx.fill_text(&self.placeholder, tx, ty);
}
}
let _ = Color::white();
}
fn on_event(&mut self, _: &Event) -> EventResult {
EventResult::Ignored
}
}