1use crate::{app::App, event::Event};
2use orfail::{OrFail, Result};
3use pagurus::image::Canvas;
4use pagurus::spatial::{Position, Region, Size};
5
6pub mod block;
7pub mod bottom_bar;
8pub mod button;
9pub mod color_config;
10pub mod color_palette;
11pub mod color_selector;
12pub mod config;
13pub mod frame_size;
14pub mod hsv_selector;
15pub mod manipulate;
16pub mod manipulate_tool;
17pub mod move_camera;
18pub mod move_frame;
19pub mod number_box;
20pub mod pixel_canvas;
21pub mod pixel_size;
22pub mod preview;
23pub mod rgb_selector;
24pub mod save_load;
25pub mod select_box;
26pub mod side_bar;
27pub mod size_box;
28pub mod slider;
29pub mod toggle;
30pub mod tool_box;
31pub mod undo_redo;
32pub mod zoom;
33
34pub trait Widget: std::fmt::Debug + 'static {
35 fn region(&self) -> Region;
36 fn render(&self, app: &App, canvas: &mut Canvas);
37 fn handle_event(&mut self, app: &mut App, event: &mut Event) -> Result<()>;
38 fn children(&mut self) -> Vec<&mut dyn Widget>;
39
40 fn handle_event_before(&mut self, app: &mut App) -> Result<()> {
41 for child in self.children() {
42 child.handle_event_before(app).or_fail()?;
43 }
44 Ok(())
45 }
46
47 fn handle_event_after(&mut self, app: &mut App) -> Result<()> {
48 for child in self.children() {
49 child.handle_event_after(app).or_fail()?;
50 }
51 Ok(())
52 }
53
54 fn render_if_need(&self, app: &App, canvas: &mut Canvas) {
55 if !self
56 .region()
57 .intersection(canvas.drawing_region())
58 .is_empty()
59 {
60 self.render(app, canvas);
61 }
62 }
63}
64
65pub trait FixedSizeWidget: Widget {
66 fn requiring_size(&self, app: &App) -> Size;
67 fn set_position(&mut self, app: &App, position: Position);
68}
69
70pub trait VariableSizeWidget: Widget {
71 fn set_region(&mut self, app: &App, region: Region);
72}