From b4d1a4a95482dd702ac263da740a1981a08c7d2e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 30 Mar 2024 19:11:15 +0100 Subject: [PATCH] First draft --- src/edt/edt/edtEditorHooks.cc | 24 ++- src/edt/edt/edtEditorHooks.h | 62 ++++-- src/edt/edt/edtServiceImpl.cc | 228 ++++++++++++++++++-- src/edt/edt/edtServiceImpl.h | 23 +- src/edt/edt/gsiDeclEdtEditorHooks.cc | 303 ++++++++++++++------------- 5 files changed, 459 insertions(+), 181 deletions(-) diff --git a/src/edt/edt/edtEditorHooks.cc b/src/edt/edt/edtEditorHooks.cc index eaca9b718..49b866769 100644 --- a/src/edt/edt/edtEditorHooks.cc +++ b/src/edt/edt/edtEditorHooks.cc @@ -59,9 +59,21 @@ public: return sp_instance; } - void register_editor_hook (EditorHooks *hook) + void register_editor_hooks (EditorHooks *hooks, const std::string &name) { - m_hooks.push_back (hook); + // needed, so we do not loose the object in case we erase it: + tl::shared_ptr tmp (hooks); + + // remove other hooks with the same name or with an identical address + for (auto h = m_hooks.begin (); h != m_hooks.end (); ) { + auto hh = h++; + if (hh.operator-> () && (hh.operator-> () == hooks || hh->name () == name)) { + m_hooks.erase (hh); + } + } + + hooks->set_name (name); + m_hooks.push_back (hooks); } tl::weak_collection @@ -69,7 +81,7 @@ public: { tl::weak_collection res; for (auto h = m_hooks.begin (); h != m_hooks.end (); ++h) { - if (! h->for_technologies () || h->is_for_technology (for_technology)) { + if (h.operator-> () && (! h->for_technologies () || h->is_for_technology (for_technology))) { res.push_back (h.operator-> ()); } } @@ -128,11 +140,11 @@ EditorHooks::add_technology (const std::string &tech) } void -EditorHooks::register_editor_hook (EditorHooks *hook) +EditorHooks::register_editor_hooks (EditorHooks *hooks, const std::string &name) { if (EditorHooksManager::instance ()) { - hook->keep (); - EditorHooksManager::instance ()->register_editor_hook (hook); + hooks->keep (); + EditorHooksManager::instance ()->register_editor_hooks (hooks, name); } } diff --git a/src/edt/edt/edtEditorHooks.h b/src/edt/edt/edtEditorHooks.h index 076fa193b..893562147 100644 --- a/src/edt/edt/edtEditorHooks.h +++ b/src/edt/edt/edtEditorHooks.h @@ -29,6 +29,7 @@ #include "dbTrans.h" #include "gsiObject.h" #include "tlExceptions.h" +#include "tlLog.h" #include "tlObjectCollection.h" #include @@ -36,7 +37,7 @@ namespace lay { - class LayoutView; + class LayoutViewBase; class ObjectInstPath; } @@ -72,6 +73,10 @@ class EDT_PUBLIC EditorHooks public: /** * @brief Constructor + * + * The name is arbitrary, but should be unique, as hooks with the + * same name replace each other. This is a debugging aid for GSI as we can + * re-register hooks while we keep them in the system. */ EditorHooks (); @@ -81,29 +86,45 @@ public: virtual ~EditorHooks (); // creation protocol - virtual void begin_create (lay::LayoutView * /*view*/) { } + virtual void begin_create (lay::LayoutViewBase * /*view*/) { } virtual void begin_new_objects () { } - virtual void create (const lay::ObjectInstPath & /*object*/, double /*dbu*/) { } + virtual void create (const lay::ObjectInstPath & /*object*/, const db::CplxTrans & /*view_trans*/) { } virtual void end_new_objects () { } virtual void commit_create () { } virtual void end_create () { } // modification protocol - virtual void begin_modify (lay::LayoutView * /*view*/) { } + virtual void begin_modify (lay::LayoutViewBase * /*view*/) { } virtual void begin_modifications () { } - virtual void modified (const lay::ObjectInstPath & /*object*/, double /*dbu*/) { } + virtual void modified (const lay::ObjectInstPath & /*object*/, const db::CplxTrans & /*view_trans*/) { } virtual void end_modifications () { } virtual void commit_modify () { } virtual void end_modify () { } // editing protocol - virtual void begin_edit (lay::LayoutView * /*view*/) { } + virtual void begin_edit (lay::LayoutViewBase * /*view*/) { } virtual void begin_edits () { } - virtual void transformed (const lay::ObjectInstPath & /*object*/, const db::DCplxTrans & /*trans*/, double /*dbu*/) { } + virtual void transformed (const lay::ObjectInstPath & /*object*/, const db::ICplxTrans & /*applied*/, const db::CplxTrans & /*view_trans*/) { } virtual void end_edits () { } virtual void commit_edit () { } virtual void end_edit () { } + /** + * @brief Gets the name + */ + const std::string &name () const + { + return m_name; + } + + /** + * @brief Sets the name + */ + void set_name (const std::string &name) + { + m_name = name; + } + /** * @brief Gets the technology name this hook is associated with * @@ -146,7 +167,7 @@ public: /** * @brief Registers the editor hook */ - static void register_editor_hook (EditorHooks *hook); + static void register_editor_hooks (EditorHooks *hooks, const std::string &name); /** * @brief Gets the editor hooks for a given technology @@ -157,6 +178,7 @@ public: private: std::set m_technologies; + std::string m_name; // no copying. EditorHooks &operator= (const EditorHooks &); @@ -171,15 +193,17 @@ inline void call_editor_hooks (const tl::weak_collection &hooks, void (EditorHooks::*meth) ()) { for (auto h = hooks.begin (); h != hooks.end (); ++h) { -BEGIN_PROTECTED try { if (h.operator-> ()) { (const_cast (h.operator-> ())->*meth) (); } } catch (tl::CancelException &) { return; + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); } -END_PROTECTED } } @@ -194,15 +218,17 @@ inline void call_editor_hooks (const tl::weak_collection &hooks, void (EditorHooks::*meth) (A1), A1 a1) { for (auto h = hooks.begin (); h != hooks.end (); ++h) { -BEGIN_PROTECTED try { if (h.operator-> ()) { (const_cast (h.operator-> ())->*meth) (a1); } } catch (tl::CancelException &) { return; + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); } -END_PROTECTED } } @@ -217,15 +243,17 @@ inline void call_editor_hooks (const tl::weak_collection &hooks, void (EditorHooks::*meth) (A1, A2), A1 a1, A2 a2) { for (auto h = hooks.begin (); h != hooks.end (); ++h) { -BEGIN_PROTECTED try { if (h.operator-> ()) { (const_cast (h.operator-> ())->*meth) (a1, a2); } } catch (tl::CancelException &) { return; + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); } -END_PROTECTED } } @@ -240,15 +268,17 @@ inline void call_editor_hooks (const tl::weak_collection &hooks, void (EditorHooks::*meth) (A1, A2), A1 a1, A2 a2, A3 a3) { for (auto h = hooks.begin (); h != hooks.end (); ++h) { -BEGIN_PROTECTED try { if (h.operator-> ()) { (const_cast (h.operator-> ())->*meth) (a1, a2, a3); } } catch (tl::CancelException &) { return; + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + } catch (std::exception &ex) { + tl::error << ex.what (); } -END_PROTECTED } } diff --git a/src/edt/edt/edtServiceImpl.cc b/src/edt/edt/edtServiceImpl.cc index 2fec150e4..03e11c1ec 100644 --- a/src/edt/edt/edtServiceImpl.cc +++ b/src/edt/edt/edtServiceImpl.cc @@ -131,7 +131,7 @@ ShapeEditService::get_edit_layer () m_cv_index = (unsigned int) cv_index; m_trans = (cl->trans ().front () * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans ()).inverted (); mp_layout = &(cv->layout ()); - mp_cell = &(mp_layout->cell (cv.cell_index ())); + mp_cell = cv.cell (); if (mp_cell->is_proxy ()) { throw tl::Exception (tl::to_string (tr ("Cannot put a shape into a PCell or library cell"))); @@ -157,7 +157,7 @@ ShapeEditService::update_edit_layer (const lay::LayerPropertiesConstIterator &cl return; } - if (cv->layout ().cell (cv.cell_index ()).is_proxy ()) { + if (cv.cell ()->is_proxy ()) { return; } @@ -198,7 +198,7 @@ ShapeEditService::update_edit_layer (const lay::LayerPropertiesConstIterator &cl m_cv_index = (unsigned int) cv_index; m_trans = (cl->trans ().front () * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans ()).inverted (); mp_layout = &(cv->layout ()); - mp_cell = &(mp_layout->cell (cv.cell_index ())); + mp_cell = cv.cell (); current_layer_changed (); } @@ -400,6 +400,62 @@ ShapeEditService::deliver_shape (const db::Point &point) } } +void +ShapeEditService::open_editor_hooks () +{ + std::string technology; + if (mp_layout && mp_layout->technology ()) { + technology = mp_layout->technology ()->name (); + } + + // NOTE: this is a kind of hack - as we want to present the new shape in some + // natural habitat (aka Shapes), we create an artificial Shapes container for holding the + // temporary object. + m_tmp_shapes.reset (new db::Shapes (0, mp_cell, true)); + + m_editor_hooks = edt::EditorHooks::get_editor_hooks (technology); + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::begin_create, view ()); +} + +void +ShapeEditService::close_editor_hooks (bool with_commit) +{ + if (with_commit) { + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::commit_create); + } + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::end_create); + + m_editor_hooks.clear (); + m_tmp_shapes.reset (0); +} + +template +void +ShapeEditService::deliver_shape_to_hooks (const Shape &shape) +{ + if (! mp_cell || ! m_tmp_shapes.get ()) { + return; + } + + m_tmp_shapes->clear (); + db::Shape s = m_tmp_shapes->insert (shape); + + lay::ObjectInstPath path; + path.set_cv_index (m_cv_index); + path.set_layer (m_layer); + path.set_topcell (mp_cell->cell_index ()); + path.set_shape (s); + + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::create, path, trans ().inverted ()); +} + +// explicit instantiations +template void ShapeEditService::deliver_shape_to_hooks (const db::Polygon &); +template void ShapeEditService::deliver_shape_to_hooks (const db::Path &); +template void ShapeEditService::deliver_shape_to_hooks (const db::Box &); +template void ShapeEditService::deliver_shape_to_hooks (const db::Point &); +template void ShapeEditService::deliver_shape_to_hooks (const db::Text &); + // ----------------------------------------------------------------------------- // PolygonService implementation @@ -433,6 +489,8 @@ PolygonService::do_begin_edit (const db::DPoint &p) m_points.push_back (pp); m_closure_set = false; + open_editor_hooks (); + update_marker (); } @@ -503,26 +561,30 @@ PolygonService::do_mouse_click (const db::DPoint &p) void PolygonService::do_finish_edit () { - deliver_shape (get_polygon ()); + deliver_shape (get_polygon (false)); commit_recent (view ()); + close_editor_hooks (true); } db::Polygon -PolygonService::get_polygon () const +PolygonService::get_polygon (bool all_points) const { db::Polygon poly; - if (m_points.size () < 4) { + if (m_points.size () + (m_closure_set ? 1 : 0) < (all_points ? 3 : 4)) { throw tl::Exception (tl::to_string (tr ("A polygon must have at least 3 points"))); } std::vector points_dbu; - points_dbu.reserve (m_points.size ()); + points_dbu.reserve (m_points.size () + 1); // one point is reserved for the current one for (std::vector::const_iterator p = m_points.begin (); p + 1 != m_points.end (); ++p) { points_dbu.push_back (trans () * *p); } + if (all_points) { + points_dbu.push_back (trans () * m_points.back ()); + } if (m_closure_set) { points_dbu.push_back (trans () * m_closure); } @@ -539,7 +601,7 @@ PolygonService::get_polygon () const void PolygonService::do_cancel_edit () { - // .. nothing yet .. + close_editor_hooks (false); } bool @@ -732,6 +794,17 @@ PolygonService::update_marker () std::string (" l: ") + tl::micron_to_string (m_points.back ().distance (m_points.end () [-2]))); } + + // call hooks with new shape + if (! editor_hooks ().empty ()) { + call_editor_hooks (editor_hooks (), &edt::EditorHooks::begin_new_objects); + try { + deliver_shape_to_hooks (get_polygon (true)); + } catch (...) { + // ignore exceptions + } + call_editor_hooks (editor_hooks (), &edt::EditorHooks::end_new_objects); + } } // ----------------------------------------------------------------------------- @@ -761,6 +834,8 @@ BoxService::do_begin_edit (const db::DPoint &p) db::DPoint pp = snap2 (p); m_p1 = m_p2 = pp; + open_editor_hooks (); + set_edit_marker (new lay::Marker (view (), cv_index ())); update_marker (); } @@ -785,6 +860,17 @@ BoxService::update_marker () tl::micron_to_string (m_p2.y () - m_p1.y ())); } + + // call hooks with new shape + if (! editor_hooks ().empty ()) { + call_editor_hooks (editor_hooks (), &edt::EditorHooks::begin_new_objects); + try { + deliver_shape_to_hooks (get_box ()); + } catch (...) { + // ignore exceptions + } + call_editor_hooks (editor_hooks (), &edt::EditorHooks::end_new_objects); + } } void @@ -816,12 +902,13 @@ BoxService::do_finish_edit () { deliver_shape (get_box ()); commit_recent (view ()); + close_editor_hooks (true); } void BoxService::do_cancel_edit () { - // .. nothing yet .. + close_editor_hooks (false); } bool @@ -857,6 +944,8 @@ PointService::do_begin_edit (const db::DPoint &p) db::DPoint pp = snap2 (p); m_p = pp; + open_editor_hooks (); + set_edit_marker (new lay::Marker (view (), cv_index ())); update_marker (); } @@ -882,6 +971,17 @@ PointService::update_marker () tl::micron_to_string (m_p.y ())); } + + // call hooks with new shape + if (! editor_hooks ().empty ()) { + call_editor_hooks (editor_hooks (), &edt::EditorHooks::begin_new_objects); + try { + deliver_shape_to_hooks (get_point ()); + } catch (...) { + // ignore exceptions + } + call_editor_hooks (editor_hooks (), &edt::EditorHooks::end_new_objects); + } } void @@ -913,12 +1013,13 @@ PointService::do_finish_edit () { deliver_shape (get_point ()); commit_recent (view ()); + close_editor_hooks (true); } void PointService::do_cancel_edit () { - // .. nothing yet .. + close_editor_hooks (false); } bool @@ -959,6 +1060,8 @@ TextService::do_begin_edit (const db::DPoint &p) m_text.trans (db::DTrans (m_rot, snap2 (p) - db::DPoint ())); + open_editor_hooks (); + lay::DMarker *marker = new lay::DMarker (view ()); marker->set_vertex_shape (lay::ViewOp::Cross); marker->set_vertex_size (9 /*cross vertex size*/); @@ -985,6 +1088,17 @@ TextService::update_marker () view ()->message (pos); } + + // call hooks with new shape + if (! editor_hooks ().empty ()) { + call_editor_hooks (editor_hooks (), &edt::EditorHooks::begin_new_objects); + try { + deliver_shape_to_hooks (get_text ()); + } catch (...) { + // ignore exceptions + } + call_editor_hooks (editor_hooks (), &edt::EditorHooks::end_new_objects); + } } bool @@ -1065,12 +1179,14 @@ TextService::do_finish_edit () } #endif + + close_editor_hooks (true); } void TextService::do_cancel_edit () { - // .. nothing yet .. + close_editor_hooks (false); } bool @@ -1166,6 +1282,8 @@ PathService::do_begin_edit (const db::DPoint &p) m_points.push_back (pp); m_points.push_back (pp); + open_editor_hooks (); + set_edit_marker (new lay::Marker (view (), cv_index ())); update_marker (); } @@ -1250,6 +1368,8 @@ PathService::do_finish_edit () deliver_shape (get_path ()); commit_recent (view ()); + + close_editor_hooks (true); } void @@ -1271,6 +1391,17 @@ PathService::update_marker () } } + + // call hooks with new shape + if (! editor_hooks ().empty ()) { + call_editor_hooks (editor_hooks (), &edt::EditorHooks::begin_new_objects); + try { + deliver_shape_to_hooks (get_path ()); + } catch (...) { + // ignore exceptions + } + call_editor_hooks (editor_hooks (), &edt::EditorHooks::end_new_objects); + } } db::Path @@ -1305,7 +1436,7 @@ PathService::get_path () const void PathService::do_cancel_edit () { - // .. nothing yet .. + close_editor_hooks (false); } bool @@ -1582,6 +1713,8 @@ InstService::do_begin_edit (const db::DPoint &p) m_trans = db::VCplxTrans (1.0 / cv->layout ().dbu ()) * tv [0] * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans (); } + open_editor_hooks (); + update_marker (); } @@ -1756,7 +1889,7 @@ InstService::do_finish_edit () cv->layout ().cell (inst.object ().cell_index ()).collect_called_cells (called); called.insert (inst.object ().cell_index ()); - cv->layout ().cell (cv.cell_index ()).collect_caller_cells (callers); + cv.cell ()->collect_caller_cells (callers); callers.insert (cv.cell_index ()); std::vector intersection; @@ -1769,7 +1902,7 @@ InstService::do_finish_edit () manager ()->transaction (tl::to_string (tr ("Create instance")), m_reference_transaction_id); } m_reference_transaction_id = 0; - db::Instance i = cv->layout ().cell (cv.cell_index ()).insert (inst); + db::Instance i = cv.cell ()->insert (inst); cv->layout ().cleanup (); if (manager ()) { manager ()->commit (); @@ -1792,10 +1925,12 @@ InstService::do_finish_edit () m_has_valid_cell = false; m_in_drag_drop = false; + close_editor_hooks (true); } catch (...) { m_has_valid_cell = false; m_in_drag_drop = false; + close_editor_hooks (false); throw; } } @@ -1819,6 +1954,8 @@ InstService::do_cancel_edit () if (cv.is_valid ()) { cv->layout ().cleanup (); } + + close_editor_hooks (false); } void @@ -2128,6 +2265,41 @@ InstService::update_marker () } else { set_edit_marker (0); } + + // call hooks with new shape + if (! editor_hooks ().empty ()) { + + call_editor_hooks (editor_hooks (), &edt::EditorHooks::begin_new_objects); + + try { + + const lay::CellView &cv = view ()->cellview (m_cv_index); + + db::CellInstArray inst; + if (cv.is_valid () && get_inst (inst)) { + + // Note: we create a temporary instance collection and a temporary + // ObjectInstPath object there, so + db::Instances instances (cv.cell ()); + + lay::ObjectInstPath path; + path.set_cv_index (m_cv_index); + path.set_topcell (cv.cell_index ()); + path.add_path (db::InstElement (instances.insert (inst))); + + db::CplxTrans view_trans = db::CplxTrans (cv->layout ().dbu ()) * m_trans; + + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::create, path, view_trans); + + } + + } catch (...) { + // ignore exceptions + } + + call_editor_hooks (editor_hooks (), &edt::EditorHooks::end_new_objects); + + } } bool @@ -2159,6 +2331,34 @@ InstService::get_inst (db::CellInstArray &inst) return false; } +void +InstService::open_editor_hooks () +{ + const lay::CellView &cv = view ()->cellview (m_cv_index); + if (! cv.is_valid ()) { + return; + } + + std::string technology; + if (cv->layout ().technology ()) { + technology = cv->layout ().technology ()->name (); + } + + m_editor_hooks = edt::EditorHooks::get_editor_hooks (technology); + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::begin_create, view ()); +} + +void +InstService::close_editor_hooks (bool with_commit) +{ + if (with_commit) { + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::commit_create); + } + call_editor_hooks (m_editor_hooks, &edt::EditorHooks::end_create); + + m_editor_hooks.clear (); +} + } // namespace edt diff --git a/src/edt/edt/edtServiceImpl.h b/src/edt/edt/edtServiceImpl.h index d799aa8ee..747597ec4 100644 --- a/src/edt/edt/edtServiceImpl.h +++ b/src/edt/edt/edtServiceImpl.h @@ -26,6 +26,7 @@ #include "edtService.h" #include "edtConfig.h" +#include "edtEditorHooks.h" #include @@ -68,6 +69,16 @@ protected: void deliver_shape (const db::Path &path); void deliver_shape (const db::Box &box); void deliver_shape (const db::Point &point); + void open_editor_hooks (); + template + void deliver_shape_to_hooks (const Shape &shape); + void close_editor_hooks (bool with_commit); + + const tl::weak_collection &editor_hooks () + { + return m_editor_hooks; + } + virtual void current_layer_changed () { } private: @@ -77,6 +88,8 @@ private: db::Cell *mp_cell; db::Layout *mp_layout; combine_mode_type m_combine_mode; + tl::weak_collection m_editor_hooks; + std::unique_ptr m_tmp_shapes; void update_edit_layer (const lay::LayerPropertiesConstIterator &iter); }; @@ -109,7 +122,7 @@ private: db::DPoint m_last; void update_marker (); - db::Polygon get_polygon () const; + db::Polygon get_polygon (bool all_points) const; void add_closure (); void set_last_point (const db::DPoint &p); }; @@ -298,6 +311,7 @@ private: const db::PCellDeclaration *mp_pcell_decl; int m_cv_index; db::ICplxTrans m_trans; + tl::weak_collection m_editor_hooks; void update_marker (); bool get_inst (db::CellInstArray &inst); @@ -305,6 +319,13 @@ private: tl::Variant get_default_layer_for_pcell (); void sync_to_config (); void switch_cell_or_pcell (bool switch_parameters); + void open_editor_hooks (); + void close_editor_hooks (bool with_commit); + + const tl::weak_collection &editor_hooks () + { + return m_editor_hooks; + } }; } diff --git a/src/edt/edt/gsiDeclEdtEditorHooks.cc b/src/edt/edt/gsiDeclEdtEditorHooks.cc index 5350014c2..19508939e 100644 --- a/src/edt/edt/gsiDeclEdtEditorHooks.cc +++ b/src/edt/edt/gsiDeclEdtEditorHooks.cc @@ -28,143 +28,21 @@ namespace gsi { -gsi::Class decl_EditorHooksBase ("lay", "EditorHooksBase", - gsi::method ("begin_create", &edt::EditorHooks::begin_create, gsi::arg ("view"), - "@brief Creation protocol - begin session\n" - "This method is called to initiate an object creation session. The session is ended with " - "\\end_create. Between these calls, new objects are announced with \\begin_new_objects, " - "\\create and \\end_new_objects calls. These calls are repeated to indicate changes in the objects " - "created.\n" - "\n" - "\\commit_create is called once before \\end_create to indicate that the last set of " - "objects are committed to the database." - ) + - gsi::method ("begin_new_objects", &edt::EditorHooks::begin_new_objects, - "@brief Creation protocol - begin new objects\n" - "See \\begin_create for a description of the protocol." - ) + - gsi::method ("create", &edt::EditorHooks::create, gsi::arg ("object"), gsi::arg ("dbu"), - "@brief Creation protocol - indicate a new object\n" - "See \\begin_create for a description of the protocol." - ) + - gsi::method ("end_new_objects", &edt::EditorHooks::end_new_objects, - "@brief Creation protocol - finish list of new objects\n" - "See \\begin_create for a description of the protocol." - ) + - gsi::method ("commit_create", &edt::EditorHooks::commit_create, - "@brief Creation protocol - commit new objects\n" - "See \\begin_create for a description of the protocol." - ) + - gsi::method ("end_create", &edt::EditorHooks::end_create, - "@brief Creation protocol - finish session\n" - "See \\begin_create for a description of the protocol." - ) + - gsi::method ("begin_modify", &edt::EditorHooks::begin_modify, gsi::arg ("view"), - "@brief Modification protocol - begin session\n" - "This method is called to initiate an object modification session. The session is ended with " - "\\end_modify. Between these calls, modified objects are announced with \\begin_modifications, " - "\\modified and \\end_modifications calls. These calls are repeated to indicate changes in the objects " - "modified while moving the mouse for example.\n" - "\n" - "\\commit_modify is called once before \\end_modify to indicate that the last set of " - "objects are committed to the database." - ) + - gsi::method ("begin_modifications", &edt::EditorHooks::begin_modifications, - "@brief Modification protocol - begin modifications\n" - "See \\begin_modify for a description of the protocol." - ) + - gsi::method ("modified", &edt::EditorHooks::modified, gsi::arg ("object"), gsi::arg ("dbu"), - "@brief Modification protocol - indicate a modified object\n" - "See \\begin_modify for a description of the protocol." - ) + - gsi::method ("end_modifications", &edt::EditorHooks::end_modifications, - "@brief Modification protocol - finish list of modifications\n" - "See \\begin_modify for a description of the protocol." - ) + - gsi::method ("commit_modify", &edt::EditorHooks::commit_modify, - "@brief Modification protocol - commit new objects\n" - "See \\begin_modify for a description of the protocol." - ) + - gsi::method ("end_modify", &edt::EditorHooks::end_modify, - "@brief Modification protocol - finish session\n" - "See \\begin_modify for a description of the protocol." - ) + - gsi::method ("begin_edit", &edt::EditorHooks::begin_edit, gsi::arg ("view"), - "@brief Editing protocol - begin session\n" - "This method is called to initiate an object editing session. The session is ended with " - "\\end_edit. Between these calls, edits are announced with \\begin_edits, " - "\\transformed and \\end_edits calls. These calls are repeated to indicate changes in the objects " - "modified while moving the mouse for example.\n" - "\n" - "\\commit_edit is called once before \\end_edit to indicate that the last set of " - "objects are committed to the database." - ) + - gsi::method ("begin_edits", &edt::EditorHooks::begin_edits, - "@brief Editing protocol - begin edits\n" - "See \\begin_edit for a description of the protocol." - ) + - gsi::method ("transformed", &edt::EditorHooks::transformed, gsi::arg ("object"), gsi::arg ("trans"), gsi::arg ("dbu"), - "@brief Editing protocol - indicate an object transformation\n" - "See \\begin_edit for a description of the protocol." - ) + - gsi::method ("end_edits", &edt::EditorHooks::end_edits, - "@brief Editing protocol - finish list of edits\n" - "See \\begin_edit for a description of the protocol." - ) + - gsi::method ("commit_edit", &edt::EditorHooks::commit_edit, - "@brief Editing protocol - commit new objects\n" - "See \\begin_edit for a description of the protocol." - ) + - gsi::method ("end_edit", &edt::EditorHooks::end_edit, - "@brief Editing protocol - finish session\n" - "See \\begin_edit for a description of the protocol." - ) + - gsi::method ("technology=", &edt::EditorHooks::set_technology, gsi::arg ("technology"), - "@brief sets the name of the technology the hooks are associated with\n" - "This will clear all technology associations and associate the hooks with that technology only.\n" - ) + - gsi::method ("clear_technologies", &edt::EditorHooks::clear_technologies, - "@brief Clears the list of technologies the hooks are associated with.\n" - "See also \\add_technology.\n" - ) + - gsi::method ("add_technology", &edt::EditorHooks::add_technology, gsi::arg ("tech"), - "@brief Additionally associates the hooks with the given technology.\n" - "See also \\clear_technologies.\n" - ) + - gsi::method ("is_for_technology", &edt::EditorHooks::is_for_technology, gsi::arg ("tech"), - "@brief Returns a value indicating whether the hooks are associated with the given technology.\n" - ) + - gsi::method ("for_technologies", &edt::EditorHooks::for_technologies, - "@brief Returns a value indicating whether the hooks are associated with any technology.\n" - "The method is equivalent to checking whether the \\technologies list is empty.\n" - ) + - gsi::method ("technologies", &edt::EditorHooks::get_technologies, - "@brief Gets the list of technologies these hooks are associated with.\n" - ) + - gsi::method ("register", &edt::EditorHooks::register_editor_hook, gsi::arg ("hooks"), - "@brief Registers the hooks in the system.\n" - "The hooks will not be active before they are registered in the system. Registration will " - "also transfer object ownership to the system." - ), - "@brief The base class for editor hooks\n" - "Editor hooks allow implementing technology-specific callbacks into the editor " - "for example to implement visual feedback about DRC rules.\n" - "\n" - "This class provides the basic interface. To implement callbacks, use the \\EditorHooks class." - "\n" - "The EditorHooksBase class has been introduced in version 0.29." -); class EditorHooksImpl : public edt::EditorHooks { public: - EditorHooksImpl () { } + EditorHooksImpl () + : edt::EditorHooks () + { + // .. nothing yet .. + } - virtual void begin_create (lay::LayoutView *view) + virtual void begin_create (lay::LayoutViewBase *view) { if (f_begin_create.can_issue ()) { - f_begin_create.issue (&edt::EditorHooks::begin_create, view); + f_begin_create.issue (&edt::EditorHooks::begin_create, view); } else { edt::EditorHooks::begin_create (view); } @@ -179,12 +57,12 @@ public: } } - virtual void create (const lay::ObjectInstPath &object, double dbu) + virtual void create (const lay::ObjectInstPath &object, const db::CplxTrans &view_trans) { if (f_create.can_issue ()) { - f_create.issue (&edt::EditorHooks::create, object, dbu); + f_create.issue (&edt::EditorHooks::create, object, view_trans); } else { - edt::EditorHooks::create (object, dbu); + edt::EditorHooks::create (object, view_trans); } } @@ -215,10 +93,10 @@ public: } } - virtual void begin_modify (lay::LayoutView *view) + virtual void begin_modify (lay::LayoutViewBase *view) { if (f_begin_modify.can_issue ()) { - f_begin_modify.issue (&edt::EditorHooks::begin_modify, view); + f_begin_modify.issue (&edt::EditorHooks::begin_modify, view); } else { edt::EditorHooks::begin_modify (view); } @@ -233,12 +111,12 @@ public: } } - virtual void modified (const lay::ObjectInstPath &object, double dbu) + virtual void modified (const lay::ObjectInstPath &object, const db::CplxTrans &view_trans) { if (f_modified.can_issue ()) { - f_modified.issue (&edt::EditorHooks::modified, object, dbu); + f_modified.issue (&edt::EditorHooks::modified, object, view_trans); } else { - edt::EditorHooks::modified (object, dbu); + edt::EditorHooks::modified (object, view_trans); } } @@ -269,10 +147,10 @@ public: } } - virtual void begin_edit (lay::LayoutView *view) + virtual void begin_edit (lay::LayoutViewBase *view) { if (f_begin_edit.can_issue ()) { - f_begin_edit.issue (&edt::EditorHooks::begin_edit, view); + f_begin_edit.issue (&edt::EditorHooks::begin_edit, view); } else { edt::EditorHooks::begin_edit (view); } @@ -287,12 +165,12 @@ public: } } - virtual void transformed (const lay::ObjectInstPath &object, const db::DCplxTrans &trans, double dbu) + virtual void transformed (const lay::ObjectInstPath &object, const db::ICplxTrans &applied_trans, const db::CplxTrans &view_trans) { if (f_transformed.can_issue ()) { - f_transformed.issue (&edt::EditorHooks::transformed, object, trans, dbu); + f_transformed.issue (&edt::EditorHooks::transformed, object, applied_trans, view_trans); } else { - edt::EditorHooks::transformed (object, trans, dbu); + edt::EditorHooks::transformed (object, applied_trans, view_trans); } } @@ -345,12 +223,149 @@ public: gsi::Callback f_end_edit; }; +static void register_editor_hooks (EditorHooksImpl *hooks, const std::string &name) +{ + edt::EditorHooks::register_editor_hooks (hooks, name); +} + gsi::Class decl_EditorHooks ("lay", "EditorHooks", - callback ("begin_create", &EditorHooksImpl::begin_create, &EditorHooksImpl::f_begin_create, + gsi::callback ("begin_create", &EditorHooksImpl::begin_create, &EditorHooksImpl::f_begin_create, "@brief Creation protocol - begin session\n" - "See \\EditorHooksBase for a description of the protocol" + "This method is called to initiate an object creation session. The session is ended with " + "\\end_create. Between these calls, new objects are announced with \\begin_new_objects, " + "\\create and \\end_new_objects calls. These calls are repeated to indicate changes in the objects " + "created.\n" + "\n" + "\\commit_create is called once before \\end_create to indicate that the last set of " + "objects are committed to the database." + ) + + gsi::callback ("begin_new_objects", &EditorHooksImpl::begin_new_objects, &EditorHooksImpl::f_begin_new_objects, + "@brief Creation protocol - begin new objects\n" + "See \\begin_create for a description of the protocol." + ) + + gsi::callback ("create", &EditorHooksImpl::create, &EditorHooksImpl::f_create, gsi::arg ("object"), gsi::arg ("view_trans"), + "@brief Creation protocol - indicate a new object\n" + "See \\begin_create for a description of the protocol." + ) + + gsi::callback ("end_new_objects", &EditorHooksImpl::end_new_objects, &EditorHooksImpl::f_end_new_objects, + "@brief Creation protocol - finish list of new objects\n" + "See \\begin_create for a description of the protocol." + ) + + gsi::callback ("commit_create", &EditorHooksImpl::commit_create, &EditorHooksImpl::f_commit_create, + "@brief Creation protocol - commit new objects\n" + "See \\begin_create for a description of the protocol." + ) + + gsi::callback ("end_create", &EditorHooksImpl::end_create, &EditorHooksImpl::f_end_create, + "@brief Creation protocol - finish session\n" + "See \\begin_create for a description of the protocol." + ) + + gsi::callback ("begin_modify", &EditorHooksImpl::begin_modify, &EditorHooksImpl::f_begin_modify, gsi::arg ("view"), + "@brief Modification protocol - begin session\n" + "This method is called to initiate an object modification session. The session is ended with " + "\\end_modify. Between these calls, modified objects are announced with \\begin_modifications, " + "\\modified and \\end_modifications calls. These calls are repeated to indicate changes in the objects " + "modified while moving the mouse for example.\n" + "\n" + "\\commit_modify is called once before \\end_modify to indicate that the last set of " + "objects are committed to the database." + ) + + gsi::callback ("begin_modifications", &EditorHooksImpl::begin_modifications, &EditorHooksImpl::f_begin_modifications, + "@brief Modification protocol - begin modifications\n" + "See \\begin_modify for a description of the protocol." + ) + + gsi::callback ("modified", &EditorHooksImpl::modified, &EditorHooksImpl::f_modified, gsi::arg ("object"), gsi::arg ("view_trans"), + "@brief Modification protocol - indicate a modified object\n" + "See \\begin_modify for a description of the protocol." + ) + + gsi::callback ("end_modifications", &EditorHooksImpl::end_modifications, &EditorHooksImpl::f_end_modifications, + "@brief Modification protocol - finish list of modifications\n" + "See \\begin_modify for a description of the protocol." + ) + + gsi::callback ("commit_modify", &EditorHooksImpl::commit_modify, &EditorHooksImpl::f_commit_modify, + "@brief Modification protocol - commit new objects\n" + "See \\begin_modify for a description of the protocol." + ) + + gsi::callback ("end_modify", &EditorHooksImpl::end_modify, &EditorHooksImpl::f_end_modify, + "@brief Modification protocol - finish session\n" + "See \\begin_modify for a description of the protocol." + ) + + gsi::callback ("begin_edit", &EditorHooksImpl::begin_edit, &EditorHooksImpl::f_begin_edit, gsi::arg ("view"), + "@brief Editing protocol - begin session\n" + "This method is called to initiate an object editing session. The session is ended with " + "\\end_edit. Between these calls, edits are announced with \\begin_edits, " + "\\transformed and \\end_edits calls. These calls are repeated to indicate changes in the objects " + "modified while moving the mouse for example.\n" + "\n" + "\\commit_edit is called once before \\end_edit to indicate that the last set of " + "objects are committed to the database." + ) + + gsi::callback ("begin_edits", &EditorHooksImpl::begin_edits, &EditorHooksImpl::f_begin_edits, + "@brief Editing protocol - begin edits\n" + "See \\begin_edit for a description of the protocol." + ) + + gsi::callback ("transformed", &EditorHooksImpl::transformed, &EditorHooksImpl::f_transformed, gsi::arg ("object"), gsi::arg ("applied_trans"), gsi::arg ("view_trans"), + "@brief Editing protocol - indicate an object transformation\n" + "See \\begin_edit for a description of the protocol.\n" + "\n" + "@param object A path to the modified object\n" + "@param applied_trans The DBU-space of the transformation applied to the object\n" + "@param view_trans The combined transformation of DBU space to view space\n" + ) + + gsi::callback ("end_edits", &EditorHooksImpl::end_edits, &EditorHooksImpl::f_end_edits, + "@brief Editing protocol - finish list of edits\n" + "See \\begin_edit for a description of the protocol." + ) + + gsi::callback ("commit_edit", &EditorHooksImpl::commit_edit, &EditorHooksImpl::f_commit_edit, + "@brief Editing protocol - commit new objects\n" + "See \\begin_edit for a description of the protocol." + ) + + gsi::callback ("end_edit", &EditorHooksImpl::end_edit, &EditorHooksImpl::f_end_edit, + "@brief Editing protocol - finish session\n" + "See \\begin_edit for a description of the protocol." + ) + + gsi::method ("technology=", &EditorHooksImpl::set_technology, gsi::arg ("technology"), + "@brief sets the name of the technology the hooks are associated with\n" + "This will clear all technology associations and associate the hooks with that technology only.\n" + ) + + gsi::method ("clear_technologies", &EditorHooksImpl::clear_technologies, + "@brief Clears the list of technologies the hooks are associated with.\n" + "See also \\add_technology.\n" + ) + + gsi::method ("add_technology", &EditorHooksImpl::add_technology, gsi::arg ("tech"), + "@brief Additionally associates the hooks with the given technology.\n" + "See also \\clear_technologies.\n" + ) + + gsi::method ("is_for_technology", &EditorHooksImpl::is_for_technology, gsi::arg ("tech"), + "@brief Returns a value indicating whether the hooks are associated with the given technology.\n" + ) + + gsi::method ("for_technologies", &EditorHooksImpl::for_technologies, + "@brief Returns a value indicating whether the hooks are associated with any technology.\n" + "The method is equivalent to checking whether the \\technologies list is empty.\n" + ) + + gsi::method ("technologies", &EditorHooksImpl::get_technologies, + "@brief Gets the list of technologies these hooks are associated with.\n" + ) + + gsi::method ("name", &EditorHooksImpl::name, + "@brief Gets the name of the hooks object.\n" + "This is the name, the object was registered under in the system." + ) + + gsi::method_ext ("register", ®ister_editor_hooks, gsi::arg ("name"), + "@brief Registers the hooks in the system.\n" + "The hooks will not be active before they are registered in the system. Registration will " + "also transfer object ownership to the system.\n" + "\n" + "The name is arbitary, but should be unique. Upon registration, this hooks object will " + "replace others with the same name already registered in the system. This will simplify " + "debugging as you can re-run the same code, without accumulating hooks.\n" ), "@brief An implementation base class for editor hooks\n" + "\n" + "Editor hooks allow implementing technology-specific callbacks into the editor " + "for example to implement visual feedback about DRC rules.\n" + "\n" + "This class provides the basic interface. To implement callbacks, use the \\EditorHooks class. " + "You should not need to instantiate this class.\n" + "\n" // @@@ "\n" "The EditorHooks class has been introduced in version 0.29."