egui_map_view/layers/area/
layer.rs1use crate::layers::{default_opacity, Layer};
2use crate::projection::MapProjection;
3use egui::{Color32, Painter, Response};
4use serde::{Deserialize, Serialize};
5use std::any::Any;
6
7use super::types::{Area, AreaMode, DraggedObject};
8
9#[derive(Clone, Serialize, Deserialize)]
11#[serde(default)]
12pub struct AreaLayer {
13 pub(crate) areas: Vec<Area>,
14
15 #[serde(skip)]
16 pub node_radius: f32,
18
19 #[serde(skip)]
20 pub node_fill: Color32,
22
23 #[serde(skip)]
24 pub mode: AreaMode,
26
27 #[serde(skip)]
28 pub(crate) dragged_object: Option<DraggedObject>,
29
30 #[serde(skip)]
31 pub(crate) hovered_object: Option<DraggedObject>,
32
33 #[serde(default = "default_opacity")]
35 pub opacity: f32,
36
37 #[serde(skip)]
38 pub selected_area: Option<usize>,
40}
41
42impl Default for AreaLayer {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
48impl AreaLayer {
49 #[must_use]
51 pub fn new() -> Self {
52 Self {
53 areas: Vec::new(),
54 node_radius: 5.0,
55 node_fill: Color32::from_rgb(0, 128, 0),
56 mode: AreaMode::default(),
57 dragged_object: None,
58 hovered_object: None,
59 opacity: 1.0,
60 selected_area: None,
61 }
62 }
63
64 pub fn add_area(&mut self, area: Area) {
66 self.areas.push(area);
67 }
68
69 #[must_use]
71 pub fn areas(&self) -> &Vec<Area> {
72 &self.areas
73 }
74
75 pub fn areas_mut(&mut self) -> &mut Vec<Area> {
77 &mut self.areas
78 }
79}
80
81impl Layer for AreaLayer {
82 fn as_any(&self) -> &dyn Any {
83 self
84 }
85
86 fn as_any_mut(&mut self) -> &mut dyn Any {
87 self
88 }
89
90 fn opacity(&self) -> f32 {
91 self.opacity
92 }
93
94 fn set_opacity(&mut self, opacity: f32) {
95 self.opacity = opacity;
96 }
97
98 fn handle_input(&mut self, response: &Response, projection: &MapProjection) -> bool {
99 match self.mode {
100 AreaMode::Disabled => {
101 self.hovered_object = None;
102 false
103 }
104 AreaMode::Modify => self.handle_modify_input(response, projection, None),
105 AreaMode::ModifySelected => {
106 if response.clicked()
107 && let Some(pointer_pos) = response.interact_pointer_pos()
108 {
109 let clicked_area_idx =
111 self.areas.iter().enumerate().rev().find_map(|(idx, area)| {
112 let contains_fill = area.contains(pointer_pos, projection);
113 let over_handle = self.find_object_at(pointer_pos, projection, Some(idx)).is_some();
114 let over_segment = self.find_line_segment_at(pointer_pos, projection, Some(idx)).is_some();
115
116 if contains_fill || over_handle || over_segment {
117 Some(idx)
118 } else {
119 None
120 }
121 });
122
123 if clicked_area_idx != self.selected_area {
124 self.selected_area = clicked_area_idx;
125 return true;
126 }
127 }
128
129 if let Some(selected_idx) = self.selected_area {
130 self.handle_modify_input(response, projection, Some(selected_idx))
131 } else {
132 false
133 }
134 }
135 }
136 }
137
138 fn draw(&self, painter: &Painter, projection: &MapProjection) {
139 self.draw_layer(painter, projection);
140 }
141}