Skip to main content

blockworx/tools/
add_text.rs

1use crate::theme::{Role, Style};
2use blockworx_geom::{Pos2, Rect, WorldPx};
3use blockworx_paint::{Canvas, Cursor, Event, Interaction};
4
5use crate::{
6    tools::{
7        EditTextBox,
8        names::ToolName,
9        tool::{Action, ToolTrait},
10    },
11    widget::drawing::Drawing,
12};
13
14/// Drag-to-place a text box. The pointer shows an I-beam over the canvas; a
15/// drag outlines where the text will begin and, on release, the box is
16/// dropped at that outline's top-left with its editor already open.
17///
18/// A box has no stored extent — it is as big as what is typed into it — so
19/// the drag names a corner rather than a size. Creating on the drag is what
20/// makes this creator like the others (playbook R40): a bare click creates
21/// nothing, and the default box lives on the drag-out path
22/// ([`crate::tools::stamp`]).
23pub enum AddText {
24    Idle,
25    Dragging { start: Pos2 },
26}
27
28impl ToolTrait for AddText {
29    fn name(&self) -> ToolName {
30        ToolName::AddText
31    }
32
33    fn widget<C: Canvas>(
34        &mut self,
35        data: &mut Drawing,
36        interaction: &Interaction,
37        painter: &mut Style<'_, C>,
38    ) -> Option<Action> {
39        crate::widget::display::widget(data, interaction, painter);
40        painter.set_cursor(Cursor::Text);
41        match self {
42            AddText::Idle => {
43                if let Some(Event::DragStarted { pos }) = interaction.event {
44                    *self = AddText::Dragging { start: pos };
45                }
46            }
47            AddText::Dragging { start } => {
48                let start = *start;
49                if let Some(Event::Dragging { pos, .. }) = interaction.event {
50                    painter.rect(
51                        Rect::from_two_pos(start, pos),
52                        WorldPx::ZERO,
53                        Role::Transparent,
54                        (1.0, Role::NewBlockPreviewStroke),
55                    );
56                } else if let Some(Event::DragStopped { pos }) = interaction.event {
57                    *self = AddText::Idle;
58                    let id = data.add_text_box(Rect::from_two_pos(start, pos).min);
59                    return Some(EditTextBox::action(data, id));
60                }
61            }
62        }
63        None
64    }
65}