diff --git a/src/db/db/dbLibrary.cc b/src/db/db/dbLibrary.cc
index fec55c29b..6c0ca490c 100644
--- a/src/db/db/dbLibrary.cc
+++ b/src/db/db/dbLibrary.cc
@@ -46,6 +46,39 @@ Library::~Library ()
// .. nothing yet ..
}
+bool
+Library::is_for_technology (const std::string &name) const
+{
+ return m_technologies.find (name) != m_technologies.end ();
+}
+
+bool
+Library::for_technologies () const
+{
+ return ! m_technologies.empty ();
+}
+
+void
+Library::set_technology (const std::string &t)
+{
+ m_technologies.clear ();
+ if (! t.empty ()) {
+ m_technologies.insert (t);
+ }
+}
+
+void
+Library::clear_technologies ()
+{
+ m_technologies.clear ();
+}
+
+void
+Library::add_technology (const std::string &tech)
+{
+ m_technologies.insert (tech);
+}
+
void
Library::register_proxy (db::LibraryProxy *lib_proxy, db::Layout *ly)
{
diff --git a/src/db/db/dbLibrary.h b/src/db/db/dbLibrary.h
index 422eec281..21cd70061 100644
--- a/src/db/db/dbLibrary.h
+++ b/src/db/db/dbLibrary.h
@@ -31,6 +31,7 @@
#include "tlObject.h"
#include
+#include
namespace db
{
@@ -108,18 +109,38 @@ public:
* If this attribute is non-empty, the library is selected only when the given technology is
* used for the layout.
*/
- const std::string &get_technology () const
+ const std::set &get_technologies () const
{
- return m_technology;
+ return m_technologies;
}
/**
- * @brief Sets the technology name this library is associated with
+ * @brief Gets a value indicating whether this library is associated with the given technology
*/
- void set_technology (const std::string &t)
- {
- m_technology = t;
- }
+ bool is_for_technology (const std::string &name) const;
+
+ /**
+ * @brief Gets a value indicating whether the library is associated with any technology
+ */
+ bool for_technologies () const;
+
+ /**
+ * @brief Sets the technology name this library is associated with
+ *
+ * This will reset the list of technologies to this one.
+ * If the given technology string is empty, the list of technologies will be cleared.
+ */
+ void set_technology (const std::string &t);
+
+ /**
+ * @brief Clears the list of technologies this library is associated with
+ */
+ void clear_technologies ();
+
+ /**
+ * @brief Additionally associate the library with the given technology
+ */
+ void add_technology (const std::string &tech);
/**
* @brief Getter for the description property
@@ -198,7 +219,7 @@ public:
private:
std::string m_name;
std::string m_description;
- std::string m_technology;
+ std::set m_technologies;
lib_id_type m_id;
db::Layout m_layout;
std::map m_referrers;
diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc
index fff5bea12..98f737d88 100644
--- a/src/db/db/gsiDeclDbLibrary.cc
+++ b/src/db/db/gsiDeclDbLibrary.cc
@@ -68,6 +68,16 @@ static void delete_lib (db::Library *lib)
db::LibraryManager::instance ().delete_lib (lib);
}
+static std::string get_technology (db::Library *lib)
+{
+ const std::set &techs = lib->get_technologies ();
+ if (techs.empty ()) {
+ return std::string ();
+ } else {
+ return *techs.begin ();
+ }
+}
+
Class decl_Library ("db", "Library",
gsi::constructor ("new", &new_lib,
"@brief Creates a new, empty library"
@@ -111,18 +121,47 @@ Class decl_Library ("db", "Library",
gsi::method ("description=", &db::Library::set_description, gsi::arg ("description"),
"@brief Sets the libraries' description text\n"
) +
- gsi::method ("technology", &db::Library::get_technology,
+ gsi::method_ext ("#technology", &get_technology,
"@brief Returns name of the technology the library is associated with\n"
"If this attribute is a non-empty string, this library is only offered for "
"selection if the current layout uses this technology.\n"
"\n"
- "This attribute has been introduced in version 0.25."
+ "This attribute has been introduced in version 0.25. In version 0.27 this attribute is deprecated as "
+ "a library can now be associated with multiple technologies."
) +
gsi::method ("technology=", &db::Library::set_technology, gsi::arg ("technology"),
"@brief sets the name of the technology the library is associated with\n"
"\n"
"See \\technology for details. "
- "This attribute has been introduced in version 0.25."
+ "This attribute has been introduced in version 0.25. In version 0.27, a library can be associated with "
+ "multiple technologies and this method will revert the selection to a single one. Passing an empty string "
+ "is equivalent to \\clear_technologies."
+ ) +
+ gsi::method ("clear_technologies", &db::Library::clear_technologies,
+ "@brief Clears the list of technologies the library is associated with.\n"
+ "See also \\add_technology.\n"
+ "\n"
+ "This method has been introduced in version 0.27"
+ ) +
+ gsi::method ("add_technology", &db::Library::add_technology, gsi::arg ("tech"),
+ "@brief Additionally associates the library with the given technology.\n"
+ "See also \\clear_technologies.\n"
+ "\n"
+ "This method has been introduced in version 0.27"
+ ) +
+ gsi::method ("is_for_technology", &db::Library::is_for_technology, gsi::arg ("tech"),
+ "@brief Returns a value indicating whether the library is associated with the given technology.\n"
+ "This method has been introduced in version 0.27"
+ ) +
+ gsi::method ("for_technologies", &db::Library::for_technologies,
+ "@brief Returns a value indicating whether the library is associated with any technology.\n"
+ "The method is equivalent to checking whether the \\technologies list is empty.\n"
+ "\n"
+ "This method has been introduced in version 0.27"
+ ) +
+ gsi::method ("technologies", &db::Library::get_technologies,
+ "@brief Gets the list of technologies this library is associated with.\n"
+ "This method has been introduced in version 0.27"
) +
gsi::method ("layout_const", (const db::Layout &(db::Library::*)() const) &db::Library::layout,
"@brief The layout object where the cells reside that this library defines (const version)\n"
diff --git a/src/edt/edt/EditorOptionsInst.ui b/src/edt/edt/EditorOptionsInst.ui
index 74a3eb7be..3cd38120a 100644
--- a/src/edt/edt/EditorOptionsInst.ui
+++ b/src/edt/edt/EditorOptionsInst.ui
@@ -1,7 +1,8 @@
-
+
+
EditorOptionsInst
-
-
+
+
0
0
@@ -9,52 +10,66 @@
574
-
+
Form
-
-
- 9
-
-
+
+
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
-
-
+
+
QFrame::NoFrame
-
+
QFrame::Raised
-
-
- 0
-
-
+
+
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
-
-
- 0
- 0
+
+
+
0
0
-
+
Cell
-
-
-
-
- 7
- 0
+
+
+
0
0
@@ -62,47 +77,41 @@
-
-
-
+
+
...
-
-
-
+
+
Library
-
-
-
- -
-
-
- Qt::Horizontal
+
+
+
+ 0
+ 0
+
-
-
- 40
- 20
-
-
-
+
-
-
+
Qt::Vertical
-
+
QSizePolicy::Fixed
-
+
522
8
@@ -111,99 +120,111 @@
-
-
-
-
- 7
- 7
+
+
+
0
1
-
+
0
-
-
+
+
Geometry
-
-
- 9
-
-
+
+
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
-
-
+
+
Rotation / Scaling
-
-
+
+
9
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
6
-
-
-
-
-
- 0
- 0
+
-
+
+
+
0
0
- -
-
-
+
-
+
+
Mirror
-
+
mirror_cbx
- -
-
-
+
-
+
+
Scaling factor (magnification)
- -
-
-
-
- 0
- 0
+
-
+
+
+
0
0
- -
-
-
+
-
+
+
degree
- -
-
-
+
-
+
+
Rotation angle
- -
-
-
+
-
+
+
(at X-axis before rotation)
@@ -212,182 +233,177 @@
-
-
-
-
- 5
- 5
+
+
+
0
0
-
+
Array Instance
-
+
true
-
-
+
+
9
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
6
-
-
-
-
+
-
+
+
Column vector (x,y)
- -
-
-
-
- 0
- 0
+
-
+
+
+
1
0
- -
-
-
+
-
+
+
x =
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
-
- 0
- 0
+
-
+
+
+
1
0
- -
-
-
+
-
+
+
y =
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
-
- 0
- 0
+
-
+
+
+
1
0
- -
-
-
+
-
+
+
y =
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
-
- 0
- 0
+
-
+
+
+
1
0
- -
-
-
+
-
+
+
x =
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
+
-
+
+
Row vector (x,y)
- -
-
-
+
-
+
+
Rows/Columns
- -
-
-
+
-
+
+
columns =
- -
-
-
-
- 0
- 0
+
-
+
+
+
1
0
- -
-
-
+
-
+
+
rows =
- -
-
-
-
- 0
- 0
+
-
+
+
+
1
0
- -
-
-
+
-
+
+
Warning: although row and column vectors can be arbitrary combination,
some design systems only accept orthogonal (rectangular) arrays.
-
+
true
@@ -397,10 +413,10 @@ some design systems only accept orthogonal (rectangular) arrays.
-
-
+
Qt::Vertical
-
+
20
40
@@ -410,26 +426,26 @@ some design systems only accept orthogonal (rectangular) arrays.
-
-
+
+
PCell
-
-
-
+
+
Place origin of cell
-
-
+
Qt::Vertical
-
+
50
8
@@ -462,8 +478,6 @@ some design systems only accept orthogonal (rectangular) arrays.
column_y_le
place_origin_cb
-
-
-
+
diff --git a/src/edt/edt/InstPropertiesPage.ui b/src/edt/edt/InstPropertiesPage.ui
index 0c6eea4c2..ab2f59622 100644
--- a/src/edt/edt/InstPropertiesPage.ui
+++ b/src/edt/edt/InstPropertiesPage.ui
@@ -17,7 +17,16 @@
6
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
9
-
@@ -32,7 +41,16 @@
6
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
@@ -84,7 +102,16 @@
6
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
@@ -119,20 +146,14 @@
-
-
-
- -
-
-
- Qt::Horizontal
+
+
+
+ 0
+ 0
+
-
-
- 40
- 20
-
-
-
+
@@ -178,7 +199,16 @@
6
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
9
-
@@ -190,7 +220,16 @@
QFrame::Raised
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
@@ -265,7 +304,16 @@
Position / Rotation / Scaling
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
9
@@ -393,7 +441,16 @@
true
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
9
@@ -629,7 +686,16 @@ some design systems only accept orthogonal (rectangular) arrays.
6
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
diff --git a/src/lay/lay/layLibraryController.cc b/src/lay/lay/layLibraryController.cc
index b9b304d37..c76f13667 100644
--- a/src/lay/lay/layLibraryController.cc
+++ b/src/lay/lay/layLibraryController.cc
@@ -205,7 +205,7 @@ LibraryController::sync_files ()
}
}
- tl::log << "Registering as '" << lib->get_name () << "' for tech '" << lib->get_technology () << "'";
+ tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'";
new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ())));
db::LibraryManager::instance ().register_lib (lib.release ());
diff --git a/src/lay/lay/layTechSetupDialog.cc b/src/lay/lay/layTechSetupDialog.cc
index e89396411..266c42cf6 100644
--- a/src/lay/lay/layTechSetupDialog.cc
+++ b/src/lay/lay/layTechSetupDialog.cc
@@ -135,7 +135,7 @@ TechBaseEditorPage::setup ()
for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) {
const db::Library *lib = db::LibraryManager::instance ().lib (l->second);
- if (lib->get_technology () == tech ()->name ()) {
+ if (lib->is_for_technology (tech ()->name ())) {
std::string text = lib->get_name ();
if (! lib->get_description ().empty ()) {
text += " - " + lib->get_description ();
diff --git a/src/laybasic/laybasic/layHierarchyControlPanel.cc b/src/laybasic/laybasic/layHierarchyControlPanel.cc
index d983e5b64..5ca8186dc 100644
--- a/src/laybasic/laybasic/layHierarchyControlPanel.cc
+++ b/src/laybasic/laybasic/layHierarchyControlPanel.cc
@@ -213,6 +213,7 @@ HierarchyControlPanel::HierarchyControlPanel (lay::LayoutView *view, QWidget *pa
mp_selector = new QComboBox (this);
mp_selector->setObjectName (QString::fromUtf8 ("cellview_selection"));
+ mp_selector->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed);
ly->addWidget (mp_selector);
mp_search_frame = new QFrame (this);
diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc
index 099c84e63..44d534acf 100644
--- a/src/laybasic/laybasic/layLayoutView.cc
+++ b/src/laybasic/laybasic/layLayoutView.cc
@@ -4739,6 +4739,8 @@ LayoutView::active_library_changed (int /*index*/)
void
LayoutView::cellview_changed (unsigned int index)
{
+ mp_hierarchy_panel->do_update_content (index);
+
cellview_changed_event (index);
if (m_title.empty ()) {
diff --git a/src/laybasic/laybasic/layLibrariesView.cc b/src/laybasic/laybasic/layLibrariesView.cc
index 3ef2bb4b6..5209b6f68 100644
--- a/src/laybasic/laybasic/layLibrariesView.cc
+++ b/src/laybasic/laybasic/layLibrariesView.cc
@@ -210,7 +210,8 @@ LibrariesView::LibrariesView (lay::LayoutView *view, QWidget *parent, const char
ly->setContentsMargins (0, 0, 0, 0);
mp_selector = new QComboBox (this);
- mp_selector->setObjectName (QString::fromUtf8 ("cellview_selection"));
+ mp_selector->setObjectName (QString::fromUtf8 ("library_selection"));
+ mp_selector->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed);
ly->addWidget (mp_selector);
mp_search_frame = new QFrame (this);
@@ -771,9 +772,10 @@ LibrariesView::display_string (int n) const
if (! lib->get_description ().empty ()) {
text += " - " + lib->get_description ();
}
- if (! lib->get_technology ().empty ()) {
+ if (lib->for_technologies ()) {
text += " ";
- text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ())));
+ std::string tn = tl::join (std::vector (lib->get_technologies ().begin (), lib->get_technologies ().end ()), ",");
+ text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (tn)));
}
return text;
}
diff --git a/src/laybasic/laybasic/layWidgets.cc b/src/laybasic/laybasic/layWidgets.cc
index 7c35f9734..aee5a598f 100644
--- a/src/laybasic/laybasic/layWidgets.cc
+++ b/src/laybasic/laybasic/layWidgets.cc
@@ -600,15 +600,16 @@ LibrarySelectionComboBox::update_list ()
for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) {
db::Library *lib = db::LibraryManager::instance ().lib (l->second);
- if (! m_tech_set || lib->get_technology ().empty () || m_tech == lib->get_technology ()) {
+ if (! m_tech_set || !lib->for_technologies ()|| lib->is_for_technology (m_tech)) {
std::string item_text = lib->get_name ();
if (! lib->get_description ().empty ()) {
item_text += " - " + lib->get_description ();
}
- if (m_tech_set && !lib->get_technology ().empty ()) {
+ if (m_tech_set && lib->for_technologies ()) {
item_text += " ";
- item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ())));
+ std::string tn = tl::join (std::vector (lib->get_technologies ().begin (), lib->get_technologies ().end ()), ",");
+ item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (tn)));
}
addItem (tl::to_qstring (item_text), QVariant ((unsigned int) lib->get_id ()));
diff --git a/src/rba/unit_tests/rba.cc b/src/rba/unit_tests/rba.cc
index 924514fc9..af7cb5105 100644
--- a/src/rba/unit_tests/rba.cc
+++ b/src/rba/unit_tests/rba.cc
@@ -104,6 +104,7 @@ RUBYTEST (dbGlyphs, "dbGlyphs.rb")
RUBYTEST (dbInstanceTest, "dbInstanceTest.rb")
RUBYTEST (dbInstElementTest, "dbInstElementTest.rb")
RUBYTEST (dbLayerMapping, "dbLayerMapping.rb")
+RUBYTEST (dbLibrary, "dbLibrary.rb")
RUBYTEST (dbLayout, "dbLayout.rb")
RUBYTEST (dbLayoutTest, "dbLayoutTest.rb")
RUBYTEST (dbLayoutDiff, "dbLayoutDiff.rb")
diff --git a/testdata/ruby/dbLibrary.rb b/testdata/ruby/dbLibrary.rb
new file mode 100644
index 000000000..cd73007a5
--- /dev/null
+++ b/testdata/ruby/dbLibrary.rb
@@ -0,0 +1,93 @@
+# encoding: UTF-8
+
+# KLayout Layout Viewer
+# Copyright (C) 2006-2020 Matthias Koefferlein
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+if !$:.member?(File::dirname($0))
+ $:.push(File::dirname($0))
+end
+
+load("test_prologue.rb")
+
+class DBLibrary_TestClass < TestBase
+
+ def test_1_registration
+
+ lib = RBA::Library::new
+
+ assert_equal(lib.name, "")
+ assert_equal(lib.id, 0)
+
+ lib.register("RBA-unit-test")
+
+ assert_equal(lib.name, "RBA-unit-test")
+ assert_equal(lib.id != 0, true)
+
+ assert_equal(RBA::Library::library_names.member?("RBA-unit-test"), true)
+ assert_equal(RBA::Library::library_by_name("RBA-unit-test").id, lib.id)
+
+ lib.delete
+ assert_equal(RBA::Library::library_by_name("RBA-unit-test"), nil)
+
+ end
+
+ def test_2_attributes
+
+ lib = RBA::Library::new
+
+ lib.description = "42 is the answer"
+ assert_equal(lib.description, "42 is the answer")
+
+ assert_equal(lib.is_for_technology("X"), false)
+ assert_equal(lib.technologies, [])
+ assert_equal(lib.for_technologies, false)
+
+ lib.technology = "X"
+ assert_equal(lib.is_for_technology("X"), true)
+ assert_equal(lib.technologies, ["X"])
+ assert_equal(lib.for_technologies, true)
+
+ lib.technology = ""
+ assert_equal(lib.is_for_technology("X"), false)
+ assert_equal(lib.technologies, [])
+ assert_equal(lib.for_technologies, false)
+
+ lib.add_technology("Y")
+ assert_equal(lib.is_for_technology("X"), false)
+ assert_equal(lib.is_for_technology("Y"), true)
+ assert_equal(lib.technologies, ["Y"])
+ assert_equal(lib.for_technologies, true)
+
+ lib.clear_technologies
+ assert_equal(lib.is_for_technology("Y"), false)
+ assert_equal(lib.technologies, [])
+ assert_equal(lib.for_technologies, false)
+
+ end
+
+ def test_3_layout
+
+ lib = RBA::Library::new
+ lib.layout.create_cell("X")
+ assert_equal(lib.layout.top_cell.name, "X")
+
+ end
+
+end
+
+load("test_epilogue.rb")
+