Skip to main content

blockworx/tools/
new_comment.rs

1use crate::theme::Style;
2use egui::Pos2;
3
4use crate::{
5    canvas::{Event, Interaction, painter::Painter},
6    grid::GRID_SIZE,
7    theme::Role,
8    tools::{
9        RenameTitle,
10        names::ToolName,
11        tool::{Action, ToolTrait},
12    },
13    units::WorldPx,
14    widget::drawing::Drawing,
15};
16
17/// Drag-to-create a boundary [`Comment`](blockworx_doc::block_model::Comment):
18/// the same gesture as [`NewBlock`](crate::tools::NewBlock), previewing the
19/// outline as it is dragged and committing it on release if it is larger than
20/// one grid cell.
21pub enum NewComment {
22    Idle,
23    Dragging { start: Pos2 },
24}
25
26impl ToolTrait for NewComment {
27    fn name(&self) -> ToolName {
28        ToolName::NewComment
29    }
30    fn widget(
31        &mut self,
32        data: &mut Drawing,
33        interaction: &Interaction,
34        painter: &mut Style<'_, Painter>,
35    ) -> Option<Action> {
36        crate::widget::display::widget(data, interaction, painter);
37        painter.set_cursor(egui::CursorIcon::Crosshair);
38        match self {
39            NewComment::Idle => {
40                if let Some(Event::DragStarted { pos }) = interaction.event {
41                    *self = NewComment::Dragging { start: pos };
42                }
43            }
44            NewComment::Dragging { start } => {
45                if let Some(Event::Dragging { pos, .. }) = interaction.event {
46                    let rect = egui::Rect::from_two_pos(*start, pos);
47                    painter.rect(
48                        rect,
49                        WorldPx::ZERO,
50                        Role::Transparent,
51                        (1.0, Role::CommentStroke),
52                    );
53                } else if let Some(Event::DragStopped { pos }) = interaction.event {
54                    let start_pos = *start;
55                    let candidate = egui::Rect::from_two_pos(start_pos, pos);
56                    *self = NewComment::Idle;
57                    if candidate.width() > GRID_SIZE && candidate.height() > GRID_SIZE {
58                        let shape = data.add_comment(start_pos, pos);
59                        // Drop straight into editing the new comment's text.
60                        return Some(RenameTitle::action(data, shape));
61                    }
62                }
63            }
64        }
65        None
66    }
67}