diff --git a/src/edt/edt/edtBoxService.cc b/src/edt/edt/edtBoxService.cc index 514cc543e..68ad5658e 100644 --- a/src/edt/edt/edtBoxService.cc +++ b/src/edt/edt/edtBoxService.cc @@ -88,7 +88,7 @@ BoxService::function (const std::string &name, const std::string &value) } m_p2 = m_p1 + dim; - finish_editing (); + finish_editing (true); } catch (...) { } @@ -209,7 +209,7 @@ BoxService::do_mouse_click (const db::DPoint &p) } void -BoxService::do_finish_edit () +BoxService::do_finish_edit (bool /*accept*/) { deliver_shape (get_box ()); commit_recent (); diff --git a/src/edt/edt/edtBoxService.h b/src/edt/edt/edtBoxService.h index c14b557f8..bed8c30d4 100644 --- a/src/edt/edt/edtBoxService.h +++ b/src/edt/edt/edtBoxService.h @@ -48,7 +48,7 @@ public: virtual void do_mouse_move (const db::DPoint &p); virtual void do_mouse_move_inactive (const db::DPoint &p); virtual bool do_mouse_click (const db::DPoint &p); - virtual void do_finish_edit (); + virtual void do_finish_edit (bool accept); virtual void do_cancel_edit (); virtual bool selection_applies (const lay::ObjectInstPath &sel) const; virtual void function (const std::string &name, const std::string &value); diff --git a/src/edt/edt/edtEditorOptionsPages.cc b/src/edt/edt/edtEditorOptionsPages.cc index f17b0b9db..04a001c6c 100644 --- a/src/edt/edt/edtEditorOptionsPages.cc +++ b/src/edt/edt/edtEditorOptionsPages.cc @@ -900,9 +900,9 @@ EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector hasFocus () && ! mp_y_le->hasFocus ()) { @@ -975,6 +975,87 @@ BoxToolkitWidget::configure (const std::string &name, const std::string &value) } } +// ------------------------------------------------------------------ +// Connections toolbox widget (for paths and polygons) + +ConnectionToolboxWidget::ConnectionToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) + : lay::EditorOptionsPageWidget (view, dispatcher), m_in_commit (false) +{ + mp_layout = new QHBoxLayout (this); + + mp_x_le = new lay::DecoratedLineEdit (this); + mp_x_le->set_label ("dx:"); + mp_layout->addWidget (mp_x_le); + + mp_y_le = new lay::DecoratedLineEdit (this); + mp_y_le->set_label ("dy:"); + mp_layout->addWidget (mp_y_le); + + mp_layout->addStretch (1); + + hide (); + + set_toolbox_widget (true); + set_transparent (true); +} + +ConnectionToolboxWidget::~ConnectionToolboxWidget () +{ + // .. nothing yet .. +} + +std::string +ConnectionToolboxWidget::title () const +{ + return "Connection Options"; +} + +void +ConnectionToolboxWidget::deactivated () +{ + hide (); +} + +void +ConnectionToolboxWidget::commit (lay::Dispatcher *dispatcher) +{ + m_in_commit = true; + + try { + + 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 (ShapeEditService::connection_function_name (), db::DVector (dx, dy).to_string ()); + + } catch (...) { + } + + m_in_commit = false; +} + +void +ConnectionToolboxWidget::configure (const std::string &name, const std::string &value) +{ + if (name == ShapeEditService::connection_configure_name () && + ((! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) || m_in_commit)) { + + try { + + db::DVector mv; + tl::from_string (value, mv); + + mp_x_le->setText (tl::to_qstring (tl::micron_to_string (mv.x ()))); + mp_y_le->setText (tl::to_qstring (tl::micron_to_string (mv.y ()))); + + } catch (...) { + } + + } +} + // ------------------------------------------------------------------ // Registrations @@ -987,7 +1068,9 @@ static tl::RegisteredClass s_factory_insts (n static tl::RegisteredClass s_factory_insts_pcell (new lay::EditorOptionsPageFactory ("edt::Service(CellInstances)"), 0); // toolkit widgets -static tl::RegisteredClass s_box_tookit_widget_factory (new lay::EditorOptionsPageFactory ("edt::Service(Boxes)"), 0); +static tl::RegisteredClass s_box_tookit_widget_factory (new lay::EditorOptionsPageFactory ("edt::Service(Boxes)"), 0); +static tl::RegisteredClass s_connection_tookit_widget_factory_paths (new lay::EditorOptionsPageFactory ("edt::Service(Paths)"), 0); +static tl::RegisteredClass s_connection_tookit_widget_factory_polygons (new lay::EditorOptionsPageFactory ("edt::Service(Polygons)"), 0); } diff --git a/src/edt/edt/edtEditorOptionsPages.h b/src/edt/edt/edtEditorOptionsPages.h index d04b43978..92f151883 100644 --- a/src/edt/edt/edtEditorOptionsPages.h +++ b/src/edt/edt/edtEditorOptionsPages.h @@ -198,14 +198,14 @@ private: /** * @brief The toolbox widget for boxes */ -class BoxToolkitWidget +class BoxToolboxWidget : public lay::EditorOptionsPageWidget { Q_OBJECT public: - BoxToolkitWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher); - ~BoxToolkitWidget (); + BoxToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher); + ~BoxToolboxWidget (); virtual std::string title () const; virtual int order () const { return 0; } @@ -218,6 +218,30 @@ private: lay::DecoratedLineEdit *mp_x_le, *mp_y_le; }; +/** + * @brief The toolbox widget for connections (path, polygon edges) + */ +class ConnectionToolboxWidget + : public lay::EditorOptionsPageWidget +{ +Q_OBJECT + +public: + ConnectionToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher); + ~ConnectionToolboxWidget (); + + virtual std::string title () const; + virtual int order () const { return 0; } + virtual void configure (const std::string &name, const std::string &value); + virtual void commit (lay::Dispatcher *root); + virtual void deactivated (); + +private: + QHBoxLayout *mp_layout; + lay::DecoratedLineEdit *mp_x_le, *mp_y_le; + bool m_in_commit; +}; + } #endif diff --git a/src/edt/edt/edtInstService.cc b/src/edt/edt/edtInstService.cc index 3e92d981a..001b87356 100644 --- a/src/edt/edt/edtInstService.cc +++ b/src/edt/edt/edtInstService.cc @@ -417,7 +417,7 @@ InstService::do_mouse_click (const db::DPoint &p) } void -InstService::do_finish_edit () +InstService::do_finish_edit (bool /*accept*/) { try { diff --git a/src/edt/edt/edtInstService.h b/src/edt/edt/edtInstService.h index 31fb98e19..4b8ecc155 100644 --- a/src/edt/edt/edtInstService.h +++ b/src/edt/edt/edtInstService.h @@ -53,7 +53,7 @@ public: virtual void do_mouse_move (const db::DPoint &p); virtual bool do_mouse_click (const db::DPoint &p); virtual void do_mouse_transform (const db::DPoint &p, db::DFTrans trans); - virtual void do_finish_edit (); + virtual void do_finish_edit (bool accept); virtual void do_cancel_edit (); virtual bool do_activated (); #if defined(HAVE_QT) diff --git a/src/edt/edt/edtPathService.cc b/src/edt/edt/edtPathService.cc index 65863b591..9ecc36992 100644 --- a/src/edt/edt/edtPathService.cc +++ b/src/edt/edt/edtPathService.cc @@ -26,6 +26,7 @@ #include "edtPropertiesPages.h" #include "layLayoutViewBase.h" +#include "layEditorOptionsPage.h" #include "layFinder.h" namespace edt @@ -160,13 +161,15 @@ PathService::do_delete () } void -PathService::do_finish_edit () +PathService::do_finish_edit (bool accept) { - // one point is reserved for the "current one" - if (m_points.size () < 3) { + // one point is reserved for the "current one" if accept is false + if (! accept && ! m_points.empty ()) { + m_points.pop_back (); + } + if (m_points.size () < 2) { throw tl::Exception (tl::to_string (tr ("A path must have at least 2 points"))); } - m_points.pop_back (); deliver_shape (get_path ()); @@ -175,6 +178,32 @@ PathService::do_finish_edit () close_editor_hooks (true); } +void +PathService::function (const std::string &name, const std::string &value) +{ + if (name == ShapeEditService::connection_function_name ()) { + + try { + + db::DVector dim; + tl::from_string (value, dim); + + if (m_points.size () >= 2) { + + m_last = m_points.back () = m_points.end () [-2] + dim; + m_points.push_back (m_last); + + update_marker (); + update_via (); + + } + + } catch (...) { + } + + } +} + void PathService::update_marker () { @@ -185,12 +214,17 @@ PathService::update_marker () marker->set (path, db::VCplxTrans (1.0 / layout ().dbu ()) * trans ().inverted ()); if (m_points.size () >= 2) { + db::DVector dim = m_points.back () - m_points.end () [-2]; view ()->message (std::string ("lx: ") + - tl::micron_to_string (m_points.back ().x () - m_points.end () [-2].x ()) + + tl::micron_to_string (dim.x ()) + std::string (" ly: ") + - tl::micron_to_string (m_points.back ().y () - m_points.end () [-2].y ()) + + tl::micron_to_string (dim.y ()) + std::string (" l: ") + - tl::micron_to_string (m_points.back ().distance (m_points.end () [-2]))); + tl::micron_to_string (dim.length ())); + auto tb = toolbox_widget (); + if (tb) { + tb->configure (ShapeEditService::connection_configure_name (), dim.to_string ()); + } } } diff --git a/src/edt/edt/edtPathService.h b/src/edt/edt/edtPathService.h index b7321fa53..507a27f16 100644 --- a/src/edt/edt/edtPathService.h +++ b/src/edt/edt/edtPathService.h @@ -47,11 +47,12 @@ public: virtual bool do_mouse_click (const db::DPoint &p); virtual void do_mouse_move_inactive (const db::DPoint &p); virtual void do_delete (); - virtual void do_finish_edit (); + virtual void do_finish_edit (bool accept); virtual void do_cancel_edit (); virtual bool do_activated (); virtual void via (int dir); virtual bool selection_applies (const lay::ObjectInstPath &sel) const; + virtual void function (const std::string &name, const std::string &value); protected: bool configure (const std::string &name, const std::string &value); diff --git a/src/edt/edt/edtPointService.cc b/src/edt/edt/edtPointService.cc index 7c627a5d1..08e3b56f8 100644 --- a/src/edt/edt/edtPointService.cc +++ b/src/edt/edt/edtPointService.cc @@ -124,7 +124,7 @@ PointService::do_mouse_click (const db::DPoint &p) } void -PointService::do_finish_edit () +PointService::do_finish_edit (bool /*accept*/) { deliver_shape (get_point ()); commit_recent (); diff --git a/src/edt/edt/edtPointService.h b/src/edt/edt/edtPointService.h index 264336398..0b262a235 100644 --- a/src/edt/edt/edtPointService.h +++ b/src/edt/edt/edtPointService.h @@ -45,7 +45,7 @@ public: virtual void do_mouse_move (const db::DPoint &p); virtual void do_mouse_move_inactive (const db::DPoint &p); virtual bool do_mouse_click (const db::DPoint &p); - virtual void do_finish_edit (); + virtual void do_finish_edit (bool); virtual void do_cancel_edit (); virtual bool selection_applies (const lay::ObjectInstPath &sel) const; diff --git a/src/edt/edt/edtPolygonService.cc b/src/edt/edt/edtPolygonService.cc index 3f45639f1..aab0d916f 100644 --- a/src/edt/edt/edtPolygonService.cc +++ b/src/edt/edt/edtPolygonService.cc @@ -24,6 +24,7 @@ #include "edtPolygonService.h" #include "layLayoutViewBase.h" +#include "layEditorOptionsPage.h" #if defined(HAVE_QT) # include "edtPropertiesPages.h" @@ -135,13 +136,44 @@ PolygonService::do_mouse_click (const db::DPoint &p) } void -PolygonService::do_finish_edit () +PolygonService::do_finish_edit (bool accept) { + if (accept) { + // add a dummy point in this case for the current one + m_last = m_points.back (); + m_points.push_back (db::DPoint ()); + } + deliver_shape (get_polygon (false)); commit_recent (); close_editor_hooks (true); } +void +PolygonService::function (const std::string &name, const std::string &value) +{ + if (name == ShapeEditService::connection_function_name ()) { + + try { + + db::DVector dim; + tl::from_string (value, dim); + + if (m_points.size () >= 2) { + + m_last = m_points.back () = m_points.end () [-2] + dim; + m_points.push_back (m_last); + + update_marker (); + + } + + } catch (...) { + } + + } +} + db::Polygon PolygonService::get_polygon (bool editing) const { @@ -363,12 +395,17 @@ PolygonService::update_marker () } if (m_points.size () >= 2) { + db::DVector dim = m_points.back () - m_points [m_points.size () - 2]; view ()->message (std::string ("lx: ") + - tl::micron_to_string (m_points.back ().x () - m_points.end () [-2].x ()) + + tl::micron_to_string (dim.x ()) + std::string (" ly: ") + - tl::micron_to_string (m_points.back ().y () - m_points.end () [-2].y ()) + + tl::micron_to_string (dim.y ()) + std::string (" l: ") + - tl::micron_to_string (m_points.back ().distance (m_points.end () [-2]))); + tl::micron_to_string (dim.length ())); + auto tb = toolbox_widget (); + if (tb) { + tb->configure (ShapeEditService::connection_configure_name (), dim.to_string ()); + } } // call hooks with new shape diff --git a/src/edt/edt/edtPolygonService.h b/src/edt/edt/edtPolygonService.h index 1171a8bab..488d59653 100644 --- a/src/edt/edt/edtPolygonService.h +++ b/src/edt/edt/edtPolygonService.h @@ -46,9 +46,10 @@ public: virtual void do_mouse_move (const db::DPoint &p); virtual void do_mouse_move_inactive (const db::DPoint &p); virtual bool do_mouse_click (const db::DPoint &p); - virtual void do_finish_edit (); + virtual void do_finish_edit (bool); virtual void do_cancel_edit (); virtual bool selection_applies (const lay::ObjectInstPath &sel) const; + virtual void function (const std::string &name, const std::string &value); private: std::vector m_points; diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index 137040363..6b0d918b7 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -956,7 +956,7 @@ Service::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio } else { if (do_mouse_click (p)) { - finish_editing (); + finish_editing (false); } } @@ -993,7 +993,7 @@ Service::mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bo if (m_editing && prio && (buttons & lay::LeftButton) != 0) { m_alt_ac = lay::ac_from_buttons (buttons); - finish_editing (); + finish_editing (false); return true; } else { return false; @@ -1022,15 +1022,19 @@ Service::key_event (unsigned int key, unsigned int buttons) if (view ()->is_editable () && m_editing && buttons == 0 && key == lay::KeyBackspace) { do_delete (); return true; + } else if (view ()->is_editable () && m_editing && buttons == 0 && (key == lay::KeyEnter || key == lay::KeyReturn)) { + m_alt_ac = lay::AC_Global; + finish_editing (true); + return true; } else { return false; } } void -Service::finish_editing () +Service::finish_editing (bool accept) { - do_finish_edit (); + do_finish_edit (accept); m_editing = false; show_toolbox (false); diff --git a/src/edt/edt/edtService.h b/src/edt/edt/edtService.h index be535ac4c..99a84c0ee 100644 --- a/src/edt/edt/edtService.h +++ b/src/edt/edt/edtService.h @@ -518,9 +518,12 @@ protected: /** * @brief Reimplemented by the specific implementation of the shape editors * - * This method is called when the object is finished + * This method is called when the object is finished. + * + * 'accept' is set to true if triggered by the Enter/Return key, false if triggered by a mouse click. + * In the latter case, first the mouse click is delivered and then "do_finish_edit" is called. */ - virtual void do_finish_edit () { } + virtual void do_finish_edit (bool /*accept*/) { } /** * @brief Reimplemented by the specific implementation of the shape editors @@ -669,8 +672,9 @@ protected: * @brief Finishes the edit operation * * Calls do_finish_edit() and terminates the editing operation. + * See "do_finish_edit" for an explanation of the "accept" parameter. */ - void finish_editing (); + void finish_editing (bool accept); /** * @brief Gets the toolbox widget or 0 if none is registered diff --git a/src/edt/edt/edtShapeService.cc b/src/edt/edt/edtShapeService.cc index 889955c28..71158cb81 100644 --- a/src/edt/edt/edtShapeService.cc +++ b/src/edt/edt/edtShapeService.cc @@ -39,6 +39,9 @@ namespace edt // ----------------------------------------------------------------------------- // ShapeEditService implementation +const char *ShapeEditService::connection_configure_name () { return "connection-toolkit-widget-value"; } +const char *ShapeEditService::connection_function_name () { return "connection-toolkit-widget-commit"; } + ShapeEditService::ShapeEditService (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIterator::flags_type shape_types) : edt::Service (manager, view, shape_types), m_layer (0), m_cv_index (0), mp_cell (0), mp_layout (0), m_combine_mode (CM_Add), m_update_edit_layer_enabled (true) diff --git a/src/edt/edt/edtShapeService.h b/src/edt/edt/edtShapeService.h index 4a9e32ead..6b1e75a34 100644 --- a/src/edt/edt/edtShapeService.h +++ b/src/edt/edt/edtShapeService.h @@ -37,6 +37,9 @@ class ShapeEditService : public edt::Service { public: + static const char *connection_configure_name (); + static const char *connection_function_name (); + ShapeEditService (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIterator::flags_type shape_types); protected: diff --git a/src/edt/edt/edtTextService.cc b/src/edt/edt/edtTextService.cc index c016b7536..9734a7af8 100644 --- a/src/edt/edt/edtTextService.cc +++ b/src/edt/edt/edtTextService.cc @@ -155,7 +155,7 @@ TextService::get_text () const } void -TextService::do_finish_edit () +TextService::do_finish_edit (bool /*accept*/) { { db::Transaction transaction (manager (), tl::to_string (tr ("Create text"))); diff --git a/src/edt/edt/edtTextService.h b/src/edt/edt/edtTextService.h index 47f7a9645..0badada54 100644 --- a/src/edt/edt/edtTextService.h +++ b/src/edt/edt/edtTextService.h @@ -47,7 +47,7 @@ public: virtual void do_mouse_move (const db::DPoint &p); virtual void do_mouse_move_inactive (const db::DPoint &p); virtual bool do_mouse_click (const db::DPoint &p); - virtual void do_finish_edit (); + virtual void do_finish_edit (bool); virtual void do_cancel_edit (); virtual bool do_activated (); virtual bool selection_applies (const lay::ObjectInstPath &sel) const; diff --git a/src/layview/layview/layEditorOptionsPageWidget.cc b/src/layview/layview/layEditorOptionsPageWidget.cc index c56c4509c..df087615b 100644 --- a/src/layview/layview/layEditorOptionsPageWidget.cc +++ b/src/layview/layview/layEditorOptionsPageWidget.cc @@ -82,9 +82,11 @@ void EditorOptionsPageWidget::keyPressEvent (QKeyEvent *event) { BEGIN_PROTECTED + if (! is_modal_page () && event->modifiers () == Qt::NoModifier && (event->key () == Qt::Key_Return || event->key () == Qt::Key_Enter || event->key () == Qt::Key_Escape)) { + if (event->key () == Qt::Key_Escape) { // The Escape key creates a call to cancel() cancel (); @@ -93,11 +95,15 @@ BEGIN_PROTECTED // to the view commit (dispatcher ()); } + view ()->set_focus (); + event->accept (); + } else { QWidget::keyPressEvent (event); } + END_PROTECTED } @@ -105,6 +111,7 @@ bool EditorOptionsPageWidget::event (QEvent *event) { if (event->type () == QEvent::ShortcutOverride) { + QKeyEvent *ke = dynamic_cast (event); if (ke->key () == Qt::Key_Escape || ke->key () == Qt::Key_Tab || @@ -115,7 +122,9 @@ EditorOptionsPageWidget::event (QEvent *event) // it in keyPressEvent ke->accept (); } + } + return QWidget::event (event); }