blockworx_tools/
move_title.rs1use crate::theme::Style;
2use blockworx_geom::{Align, Vec2};
3use blockworx_paint::{Canvas, Cursor, Event, Interaction};
4
5use crate::{
6 grid::round_to_grid,
7 names::ToolName,
8 render::{clamp_label_offset, label_side_for_y},
9 resize_block::ResizeBlock,
10 shape::ShapeId,
11 state::RenderMode,
12 tool::{ToolTrait, Transition},
13 widget::{DrawingPasses, drawing::Drawing},
14};
15
16pub enum MoveTitle {
17 Idle,
18 Dragging { shape: ShapeId, delta_pos: Vec2 },
19}
20
21impl ToolTrait for MoveTitle {
22 fn name(&self) -> ToolName {
23 ToolName::MoveTitle
24 }
25
26 fn widget<C: Canvas>(
27 &mut self,
28 data: &mut Drawing,
29 interaction: &Interaction,
30 painter: &mut Style<'_, C>,
31 ) -> Option<Transition> {
32 match self {
33 MoveTitle::Idle => {
34 crate::widget::display::widget(data, interaction, painter);
35 if let Some(Event::HoverAt(hover_pos)) = interaction.event {
36 if data.title_anchor_at_pos(hover_pos).is_some() {
37 painter.set_cursor(Cursor::PointingHand);
38 }
39 } else if let Some(Event::DragStarted { pos }) = interaction.event
40 && let Some(shape) = data.title_anchor_at_pos(pos)
41 {
42 *self = MoveTitle::Dragging {
43 shape,
44 delta_pos: Vec2::ZERO,
45 };
46 }
47 }
48 MoveTitle::Dragging { shape, delta_pos } => {
49 if let Some(Event::Dragging { delta, .. }) = interaction.event {
50 *delta_pos += delta;
51 }
52 if let Some(Event::DragStopped { .. }) = interaction.event {
53 let placement = data.shape(*shape).and_then(|shape_ref| {
54 let title = shape_ref.title()?;
55 let bbox = shape_ref.gui_rect();
56 let proposed = title.offset + round_to_grid(delta_pos.x);
57 let text_w = painter.text_size(title.name, &painter.theme().title_font).x;
60 Some(crate::widget::drawing::LabelPlacement {
61 offset: clamp_label_offset(bbox, text_w, proposed, Align::Center),
62 side: shape_ref
63 .title_anchor()
64 .map(|anchor| label_side_for_y(bbox, anchor.y + delta_pos.y)),
65 })
66 });
67 if let Some(placement) = placement {
68 data.place_title(*shape, placement);
69 }
70 crate::widget::display::widget(data, interaction, painter);
74 return Some(Transition::SwitchTool(
76 ResizeBlock::Selected { shape: *shape }.into(),
77 ));
78 }
79 let dragged = *shape;
80 let delta = *delta_pos;
81 DrawingPasses::new(data)
82 .shape_mode(move |id| {
83 if id == dragged {
84 RenderMode::TitleDragged { delta }
85 } else {
86 RenderMode::Normal
87 }
88 })
89 .draw(painter);
90 }
91 }
92 None
93 }
94}