mirror of https://github.com/KLayout/klayout.git
WIP: first steps towards multi-segment rulers
This commit is contained in:
parent
7b4b345cf4
commit
d1b7cd1f8f
File diff suppressed because it is too large
Load Diff
|
|
@ -33,7 +33,7 @@ namespace ant
|
|||
{
|
||||
|
||||
Object::Object ()
|
||||
: m_p1 (), m_p2 (), m_id (-1),
|
||||
: m_id (-1),
|
||||
m_fmt_x ("$X"), m_fmt_y ("$Y"), m_fmt ("$D"),
|
||||
m_style (STY_ruler), m_outline (OL_diag),
|
||||
m_snap (true), m_angle_constraint (lay::AC_Global),
|
||||
|
|
@ -45,8 +45,8 @@ Object::Object ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
|
||||
: m_p1 (p1), m_p2 (p2), m_id (id),
|
||||
Object::Object (const db::DPoint &_p1, const db::DPoint &_p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
|
||||
: m_id (id),
|
||||
m_fmt_x (fmt_x), m_fmt_y (fmt_y), m_fmt (fmt),
|
||||
m_style (style), m_outline (outline),
|
||||
m_snap (snap), m_angle_constraint (angle_constraint),
|
||||
|
|
@ -55,11 +55,25 @@ Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::s
|
|||
m_xlabel_xalign (AL_auto), m_xlabel_yalign (AL_auto),
|
||||
m_ylabel_xalign (AL_auto), m_ylabel_yalign (AL_auto)
|
||||
{
|
||||
// .. nothing else ..
|
||||
p1 (_p1);
|
||||
p2 (_p2);
|
||||
}
|
||||
|
||||
Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::Template &t)
|
||||
: m_p1 (p1), m_p2 (p2), m_id (id),
|
||||
Object::Object (const Object::point_list &pts, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
|
||||
: m_id (id),
|
||||
m_fmt_x (fmt_x), m_fmt_y (fmt_y), m_fmt (fmt),
|
||||
m_style (style), m_outline (outline),
|
||||
m_snap (snap), m_angle_constraint (angle_constraint),
|
||||
m_main_position (POS_auto),
|
||||
m_main_xalign (AL_auto), m_main_yalign (AL_auto),
|
||||
m_xlabel_xalign (AL_auto), m_xlabel_yalign (AL_auto),
|
||||
m_ylabel_xalign (AL_auto), m_ylabel_yalign (AL_auto)
|
||||
{
|
||||
set_points (pts);
|
||||
}
|
||||
|
||||
Object::Object (const db::DPoint &_p1, const db::DPoint &_p2, int id, const ant::Template &t)
|
||||
: 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 ()),
|
||||
|
|
@ -69,11 +83,26 @@ Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::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 ())
|
||||
{
|
||||
// .. nothing else ..
|
||||
p1 (_p1);
|
||||
p2 (_p2);
|
||||
}
|
||||
|
||||
Object::Object (const Object::point_list &pts, int id, const ant::Template &t)
|
||||
: 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 ()),
|
||||
m_category (t.category ()),
|
||||
m_main_position (t.main_position ()),
|
||||
m_main_xalign (t.main_xalign ()), m_main_yalign (t.main_yalign ()),
|
||||
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);
|
||||
}
|
||||
|
||||
Object::Object (const ant::Object &d)
|
||||
: m_p1 (d.m_p1), m_p2 (d.m_p2), m_id (d.m_id),
|
||||
: m_points (d.m_points), m_id (d.m_id),
|
||||
m_fmt_x (d.m_fmt_x), m_fmt_y (d.m_fmt_y), m_fmt (d.m_fmt),
|
||||
m_style (d.m_style), m_outline (d.m_outline),
|
||||
m_snap (d.m_snap), m_angle_constraint (d.m_angle_constraint),
|
||||
|
|
@ -90,8 +119,7 @@ Object &
|
|||
Object::operator= (const ant::Object &d)
|
||||
{
|
||||
if (this != &d) {
|
||||
m_p1 = d.m_p1;
|
||||
m_p2 = d.m_p2;
|
||||
m_points = d.m_points;
|
||||
m_id = d.m_id;
|
||||
m_fmt_x = d.m_fmt_x;
|
||||
m_fmt_y = d.m_fmt_y;
|
||||
|
|
@ -119,11 +147,8 @@ Object::operator< (const ant::Object &b) const
|
|||
if (m_id != b.m_id) {
|
||||
return m_id < b.m_id;
|
||||
}
|
||||
if (m_p1 != b.m_p1) {
|
||||
return m_p1 < b.m_p1;
|
||||
}
|
||||
if (m_p2 != b.m_p2) {
|
||||
return m_p2 < b.m_p2;
|
||||
if (m_points != b.m_points) {
|
||||
return m_points < b.m_points;
|
||||
}
|
||||
if (m_fmt_x != b.m_fmt_x) {
|
||||
return m_fmt_x < b.m_fmt_x;
|
||||
|
|
@ -187,7 +212,7 @@ Object::equals (const db::DUserObjectBase *d) const
|
|||
bool
|
||||
Object::operator== (const ant::Object &d) const
|
||||
{
|
||||
return m_p1 == d.m_p1 && m_p2 == d.m_p2 && m_id == d.m_id &&
|
||||
return m_points == d.m_points && m_id == d.m_id &&
|
||||
m_fmt_x == d.m_fmt_x && m_fmt_y == d.m_fmt_y && m_fmt == d.m_fmt &&
|
||||
m_style == d.m_style && m_outline == d.m_outline &&
|
||||
m_snap == d.m_snap && m_angle_constraint == d.m_angle_constraint &&
|
||||
|
|
@ -199,6 +224,87 @@ Object::operator== (const ant::Object &d) const
|
|||
;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (m_points != new_points) {
|
||||
m_points = new_points;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
Object::seg_p1 (size_t seg_index) const
|
||||
{
|
||||
if (seg_index < m_points.size ()) {
|
||||
return m_points[seg_index];
|
||||
} else if (m_points.empty ()) {
|
||||
return db::DPoint ();
|
||||
} else {
|
||||
return m_points.back ();
|
||||
}
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
Object::seg_p2 (size_t seg_index) const
|
||||
{
|
||||
if (seg_index + 1 < m_points.size ()) {
|
||||
return m_points[seg_index + 1];
|
||||
} else if (m_points.empty ()) {
|
||||
return db::DPoint ();
|
||||
} else {
|
||||
return m_points.back ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::p1 (const db::DPoint &p)
|
||||
{
|
||||
if (! p1 ().equal (p)) {
|
||||
if (m_points.size () < 1) {
|
||||
m_points.push_back (p);
|
||||
} else {
|
||||
m_points.front () = p;
|
||||
// makes sure there is only one point if p1 == p2
|
||||
if (m_points.size () == 2 && m_points.back () == m_points.front ()) {
|
||||
m_points.pop_back ();
|
||||
}
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::p2 (const db::DPoint &p)
|
||||
{
|
||||
if (! p2 ().equal (p)) {
|
||||
if (m_points.size () < 2) {
|
||||
if (m_points.empty ()) {
|
||||
m_points.push_back (db::DPoint ());
|
||||
}
|
||||
m_points.push_back (p);
|
||||
} else {
|
||||
m_points.back () = p;
|
||||
}
|
||||
// makes sure there is only one point if p1 == p2
|
||||
if (m_points.size () == 2 && m_points.back () == m_points.front ()) {
|
||||
m_points.pop_back ();
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Object::less (const db::DUserObjectBase *d) const
|
||||
{
|
||||
|
|
@ -226,7 +332,11 @@ Object::clone () const
|
|||
db::DBox
|
||||
Object::box () const
|
||||
{
|
||||
return db::DBox (m_p1, m_p2);
|
||||
db::DBox bx;
|
||||
for (auto d = m_points.begin (); d != m_points.end (); ++d) {
|
||||
bx += *d;
|
||||
}
|
||||
return bx;
|
||||
}
|
||||
|
||||
class AnnotationEval
|
||||
|
|
@ -245,38 +355,12 @@ private:
|
|||
db::DFTrans m_trans;
|
||||
};
|
||||
|
||||
static double
|
||||
delta_x (const Object &obj, const db::DFTrans &t)
|
||||
{
|
||||
double dx = ((t * obj.p2 ()).x () - (t * obj.p1 ()).x ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dx) < 1e-5 /*micron*/) {
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
return dx;
|
||||
}
|
||||
|
||||
static double
|
||||
delta_y (const Object &obj, const db::DFTrans &t)
|
||||
{
|
||||
double dy = ((t * obj.p2 ()).y () - (t * obj.p1 ()).y ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dy) < 1e-5 /*micron*/) {
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
return dy;
|
||||
}
|
||||
|
||||
class AnnotationEvalFunction
|
||||
: public tl::EvalFunction
|
||||
{
|
||||
public:
|
||||
AnnotationEvalFunction (char function, const AnnotationEval *eval)
|
||||
: m_function (function), mp_eval (eval)
|
||||
AnnotationEvalFunction (char function, const AnnotationEval *eval, size_t index)
|
||||
: m_function (function), mp_eval (eval), m_index (index)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -301,36 +385,73 @@ public:
|
|||
} else if (m_function == 'Y') {
|
||||
out = delta_y (obj, trans);
|
||||
} else if (m_function == 'U') {
|
||||
out = (trans * obj.p1 ()).x ();
|
||||
out = (trans * p1 (obj)).x ();
|
||||
} else if (m_function == 'V') {
|
||||
out = (trans * obj.p1 ()).y ();
|
||||
out = (trans * p1 (obj)).y ();
|
||||
} else if (m_function == 'P') {
|
||||
out = (trans * obj.p2 ()).x ();
|
||||
out = (trans * p2 (obj)).x ();
|
||||
} else if (m_function == 'Q') {
|
||||
out = (trans * obj.p2 ()).y ();
|
||||
out = (trans * p2 (obj)).y ();
|
||||
} else {
|
||||
out = tl::Variant ();
|
||||
}
|
||||
}
|
||||
|
||||
db::DPoint p1 (const Object &obj) const
|
||||
{
|
||||
return obj.seg_p1 (m_index);
|
||||
}
|
||||
|
||||
db::DPoint p2 (const Object &obj) const
|
||||
{
|
||||
return obj.seg_p2 (m_index);
|
||||
}
|
||||
|
||||
double
|
||||
delta_x (const Object &obj, const db::DFTrans &t) const
|
||||
{
|
||||
double dx = ((t * p2 (obj)).x () - (t * p1 (obj)).x ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dx) < 1e-5 /*micron*/) {
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
return dx;
|
||||
}
|
||||
|
||||
double
|
||||
delta_y (const Object &obj, const db::DFTrans &t) const
|
||||
{
|
||||
double dy = ((t * p2 (obj)).y () - (t * p1 (obj)).y ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dy) < 1e-5 /*micron*/) {
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
return dy;
|
||||
}
|
||||
|
||||
private:
|
||||
char m_function;
|
||||
const AnnotationEval *mp_eval;
|
||||
size_t m_index;
|
||||
};
|
||||
|
||||
std::string
|
||||
Object::formatted (const std::string &fmt, const db::DFTrans &t) const
|
||||
Object::formatted (const std::string &fmt, const db::DFTrans &t, size_t index) const
|
||||
{
|
||||
AnnotationEval eval (*this, t);
|
||||
eval.define_function ("L", new AnnotationEvalFunction('L', &eval)); // manhattan length
|
||||
eval.define_function ("D", new AnnotationEvalFunction('D', &eval)); // euclidian distance
|
||||
eval.define_function ("X", new AnnotationEvalFunction('X', &eval)); // x delta
|
||||
eval.define_function ("Y", new AnnotationEvalFunction('Y', &eval)); // y delta
|
||||
eval.define_function ("U", new AnnotationEvalFunction('U', &eval)); // p1.x
|
||||
eval.define_function ("V", new AnnotationEvalFunction('V', &eval)); // p1.y
|
||||
eval.define_function ("P", new AnnotationEvalFunction('P', &eval)); // p2.x
|
||||
eval.define_function ("Q", new AnnotationEvalFunction('Q', &eval)); // p2.y
|
||||
eval.define_function ("A", new AnnotationEvalFunction('A', &eval)); // area mm2
|
||||
eval.define_function ("L", new AnnotationEvalFunction('L', &eval, index)); // manhattan length
|
||||
eval.define_function ("D", new AnnotationEvalFunction('D', &eval, index)); // euclidian distance
|
||||
eval.define_function ("X", new AnnotationEvalFunction('X', &eval, index)); // x delta
|
||||
eval.define_function ("Y", new AnnotationEvalFunction('Y', &eval, index)); // y delta
|
||||
eval.define_function ("U", new AnnotationEvalFunction('U', &eval, index)); // p1.x
|
||||
eval.define_function ("V", new AnnotationEvalFunction('V', &eval, index)); // p1.y
|
||||
eval.define_function ("P", new AnnotationEvalFunction('P', &eval, index)); // p2.x
|
||||
eval.define_function ("Q", new AnnotationEvalFunction('Q', &eval, index)); // p2.y
|
||||
eval.define_function ("A", new AnnotationEvalFunction('A', &eval, index)); // area mm2
|
||||
return eval.interpolate (fmt);
|
||||
}
|
||||
|
||||
|
|
@ -343,6 +464,9 @@ Object::class_name () const
|
|||
void
|
||||
Object::from_string (const char *s, const char * /*base_dir*/)
|
||||
{
|
||||
m_points.clear ();
|
||||
point_list new_points;
|
||||
|
||||
tl::Extractor ex (s);
|
||||
while (! ex.at_end ()) {
|
||||
|
||||
|
|
@ -408,6 +532,14 @@ Object::from_string (const char *s, const char * /*base_dir*/)
|
|||
p.set_y (q);
|
||||
p2 (p);
|
||||
|
||||
} else if (ex.test ("pt=")) {
|
||||
|
||||
double x = 0.0, y = 0.0;
|
||||
ex.read (x);
|
||||
ex.expect (":");
|
||||
ex.read (y);
|
||||
new_points.push_back (db::DPoint (x, y));
|
||||
|
||||
} else if (ex.test ("position=")) {
|
||||
|
||||
std::string s;
|
||||
|
|
@ -518,6 +650,10 @@ Object::from_string (const char *s, const char * /*base_dir*/)
|
|||
ex.test (",");
|
||||
|
||||
}
|
||||
|
||||
if (! new_points.empty ()) {
|
||||
set_points (new_points);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
@ -529,18 +665,28 @@ Object::to_string () const
|
|||
r += tl::to_string (id ());
|
||||
r += ",";
|
||||
|
||||
r += "x1=";
|
||||
r += tl::to_string (p1 ().x ());
|
||||
r += ",";
|
||||
r += "y1=";
|
||||
r += tl::to_string (p1 ().y ());
|
||||
r += ",";
|
||||
r += "x2=";
|
||||
r += tl::to_string (p2 ().x ());
|
||||
r += ",";
|
||||
r += "y2=";
|
||||
r += tl::to_string (p2 ().y ());
|
||||
r += ",";
|
||||
if (m_points.size () > 2) {
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
r += "pt=";
|
||||
r += tl::to_string (p->x ());
|
||||
r += ":";
|
||||
r += tl::to_string (p->y ());
|
||||
r += ",";
|
||||
}
|
||||
} else {
|
||||
r += "x1=";
|
||||
r += tl::to_string (p1 ().x ());
|
||||
r += ",";
|
||||
r += "y1=";
|
||||
r += tl::to_string (p1 ().y ());
|
||||
r += ",";
|
||||
r += "x2=";
|
||||
r += tl::to_string (p2 ().x ());
|
||||
r += ",";
|
||||
r += "y2=";
|
||||
r += tl::to_string (p2 ().y ());
|
||||
r += ",";
|
||||
}
|
||||
|
||||
r += "category=";
|
||||
r += tl::to_word_or_quoted_string (category ());
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class ANT_PUBLIC Object
|
|||
{
|
||||
public:
|
||||
typedef db::coord_traits<coord_type> coord_traits;
|
||||
typedef std::vector<db::DPoint> point_list;
|
||||
|
||||
/**
|
||||
* @brief The ruler style
|
||||
|
|
@ -109,11 +110,21 @@ public:
|
|||
*/
|
||||
Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint);
|
||||
|
||||
/**
|
||||
* @brief Parametrized constructor and a list of points
|
||||
*/
|
||||
Object (const point_list &points, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint);
|
||||
|
||||
/**
|
||||
* @brief Parametrized constructor from a template
|
||||
*/
|
||||
Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::Template &d);
|
||||
|
||||
/**
|
||||
* @brief Parametrized constructor from a template and a list of points
|
||||
*/
|
||||
Object (const point_list &points, int id, const ant::Template &d);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
|
|
@ -185,8 +196,9 @@ public:
|
|||
*/
|
||||
virtual void transform (const db::DCplxTrans &t)
|
||||
{
|
||||
m_p1 = t * m_p1;
|
||||
m_p2 = t * m_p2;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p = t * *p;
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
|
||||
|
|
@ -195,8 +207,9 @@ public:
|
|||
*/
|
||||
virtual void transform (const db::DTrans &t)
|
||||
{
|
||||
m_p1 = t * m_p1;
|
||||
m_p2 = t * m_p2;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p = t * *p;
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
|
||||
|
|
@ -205,8 +218,9 @@ public:
|
|||
*/
|
||||
virtual void transform (const db::DFTrans &t)
|
||||
{
|
||||
m_p1 = t * m_p1;
|
||||
m_p2 = t * m_p2;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p = t * *p;
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
|
||||
|
|
@ -224,10 +238,11 @@ public:
|
|||
/**
|
||||
* @brief Moves the object by the given distance
|
||||
*/
|
||||
Object &move (const db::DVector &p)
|
||||
Object &move (const db::DVector &d)
|
||||
{
|
||||
m_p1 += p;
|
||||
m_p2 += p;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p += d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -265,42 +280,71 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the first definition point
|
||||
* @brief Gets the ruler's definition points
|
||||
*/
|
||||
const db::DPoint &p1 () const
|
||||
const point_list &points () const
|
||||
{
|
||||
return m_p1;
|
||||
return m_points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the ruler's definition points
|
||||
*/
|
||||
void set_points (const point_list &points);
|
||||
|
||||
/**
|
||||
* @brief Gets the first point of the indicated segment
|
||||
*/
|
||||
db::DPoint seg_p1 (size_t seg_index) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the second point of the indicated segment
|
||||
*/
|
||||
db::DPoint seg_p2 (size_t seg_index) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of segments
|
||||
*
|
||||
* The number of segments is at least 1 for backward compatibility.
|
||||
*/
|
||||
size_t segments () const
|
||||
{
|
||||
return m_points.size () < 2 ? 1 : m_points.size () - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the first definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
db::DPoint p1 () const
|
||||
{
|
||||
return seg_p1 (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the second definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
const db::DPoint &p2 () const
|
||||
db::DPoint p2 () const
|
||||
{
|
||||
return m_p2;
|
||||
return seg_p2 (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the first definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
void p1 (const db::DPoint &p)
|
||||
{
|
||||
if (!m_p1.equal (p)) {
|
||||
m_p1 = p;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
void p1 (const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Sets the second definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
void p2 (const db::DPoint &p)
|
||||
{
|
||||
if (!m_p2.equal (p)) {
|
||||
m_p2 = p;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
void p2 (const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Gets the ID of the annotation object
|
||||
|
|
@ -619,52 +663,52 @@ public:
|
|||
/**
|
||||
* @brief Gets the formatted text for the x label
|
||||
*/
|
||||
std::string text_x () const
|
||||
std::string text_x (size_t index) const
|
||||
{
|
||||
return formatted (m_fmt_x, db::DFTrans ());
|
||||
return formatted (m_fmt_x, db::DFTrans (), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the y label
|
||||
*/
|
||||
std::string text_y () const
|
||||
std::string text_y (size_t index) const
|
||||
{
|
||||
return formatted (m_fmt_y, db::DFTrans ());
|
||||
return formatted (m_fmt_y, db::DFTrans (), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the main label
|
||||
*/
|
||||
std::string text () const
|
||||
std::string text (size_t index) const
|
||||
{
|
||||
return formatted (m_fmt, db::DFTrans ());
|
||||
return formatted (m_fmt, db::DFTrans (), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the x label
|
||||
* @param t The transformation to apply to the vector before producing the text
|
||||
*/
|
||||
std::string text_x (const db::DFTrans &t) const
|
||||
std::string text_x (size_t index, const db::DFTrans &t) const
|
||||
{
|
||||
return formatted (m_fmt_x, t);
|
||||
return formatted (m_fmt_x, t, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the y label
|
||||
* @param t The transformation to apply to the vector before producing the text
|
||||
*/
|
||||
std::string text_y (const db::DFTrans &t) const
|
||||
std::string text_y (size_t index, const db::DFTrans &t) const
|
||||
{
|
||||
return formatted (m_fmt_y, t);
|
||||
return formatted (m_fmt_y, t, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the main label
|
||||
* @param t The transformation to apply to the vector before producing the text
|
||||
*/
|
||||
std::string text (const db::DFTrans &t) const
|
||||
std::string text (size_t index, const db::DFTrans &t) const
|
||||
{
|
||||
return formatted (m_fmt, t);
|
||||
return formatted (m_fmt, t, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -695,7 +739,7 @@ protected:
|
|||
virtual void property_changed ();
|
||||
|
||||
private:
|
||||
db::DPoint m_p1, m_p2;
|
||||
point_list m_points;
|
||||
int m_id;
|
||||
std::string m_fmt_x;
|
||||
std::string m_fmt_y;
|
||||
|
|
@ -710,7 +754,7 @@ private:
|
|||
alignment_type m_xlabel_xalign, m_xlabel_yalign;
|
||||
alignment_type m_ylabel_xalign, m_ylabel_yalign;
|
||||
|
||||
std::string formatted (const std::string &fmt, const db::DFTrans &trans) const;
|
||||
std::string formatted (const std::string &fmt, const db::DFTrans &trans, size_t index) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "antPropertiesPage.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layQtTools.h"
|
||||
#include "tlException.h"
|
||||
|
||||
namespace ant
|
||||
{
|
||||
|
|
@ -33,7 +34,7 @@ namespace ant
|
|||
// PropertiesPage implementation
|
||||
|
||||
PropertiesPage::PropertiesPage (ant::Service *rulers, db::Manager *manager, QWidget *parent)
|
||||
: lay::PropertiesPage (parent, manager, rulers), mp_rulers (rulers), m_enable_cb_callback (true)
|
||||
: lay::PropertiesPage (parent, manager, rulers), mp_rulers (rulers), m_enable_cb_callback (true), m_in_text_changed (false)
|
||||
{
|
||||
mp_rulers->get_selection (m_selection);
|
||||
m_pos = m_selection.begin ();
|
||||
|
|
@ -56,8 +57,10 @@ PropertiesPage::PropertiesPage (ant::Service *rulers, db::Manager *manager, QWid
|
|||
connect (fmt_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (fmt_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (fmt_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (x0, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (x1, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (x2, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (y0, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (y1, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (y2, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
|
||||
|
|
@ -71,6 +74,8 @@ PropertiesPage::PropertiesPage (ant::Service *rulers, db::Manager *manager, QWid
|
|||
connect (ylabel_xalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (ylabel_yalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
|
||||
connect (points_edit, SIGNAL (textChanged ()), this, SLOT (text_changed ()));
|
||||
|
||||
} else {
|
||||
|
||||
fmt_le->setReadOnly (true);
|
||||
|
|
@ -172,6 +177,80 @@ PropertiesPage::get_points (db::DPoint &p1, db::DPoint &p2)
|
|||
p2 = db::DPoint (dx2, dy2);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::get_point (db::DPoint &p)
|
||||
{
|
||||
double dx = 0.0, dy = 0.0;
|
||||
bool has_error = false;
|
||||
|
||||
try {
|
||||
tl::from_string_ext (tl::to_string (x0->text ()), dx);
|
||||
lay::indicate_error (x0, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x0, &ex);
|
||||
has_error = true;
|
||||
}
|
||||
|
||||
try {
|
||||
tl::from_string_ext (tl::to_string (y0->text ()), dy);
|
||||
lay::indicate_error (y0, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y0, &ex);
|
||||
has_error = true;
|
||||
}
|
||||
|
||||
if (has_error) {
|
||||
throw tl::Exception (tl::to_string (tr ("At least one value is invalid - see highlighted entry fields")));
|
||||
}
|
||||
|
||||
p = db::DPoint (dx, dy);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::get_points (ant::Object::point_list &points)
|
||||
{
|
||||
std::string coordinates = tl::to_string (points_edit->toPlainText ());
|
||||
points.clear ();
|
||||
|
||||
try {
|
||||
|
||||
tl::Extractor ex (coordinates.c_str ());
|
||||
while (! ex.at_end ()) {
|
||||
double x = 0.0, y = 0.0;
|
||||
ex.read (x);
|
||||
ex.test (",");
|
||||
ex.read (y);
|
||||
ex.test (";");
|
||||
ex.test (",");
|
||||
points.push_back (db::DPoint (x, y));
|
||||
}
|
||||
|
||||
lay::indicate_error (points_edit, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (points_edit, &ex);
|
||||
throw tl::Exception (tl::to_string (tr ("At least one value is invalid - see highlighted entry fields")));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::text_changed ()
|
||||
{
|
||||
if (m_in_text_changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
m_in_text_changed = true;
|
||||
update_with (get_object ());
|
||||
emit edited ();
|
||||
m_in_text_changed = false;
|
||||
} catch (...) {
|
||||
m_in_text_changed = false;
|
||||
// ignore exceptions - the edit field will be highlighted anyway
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::snap_to_layout_clicked ()
|
||||
{
|
||||
|
|
@ -296,32 +375,74 @@ void
|
|||
PropertiesPage::update ()
|
||||
{
|
||||
mp_rulers->highlight (std::distance (m_selection.begin (), m_pos));
|
||||
update_with (current ());
|
||||
}
|
||||
|
||||
fmt_le->setText (tl::to_qstring (current ().fmt ()));
|
||||
fmt_x_le->setText (tl::to_qstring (current ().fmt_x ()));
|
||||
fmt_y_le->setText (tl::to_qstring (current ().fmt_y ()));
|
||||
style_cb->setCurrentIndex (current ().style ());
|
||||
outline_cb->setCurrentIndex (current ().outline ());
|
||||
void
|
||||
PropertiesPage::update_with (const ant::Object &obj)
|
||||
{
|
||||
fmt_le->setText (tl::to_qstring (obj.fmt ()));
|
||||
fmt_x_le->setText (tl::to_qstring (obj.fmt_x ()));
|
||||
fmt_y_le->setText (tl::to_qstring (obj.fmt_y ()));
|
||||
style_cb->setCurrentIndex (obj.style ());
|
||||
outline_cb->setCurrentIndex (obj.outline ());
|
||||
|
||||
x1->setText (tl::to_qstring (tl::micron_to_string (current ().p1 ().x ())));
|
||||
main_position->setCurrentIndex (obj.main_position ());
|
||||
main_xalign->setCurrentIndex (obj.main_xalign ());
|
||||
main_yalign->setCurrentIndex (obj.main_yalign ());
|
||||
xlabel_xalign->setCurrentIndex (obj.xlabel_xalign ());
|
||||
xlabel_yalign->setCurrentIndex (obj.xlabel_yalign ());
|
||||
ylabel_xalign->setCurrentIndex (obj.ylabel_xalign ());
|
||||
ylabel_yalign->setCurrentIndex (obj.ylabel_yalign ());
|
||||
|
||||
int tab = 2;
|
||||
if (obj.points ().size () == 1) {
|
||||
tab = 0;
|
||||
} else if (obj.points ().size () == 2) {
|
||||
tab = 1;
|
||||
}
|
||||
|
||||
segments_tab->setTabEnabled (0, tab == 0);
|
||||
segments_tab->setTabEnabled (1, tab == 1);
|
||||
|
||||
if (! m_in_text_changed) {
|
||||
segments_tab->setCurrentIndex (tab);
|
||||
}
|
||||
|
||||
point_list->clear ();
|
||||
for (auto p = obj.points ().begin (); p != obj.points ().end (); ++p) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem (point_list);
|
||||
item->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (tl::to_string (p->x ()))));
|
||||
item->setData (1, Qt::DisplayRole, QVariant (tl::to_qstring (tl::to_string (p->y ()))));
|
||||
}
|
||||
|
||||
if (! m_in_text_changed) {
|
||||
std::string text;
|
||||
for (auto p = obj.points ().begin (); p != obj.points ().end (); ++p) {
|
||||
text += tl::to_string (p->x ());
|
||||
text += ", ";
|
||||
text += tl::to_string (p->y ());
|
||||
text += "\n";
|
||||
}
|
||||
points_edit->setPlainText (tl::to_qstring (text));
|
||||
}
|
||||
|
||||
x0->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().x ())));
|
||||
x0->setCursorPosition (0);
|
||||
y0->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().y ())));
|
||||
y0->setCursorPosition (0);
|
||||
|
||||
x1->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().x ())));
|
||||
x1->setCursorPosition (0);
|
||||
x2->setText (tl::to_qstring (tl::micron_to_string (current ().p2 ().x ())));
|
||||
x2->setText (tl::to_qstring (tl::micron_to_string (obj.p2 ().x ())));
|
||||
x2->setCursorPosition (0);
|
||||
y1->setText (tl::to_qstring (tl::micron_to_string (current ().p1 ().y ())));
|
||||
y1->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().y ())));
|
||||
y1->setCursorPosition (0);
|
||||
y2->setText (tl::to_qstring (tl::micron_to_string (current ().p2 ().y ())));
|
||||
y2->setText (tl::to_qstring (tl::micron_to_string (obj.p2 ().y ())));
|
||||
y2->setCursorPosition (0);
|
||||
|
||||
main_position->setCurrentIndex (current ().main_position ());
|
||||
main_xalign->setCurrentIndex (current ().main_xalign ());
|
||||
main_yalign->setCurrentIndex (current ().main_yalign ());
|
||||
xlabel_xalign->setCurrentIndex (current ().xlabel_xalign ());
|
||||
xlabel_yalign->setCurrentIndex (current ().xlabel_yalign ());
|
||||
ylabel_xalign->setCurrentIndex (current ().ylabel_xalign ());
|
||||
ylabel_yalign->setCurrentIndex (current ().ylabel_yalign ());
|
||||
|
||||
double sx = (current ().p2 ().x () - current ().p1 ().x ());
|
||||
double sy = (current ().p2 ().y () - current ().p1 ().y ());
|
||||
double sx = (obj.p2 ().x () - obj.p1 ().x ());
|
||||
double sy = (obj.p2 ().y () - obj.p1 ().y ());
|
||||
dx->setText (tl::to_qstring (tl::micron_to_string (sx)));
|
||||
dx->setCursorPosition (0);
|
||||
dy->setText (tl::to_qstring (tl::micron_to_string (sy)));
|
||||
|
|
@ -339,9 +460,13 @@ PropertiesPage::readonly ()
|
|||
void
|
||||
PropertiesPage::apply ()
|
||||
{
|
||||
// only adjust the values if the text has changed
|
||||
db::DPoint p1, p2;
|
||||
get_points (p1, p2);
|
||||
mp_rulers->change_ruler (*m_pos, get_object ());
|
||||
}
|
||||
|
||||
ant::Object
|
||||
PropertiesPage::get_object ()
|
||||
{
|
||||
ant::Object ruler;
|
||||
|
||||
std::string fmt = tl::to_string (fmt_le->text ());
|
||||
std::string fmt_x = tl::to_string (fmt_x_le->text ());
|
||||
|
|
@ -349,7 +474,26 @@ PropertiesPage::apply ()
|
|||
Object::style_type style = Object::style_type (style_cb->currentIndex ());
|
||||
Object::outline_type outline = Object::outline_type (outline_cb->currentIndex ());
|
||||
|
||||
ant::Object ruler (p1, p2, current ().id (), fmt_x, fmt_y, fmt, style, outline, current ().snap (), current ().angle_constraint ());
|
||||
if (segments_tab->currentIndex () == 0 || segments_tab->currentIndex () == 1) {
|
||||
|
||||
db::DPoint p1, p2;
|
||||
if (segments_tab->currentIndex () == 0) {
|
||||
get_points (p1, p2);
|
||||
} else {
|
||||
get_point (p1);
|
||||
p2 = p1;
|
||||
}
|
||||
|
||||
ruler = ant::Object (p1, p2, current ().id (), fmt_x, fmt_y, fmt, style, outline, current ().snap (), current ().angle_constraint ());
|
||||
|
||||
} else if (segments_tab->currentIndex () == 2 || segments_tab->currentIndex () == 3) {
|
||||
|
||||
ant::Object::point_list points;
|
||||
get_points (points);
|
||||
|
||||
ruler = ant::Object (points, current ().id (), fmt_x, fmt_y, fmt, style, outline, current ().snap (), current ().angle_constraint ());
|
||||
|
||||
}
|
||||
|
||||
ruler.set_main_position (Object::position_type (main_position->currentIndex ()));
|
||||
ruler.set_main_xalign (Object::alignment_type (main_xalign->currentIndex ()));
|
||||
|
|
@ -361,7 +505,7 @@ PropertiesPage::apply ()
|
|||
|
||||
ruler.set_category (current ().category ());
|
||||
|
||||
mp_rulers->change_ruler (*m_pos, ruler);
|
||||
return ruler;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,20 +52,26 @@ public:
|
|||
virtual void update ();
|
||||
virtual void leave ();
|
||||
virtual bool readonly ();
|
||||
virtual void apply ();
|
||||
virtual void apply ();
|
||||
|
||||
private slots:
|
||||
void swap_points_clicked ();
|
||||
void snap_to_layout_clicked ();
|
||||
void text_changed ();
|
||||
|
||||
private:
|
||||
std::vector <ant::Service::obj_iterator> m_selection;
|
||||
std::vector <ant::Service::obj_iterator>::iterator m_pos;
|
||||
ant::Service *mp_rulers;
|
||||
bool m_enable_cb_callback;
|
||||
bool m_in_text_changed;
|
||||
|
||||
const ant::Object ¤t () const;
|
||||
void get_points(db::DPoint &p1, db::DPoint &p2);
|
||||
void get_points (db::DPoint &p1, db::DPoint &p2);
|
||||
void get_point (db::DPoint &p);
|
||||
void get_points (ant::Object::point_list &points);
|
||||
void update_with (const ant::Object &obj);
|
||||
ant::Object get_object ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -570,21 +570,23 @@ draw_ellipse (const db::DPoint &q1,
|
|||
}
|
||||
|
||||
void
|
||||
draw_ruler (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
draw_ruler_segment (const ant::Object &ruler, size_t index, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
db::DPoint p1 = ruler.seg_p1 (index), p2 = ruler.seg_p2 (index);
|
||||
|
||||
// round the starting point, shift both, and round the end point
|
||||
std::pair <db::DPoint, db::DPoint> v = lay::snap (trans * ruler.p1 (), trans * ruler.p2 ());
|
||||
std::pair <db::DPoint, db::DPoint> v = lay::snap (trans * p1, trans * p2);
|
||||
db::DPoint q1 = v.first;
|
||||
db::DPoint q2 = v.second;
|
||||
|
||||
bool xy_swapped = ((trans.rot () % 2) != 0);
|
||||
double lu = ruler.p1 ().double_distance (ruler.p2 ());
|
||||
double lu = p1.double_distance (p2);
|
||||
int min_tick_spc = int (0.5 + 20 / renderer.resolution ()); // min tick spacing in canvas units
|
||||
double mu = double (min_tick_spc) / trans.ctrans (1.0);
|
||||
|
||||
if (ruler.outline () == Object::OL_diag) {
|
||||
draw_ruler (q1, q2, lu, mu, sel, q2.x () < q1.x (), ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (), q2.x () < q1.x (), ruler.style (), ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), q2.x () < q1.x (), ruler.style (), ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
}
|
||||
|
||||
if ((!xy_swapped && (ruler.outline () == Object::OL_xy || ruler.outline () == Object::OL_diag_xy)) ||
|
||||
|
|
@ -594,12 +596,12 @@ draw_ruler (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay
|
|||
|
||||
if (ruler.outline () == Object::OL_diag_xy || ruler.outline () == Object::OL_diag_yx) {
|
||||
draw_ruler (q1, q2, lu, mu, sel, !r, ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (), !r, ruler.style (), ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ruler.style (), ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
}
|
||||
draw_ruler (q1, db::DPoint (q2.x (), q1.y ()), lu, mu, sel, r, ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (db::DPoint (q2.x (), q1.y ()), q2, lu, mu, sel, r, ruler.style (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -610,12 +612,12 @@ draw_ruler (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay
|
|||
|
||||
if (ruler.outline () == Object::OL_diag_xy || ruler.outline () == Object::OL_diag_yx) {
|
||||
draw_ruler (q1, q2, lu, mu, sel, !r, ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (), !r, ruler.style (), ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ruler.style (), ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
}
|
||||
draw_ruler (q1, db::DPoint (q1.x (), q2.y ()), lu, mu, sel, r, ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q1.x (), q2.y ()), lu, ruler.text_y (trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q1.x (), q2.y ()), lu, ruler.text_y (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (db::DPoint (q1.x (), q2.y ()), q2, lu, mu, sel, r, ruler.style (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q1.x (), q2.y ()), q2, lu, ruler.text_x (trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q1.x (), q2.y ()), q2, lu, ruler.text_x (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -624,34 +626,43 @@ draw_ruler (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay
|
|||
bool r = (q2.x () > q1.x ()) ^ (q2.y () < q1.y ());
|
||||
|
||||
draw_ruler (q1, db::DPoint (q2.x (), q1.y ()), lu, mu, sel, r, ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (db::DPoint (q2.x (), q1.y ()), q2, lu, mu, sel, r, ruler.style (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (q1, db::DPoint (q1.x (), q2.y ()), lu, mu, sel, !r, ruler.style (), bitmap, renderer);
|
||||
draw_ruler (db::DPoint (q1.x (), q2.y ()), q2, lu, mu, sel, !r, ruler.style (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
|
||||
} else if (ruler.outline () == Object::OL_ellipse) {
|
||||
|
||||
bool r = (q2.x () > q1.x ()) ^ (q2.y () < q1.y ());
|
||||
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
|
||||
draw_ellipse (q1, q2, lu, sel, bitmap, renderer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
is_selected (const ant::Object &ruler, const db::DPoint &pos, double enl, double &distance)
|
||||
void
|
||||
draw_ruler (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
for (size_t index = 0; index < ruler.segments (); ++index) {
|
||||
draw_ruler_segment (ruler, index, trans, sel, bitmap, renderer);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
is_selected (const ant::Object &ruler, size_t index, const db::DPoint &pos, double enl, double &distance)
|
||||
{
|
||||
db::DPoint p1 = ruler.seg_p1 (index), p2 = ruler.seg_p2 (index);
|
||||
db::DBox b (p1, p2);
|
||||
|
||||
if (ruler.outline () == ant::Object::OL_ellipse) {
|
||||
|
||||
// special handling of the (non-degenerated) ellipse case
|
||||
db::DBox b (ruler.p1 (), ruler.p2 ());
|
||||
|
||||
if (b.height () > 1e-6 && b.width () > 1e-6) {
|
||||
|
||||
double dx = (pos.x () - b.center ().x ()) / (b.width () * 0.5);
|
||||
|
|
@ -674,8 +685,6 @@ is_selected (const ant::Object &ruler, const db::DPoint &pos, double enl, double
|
|||
|
||||
}
|
||||
|
||||
db::DBox b (ruler.p1 (), ruler.p2 ());
|
||||
|
||||
// enlarge this box by some pixels
|
||||
b.enlarge (db::DVector (enl, enl));
|
||||
|
||||
|
|
@ -717,10 +726,23 @@ is_selected (const ant::Object &ruler, const db::DPoint &pos, double enl, double
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_selected (const ant::Object &ruler, const db::DPoint &pos, double enl, double &distance)
|
||||
{
|
||||
bool any = false;
|
||||
for (size_t index = 0; index < ruler.segments (); ++index) {
|
||||
// NOTE: we check *all* since distance is updated herein.
|
||||
if (is_selected (ruler, index, pos, enl, distance)) {
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_selected (const ant::Object &ruler, const db::DBox &box, double /*enl*/)
|
||||
{
|
||||
return (box.contains (ruler.p1 ()) && box.contains (ruler.p2 ()));
|
||||
return ruler.box ().inside (box);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2180,7 +2202,11 @@ Service::display_status (bool transient)
|
|||
if (! transient) {
|
||||
msg = tl::to_string (tr ("selected: "));
|
||||
}
|
||||
msg += tl::sprintf (tl::to_string (tr ("annotation(d=%s x=%s y=%s)")), ruler->text (), ruler->text_x (), ruler->text_y ());
|
||||
if (ruler->segments () > 1) {
|
||||
msg += tl::sprintf (tl::to_string (tr ("annotation(d=%s x=%s y=%s ...)")), ruler->text (0), ruler->text_x (0), ruler->text_y (0));
|
||||
} else {
|
||||
msg += tl::sprintf (tl::to_string (tr ("annotation(d=%s x=%s y=%s)")), ruler->text (0), ruler->text_x (0), ruler->text_y (0));
|
||||
}
|
||||
view ()->message (msg);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,6 +236,13 @@ static AnnotationRef create_measure_ruler (lay::LayoutViewBase *view, const db::
|
|||
}
|
||||
}
|
||||
|
||||
static AnnotationRef *ant_from_s (const std::string &s)
|
||||
{
|
||||
std::unique_ptr<AnnotationRef> aref (new AnnotationRef ());
|
||||
aref->from_string (s.c_str ());
|
||||
return aref.release ();
|
||||
}
|
||||
|
||||
static int get_style (const AnnotationRef *obj)
|
||||
{
|
||||
return int (obj->style ());
|
||||
|
|
@ -704,27 +711,80 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("p1", (const db::DPoint & (AnnotationRef::*) () const) &AnnotationRef::p1,
|
||||
gsi::method ("points", &AnnotationRef::points,
|
||||
"@brief Gets the points of the ruler\n"
|
||||
"A single-segmented ruler has two points. Rulers with more points "
|
||||
"have more segments correspondingly. Note that the point list may have one point "
|
||||
"only (single-point ruler) or may even be empty.\n"
|
||||
"\n"
|
||||
"Use \\points= to set the segment points. Use \\segments to get the number of "
|
||||
"segments and \\seg_p1 and \\seg_p2 to get the first and second point of one segment.\n"
|
||||
"\n"
|
||||
"Multi-segmented rulers have been introduced in version 0.28"
|
||||
) +
|
||||
gsi::method ("points=", &AnnotationRef::set_points, gsi::arg ("points"),
|
||||
"@brief Sets the points for a (potentially) multi-segmented ruler\n"
|
||||
"See \\points for a description of multi-segmented rulers. "
|
||||
"The list of points passed to this method is cleaned from duplicates before being "
|
||||
"stored inside the ruler.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("segments", &AnnotationRef::segments,
|
||||
"@brief Gets the number of segments.\n"
|
||||
"This method returns the number of segments the ruler is made up. Even though the "
|
||||
"ruler can be one or even zero points, the number of segments is at least 1.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("seg_p1", &AnnotationRef::seg_p1, gsi::arg ("segment_index"),
|
||||
"@brief Gets the first point of the given segment.\n"
|
||||
"The segment is indicated by the segment index which is a number between 0 and \\segments-1.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("seg_p2", &AnnotationRef::seg_p2, gsi::arg ("segment_index"),
|
||||
"@brief Gets the second point of the given segment.\n"
|
||||
"The segment is indicated by the segment index which is a number between 0 and \\segments-1.\n"
|
||||
"The second point of a segment is also the first point of the following segment if there is one.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("p1", (db::DPoint (AnnotationRef::*) () const) &AnnotationRef::p1,
|
||||
"@brief Gets the first point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points or \\seg_p1 to retrieve the points of the ruler segments.\n"
|
||||
"\n"
|
||||
"@return The first point\n"
|
||||
) +
|
||||
gsi::method ("p2", (const db::DPoint & (AnnotationRef::*) () const) &AnnotationRef::p2,
|
||||
gsi::method ("p2", (db::DPoint (AnnotationRef::*) () const) &AnnotationRef::p2,
|
||||
"@brief Gets the second point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points or \\seg_p1 to retrieve the points of the ruler segments.\n"
|
||||
"\n"
|
||||
"@return The second point\n"
|
||||
) +
|
||||
gsi::method ("p1=", (void (AnnotationRef::*) (const db::DPoint &)) &AnnotationRef::p1, gsi::arg ("point"),
|
||||
"@brief Sets the first point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points= to specify the ruler segments.\n"
|
||||
) +
|
||||
gsi::method ("p2=", (void (AnnotationRef::*) (const db::DPoint &)) &AnnotationRef::p2, gsi::arg ("point"),
|
||||
"@brief Sets the second point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points= to specify the ruler segments.\n"
|
||||
) +
|
||||
gsi::method ("box", &AnnotationRef::box,
|
||||
"@brief Gets the bounding box of the object (not including text)\n"
|
||||
|
|
@ -924,14 +984,17 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"@brief Returns the angle constraint attribute\n"
|
||||
"See \\angle_constraint= for a more detailed description."
|
||||
) +
|
||||
gsi::method ("text_x", (std::string (AnnotationRef::*)() const) &AnnotationRef::text_x,
|
||||
"@brief Returns the formatted text for the x-axis label"
|
||||
gsi::method ("text_x", (std::string (AnnotationRef::*)(size_t index) const) &AnnotationRef::text_x, gsi::arg ("index", 0),
|
||||
"@brief Returns the formatted text for the x-axis label\n"
|
||||
"The index parameter indicates which segment to use (0 is the first one). It has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("text_y", (std::string (AnnotationRef::*)() const) &AnnotationRef::text_y,
|
||||
"@brief Returns the formatted text for the y-axis label"
|
||||
gsi::method ("text_y", (std::string (AnnotationRef::*)(size_t index) const) &AnnotationRef::text_y, gsi::arg ("index", 0),
|
||||
"@brief Returns the formatted text for the y-axis label\n"
|
||||
"The index parameter indicates which segment to use (0 is the first one). It has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("text", (std::string (AnnotationRef::*)() const) &AnnotationRef::text,
|
||||
"@brief Returns the formatted text for the main label"
|
||||
gsi::method ("text", (std::string (AnnotationRef::*)(size_t index) const) &AnnotationRef::text, gsi::arg ("index", 0),
|
||||
"@brief Returns the formatted text for the main label\n"
|
||||
"The index parameter indicates which segment to use (0 is the first one). It has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("id", (int (AnnotationRef::*)() const) &AnnotationRef::id,
|
||||
"@brief Returns the annotation's ID"
|
||||
|
|
@ -953,6 +1016,12 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This method was introduced in version 0.19."
|
||||
) +
|
||||
gsi::constructor ("from_s", &ant_from_s, gsi::arg ("s"),
|
||||
"@brief Creates a ruler from a string representation\n"
|
||||
"This function creates a ruler from the string returned by \\to_s.\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("==", &AnnotationRef::operator==, gsi::arg ("other"),
|
||||
"@brief Equality operator\n"
|
||||
) +
|
||||
|
|
|
|||
Loading…
Reference in New Issue