blockworx_editor/shape/
text_box.rs1use crate::grid::{px_point, snap_rect};
2use crate::theme::{Role, Style};
3use blockworx_geom::{Pos2, Rect, Vec2};
4use blockworx_paint::Renderer;
5
6use blockworx_doc::{block_model::Text, geometry::GridSize};
7
8use crate::{
9 edit::lower::accent_from_role,
10 render::{
11 draw_selection_frame,
12 text_box::{BoxWidth, box_rect, draw_anchor, draw_boundary, draw_text, measure_box_size},
13 },
14 shape::{BaseShape, block::resize_rect},
15 state::RenderMode,
16};
17
18#[derive(Clone, Copy)]
24pub struct TextShape<'a> {
25 pub text: &'a Text,
26 pub extent: Option<GridSize>,
27}
28
29impl TextShape<'_> {
30 fn accent_role(&self) -> Role {
35 crate::theme::accent_role(accent_from_role(self.text.role)).unwrap_or(Role::TextBoxStroke)
36 }
37
38 fn anchor(&self) -> Pos2 {
39 px_point(self.text.pos)
40 }
41
42 fn body(&self) -> &str {
43 &self.text.text
44 }
45
46 fn width(&self) -> BoxWidth {
47 BoxWidth::of(self.text)
48 }
49}
50
51impl BaseShape for TextShape<'_> {
52 fn gui_rect(&self) -> Rect {
53 box_rect(self.anchor(), self.extent, self.body(), self.width())
54 }
55
56 fn constrain_resize_delta(&self, mut delta: Vec2) -> Vec2 {
59 delta.y = 0.0;
60 delta
61 }
62
63 fn resizable(&self) -> bool {
64 true
65 }
66
67 fn render_ng<R: Renderer>(&self, mode: RenderMode, painter: &mut Style<'_, R>) {
68 let anchor = self.anchor();
69 let (text, accent, width) = (self.body(), self.accent_role(), self.width());
70 let rect = self.gui_rect();
71 match mode {
73 RenderMode::Hidden => {}
75 RenderMode::Moving { delta } => {
76 let shifted = anchor + delta;
77 draw_boundary(rect.translate(delta), accent, painter);
78 draw_text(shifted, text, width, painter);
79 draw_anchor(shifted, painter);
80 }
81 RenderMode::Selected { .. } => {
82 draw_boundary(rect, accent, painter);
83 draw_text(anchor, text, width, painter);
84 draw_selection_frame(rect, None, painter);
85 }
86 RenderMode::Resizing { mode, delta } => {
87 let resized = snap_rect(resize_rect(&rect, mode, delta));
88 let width = BoxWidth::Cells(BoxWidth::spanning(resized));
89 let size = Some(measure_box_size(painter, text, width));
90 let preview = box_rect(resized.min, size, text, width);
91 draw_boundary(preview, accent, painter);
92 draw_text(resized.min, text, width, painter);
93 draw_selection_frame(preview, Some(mode), painter);
94 }
95 _ => {
98 draw_boundary(rect, accent, painter);
99 draw_text(anchor, text, width, painter);
100 }
101 }
102 }
103}