1use super::frame_size::FrameSizeWidget;
2use super::{
3 FixedSizeWidget, VariableSizeWidget, Widget, block::BlockWidget, number_box::NumberBoxWidget,
4 pixel_size::PixelSizeWidget, toggle::ToggleWidget,
5};
6use crate::{app::App, event::Event, model::config::Animation, region_ext::RegionExt};
7use orfail::{OrFail, Result};
8use pagurus::image::Canvas;
9use pagurus::spatial::{Position, Region, Size};
10
11const MARGIN_X: u32 = 8;
12const MARGIN_Y: u32 = 14;
13
14#[derive(Debug)]
15pub struct ConfigWidget {
16 region: Region,
17
18 frame_size: BlockWidget<FrameSizeWidget>,
20 pixel_size: BlockWidget<PixelSizeWidget>,
21
22 frame_preview: BlockWidget<ToggleWidget>,
24 frame_preview_scale: BlockWidget<NumberBoxWidget>,
25 silhouette: BlockWidget<ToggleWidget>,
26
27 layer_enable: BlockWidget<ToggleWidget>,
29 animation_enable: BlockWidget<ToggleWidget>,
30 fps: BlockWidget<NumberBoxWidget>,
31 apng: BlockWidget<ToggleWidget>,
32
33 gesture: BlockWidget<ToggleWidget>,
35}
36
37impl ConfigWidget {
38 pub fn new(app: &App) -> Self {
39 let frame_preview = app.models().config.frame_preview.get();
40 let frame_preview_scale = app.models().config.frame_preview_scale.get();
41 let silhouette_preview = app.models().config.silhouette_preview;
42 let layer = app.models().config.layer;
43 let animation = app.models().config.animation;
44 let apng = app.models().config.apng();
45 let gesture = app.models().config.gesture;
46 Self {
47 region: Region::default(),
48
49 frame_size: BlockWidget::new(
51 "FRAME SIZE".parse().expect("unreachable"),
52 FrameSizeWidget::new(app),
53 ),
54 pixel_size: BlockWidget::new(
55 "TOOL SIZE".parse().expect("unreachable"),
56 PixelSizeWidget::new(app),
57 ),
58
59 frame_preview: BlockWidget::new(
61 "PREVIEW".parse().expect("unreachable"),
62 ToggleWidget::new(frame_preview),
63 ),
64 frame_preview_scale: BlockWidget::new(
65 "PREVIEW SCALE".parse().expect("unreachable"),
66 NumberBoxWidget::new(1, frame_preview_scale as u32, 32),
67 ),
68 silhouette: BlockWidget::new(
69 "SILHOUETTE".parse().expect("unreachable"),
70 ToggleWidget::new(silhouette_preview),
71 ),
72
73 layer_enable: BlockWidget::new(
75 "LAYER".parse().expect("unreachable"),
76 ToggleWidget::new(layer.is_enabled()),
77 ),
78 animation_enable: BlockWidget::new(
79 "ANIMATION".parse().expect("unreachable"),
80 ToggleWidget::new(animation.is_enabled()),
81 ),
82 fps: BlockWidget::new(
83 "FPS".parse().expect("unreachable"),
84 NumberBoxWidget::new(
85 Animation::MIN_FPS as u32,
86 animation.fps() as u32,
87 Animation::MAX_FPS as u32,
88 ),
89 ),
90 apng: BlockWidget::new(
91 "APNG".parse().expect("unreachable"),
92 ToggleWidget::new(apng),
93 ),
94
95 gesture: BlockWidget::new(
97 "GESTURE".parse().expect("unreachable"),
98 ToggleWidget::new(gesture),
99 ),
100 }
101 }
102}
103
104impl Widget for ConfigWidget {
105 fn region(&self) -> Region {
106 self.region
107 }
108
109 fn render(&self, app: &App, canvas: &mut Canvas) {
110 self.frame_size.render_if_need(app, canvas);
112 self.pixel_size.render_if_need(app, canvas);
113
114 self.frame_preview.render_if_need(app, canvas);
116 self.frame_preview_scale.render_if_need(app, canvas);
117 self.silhouette.render_if_need(app, canvas);
118
119 self.layer_enable.render_if_need(app, canvas);
121 self.animation_enable.render_if_need(app, canvas);
122 self.fps.render_if_need(app, canvas);
123 self.apng.render_if_need(app, canvas);
124
125 self.gesture.render_if_need(app, canvas);
127 }
128
129 fn handle_event(&mut self, app: &mut App, event: &mut Event) -> Result<()> {
130 let frame = app.models().config.frame;
132 self.frame_size.handle_event(app, event).or_fail()?;
133 app.models_mut()
134 .config
135 .frame
136 .set_from_pixel_size(self.frame_size.body().value());
137 if frame != app.models().config.frame {
138 app.request_redraw(app.screen_size().to_region());
139 }
140
141 self.pixel_size.handle_event(app, event).or_fail()?;
142 app.models_mut()
143 .config
144 .minimum_pixel_size
145 .set(self.pixel_size.body().value());
146
147 self.frame_preview.handle_event(app, event).or_fail()?;
149 app.models_mut()
150 .config
151 .frame_preview
152 .set(self.frame_preview.body().is_on());
153 self.frame_preview_scale
154 .handle_event(app, event)
155 .or_fail()?;
156 app.models_mut()
157 .config
158 .frame_preview_scale
159 .set(self.frame_preview_scale.body().value() as u8)
160 .or_fail()?;
161 self.silhouette.handle_event(app, event).or_fail()?;
162 app.models_mut().config.silhouette_preview = self.silhouette.body().is_on();
163
164 let layer = app.models().config.layer;
166 self.layer_enable.handle_event(app, event).or_fail()?;
167 app.models_mut()
168 .config
169 .layer
170 .set_enabled(self.layer_enable.body().is_on());
171 if layer != app.models().config.layer {
172 app.request_redraw(app.screen_size().to_region());
173 }
174
175 let animation = app.models_mut().config.animation;
176 self.animation_enable.handle_event(app, event).or_fail()?;
177 app.models_mut()
178 .config
179 .animation
180 .set_enabled(self.animation_enable.body().is_on());
181
182 self.fps.handle_event(app, event).or_fail()?;
183 app.models_mut()
184 .config
185 .animation
186 .set_fps(self.fps.body().value() as u8);
187
188 self.apng.handle_event(app, event).or_fail()?;
189 app.models_mut().config.apng = Some(self.apng.body().is_on());
190
191 if animation != app.models_mut().config.animation {
192 app.request_redraw(app.screen_size().to_region());
193 }
194
195 self.gesture.handle_event(app, event).or_fail()?;
197 app.models_mut().config.gesture = self.gesture.body().is_on();
198
199 Ok(())
200 }
201
202 fn children(&mut self) -> Vec<&mut dyn Widget> {
203 vec![
204 &mut self.frame_size,
206 &mut self.pixel_size,
207 &mut self.frame_preview,
209 &mut self.frame_preview_scale,
210 &mut self.silhouette,
211 &mut self.layer_enable,
213 &mut self.animation_enable,
214 &mut self.fps,
215 &mut self.apng,
216 &mut self.gesture,
218 ]
219 }
220}
221
222impl FixedSizeWidget for ConfigWidget {
223 fn requiring_size(&self, app: &App) -> Size {
224 let row1 = self.frame_size.requiring_size(app);
226
227 let mut row2 = self.pixel_size.requiring_size(app);
229 row2.width += MARGIN_X + self.gesture.requiring_size(app).width;
230
231 let mut row3 = self.frame_preview.requiring_size(app);
233 row3.width += MARGIN_X + self.frame_preview_scale.requiring_size(app).width;
234 row3.width += MARGIN_X + self.silhouette.requiring_size(app).width;
235
236 let mut row4 = self.layer_enable.requiring_size(app);
238 row4.width += MARGIN_X + self.animation_enable.requiring_size(app).width;
239 row4.width += MARGIN_X + self.fps.requiring_size(app).width;
240 row4.width += MARGIN_X + self.apng.requiring_size(app).width;
241
242 Size::from_wh(
243 row1.width.max(row2.width).max(row3.width).max(row4.width),
244 row1.height + MARGIN_Y + row2.height + MARGIN_Y + row3.height + MARGIN_Y + row4.height,
245 ) + MARGIN_X * 2
246 }
247
248 fn set_position(&mut self, app: &App, position: Position) {
249 self.region = Region::new(position, self.requiring_size(app));
250
251 let mut region = self.region.without_margin(MARGIN_X);
252
253 let mut frame_size_region = region;
255 frame_size_region.size = self.frame_size.requiring_size(app);
256 self.frame_size.set_region(app, frame_size_region);
257 region.consume_y(frame_size_region.size.height + MARGIN_Y);
258
259 let mut pixel_size_region = region;
260 pixel_size_region.size = self.pixel_size.requiring_size(app);
261 self.pixel_size.set_region(app, pixel_size_region);
262
263 let mut gesture_region = region;
264 gesture_region.position.x = pixel_size_region.end().x + MARGIN_X as i32;
265 gesture_region.size = self.gesture.requiring_size(app);
266 self.gesture.set_region(app, gesture_region);
267
268 region.consume_y(gesture_region.size.height + MARGIN_Y);
269
270 let mut frame_preview_region = region;
272 frame_preview_region.size = self.frame_preview.requiring_size(app);
273 self.frame_preview.set_region(app, frame_preview_region);
274
275 let mut preview_scale_region = region;
276 preview_scale_region.position.x = frame_preview_region.end().x + MARGIN_X as i32;
277 preview_scale_region.size = self.frame_preview_scale.requiring_size(app);
278 self.frame_preview_scale
279 .set_region(app, preview_scale_region);
280
281 let mut silhouette_region = region;
282 silhouette_region.position.x = preview_scale_region.end().x + MARGIN_X as i32;
283 silhouette_region.size = self.silhouette.requiring_size(app);
284 self.silhouette.set_region(app, silhouette_region);
285
286 region.consume_y(frame_preview_region.size.height + MARGIN_Y);
287
288 let mut layer_enable_region = region;
290 layer_enable_region.size = self.layer_enable.requiring_size(app);
291 self.layer_enable.set_region(app, layer_enable_region);
292
293 let mut animation_enable_region = region;
294 animation_enable_region.position.x = layer_enable_region.end().x + MARGIN_X as i32;
295 animation_enable_region.size = self.animation_enable.requiring_size(app);
296 self.animation_enable
297 .set_region(app, animation_enable_region);
298
299 let mut fps_region = region;
300 fps_region.position.x = animation_enable_region.end().x + MARGIN_X as i32;
301 fps_region.size = self.fps.requiring_size(app);
302 self.fps.set_region(app, fps_region);
303
304 let mut apng_region = region;
305 apng_region.position.x = fps_region.end().x + MARGIN_X as i32;
306 apng_region.size = self.apng.requiring_size(app);
307 self.apng.set_region(app, apng_region);
308 }
309}