mirror of https://github.com/KLayout/klayout.git
WIP: point editing of multi-segment rulers
This commit is contained in:
parent
8cbe5a2359
commit
d2d321c35b
|
|
@ -32,6 +32,24 @@
|
|||
namespace ant
|
||||
{
|
||||
|
||||
static void
|
||||
clean_points_impl (ant::Object::point_list &points)
|
||||
{
|
||||
auto wp = points.begin ();
|
||||
auto p = points.begin ();
|
||||
while (p != points.end ()) {
|
||||
auto pp = p + 1;
|
||||
while (pp != points.end () && *pp == *p) {
|
||||
++pp;
|
||||
}
|
||||
*wp++ = *p;
|
||||
p = pp;
|
||||
}
|
||||
|
||||
points.erase (wp, points.end ());
|
||||
}
|
||||
|
||||
|
||||
Object::Object ()
|
||||
: m_id (-1),
|
||||
m_fmt_x ("$X"), m_fmt_y ("$Y"), m_fmt ("$D"),
|
||||
|
|
@ -88,7 +106,7 @@ Object::Object (const db::DPoint &_p1, const db::DPoint &_p2, int id, const ant:
|
|||
}
|
||||
|
||||
Object::Object (const Object::point_list &pts, int id, const ant::Template &t)
|
||||
: m_id (id),
|
||||
: m_points (pts), m_id (id),
|
||||
m_fmt_x (t.fmt_x ()), m_fmt_y (t.fmt_y ()), m_fmt (t.fmt ()),
|
||||
m_style (t.style ()), m_outline (t.outline ()),
|
||||
m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()),
|
||||
|
|
@ -98,7 +116,7 @@ Object::Object (const Object::point_list &pts, int id, const ant::Template &t)
|
|||
m_xlabel_xalign (t.xlabel_xalign ()), m_xlabel_yalign (t.xlabel_yalign ()),
|
||||
m_ylabel_xalign (t.ylabel_xalign ()), m_ylabel_yalign (t.ylabel_yalign ())
|
||||
{
|
||||
set_points (pts);
|
||||
clean_points_impl (m_points);
|
||||
}
|
||||
|
||||
Object::Object (const ant::Object &d)
|
||||
|
|
@ -224,22 +242,36 @@ Object::operator== (const ant::Object &d) const
|
|||
;
|
||||
}
|
||||
|
||||
void
|
||||
Object::clean_points ()
|
||||
{
|
||||
auto new_points = m_points;
|
||||
clean_points_impl (new_points);
|
||||
set_points_exact (std::move (new_points));
|
||||
}
|
||||
|
||||
void
|
||||
Object::set_points (const point_list &points)
|
||||
{
|
||||
point_list new_points;
|
||||
auto p = points.begin ();
|
||||
while (p != points.end ()) {
|
||||
auto pp = p + 1;
|
||||
while (pp != points.end () && *pp == *p) {
|
||||
++pp;
|
||||
}
|
||||
new_points.push_back (*p);
|
||||
p = pp;
|
||||
}
|
||||
auto new_points = points;
|
||||
clean_points_impl (new_points);
|
||||
set_points_exact (std::move (new_points));
|
||||
}
|
||||
|
||||
if (m_points != new_points) {
|
||||
m_points = new_points;
|
||||
void
|
||||
Object::set_points_exact (const point_list &points)
|
||||
{
|
||||
if (m_points != points) {
|
||||
m_points = points;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::set_points_exact (point_list &&points)
|
||||
{
|
||||
if (m_points != points) {
|
||||
m_points.swap (points);
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
|
@ -272,6 +304,30 @@ Object::seg_p2 (size_t seg_index) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::seg_p1 (size_t seg_index, const db::DPoint &p)
|
||||
{
|
||||
if (seg_index == std::numeric_limits<size_t>::max ()) {
|
||||
p1 (p);
|
||||
} else if (seg_index < m_points.size ()) {
|
||||
m_points[seg_index] = p;
|
||||
} else if (! m_points.empty ()) {
|
||||
m_points.back () = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::seg_p2 (size_t seg_index, const db::DPoint &p)
|
||||
{
|
||||
if (seg_index == std::numeric_limits<size_t>::max ()) {
|
||||
p2 (p);
|
||||
} else if (seg_index + 1 < m_points.size ()) {
|
||||
m_points[seg_index + 1] = p;
|
||||
} else if (! m_points.empty ()) {
|
||||
m_points.back () = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::p1 (const db::DPoint &p)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -295,10 +295,17 @@ public:
|
|||
/**
|
||||
* @brief Sets the ruler's definition points without cleaning
|
||||
*/
|
||||
void set_points_exact (const point_list &points)
|
||||
{
|
||||
m_points = points;
|
||||
}
|
||||
void set_points_exact (const point_list &points);
|
||||
|
||||
/**
|
||||
* @brief Sets the ruler's definition points without cleaning (move semantics)
|
||||
*/
|
||||
void set_points_exact (point_list &&points);
|
||||
|
||||
/**
|
||||
* @brief Cleans the point list
|
||||
*/
|
||||
void clean_points ();
|
||||
|
||||
/**
|
||||
* @brief Gets the first point of the indicated segment
|
||||
|
|
@ -310,6 +317,16 @@ public:
|
|||
*/
|
||||
db::DPoint seg_p2 (size_t seg_index) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the first point of the indicated segment
|
||||
*/
|
||||
void seg_p1 (size_t seg_index, const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Sets the second point of the indicated segment
|
||||
*/
|
||||
void seg_p2 (size_t seg_index, const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of segments
|
||||
*
|
||||
|
|
|
|||
|
|
@ -858,6 +858,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
mp_transient_ruler (0),
|
||||
m_drawing (false), m_current (),
|
||||
m_move_mode (MoveNone),
|
||||
m_seg_index (0),
|
||||
m_current_template (0)
|
||||
{
|
||||
mp_view->annotations_changed_event.add (this, &Service::annotations_changed);
|
||||
|
|
@ -1074,29 +1075,28 @@ Service::insert_ruler (const ant::Object &ruler, bool limit_number)
|
|||
return new_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to determine which move mode to choose given a certain search box and ant::Object
|
||||
*/
|
||||
static bool
|
||||
dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1)
|
||||
dragging_what_seg (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1, size_t index)
|
||||
{
|
||||
ant::Object::outline_type outline = robj->outline ();
|
||||
|
||||
db::DPoint p12, p21;
|
||||
bool has_p12 = false, has_p21 = false;
|
||||
|
||||
db::DPoint p11 = robj->p1 (), p22 = robj->p2 ();
|
||||
db::DPoint p11 = robj->seg_p1 (index), p22 = robj->seg_p2 (index);
|
||||
db::DPoint c = p11 + (p22 - p11) * 0.5;
|
||||
|
||||
if (robj->outline () == ant::Object::OL_xy || robj->outline () == ant::Object::OL_diag_xy || robj->outline () == ant::Object::OL_box) {
|
||||
p12 = db::DPoint (robj->p2 ().x (), robj->p1 ().y ());
|
||||
|
||||
if (outline == ant::Object::OL_xy || outline== ant::Object::OL_diag_xy || outline == ant::Object::OL_box) {
|
||||
p12 = db::DPoint (p22.x (), p11.y ());
|
||||
has_p12 = true;
|
||||
}
|
||||
|
||||
if (robj->outline () == ant::Object::OL_yx || robj->outline () == ant::Object::OL_diag_yx || robj->outline () == ant::Object::OL_box) {
|
||||
p21 = db::DPoint (robj->p1 ().x (), robj->p2 ().y ());
|
||||
if (outline == ant::Object::OL_yx || outline == ant::Object::OL_diag_yx || outline == ant::Object::OL_box) {
|
||||
p21 = db::DPoint (p11.x (), p22.y ());
|
||||
has_p21 = true;
|
||||
}
|
||||
|
||||
if (robj->outline () == ant::Object::OL_ellipse) {
|
||||
|
||||
if (outline == ant::Object::OL_ellipse) {
|
||||
db::DVector d = (p22 - p11) * 0.5;
|
||||
p12 = c + db::DVector (d.x (), -d.y ());
|
||||
p21 = c + db::DVector (-d.x (), d.y ());
|
||||
|
|
@ -1106,7 +1106,7 @@ dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Servic
|
|||
|
||||
// HINT: this was implemented returning a std::pair<MoveMode, db::DPoint>, but
|
||||
// I was not able to get it to work in gcc 4.1.2 in -O3 mode ...
|
||||
|
||||
|
||||
if (search_dbox.contains (p11)) {
|
||||
p1 = p11;
|
||||
mode = ant::Service::MoveP1;
|
||||
|
|
@ -1147,18 +1147,28 @@ dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Servic
|
|||
mode = ant::Service::MoveP2Y;
|
||||
return true;
|
||||
}
|
||||
if ((robj->outline () == ant::Object::OL_diag || robj->outline () == ant::Object::OL_diag_xy || robj->outline () == ant::Object::OL_diag_yx)
|
||||
&& db::DEdge (p11, p22).distance_abs (search_dbox.center ()) <= search_dbox.width () * 0.5) {
|
||||
p1 = search_dbox.center ();
|
||||
mode = ant::Service::MoveRuler;
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to determine which move mode to choose given a certain search box and ant::Object
|
||||
*/
|
||||
static bool
|
||||
dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1, size_t &index)
|
||||
{
|
||||
ant::Object::outline_type outline = robj->outline ();
|
||||
|
||||
if (outline == ant::Object::OL_box || outline == ant::Object::OL_ellipse) {
|
||||
index = std::numeric_limits<size_t>::max ();
|
||||
return dragging_what_seg (robj, search_dbox, mode, p1, index);
|
||||
}
|
||||
if ((robj->outline () == ant::Object::OL_box || robj->outline () == ant::Object::OL_ellipse) && search_dbox.inside (db::DBox (p11, p22))) {
|
||||
p1 = search_dbox.center ();
|
||||
mode = ant::Service::MoveRuler;
|
||||
return true;
|
||||
|
||||
for (index = 0; index < robj->segments (); ++index) {
|
||||
if (dragging_what_seg (robj, search_dbox, mode, p1, index)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1185,6 +1195,7 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
|
|||
} else if (mode == lay::Editable::Partial) {
|
||||
|
||||
m_move_mode = MoveNone;
|
||||
m_seg_index = 0;
|
||||
|
||||
// compute search box
|
||||
double l = catch_distance ();
|
||||
|
|
@ -1216,7 +1227,7 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
|
|||
const ant::Object *robj = dynamic_cast <const ant::Object *> ((*ri).ptr ());
|
||||
if (robj && (! robj_min || robj == robj_min)) {
|
||||
|
||||
if (dragging_what (robj, search_dbox, m_move_mode, m_p1) && m_move_mode != MoveRuler) {
|
||||
if (dragging_what (robj, search_dbox, m_move_mode, m_p1, m_seg_index) && m_move_mode != MoveRuler) {
|
||||
|
||||
// found anything: make the moved ruler the selection
|
||||
clear_selection ();
|
||||
|
|
@ -1273,7 +1284,7 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
|
|||
const ant::Object *robj = dynamic_cast <const ant::Object *> ((*r).ptr ());
|
||||
if (robj && (! robj_min || robj == robj_min)) {
|
||||
|
||||
if (dragging_what (robj, search_dbox, m_move_mode, m_p1)) {
|
||||
if (dragging_what (robj, search_dbox, m_move_mode, m_p1, m_seg_index)) {
|
||||
|
||||
// found anything: make the moved ruler the selection
|
||||
clear_selection ();
|
||||
|
|
@ -1340,50 +1351,50 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
|
||||
if (m_move_mode == MoveP1) {
|
||||
|
||||
m_current.p1 (snap2 (m_p1, p, &m_current, ac).second);
|
||||
m_current.seg_p1 (m_seg_index, snap2 (m_p1, p, &m_current, ac).second);
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP2) {
|
||||
|
||||
m_current.p2 (snap2 (m_p1, p, &m_current, ac).second);
|
||||
m_current.seg_p2 (m_seg_index, snap2 (m_p1, p, &m_current, ac).second);
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP12) {
|
||||
|
||||
db::DPoint p12 = snap2 (m_p1, p, &m_current, ac).second;
|
||||
m_current.p1 (db::DPoint (m_current.p1 ().x(), p12.y ()));
|
||||
m_current.p2 (db::DPoint (p12.x (), m_current.p2 ().y ()));
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x(), p12.y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (p12.x (), m_current.seg_p2 (m_seg_index).y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP21) {
|
||||
|
||||
db::DPoint p21 = snap2 (m_p1, p, &m_current, ac).second;
|
||||
m_current.p1 (db::DPoint (p21.x (), m_current.p1 ().y ()));
|
||||
m_current.p2 (db::DPoint (m_current.p2 ().x(), p21.y ()));
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (p21.x (), m_current.seg_p1 (m_seg_index).y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x(), p21.y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP1X) {
|
||||
|
||||
db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second;
|
||||
m_current.p1 (db::DPoint (pc.x (), m_current.p1 ().y ()));
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (pc.x (), m_current.seg_p1 (m_seg_index).y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP2X) {
|
||||
|
||||
db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second;
|
||||
m_current.p2 (db::DPoint (pc.x (), m_current.p2 ().y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (pc.x (), m_current.seg_p2 (m_seg_index).y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP1Y) {
|
||||
|
||||
db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second;
|
||||
m_current.p1 (db::DPoint (m_current.p1 ().x (), pc.y ()));
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x (), pc.y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP2Y) {
|
||||
|
||||
db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second;
|
||||
m_current.p2 (db::DPoint (m_current.p2 ().x (), pc.y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x (), pc.y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveRuler) {
|
||||
|
|
@ -1474,6 +1485,7 @@ Service::end_move (const db::DPoint &, lay::angle_constraint_type)
|
|||
} else if (m_move_mode != MoveNone) {
|
||||
|
||||
// replace the ruler that was moved
|
||||
m_current.clean_points ();
|
||||
mp_view->annotation_shapes ().replace (m_selected.begin ()->first, db::DUserObject (new ant::Object (m_current)));
|
||||
annotation_changed_event (m_current.id ());
|
||||
|
||||
|
|
|
|||
|
|
@ -545,6 +545,8 @@ private:
|
|||
ant::Object m_original;
|
||||
// The current move mode
|
||||
MoveMode m_move_mode;
|
||||
// The currently moving segment
|
||||
size_t m_seg_index;
|
||||
// The ruler template
|
||||
std::vector<ant::Template> m_ruler_templates;
|
||||
unsigned int m_current_template;
|
||||
|
|
|
|||
Loading…
Reference in New Issue