diff --git a/src/lay/lay/layMainConfigPages.cc b/src/lay/lay/layMainConfigPages.cc index ffe99975b..67f8734a8 100644 --- a/src/lay/lay/layMainConfigPages.cc +++ b/src/lay/lay/layMainConfigPages.cc @@ -27,6 +27,7 @@ #include "layStream.h" #include "layAbstractMenu.h" #include "layMainWindow.h" +#include "tlLog.h" #include "ui_MainConfigPage.h" #include "ui_MainConfigPage2.h" #include "ui_MainConfigPage3.h" @@ -412,15 +413,31 @@ CustomizeMenuConfigPage::apply (const std::vectormenu ()->get_shortcuts (false); + // retained bindings, even if not configured + std::vector::iterator> retained; + std::set shortcuts; + + // initialize configured bindings, clear others (for now) and remember std::map b; b.insert (key_bindings.begin (), key_bindings.end ()); - for (std::map::iterator kb = m_current_bindings.begin (); kb != m_current_bindings.end (); ++kb) { + for (auto kb = m_current_bindings.begin (); kb != m_current_bindings.end (); ++kb) { std::map::iterator bb = b.find (kb->first); if (bb != b.end ()) { lay::Action *a = mp_dispatcher->menu ()->action (kb->first); kb->second = a->get_effective_shortcut_for (bb->second); - } else { - kb->second.clear (); + if (! kb->second.empty ()) { + shortcuts.insert (kb->second); + } + } else if (! kb->second.empty ()) { + retained.push_back (kb); + } + } + + // retain key bindings which don't conflict + for (auto i = retained.begin (); i != retained.end (); ++i) { + if (shortcuts.find ((*i)->second) != shortcuts.end ()) { + tl::warn << tl::sprintf (tl::to_string (tr ("Resetting key binding for '%s' (was '%s') because of conflicts")), (*i)->first, (*i)->second); + (*i)->second.clear (); } } diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 6a2582643..7371b9a44 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -1970,6 +1970,18 @@ MainWindow::redraw () } } +void +MainWindow::cm_grid_decrease () +{ + change_grid (-1); +} + +void +MainWindow::cm_grid_increase () +{ + change_grid (1); +} + void MainWindow::cm_cancel () { @@ -4041,6 +4053,10 @@ MainWindow::menu_activated (const std::string &symbol) cm_bookmark_view (); } else if (symbol == "cm_cancel") { cm_cancel (); + } else if (symbol == "cm_grid_decrease") { + cm_grid_decrease (); + } else if (symbol == "cm_grid_increase") { + cm_grid_increase (); } else if (symbol == "cm_save_layer_props") { cm_save_layer_props (); } else if (symbol == "cm_load_layer_props") { @@ -4137,38 +4153,114 @@ MainWindow::menu_changed () dm_do_update_menu (); } -void -MainWindow::do_update_grids () +std::vector +MainWindow::default_grids () const { - const std::vector *grids = &m_default_grids; - double default_grid = m_default_grid; - - std::vector tech_grids; lay::TechnologyController *tc = lay::TechnologyController::instance (); if (tc && tc->active_technology ()) { - tech_grids = tc->active_technology ()->default_grid_list (); + std::vector tech_grids = tc->active_technology ()->default_grid_list (); if (! tech_grids.empty ()) { - grids = &tech_grids; - default_grid = tc->active_technology ()->default_grid (); + return tech_grids; } } - if (default_grid > db::epsilon) { - for (auto g = grids->begin (); g != grids->end (); ++g) { + return m_default_grids; +} + +double +MainWindow::default_grid () const +{ + lay::TechnologyController *tc = lay::TechnologyController::instance (); + if (tc && tc->active_technology ()) { + auto tech_grids = tc->active_technology ()->default_grid_list (); + if (! tech_grids.empty ()) { + return tc->active_technology ()->default_grid (); + } + } + + return m_default_grid; +} + +void +MainWindow::change_grid (int dir) +{ + std::vector grids = default_grids (); + if (grids.empty ()) { + return; + } + + std::sort (grids.begin (), grids.end ()); + + size_t i = 0; + for (std::vector::const_iterator g = grids.begin (); g != grids.end (); ++g, ++i) { + if (db::coord_traits::equals (*g, m_grid_micron)) { + break; + } + } + + if (i == grids.size ()) { + i = (dir > 0 ? grids.size () - 1 : 0); + } else { + if (dir > 0) { + if (i + 1 < grids.size ()) { + ++i; + } + } else if (dir < 0) { + if (i > 0) { + --i; + } + } + } + + dispatcher ()->config_set (cfg_grid, grids [i]); +} + +void +MainWindow::do_update_grids () +{ + std::vector grids = default_grids (); + double def_grid = default_grid (); + + if (def_grid > db::epsilon) { + for (auto g = grids.begin (); g != grids.end (); ++g) { if (db::coord_traits::equals (*g, m_grid_micron)) { - default_grid = 0.0; + def_grid = 0.0; break; } } } - if (default_grid > db::epsilon) { - dispatcher ()->config_set (cfg_grid, default_grid); + if (def_grid > db::epsilon) { + dispatcher ()->config_set (cfg_grid, def_grid); } do_update_menu (); } +namespace { + +class GenericMenuAction + : public Action +{ +public: + GenericMenuAction (lay::Dispatcher *dispatcher, const std::string &title, const std::string &symbol) + : Action (title), mp_dispatcher (dispatcher), m_symbol (symbol) + { } + + void triggered () + { + if (mp_dispatcher) { + mp_dispatcher->menu_activated (m_symbol); + } + } + +private: + Dispatcher *mp_dispatcher; + std::string m_symbol; +}; + +} + void MainWindow::do_update_menu () { @@ -4176,27 +4268,26 @@ MainWindow::do_update_menu () m_default_grids_updated = false; - const std::vector *grids = &m_default_grids; - std::vector tech_grids; - lay::TechnologyController *tc = lay::TechnologyController::instance (); - if (tc && tc->active_technology ()) { - tech_grids = tc->active_technology ()->default_grid_list (); - if (! tech_grids.empty ()) { - grids = &tech_grids; - } - } + std::vector grids = default_grids (); + double def_grid = default_grid (); std::vector group = menu ()->group ("default_grids_group"); for (std::vector::const_iterator t = group.begin (); t != group.end (); ++t) { + std::vector items = menu ()->items (*t); for (std::vector::const_iterator i = items.begin (); i != items.end (); ++i) { menu ()->delete_item (*i); } + + menu ()->insert_item (*t + ".end", "finer_grid", new GenericMenuAction (dispatcher (), tl::to_string (tr ("Finer Grid(G)")), "cm_grid_decrease")); + menu ()->insert_item (*t + ".end", "coarser_grid", new GenericMenuAction (dispatcher (), tl::to_string (tr ("Coarser Grid(Shift+G)")), "cm_grid_increase")); + menu ()->insert_separator (*t + ".end", "default_grids_group_separator"); + } int i = 1; - for (std::vector::const_iterator g = grids->begin (); g != grids->end (); ++g, ++i) { + for (std::vector::const_iterator g = grids.begin (); g != grids.end (); ++g, ++i) { std::string name = "default_grid_" + tl::to_string (i); @@ -4208,6 +4299,10 @@ MainWindow::do_update_menu () gs = tl::to_string (*g) + tl::to_string (QObject::tr (" um")); } + if (def_grid > 0 && db::coord_traits::equals (*g, def_grid)) { + gs += tl::to_string (tr (" \\(default)")); + } + lay::Action *ga = new lay::ConfigureAction (gs, cfg_grid, tl::to_string (*g)); ga->set_checkable (true); ga->set_checked (db::coord_traits::equals (*g, m_grid_micron)); diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index ade27bd24..7e26be752 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -277,6 +277,28 @@ public: */ double grid_micron () const; + /** + * @brief Gets a list of the default grids + * + * The default grids are globally defined, but may change depending on the technology + * selected in the current view. + */ + std::vector default_grids () const; + + /** + * @brief Gets the default grid + * + * The default (fallback) grid is the one marked with "!" in the grid list + * and it is used, when the current grid is not one of the provided grids + * in the default grid list. + * + * The default grid is globally defined, but my change depending on the technology + * selected in the current view. + * + * If no such grid exists, 0 is returned. + */ + double default_grid () const; + /** * @brief Hierarchy level selection setter */ @@ -818,6 +840,8 @@ private: void cm_manage_bookmarks (); void cm_bookmark_view (); void cm_cancel (); + void cm_grid_decrease (); + void cm_grid_increase (); void cm_save_layer_props (); void cm_load_layer_props (); void cm_save_session (); @@ -863,6 +887,8 @@ private: void update_tab_title (int i); void add_view (LayoutViewWidget *view); + void change_grid (int dir); + bool can_close (); lay::CellViewRef create_or_load_layout (const std::string *filename, const db::LoadLayoutOptions *options, const std::string &tech, const int mode); int do_create_view (); diff --git a/src/layview/layview/layGridNet.cc b/src/layview/layview/layGridNet.cc index 8a1e1c4b1..b5c479f1d 100644 --- a/src/layview/layview/layGridNet.cc +++ b/src/layview/layview/layGridNet.cc @@ -29,6 +29,7 @@ #include "layPixelBufferPainter.h" #include "laySnap.h" #include "tlColor.h" +#include "tlInternational.h" #include "dbTrans.h" #if defined(HAVE_QT) @@ -118,7 +119,7 @@ GridNetPluginDeclaration::get_options (std::vector < std::pair 1e-6) { + m_grid = g; need_update = true; + + std::string gs; + if (m_grid < 0.4) { + // pick nm units below 400nm + gs = tl::to_string (m_grid * 1000.0) + tl::to_string (tr (" nm")); + } else { + gs = tl::to_string (m_grid) + tl::to_string (tr (" um")); + } + mp_view->message (tl::sprintf (tl::to_string (tr ("Grid: %s")), gs)); + } + taken = false; // to let others use the grid too. } else {