Skip to main content

blockworx_tools/
add_port.rs

1use crate::render::draw_port_outline;
2use crate::theme::{Role, Style};
3use blockworx_geom::Rect;
4use blockworx_paint::{Canvas, Cursor, Event, Interaction};
5
6use crate::{
7    edit::create::stamped_port,
8    names::ToolName,
9    shape::pin::PinSide,
10    tool::{ToolTrait, Transition},
11    widget::drawing::Drawing,
12};
13
14/// Click-to-place a boundary port. A ghost outline previews the port under the
15/// cursor; a click stamps it at the default size and opens its name for
16/// editing, as a cell dropped off the cluster does ([`crate::stamp`]).
17pub struct AddPort;
18
19impl ToolTrait for AddPort {
20    fn name(&self) -> ToolName {
21        ToolName::AddPort
22    }
23
24    fn widget<C: Canvas>(
25        &mut self,
26        data: &mut Drawing,
27        interaction: &Interaction,
28        painter: &mut Style<'_, C>,
29    ) -> Option<Transition> {
30        crate::widget::display::widget(data, interaction, painter);
31        painter.set_cursor(Cursor::Crosshair);
32        // A locked level keeps its port interface frozen, so it previews none.
33        if let Some(Event::HoverAt(pos)) = interaction.event
34            && !data.current_locked()
35        {
36            preview_port(painter, stamped_port(pos));
37        }
38        crate::stamp::on_click(self.name(), interaction)
39    }
40}
41
42/// Draw the ghost port outline the placement will produce. The facing is
43/// cosmetic here — the real slot side is resolved when the port is created — so
44/// the preview always points East.
45fn preview_port<C: Canvas>(painter: &mut Style<'_, C>, bbox: Rect) {
46    draw_port_outline(
47        bbox,
48        PinSide::East,
49        Role::Transparent,
50        (1.0, Role::NewPinPreviewStroke),
51        painter,
52    );
53}