Type: selected overflowing type shows its red out port with any tool (#2323)

The overflow marker was drawn by the Type tools only, so with the Selection tool a text box smaller than its text showed no sign that text was hidden. Session::overlays now adds the marker of every selected area type and type on a path that overflows, unless a Type tool is active (it draws its own). The verdict is cached per object and font generation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
vangel76
2026-10-17 13:06:51 +07:00
committed by bflatastic
co-authored by Claude Opus 5.5
parent 5fd7fd4312
commit d39e02b3fe
5 changed files with 96 additions and 16 deletions
+3
View File
@@ -1198,6 +1198,8 @@ pub struct Session {
pub(crate) plane_widget_press: bool,
/// A guide being dragged out of a ruler ([`Session::ruler_guide`]).
pub(crate) ruler_guide: Option<vectorcraft_tools::rulerguide::NewGuide>,
/// Which selected type overflows its frame, for the markers every tool but the Type tools shows.
pub(crate) overflow_marks: vectorcraft_tools::text::OverflowMarks,
/// The last search for the files of missing fonts (`text.findFontFiles`), until another
/// starts; dropping it stops it.
pub(crate) font_search: Option<cmd::fontfiles::FontSearch>,
@@ -1268,6 +1270,7 @@ impl Session {
liquify_stroke: None,
plane_widget_press: false,
ruler_guide: None,
overflow_marks: Default::default(),
font_search: None,
link_search: None,
search_rules: None,
+20
View File
@@ -737,3 +737,23 @@ fn a_colour_previewed_while_typing_keeps_the_typing() {
s.tool_text("d", v).unwrap();
assert_eq!(obj(&s, id).plain_text(), "abcd");
}
/// The red out port of selected overflowing area type is drawn with the Selection tool too, and
/// not twice with the Type tool, which draws it itself (#2323).
#[test]
fn overflow_marker_shows_with_the_selection_tool() {
let mut s = session();
let v = ViewInfo::default();
let long = "Words that fill more than the frame holds. ".repeat(20);
let r = s.execute("text.create", &json!({"x": 50, "y": 50, "text": long, "size": 20, "area": {"width": 100, "height": 40}})).unwrap();
let id = NodeId(r["id"].as_u64().unwrap());
s.execute("select.set", &json!({"ids": [id.0]})).unwrap();
s.select_tool("selection", v).unwrap();
let red = |s: &mut Session| s.overlays(v).iter().filter(|o| matches!(o, vectorcraft_tools::Overlay::Path { color: [230, 30, 30], .. })).count();
assert_eq!(red(&mut s), 1, "the out port");
s.select_tool("type", v).unwrap();
assert_eq!(red(&mut s), 1, "the Type tool's own, not a second one");
s.execute("select.set", &json!({"ids": []})).unwrap();
s.select_tool("selection", v).unwrap();
assert_eq!(red(&mut s), 0, "nothing selected");
}
+6
View File
@@ -399,6 +399,12 @@ impl Session {
pub fn overlays(&mut self, view: ViewInfo) -> Vec<Overlay> {
let mut v = self.with_tool_cx(view, |t, cx| t.overlays(cx));
// The Type tools draw the overflow markers of selected type themselves.
if !matches!(self.tool.id(), "type" | "areaType" | "typeOnPath" | "verticalType" | "verticalAreaType" | "verticalTypeOnPath") {
let mut marks = std::mem::take(&mut self.overflow_marks);
v.extend(self.with_tool_cx(view, |_, cx| vectorcraft_tools::text::overflow_markers(&mut marks, cx)));
self.overflow_marks = marks;
}
if let Some(g) = self.ruler_guide.take() {
v.extend(self.with_tool_cx(view, |_, cx| g.overlays(cx)));
self.ruler_guide = Some(g);