First draft

This commit is contained in:
Matthias Koefferlein 2024-03-30 19:11:15 +01:00
parent 7e8ce51da2
commit b4d1a4a954
5 changed files with 459 additions and 181 deletions

View File

@ -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<EditorHooks> 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<EditorHooks>
@ -69,7 +81,7 @@ public:
{
tl::weak_collection<EditorHooks> 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);
}
}

View File

@ -29,6 +29,7 @@
#include "dbTrans.h"
#include "gsiObject.h"
#include "tlExceptions.h"
#include "tlLog.h"
#include "tlObjectCollection.h"
#include <set>
@ -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<std::string> 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<EditorHooks> &hooks, void (EditorHooks::*meth) ())
{
for (auto h = hooks.begin (); h != hooks.end (); ++h) {
BEGIN_PROTECTED
try {
if (h.operator-> ()) {
(const_cast<EditorHooks *> (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<EditorHooks> &hooks, void (EditorHooks::*meth) (A1), A1 a1)
{
for (auto h = hooks.begin (); h != hooks.end (); ++h) {
BEGIN_PROTECTED
try {
if (h.operator-> ()) {
(const_cast<EditorHooks *> (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<EditorHooks> &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<EditorHooks *> (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<EditorHooks> &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<EditorHooks *> (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
}
}

View File

@ -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 <class Shape>
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<const lay::ObjectInstPath &, const db::CplxTrans &> (m_editor_hooks, &edt::EditorHooks::create, path, trans ().inverted ());
}
// explicit instantiations
template void ShapeEditService::deliver_shape_to_hooks<db::Polygon> (const db::Polygon &);
template void ShapeEditService::deliver_shape_to_hooks<db::Path> (const db::Path &);
template void ShapeEditService::deliver_shape_to_hooks<db::Box> (const db::Box &);
template void ShapeEditService::deliver_shape_to_hooks<db::Point> (const db::Point &);
template void ShapeEditService::deliver_shape_to_hooks<db::Text> (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<db::Point> 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<db::DPoint>::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 <db::cell_index_type> 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<const lay::ObjectInstPath &, const db::CplxTrans &> (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

View File

@ -26,6 +26,7 @@
#include "edtService.h"
#include "edtConfig.h"
#include "edtEditorHooks.h"
#include <memory>
@ -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 <class Shape>
void deliver_shape_to_hooks (const Shape &shape);
void close_editor_hooks (bool with_commit);
const tl::weak_collection<edt::EditorHooks> &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<edt::EditorHooks> m_editor_hooks;
std::unique_ptr<db::Shapes> 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<edt::EditorHooks> 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<edt::EditorHooks> &editor_hooks ()
{
return m_editor_hooks;
}
};
}

View File

@ -28,143 +28,21 @@
namespace gsi
{
gsi::Class<edt::EditorHooks> 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, lay::LayoutView *> (&edt::EditorHooks::begin_create, view);
f_begin_create.issue<edt::EditorHooks, lay::LayoutViewBase *> (&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, const lay::ObjectInstPath &, double> (&edt::EditorHooks::create, object, dbu);
f_create.issue<edt::EditorHooks, const lay::ObjectInstPath &, const db::CplxTrans &> (&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, lay::LayoutView *> (&edt::EditorHooks::begin_modify, view);
f_begin_modify.issue<edt::EditorHooks, lay::LayoutViewBase *> (&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, const lay::ObjectInstPath &, double> (&edt::EditorHooks::modified, object, dbu);
f_modified.issue<edt::EditorHooks, const lay::ObjectInstPath &, const db::CplxTrans &> (&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, lay::LayoutView *> (&edt::EditorHooks::begin_edit, view);
f_begin_edit.issue<edt::EditorHooks, lay::LayoutViewBase *> (&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, const lay::ObjectInstPath &, const db::DCplxTrans &, double> (&edt::EditorHooks::transformed, object, trans, dbu);
f_transformed.issue<edt::EditorHooks, const lay::ObjectInstPath &, const db::ICplxTrans &, const db::CplxTrans &> (&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<EditorHooksImpl> 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", &register_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."