WIP: debugging, first implementation of new templates

This commit is contained in:
Matthias Koefferlein 2022-09-28 00:37:37 +02:00
parent 79102d399e
commit 8cbe5a2359
8 changed files with 195 additions and 37 deletions

View File

@ -89,7 +89,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/up_16px.png</normaloff>:/up_16px.png</iconset>
</property>
</widget>
@ -103,7 +103,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
</property>
</widget>
@ -117,7 +117,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/del_16px.png</normaloff>:/del_16px.png</iconset>
</property>
</widget>
@ -131,7 +131,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/down_16px.png</normaloff>:/down_16px.png</iconset>
</property>
</widget>
@ -833,6 +833,16 @@
<string>Auto measure (points will be set automatically)</string>
</property>
</item>
<item>
<property name="text">
<string>Angle measurement (three mouse clicks)</string>
</property>
</item>
<item>
<property name="text">
<string>Multi-segment (finish with double click)</string>
</property>
</item>
</widget>
</item>
<item row="9" column="0">
@ -866,7 +876,7 @@
<tabstop>t_snap_cbx</tabstop>
</tabstops>
<resources>
<include location="../../lay/lay/layResources.qrc"/>
<include location="../../icons/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -239,6 +239,10 @@ RulerModeConverter::to_string (ant::Template::ruler_mode_type m)
return "single_click";
} else if (m == ant::Template::RulerAutoMetric) {
return "auto_metric";
} else if (m == ant::Template::RulerMultiSegment) {
return "multi_segment";
} else if (m == ant::Template::RulerAngle) {
return "angle";
} else {
return "normal";
}
@ -254,6 +258,10 @@ RulerModeConverter::from_string (const std::string &s, ant::Template::ruler_mode
a = ant::Template::RulerSingleClick;
} else if (t == "auto_metric") {
a = ant::Template::RulerAutoMetric;
} else if (t == "multi_segment") {
a = ant::Template::RulerMultiSegment;
} else if (t == "angle") {
a = ant::Template::RulerAngle;
} else {
a = ant::Template::RulerNormal;
}

View File

@ -292,6 +292,14 @@ public:
*/
void set_points (const point_list &points);
/**
* @brief Sets the ruler's definition points without cleaning
*/
void set_points_exact (const point_list &points)
{
m_points = points;
}
/**
* @brief Gets the first point of the indicated segment
*/

View File

