agg_gui/widgets/
image_view.rs1use std::cell::RefCell;
12use std::rc::Rc;
13use std::sync::Arc;
14
15use crate::color::Color;
16use crate::draw_ctx::DrawCtx;
17use crate::event::{Event, EventResult};
18use crate::geometry::{Rect, Size};
19use crate::layout_props::{HAnchor, Insets, VAnchor, WidgetBase};
20use crate::text::Font;
21use crate::widget::Widget;
22
23pub struct ImageView {
24 bounds: Rect,
25 children: Vec<Box<dyn Widget>>, base: WidgetBase,
27 font: Arc<Font>,
28 source: Rc<RefCell<Option<(Vec<u8>, u32, u32)>>>,
29 placeholder: String,
31 min_height: f64,
33 outline: bool,
35 fill_background: bool,
38}
39
40impl ImageView {
41 pub fn new(font: Arc<Font>, source: Rc<RefCell<Option<(Vec<u8>, u32, u32)>>>) -> Self {
42 Self {
43 bounds: Rect::default(),
44 children: Vec::new(),
45 base: WidgetBase::new(),
46 font,
47 source,
48 placeholder: "No image yet.".into(),
49 min_height: 120.0,
50 outline: true,
51 fill_background: true,
52 }
53 }
54
55 pub fn with_placeholder(mut self, text: impl Into<String>) -> Self {
56 self.placeholder = text.into();
57 self
58 }
59 pub fn with_min_height(mut self, h: f64) -> Self {
60 self.min_height = h;
61 self
62 }
63 pub fn with_outline(mut self, on: bool) -> Self {
64 self.outline = on;
65 self
66 }
67 pub fn with_fill_background(mut self, on: bool) -> Self {
68 self.fill_background = on;
69 self
70 }
71
72 pub fn with_margin(mut self, m: Insets) -> Self {
73 self.base.margin = m;
74 self
75 }
76 pub fn with_h_anchor(mut self, h: HAnchor) -> Self {
77 self.base.h_anchor = h;
78 self
79 }
80 pub fn with_v_anchor(mut self, v: VAnchor) -> Self {
81 self.base.v_anchor = v;
82 self
83 }
84 pub fn with_min_size(mut self, s: Size) -> Self {
85 self.base.min_size = s;
86 self
87 }
88 pub fn with_max_size(mut self, s: Size) -> Self {
89 self.base.max_size = s;
90 self
91 }
92}
93
94impl Widget for ImageView {
95 fn type_name(&self) -> &'static str {
96 "ImageView"
97 }
98 fn bounds(&self) -> Rect {
99 self.bounds
100 }
101 fn set_bounds(&mut self, b: Rect) {
102 self.bounds = b;
103 }
104 fn children(&self) -> &[Box<dyn Widget>] {
105 &self.children
106 }
107 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> {
108 &mut self.children
109 }
110
111 fn margin(&self) -> Insets {
112 self.base.margin
113 }
114 fn widget_base(&self) -> Option<&WidgetBase> {
115 Some(&self.base)
116 }
117 fn widget_base_mut(&mut self) -> Option<&mut WidgetBase> {
118 Some(&mut self.base)
119 }
120 fn h_anchor(&self) -> HAnchor {
121 self.base.h_anchor
122 }
123 fn v_anchor(&self) -> VAnchor {
124 self.base.v_anchor
125 }
126 fn min_size(&self) -> Size {
127 self.base.min_size
128 }
129 fn max_size(&self) -> Size {
130 self.base.max_size
131 }
132
133 fn layout(&mut self, available: Size) -> Size {
134 let h = available.height.max(self.min_height);
135 self.bounds = Rect::new(0.0, 0.0, available.width, h);
136 Size::new(self.bounds.width, self.bounds.height)
137 }
138
139 fn paint(&mut self, ctx: &mut dyn DrawCtx) {
140 let v = ctx.visuals();
141 let w = self.bounds.width;
142 let h = self.bounds.height;
143
144 if self.fill_background {
145 ctx.set_fill_color(v.bg_color);
146 ctx.begin_path();
147 ctx.rounded_rect(0.0, 0.0, w, h, 4.0);
148 ctx.fill();
149 }
150
151 let src = self.source.borrow();
152 if let Some((pixels, iw, ih)) = src.as_ref() {
153 let iwf = *iw as f64;
154 let ihf = *ih as f64;
155 let scale = (w / iwf).min(h / ihf).max(0.0);
156 let dw = iwf * scale;
157 let dh = ihf * scale;
158 let dx = (w - dw) * 0.5;
159 let dy = (h - dh) * 0.5;
160 ctx.draw_image_rgba(pixels, *iw, *ih, dx, dy, dw, dh);
161
162 if self.outline {
163 ctx.set_stroke_color(v.text_color);
164 ctx.set_line_width(1.0);
165 ctx.begin_path();
166 ctx.rect(dx, dy, dw, dh);
167 ctx.stroke();
168 }
169 } else {
170 ctx.set_font(Arc::clone(&self.font));
171 ctx.set_font_size(13.0);
172 ctx.set_fill_color(v.text_dim);
173 if let Some(m) = ctx.measure_text(&self.placeholder) {
174 let tx = (w - m.width) * 0.5;
175 let ty = h * 0.5 - (m.ascent - m.descent) * 0.5;
176 ctx.fill_text(&self.placeholder, tx, ty);
177 }
178 }
179
180 let _ = Color::white();
182 }
183
184 fn on_event(&mut self, _: &Event) -> EventResult {
185 EventResult::Ignored
186 }
187}