Skip to main content

egui_cable/
cable_control.rs

1use egui::{Order, Pos2, Widget};
2
3use crate::{cable::CableId, custom_widget::CustomWidget, state::State};
4
5#[derive(Debug)]
6pub struct CableControl {
7    pub(crate) id: CableId,
8    pub(crate) pos: Pos2,
9    pub(crate) widget: CustomWidget,
10}
11
12impl Widget for CableControl {
13    fn ui(self, ui: &mut egui::Ui) -> egui::Response {
14        let mut state = State::get_cloned(ui);
15        let size = state.cable_control_size(&self.id);
16        egui::Area::new(egui::Id::new((self.id, "cable_control")))
17            // must be top-left of the widget
18            .current_pos(if let Some(size) = size {
19                self.pos - size / 2.0
20            } else {
21                self.pos
22            })
23            .order(Order::Foreground)
24            .show(ui.ctx(), |ui| {
25                if size.is_none() {
26                    // hide cable control for first rendering.
27                    ui.set_invisible();
28                }
29                // should be displayed on cable bezier
30                ui.ctx().move_to_top(ui.layer_id());
31
32                // cable control has click sense for make cable active, and drag sense for bezier deforming.
33                let response = self.widget.ui(ui);
34
35                // update cable control size for calculate the next position of this area
36                state.update_cable_control_size(self.id, response.rect.size());
37                state.store_to(ui);
38
39                response
40            })
41            .inner
42    }
43}