diff --git a/src/edt/edt/MakeArrayOptionsDialog.ui b/src/edt/edt/MakeArrayOptionsDialog.ui index 25e43bdb3..845a9c832 100644 --- a/src/edt/edt/MakeArrayOptionsDialog.ui +++ b/src/edt/edt/MakeArrayOptionsDialog.ui @@ -6,8 +6,8 @@ 0 0 - 561 - 323 + 586 + 431 @@ -20,32 +20,6 @@ 9 - - - - The selection will be copied row * columns times. Each copy will be displaced by a vector given by the row vector times the row index and the column vector times the column index. - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - @@ -61,144 +35,248 @@ false - - 9 - 6 - - - - - 1 - 0 - + + + + 1 + + + Array with pitch vectors + + + + + + Each copy will be displaced by a vector given by the row vector times the row index and the column vector times the column index. + + + true + + + + + + + y = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + + + + + Column vector (x,y) + + + + + + + x = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + + + + + + 1 + 0 + + + + + + + + x = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + y = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + + + + + Row vector (x,y) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Grid with space + + + + + + Space + + + + + + + + 1 + 0 + + + + + + + + + 1 + 0 + + + + + + + + Qt::Vertical + + + + 20 + 30 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + horizonal = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + vertical = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Use visible layers only for bounding boxes of instances + + + + + + + The selection is placed in a rectangular array, with the bounding box defining the pitch. Additional space can be added between columns and rows. + + + true + + + + + - - + + - x = + The selection will be copied row * columns times. - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + true - - - - - 1 - 0 - - - - - - - - Columns = - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Rows = - - - - - - - - 1 - 0 - - - - - - - - Row vector (x,y) - - - - - - - Column vector (x,y) - - - - - - - - 1 - 0 - - - - - - - - x = - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 1 - 0 - - - - - - - - - 1 - 0 - - - - - - - - y = - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - y = - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + Qt::Vertical @@ -214,6 +292,59 @@ + + + + Columns = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + + + + + Rows = + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -271,10 +402,14 @@ columns_le rows_le + mode_tab column_x_le column_y_le row_x_le row_y_le + space_x_le + space_y_le + vis_only_cbx diff --git a/src/edt/edt/edtDialogs.cc b/src/edt/edt/edtDialogs.cc index 0e127f5bb..8a4d8873d 100644 --- a/src/edt/edt/edtDialogs.cc +++ b/src/edt/edt/edtDialogs.cc @@ -26,6 +26,7 @@ #include "dbLayout.h" #include "edtDialogs.h" +#include "edtMainService.h" #include "layEditorUtils.h" #include "layObjectInstPath.h" #include "layCellView.h" @@ -646,29 +647,41 @@ MakeArrayOptionsDialog::MakeArrayOptionsDialog (QWidget *parent) } bool -MakeArrayOptionsDialog::exec_dialog (db::DVector &a, unsigned int &na, db::DVector &b, unsigned int &nb) +MakeArrayOptionsDialog::exec_dialog (ArrayOptions &options) { - rows_le->setText (tl::to_qstring (tl::to_string (na))); - columns_le->setText (tl::to_qstring (tl::to_string (nb))); - row_x_le->setText (tl::to_qstring (tl::micron_to_string (a.x ()))); - row_y_le->setText (tl::to_qstring (tl::micron_to_string (a.y ()))); - column_x_le->setText (tl::to_qstring (tl::micron_to_string (b.x ()))); - column_y_le->setText (tl::to_qstring (tl::micron_to_string (b.y ()))); + rows_le->setText (tl::to_qstring (tl::to_string (options.na))); + columns_le->setText (tl::to_qstring (tl::to_string (options.nb))); + row_x_le->setText (tl::to_qstring (tl::micron_to_string (options.a.x ()))); + row_y_le->setText (tl::to_qstring (tl::micron_to_string (options.a.y ()))); + column_x_le->setText (tl::to_qstring (tl::micron_to_string (options.b.x ()))); + column_y_le->setText (tl::to_qstring (tl::micron_to_string (options.b.y ()))); + space_x_le->setText (tl::to_qstring (tl::micron_to_string (options.space.x ()))); + space_y_le->setText (tl::to_qstring (tl::micron_to_string (options.space.y ()))); + + mode_tab->setCurrentIndex (options.mode == ArrayOptions::PitchVectors ? 0 : 1); + vis_only_cbx->setChecked (options.use_visible_layers); if (QDialog::exec ()) { + options.mode = mode_tab->currentIndex () == 0 ? ArrayOptions::PitchVectors : ArrayOptions::Spaced; + options.use_visible_layers = vis_only_cbx->isChecked (); + double bx = 0.0, by = 0.0; double ax = 0.0, ay = 0.0; + double sx = 0.0, sy = 0.0; tl::from_string_ext (tl::to_string (column_x_le->text ()), bx); tl::from_string_ext (tl::to_string (column_y_le->text ()), by); - tl::from_string_ext (tl::to_string (columns_le->text ()), nb); + tl::from_string_ext (tl::to_string (columns_le->text ()), options.nb); tl::from_string_ext (tl::to_string (row_x_le->text ()), ax); tl::from_string_ext (tl::to_string (row_y_le->text ()), ay); - tl::from_string_ext (tl::to_string (rows_le->text ()), na); + tl::from_string_ext (tl::to_string (rows_le->text ()), options.na); + tl::from_string_ext (tl::to_string (space_x_le->text ()), sx); + tl::from_string_ext (tl::to_string (space_y_le->text ()), sy); - a = db::DVector (ax, ay); - b = db::DVector (bx, by); + options.a = db::DVector (ax, ay); + options.b = db::DVector (bx, by); + options.space = db::DVector (sx, sy); return true; @@ -758,7 +771,7 @@ popup_tap_layer_menu (lay::LayoutViewBase *view, const std::set > layers_in_selection; for (lay::ShapeFinder::iterator f = finder.begin (); f != finder.end (); ++f) { - if (cv_index < 0 || f->cv_index () == cv_index) { + if (cv_index < 0 || int (f->cv_index ()) == cv_index) { const db::Layout &ly = view->cellview (f->cv_index ())->layout (); // ignore guiding shapes and only provide layers from the filter if (f->layer () != ly.guiding_shape_layer () diff --git a/src/edt/edt/edtDialogs.h b/src/edt/edt/edtDialogs.h index b1de5961b..bb288d556 100644 --- a/src/edt/edt/edtDialogs.h +++ b/src/edt/edt/edtDialogs.h @@ -56,6 +56,8 @@ namespace lay namespace edt { +class ArrayOptions; + /** * @brief The copy mode dialog */ @@ -173,10 +175,10 @@ class MakeArrayOptionsDialog private Ui::MakeArrayOptionsDialog { Q_OBJECT - public: + MakeArrayOptionsDialog (QWidget *parent); - bool exec_dialog (db::DVector &a, unsigned int &na, db::DVector &b, unsigned int &nb); + bool exec_dialog (ArrayOptions &options); virtual void accept (); }; diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index 2187b574d..f2331e109 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -81,8 +81,6 @@ MainService::MainService (db::Manager *manager, lay::LayoutViewBase *view, lay:: m_distribute_vmode (1), m_distribute_vpitch (0.0), m_distribute_vspace (0.0), m_distribute_visible_layers (false), m_origin_mode_x (-1), m_origin_mode_y (-1), m_origin_visible_layers_for_bbox (false), - m_array_a (0.0, 1.0), m_array_b (1.0, 0.0), - m_array_na (1), m_array_nb (1), m_router (0.0), m_rinner (0.0), m_npoints (64), m_undo_before_apply (true) { #if defined(HAVE_QT) @@ -2251,32 +2249,66 @@ MainService::cm_make_array () tl_assert (false); // see TODO #endif - size_t n = 0; check_no_guiding_shapes (); std::vector edt_services = view ()->get_plugins (); - for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) { - for (EditableSelectionIterator s = (*es)->begin_selection (); ! s.at_end (); ++s) { - ++n; - } + bool any = false; + for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end () && ! any; ++es) { + any = ! (*es)->begin_selection ().at_end (); } - - if (n == 0) { + if (! any) { throw tl::Exception (tl::to_string (tr ("Nothing selected to make arrays of"))); } #if defined(HAVE_QT) // TODO: make parameters persistent so we can set them externally - if (! make_array_options_dialog ()->exec_dialog (m_array_a, m_array_na, m_array_b, m_array_nb)) { + if (! make_array_options_dialog ()->exec_dialog (m_array_options)) { return; } #endif + unsigned int na = m_array_options.na; + unsigned int nb = m_array_options.nb; + db::DVector a = m_array_options.a; + db::DVector b = m_array_options.b; + + if (m_array_options.mode == ArrayOptions::Spaced) { + + db::DBox bbox; + + // get the selection bbox + for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) { + for (EditableSelectionIterator s = (*es)->begin_selection (); ! s.at_end (); ++s) { + + const db::Layout &layout = view ()->cellview (s->cv_index ())->layout (); + db::CplxTrans tr = db::CplxTrans (layout.dbu ()) * s->trans (); + + if (! s->is_cell_inst ()) { + bbox += tr * s->shape ().bbox (); + } else { + bbox += inst_bbox (tr, view (), s->cv_index (), s->back (), m_array_options.use_visible_layers); + } + + } + } + + // compute pitch vectors + a = db::DVector (0.0, m_array_options.space.y () + bbox.height ()); // row-pitch + b = db::DVector (m_array_options.space.x () + bbox.width (), 0.0); // column-pitch + + } + + make_array (na, nb, a, b); +} + +void +MainService::make_array (unsigned int na, unsigned int nb, const db::DVector &a, const db::DVector &b) +{ view ()->cancel_edits (); // undo support for small arrays only - bool has_undo = (m_array_na * m_array_nb < 1000); + bool has_undo = (na * nb < 1000); // No undo support currently - the undo buffering is pretty inefficient right now. if (manager ()) { @@ -2287,7 +2319,17 @@ MainService::cm_make_array () } } - tl::RelativeProgress progress (tl::to_string (tr ("Make array")), (size_t (m_array_na) * size_t (m_array_nb) - 1) * n, 1000); + std::vector edt_services = view ()->get_plugins (); + + // count selected items for progress + size_t n = 0; + for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) { + for (EditableSelectionIterator s = (*es)->begin_selection (); ! s.at_end (); ++s) { + ++n; + } + } + + tl::RelativeProgress progress (tl::to_string (tr ("Make array")), (size_t (na) * size_t (nb) - 1) * n, 1000); for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) { @@ -2302,15 +2344,15 @@ MainService::cm_make_array () if (s->is_cell_inst ()) { - for (unsigned int ia = 0; ia < m_array_na; ++ia) { - for (unsigned int ib = 0; ib < m_array_nb; ++ib) { + for (unsigned int ia = 0; ia < na; ++ia) { + for (unsigned int ib = 0; ib < nb; ++ib) { // don't create a copy if (ia == 0 && ib == 0) { continue; } - db::DCplxTrans dtrans (m_array_a * double (ia) + m_array_b * double (ib)); + db::DCplxTrans dtrans (a * double (ia) + b * double (ib)); db::ICplxTrans itrans (db::DCplxTrans (s->trans ()).inverted () * db::DCplxTrans (1.0 / cv->layout ().dbu ()) * dtrans * db::DCplxTrans (cv->layout ().dbu ()) * db::DCplxTrans (s->trans ())); db::Instance new_inst = target_cell.insert (s->back ().inst_ptr); @@ -2326,15 +2368,15 @@ MainService::cm_make_array () db::Shapes &target_shapes = target_cell.shapes (s->layer ()); - for (unsigned int ia = 0; ia < m_array_na; ++ia) { - for (unsigned int ib = 0; ib < m_array_nb; ++ib) { + for (unsigned int ia = 0; ia < na; ++ia) { + for (unsigned int ib = 0; ib < nb; ++ib) { // don't create a copy if (ia == 0 && ib == 0) { continue; } - db::DCplxTrans dtrans (m_array_a * double (ia) + m_array_b * double (ib)); + db::DCplxTrans dtrans (a * double (ia) + b * double (ib)); db::ICplxTrans itrans (db::DCplxTrans (s->trans ()).inverted () * db::DCplxTrans (1.0 / cv->layout ().dbu ()) * dtrans * db::DCplxTrans (cv->layout ().dbu ()) * db::DCplxTrans (s->trans ())); db::Shape new_shape = target_shapes.insert (s->shape ()); diff --git a/src/edt/edt/edtMainService.h b/src/edt/edt/edtMainService.h index 34820fbca..773de00b1 100644 --- a/src/edt/edt/edtMainService.h +++ b/src/edt/edt/edtMainService.h @@ -56,6 +56,21 @@ class DistributeOptionsDialog; // ------------------------------------------------------------- +struct ArrayOptions +{ + enum mode_type { PitchVectors, Spaced }; + + ArrayOptions () : mode (PitchVectors), a (0.0, 1.0), b (1.0, 0.0), na (1), nb (1) { } + + mode_type mode; + db::DVector a, b; + unsigned int na, nb; + db::DVector space; + bool use_visible_layers; +}; + +// ------------------------------------------------------------- + class MainService : public lay::Plugin, public lay::Editable, @@ -155,6 +170,11 @@ public: */ void cm_make_array (); + /** + * @brief The parameterized function for making arrays + */ + void make_array (unsigned na, unsigned nb, const db::DVector &a, const db::DVector &b); + /** * @brief Align the selected shapes and instances */ @@ -242,11 +262,11 @@ private: std::string m_make_cell_name; int m_origin_mode_x, m_origin_mode_y; bool m_origin_visible_layers_for_bbox; - db::DVector m_array_a, m_array_b; - unsigned int m_array_na, m_array_nb; double m_router, m_rinner; unsigned int m_npoints; bool m_undo_before_apply; + ArrayOptions m_array_options; + #if defined(HAVE_QT) edt::RoundCornerOptionsDialog *mp_round_corners_dialog; edt::AreaAndPerimeterDialog *mp_area_and_perimeter_dialog; diff --git a/src/layui/layui/AlignCellOptionsDialog.ui b/src/layui/layui/AlignCellOptionsDialog.ui index 637bdd8b2..9b5d4bf13 100644 --- a/src/layui/layui/AlignCellOptionsDialog.ui +++ b/src/layui/layui/AlignCellOptionsDialog.ui @@ -6,8 +6,8 @@ 0 0 - 432 - 349 + 449 + 370 @@ -405,6 +405,13 @@ + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + @@ -429,44 +436,12 @@ 0 - - - - Qt::Horizontal - - - - 209 - 20 - - - - - - - - Ok - - - true - - - - - - - Cancel - - - - pushButton - pushButton_2 lt ct rt @@ -486,34 +461,34 @@ - pushButton - clicked() + buttonBox + accepted() AlignCellOptionsDialog accept() - 237 - 203 + 224 + 295 - 147 - 81 + 224 + 176 - pushButton_2 - clicked() + buttonBox + rejected() AlignCellOptionsDialog reject() - 325 - 202 + 224 + 295 - 325 - 57 + 224 + 176