@ -68,12 +68,18 @@ static std::vector<ant::Template> make_standard_templates ()
templates.push_back (ant::Template (tl::to_string (tr ("Ruler")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_ruler"));
templates.push_back (ant::Template (tl::to_string (tr ("Multi-ruler")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_multi_ruler"));
templates.back ().set_mode (ant::Template::RulerMultiSegment);
templates.push_back (ant::Template (tl::to_string (tr ("Cross")), "", "", "$U,$V", ant::Object::STY_cross_both, ant::Object::OL_diag, true, lay::AC_Global, "_cross"));
templates.back ().set_mode (ant::Template::RulerSingleClick);
templates.push_back (ant::Template (tl::to_string (tr ("Measure")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure"));
templates.back ().set_mode (ant::Template::RulerAutoMetric);
templates.push_back (ant::Template (tl::to_string (tr ("Angle")), "$X", "$Y", "$D", ant::Object::STY_line, ant::Object::OL_diag, true, lay::AC_Global, "_angle"));
templates.back ().set_mode (ant::Template::RulerAngle);
templates.push_back (ant::Template (tl::to_string (tr ("Ellipse")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_ellipse, true, lay::AC_Global, std::string ()));
templates.push_back (ant::Template (tl::to_string (tr ("Box")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_box, true, lay::AC_Global, std::string ()));
@ -197,14 +203,50 @@ PluginDeclaration::initialized (lay::Dispatcher *root)
// Check if we already have templates (initial setup)
// NOTE: this is not done by using a default value for the configuration item but dynamically.
// This provides a migration path from earlier versions (not having templates) to recent ones.
bool any_templates = false;
for (std::vector<ant::Template>::iterator i = m_templates.begin (); ! any_templates && i != m_templates.end (); ++i) {
any_templates = ! i->category ().empty ();
std::map<std::string, const ant::Template *> cat_names;
for (auto i = m_templates.begin (); i != m_templates.end (); ++i) {
if (! i->category ().empty ()) {
cat_names.insert (std::make_pair (i->category (), i.operator-> ()));
}
}
if (! any_templates) {
bool any_missing = false;
auto std_templates = make_standard_templates ();
for (auto t = std_templates.begin (); ! any_missing && t != std_templates.end (); ++t) {
if (! t->category ().empty () && cat_names.find (t->category ()) == cat_names.end ()) {
any_missing = true;
}
}
if (cat_names.empty ()) {
// full initial configuration
root->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (make_standard_templates ()));
root->config_end ();
} else if (any_missing) {
// some standard templates are missing - add them now (migration path for later versions)
decltype (m_templates) new_templates;
for (auto t = std_templates.begin (); t != std_templates.end (); ++t) {
if (! t->category ().empty ()) {
auto tt = cat_names.find (t->category ());
if (tt != cat_names.end ()) {
new_templates.push_back (*tt->second);
} else {
new_templates.push_back (*t);
}
}
}
for (auto i = m_templates.begin (); i != m_templates.end (); ++i) {
if (i->category ().empty ()) {
new_templates.push_back (*i);
}
}
root->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (new_templates));
root->config_end ();
}
}

View File

@ -1560,11 +1560,52 @@ Service::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio
return mouse_click_event (p, buttons, prio);
}
bool
void
Service::finish_drawing ()
{
// create the ruler object
// begin the transaction
if (manager ()) {
tl_assert (! manager ()->transacting ());
manager ()->transaction (tl::to_string (tr ("Create ruler")));
}
show_message ();
insert_ruler (ant::Object (m_current.points (), 0, current_template ()), true);
// stop dragging
drag_cancel ();
clear_transient_selection ();
// end the transaction
if (manager ()) {
manager ()->commit ();
}
}
bool
Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int buttons, bool prio)
{
if (m_drawing && prio && (buttons & lay::LeftButton) != 0) {
// ends the current ruler (specifically in multi-segment mode)
finish_drawing ();
return true;
}
return false;
}
bool
Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
if (prio && (buttons & lay::LeftButton) != 0) {
const ant::Template &tpl = current_template ();
if (! m_drawing) {
// cancel any edit operations so far
@ -1577,8 +1618,6 @@ 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);
const ant::Template &tpl = current_template ();
// create and start dragging the ruler
if (tpl.mode () == ant::Template::RulerSingleClick) {
@ -1648,7 +1687,13 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
m_p1 = snap1 (p, m_obj_snap && tpl.snap ()).second;
m_current = ant::Object (m_p1, m_p1, 0, tpl);
// NOTE: generating the ruler this way makes sure we have two points
ant::Object::point_list pts;
m_current = ant::Object (pts, 0, tpl);
pts.push_back (m_p1);
pts.push_back (m_p1);
m_current.set_points_exact (pts);
show_message ();
if (mp_active_ruler) {
@ -1662,29 +1707,29 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
}
} else if (tpl.mode () == ant::Template::RulerMultiSegment || tpl.mode () == ant::Template::RulerAngle) {
ant::Object::point_list pts = m_current.points ();
tl_assert (! pts.empty ());
if (tpl.mode () == ant::Template::RulerAngle && pts.size () == 3) {
finish_drawing ();
} else {
// add a new point
m_p1 = pts.back ();
pts.push_back (m_p1);
m_current.set_points_exact (pts);
}
} else {
// create the ruler object
finish_drawing ();
// begin the transaction
if (manager ()) {
tl_assert (! manager ()->transacting ());
manager ()->transaction (tl::to_string (tr ("Create ruler")));
}
show_message ();
insert_ruler (ant::Object (m_current.p1 (), m_current.p2 (), 0, current_template ()), true);
// stop dragging
drag_cancel ();
clear_transient_selection ();
// end the transaction
if (manager ()) {
manager ()->commit ();
}
}
return true;
@ -1731,7 +1776,14 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
set_cursor (lay::Cursor::cross);
m_current.p2 (snap2 (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons)).second);
// NOTE: we use the direct access path so we do not encounter cleanup by the p1 and p2 setters
// otherwise we risk manipulating p1 too.
ant::Object::point_list pts = m_current.points ();
if (! pts.empty ()) {
pts.back () = snap2 (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons)).second;
}
m_current.set_points_exact (pts);
mp_active_ruler->redraw ();
show_message ();

View File

@ -566,6 +566,7 @@ private:
virtual bool mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual bool mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual bool mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual void deactivated ();
/**
@ -585,6 +586,11 @@ private:
*/
void reduce_rulers (int num);
/**
* @brief Finishes drawing mode and creates the ruler
*/
void finish_drawing ();
/**
* @brief Delete the selected rulers
*

View File

@ -62,7 +62,17 @@ public:
/**
* @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
RulerAutoMetric = 2,
/**
* @brief The ruler an angle type (two segments, three mouse clicks) for angle and circle radius measurements
*/
RulerAngle = 3,
/**
* @brief The ruler is a multi-segment type
*/
RulerMultiSegment = 4
};
/**

View File

@ -432,6 +432,16 @@ static int ruler_mode_auto_metric ()
return ant::Template::RulerAutoMetric;
}
static int ruler_mode_angle ()
{
return ant::Template::RulerAngle;
}
static int ruler_mode_multi_segment ()
{
return ant::Template::RulerMultiSegment;
}
static void register_annotation_template (const ant::Object &a, const std::string &title, int mode)
{
ant::Template t = ant::Template::from_object (a, title, mode);
@ -503,16 +513,28 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
) +
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."
"In single click-mode, a ruler can be placed with a single click and p1 will be == p2.\n"
"\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."
"In auto-metric mode, a ruler can be placed with a single click and p1/p2 will be determined from the neighborhood.\n"
"\n"
"This constant has been introduced in version 0.25"
) +
gsi::method ("RulerAngle", &gsi::ruler_mode_angle,
"@brief Specifies angle ruler mode for the \\register_template method\n"
"In angle ruler mode, two segments are created for angle and circle radius measurements. Three mouse clicks are required.\n"
"\n"
"This constant has been introduced in version 0.28"
) +
gsi::method ("RulerMultiSegment", &gsi::ruler_mode_multi_segment,
"@brief Specifies multi-segment mode\n"
"In multi-segment mode, multiple segments can be created. The ruler is finished with a double click.\n"
"\n"
"This constant has been introduced in version 0.28"
) +
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 "