Merge remote-tracking branch 'upstream/master' into macos-build

This commit is contained in:
Kazunari Sekigawa 2018-02-13 06:56:27 +09:00
commit 9d9996b91d
19 changed files with 271 additions and 86 deletions

View File

@ -1349,13 +1349,17 @@ get_intersections_per_band_any (std::vector <CutPoints> &cutpoints, std::vector
// the cutpoint will be a weak attractor - that is an optional cutpoint.
// In that case we can skip the cutpoint because no related edge will move.
ip_weak.clear ();
size_t n_off_edge = on_edge1 ? 0 : 1;
for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) {
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
ip_weak.push_back (&*cc);
if (!is_point_on_exact (*cc, cp.second)) {
++n_off_edge;
}
}
}
for (std::vector <WorkEdge *>::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) {
if (ip_weak.size () > 1 || !on_edge1) {
if (n_off_edge > 1) {
(*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
#ifdef DEBUG_EDGE_PROCESSOR
printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
@ -1435,13 +1439,23 @@ get_intersections_per_band_any (std::vector <CutPoints> &cutpoints, std::vector
// the cutpoint will be a weak attractor - that is an optional cutpoint.
// In that case we can skip the cutpoint because no related edge will move.
ip_weak.clear ();
size_t n_off_edge = 0;
if (!on_edge1) {
n_off_edge += 1;
}
if (!on_edge2) {
n_off_edge += 1;
}
for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) {
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
ip_weak.push_back (&*cc);
if (!is_point_on_exact (*cc, cp.second)) {
++n_off_edge;
}
}
}
for (std::vector <WorkEdge *>::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) {
if (ip_weak.size () > 1 || !on_edge1 || !on_edge2) {
if (n_off_edge > 1) {
(*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
#ifdef DEBUG_EDGE_PROCESSOR
printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());

View File

@ -1884,6 +1884,26 @@ Layout::is_pcell_instance (cell_index_type cell_index) const
}
}
const Layout::pcell_declaration_type *
Layout::pcell_declaration_for_pcell_variant (cell_index_type variant_cell_index) const
{
const Cell *variant_cell = &cell (variant_cell_index);
const LibraryProxy *lib_proxy = dynamic_cast<const LibraryProxy *> (variant_cell);
if (lib_proxy) {
Library *lib = LibraryManager::instance ().lib (lib_proxy->lib_id ());
tl_assert (lib != 0);
return lib->layout ().pcell_declaration_for_pcell_variant (lib_proxy->library_cell_index ());
}
const PCellVariant *pcell_variant = dynamic_cast<const PCellVariant *> (variant_cell);
if (pcell_variant) {
return pcell_declaration (pcell_variant->pcell_id ());
} else {
return 0;
}
}
std::pair<db::Library *, db::cell_index_type>
Layout::defining_library (cell_index_type cell_index) const
{

View File

@ -881,11 +881,22 @@ public:
*/
std::pair<db::Library *, db::cell_index_type> defining_library (cell_index_type cell_index) const;
/**
* @brief Gets the PCell declaration object for a PCell instance
*
* This method determines the PCell declaration object for a given PCell variant cell.
* Note, that the declaration may originate from a different layout than this, if the PCell
* is imported from a library.
*
* The cell given cell is not a PCell variant cell, 0 is returned.
*/
const Layout::pcell_declaration_type *pcell_declaration_for_pcell_variant (cell_index_type cell_index) const;
/**
* @brief Get the PCell parameters of a PCell instance
*
* For the order of the parameters, ask the PCell declaration (available trough Layout::pcell_declaration
* from the PCell id).
* from the PCell id or from Layout::pcell_declaration_for_pcell_variant from the cell_index).
*
* @return A list of parameters in the order they are declared.
*/

View File

@ -62,7 +62,7 @@ Reader::Reader (tl::InputStream &stream)
}
if (! mp_actual_reader) {
throw db::ReaderException (tl::to_string (QObject::tr ("Stream has unknown format")));
throw db::ReaderException (tl::to_string (QObject::tr ("Stream has unknown format: ")) + stream.source ());
}
}

View File

@ -2244,3 +2244,54 @@ TEST(100)
db::compare_layouts (_this, lr, au_fn);
}
// #74 (GitHub)
TEST(101)
{
db::EdgeProcessor ep;
{
db::Point pts[] = {
db::Point (0, 0),
db::Point (0, 10),
db::Point (10, 10),
db::Point (10, 0)
};
db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
ep.insert (p, 0);
}
{
db::Point pts[] = {
db::Point (-1, -1),
db::Point (-1, 8),
db::Point (2, 11),
db::Point (2, -1)
};
db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
ep.insert (p, 1);
}
{
db::Point pts[] = {
db::Point (2, -1),
db::Point (2, 11),
db::Point (11, 11),
db::Point (11, -1)
};
db::Polygon p;
p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]);
ep.insert (p, 1);
}
std::vector<db::Polygon> out;
db::PolygonContainer pc (out);
db::PolygonGenerator pg (pc, false, true);
db::BooleanOp op (db::BooleanOp::And);
ep.process (pg, op);
EXPECT_EQ (out.size (), size_t (1));
EXPECT_EQ (out[0].to_string (), "(0,0;0,9;1,10;10,10;10,0)");
}

