use eframe::egui::{self, Align2, Color32, Stroke, Ui, Vec2};
use egui_map::map::Map;
use egui_map::map::objects::{
MapPoint, MapSegment, MarkerContext, NodeContext, NodeTemplate, NotificationContext,
SelectionContext, VisibilitySetting,
};
use std::rc::Rc;
use std::time::Instant;
struct SvgNodes;
impl NodeTemplate for SvgNodes {
fn node_ui(&self, ui: &mut Ui, ctx: NodeContext) {
let size = 24.0 * ctx.zoom;
let source = match ctx.point.get_id() {
1 => egui::include_image!("router_pool.svg"),
2 => egui::include_image!("switch_pool.svg"),
_ => egui::include_image!("server_mango.svg"),
};
let rect = egui::Rect::from_center_size(ctx.position, Vec2::splat(size));
ui.put(
rect,
egui::Image::new(source).fit_to_exact_size(Vec2::splat(size)),
);
ui.painter().text(
ctx.position + Vec2::new(0.0, size / 2.0),
Align2::CENTER_TOP,
ctx.point.get_name(),
egui::FontId::proportional(11.0 * ctx.zoom),
ui.visuals().text_color(),
);
}
fn selection_ui(&self, ui: &mut Ui, ctx: SelectionContext) {
ui.painter().circle_stroke(
ctx.position,
16.0 * ctx.zoom,
Stroke::new(2.0 * ctx.zoom, ctx.color),
);
}
fn notification_ui(&self, ui: &mut Ui, ctx: NotificationContext) -> bool {
let secs = ctx.initial_time.elapsed().as_secs_f32();
let alpha = (1.0 - secs / 2.0).clamp(0.0, 1.0);
let fading = Color32::from_rgba_unmultiplied(
ctx.color.r(),
ctx.color.g(),
ctx.color.b(),
(255.0 * alpha) as u8,
);
ui.painter().circle_stroke(
ctx.position,
(16.0 + 30.0 * secs) * ctx.zoom,
Stroke::new(3.0 * ctx.zoom, fading),
);
ui.ctx().request_repaint(); secs < 2.0 }
fn marker_ui(&self, ui: &mut Ui, ctx: MarkerContext) {
ui.painter().circle_stroke(
ctx.position,
20.0 * ctx.zoom,
Stroke::new(2.0 * ctx.zoom, Color32::LIGHT_GREEN),
);
}
}
fn main() -> eframe::Result<()> {
let mut points = Vec::new();
for (id, name, x, y) in [
(1, "router-01", 0.0, 0.0),
(2, "switch-01", 100.0, 50.0),
(3, "Zeus", 100.0, 130.0),
] {
let mut point = MapPoint::new(id, [x, y]);
point.set_name(name.to_string());
match point.get_id() {
1 => point.connections.push((0, 1)),
2 => {
point.connections.push((0, 1));
point.connections.push((1, 2));
}
_ => point.connections.push((1, 2)),
}
points.push(point);
}
let mut vec_segmnents = Vec::new();
let ids = vec![[1, 2], [2, 3]];
for (cont, id) in ids.into_iter().enumerate() {
let point1 = points.get(id[0]).unwrap();
let point2 = points.get(id[1]).unwrap();
let line = MapSegment::new((cont, cont + 1), point1.coords, point2.coords);
vec_segmnents.push(line);
}
let mut map = Map::new();
map.add_points(points);
map.add_lines(vec_segmnents);
map.set_node_template(Rc::new(SvgNodes));
map.settings.node_text_visibility = VisibilitySetting::Hover;
map.update_marker(0, 3);
let mut last_pulse = Instant::now() - std::time::Duration::from_secs(3);
let mut loaders_installed = false;
eframe::run_ui_native(
"egui-map: svg template",
eframe::NativeOptions::default(),
move |ui, _frame| {
if !loaders_installed {
egui_extras::install_image_loaders(ui.ctx());
loaders_installed = true;
}
if last_pulse.elapsed().as_secs() >= 3 {
if let Some(node) = map.node(2) {
node.pulse(Instant::now());
}
last_pulse = Instant::now();
}
ui.add(&mut map);
},
)
}