diff --git a/src/db/db/dbPCellVariant.cc b/src/db/db/dbPCellVariant.cc index c2581a748..7b8cea8be 100644 --- a/src/db/db/dbPCellVariant.cc +++ b/src/db/db/dbPCellVariant.cc @@ -159,9 +159,8 @@ PCellVariant::update (ImportLayerMapping *layer_mapping) header->declaration ()->produce (*layout (), layer_ids, m_parameters, *this); m_display_name = header->declaration ()->get_display_name (m_parameters); } catch (tl::Exception &ex) { - if (layer_ids.empty ()) { - tl::error << ex.msg (); - } else { + tl::error << ex.msg (); + if (! layer_ids.empty ()) { // put error messages into layout as text objects shapes (layer_ids [0]).insert (db::Text (ex.msg (), db::Trans ())); } diff --git a/src/edt/edt/edtEditorOptionsPages.cc b/src/edt/edt/edtEditorOptionsPages.cc index 4114ff04d..22893aafe 100644 --- a/src/edt/edt/edtEditorOptionsPages.cc +++ b/src/edt/edt/edtEditorOptionsPages.cc @@ -849,8 +849,11 @@ EditorOptionsInst::update_pcell_parameters (const std::vector &par } mp_ui->cell_le->setPalette (pl); + PCellParametersPage::State pcp_state; + // Hint: we shall not delete the page immediately. This gives a segmentation fault in some cases. if (mp_pcell_parameters) { + pcp_state = mp_pcell_parameters->get_state (); mp_pcell_parameters->hide (); mp_pcell_parameters->deleteLater (); } @@ -864,6 +867,8 @@ EditorOptionsInst::update_pcell_parameters (const std::vector &par mp_pcell_parameters = new PCellParametersPage (mp_ui->pcell_tab, &view->cellview (m_cv_index)->layout (), view, m_cv_index, layout->pcell_declaration (pc.second), parameters); mp_ui->pcell_tab->layout ()->addWidget (mp_pcell_parameters); + mp_pcell_parameters->set_state (pcp_state); + } else { mp_ui->param_tab_widget->setTabEnabled (1, false); } diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc index b39a35d88..a851e3508 100644 --- a/src/edt/edt/edtPCellParametersPage.cc +++ b/src/edt/edt/edtPCellParametersPage.cc @@ -23,6 +23,7 @@ #include "edtPCellParametersPage.h" #include "layWidgets.h" +#include "tlScriptError.h" #include #include @@ -32,6 +33,7 @@ #include #include #include +#include namespace edt { @@ -127,11 +129,34 @@ static void set_value (const db::PCellParameterDeclaration &p, const db::Layout } PCellParametersPage::PCellParametersPage (QWidget *parent, const db::Layout *layout, lay::LayoutView *view, int cv_index, const db::PCellDeclaration *pcell_decl, const db::pcell_parameters_type ¶meters) - : QScrollArea (parent), mp_pcell_decl (pcell_decl), mp_layout (layout), mp_view (view), m_cv_index (cv_index) + : QFrame (parent), mp_pcell_decl (pcell_decl), mp_layout (layout), mp_view (view), m_cv_index (cv_index) { + QGridLayout *frame_layout = new QGridLayout (this); + setLayout (frame_layout); + + mp_parameters_area = new QScrollArea (this); + frame_layout->addWidget (mp_parameters_area, 0, 0, 1, 2); + frame_layout->setRowStretch (0, 1); + + mp_error_icon = new QLabel (this); + mp_error_icon->setPixmap (QPixmap (":/warn.png")); + mp_error_icon->hide (); + frame_layout->addWidget (mp_error_icon, 1, 0, 1, 1); + + mp_error_label = new QLabel (this); + QPalette palette = mp_error_label->palette (); + palette.setColor (QPalette::Foreground, Qt::red); + mp_error_label->setPalette (palette); + QFont font = mp_error_label->font (); + font.setBold (true); + mp_error_label->setFont (font); + mp_error_label->hide (); + frame_layout->addWidget (mp_error_label, 1, 1, 1, 1); + frame_layout->setColumnStretch (1, 1); + m_parameters = parameters; - QFrame *fi = new QFrame (this); + QFrame *fi = new QFrame (mp_parameters_area); QWidget *inner_frame = fi; fi->setFrameShape (QFrame::NoFrame); setFrameShape (QFrame::NoFrame); @@ -295,13 +320,32 @@ PCellParametersPage::PCellParametersPage (QWidget *parent, const db::Layout *lay } - setWidget (main_frame); + mp_parameters_area->setWidget (main_frame); main_frame->show (); // does a first coerce and update get_parameters (); } +PCellParametersPage::State +PCellParametersPage::get_state () +{ + State s; + s.valid = true; + s.vScrollPosition = mp_parameters_area->verticalScrollBar ()->value (); + s.hScrollPosition = mp_parameters_area->horizontalScrollBar ()->value (); + return s; +} + +void +PCellParametersPage::set_state (const State &s) +{ + if (s.valid) { + mp_parameters_area->verticalScrollBar ()->setValue (s.vScrollPosition); + mp_parameters_area->horizontalScrollBar ()->setValue (s.hScrollPosition); + } +} + void PCellParametersPage::activated (int) { @@ -416,10 +460,26 @@ PCellParametersPage::get_parameters () } - // call coerce on the parameters - mp_pcell_decl->coerce_parameters (*mp_layout, parameters); + try { - set_parameters (parameters); + // coerce the parameters + mp_pcell_decl->coerce_parameters (*mp_layout, parameters); + set_parameters (parameters); + + } catch (tl::ScriptError &ex) { + + mp_error_label->setText (tl::to_qstring (ex.basic_msg ())); + mp_error_label->setToolTip (tl::to_qstring (ex.msg ())); + mp_error_icon->show (); + mp_error_label->show (); + + } catch (tl::Exception &ex) { + + mp_error_label->setText (tl::to_qstring (ex.msg ())); + mp_error_icon->show (); + mp_error_label->show (); + + } return parameters; } diff --git a/src/edt/edt/edtPCellParametersPage.h b/src/edt/edt/edtPCellParametersPage.h index 2039e6069..5da75cfbf 100644 --- a/src/edt/edt/edtPCellParametersPage.h +++ b/src/edt/edt/edtPCellParametersPage.h @@ -26,7 +26,9 @@ #include "dbPCellDeclaration.h" +#include #include +#include namespace lay { @@ -40,11 +42,20 @@ namespace edt * @brief A QScrollArea that displays and allows editing PCell parameters */ class PCellParametersPage - : public QScrollArea + : public QFrame { Q_OBJECT public: + struct State + { + State () : valid (false), hScrollPosition (0), vScrollPosition (0) { } + + bool valid; + int hScrollPosition; + int vScrollPosition; + }; + /** * @brief Constructor: create a page showing the given parameters * @@ -57,6 +68,16 @@ public: */ PCellParametersPage (QWidget *parent, const db::Layout *layout, lay::LayoutView *view, int cv_index, const db::PCellDeclaration *pcell_decl, const db::pcell_parameters_type ¶meters); + /** + * @brief Gets the pages current state + */ + State get_state (); + + /** + * @brief Restores the state + */ + void set_state (const State &s); + /** * @brief Get the current parameters */ @@ -80,6 +101,9 @@ public slots: void clicked (); private: + QScrollArea *mp_parameters_area; + QLabel *mp_error_label; + QLabel *mp_error_icon; const db::PCellDeclaration *mp_pcell_decl; std::vector m_widgets; const db::Layout *mp_layout; diff --git a/src/edt/edt/gsiDeclEdt.cc b/src/edt/edt/gsiDeclEdt.cc index 9af7a6e8c..e3af87305 100644 --- a/src/edt/edt/gsiDeclEdt.cc +++ b/src/edt/edt/gsiDeclEdt.cc @@ -23,6 +23,7 @@ #include "gsiDecl.h" #include "edtService.h" +#include "dbRecursiveShapeIterator.h" #include "layObjectInstPath.h" #include "layLayoutView.h" @@ -94,7 +95,42 @@ static db::DCplxTrans dtrans (const lay::ObjectInstPath *p) } } +static std::vector get_path (const lay::ObjectInstPath *p) +{ + std::vector pe; + pe.insert (pe.end (), p->begin (), p->end ()); + return pe; +} + +static void set_path (lay::ObjectInstPath *p, const std::vector &pe) +{ + p->assign_path (pe.begin (), pe.end ()); +} + +static lay::ObjectInstPath *from_si (const db::RecursiveShapeIterator &si, int cv_index) +{ + lay::ObjectInstPath *ip = new lay::ObjectInstPath (); + + if (! si.at_end ()) { + + ip->set_cv_index (cv_index); + ip->set_layer (si.layer ()); + ip->set_shape (si.shape ()); + ip->set_topcell (si.top_cell ()->cell_index ()); + std::vector path (si.path ()); + ip->assign_path (path.begin (), path.end ()); + + } + + return ip; +} + gsi::Class decl_ObjectInstPath ("lay", "ObjectInstPath", + gsi::constructor ("new", &from_si, gsi::arg ("si"), gsi::arg ("cv_index"), + "@brief Creates a new path object from a \\RecursiveShapeIterator\n" + "Use this constructor to quickly turn a recursive shape iterator delivery " + "into a shape selection." + ) + gsi::method ("<", &lay::ObjectInstPath::operator<, "@brief Provides an order criterion for two ObjectInstPath objects\n" "@args b\n" @@ -281,7 +317,18 @@ gsi::Class decl_ObjectInstPath ("lay", "ObjectInstPath", "\n" "This method was introduced in version 0.24.\n" ) + - gsi::method ("append_path", (void (lay::ObjectInstPath::*) (const db::InstElement &)) &lay::ObjectInstPath::add_path, + gsi::method_ext ("path", &get_path, + "@brief Gets the instantiation path\n" + "The path is a sequence of \\InstElement objects leading to the target object.\n" + "\n" + "This method was introduced in version 0.26.\n" + ) + + gsi::method_ext ("path=", &set_path, gsi::arg ("p"), + "@brief Sets the instantiation path\n" + "\n" + "This method was introduced in version 0.26.\n" + ) + + gsi::method ("append_path", (void (lay::ObjectInstPath::*) (const db::InstElement &)) &lay::ObjectInstPath::add_path, "@brief Appends an element to the instantiation path\n" "@args element\n" "\n" @@ -528,7 +575,6 @@ static EditableSelectionIterator begin_objects_selected_transient (const lay::La return EditableSelectionIterator (view->get_plugins (), true); } - static gsi::ClassExt layout_view_decl ( gsi::method_ext ("has_object_selection?", &has_object_selection, diff --git a/src/klayout.pro b/src/klayout.pro index cee1039c9..fbf20df44 100644 --- a/src/klayout.pro +++ b/src/klayout.pro @@ -101,8 +101,3 @@ plugins.depends += lib rdb db unit_tests.depends += plugins $$MAIN_DEPENDS -RESOURCES += \ - laybasic/laybasic/layResources.qrc \ - laybasic/laybasic/layResources.qrc \ - plugins/streamers/lay/lay/layResources.qrc \ - plugins/streamers/lay/lay/layResources.qrc diff --git a/src/laybasic/laybasic/layBitmapRenderer.cc b/src/laybasic/laybasic/layBitmapRenderer.cc index 7259551fb..fd47637f2 100644 --- a/src/laybasic/laybasic/layBitmapRenderer.cc +++ b/src/laybasic/laybasic/layBitmapRenderer.cc @@ -161,53 +161,35 @@ BitmapRenderer::insert (const db::DEdge &e) m_edges.push_back (e); } +static inline bool point_inside_box (const db::DPoint &pt, const db::DBox &box) +{ + return (! (db::coord_traits::equal (pt.x (), box.left ()) || db::coord_traits::equal (pt.x (), box.right ())) && + ! (db::coord_traits::equal (pt.y (), box.bottom ()) || db::coord_traits::equal (pt.y (), box.top ()))); +} + void BitmapRenderer::add_xfill () { - bool any = false; - db::DPoint a1, a2, b1, b2; - const double eps = 1e-10; - + db::DBox box; for (std::vector::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) { - - db::DPoint p1 = e->p1 (); - - if (!any) { - - a1 = a2 = b1 = b2 = p1; - any = true; - - } else { - - db::DVector d; - - d = p1 - a1; - if (d.x () - d.y () < -eps) { - a1 = p1; - } - - d = p1 - a2; - if (d.x () - d.y () > eps) { - a2 = p1; - } - - d = p1 - b1; - if (d.x () + d.y () < -eps) { - b1 = p1; - } - - d = p1 - b2; - if (d.x () + d.y () > eps) { - b2 = p1; - } - + if (! e->is_ortho ()) { + return; } - + box += e->p1 (); + box += e->p2 (); } - if (any) { - insert (db::DEdge (a1, a2)); - insert (db::DEdge (b1, b2)); + if (! box.empty () && box.area () > 0.0) { + + for (std::vector::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) { + if (point_inside_box (e->p1 (), box) || point_inside_box (e->p2 (), box)) { + return; + } + } + + insert (db::DEdge (box.p1 (), box.p2 ())); + insert (db::DEdge (box.lower_right (), box.upper_left ())); + } } @@ -483,6 +465,9 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans, render_fill (*fill); } if (frame) { + if (m_xfill) { + add_xfill (); + } render_contour (*frame); } diff --git a/src/tl/tl/tlScriptError.cc b/src/tl/tl/tlScriptError.cc index f54573b0e..ef8cca1d5 100644 --- a/src/tl/tl/tlScriptError.cc +++ b/src/tl/tl/tlScriptError.cc @@ -67,11 +67,7 @@ BacktraceElement::to_string() const std::string ScriptError::basic_msg () const { - std::string m = tl::Exception::msg (); - if (! m_context.empty ()) { - m += tl::to_string (tr (" in ")) + m_context; - } - return m; + return tl::Exception::msg (); } std::string @@ -79,6 +75,10 @@ ScriptError::msg () const { std::string m = basic_msg (); + if (! m_context.empty ()) { + m += tl::to_string (tr (" in ")) + m_context; + } + for (std::vector::const_iterator bt = backtrace ().begin (); bt != backtrace ().end (); ++bt) { m += "\n "; m += bt->to_string (); diff --git a/testdata/ruby/edtTest.rb b/testdata/ruby/edtTest.rb index 6708c6b6a..2ee85bc55 100644 --- a/testdata/ruby/edtTest.rb +++ b/testdata/ruby/edtTest.rb @@ -109,6 +109,16 @@ class EDT_TestClass < TestBase assert_equal(p.trans.to_s, "r0 *1 0,0") assert_equal(p.source_trans.to_s, "r0 *1 0,0") + # ObjectInstPath from RecursiveShapeIterator + + si = tc.begin_shapes_rec(li) + oi = RBA::ObjectInstPath::new(si, 2) + + assert_equal(oi.cv_index, 2) + assert_equal(oi.shape.to_s, si.shape.to_s) + assert_equal(oi.cell_index, si.cell.cell_index) + assert_equal(oi.top, tc.cell_index) + end # Selection