Improve Text tool resize/drag behavior (#2428)

* Have red be below quads

* Code review pt 1

* Skip rendering of pivot

* Code review pt 2

* Code review pt 3

* Cancel resize and its hints

* Remove the redundant placing message

* Dragging state for text tool fsm

* Cleanup

* Fix line tool undo and abort problems

* Code review

* 3px textbox overflow bottom

* Some more cleanup

* Fix reversed match arms that had been converted to if-else

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mTvare
2025-03-19 06:49:49 +00:00
committed by GitHub
co-authored by Keavon Chambers
parent 43275b7a1e
commit b98711dbdb
23 changed files with 234 additions and 259 deletions
@@ -8,7 +8,7 @@ fn draw_dashed_line(line_start: DVec2, line_end: DVec2, transform: DAffine2, ove
let min_viewport = transform.transform_point2(line_start);
let max_viewport = transform.transform_point2(line_end);
overlay_context.dashed_line(min_viewport, max_viewport, None, Some(2.), Some(2.), Some(0.5));
overlay_context.dashed_line(min_viewport, max_viewport, None, None, Some(2.), Some(2.), Some(0.5));
}
/// Draws a solid line with a length annotation between two points transformed by the given affine transformations.
fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2, document_to_viewport: DAffine2, overlay_context: &mut OverlayContext, label_alignment: LabelAlignment) {
@@ -16,7 +16,7 @@ fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2
let min_viewport = transform.transform_point2(line_start);
let max_viewport = transform.transform_point2(line_end);
overlay_context.line(min_viewport, max_viewport, None);
overlay_context.line(min_viewport, max_viewport, None, None);
// Remove trailing zeros from the formatted string
let length = format!("{:.2}", transform_to_document.transform_vector2(line_end - line_start).length())
@@ -81,10 +81,10 @@ impl Pivot {
}
}
pub fn update_pivot(&mut self, document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, angle: f64) {
pub fn update_pivot(&mut self, document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, draw_data: Option<(f64,)>) {
self.recalculate_pivot(document);
if let Some(pivot) = self.pivot {
overlay_context.pivot(pivot, angle);
if let (Some(pivot), Some(data)) = (self.pivot, draw_data) {
overlay_context.pivot(pivot, data.0);
}
}
@@ -593,10 +593,7 @@ impl ShapeState {
if points_colinear_status.any(|point| first_is_colinear != point) {
return ManipulatorAngle::Mixed;
}
match first_is_colinear {
false => ManipulatorAngle::Free,
true => ManipulatorAngle::Colinear,
}
if first_is_colinear { ManipulatorAngle::Colinear } else { ManipulatorAngle::Free }
}
pub fn convert_manipulator_handles_to_colinear(&self, vector_data: &VectorData, point_id: PointId, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier) {
@@ -414,12 +414,13 @@ impl SnapManager {
let start = DVec2::new(first.max().x, y);
let end = DVec2::new(second.min().x, y);
let signed_size = if bottom { y_size } else { -y_size };
overlay_context.line(transform.transform_point2(start), transform.transform_point2(start + DVec2::Y * signed_size), None);
overlay_context.line(transform.transform_point2(end), transform.transform_point2(end + DVec2::Y * signed_size), None);
overlay_context.line(transform.transform_point2(start), transform.transform_point2(start + DVec2::Y * signed_size), None, None);
overlay_context.line(transform.transform_point2(end), transform.transform_point2(end + DVec2::Y * signed_size), None, None);
overlay_context.line(
transform.transform_point2(start + DVec2::Y * signed_size / 2.),
transform.transform_point2(end + DVec2::Y * signed_size / 2.),
None,
None,
);
}
}
@@ -432,12 +433,13 @@ impl SnapManager {
let start = DVec2::new(x, first.max().y);
let end = DVec2::new(x, second.min().y);
let signed_size = if right { x_size } else { -x_size };
overlay_context.line(transform.transform_point2(start), transform.transform_point2(start + DVec2::X * signed_size), None);
overlay_context.line(transform.transform_point2(end), transform.transform_point2(end + DVec2::X * signed_size), None);
overlay_context.line(transform.transform_point2(start), transform.transform_point2(start + DVec2::X * signed_size), None, None);
overlay_context.line(transform.transform_point2(end), transform.transform_point2(end + DVec2::X * signed_size), None, None);
overlay_context.line(
transform.transform_point2(start + DVec2::X * signed_size / 2.),
transform.transform_point2(end + DVec2::X * signed_size / 2.),
None,
None,
);
}
}
@@ -460,7 +462,7 @@ impl SnapManager {
let align = [ind.alignment_target_x, ind.alignment_target_y].map(|target| target.map(|target| to_viewport.transform_point2(target)));
let any_align = align.iter().flatten().next().is_some();
for &target in align.iter().flatten() {
overlay_context.line(viewport, target, None);
overlay_context.line(viewport, target, None, None);
}
for &target in align.iter().flatten() {
overlay_context.manipulator_handle(target, false, None);
@@ -374,7 +374,7 @@ pub struct BoundingBoxManager {
pub bounds: [DVec2; 2],
/// The transform to viewport space for the bounds co-ordinates when the bounds were last updated.
pub transform: DAffine2,
/// Was the transform previously singular?
/// Whether the transform is actually singular but adjusted to not be so.
pub transform_tampered: bool,
/// The transform to viewport space for the bounds co-ordinates when the transformation was started.
pub original_bound_transform: DAffine2,
@@ -566,16 +566,24 @@ impl BoundingBoxManager {
}
}
pub fn render_quad(&self, overlay_context: &mut OverlayContext) {
let quad = self.transform * Quad::from_box(self.bounds);
// Draw the bounding box rectangle
overlay_context.quad(quad, None);
}
/// Update the position of the bounding box and transform handles
pub fn render_overlays(&mut self, overlay_context: &mut OverlayContext) {
pub fn render_overlays(&mut self, overlay_context: &mut OverlayContext, render_quad: bool) {
let quad = self.transform * Quad::from_box(self.bounds);
let category = self.overlay_display_category();
let horizontal_edges = [quad.top_right().midpoint(quad.bottom_right()), quad.bottom_left().midpoint(quad.top_left())];
let vertical_edges = [quad.top_left().midpoint(quad.top_right()), quad.bottom_right().midpoint(quad.bottom_left())];
// Draw the bounding box rectangle
overlay_context.quad(quad, None);
if render_quad {
self.render_quad(overlay_context);
}
let mut draw_handle = |point: DVec2, angle: f64| {
let quad = DAffine2::from_angle_translation(angle, point) * Quad::from_box([DVec2::splat(-RESIZE_HANDLE_SIZE / 2.), DVec2::splat(RESIZE_HANDLE_SIZE / 2.)]);
@@ -60,7 +60,7 @@ pub fn text_bounding_box(layer: LayerNodeIdentifier, document: &DocumentMessageH
let (text, font, typesetting) = get_text(layer, &document.network_interface).expect("Text layer should have text when interacting with the Text tool");
let buzz_face = font_cache.get(font).map(|data| load_face(data));
let far = graphene_core::text::bounding_box(text, buzz_face.as_ref(), typesetting);
let far = graphene_core::text::bounding_box(text, buzz_face.as_ref(), typesetting, false);
Quad::from_box([DVec2::ZERO, far])
}