mirror of https://github.com/KLayout/klayout.git
Rulers: confine box/ellipse to square/circle with Ctrl, center box/ellipse with Ctrl - same as for drawing boxes
This commit is contained in:
parent
18c2f5dfa4
commit
ddee74ab78
|
|
@ -50,6 +50,10 @@ ToolkitWidget::ToolkitWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispat
|
|||
mp_y_le->set_label ("dy:");
|
||||
mp_layout->addWidget (mp_y_le);
|
||||
|
||||
mp_d_le = new lay::DecoratedLineEdit (this);
|
||||
mp_d_le->set_label ("d:");
|
||||
mp_layout->addWidget (mp_d_le);
|
||||
|
||||
mp_layout->addStretch (1);
|
||||
|
||||
hide ();
|
||||
|
|
@ -86,12 +90,24 @@ ToolkitWidget::commit (lay::Dispatcher *dispatcher)
|
|||
{
|
||||
try {
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
if (mp_d_le->hasFocus ()) {
|
||||
|
||||
tl::from_string (tl::to_string (mp_x_le->text ()), dx);
|
||||
tl::from_string (tl::to_string (mp_y_le->text ()), dy);
|
||||
double d = 0.0;
|
||||
|
||||
dispatcher->call_function (ant::Service::function_name (), db::DVector (dx, dy).to_string ());
|
||||
tl::from_string (tl::to_string (mp_d_le->text ()), d);
|
||||
|
||||
dispatcher->call_function (ant::Service::d_function_name (), tl::to_string (d));
|
||||
|
||||
} else {
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
|
||||
tl::from_string (tl::to_string (mp_x_le->text ()), dx);
|
||||
tl::from_string (tl::to_string (mp_y_le->text ()), dy);
|
||||
|
||||
dispatcher->call_function (ant::Service::xy_function_name (), db::DVector (dx, dy).to_string ());
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
|
@ -100,7 +116,7 @@ ToolkitWidget::commit (lay::Dispatcher *dispatcher)
|
|||
void
|
||||
ToolkitWidget::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == ant::Service::configure_name () && ! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) {
|
||||
if (name == ant::Service::xy_configure_name () && ! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) {
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -113,6 +129,18 @@ ToolkitWidget::configure (const std::string &name, const std::string &value)
|
|||
} catch (...) {
|
||||
}
|
||||
|
||||
} else if (name == ant::Service::d_configure_name () && ! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) {
|
||||
|
||||
try {
|
||||
|
||||
double d;
|
||||
tl::from_string (value, d);
|
||||
|
||||
mp_d_le->setText (tl::to_qstring (tl::micron_to_string (d)));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public:
|
|||
|
||||
private:
|
||||
QHBoxLayout *mp_layout;
|
||||
lay::DecoratedLineEdit *mp_x_le, *mp_y_le;
|
||||
lay::DecoratedLineEdit *mp_x_le, *mp_y_le, *mp_d_le;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1043,8 +1043,10 @@ View::render (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas)
|
|||
// ant::Service implementation
|
||||
|
||||
const char *Service::editor_options_name () { return "ant-toolkit-widget-name"; }
|
||||
const char *Service::configure_name () { return "ant-toolkit-widget-value"; }
|
||||
const char *Service::function_name () { return "ant-toolkit-widget-commit"; }
|
||||
const char *Service::xy_configure_name () { return "ant-toolkit-widget-xy-value"; }
|
||||
const char *Service::d_configure_name () { return "ant-toolkit-widget-d-value"; }
|
||||
const char *Service::xy_function_name () { return "ant-toolkit-widget-xy-commit"; }
|
||||
const char *Service::d_function_name () { return "ant-toolkit-widget-d-commit"; }
|
||||
|
||||
Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
||||
: lay::EditorServiceBase (view),
|
||||
|
|
@ -1061,6 +1063,9 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
m_drawing (false), m_current (),
|
||||
m_move_mode (MoveNone),
|
||||
m_seg_index (0),
|
||||
m_length_confined (false),
|
||||
m_length (0.0),
|
||||
m_centered (false),
|
||||
m_current_template (0),
|
||||
m_hover (false),
|
||||
m_hover_wait (false),
|
||||
|
|
@ -1906,6 +1911,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
// cancel any edit operations so far
|
||||
m_move_mode = MoveNone;
|
||||
m_length_confined = false;
|
||||
|
||||
// reset selection
|
||||
clear_selection ();
|
||||
|
|
@ -2023,6 +2029,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
pts.push_back (m_p1);
|
||||
m_current.set_points_exact (pts);
|
||||
m_length_confined = false;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2058,7 +2065,7 @@ Service::create_measure_ruler (const db::DPoint &pt, lay::angle_constraint_type
|
|||
void
|
||||
Service::function (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == function_name ()) {
|
||||
if (name == xy_function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -2109,6 +2116,59 @@ Service::function (const std::string &name, const std::string &value)
|
|||
} catch (...) {
|
||||
}
|
||||
|
||||
} else if (name == d_function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
double s = 0.0;
|
||||
tl::from_string (value, s);
|
||||
|
||||
if (m_drawing) {
|
||||
|
||||
m_length_confined = true;
|
||||
m_length = s;
|
||||
|
||||
ant::Object::point_list pts = m_current.points ();
|
||||
confine_length (pts);
|
||||
m_current.set_points_exact (pts);
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::confine_length (ant::Object::point_list &pts)
|
||||
{
|
||||
if (m_length_confined && pts.size () >= 2) {
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
bool is_box_style = (tpl.outline () == ant::Object::OL_box || tpl.outline () == ant::Object::OL_ellipse);
|
||||
|
||||
db::DPoint p1 = m_centered ? m_p1 : pts [pts.size () - 2];
|
||||
db::DVector s = pts.back () - p1;
|
||||
if (is_box_style) {
|
||||
db::DVector snew = s;
|
||||
double l = m_centered ? m_length * 0.5 : m_length;
|
||||
if (fabs (s.x ()) < fabs (s.y ()) + db::epsilon) {
|
||||
snew.set_y (l * (s.y () < 0 ? -1.0 : 1.0));
|
||||
}
|
||||
if (fabs (s.y ()) < fabs (s.x ()) + db::epsilon) {
|
||||
snew.set_x (l * (s.x () < 0 ? -1.0 : 1.0));
|
||||
}
|
||||
s = snew;
|
||||
} else {
|
||||
double l = s.double_length ();
|
||||
if (l > db::epsilon) {
|
||||
s *= m_length / l;
|
||||
}
|
||||
}
|
||||
|
||||
pts.back () = p1 + s;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2131,11 +2191,31 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|||
|
||||
}
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
|
||||
// for normal rulers with box or ellipse rendering we use a different button scheme:
|
||||
// Shift will keep the center, Ctrl will confine the box to a square/ellipse to a circle
|
||||
bool snap_square = false;
|
||||
bool is_box_style = (tpl.outline () == ant::Object::OL_box || tpl.outline () == ant::Object::OL_ellipse);
|
||||
if (tpl.mode () == ant::Template::RulerNormal && is_box_style) {
|
||||
snap_square = (buttons & lay::ControlButton) != 0;
|
||||
m_centered = (buttons & lay::ShiftButton) != 0;
|
||||
} else {
|
||||
m_centered = false;
|
||||
}
|
||||
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
if (m_drawing) {
|
||||
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons));
|
||||
lay::angle_constraint_type ac;
|
||||
if (snap_square) {
|
||||
ac = lay::AC_DiagonalOnly;
|
||||
} else if (is_box_style) {
|
||||
ac = lay::AC_Any;
|
||||
} else {
|
||||
ac = ac_from_buttons (buttons);
|
||||
}
|
||||
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac);
|
||||
} else {
|
||||
const ant::Template &tpl = current_template ();
|
||||
snap_details = snap1_details (p, m_obj_snap && tpl.snap () && (tpl.mode () != ant::Template::RulerAutoMetricEdge || ! view ()->transient_selection_mode ()));
|
||||
}
|
||||
|
||||
|
|
@ -2149,8 +2229,19 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|||
// otherwise we risk manipulating p1 too.
|
||||
ant::Object::point_list pts = m_current.points ();
|
||||
if (! pts.empty ()) {
|
||||
|
||||
pts.back () = snap_details.snapped_point;
|
||||
|
||||
confine_length (pts);
|
||||
|
||||
if (m_centered) {
|
||||
pts.front () = m_p1 - (pts.back () - m_p1);
|
||||
} else {
|
||||
pts.front () = m_p1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_current.set_points_exact (pts);
|
||||
|
||||
db::DVector delta;
|
||||
|
|
@ -2161,7 +2252,9 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|||
|
||||
lay::EditorOptionsPage *tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->configure (configure_name (), delta.to_string ());
|
||||
double d = is_box_style ? std::min (fabs (delta.x ()), fabs (delta.y ())) : delta.length ();
|
||||
tb->configure (xy_configure_name (), delta.to_string ());
|
||||
tb->configure (d_configure_name (), tl::to_string (d));
|
||||
}
|
||||
|
||||
mp_active_ruler->redraw ();
|
||||
|
|
|
|||
|
|
@ -199,8 +199,10 @@ public:
|
|||
|
||||
// for communicating with the toolbox widget
|
||||
static const char *editor_options_name ();
|
||||
static const char *configure_name ();
|
||||
static const char *function_name ();
|
||||
static const char *xy_configure_name ();
|
||||
static const char *d_configure_name ();
|
||||
static const char *xy_function_name ();
|
||||
static const char *d_function_name ();
|
||||
|
||||
/**
|
||||
* The current move mode:
|
||||
|
|
@ -598,6 +600,11 @@ private:
|
|||
MoveMode m_move_mode;
|
||||
// The currently moving segment
|
||||
size_t m_seg_index;
|
||||
// When set to true, the length is confined to the value given by m_length
|
||||
bool m_length_confined;
|
||||
double m_length;
|
||||
// When set to true, the last point was established in centered fashion
|
||||
bool m_centered;
|
||||
// The ruler template
|
||||
std::vector<ant::Template> m_ruler_templates;
|
||||
unsigned int m_current_template;
|
||||
|
|
@ -618,6 +625,7 @@ private:
|
|||
db::DPoint snap2_visual (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
|
||||
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
|
||||
lay::TwoPointSnapToObjectResult auto_measure (const db::DPoint &p, lay::angle_constraint_type ac, const ant::Template &tpl);
|
||||
void confine_length (ant::Object::point_list &pts);
|
||||
|
||||
const ant::Template ¤t_template () const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue