diff --git a/src/edt/edt/EditorOptionsGeneric.ui b/src/edt/edt/EditorOptionsGeneric.ui
index 8de52d0097..84c102c717 100644
--- a/src/edt/edt/EditorOptionsGeneric.ui
+++ b/src/edt/edt/EditorOptionsGeneric.ui
@@ -95,10 +95,30 @@
2
- -
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Enter the grid in micron. Can be anisotropic ("gx,gy")
+
+
+
+ -
+
- Grid
+ Objects
+
+
+
+ -
+
+
+ Snap to other objects
@@ -130,17 +150,10 @@
- -
-
-
- Snap to other objects
-
-
-
- -
-
+
-
+
- Objects
+ Grid
@@ -157,16 +170,10 @@
- -
-
-
-
- 0
- 0
-
-
-
- Enter the grid in micron. Can be anisotropic ("gx,gy")
+
-
+
+
+ Snap to grid while moving
diff --git a/src/edt/edt/edtConfig.cc b/src/edt/edt/edtConfig.cc
index 8c158130ea..50be8b6c58 100644
--- a/src/edt/edt/edtConfig.cc
+++ b/src/edt/edt/edtConfig.cc
@@ -32,6 +32,7 @@ namespace edt
std::string cfg_edit_grid ("edit-grid");
std::string cfg_edit_snap_to_objects ("edit-snap-to-objects");
+std::string cfg_edit_snap_objects_to_grid ("edit-snap-objects-to-grid");
std::string cfg_edit_move_angle_mode ("edit-move-angle-mode");
std::string cfg_edit_connect_angle_mode ("edit-connect-angle-mode");
std::string cfg_edit_text_string ("edit-text-string");
diff --git a/src/edt/edt/edtConfig.h b/src/edt/edt/edtConfig.h
index 6a8ce403a5..36862a8ea2 100644
--- a/src/edt/edt/edtConfig.h
+++ b/src/edt/edt/edtConfig.h
@@ -40,6 +40,7 @@ namespace edt
*/
extern EDT_PUBLIC std::string cfg_edit_grid;
extern EDT_PUBLIC std::string cfg_edit_snap_to_objects;
+extern EDT_PUBLIC std::string cfg_edit_snap_objects_to_grid;
extern EDT_PUBLIC std::string cfg_edit_move_angle_mode;
extern EDT_PUBLIC std::string cfg_edit_connect_angle_mode;
extern EDT_PUBLIC std::string cfg_edit_text_string;
diff --git a/src/edt/edt/edtEditorOptionsPages.cc b/src/edt/edt/edtEditorOptionsPages.cc
index e7d23954d8..74a364b5b9 100644
--- a/src/edt/edt/edtEditorOptionsPages.cc
+++ b/src/edt/edt/edtEditorOptionsPages.cc
@@ -85,6 +85,7 @@ EditorOptionsGeneric::EditorOptionsGeneric (lay::LayoutViewBase *view, lay::Disp
connect (mp_ui->hier_sel_cbx, SIGNAL (clicked ()), this, SLOT (edited ()));
connect (mp_ui->hier_copy_mode_cbx, SIGNAL (activated (int)), this, SLOT (edited ()));
connect (mp_ui->snap_objects_cbx, SIGNAL (clicked ()), this, SLOT (edited ()));
+ connect (mp_ui->snap_objects_to_grid_cbx, SIGNAL (clicked ()), this, SLOT (edited ()));
connect (mp_ui->max_shapes_le, SIGNAL (editingFinished ()), this, SLOT (edited ()));
connect (mp_ui->show_shapes_cbx, SIGNAL (clicked ()), this, SLOT (edited ()));
}
@@ -132,6 +133,7 @@ EditorOptionsGeneric::apply (lay::Dispatcher *root)
int cpm = mp_ui->hier_copy_mode_cbx->currentIndex ();
root->config_set (cfg_edit_hier_copy_mode, tl::to_string ((cpm < 0 || cpm > 1) ? -1 : cpm));
root->config_set (cfg_edit_snap_to_objects, tl::to_string (mp_ui->snap_objects_cbx->isChecked ()));
+ root->config_set (cfg_edit_snap_objects_to_grid, tl::to_string (mp_ui->snap_objects_to_grid_cbx->isChecked ()));
configure_from_line_edit (root, mp_ui->max_shapes_le, cfg_edit_max_shapes_of_instances);
root->config_set (cfg_edit_show_shapes_of_instances, tl::to_string (mp_ui->show_shapes_cbx->isChecked ()));
@@ -194,6 +196,10 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root)
root->config_get (cfg_edit_snap_to_objects, snap_to_objects);
mp_ui->snap_objects_cbx->setChecked (snap_to_objects);
+ bool snap_objects_to_grid = false;
+ root->config_get (cfg_edit_snap_objects_to_grid, snap_objects_to_grid);
+ mp_ui->snap_objects_to_grid_cbx->setChecked (snap_objects_to_grid);
+
unsigned int max_shapes = 1000;
root->config_get (cfg_edit_max_shapes_of_instances, max_shapes);
mp_ui->max_shapes_le->setText (tl::to_qstring (tl::to_string (max_shapes)));
diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc
index 85fe17e9ec..0721171539 100644
--- a/src/edt/edt/edtPartialService.cc
+++ b/src/edt/edt/edtPartialService.cc
@@ -1102,6 +1102,7 @@ PartialService::PartialService (db::Manager *manager, lay::LayoutViewBase *view,
m_buttons (0),
m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global),
m_snap_to_objects (true),
+ m_snap_objects_to_grid (true),
m_top_level_sel (false),
m_hover (false),
m_hover_wait (false),
@@ -1341,6 +1342,9 @@ PartialService::configure (const std::string &name, const std::string &value)
} else if (name == cfg_edit_snap_to_objects) {
tl::from_string (value, m_snap_to_objects);
return true; // taken
+ } else if (name == cfg_edit_snap_objects_to_grid) {
+ tl::from_string (value, m_snap_objects_to_grid);
+ return true; // taken
} else if (name == cfg_edit_move_angle_mode) {
acc.from_string (value, m_move_ac);
return true; // taken
diff --git a/src/edt/edt/edtPartialService.h b/src/edt/edt/edtPartialService.h
index cdc07b61dc..cd98b953da 100644
--- a/src/edt/edt/edtPartialService.h
+++ b/src/edt/edt/edtPartialService.h
@@ -341,6 +341,7 @@ public slots:
lay::angle_constraint_type m_connect_ac, m_move_ac, m_alt_ac;
db::DVector m_edit_grid;
bool m_snap_to_objects;
+ bool m_snap_objects_to_grid;
db::DVector m_global_grid;
bool m_top_level_sel;
diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc
index d9e374902f..a23055a27b 100644
--- a/src/edt/edt/edtPlugin.cc
+++ b/src/edt/edt/edtPlugin.cc
@@ -331,6 +331,7 @@ class MainPluginDeclaration
options.push_back (std::pair (cfg_edit_hier_copy_mode, "-1"));
options.push_back (std::pair (cfg_edit_grid, ""));
options.push_back (std::pair (cfg_edit_snap_to_objects, "false"));
+ options.push_back (std::pair (cfg_edit_snap_objects_to_grid, "true"));
options.push_back (std::pair (cfg_edit_move_angle_mode, "any"));
options.push_back (std::pair (cfg_edit_connect_angle_mode, "any"));
options.push_back (std::pair (cfg_edit_combine_mode, "add"));
diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc
index 1b5950d61f..83a0b8744b 100644
--- a/src/edt/edt/edtService.cc
+++ b/src/edt/edt/edtService.cc
@@ -72,7 +72,8 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
m_flags (flags),
m_move_sel (false), m_moving (false),
m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global),
- m_snap_to_objects (false),
+ m_snap_to_objects (true),
+ m_snap_objects_to_grid (true),
m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000),
m_hier_copy_mode (-1),
m_indicate_secondary_selection (false),
@@ -94,6 +95,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
m_move_sel (false), m_moving (false),
m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global),
m_snap_to_objects (true),
+ m_snap_objects_to_grid (true),
m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000),
m_hier_copy_mode (-1),
m_indicate_secondary_selection (false),
@@ -152,7 +154,6 @@ void
Service::update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const
{
db::DVector v = snap (pt) - pt;
- v = lay::snap_angle (v, move_ac ());
if (! result_set || v.length () < vr.length ()) {
result_set = true;
@@ -204,32 +205,51 @@ Service::update_vector_snapped_marker (const lay::ShapeMarker *sm, const db::DTr
}
}
+void
+Service::update_vector_snapped_marker (const lay::InstanceMarker *im, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const
+{
+ const db::Instance &instance = im->instance ();
+ db::CplxTrans tr = db::DCplxTrans (trans) * db::DCplxTrans (-im->trans ().disp ()) * im->trans ();
+
+ update_vector_snapped_point (tr * (instance.complex_trans () * db::Point ()), vr, result_set);
+ --count;
+}
+
db::DVector
-Service::snap_marker_to_grid (const db::DVector &v) const
+Service::snap_marker_to_grid (const db::DVector &v, bool &snapped) const
{
+ if (! m_snap_objects_to_grid) {
+ return v;
+ }
+
+ snapped = false;
db::DVector vr;
- bool result_set = false;
// max. 10000 checks
size_t count = 10000;
- db::DTrans tt = db::DTrans (v);
+ db::DVector snapped_to (1.0, 1.0);
+ db::DVector vv = lay::snap_angle (v, move_ac (), &snapped_to);
+
+ db::DTrans tt = db::DTrans (vv);
for (auto m = m_markers.begin (); m != m_markers.end () && count > 0; ++m) {
const lay::ShapeMarker *sm = dynamic_cast (*m);
+ const lay::InstanceMarker *im = dynamic_cast (*m);
if (sm) {
- update_vector_snapped_marker (sm, tt, vr, result_set, count);
- } else {
- // @@@ instance markers
+ update_vector_snapped_marker (sm, tt, vr, snapped, count);
+ } else if (im) {
+ update_vector_snapped_marker (im, tt, vr, snapped, count);
}
}
- if (result_set) {
- return vr + v;
+ if (snapped) {
+ vr += vv;
+ return db::DVector (vr.x () * snapped_to.x (), vr.y () * snapped_to.y ());
} else {
- return v;
+ return db::DVector ();
}
}
@@ -324,6 +344,13 @@ Service::configure (const std::string &name, const std::string &value)
return true; // taken
+ } else if (name == cfg_edit_snap_objects_to_grid) {
+
+ tl::from_string (value, m_snap_objects_to_grid);
+ service_configuration_changed ();
+
+ return true; // taken
+
} else if (name == cfg_edit_move_angle_mode) {
acc.from_string (value, m_move_ac);
@@ -521,8 +548,9 @@ Service::move (const db::DPoint &pu, lay::angle_constraint_type ac)
m_alt_ac = ac;
if (view ()->is_editable () && m_moving) {
db::DPoint ref = snap (m_move_start);
- db::DPoint p = ref + snap_marker_to_grid (pu - ref);
- if (p.equal (pu)) {
+ bool snapped = false;
+ db::DPoint p = ref + snap_marker_to_grid (pu - m_move_start, snapped);
+ if (! snapped) {
p = ref + snap (pu - m_move_start, false /*move*/);
}
move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - ref));
@@ -536,8 +564,9 @@ Service::move_transform (const db::DPoint &pu, db::DFTrans tr, lay::angle_constr
m_alt_ac = ac;
if (view ()->is_editable () && m_moving) {
db::DPoint ref = snap (m_move_start);
- db::DPoint p = ref + snap_marker_to_grid (pu - ref);
- if (p.equal (pu)) {
+ bool snapped = false;
+ db::DPoint p = ref + snap_marker_to_grid (pu - m_move_start, snapped);
+ if (! snapped) {
p = ref + snap (pu - m_move_start, false /*move*/);
}
move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (tr * m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - ref));
diff --git a/src/edt/edt/edtService.h b/src/edt/edt/edtService.h
index 55f756f1bf..bc09bed4b2 100644
--- a/src/edt/edt/edtService.h
+++ b/src/edt/edt/edtService.h
@@ -524,7 +524,7 @@ class EDT_PUBLIC Service
* @param v The input displacement
* @return A displacement that pushes the (current) markers on-grid, definition depending on marker
*/
- db::DVector snap_marker_to_grid (const db::DVector &v) const;
+ db::DVector snap_marker_to_grid (const db::DVector &v, bool &snapped) const;
/**
* @brief Snap a point to the edit grid with advanced snapping (including object snapping)
@@ -613,6 +613,7 @@ class EDT_PUBLIC Service
lay::angle_constraint_type m_connect_ac, m_move_ac, m_alt_ac;
db::DVector m_edit_grid;
bool m_snap_to_objects;
+ bool m_snap_objects_to_grid;
db::DVector m_global_grid;
bool m_top_level_sel;
bool m_show_shapes_of_instances;
@@ -668,6 +669,7 @@ class EDT_PUBLIC Service
void copy_selected (unsigned int inst_mode);
void update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const;
void update_vector_snapped_marker (const lay::ShapeMarker *sm, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const;
+ void update_vector_snapped_marker (const lay::InstanceMarker *sm, const db::DTrans &trans, db::DVector &vr, bool &result_set, size_t &count) const;
};
}
diff --git a/src/laybasic/laybasic/layMarker.h b/src/laybasic/laybasic/layMarker.h
index 2563bd6989..3fa54b4427 100644
--- a/src/laybasic/laybasic/layMarker.h
+++ b/src/laybasic/laybasic/layMarker.h
@@ -439,6 +439,14 @@ class LAYBASIC_PUBLIC InstanceMarker
*/
~InstanceMarker ();
+ /**
+ * @brief Gets the instance
+ */
+ const db::Instance &instance () const
+ {
+ return m_inst;
+ }
+
/**
* @brief Set the instance the marker is to display
*
diff --git a/src/laybasic/laybasic/laySnap.cc b/src/laybasic/laybasic/laySnap.cc
index b6d268b328..d04f9395bb 100644
--- a/src/laybasic/laybasic/laySnap.cc
+++ b/src/laybasic/laybasic/laySnap.cc
@@ -183,7 +183,7 @@ draw_round_dbl (const db::DPoint &p1, const db::DPoint &p2, int /*h*/)
}
db::DVector
-snap_angle (const db::DVector &in, lay::angle_constraint_type ac)
+snap_angle (const db::DVector &in, lay::angle_constraint_type ac, db::DVector *snapped_to)
{
std::vector ref_dir;
if (ac != lay::AC_Any) {
@@ -206,11 +206,17 @@ snap_angle (const db::DVector &in, lay::angle_constraint_type ac)
proj = db::sprod (*re, in) / (elen * re->length ());
if (proj > max_proj) {
max_proj = proj;
+ if (snapped_to) {
+ *snapped_to = *re;
+ }
out = *re * (elen * proj / re->length ());
}
proj = db::sprod (-*re, in) / (elen * re->length ());
if (proj > max_proj) {
max_proj = proj;
+ if (snapped_to) {
+ *snapped_to = *re;
+ }
out = -*re * (elen * proj / re->length ());
}
}
@@ -218,6 +224,7 @@ snap_angle (const db::DVector &in, lay::angle_constraint_type ac)
return out;
}
+
// ---------------------------------------------------------------------------------------
// obj_snap implementations
diff --git a/src/laybasic/laybasic/laySnap.h b/src/laybasic/laybasic/laySnap.h
index 6ac05fc685..bb22a2be95 100644
--- a/src/laybasic/laybasic/laySnap.h
+++ b/src/laybasic/laybasic/laySnap.h
@@ -238,8 +238,12 @@ namespace lay
/**
* @brief Reduce a given vector according to the angle constraint
+ *
+ * If the "snapped_to" pointer is non-null, it will receive the snap target
+ * vector (e.g. (1, 0) for snapping to horizontal axis. If no snapping happens,
+ * the value of this vector is not changed.
*/
- LAYBASIC_PUBLIC db::DVector snap_angle (const db::DVector &in, lay::angle_constraint_type ac);
+ LAYBASIC_PUBLIC db::DVector snap_angle (const db::DVector &in, lay::angle_constraint_type ac, db::DVector *snapped_to = 0);
/**
* @brief rounding of a double value for drawing purposes