Comments: Squiggly underline tool (Highlight flyout, All tools, command)

The engine and agent tool already made squiggly underlines; the UI had no
way to. CommentTool::Squiggly joins Underline and Strikethrough in the
Highlight flyout and the Comment tool's Markup section, as the
comment.squiggly command, and existing squiggly comments edit as themselves.
Test: comments.rs::the_squiggly_tool_marks_selected_text. Parity
comment.squiggly: shipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-05 18:57:28 -04:00
co-authored by Claude Opus 5.5
parent ead70695c8
commit c02e1e91c2
5 changed files with 30 additions and 7 deletions
+1
View File
@@ -210,6 +210,7 @@ pub static TOOL_GROUPS: &[ToolGroup] = &[
item("Highlight text", "highlighter", "comment.highlight", Ready),
item("Underline", "underline", "comment.underline", Ready),
item("Strikethrough", "strikethrough", "comment.strikeout", Ready),
item("Squiggly underline", "spline", "comment.squiggly", Ready),
item("Text box", "type", "comment.freetext", Ready),
],
},
+1
View File
@@ -178,6 +178,7 @@ pub const COMMANDS: &[CommandSpec] = &[
c("comment.highlight", "Highlight text", None, None, Annotate, "highlighter"),
c("comment.underline", "Underline text", None, None, Annotate, "underline"),
c("comment.strikeout", "Strikethrough text", None, None, Annotate, "strikethrough"),
c("comment.squiggly", "Squiggly underline text", None, None, Annotate, "spline"),
c("comment.ink", "Draw freehand", None, None, Annotate, "pencil"),
c("comment.line", "Draw a line", None, None, Annotate, "minus"),
c("comment.arrow", "Draw an arrow", None, None, Annotate, "move-right"),
+10 -3
View File
@@ -30,6 +30,7 @@ pub enum CommentTool {
Highlight,
Underline,
StrikeOut,
Squiggly,
Ink,
Line,
Arrow,
@@ -48,7 +49,7 @@ pub enum CommentTool {
/// The quick-bar flyout groups, in Acrobat's order: Comment ▸, Highlight ▸, Draw ▸.
pub const GROUPS: [&[CommentTool]; 3] = [
&[CommentTool::Note, CommentTool::TextBox, CommentTool::Callout, CommentTool::Attach],
&[CommentTool::Highlight, CommentTool::Underline, CommentTool::StrikeOut, CommentTool::Caret, CommentTool::ReplaceText],
&[CommentTool::Highlight, CommentTool::Underline, CommentTool::StrikeOut, CommentTool::Squiggly, CommentTool::Caret, CommentTool::ReplaceText],
&[
CommentTool::Ink,
CommentTool::Line,
@@ -62,7 +63,7 @@ pub const GROUPS: [&[CommentTool]; 3] = [
],
];
pub const ALL: [CommentTool; 18] = [
pub const ALL: [CommentTool; 19] = [
CommentTool::Eraser,
CommentTool::ReplaceText,
CommentTool::Attach,
@@ -76,6 +77,7 @@ pub const ALL: [CommentTool; 18] = [
CommentTool::Highlight,
CommentTool::Underline,
CommentTool::StrikeOut,
CommentTool::Squiggly,
CommentTool::Ink,
CommentTool::Line,
CommentTool::Arrow,
@@ -91,6 +93,7 @@ impl CommentTool {
Self::Highlight => "comment.highlight",
Self::Underline => "comment.underline",
Self::StrikeOut => "comment.strikeout",
Self::Squiggly => "comment.squiggly",
Self::Ink => "comment.ink",
Self::Line => "comment.line",
Self::Arrow => "comment.arrow",
@@ -118,6 +121,7 @@ impl CommentTool {
Self::Highlight => "Highlight",
Self::Underline => "Underline",
Self::StrikeOut => "Strikethrough",
Self::Squiggly => "Squiggly underline",
Self::Ink => "Draw",
Self::Line => "Line",
Self::Arrow => "Arrow",
@@ -141,6 +145,7 @@ impl CommentTool {
Self::Highlight => "highlighter",
Self::Underline => "underline",
Self::StrikeOut => "strikethrough",
Self::Squiggly => "spline",
Self::Ink => "pencil",
Self::Line => "minus",
Self::Arrow => "move-right",
@@ -166,6 +171,7 @@ impl CommentTool {
Self::Highlight => Some(Markup::Highlight),
Self::Underline => Some(Markup::Underline),
Self::StrikeOut => Some(Markup::StrikeOut),
Self::Squiggly => Some(Markup::Squiggly),
_ => None,
}
}
@@ -190,7 +196,7 @@ impl CommentTool {
match self {
Self::Note => Shape::Note { at: [0.0; 2], icon: NoteIcon::Comment },
Self::TextBox => Shape::TextBox { rect: [0.0; 4], font_size: 12.0 },
Self::Highlight | Self::Underline | Self::StrikeOut => {
Self::Highlight | Self::Underline | Self::StrikeOut | Self::Squiggly => {
Shape::TextMarkup { kind: self.markup().unwrap_or(Markup::Highlight), quads: Vec::new() }
}
Self::Ink => Shape::Ink { strokes: Vec::new() },
@@ -286,6 +292,7 @@ pub fn tool_for(a: &Annotation) -> Option<CommentTool> {
("Highlight", _) => CommentTool::Highlight,
("Underline", _) => CommentTool::Underline,
("StrikeOut", _) => CommentTool::StrikeOut,
("Squiggly", _) => CommentTool::Squiggly,
("Ink", _) => CommentTool::Ink,
("Line", _) => CommentTool::Line,
("Square", _) => CommentTool::Rectangle,
+14
View File
@@ -554,3 +554,17 @@ fn hovering_a_comment_shows_its_author_and_text() {
h.get_by_label_contains("Check this figure");
h.get_by_label_contains("Ada");
}
#[test]
fn the_squiggly_tool_marks_selected_text() {
let mut h = harness(|_| {});
h.state_mut().views[0].select_text(0, 4, 8);
assert!(h.state_mut().execute("comment.squiggly"));
h.run_steps(2);
let c = comments(&h);
assert_eq!(c.len(), 1, "{c:?}");
assert_eq!((c[0].subtype.as_str(), c[0].quads.len()), ("Squiggly", 1));
// It sits with the other text markup in the Highlight ▸ flyout, and edits as itself.
assert!(printcraft_ui_egui::comments::GROUPS[1].contains(&printcraft_ui_egui::comments::CommentTool::Squiggly));
assert_eq!(printcraft_ui_egui::comments::tool_for(&c[0]), Some(printcraft_ui_egui::comments::CommentTool::Squiggly));
}
+4 -4
View File
@@ -3515,11 +3515,11 @@ title = "Squiggly underline"
area = "E"
tier = "P2"
milestone = "M5"
status = "partial"
commands = []
status = "shipped"
commands = ["comment.squiggly"]
tools = ["comment_add"]
evidence = ["crates/annot/src/tests.rs::every_tool_creates_a_drawable_comment"]
notes = "engine and agent tool; no toolbar entry yet"
evidence = ["crates/annot/src/tests.rs::every_tool_creates_a_drawable_comment", "crates/ui-egui/tests/comments.rs::the_squiggly_tool_marks_selected_text"]
notes = "Highlight ▸ Squiggly underline (with Underline and Strikethrough), the agent tool and the engine"
[[feature]]
id = "comment.replace-text"