View File

@ -1906,12 +1906,10 @@ MainService::cm_change_layer ()
// get (common) cellview index of the selected shapes
for (std::vector<edt::Service *>::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) {
for (edt::Service::obj_iterator s = (*es)->selection ().begin (); s != (*es)->selection ().end (); ++s) {
if (! s->is_cell_inst ()) {
if (cv_index >= 0 && cv_index != int (s->cv_index ())) {
throw tl::Exception (tl::to_string (QObject::tr ("Selections originate from different layouts - cannot switch layer in this case.")));
}
cv_index = int (s->cv_index ());
if (cv_index >= 0 && cv_index != int (s->cv_index ())) {
throw tl::Exception (tl::to_string (QObject::tr ("Selections originate from different layouts - cannot switch layer in this case.")));
}
cv_index = int (s->cv_index ());
}
}
@ -1975,17 +1973,58 @@ MainService::cm_change_layer ()
// Insert and delete the shape. This exploits the fact, that a shape can be erased multiple times -
// this is important since the selection potentially contains the same shape multiple times.
for (std::vector<edt::Service *>::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) {
for (edt::Service::obj_iterator s = (*es)->selection ().begin (); s != (*es)->selection ().end (); ++s) {
if (!s->is_cell_inst () && int (s->layer ()) != layer) {
db::Cell &cell = layout.cell (s->cell_index ());
if (cell.shapes (s->layer ()).is_valid (s->shape ())) {
cell.shapes (layer).insert (s->shape ());
cell.shapes (s->layer ()).erase_shape (s->shape ());
}
} else if (s->is_cell_inst ()) {
// If the selected object is a PCell instance, and there is exactly one visible, writable layer type parameter, change this one
db::Instance inst = s->back ().inst_ptr;
db::Cell &cell = layout.cell (s->cell_index ());
if (cell.is_valid (inst)) {
const db::PCellDeclaration *pcell_decl = layout.pcell_declaration_for_pcell_variant (inst.cell_index ());
if (pcell_decl) {
size_t layer_par_index = 0;
int n_layer_par = 0;
for (std::vector<db::PCellParameterDeclaration>::const_iterator d = pcell_decl->parameter_declarations ().begin (); d != pcell_decl->parameter_declarations ().end () && n_layer_par < 2; ++d) {
if (d->get_type () == db::PCellParameterDeclaration::t_layer && !d->is_hidden () && !d->is_readonly ()) {
++n_layer_par;
layer_par_index = size_t (d - pcell_decl->parameter_declarations ().begin ());
}
}
if (n_layer_par == 1) {
std::vector<tl::Variant> parameters = cell.get_pcell_parameters (inst);
tl_assert (layer_par_index < parameters.size ());
parameters [layer_par_index] = layout.get_properties (layer);
cell.change_pcell_parameters (inst, parameters);
}
}
}
}
}
}
// remove superfluous proxies
layout.cleanup ();
// The selection is no longer valid
view ()->clear_selection ();

View File

@ -609,11 +609,6 @@ MainWindow::MainWindow (QApplication *app, const char *name)
cp_frame_ly->addWidget (mp_cpy_label);
cp_frame_ly->insertSpacing (-1, 6);
// connect to the menus to provide the dynamic parts
QMenu *bookmark_menu = mp_menu->menu ("bookmark_menu");
tl_assert (bookmark_menu != 0);
connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ()));
// select the default mode
select_mode (lay::LayoutView::default_mode ());
@ -1798,6 +1793,12 @@ MainWindow::edits_enabled_changed ()
}
}
void
MainWindow::menu_needs_update ()
{
lay::LayoutView::update_menu (current_view (), *mp_menu);
}
void
MainWindow::libraries_changed ()
{
@ -2426,57 +2427,6 @@ MainWindow::cm_redo ()
END_PROTECTED
}
void
MainWindow::bookmark_menu_show ()
{
if (mp_menu->is_valid ("bookmark_menu.goto_bookmark_menu")) {
Action goto_bookmark_action = mp_menu->action ("bookmark_menu.goto_bookmark_menu");
bool has_bookmarks = current_view () && current_view ()->bookmarks ().size () > 0;
if (has_bookmarks && edits_enabled ()) {
goto_bookmark_action.set_enabled (true);
QMenu *goto_bookmark_menu = goto_bookmark_action.qaction ()->menu ();
if (goto_bookmark_menu) {
goto_bookmark_menu->clear ();
if (current_view ()) {
const lay::BookmarkList &bookmarks = current_view ()->bookmarks ();
for (size_t i = 0; i < bookmarks.size (); ++i) {
QAction *action = goto_bookmark_menu->addAction (tl::to_qstring (bookmarks.name (i)));
action->setObjectName (tl::to_qstring (tl::sprintf ("bookmark_%d", i + 1)));
gtf::action_connect (action, SIGNAL (triggered ()), this, SLOT (goto_bookmark ()));
action->setData (QVariant (int (i)));
}
}
}
} else {
goto_bookmark_action.set_enabled (false);
}
}
}
void
MainWindow::goto_bookmark ()
{
BEGIN_PROTECTED
QAction *action = dynamic_cast <QAction *> (sender ());
tl_assert (action);
size_t id = size_t (action->data ().toInt ());
if (current_view () && current_view ()->bookmarks ().size () > id) {
current_view ()->goto_view (current_view ()->bookmarks ().state (id));
}
END_PROTECTED
}
void
MainWindow::cm_goto_position ()
{
@ -2580,19 +2530,7 @@ MainWindow::cm_bookmark_view ()
BEGIN_PROTECTED
if (current_view ()) {
while (true) {
bool ok = false;
QString text = QInputDialog::getText (this, QObject::tr ("Enter Bookmark Name"), QObject::tr ("Bookmark name"),
QLineEdit::Normal, QString::null, &ok);
if (! ok) {
break;
} else if (text.isEmpty ()) {
QMessageBox::critical (this, QObject::tr ("Error"), QObject::tr ("Enter a name for the bookmark"));
} else {
current_view ()->bookmark_view (tl::to_string (text));
break;
}
}
current_view ()->bookmark_current_view ();
}
END_PROTECTED
@ -3359,6 +3297,7 @@ MainWindow::select_view (int index)
clear_current_pos ();
edits_enabled_changed ();
clear_message ();
menu_needs_update ();
m_disable_tab_selected = dis;
@ -3738,6 +3677,7 @@ MainWindow::clone_current_view ()
connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ()));
connect (view, SIGNAL (menu_needs_update ()), this, SLOT (menu_needs_update ()));
connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int)));
connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool)));
connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ()));
@ -4041,6 +3981,7 @@ MainWindow::close_view (int index)
clear_current_pos ();
edits_enabled_changed ();
menu_needs_update ();
clear_message ();
update_dock_widget_state ();
@ -4184,10 +4125,7 @@ MainWindow::do_update_file_menu ()
if (m_mru.size () > 0 && edits_enabled ()) {
// rebuild MRU menu
std::vector<std::string> items = mp_menu->items (mru_menu);
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
mp_menu->delete_item (mru_menu + "." + *i);
}
mp_menu->clear_menu (mru_menu);
for (std::vector<std::pair<std::string, std::string> >::iterator mru = m_mru.end (); mru != m_mru.begin (); ) {
--mru;
@ -4349,6 +4287,7 @@ MainWindow::do_create_view ()
connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ()));
connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ()));
connect (view, SIGNAL (menu_needs_update ()), this, SLOT (menu_needs_update ()));
connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int)));
connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool)));
connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ()));

View File

@ -689,7 +689,6 @@ public slots:
void tab_close_requested (int);
void enable_all ();
void disable_all ();
void goto_bookmark ();
void open_recent ();
void view_selected (int index);
void view_title_changed ();
@ -858,8 +857,9 @@ public slots:
protected slots:
void menu_changed ();
void message_timer ();
void bookmark_menu_show ();
void edits_enabled_changed ();
void menu_needs_update ();
void file_changed_timer ();
void file_changed (const QString &path);
void file_removed (const QString &path);
@ -874,7 +874,6 @@ private:
// Main menu
AbstractMenu *mp_menu;
QMenu *mp_goto_bookmark_menu;
QTabBar *mp_tab_bar;
QToolBar *mp_tool_bar;
QDockWidget *mp_navigator_dock_widget;

View File

@ -1354,6 +1354,17 @@ AbstractMenu::insert_menu (const std::string &path, const std::string &name, con
insert_menu (path, name, create_action (title));
}
void
AbstractMenu::clear_menu (const std::string &p)
{
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
path_type path = find_item (p);
if (! path.empty () && ! path.back ().second->children.empty ()) {
path.back ().second->children.clear ();
emit changed ();
}
}
void
AbstractMenu::delete_item (const std::string &p)
{

View File

@ -784,6 +784,13 @@ public:
*/
void insert_menu (const std::string &path, const std::string &name, const std::string &title);
/**
* @brief Deletes the children of the item with the given path
*
* If the item does not exist or is not a menu, this method does nothing.
*/
void clear_menu (const std::string &path);
/**
* @brief Delete the item given by the path
*

View File

@ -42,6 +42,7 @@
#include "tlString.h"
#include "tlLog.h"
#include "tlAssert.h"
#include "tlExceptions.h"
#include "layLayoutView.h"
#include "layViewOp.h"
#include "layViewObject.h"
@ -74,6 +75,7 @@
#include "rdbMarkerBrowserDialog.h"
#include "tlXMLParser.h"
#include "gsi.h"
#include "gtf.h"
#include <limits>
@ -772,6 +774,37 @@ LayoutView::init_menu (lay::AbstractMenu &menu)
lay::HierarchyControlPanel::init_menu (menu);
}
void
LayoutView::update_menu (lay::LayoutView *view, lay::AbstractMenu &menu)
{
std::string bm_menu = "bookmark_menu.goto_bookmark_menu";
if (menu.is_valid (bm_menu)) {
menu.clear_menu (bm_menu);
Action goto_bookmark_action = menu.action (bm_menu);
if (view && view->bookmarks ().size () > 0) {
goto_bookmark_action.set_enabled (true);
const lay::BookmarkList &bookmarks = view->bookmarks ();
for (size_t i = 0; i < bookmarks.size (); ++i) {
Action action;
gtf::action_connect (action.qaction (), SIGNAL (triggered ()), view, SLOT (goto_bookmark ()));
action.set_title (bookmarks.name (i));
action.qaction ()->setData (QVariant (int (i)));
menu.insert_item (bm_menu + ".end", tl::sprintf ("bookmark_%d", i + 1), action);
}
} else {
goto_bookmark_action.set_enabled (false);
}
}
}
void
LayoutView::set_drawing_workers (int workers)
{
@ -3650,6 +3683,24 @@ LayoutView::cancel ()
clear_selection ();
}
void
LayoutView::bookmark_current_view ()
{
while (true) {
bool ok = false;
QString text = QInputDialog::getText (this, QObject::tr ("Enter Bookmark Name"), QObject::tr ("Bookmark name"),
QLineEdit::Normal, QString::null, &ok);
if (! ok) {
break;
} else if (text.isEmpty ()) {
QMessageBox::critical (this, QObject::tr ("Error"), QObject::tr ("Enter a name for the bookmark"));
} else {
bookmark_view (tl::to_string (text));
break;
}
}
}
void
LayoutView::manage_bookmarks ()
{
@ -3663,6 +3714,7 @@ void
LayoutView::bookmarks (const BookmarkList &b)
{
m_bookmarks = b;
emit menu_needs_update ();
}
void
@ -3670,6 +3722,22 @@ LayoutView::bookmark_view (const std::string &name)
{
DisplayState state (box (), get_min_hier_levels (), get_max_hier_levels (), m_cellviews);
m_bookmarks.add (name, state);
emit menu_needs_update ();
}
void
LayoutView::goto_bookmark ()
{
BEGIN_PROTECTED
QAction *action = dynamic_cast <QAction *> (sender ());
tl_assert (action);
size_t id = size_t (action->data ().toInt ());
if (bookmarks ().size () > id) {
goto_view (bookmarks ().state (id));
}
END_PROTECTED
}
void

View File

@ -1557,6 +1557,11 @@ public:
*/
void bookmark_view (const std::string &name);
/**
* @brief Asks for a bookmark name and bookmark the current view under this name
*/
void bookmark_current_view ();
/**
* @brief Show the bookmark management form
*/
@ -1603,6 +1608,12 @@ public:
*/
static void init_menu (lay::AbstractMenu &menu);
/**
* @brief Updates the menu for the given view
* If the view is 0, the menu shall be updated to reflect "no view active"
*/
static void update_menu (lay::LayoutView *view, lay::AbstractMenu &menu);
/**
* @brief Query the default mode
*/
@ -2530,6 +2541,7 @@ public slots:
private slots:
void active_cellview_changed (int index);
void goto_bookmark ();
signals:
/**
@ -2562,6 +2574,11 @@ signals:
*/
void edits_enabled_changed ();
/**
* @brief This signal is sent when the view wants to update the menu
*/
void menu_needs_update ();
protected:
/**
* @brief Establish the view operations

View File

@ -124,5 +124,14 @@ TEST(1)
menu.delete_item ("n1.c2");
EXPECT_EQ (menu_to_string (menu), "(n2)");
}
menu.clear_menu ("n1");
EXPECT_EQ (menu_to_string (menu), "(n2)");
menu.insert_menu ("end", "n1", lay::Action ("title:n1"));
menu.insert_item ("n1.begin", "c1", lay::Action ("title:c1"));
menu.insert_item ("n1.end", "c2", lay::Action ("title:c2"));
EXPECT_EQ (menu_to_string (menu), "(n2,n1(n1.c1,n1.c2))");
menu.clear_menu ("n1");
EXPECT_EQ (menu_to_string (menu), "(n2,n1)");
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.