WIP: first steps towards multi-segment rulers

This commit is contained in:
Matthias Koefferlein 2022-09-26 23:37:22 +02:00
parent 7b4b345cf4
commit d1b7cd1f8f
7 changed files with 1280 additions and 653 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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 ());

View File

@ -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;
};
}

View File

@ -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;
}
}

View File

@ -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 &current () 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 ();
};
}

View File

@ -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);
}

View File

@ -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"
) +