egui_cable/
default_plug.rs

1use egui::{Rect, Response, Sense, Ui, Widget};
2use epaint::Stroke;
3
4use crate::{
5    plug_params::PlugParams,
6    utils::{widget_visuals, SIZE},
7};
8
9#[derive(Debug)]
10pub struct DefaultPlug;
11
12impl Widget for DefaultPlug {
13    fn ui(self, ui: &mut Ui) -> Response {
14        let params = PlugParams::get(ui);
15        let vector = params.vector;
16        let active = params.active;
17        let plugged = params.plugged;
18        let locked = params.locked;
19
20        let (rect, response) = ui.allocate_exact_size(
21            SIZE,
22            if (active || !plugged) && !locked {
23                Sense::drag()
24            } else {
25                // minimum sense to make not interactive
26                Sense::hover()
27            },
28        );
29
30        // handle drag
31        let pos = rect.left_top() + response.drag_delta();
32        let size = rect.size();
33        // this should not be response.rect.center() for painting it correctly while dragging
34        let center_pos = pos + size / 2.0;
35
36        if ui.is_rect_visible(Rect::from_center_size(center_pos, size)) {
37            let visuals = if locked {
38                ui.visuals().widgets.noninteractive
39            } else {
40                widget_visuals(ui, &response)
41            };
42            if response.dragged() {
43                if let Some(vector) = vector {
44                    ui.painter().arrow(
45                        center_pos,
46                        vector * size.x / 2.0 * 1.5,
47                        Stroke::new(2.0, visuals.fg_stroke.color),
48                    );
49                }
50            }
51            ui.painter().add(epaint::CircleShape {
52                center: center_pos,
53                radius: size.x / 2.0 * if active { 0.7 } else { 0.2 },
54                fill: visuals.fg_stroke.color,
55                stroke: visuals.fg_stroke,
56            });
57        }
58
59        response
60    }
61}