1mod always_active_zoom;
2mod attributes;
3mod bbox;
4mod brush;
5mod core;
6mod instance_anno_shared;
7mod rot90;
8mod wand;
9mod zoom;
10use crate::{
11 history::{History, Record},
12 tools_data::{AttributesToolData, BboxToolData, BrushToolData, VisibleInactiveToolsState},
13 world::World,
14};
15
16pub use self::core::Manipulate;
17use crate::tools_data::Rot90ToolData;
18pub use always_active_zoom::AlwaysActiveZoom;
19pub use attributes::Attributes;
20pub use bbox::Bbox;
21pub use brush::Brush;
22pub use rot90::Rot90;
23use std::fmt::Debug;
24use tracing::info;
25pub use zoom::Zoom;
26pub const BBOX_NAME: &str = bbox::ACTOR_NAME;
27pub const BRUSH_NAME: &str = brush::ACTOR_NAME;
28pub const ZOOM_NAME: &str = "Zoom";
29pub const ROT90_NAME: &str = rot90::ACTOR_NAME;
30pub const ALWAYS_ACTIVE_ZOOM: &str = "AlwaysActiveZoom";
31pub const ATTRIBUTES_NAME: &str = "Attributes";
32
33macro_rules! make_tools {
34($(($tool:ident, $label:expr, $name:expr, $active:expr, $always_active:expr, $data_default:expr, $visible_inactive_names:expr)),+) => {
35 #[must_use] pub fn get_visible_inactive_names(name: &str) -> [&str; 1]{
36 $(if name == $name {
37 return $visible_inactive_names;
38 })+
39 else {
40 panic!("unknown tool {name}");
41 }
42
43 }
44 #[derive(Clone, Debug)]
45 pub enum ToolWrapper {
46 $($tool($tool)),+
47 }
48 #[must_use]
49 pub fn make_tool_vec() -> Vec<ToolState> {
50 vec![$(
51 ToolState {
52 tool_wrapper: ToolWrapper::$tool($tool::new()),
53 is_active: $active,
54 is_always_active: $always_active,
55 name: $name,
56 button_label: $label
57 }),+]
58 }
59 #[must_use] pub fn add_tools_initial_data(mut tdm: $crate::ToolsDataMap) -> $crate::ToolsDataMap {
60
61 $(if tdm.get_mut($name).is_none() {
62 tdm.insert(
63 $name.to_string(),
64 $crate::tools_data::ToolsData::new(
65 $crate::tools_data::ToolSpecifics::$tool($data_default), VisibleInactiveToolsState::default()
66 ),
67 );
68 })+
69 tdm
70 }
71 };
72}
73make_tools!(
74 (
75 Rot90,
76 "🔄",
77 ROT90_NAME,
78 true,
79 true,
80 Rot90ToolData::default(),
81 [""]
82 ),
83 (
84 Brush,
85 "✏",
86 BRUSH_NAME,
87 false,
88 false,
89 BrushToolData::default(),
90 [BBOX_NAME]
91 ),
92 (
93 Bbox,
94 "⬜",
95 BBOX_NAME,
96 false,
97 false,
98 BboxToolData::default(),
99 [BRUSH_NAME]
100 ),
101 (
102 Attributes,
103 "A",
104 ATTRIBUTES_NAME,
105 false,
106 false,
107 AttributesToolData::default(),
108 [""]
109 ),
110 (Zoom, "🔍", ZOOM_NAME, false, false, (), [""]),
111 (
112 AlwaysActiveZoom,
113 "AA🔍",
114 ALWAYS_ACTIVE_ZOOM,
115 true,
116 true,
117 (),
118 [""]
119 )
120);
121
122#[macro_export]
123macro_rules! apply_tool_method_mut {
124 ($tool_state:expr, $f:ident, $($args:expr),*) => {
125 match &mut $tool_state.tool_wrapper {
126 ToolWrapper::Rot90(z) => z.$f($($args,)*),
127 ToolWrapper::Brush(z) => z.$f($($args,)*),
128 ToolWrapper::Bbox(z) => z.$f($($args,)*),
129 ToolWrapper::Zoom(z) => z.$f($($args,)*),
130 ToolWrapper::AlwaysActiveZoom(z) => z.$f($($args,)*),
131 ToolWrapper::Attributes(z) => z.$f($($args,)*),
132 }
133 };
134}
135
136pub struct ToolState {
137 pub tool_wrapper: ToolWrapper,
138 is_active: bool,
139 is_always_active: bool, pub name: &'static str,
141 pub button_label: &'static str,
142}
143impl ToolState {
144 pub fn activate(&mut self, mut world: World, mut history: History) -> (World, History) {
145 info!("activate {}", self.name);
146 self.is_active = true;
147 world = apply_tool_method_mut!(self, on_activate, world);
148 if !self.is_always_active() {
149 history.push(Record::new(world.clone(), self.name));
150 }
151 (world, history)
152 }
153 pub fn file_changed(&mut self, mut world: World, mut history: History) -> (World, History) {
154 (world, history) = apply_tool_method_mut!(self, on_filechange, world, history);
155 (world, history)
156 }
157 pub fn deactivate(&mut self, mut world: World) -> World {
158 if self.is_active {
159 info!("deactivate {}", self.name);
160 world = apply_tool_method_mut!(self, on_deactivate, world);
161 }
162 if !self.is_always_active {
163 self.is_active = false;
164 }
165 world
166 }
167 #[must_use]
168 pub fn is_active(&self) -> bool {
169 self.is_active
170 }
171 #[must_use]
172 pub fn is_always_active(&self) -> bool {
173 self.is_always_active
174 }
175}