From 160cceb7b54cce1ee45cf8bf5f8a83e15fb3eeba Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 11 Jan 2026 23:46:11 +0100 Subject: [PATCH] Pressing Ctrl key while drawing a box forces it into a square --- src/edt/edt/edtBoxService.cc | 19 ++++++++++++++++--- src/edt/edt/edtService.cc | 27 +++++++++++++++++++++++---- src/edt/edt/edtService.h | 11 +++++++++++ src/laybasic/laybasic/laySnap.cc | 12 +++++++++--- src/laybasic/laybasic/laySnap.h | 2 +- 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/edt/edt/edtBoxService.cc b/src/edt/edt/edtBoxService.cc index 8b1cdd173..a8554c43b 100644 --- a/src/edt/edt/edtBoxService.cc +++ b/src/edt/edt/edtBoxService.cc @@ -108,7 +108,10 @@ BoxService::do_mouse_move_inactive (const db::DPoint &p) void BoxService::do_mouse_move (const db::DPoint &p) { - lay::PointSnapToObjectResult snap_details = snap2_details (p); + // snap to square if Ctrl button is pressed + bool snap_square = alt_ac () == lay::AC_Diagonal; + + lay::PointSnapToObjectResult snap_details = snap2_details (p, m_p1, snap_square ? lay::AC_DiagonalOnly : lay::AC_Any); db::DPoint ps = snap_details.snapped_point; if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) { @@ -122,12 +125,22 @@ BoxService::do_mouse_move (const db::DPoint &p) lay::PointSnapToObjectResult snap_details_y = snap2_details (py); if (snap_details_x.object_snap != lay::PointSnapToObjectResult::NoObject) { - ps = db::DPoint (snap_details_x.snapped_point.x (), ps.y ()); + if (snap_square) { + double dx = fabs (snap_details_x.snapped_point.x () - m_p1.x ()); + ps = db::DPoint (snap_details_x.snapped_point.x (), m_p1.y () + (ps.y () < m_p1.y () ? -dx : dx)); + } else { + ps = db::DPoint (snap_details_x.snapped_point.x (), ps.y ()); + } mouse_cursor_from_snap_details (snap_details_x, true /*add*/); } if (snap_details_y.object_snap != lay::PointSnapToObjectResult::NoObject) { - ps = db::DPoint (ps.x (), snap_details_y.snapped_point.y ()); + if (snap_square) { + double dy = fabs (snap_details_y.snapped_point.x () - m_p1.y ()); + ps = db::DPoint (m_p1.x () + (ps.x () < m_p1.x () ? -dy : dy), snap_details_y.snapped_point.y ()); + } else { + ps = db::DPoint (ps.x (), snap_details_y.snapped_point.y ()); + } mouse_cursor_from_snap_details (snap_details_y, true /*add*/); } diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index 83c164472..ff098ac94 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -103,14 +103,21 @@ Service::~Service () clear_transient_selection (); } -lay::angle_constraint_type +lay::angle_constraint_type +Service::alt_ac () const +{ + // fetch m_alt_ac (which is set from mouse buttons) + return m_alt_ac; +} + +lay::angle_constraint_type Service::connect_ac () const { // m_alt_ac (which is set from mouse buttons) can override the specified connect angle constraint return m_alt_ac != lay::AC_Global ? m_alt_ac : m_connect_ac; } -lay::angle_constraint_type +lay::angle_constraint_type Service::move_ac () const { // m_alt_ac (which is set from mouse buttons) can override the specified move angle constraint @@ -290,11 +297,23 @@ Service::snap2 (const db::DPoint &p) const return snap2_details (p).snapped_point; } +lay::PointSnapToObjectResult +Service::snap2_details (const db::DPoint &p, const db::DPoint &plast, lay::angle_constraint_type ac) const +{ + double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (lay::snap_range_pixels ()); + return lay::obj_snap (m_snap_to_objects ? view () : 0, plast, p, m_edit_grid == db::DVector () ? m_global_grid : m_edit_grid, ac, snap_range); +} + +lay::PointSnapToObjectResult +Service::snap2_details (const db::DPoint &p, const db::DPoint &plast, bool connect) const +{ + return snap2_details (p, plast, connect ? connect_ac () : move_ac ()); +} + db::DPoint Service::snap2 (const db::DPoint &p, const db::DPoint &plast, bool connect) const { - double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (lay::snap_range_pixels ()); - return lay::obj_snap (m_snap_to_objects ? view () : 0, plast, p, m_edit_grid == db::DVector () ? m_global_grid : m_edit_grid, connect ? connect_ac () : move_ac (), snap_range).snapped_point; + return snap2_details (p, plast, connect ? connect_ac () : move_ac ()).snapped_point; } void diff --git a/src/edt/edt/edtService.h b/src/edt/edt/edtService.h index a791187e5..09bb56e96 100644 --- a/src/edt/edt/edtService.h +++ b/src/edt/edt/edtService.h @@ -611,6 +611,7 @@ protected: db::DPoint snap2 (const db::DPoint &p, const db::DPoint &plast, bool connect = true) const; protected: + lay::angle_constraint_type alt_ac () const; lay::angle_constraint_type connect_ac () const; lay::angle_constraint_type move_ac () const; @@ -654,6 +655,16 @@ protected: */ lay::PointSnapToObjectResult snap2_details (const db::DPoint &p) const; + /** + * @brief Point snapping with detailed return value + */ + lay::PointSnapToObjectResult snap2_details (const db::DPoint &p, const db::DPoint &plast, bool connect) const; + + /** + * @brief Point snapping with detailed return value and specific angle constraint + */ + lay::PointSnapToObjectResult snap2_details (const db::DPoint &p, const db::DPoint &plast, lay::angle_constraint_type ac) const; + private: friend class EditableSelectionIterator; diff --git a/src/laybasic/laybasic/laySnap.cc b/src/laybasic/laybasic/laySnap.cc index 8578e84dd..c7f02b351 100644 --- a/src/laybasic/laybasic/laySnap.cc +++ b/src/laybasic/laybasic/laySnap.cc @@ -188,9 +188,11 @@ snap_angle (const db::DVector &in, lay::angle_constraint_type ac, db::DVector *s std::vector ref_dir; if (ac != lay::AC_Any) { ref_dir.reserve (4); - ref_dir.push_back (db::DVector (1.0, 0)); - ref_dir.push_back (db::DVector (0, 1.0)); - if (ac == lay::AC_Diagonal) { + if (ac != lay::AC_DiagonalOnly) { + ref_dir.push_back (db::DVector (1.0, 0)); + ref_dir.push_back (db::DVector (0, 1.0)); + } + if (ac == lay::AC_Diagonal || ac == lay::AC_DiagonalOnly) { ref_dir.push_back (db::DVector (-1.0, 1.0)); ref_dir.push_back (db::DVector (1.0, 1.0)); } @@ -963,6 +965,10 @@ make_cutlines (lay::angle_constraint_type snap_mode, const db::DPoint &p1, std:: cutlines.push_back (db::DEdge (p1, p1 + db::DVector (1.0, 0.0))); cutlines.push_back (db::DEdge (p1, p1 + db::DVector (1.0, 1.0))); cutlines.push_back (db::DEdge (p1, p1 + db::DVector (1.0, -1.0))); + } else if (snap_mode == lay::AC_DiagonalOnly) { + cutlines.reserve (2); + cutlines.push_back (db::DEdge (p1, p1 + db::DVector (1.0, 1.0))); + cutlines.push_back (db::DEdge (p1, p1 + db::DVector (1.0, -1.0))); } } diff --git a/src/laybasic/laybasic/laySnap.h b/src/laybasic/laybasic/laySnap.h index 51f209633..cfa63ae9b 100644 --- a/src/laybasic/laybasic/laySnap.h +++ b/src/laybasic/laybasic/laySnap.h @@ -53,7 +53,7 @@ namespace lay * Vertical: vertical only * Global: use global setting (templates and ruler specific setting only) */ - enum angle_constraint_type { AC_Any = 0, AC_Diagonal, AC_Ortho, AC_Horizontal, AC_Vertical, AC_Global, AC_NumModes }; + enum angle_constraint_type { AC_Any = 0, AC_Diagonal, AC_DiagonalOnly, AC_Ortho, AC_Horizontal, AC_Vertical, AC_Global, AC_NumModes }; /** * @brief snap a coordinate value to a unit grid