Merge pull request #2394 from KLayout/feature/issue-2391

Implemented "cm_grid_increase" and "cm_grid_decrease"
This commit is contained in:
Matthias Köfferlein 2026-07-20 23:03:15 +02:00 committed by GitHub
commit bc5d1a35f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 179 additions and 28 deletions

View File

@ -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::vector<std::pair<std::string, std::st
// gets the current bindings and merges with the given ones
m_current_bindings = mp_dispatcher->menu ()->get_shortcuts (false);
// retained bindings, even if not configured
std::vector<std::map<std::string, std::string>::iterator> retained;
std::set<std::string> shortcuts;
// initialize configured bindings, clear others (for now) and remember
std::map<std::string, std::string> b;
b.insert (key_bindings.begin (), key_bindings.end ());
for (std::map<std::string, std::string>::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<std::string, std::string>::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 ();
}
}

View File

@ -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<double>
MainWindow::default_grids () const
{
const std::vector<double> *grids = &m_default_grids;
double default_grid = m_default_grid;
std::vector<double> tech_grids;
lay::TechnologyController *tc = lay::TechnologyController::instance ();
if (tc && tc->active_technology ()) {
tech_grids = tc->active_technology ()->default_grid_list ();
std::vector<double> 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<double> grids = default_grids ();
if (grids.empty ()) {
return;
}
std::sort (grids.begin (), grids.end ());
size_t i = 0;
for (std::vector<double>::const_iterator g = grids.begin (); g != grids.end (); ++g, ++i) {
if (db::coord_traits<db::DCoord>::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<double> 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<db::DCoord>::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<double> *grids = &m_default_grids;
std::vector<double> 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<double> grids = default_grids ();
double def_grid = default_grid ();
std::vector<std::string> group = menu ()->group ("default_grids_group");
for (std::vector<std::string>::const_iterator t = group.begin (); t != group.end (); ++t) {
std::vector<std::string> items = menu ()->items (*t);
for (std::vector<std::string>::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<double>::const_iterator g = grids->begin (); g != grids->end (); ++g, ++i) {
for (std::vector<double>::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<db::DCoord>::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<db::DCoord>::equals (*g, m_grid_micron));

View File

@ -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<double> 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 ();

View File

@ -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<std::string, std:
lay::ConfigPage *
GridNetPluginDeclaration::config_page (QWidget *parent, std::string &title) const
{
title = tl::to_string (QObject::tr ("Display|Background"));
title = tl::to_string (tr ("Display|Background"));
return new GridNetConfigPage (parent);
}
#endif
@ -216,9 +217,21 @@ GridNet::configure (const std::string &name, const std::string &value)
double g = 0;
tl::from_string (value, g);
if (fabs (g - m_grid) > 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 {