mirror of https://github.com/KLayout/klayout.git
WIP: introduced technology controller
The technology controller is a further abstraction and is derived from the TechnologySelector. It will act together with the MacroController and supply technology specific information. Macros are part of that.
This commit is contained in:
parent
683be55104
commit
9563d13bf3
|
|
@ -41,13 +41,13 @@ HEADERS = \
|
||||||
laySelectCellViewForm.h \
|
laySelectCellViewForm.h \
|
||||||
laySession.h \
|
laySession.h \
|
||||||
laySettingsForm.h \
|
laySettingsForm.h \
|
||||||
layTechnologySelector.h \
|
|
||||||
layTechSetupDialog.h \
|
layTechSetupDialog.h \
|
||||||
layTextProgress.h \
|
layTextProgress.h \
|
||||||
layVersion.h \
|
layVersion.h \
|
||||||
layCommon.h \
|
layCommon.h \
|
||||||
layConfig.h \
|
layConfig.h \
|
||||||
layMacroController.h
|
layMacroController.h \
|
||||||
|
layTechnologyController.h
|
||||||
|
|
||||||
FORMS = \
|
FORMS = \
|
||||||
ClipDialog.ui \
|
ClipDialog.ui \
|
||||||
|
|
@ -132,11 +132,11 @@ SOURCES = \
|
||||||
laySelectCellViewForm.cc \
|
laySelectCellViewForm.cc \
|
||||||
laySession.cc \
|
laySession.cc \
|
||||||
laySettingsForm.cc \
|
laySettingsForm.cc \
|
||||||
layTechnologySelector.cc \
|
|
||||||
layTechSetupDialog.cc \
|
layTechSetupDialog.cc \
|
||||||
layTextProgress.cc \
|
layTextProgress.cc \
|
||||||
layVersion.cc \
|
layVersion.cc \
|
||||||
layMacroController.cc
|
layMacroController.cc \
|
||||||
|
layTechnologyController.cc
|
||||||
|
|
||||||
RESOURCES = layBuildInMacros.qrc \
|
RESOURCES = layBuildInMacros.qrc \
|
||||||
layHelpResources.qrc \
|
layHelpResources.qrc \
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "layMacroController.h"
|
#include "layMacroController.h"
|
||||||
|
#include "layTechnologyController.h"
|
||||||
#include "layMacroEditorDialog.h"
|
#include "layMacroEditorDialog.h"
|
||||||
#include "layMacroInterpreter.h"
|
#include "layMacroInterpreter.h"
|
||||||
#include "layMainWindow.h"
|
#include "layMainWindow.h"
|
||||||
|
|
@ -54,6 +55,8 @@ MacroController::initialized (lay::PluginRoot *root)
|
||||||
|
|
||||||
connect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
|
connect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
|
||||||
connect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
|
connect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
|
||||||
|
connect (lay::TechnologyController::instance (), SIGNAL (active_technology_changed ()), this, SLOT (update_menu_with_macros ()));
|
||||||
|
connect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (update_menu_with_macros ()));
|
||||||
|
|
||||||
// update the menus with the macro menu bindings as late as possible (now we
|
// update the menus with the macro menu bindings as late as possible (now we
|
||||||
// can be sure that the menus are created propertly)
|
// can be sure that the menus are created propertly)
|
||||||
|
|
@ -65,6 +68,8 @@ MacroController::uninitialize (lay::PluginRoot * /*root*/)
|
||||||
{
|
{
|
||||||
disconnect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
|
disconnect (&lay::MacroCollection::root (), SIGNAL (menu_needs_update ()), this, SLOT (update_menu_with_macros ()));
|
||||||
disconnect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
|
disconnect (&lay::MacroCollection::root (), SIGNAL (macro_collection_changed (MacroCollection *)), this, SLOT (update_menu_with_macros ()));
|
||||||
|
disconnect (lay::TechnologyController::instance (), SIGNAL (active_technology_changed ()), this, SLOT (update_menu_with_macros ()));
|
||||||
|
disconnect (lay::TechnologyController::instance (), SIGNAL (technologies_edited ()), this, SLOT (update_menu_with_macros ()));
|
||||||
|
|
||||||
delete mp_macro_editor;
|
delete mp_macro_editor;
|
||||||
mp_macro_editor = 0;
|
mp_macro_editor = 0;
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@
|
||||||
#include "layLayerToolbox.h"
|
#include "layLayerToolbox.h"
|
||||||
#include "laySettingsForm.h"
|
#include "laySettingsForm.h"
|
||||||
#include "laySettingsForm.h"
|
#include "laySettingsForm.h"
|
||||||
#include "layTechSetupDialog.h"
|
#include "layTechnologyController.h"
|
||||||
#include "layTipDialog.h"
|
#include "layTipDialog.h"
|
||||||
#include "laySelectCellViewForm.h"
|
#include "laySelectCellViewForm.h"
|
||||||
#include "layLayoutPropertiesForm.h"
|
#include "layLayoutPropertiesForm.h"
|
||||||
|
|
@ -4507,29 +4507,9 @@ MainWindow::show_progress_bar (bool show)
|
||||||
void
|
void
|
||||||
MainWindow::cm_technologies ()
|
MainWindow::cm_technologies ()
|
||||||
{
|
{
|
||||||
lay::TechSetupDialog dialog (this);
|
lay::TechnologyController *tc = lay::TechnologyController::instance ();
|
||||||
if (dialog.exec ()) {
|
if (tc) {
|
||||||
|
tc->show_editor ();
|
||||||
std::vector<lay::MacroCollection *> nm = lay::Application::instance ()->sync_tech_macro_locations ();
|
|
||||||
|
|
||||||
bool has_autorun = false;
|
|
||||||
for (std::vector<lay::MacroCollection *>::const_iterator m = nm.begin (); m != nm.end () && ! has_autorun; ++m) {
|
|
||||||
has_autorun = (*m)->has_autorun ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_autorun && QMessageBox::question (this, QObject::tr ("Run Macros"), QObject::tr ("Some macros associated with technologies now are configured to run automatically.\n\nChoose 'Yes' to run these macros now. Choose 'No' to not run them."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
|
||||||
for (std::vector<lay::MacroCollection *>::const_iterator m = nm.begin (); m != nm.end (); ++m) {
|
|
||||||
(*m)->autorun ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// because the macro-tech association might have changed, do this:
|
|
||||||
// TODO: let the macro controller monitor the technologies.
|
|
||||||
lay::MacroController *mc = lay::MacroController::instance ();
|
|
||||||
if (mc) {
|
|
||||||
mc->update_menu_with_macros ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,295 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "layTechnologyController.h"
|
||||||
|
#include "layTechSetupDialog.h"
|
||||||
|
#include "layMainWindow.h"
|
||||||
|
#include "layMacroController.h"
|
||||||
|
#include "layApplication.h"
|
||||||
|
#include "laybasicConfig.h"
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
namespace lay
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string tech_string_from_name (const std::string &tn)
|
||||||
|
{
|
||||||
|
if (tn.empty ()) {
|
||||||
|
return tl::to_string (QObject::tr ("(Default)"));
|
||||||
|
} else {
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TechnologyController::TechnologyController ()
|
||||||
|
: PluginDeclaration (), mp_editor (0), mp_mw (0)
|
||||||
|
{
|
||||||
|
m_current_technology_updated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TechnologyController *
|
||||||
|
TechnologyController::instance ()
|
||||||
|
{
|
||||||
|
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
|
||||||
|
TechnologyController *tc = dynamic_cast <TechnologyController *> (cls.operator-> ());
|
||||||
|
if (tc) {
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::initialized (lay::PluginRoot *root)
|
||||||
|
{
|
||||||
|
mp_mw = dynamic_cast <lay::MainWindow *> (root);
|
||||||
|
if (mp_mw) {
|
||||||
|
mp_editor = new lay::TechSetupDialog (mp_mw);
|
||||||
|
mp_editor->setModal (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_menu ();
|
||||||
|
update_after_change ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::uninitialize (lay::PluginRoot * /*root*/)
|
||||||
|
{
|
||||||
|
m_tech_actions.clear ();
|
||||||
|
tl::Object::detach_from_all_events ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
||||||
|
{
|
||||||
|
options.push_back (std::pair<std::string, std::string> (cfg_initial_technology, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
||||||
|
{
|
||||||
|
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||||
|
menu_entries.push_back (lay::MenuEntry ("technology_selector:apply_technology", "technology_selector:tech_selector_group", "@toolbar.end", tl::to_string (QObject::tr ("Technology<:techs.png>{Select technology (click to apply)}"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::update_after_change ()
|
||||||
|
{
|
||||||
|
// re-attach all events
|
||||||
|
tl::Object::detach_from_all_events ();
|
||||||
|
|
||||||
|
lay::MainWindow::instance ()->current_view_changed_event.add (this, &TechnologyController::update_after_change);
|
||||||
|
lay::Technologies::instance ()->technology_changed_event.add (this, &TechnologyController::technology_changed);
|
||||||
|
lay::Technologies::instance ()->technologies_changed_event.add (this, &TechnologyController::technologies_changed);
|
||||||
|
|
||||||
|
if (lay::LayoutView::current ()) {
|
||||||
|
lay::LayoutView::current ()->active_cellview_changed_event.add (this, &TechnologyController::update_after_change);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string active_tech;
|
||||||
|
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview_index () >= 0 && lay::LayoutView::current ()->active_cellview_index () <= int (lay::LayoutView::current ()->cellviews ())) {
|
||||||
|
lay::LayoutView::current ()->active_cellview ()->technology_changed_event.add (this, &TechnologyController::update_after_change);
|
||||||
|
active_tech = lay::LayoutView::current ()->active_cellview ()->tech_name ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_active_technology != active_tech) {
|
||||||
|
|
||||||
|
m_active_technology = active_tech;
|
||||||
|
|
||||||
|
lay::MainWindow *mw = lay::MainWindow::instance ();
|
||||||
|
if (mw) {
|
||||||
|
mw->tech_message (tech_string_from_name (active_tech));
|
||||||
|
}
|
||||||
|
lay::MacroController *mc = lay::MacroController::instance ();
|
||||||
|
if (mc) {
|
||||||
|
// TODO: let the macro controller monitor the active technology
|
||||||
|
// need to do this since macros may be bound to the new technology
|
||||||
|
mc->update_menu_with_macros ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Hint with this implementation, the current technology follows the current layout.
|
||||||
|
// Although that's a nice way to display the current technology, it's pretty confusing
|
||||||
|
lay::PluginRoot *pr = lay::PluginRoot::instance ();
|
||||||
|
if (pr) {
|
||||||
|
pr->config_set (cfg_initial_technology, active_tech);
|
||||||
|
pr->config_finalize ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::technologies_changed ()
|
||||||
|
{
|
||||||
|
// delay actual update of menu so we can compress multiple events
|
||||||
|
update_menu ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::technology_changed (lay::Technology *)
|
||||||
|
{
|
||||||
|
// delay actual update of menu so we can compress multiple events
|
||||||
|
update_menu ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TechnologyController::configure (const std::string &name, const std::string &value)
|
||||||
|
{
|
||||||
|
if (name == cfg_initial_technology) {
|
||||||
|
|
||||||
|
if (value != m_current_technology) {
|
||||||
|
m_current_technology = value;
|
||||||
|
m_current_technology_updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::config_finalize ()
|
||||||
|
{
|
||||||
|
if (m_current_technology_updated) {
|
||||||
|
update_current_technology ();
|
||||||
|
m_current_technology_updated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TechnologyController::menu_activated (const std::string &symbol) const
|
||||||
|
{
|
||||||
|
if (symbol == "technology_selector:apply_technology") {
|
||||||
|
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview ().is_valid ()) {
|
||||||
|
lay::LayoutView::current ()->active_cellview ()->apply_technology (m_current_technology);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return lay::PluginDeclaration::menu_activated (symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::update_current_technology ()
|
||||||
|
{
|
||||||
|
lay::AbstractMenuProvider *pr = lay::AbstractMenuProvider::instance ();
|
||||||
|
if (! pr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string title = tech_string_from_name (m_current_technology);
|
||||||
|
|
||||||
|
std::vector<std::string> menu_entries = pr->menu ()->group ("tech_selector_group");
|
||||||
|
for (std::vector<std::string>::const_iterator m = menu_entries.begin (); m != menu_entries.end (); ++m) {
|
||||||
|
lay::Action action = pr->menu ()->action (*m);
|
||||||
|
action.set_title (title);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t it = 0;
|
||||||
|
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end () && it < m_tech_actions.size (); ++t, ++it) {
|
||||||
|
m_tech_actions[it].set_checked (t->name () == m_current_technology);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::update_menu ()
|
||||||
|
{
|
||||||
|
lay::AbstractMenuProvider *pr = lay::AbstractMenuProvider::instance ();
|
||||||
|
if (! pr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview ().is_valid ()) {
|
||||||
|
m_current_technology = lay::LayoutView::current ()->active_cellview ()->tech_name ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string title = tech_string_from_name (m_current_technology);
|
||||||
|
|
||||||
|
size_t ntech = 0;
|
||||||
|
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) {
|
||||||
|
++ntech;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> tech_group = pr->menu ()->group ("tech_selector_group");
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator t = tech_group.begin (); t != tech_group.end (); ++t) {
|
||||||
|
lay::Action action = pr->menu ()->action (*t);
|
||||||
|
action.set_title (title);
|
||||||
|
action.set_visible (ntech > 1);
|
||||||
|
std::vector<std::string> items = pr->menu ()->items (*t);
|
||||||
|
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
|
||||||
|
pr->menu ()->delete_item (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_tech_actions.clear ();
|
||||||
|
|
||||||
|
int it = 0;
|
||||||
|
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t, ++it) {
|
||||||
|
|
||||||
|
std::string title = tech_string_from_name (t->name ());
|
||||||
|
|
||||||
|
m_tech_actions.push_back (pr->create_config_action ("", cfg_initial_technology, t->name ()));
|
||||||
|
m_tech_actions.back ().set_title (title); // setting the title here avoids interpretation of '(...)' etc.
|
||||||
|
m_tech_actions.back ().set_checkable (true);
|
||||||
|
m_tech_actions.back ().set_checked (t->name () == m_current_technology);
|
||||||
|
for (std::vector<std::string>::const_iterator t = tech_group.begin (); t != tech_group.end (); ++t) {
|
||||||
|
pr->menu ()->insert_item (*t + ".end", "technology_" + tl::to_string (it), m_tech_actions.back ());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TechnologyController::show_editor ()
|
||||||
|
{
|
||||||
|
if (mp_editor && mp_editor->exec ()) {
|
||||||
|
|
||||||
|
std::vector<lay::MacroCollection *> nm = lay::Application::instance ()->sync_tech_macro_locations ();
|
||||||
|
|
||||||
|
bool has_autorun = false;
|
||||||
|
for (std::vector<lay::MacroCollection *>::const_iterator m = nm.begin (); m != nm.end () && ! has_autorun; ++m) {
|
||||||
|
has_autorun = (*m)->has_autorun ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_autorun && QMessageBox::question (mp_mw, QObject::tr ("Run Macros"), QObject::tr ("Some macros associated with technologies now are configured to run automatically.\n\nChoose 'Yes' to run these macros now. Choose 'No' to not run them."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||||
|
for (std::vector<lay::MacroCollection *>::const_iterator m = nm.begin (); m != nm.end (); ++m) {
|
||||||
|
(*m)->autorun ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// because the macro-tech association might have changed, do this:
|
||||||
|
// TODO: let the macro controller monitor the technologies.
|
||||||
|
lay::MacroController *mc = lay::MacroController::instance ();
|
||||||
|
if (mc) {
|
||||||
|
mc->update_menu_with_macros ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new TechnologyController (), 110, "TechnologyController");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HDR_layTechnologyController
|
||||||
|
#define HDR_layTechnologyController
|
||||||
|
|
||||||
|
#include "layCommon.h"
|
||||||
|
#include "layPlugin.h"
|
||||||
|
#include "layTechnology.h"
|
||||||
|
#include "layAbstractMenu.h"
|
||||||
|
|
||||||
|
namespace lay
|
||||||
|
{
|
||||||
|
|
||||||
|
class TechSetupDialog;
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A "controller" for the technologies
|
||||||
|
* The main task of the controller is to establish and manage the
|
||||||
|
* list of technologies and to manage the active technology.
|
||||||
|
*/
|
||||||
|
class LAY_PUBLIC TechnologyController
|
||||||
|
: public PluginDeclaration,
|
||||||
|
public tl::Object
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
TechnologyController ();
|
||||||
|
|
||||||
|
void initialized (lay::PluginRoot *root);
|
||||||
|
void uninitialize (lay::PluginRoot *root);
|
||||||
|
|
||||||
|
void get_options (std::vector < std::pair<std::string, std::string> > &options) const;
|
||||||
|
void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const;
|
||||||
|
|
||||||
|
void show_editor ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the name of the active technology
|
||||||
|
* The active technology is the one the current cellview uses
|
||||||
|
*/
|
||||||
|
const std::string &active_technology () const
|
||||||
|
{
|
||||||
|
return m_active_technology;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TechnologyController *instance ();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief This signal is emitted if the active technology has changed
|
||||||
|
*/
|
||||||
|
void active_technology_changed ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This signal is emitted if the technology list has been edited
|
||||||
|
* This signal is emitted if either the list or one technology has been
|
||||||
|
* edited. It indicates the need for reflecting changes in the technology
|
||||||
|
* setup.
|
||||||
|
*/
|
||||||
|
void technologies_edited ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
tl::stable_vector <lay::Action> m_tech_actions;
|
||||||
|
std::string m_current_technology;
|
||||||
|
std::string m_active_technology;
|
||||||
|
bool m_current_technology_updated;
|
||||||
|
lay::TechSetupDialog *mp_editor;
|
||||||
|
lay::MainWindow *mp_mw;
|
||||||
|
|
||||||
|
void update_after_change ();
|
||||||
|
void technologies_changed ();
|
||||||
|
void technology_changed (lay::Technology *);
|
||||||
|
bool configure (const std::string &name, const std::string &value);
|
||||||
|
void config_finalize ();
|
||||||
|
bool menu_activated (const std::string &symbol) const;
|
||||||
|
void update_current_technology ();
|
||||||
|
void update_menu ();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -1,256 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
KLayout Layout Viewer
|
|
||||||
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "layTechnologySelector.h"
|
|
||||||
#include "layPlugin.h"
|
|
||||||
#include "laybasicConfig.h"
|
|
||||||
#include "layMainWindow.h"
|
|
||||||
#include "layMacroController.h"
|
|
||||||
#include "layTechnology.h"
|
|
||||||
#include "laybasicConfig.h"
|
|
||||||
#include "tlDeferredExecution.h"
|
|
||||||
|
|
||||||
namespace lay
|
|
||||||
{
|
|
||||||
|
|
||||||
std::string tech_string_from_name (const std::string &tn)
|
|
||||||
{
|
|
||||||
if (tn.empty ()) {
|
|
||||||
return tl::to_string (QObject::tr ("(Default)"));
|
|
||||||
} else {
|
|
||||||
return tn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LAY_PUBLIC TechnologySelector
|
|
||||||
: public PluginDeclaration,
|
|
||||||
public tl::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TechnologySelector ()
|
|
||||||
: PluginDeclaration ()
|
|
||||||
{
|
|
||||||
m_current_technology_updated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initialize (lay::PluginRoot * /*root*/)
|
|
||||||
{
|
|
||||||
// don't initialize in the -z case (no gui)
|
|
||||||
if (! lay::MainWindow::instance ()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_menu ();
|
|
||||||
update_after_change ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void uninitialize (lay::PluginRoot * /*root*/)
|
|
||||||
{
|
|
||||||
m_tech_actions.clear ();
|
|
||||||
tl::Object::detach_from_all_events ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
|
||||||
{
|
|
||||||
options.push_back (std::pair<std::string, std::string> (cfg_initial_technology, ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
|
||||||
{
|
|
||||||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
|
||||||
menu_entries.push_back (lay::MenuEntry ("technology_selector:apply_technology", "technology_selector:tech_selector_group", "@toolbar.end", tl::to_string (QObject::tr ("Technology<:techs.png>{Select technology (click to apply)}"))));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
tl::stable_vector <lay::Action> m_tech_actions;
|
|
||||||
std::string m_current_technology;
|
|
||||||
std::string m_active_technology;
|
|
||||||
bool m_current_technology_updated;
|
|
||||||
|
|
||||||
void update_after_change ()
|
|
||||||
{
|
|
||||||
// re-attach all events
|
|
||||||
tl::Object::detach_from_all_events ();
|
|
||||||
|
|
||||||
lay::MainWindow::instance ()->current_view_changed_event.add (this, &TechnologySelector::update_after_change);
|
|
||||||
lay::Technologies::instance ()->technology_changed_event.add (this, &TechnologySelector::technology_changed);
|
|
||||||
lay::Technologies::instance ()->technologies_changed_event.add (this, &TechnologySelector::technologies_changed);
|
|
||||||
|
|
||||||
if (lay::LayoutView::current ()) {
|
|
||||||
lay::LayoutView::current ()->active_cellview_changed_event.add (this, &TechnologySelector::update_after_change);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string active_tech;
|
|
||||||
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview_index () >= 0 && lay::LayoutView::current ()->active_cellview_index () <= int (lay::LayoutView::current ()->cellviews ())) {
|
|
||||||
lay::LayoutView::current ()->active_cellview ()->technology_changed_event.add (this, &TechnologySelector::update_after_change);
|
|
||||||
active_tech = lay::LayoutView::current ()->active_cellview ()->tech_name ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_active_technology != active_tech) {
|
|
||||||
|
|
||||||
m_active_technology = active_tech;
|
|
||||||
|
|
||||||
lay::MainWindow *mw = lay::MainWindow::instance ();
|
|
||||||
if (mw) {
|
|
||||||
mw->tech_message (tech_string_from_name (active_tech));
|
|
||||||
}
|
|
||||||
lay::MacroController *mc = lay::MacroController::instance ();
|
|
||||||
if (mc) {
|
|
||||||
// TODO: let the macro controller monitor the active technology
|
|
||||||
// need to do this since macros may be bound to the new technology
|
|
||||||
mc->update_menu_with_macros ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Hint with this implementation, the current technology follows the current layout.
|
|
||||||
// Although that's a nice way to display the current technology, it's pretty confusing
|
|
||||||
lay::PluginRoot *pr = lay::PluginRoot::instance ();
|
|
||||||
if (pr) {
|
|
||||||
pr->config_set (cfg_initial_technology, active_tech);
|
|
||||||
pr->config_finalize ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void technologies_changed ()
|
|
||||||
{
|
|
||||||
// delay actual update of menu so we can compress multiple events
|
|
||||||
update_menu ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void technology_changed (lay::Technology *)
|
|
||||||
{
|
|
||||||
// delay actual update of menu so we can compress multiple events
|
|
||||||
update_menu ();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configure (const std::string &name, const std::string &value)
|
|
||||||
{
|
|
||||||
if (name == cfg_initial_technology) {
|
|
||||||
|
|
||||||
if (value != m_current_technology) {
|
|
||||||
m_current_technology = value;
|
|
||||||
m_current_technology_updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void config_finalize ()
|
|
||||||
{
|
|
||||||
if (m_current_technology_updated) {
|
|
||||||
update_current_technology ();
|
|
||||||
m_current_technology_updated = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool menu_activated (const std::string &symbol) const
|
|
||||||
{
|
|
||||||
if (symbol == "technology_selector:apply_technology") {
|
|
||||||
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview ().is_valid ()) {
|
|
||||||
lay::LayoutView::current ()->active_cellview ()->apply_technology (m_current_technology);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return lay::PluginDeclaration::menu_activated (symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_current_technology ()
|
|
||||||
{
|
|
||||||
lay::AbstractMenuProvider *pr = lay::AbstractMenuProvider::instance ();
|
|
||||||
if (! pr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string title = tech_string_from_name (m_current_technology);
|
|
||||||
|
|
||||||
std::vector<std::string> menu_entries = pr->menu ()->group ("tech_selector_group");
|
|
||||||
for (std::vector<std::string>::const_iterator m = menu_entries.begin (); m != menu_entries.end (); ++m) {
|
|
||||||
lay::Action action = pr->menu ()->action (*m);
|
|
||||||
action.set_title (title);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t it = 0;
|
|
||||||
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end () && it < m_tech_actions.size (); ++t, ++it) {
|
|
||||||
m_tech_actions[it].set_checked (t->name () == m_current_technology);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_menu ()
|
|
||||||
{
|
|
||||||
lay::AbstractMenuProvider *pr = lay::AbstractMenuProvider::instance ();
|
|
||||||
if (! pr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lay::LayoutView::current () && lay::LayoutView::current ()->active_cellview ().is_valid ()) {
|
|
||||||
m_current_technology = lay::LayoutView::current ()->active_cellview ()->tech_name ();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string title = tech_string_from_name (m_current_technology);
|
|
||||||
|
|
||||||
size_t ntech = 0;
|
|
||||||
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) {
|
|
||||||
++ntech;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> tech_group = pr->menu ()->group ("tech_selector_group");
|
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator t = tech_group.begin (); t != tech_group.end (); ++t) {
|
|
||||||
lay::Action action = pr->menu ()->action (*t);
|
|
||||||
action.set_title (title);
|
|
||||||
action.set_visible (ntech > 1);
|
|
||||||
std::vector<std::string> items = pr->menu ()->items (*t);
|
|
||||||
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
|
|
||||||
pr->menu ()->delete_item (*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tech_actions.clear ();
|
|
||||||
|
|
||||||
int it = 0;
|
|
||||||
for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t, ++it) {
|
|
||||||
|
|
||||||
std::string title = tech_string_from_name (t->name ());
|
|
||||||
|
|
||||||
m_tech_actions.push_back (pr->create_config_action ("", cfg_initial_technology, t->name ()));
|
|
||||||
m_tech_actions.back ().set_title (title); // setting the title here avoids interpretation of '(...)' etc.
|
|
||||||
m_tech_actions.back ().set_checkable (true);
|
|
||||||
m_tech_actions.back ().set_checked (t->name () == m_current_technology);
|
|
||||||
for (std::vector<std::string>::const_iterator t = tech_group.begin (); t != tech_group.end (); ++t) {
|
|
||||||
pr->menu ()->insert_item (*t + ".end", "technology_" + tl::to_string (it), m_tech_actions.back ());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new TechnologySelector (), 9000, "TechnologySelector");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
KLayout Layout Viewer
|
|
||||||
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HDR_layTechnologySelector
|
|
||||||
#define HDR_layTechnologySelector
|
|
||||||
|
|
||||||
namespace lay
|
|
||||||
{
|
|
||||||
|
|
||||||
// no exposes classes. Everything is inside the plugin declaration singleton.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue