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> <x>0</x>
<y>0</y> <y>0</y>
<width>668</width> <width>668</width>
<height>373</height> <height>410</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -169,7 +169,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QFrame" name="frame_2"> <widget class="QFrame" name="mode_cb">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::StyledPanel</enum>
</property> </property>
@ -192,51 +192,13 @@
<property name="spacing"> <property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<item row="3" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string> ... position</string> <string> ... position</string>
</property> </property>
</widget> </widget>
</item> </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"> <item row="2" column="1">
<widget class="QLineEdit" name="fmt_x_le"> <widget class="QLineEdit" name="fmt_x_le">
<property name="toolTip"> <property name="toolTip">
@ -244,18 +206,122 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="8" column="0">
<widget class="QLabel" name="label_16"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Style</string> <string>Angle constraints</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="5" column="1">
<widget class="QLineEdit" name="fmt_y_le"> <widget class="QFrame" name="frame_6">
<property name="toolTip"> <property name="frameShape">
<string>Specify the y label format (applicable only for outline modes that have a vertical component, i.e. box)</string> <enum>QFrame::NoFrame</enum>
</property> </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> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
@ -433,64 +499,41 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string> ... position</string> <string>X label format</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="11" column="0" colspan="2">
<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">
<widget class="QLabel" name="help_label"> <widget class="QLabel" name="help_label">
<property name="text"> <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> <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> </property>
</widget> </widget>
</item> </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"> <item row="7" column="1">
<widget class="QComboBox" name="outline_cb"> <widget class="QComboBox" name="outline_cb">
<property name="toolTip"> <property name="toolTip">
@ -533,67 +576,81 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="7" column="0">
<widget class="QComboBox" name="style_cb"> <widget class="QLabel" name="label_17">
<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">
<property name="text"> <property name="text">
<string>X label format</string> <string>Outline</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="10" column="1">
<widget class="QLabel" name="label_5"> <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"> <property name="text">
<string> ... position</string> <string> ... position</string>
</property> </property>
</widget> </widget>
</item> </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"> <item row="3" column="1">
<widget class="QFrame" name="frame_5"> <widget class="QFrame" name="frame_5">
<property name="frameShape"> <property name="frameShape">
@ -705,115 +762,84 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="6" column="1">
<widget class="QFrame" name="frame_6"> <widget class="QComboBox" name="style_cb">
<property name="frameShape"> <property name="toolTip">
<enum>QFrame::NoFrame</enum> <string>Specify style of the ruler template</string>
</property> </property>
<property name="frameShadow"> <item>
<enum>QFrame::Raised</enum> <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> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> </widget>
<property name="leftMargin"> </item>
<number>0</number> <item row="9" column="1">
<widget class="QComboBox" name="t_mode_cb">
<item>
<property name="text">
<string>Normal</string>
</property> </property>
<property name="topMargin"> </item>
<number>0</number> <item>
<property name="text">
<string>Single click (both points will be equal)</string>
</property> </property>
<property name="rightMargin"> </item>
<number>0</number> <item>
<property name="text">
<string>Auto measure (points will be set automatically)</string>
</property> </property>
<property name="bottomMargin"> </item>
<number>0</number> </widget>
</property> </item>
<item> <item row="9" column="0">
<spacer name="horizontalSpacer_3"> <widget class="QLabel" name="label_6">
<property name="orientation"> <property name="text">
<enum>Qt::Horizontal</enum> <string>Mode</string>
</property> </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> </widget>
</item> </item>
</layout> </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 std::string
TemplatesConverter::to_string (const std::vector <ant::Template> &t) 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); 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 struct TemplatesConverter
{ {
std::string to_string (const std::vector <ant::Template> &t); 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->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_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_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_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 ()); 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 ()); lay::angle_constraint_type ac = lay::angle_constraint_type (mp_ui->t_angle_cb->currentIndex ());
m_ruler_templates [m_current_template].angle_constraint (ac); 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].snap (mp_ui->t_snap_cbx->isChecked ());
m_ruler_templates [m_current_template].set_main_position (Object::position_type (mp_ui->main_position->currentIndex ())); 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_fmt_x (t.fmt_x ()), m_fmt_y (t.fmt_y ()), m_fmt (t.fmt ()),
m_style (t.style ()), m_outline (t.outline ()), m_style (t.style ()), m_outline (t.outline ()),
m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()), m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()),
m_category (t.category ()),
m_main_position (t.main_position ()), m_main_position (t.main_position ()),
m_main_xalign (t.main_xalign ()), m_main_yalign (t.main_yalign ()), 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_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 arrow_length = 12 / renderer.resolution ();
double sel_width = 2 / 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) { if (sel) {
@ -153,7 +153,7 @@ draw_ruler (const db::DPoint &q1,
// normal and unit vector // normal and unit vector
double len = q1.double_distance (q2); 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_length = len / 1.2;
arrow_width = arrow_length * 2.0 / 3.0; arrow_width = arrow_length * 2.0 / 3.0;
} else if (style == ant::Object::STY_arrow_both && len < double (arrow_length) * 2.4) { } 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) { if (len > 1e-10) {
qq *= 1.0 / len; qq *= 1.0 / len;
} else { } else {
qq = db::DVector (1.0, 0.0); qq = db::DVector (0.0, 1.0);
} }
if (!right) { if (!right) {
qq = -qq; qq = -qq;
@ -340,7 +340,7 @@ draw_text (const db::DPoint &q1,
pos = ant::Object::POS_p2; 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), renderer.draw (db::DBox (q1, q1),
label, label,
@ -357,7 +357,7 @@ draw_text (const db::DPoint &q1,
// normal and unit vector // normal and unit vector
double len = q1.double_distance (q2); 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_length = len / 1.2;
arrow_width = arrow_length * 2.0 / 3.0; arrow_width = arrow_length * 2.0 / 3.0;
} else if (style == ant::Object::STY_arrow_both && len < double (arrow_length) * 2.4) { } 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) { if (len > 1e-10) {
qq *= 1.0 / len; qq *= 1.0 / len;
} else { } else {
qq = db::DVector (1.0, 0.0); qq = db::DVector (0.0, 1.0);
} }
if (!right) { if (!right) {
qq = -qq; 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; db::HAlign text_halign = db::HAlignCenter;
if (halign == ant::Object::AL_auto) { if (halign == ant::Object::AL_auto) {
// Compute a nice alignment depending on the anchor point // Compute a nice alignment depending on the anchor point
if (fabs (qq.x ()) > 1e-6) { if (fabs (qq.x ()) > 1e-6) {
text_halign = qq.x () > 0.0 ? db::HAlignLeft : db::HAlignRight; 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) { } else if (pos == ant::Object::POS_p2) {
text_halign = q2.x () < q1.x () ? db::HAlignLeft : db::HAlignRight; text_halign = q2.x () < q1.x () ? db::HAlignLeft : db::HAlignRight;
} else if (pos == ant::Object::POS_p1) { } else if (pos == ant::Object::POS_p1) {
@ -396,7 +405,9 @@ draw_text (const db::DPoint &q1,
db::VAlign text_valign = db::VAlignCenter; db::VAlign text_valign = db::VAlignCenter;
if (valign == ant::Object::AL_auto) { if (valign == ant::Object::AL_auto) {
// Compute a nice alignment depending on the anchor point // 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; text_valign = qq.y () > 0.0 ? db::VAlignBottom : db::VAlignTop;
} else if (pos == ant::Object::POS_p2) { } else if (pos == ant::Object::POS_p2) {
text_valign = q1.y () > q2.y () ? db::VAlignBottom : db::VAlignTop; 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) { 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); 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) { } 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 { } else {
tv_text = qq * (tick_length + 2.0); 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 // and clear surplus rulers
reduce_rulers (m_max_number_of_rulers - 1); 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 // create and start dragging the ruler
m_current = ant::Object (m_p1, m_p1, 0, current_template ()); if (tpl.mode () == ant::Template::RulerSingleClick) {
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); // 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 { } 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 } // namespace ant

View File

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

View File

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

View File

@ -47,6 +47,24 @@ public:
typedef ant::Object::alignment_type alignment_type; typedef ant::Object::alignment_type alignment_type;
typedef lay::angle_constraint_type angle_constraint_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 * @brief Default constructor
* *
@ -71,6 +89,40 @@ public:
*/ */
Template &operator= (const ant::Template &d); 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 * @brief Title read accessor
*/ */
@ -355,6 +407,7 @@ public:
private: private:
std::string m_title; std::string m_title;
std::string m_category;
std::string m_fmt_x; std::string m_fmt_x;
std::string m_fmt_y; std::string m_fmt_y;
std::string m_fmt; std::string m_fmt;
@ -366,6 +419,7 @@ private:
alignment_type m_main_xalign, m_main_yalign; alignment_type m_main_xalign, m_main_yalign;
alignment_type m_xlabel_xalign, m_xlabel_yalign; alignment_type m_xlabel_xalign, m_xlabel_yalign;
alignment_type m_ylabel_xalign, m_ylabel_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; 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. // 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::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, gsi::method ("StyleRuler|#style_ruler", &gsi::style_ruler,
"@brief Gets the ruler style code for use the \\style method\n" "@brief Gets the ruler style code for use the \\style method\n"
"When this style is specified, the annotation will show a ruler with " "When this style is specified, the annotation will show a ruler with "