mirror of https://github.com/KLayout/klayout.git
API enhancements for annotation template management
This commit is contained in:
parent
84cdefccf6
commit
a853ed904f
|
|
@ -62,6 +62,25 @@ PluginDeclaration::instance ()
|
|||
return sp_instance;
|
||||
}
|
||||
|
||||
static std::vector<ant::Template> make_standard_templates ()
|
||||
{
|
||||
std::vector<ant::Template> templates;
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Ruler")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_ruler"));
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Cross")), "", "", "$U,$V", ant::Object::STY_cross_both, ant::Object::OL_diag, true, lay::AC_Global, "_cross"));
|
||||
templates.back ().set_mode (ant::Template::RulerSingleClick);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Measure")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure"));
|
||||
templates.back ().set_mode (ant::Template::RulerAutoMetric);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Ellipse")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_ellipse, true, lay::AC_Global, std::string ()));
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Box")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_box, true, lay::AC_Global, std::string ()));
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
void
|
||||
PluginDeclaration::get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
||||
{
|
||||
|
|
@ -72,7 +91,7 @@ PluginDeclaration::get_options (std::vector < std::pair<std::string, std::string
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_snap_mode, ACConverter ().to_string (lay::AC_Any)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_obj_snap, tl::to_string (true)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_grid_snap, tl::to_string (false)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_templates, ""));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_templates, ant::TemplatesConverter ().to_string (make_standard_templates ())));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_current_ruler_template, "0"));
|
||||
// grid-micron is not configured here since some other entity is supposed to do this.
|
||||
}
|
||||
|
|
@ -189,21 +208,7 @@ PluginDeclaration::initialized (lay::Dispatcher *root)
|
|||
// This is the migration path from <= 0.24 to 0.25: clear all templates unless we
|
||||
// have categorized ones there. Those can't be deleted, so we know we have a 0.25
|
||||
// setup if there are some
|
||||
m_templates.clear ();
|
||||
|
||||
// Set up the templates we want to see (plus some non-categorized templates)
|
||||
|
||||
m_templates.push_back (ant::Template (tl::to_string (tr ("Ruler")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_ruler"));
|
||||
|
||||
m_templates.push_back (ant::Template (tl::to_string (tr ("Cross")), "", "", "$U,$V", ant::Object::STY_cross_both, ant::Object::OL_diag, true, lay::AC_Global, "_cross"));
|
||||
m_templates.back ().set_mode (ant::Template::RulerSingleClick);
|
||||
|
||||
m_templates.push_back (ant::Template (tl::to_string (tr ("Measure")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure"));
|
||||
m_templates.back ().set_mode (ant::Template::RulerAutoMetric);
|
||||
|
||||
m_templates.push_back (ant::Template (tl::to_string (tr ("Ellipse")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_ellipse, true, lay::AC_Global, std::string ()));
|
||||
|
||||
m_templates.push_back (ant::Template (tl::to_string (tr ("Box")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_box, true, lay::AC_Global, std::string ()));
|
||||
m_templates = make_standard_templates ();
|
||||
|
||||
root->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (m_templates));
|
||||
root->config_end ();
|
||||
|
|
@ -292,7 +297,7 @@ PluginDeclaration::update_menu ()
|
|||
}
|
||||
|
||||
void
|
||||
PluginDeclaration::register_annotation_template (const ant::Template &t)
|
||||
PluginDeclaration::register_annotation_template (const ant::Template &t, lay::Plugin *plugin)
|
||||
{
|
||||
if (t.category ().empty ()) {
|
||||
return;
|
||||
|
|
@ -305,8 +310,38 @@ PluginDeclaration::register_annotation_template (const ant::Template &t)
|
|||
}
|
||||
|
||||
m_templates.push_back (t);
|
||||
lay::Dispatcher::instance ()->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (m_templates));
|
||||
lay::Dispatcher::instance ()->config_end ();
|
||||
|
||||
if (! plugin) {
|
||||
plugin = lay::Dispatcher::instance ();
|
||||
}
|
||||
if (plugin) {
|
||||
plugin->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (m_templates));
|
||||
plugin->config_end ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginDeclaration::unregister_annotation_template (const std::string &category, lay::Plugin *plugin)
|
||||
{
|
||||
std::vector<ant::Template> tpl;
|
||||
|
||||
if (! category.empty ()) {
|
||||
for (auto i = m_templates.begin (); i != m_templates.end (); ++i) {
|
||||
if (i->category () != category) {
|
||||
tpl.push_back (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_templates.swap (tpl);
|
||||
|
||||
if (! plugin) {
|
||||
plugin = lay::Dispatcher::instance ();
|
||||
}
|
||||
if (plugin) {
|
||||
plugin->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (m_templates));
|
||||
plugin->config_end ();
|
||||
}
|
||||
}
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new ant::PluginDeclaration (), 3000, "ant::Plugin");
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ public:
|
|||
virtual void uninitialize (lay::Dispatcher *);
|
||||
virtual bool menu_activated (const std::string &symbol) const;
|
||||
|
||||
void register_annotation_template (const ant::Template &t);
|
||||
void register_annotation_template (const ant::Template &t, lay::Plugin *plugin = 0);
|
||||
void unregister_annotation_template (const std::string &category, lay::Plugin *plugin = 0);
|
||||
|
||||
static PluginDeclaration *instance ();
|
||||
|
||||
|
|
|
|||
|
|
@ -481,6 +481,14 @@ public:
|
|||
*/
|
||||
ant::Object create_measure_ruler(const db::DPoint &pt, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Gets the annotation templates
|
||||
*/
|
||||
const std::vector<ant::Template> &ruler_templates () const
|
||||
{
|
||||
return m_ruler_templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief An event triggered when the annotations changed
|
||||
* When an annotation is added or removed, this event is triggered.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,32 @@
|
|||
namespace ant
|
||||
{
|
||||
|
||||
ant::Template
|
||||
Template::from_object (const ant::Object &a, const std::string &title, int mode)
|
||||
{
|
||||
ant::Template t;
|
||||
|
||||
t.angle_constraint (a.angle_constraint ());
|
||||
t.category (a.category ());
|
||||
t.fmt (a.fmt ());
|
||||
t.fmt_x (a.fmt_x ());
|
||||
t.fmt_y (a.fmt_y ());
|
||||
t.set_main_position (a.main_position ());
|
||||
t.set_main_xalign (a.main_xalign ());
|
||||
t.set_main_yalign (a.main_yalign ());
|
||||
t.set_xlabel_xalign (a.xlabel_xalign ());
|
||||
t.set_xlabel_yalign (a.xlabel_yalign ());
|
||||
t.set_ylabel_xalign (a.ylabel_xalign ());
|
||||
t.set_ylabel_yalign (a.ylabel_yalign ());
|
||||
t.outline (a.outline ());
|
||||
t.style (a.style ());
|
||||
t.title (title);
|
||||
|
||||
t.set_mode (ant::Template::ruler_mode_type (mode));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
Template::Template ()
|
||||
: m_title (tl::to_string (tr ("Ruler"))),
|
||||
m_fmt_x ("$X"), m_fmt_y ("$Y"), m_fmt ("$D"),
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ public:
|
|||
RulerAutoMetric = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a template from a ruler object
|
||||
*
|
||||
* This will ignore the positions of the ruler but use the properties to
|
||||
* initialize the template.
|
||||
*/
|
||||
static ant::Template from_object (const ant::Object &object, const std::string &title, int mode);
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*
|
||||
|
|
|
|||
|
|
@ -427,47 +427,68 @@ static int ruler_mode_auto_metric ()
|
|||
|
||||
static void register_annotation_template (const ant::Object &a, const std::string &title, int mode)
|
||||
{
|
||||
ant::Template t;
|
||||
|
||||
t.angle_constraint (a.angle_constraint ());
|
||||
t.category (a.category ());
|
||||
t.fmt (a.fmt ());
|
||||
t.fmt_x (a.fmt_x ());
|
||||
t.fmt_y (a.fmt_y ());
|
||||
t.set_main_position (a.main_position ());
|
||||
t.set_main_xalign (a.main_xalign ());
|
||||
t.set_main_yalign (a.main_yalign ());
|
||||
t.set_xlabel_xalign (a.xlabel_xalign ());
|
||||
t.set_xlabel_yalign (a.xlabel_yalign ());
|
||||
t.set_ylabel_xalign (a.ylabel_xalign ());
|
||||
t.set_ylabel_yalign (a.ylabel_yalign ());
|
||||
t.outline (a.outline ());
|
||||
t.style (a.style ());
|
||||
t.title (title);
|
||||
|
||||
t.set_mode (ant::Template::ruler_mode_type (mode));
|
||||
ant::Template t = ant::Template::from_object (a, title, mode);
|
||||
|
||||
if (ant::PluginDeclaration::instance ()) {
|
||||
ant::PluginDeclaration::instance ()->register_annotation_template (t);
|
||||
}
|
||||
}
|
||||
|
||||
static void register_annotation_template2 (lay::LayoutViewBase *view, const ant::Object &a, const std::string &title, int mode)
|
||||
{
|
||||
ant::Template t = ant::Template::from_object (a, title, mode);
|
||||
|
||||
if (ant::PluginDeclaration::instance ()) {
|
||||
ant::PluginDeclaration::instance ()->register_annotation_template (t, view);
|
||||
}
|
||||
}
|
||||
|
||||
static void unregister_annotation_template (const std::string &category)
|
||||
{
|
||||
if (ant::PluginDeclaration::instance ()) {
|
||||
ant::PluginDeclaration::instance ()->unregister_annotation_template (category);
|
||||
}
|
||||
}
|
||||
|
||||
static void unregister_annotation_template2 (lay::LayoutViewBase *view, const std::string &category)
|
||||
{
|
||||
if (ant::PluginDeclaration::instance ()) {
|
||||
ant::PluginDeclaration::instance ()->unregister_annotation_template (category, view);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: ant::Object is available as "BasicAnnotation" to allow binding for other methods.
|
||||
gsi::Class<ant::Object> decl_BasicAnnotation ("lay", "BasicAnnotation", gsi::Methods (), "@hide\n@alias Annotation");
|
||||
|
||||
gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotation",
|
||||
gsi::method ("register_template", &gsi::register_annotation_template,
|
||||
gsi::arg ("annotation"), gsi::arg ("title"), gsi::arg ("mode", ruler_mode_normal (), "\\RulerModeNormal"),
|
||||
"@brief Registers the given annotation as a template\n"
|
||||
"@brief Registers the given annotation as a template globally\n"
|
||||
"@annotation The annotation to use for the template (positions are ignored)\n"
|
||||
"@param title The title to use for the ruler template\n"
|
||||
"@param mode The mode the ruler will be created in (see Ruler... constants)\n"
|
||||
"\n"
|
||||
"In order to register a system template, the category string of the annotation should be "
|
||||
"In order to register a system template, the category string of the annotation has to be "
|
||||
"a unique and non-empty string. The annotation is added to the list of annotation templates "
|
||||
"and becomes available as a new template in the ruler drop-down menu.\n"
|
||||
"\n"
|
||||
"The new annotation template is registered on all views.\n"
|
||||
"\n"
|
||||
"NOTE: this setting is persisted and the the application configuration is updated.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.25."
|
||||
) +
|
||||
gsi::method ("unregister_templates", &gsi::unregister_annotation_template,
|
||||
gsi::arg ("category"),
|
||||
"@brief Unregisters the template or templates with the given category string globally\n"
|
||||
"\n"
|
||||
"This method will remove all templates with the given category string. If the category string is empty, "
|
||||
"all templates are removed.\n"
|
||||
"\n"
|
||||
"NOTE: this setting is persisted and the the application configuration is updated.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.28."
|
||||
) +
|
||||
gsi::method ("RulerModeNormal", &gsi::ruler_mode_normal,
|
||||
"@brief Specifies normal ruler mode for the \\register_template method\n"
|
||||
"\n"
|
||||
|
|
@ -988,6 +1009,25 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"@/code\n"
|
||||
);
|
||||
|
||||
static std::vector<std::vector<tl::Variant> > get_annotation_templates (lay::LayoutViewBase *view)
|
||||
{
|
||||
ant::Service *ant_service = view->get_plugin <ant::Service> ();
|
||||
tl_assert (ant_service != 0);
|
||||
|
||||
std::vector<std::vector<tl::Variant> > ant_objects;
|
||||
const std::vector<ant::Template> &ruler_templates = ant_service->ruler_templates ();
|
||||
|
||||
ant_objects.reserve (ruler_templates.size ());
|
||||
for (auto i = ruler_templates.begin (); i != ruler_templates.end (); ++i) {
|
||||
ant_objects.push_back (std::vector<tl::Variant> ());
|
||||
ant_objects.back ().push_back (tl::Variant (gsi::AnnotationRef (ant::Object (db::DPoint (), db::DPoint (), 0, *i), 0)));
|
||||
ant_objects.back ().push_back (tl::Variant (i->title ()));
|
||||
ant_objects.back ().push_back (tl::Variant (int (i->mode ())));
|
||||
}
|
||||
|
||||
return ant_objects;
|
||||
}
|
||||
|
||||
static
|
||||
gsi::ClassExt<lay::LayoutViewBase> layout_view_decl (
|
||||
gsi::method_ext ("clear_annotations", &gsi::clear_annotations,
|
||||
|
|
@ -1063,6 +1103,42 @@ gsi::ClassExt<lay::LayoutViewBase> layout_view_decl (
|
|||
"@return The new ruler object\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.26."
|
||||
) +
|
||||
gsi::method_ext ("register_annotation_template", &gsi::register_annotation_template2,
|
||||
gsi::arg ("annotation"), gsi::arg ("title"), gsi::arg ("mode", ruler_mode_normal (), "\\RulerModeNormal"),
|
||||
"@brief Registers the given annotation as a template for this particular view\n"
|
||||
"@annotation The annotation to use for the template (positions are ignored)\n"
|
||||
"@param title The title to use for the ruler template\n"
|
||||
"@param mode The mode the ruler will be created in (see Ruler... constants)\n"
|
||||
"\n"
|
||||
"See \\Annotation#register_template for a method doing the same on application level. "
|
||||
"This method is hardly useful normally, but can be used when customizing layout views as "
|
||||
"individual widgets.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("unregister_annotation_templates", &gsi::unregister_annotation_template2,
|
||||
gsi::arg ("category"),
|
||||
"@brief Unregisters the template or templates with the given category string on this particular view\n"
|
||||
"\n"
|
||||
"See \\Annotation#unregister_template for a method doing the same on application level."
|
||||
"This method is hardly useful normally, but can be used when customizing layout views as "
|
||||
"individual widgets.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("annotation_templates", &get_annotation_templates,
|
||||
"@brief Gets a list of \\Annotation objects representing the annotation templates.\n"
|
||||
"\n"
|
||||
"Annotation templates are the rulers available in the ruler drop-down (preset ruler types). "
|
||||
"This method will fetch the templates available. This method returns triplets '(annotation, title, mode)'. "
|
||||
"The first member of the triplet is the annotation object representing the template. The second "
|
||||
"member is the title string displayed in the menu for this templates. The third member is the mode "
|
||||
"value (one of the RulerMode... constants - e.g \\RulerModeNormal).\n"
|
||||
"\n"
|
||||
"The positions of the returned annotation objects are undefined.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
),
|
||||
""
|
||||
);
|
||||
|
|
|
|||
|
|
@ -467,13 +467,27 @@ private:
|
|||
/**
|
||||
* @brief The plugin interface
|
||||
*
|
||||
* Each configurable object must be derived from this interface.
|
||||
* An configurable object can have a parent. This way, a hierarchy
|
||||
* of configurable objects is created. The root object not having a
|
||||
* parent acts as the main entry point: it will try to dispatch
|
||||
* This is a basic interface providing several services in a
|
||||
* hierarchically organized fashion. It also provides a configuration
|
||||
* space (key/value pairs).
|
||||
*
|
||||
* Each object participating in the plugin scheme must be derived from this interface.
|
||||
* An plugin can have a parent. This way, a hierarchy of plugin objects is created.
|
||||
* The root object not having a parent acts as the main entry point: it will try to dispatch
|
||||
* configuration requests to the children.
|
||||
* A node may have a local configuration - it will override any
|
||||
* parent configurations.
|
||||
*
|
||||
* Each node has a local configuration space which overrides the configuration changes
|
||||
* made to be parent.
|
||||
*
|
||||
* Each plugin also has a static or global configuration space inside the
|
||||
* "plugin declaration". Configuration changes made to top level nodes are
|
||||
* reflected in the static space too.
|
||||
*
|
||||
* A "standalone" node is one without a parent, but which does not communicate
|
||||
* with the static configuration space.
|
||||
*
|
||||
* The "Dispatcher" adds the concept of a (singleton) root plugin to this hierarchical
|
||||
* configuration tree.
|
||||
*/
|
||||
|
||||
class LAYBASIC_PUBLIC Plugin
|
||||
|
|
|
|||
|
|
@ -564,6 +564,42 @@ class Ant_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# annotation template registration
|
||||
def test_5
|
||||
|
||||
lv = RBA::LayoutView::new
|
||||
tpl = lv.annotation_templates
|
||||
assert_equal(tpl.size > 0, true) # at least one default template
|
||||
|
||||
lv.unregister_annotation_templates("")
|
||||
|
||||
tpl = lv.annotation_templates
|
||||
assert_equal(tpl.size, 0)
|
||||
|
||||
a = RBA::Annotation::new
|
||||
a.fmt = "U"
|
||||
a.category = "42"
|
||||
lv.register_annotation_template(a, "X", RBA::Annotation::RulerModeSingleClick)
|
||||
|
||||
tpl = lv.annotation_templates
|
||||
assert_equal(tpl.size, 1)
|
||||
assert_equal(tpl[0].size, 3)
|
||||
(a, title, mode) = tpl[0]
|
||||
assert_equal(a.fmt, "U")
|
||||
assert_equal(a.category, "42")
|
||||
assert_equal(title, "X")
|
||||
assert_equal(mode, RBA::Annotation::RulerModeSingleClick)
|
||||
|
||||
lv.unregister_annotation_templates("X")
|
||||
tpl = lv.annotation_templates
|
||||
assert_equal(tpl.size, 1)
|
||||
|
||||
lv.unregister_annotation_templates("42")
|
||||
tpl = lv.annotation_templates
|
||||
assert_equal(tpl.size, 0)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue