Ruler enhancements

* There is a ruler mode now
* Ruler templates can have categories
* Ruler templates can be defined from RBA/pya
* Single-click annotations are implemented already
This commit is contained in:
Matthias Koefferlein 2017-06-28 23:17:02 +02:00
parent e30f1b6a34
commit 919de1af01
10 changed files with 569 additions and 277 deletions

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>668</width>
<height>373</height>
<height>410</height>
</rect>
</property>
<property name="windowTitle">
@ -169,7 +169,7 @@
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<widget class="QFrame" name="mode_cb">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -192,51 +192,13 @@
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string> ... position</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="t_snap_cbx">
<property name="toolTip">
<string>If checked, snap to edges or vertices of objects unless disabled above</string>
</property>
<property name="text">
<string>Snap to objects</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Outline</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="fmt_le">
<property name="toolTip">
<string>Specify the main label format</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Label format</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Angle constraints</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="fmt_x_le">
<property name="toolTip">
@ -244,18 +206,122 @@
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_16">
<item row="8" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Style</string>
<string>Angle constraints</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="fmt_y_le">
<property name="toolTip">
<string>Specify the y label format (applicable only for outline modes that have a vertical component, i.e. box)</string>
<item row="5" column="1">
<widget class="QFrame" name="frame_6">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>148</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_28">
<property name="text">
<string>H</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="ylabel_xalign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>H. center</string>
</property>
</item>
<item>
<property name="text">
<string>Left</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_27">
<property name="text">
<string>V</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="ylabel_yalign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>V. center</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom</string>
</property>
</item>
<item>
<property name="text">
<string>Top</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
@ -433,64 +499,41 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string> ... position</string>
<string>X label format</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="t_angle_cb">
<property name="toolTip">
<string>Override the global angle constraint setting for this type of rulers</string>
</property>
<item>
<property name="text">
<string>Any angle</string>
</property>
</item>
<item>
<property name="text">
<string>Diagonal</string>
</property>
</item>
<item>
<property name="text">
<string>Orthogonal</string>
</property>
</item>
<item>
<property name="text">
<string>Horizontal only</string>
</property>
</item>
<item>
<property name="text">
<string>Vertical only</string>
</property>
</item>
<item>
<property name="text">
<string>Use global setting</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Y label format</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<item row="11" column="0" colspan="2">
<widget class="QLabel" name="help_label">
<property name="text">
<string>&lt;html&gt;(See &lt;a href=&quot;int:/manual/ruler_properties.xml&quot;&gt;here&lt;/a&gt; for a description of the properties)&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="fmt_y_le">
<property name="toolTip">
<string>Specify the y label format (applicable only for outline modes that have a vertical component, i.e. box)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Label format</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Style</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="outline_cb">
<property name="toolTip">
@ -533,67 +576,81 @@
</item>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="style_cb">
<property name="toolTip">
<string>Specify style of the ruler template</string>
</property>
<item>
<property name="text">
<string>Ruler</string>
</property>
</item>
<item>
<property name="text">
<string>Arrow at end</string>
</property>
</item>
<item>
<property name="text">
<string>Arrow at start</string>
</property>
</item>
<item>
<property name="text">
<string>Arrow at both ends</string>
</property>
</item>
<item>
<property name="text">
<string>Plain line</string>
</property>
</item>
<item>
<property name="text">
<string>Cross at end</string>
</property>
</item>
<item>
<property name="text">
<string>Cross at start</string>
</property>
</item>
<item>
<property name="text">
<string>Cross at both ends</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<item row="7" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>X label format</string>
<string>Outline</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<item row="10" column="1">
<widget class="QCheckBox" name="t_snap_cbx">
<property name="toolTip">
<string>If checked, snap to edges or vertices of objects unless disabled above</string>
</property>
<property name="text">
<string>Snap to objects</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="fmt_le">
<property name="toolTip">
<string>Specify the main label format</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Y label format</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string> ... position</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="t_angle_cb">
<property name="toolTip">
<string>Override the global angle constraint setting for this type of rulers</string>
</property>
<item>
<property name="text">
<string>Any angle</string>
</property>
</item>
<item>
<property name="text">
<string>Diagonal</string>
</property>
</item>
<item>
<property name="text">
<string>Orthogonal</string>
</property>
</item>
<item>
<property name="text">
<string>Horizontal only</string>
</property>
</item>
<item>
<property name="text">
<string>Vertical only</string>
</property>
</item>
<item>
<property name="text">
<string>Use global setting</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QFrame" name="frame_5">
<property name="frameShape">
@ -705,115 +762,84 @@
</layout>
</widget>
</item>
<item row="5" column="1">
<widget class="QFrame" name="frame_6">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<item row="6" column="1">
<widget class="QComboBox" name="style_cb">
<property name="toolTip">
<string>Specify style of the ruler template</string>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<item>
<property name="text">
<string>Ruler</string>
</property>
</item>
<item>
<property name="text">
<string>Arrow at end</string>
</property>
</item>
<item>
<property name="text">
<string>Arrow at start</string>
</property>
</item>
<item>
<property name="text">
<string>Arrow at both ends</string>
</property>
</item>
<item>
<property name="text">
<string>Plain line</string>
</property>
</item>
<item>
<property name="text">
<string>Cross at end</string>
</property>
</item>
<item>
<property name="text">
<string>Cross at start</string>
</property>
</item>
<item>
<property name="text">
<string>Cross at both ends</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string> ... position</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</widget>
</item>
<item row="9" column="1">
<widget class="QComboBox" name="t_mode_cb">
<item>
<property name="text">
<string>Normal</string>
</property>
<property name="topMargin">
<number>0</number>
</item>
<item>
<property name="text">
<string>Single click (both points will be equal)</string>
</property>
<property name="rightMargin">
<number>0</number>
</item>
<item>
<property name="text">
<string>Auto measure (points will be set automatically)</string>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>148</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_28">
<property name="text">
<string>H</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="ylabel_xalign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>H. center</string>
</property>
</item>
<item>
<property name="text">
<string>Left</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_27">
<property name="text">
<string>V</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="ylabel_yalign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>V. center</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom</string>
</property>
</item>
<item>
<property name="text">
<string>Top</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
</layout>

View File

@ -230,6 +230,35 @@ AlignmentConverter::from_string (const std::string &s, ant::Object::alignment_ty
}
}
std::string
RulerModeConverter::to_string (ant::Template::ruler_mode_type m)
{
if (m == ant::Template::RulerNormal) {
return "normal";
} else if (m == ant::Template::RulerSingleClick) {
return "single_click";
} else if (m == ant::Template::RulerAutoMetric) {
return "auto_metric";
} else {
return "normal";
}
}
void
RulerModeConverter::from_string (const std::string &s, ant::Template::ruler_mode_type &a)
{
std::string t (tl::trim (s));
if (t == "normal") {
a = ant::Template::RulerNormal;
} else if (t == "single_click") {
a = ant::Template::RulerSingleClick;
} else if (t == "auto_metric") {
a = ant::Template::RulerAutoMetric;
} else {
a = ant::Template::RulerNormal;
}
}
std::string
TemplatesConverter::to_string (const std::vector <ant::Template> &t)
{

View File

@ -81,6 +81,12 @@ struct AlignmentConverter
void from_string (const std::string &s, ant::Object::alignment_type &a);
};
struct RulerModeConverter
{
std::string to_string (ant::Template::ruler_mode_type a);
void from_string (const std::string &s, ant::Template::ruler_mode_type &a);
};
struct TemplatesConverter
{
std::string to_string (const std::vector <ant::Template> &t);

View File

@ -355,6 +355,7 @@ ConfigPage4::show ()
mp_ui->outline_cb->setCurrentIndex ((unsigned int) m_ruler_templates [m_current_template].outline ());
mp_ui->t_angle_cb->setCurrentIndex ((unsigned int) m_ruler_templates [m_current_template].angle_constraint ());
mp_ui->t_snap_cbx->setChecked (m_ruler_templates [m_current_template].snap ());
mp_ui->t_mode_cb->setCurrentIndex ((unsigned int) m_ruler_templates [m_current_template].mode ());
mp_ui->main_position->setCurrentIndex ((unsigned int) m_ruler_templates [m_current_template].main_position ());
mp_ui->main_xalign->setCurrentIndex ((unsigned int) m_ruler_templates [m_current_template].main_xalign ());
@ -385,6 +386,9 @@ ConfigPage4::commit ()
lay::angle_constraint_type ac = lay::angle_constraint_type (mp_ui->t_angle_cb->currentIndex ());
m_ruler_templates [m_current_template].angle_constraint (ac);
ant::Template::ruler_mode_type mode = ant::Template::ruler_mode_type (mp_ui->t_mode_cb->currentIndex ());
m_ruler_templates [m_current_template].set_mode (mode);
m_ruler_templates [m_current_template].snap (mp_ui->t_snap_cbx->isChecked ());
m_ruler_templates [m_current_template].set_main_position (Object::position_type (mp_ui->main_position->currentIndex ()));

View File

@ -63,6 +63,7 @@ Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::T
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 ()),

View File

@ -125,7 +125,7 @@ draw_ruler (const db::DPoint &q1,
double arrow_length = 12 / renderer.resolution ();
double sel_width = 2 / renderer.resolution ();
if (length_u < 1e-5 /*micron*/) {
if (length_u < 1e-5 /*micron*/ && style != ant::Object::STY_cross_both && style != ant::Object::STY_cross_end && style != ant::Object::STY_cross_start) {
if (sel) {
@ -153,7 +153,7 @@ draw_ruler (const db::DPoint &q1,
// normal and unit vector
double len = q1.double_distance (q2);
if (style == ant::Object::STY_arrow_end && len < double (arrow_length) * 1.2) {
if ((style == ant::Object::STY_arrow_end || style == ant::Object::STY_arrow_start) && len < double (arrow_length) * 1.2) {
arrow_length = len / 1.2;
arrow_width = arrow_length * 2.0 / 3.0;
} else if (style == ant::Object::STY_arrow_both && len < double (arrow_length) * 2.4) {
@ -165,7 +165,7 @@ draw_ruler (const db::DPoint &q1,
if (len > 1e-10) {
qq *= 1.0 / len;
} else {
qq = db::DVector (1.0, 0.0);
qq = db::DVector (0.0, 1.0);
}
if (!right) {
qq = -qq;
@ -340,7 +340,7 @@ draw_text (const db::DPoint &q1,
pos = ant::Object::POS_p2;
}
if (length_u < 1e-5 /*micron*/) {
if (length_u < 1e-5 /*micron*/ && style != ant::Object::STY_cross_both && style != ant::Object::STY_cross_end && style != ant::Object::STY_cross_start) {
renderer.draw (db::DBox (q1, q1),
label,
@ -357,7 +357,7 @@ draw_text (const db::DPoint &q1,
// normal and unit vector
double len = q1.double_distance (q2);
if (style == ant::Object::STY_arrow_end && len < double (arrow_length) * 1.2) {
if ((style == ant::Object::STY_arrow_end || style == ant::Object::STY_arrow_start) && len < double (arrow_length) * 1.2) {
arrow_length = len / 1.2;
arrow_width = arrow_length * 2.0 / 3.0;
} else if (style == ant::Object::STY_arrow_both && len < double (arrow_length) * 2.4) {
@ -369,17 +369,26 @@ draw_text (const db::DPoint &q1,
if (len > 1e-10) {
qq *= 1.0 / len;
} else {
qq = db::DVector (1.0, 0.0);
qq = db::DVector (0.0, 1.0);
}
if (!right) {
qq = -qq;
}
db::DVector qu = q2 - q1;
if (len > 1e-10) {
qu *= 1.0 / len;
} else {
qu = db::DVector (1.0, 0.0);
}
db::HAlign text_halign = db::HAlignCenter;
if (halign == ant::Object::AL_auto) {
// Compute a nice alignment depending on the anchor point
if (fabs (qq.x ()) > 1e-6) {
text_halign = qq.x () > 0.0 ? db::HAlignLeft : db::HAlignRight;
} else if (length_u < 1e-5) {
text_halign = db::HAlignLeft;
} else if (pos == ant::Object::POS_p2) {
text_halign = q2.x () < q1.x () ? db::HAlignLeft : db::HAlignRight;
} else if (pos == ant::Object::POS_p1) {
@ -396,7 +405,9 @@ draw_text (const db::DPoint &q1,
db::VAlign text_valign = db::VAlignCenter;
if (valign == ant::Object::AL_auto) {
// Compute a nice alignment depending on the anchor point
if (fabs (qq.y ()) > 1e-6) {
if (length_u < 1e-5) {
text_valign = db::VAlignBottom;
} else if (fabs (qq.y ()) > 1e-6) {
text_valign = qq.y () > 0.0 ? db::VAlignBottom : db::VAlignTop;
} else if (pos == ant::Object::POS_p2) {
text_valign = q1.y () > q2.y () ? db::VAlignBottom : db::VAlignTop;
@ -415,7 +426,17 @@ draw_text (const db::DPoint &q1,
if (style == ant::Object::STY_arrow_start || style == ant::Object::STY_arrow_both || style == ant::Object::STY_arrow_end) {
tv_text = qq * (arrow_width * 0.5 + 2.0);
} else if (style == ant::Object::STY_cross_start || style == ant::Object::STY_cross_both || style == ant::Object::STY_cross_end) {
tv_text = qq * (arrow_width + 2.0);
if (length_u < 1e-5 /*micron*/) {
if (text_halign == db::HAlignRight) {
tv_text = (qq - qu) * 2.0;
} else if (text_halign == db::HAlignLeft) {
tv_text = (qq + qu) * 2.0;
} else {
tv_text = qq * 2.0;
}
} else {
tv_text = qq * (arrow_width + 2.0);
}
} else {
tv_text = qq * (tick_length + 2.0);
}
@ -1366,21 +1387,40 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
// and clear surplus rulers
reduce_rulers (m_max_number_of_rulers - 1);
m_p1 = snap1 (p, m_obj_snap && current_template ().snap ()).second;
const ant::Template &tpl = current_template ();
m_p1 = snap1 (p, m_obj_snap && tpl.snap ()).second;
// create and start dragging the ruler
m_current = ant::Object (m_p1, m_p1, 0, current_template ());
show_message ();
if (mp_active_ruler) {
delete mp_active_ruler;
}
mp_active_ruler = new ant::View (this, &m_current, false /*not selected*/);
mp_active_ruler->thaw ();
m_drawing = true;
if (tpl.mode () == ant::Template::RulerSingleClick) {
widget ()->grab_mouse (this, false);
// begin the transaction
tl_assert (! manager ()->transacting ());
manager ()->transaction (tl::to_string (QObject::tr ("Create ruler")));
show_message ();
insert_ruler (ant::Object (m_p1, m_p1, 0, tpl), true);
// end the transaction
manager ()->commit ();
} else {
m_current = ant::Object (m_p1, m_p1, 0, tpl);
show_message ();
if (mp_active_ruler) {
delete mp_active_ruler;
}
mp_active_ruler = new ant::View (this, &m_current, false /*not selected*/);
mp_active_ruler->thaw ();
m_drawing = true;
widget ()->grab_mouse (this, false);
}
} else {
@ -2046,6 +2086,33 @@ Service::menu_activated (const std::string &symbol)
}
}
void
Service::register_annotation_template (const ant::Template &t)
{
std::string value = lay::PluginRoot::instance ()->config_get (cfg_ruler_templates);
std::vector<ant::Template> templates = ant::Template::from_string (value);
// Remove a template with the same category if such a template already exists
if (! t.category ().empty ()) {
for (size_t i = 0; i < templates.size (); ) {
if (templates[i].category () == t.category ()) {
templates.erase (templates.begin () + i);
} else {
++i;
}
}
}
// and add the new one
templates.push_back (t);
value = ant::Template::to_string (templates);
lay::PluginRoot::instance ()->config_set (cfg_ruler_templates, value);
lay::PluginRoot::instance ()->config_end ();
}
// -------------------------------------------------------------
} // namespace ant

View File

@ -437,6 +437,11 @@ public:
* @brief An event triggered when the selected annotations changed
*/
tl::Event annotation_selection_changed_event;
/**
* @brief Registers an annotation template globally
*/
static void register_annotation_template (const ant::Template &t);
private:
// Ruler display and snapping configuration

View File

@ -38,7 +38,8 @@ Template::Template ()
m_main_position (ant::Object::POS_auto),
m_main_xalign (ant::Object::AL_auto), m_main_yalign (ant::Object::AL_auto),
m_xlabel_xalign (ant::Object::AL_auto), m_xlabel_yalign (ant::Object::AL_auto),
m_ylabel_xalign (ant::Object::AL_auto), m_ylabel_yalign (ant::Object::AL_auto)
m_ylabel_xalign (ant::Object::AL_auto), m_ylabel_yalign (ant::Object::AL_auto),
m_mode (ant::Template::RulerNormal)
{
// .. nothing yet ..
}
@ -53,20 +54,23 @@ Template::Template (const std::string &title,
m_main_position (ant::Object::POS_auto),
m_main_xalign (ant::Object::AL_auto), m_main_yalign (ant::Object::AL_auto),
m_xlabel_xalign (ant::Object::AL_auto), m_xlabel_yalign (ant::Object::AL_auto),
m_ylabel_xalign (ant::Object::AL_auto), m_ylabel_yalign (ant::Object::AL_auto)
m_ylabel_xalign (ant::Object::AL_auto), m_ylabel_yalign (ant::Object::AL_auto),
m_mode (ant::Template::RulerNormal)
{
// .. nothing else ..
}
Template::Template (const ant::Template &d)
: m_title (d.m_title),
m_category (d.m_category),
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),
m_main_position (d.m_main_position),
m_main_xalign (d.m_main_xalign), m_main_yalign (d.m_main_yalign),
m_xlabel_xalign (d.m_xlabel_xalign), m_xlabel_yalign (d.m_xlabel_yalign),
m_ylabel_xalign (d.m_ylabel_xalign), m_ylabel_yalign (d.m_ylabel_yalign)
m_ylabel_xalign (d.m_ylabel_xalign), m_ylabel_yalign (d.m_ylabel_yalign),
m_mode (d.m_mode)
{
// .. nothing else ..
}
@ -76,6 +80,7 @@ Template::operator= (const ant::Template &d)
{
if (this != &d) {
m_title = d.m_title;
m_category = d.m_category;
m_fmt_x = d.m_fmt_x;
m_fmt_y = d.m_fmt_y;
m_fmt = d.m_fmt;
@ -90,6 +95,7 @@ Template::operator= (const ant::Template &d)
m_xlabel_yalign = d.m_xlabel_yalign;
m_ylabel_xalign = d.m_ylabel_xalign;
m_ylabel_yalign = d.m_ylabel_yalign;
m_mode = d.m_mode;
}
return *this;
}
@ -109,13 +115,30 @@ Template::from_string (const std::string &s)
while (! ex.at_end ()) {
if (ex.test ("title=")) {
if (ex.test ("mode=")) {
std::string s;
ex.read_word_or_quoted (s);
ant::RulerModeConverter mc;
ant::Template::ruler_mode_type mode;
mc.from_string (s, mode);
r.back ().set_mode (mode);
ex.test (",");
} else if (ex.test ("title=")) {
std::string s;
ex.read_word_or_quoted (s);
r.back ().title (s);
ex.test (",");
} else if (ex.test ("category=")) {
std::string s;
ex.read_word_or_quoted (s);
r.back ().category (s);
ex.test (",");
} else if (ex.test ("fmt=")) {
std::string s;
@ -276,9 +299,17 @@ Template::to_string (const std::vector<Template> &v)
r += ";";
}
r += "mode=";
ant::RulerModeConverter mc;
r += mc.to_string (t->mode ());
r += ",";
r += "title=";
r += tl::to_word_or_quoted_string (t->title ());
r += ",";
r += "category=";
r += tl::to_word_or_quoted_string (t->category ());
r += ",";
r += "fmt=";
r += tl::to_word_or_quoted_string (t->fmt ());
r += ",";

View File

@ -47,6 +47,24 @@ public:
typedef ant::Object::alignment_type alignment_type;
typedef lay::angle_constraint_type angle_constraint_type;
enum ruler_mode_type
{
/**
* @brief The rulers acts normal and a start and end point need to be defined
*/
RulerNormal = 0,
/**
* @brief The ruler is single-click: a single click is sufficient to place a ruler and p1 will be == p2
*/
RulerSingleClick = 1,
/**
* @brief The ruler is auto-metric: a single click will place a ruler and the ruler will extend to the next adjacent structures
*/
RulerAutoMetric = 2
};
/**
* @brief Default constructor
*
@ -71,6 +89,40 @@ public:
*/
Template &operator= (const ant::Template &d);
/**
* @brief Gets the category string
* The category string is used to label the rulers generated from this template.
* Templates that use a category string are regarded "system templates" and are not editable.
*/
const std::string &category () const
{
return m_category;
}
/**
* @brief Sets the category string
*/
void category (const std::string &c)
{
m_category = c;
}
/**
* @brief Sets the ruler mode
*/
void set_mode (ruler_mode_type mode)
{
m_mode = mode;
}
/**
* @brief Gets the ruler mode
*/
ruler_mode_type mode () const
{
return m_mode;
}
/**
* @brief Title read accessor
*/
@ -355,6 +407,7 @@ public:
private:
std::string m_title;
std::string m_category;
std::string m_fmt_x;
std::string m_fmt_y;
std::string m_fmt;
@ -366,6 +419,7 @@ private:
alignment_type m_main_xalign, m_main_yalign;
alignment_type m_xlabel_xalign, m_xlabel_yalign;
alignment_type m_ylabel_xalign, m_ylabel_yalign;
ruler_mode_type m_mode;
};
}

View File

@ -379,10 +379,79 @@ static tl::event<int> &get_annotation_changed_event (lay::LayoutView *view)
return ant_service->annotation_changed_event;
}
static int ruler_mode_normal ()
{
return ant::Template::RulerNormal;
}
static int ruler_mode_single_click ()
{
return ant::Template::RulerSingleClick;
}
static int ruler_mode_auto_metric ()
{
return ant::Template::RulerAutoMetric;
}
static void register_annotation_template (const ant::Object &a, const std::string &title, int mode)
{
ant::Template t;
t.angle_constraint (a.angle_constraint ());
t.category (a.category ());
t.fmt (a.fmt ());
t.fmt_x (a.fmt_x ());
t.fmt_y (a.fmt_y ());
t.set_main_position (a.main_position ());
t.set_main_xalign (a.main_xalign ());
t.set_main_yalign (a.main_yalign ());
t.set_xlabel_xalign (a.xlabel_xalign ());
t.set_xlabel_yalign (a.xlabel_yalign ());
t.set_ylabel_xalign (a.ylabel_xalign ());
t.set_ylabel_yalign (a.ylabel_yalign ());
t.outline (a.outline ());
t.style (a.style ());
t.title (title);
t.set_mode (ant::Template::ruler_mode_type (mode));
ant::Service::register_annotation_template (t);
}
// NOTE: ant::Object is available as "BasicAnnotation" to allow binding for other methods.
gsi::Class<ant::Object> decl_BasicAnnotation ("BasicAnnotation", gsi::Methods (), "@hide");
gsi::Class<ant::Object> decl_BasicAnnotation ("BasicAnnotation", gsi::Methods (), "@hide\n@alias Annotation");
gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "Annotation",
gsi::method ("register_template", &gsi::register_annotation_template,
gsi::arg ("annotation"), gsi::arg ("title"), gsi::arg ("mode", ruler_mode_normal (), "\\RulerModeNormal"),
"@brief Registers the given annotation as a template\n"
"@param title The title to use for the ruler template\n"
"@param mode The mode the ruler will be created in (see Ruler... constants)\n"
"\n"
"In order to register a system template, the category string of the annotation should be "
"a unique and non-empty string. The annotation is added to the list of annotation templates "
"and becomes available as a new template in the ruler drop-down menu.\n"
"\n"
"This method has been added in version 0.25."
) +
gsi::method ("RulerModeNormal", &gsi::ruler_mode_normal,
"@brief Specifies normal ruler mode for the \\register_template method\n"
"\n"
"This constant has been introduced in version 0.25"
) +
gsi::method ("RulerModeSingleClick", &gsi::ruler_mode_single_click,
"@brief Specifies single-click ruler mode for the \\register_template method\n"
"In single click-mode, a ruler can be placed with a single click and p1 will be == p2."
"\n"
"This constant has been introduced in version 0.25"
) +
gsi::method ("RulerModeAutoMetric", &gsi::ruler_mode_auto_metric,
"@brief Specifies auto-metric ruler mode for the \\register_template method\n"
"In auto-metric mode, a ruler can be placed with a single click and p1/p2 will be determined from the neighborhood."
"\n"
"This constant has been introduced in version 0.25"
) +
gsi::method ("StyleRuler|#style_ruler", &gsi::style_ruler,
"@brief Gets the ruler style code for use the \\style method\n"
"When this style is specified, the annotation will show a ruler with "