mirror of https://github.com/KLayout/klayout.git
WIP: Implementing initial via
This commit is contained in:
parent
d3d2eda54a
commit
9137919894
|
|
@ -2484,20 +2484,6 @@ MainService::via_impl (int dir)
|
|||
edt::Service *es = dynamic_cast<edt::Service *> (view ()->canvas ()->active_service ());
|
||||
if (es) {
|
||||
es->via (dir);
|
||||
} else {
|
||||
|
||||
#if 0 // @@@
|
||||
db::ShapeIterator::flags_type (db::ShapeIterator::All - db::ShapeIterator::Texts), // do not consider texts - their bounding box may be too large
|
||||
lay::ShapeFinder finder (true, view ()->is_editable () && m_top_level_sel, m_flags, &m_previous_selection);
|
||||
|
||||
// go through all visible layers of all cellviews
|
||||
finder.find (view (), search_box);
|
||||
|
||||
// collect the founds from the finder
|
||||
lay::ShapeFinder::iterator r = finder.begin ();
|
||||
if (r != finder.end ()) {
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
|
|||
db::Object (manager),
|
||||
mp_view (view),
|
||||
mp_transient_marker (0),
|
||||
m_editing (false), m_immediate (false),
|
||||
m_mouse_in_view (false), m_editing (false), m_immediate (false),
|
||||
m_selection_maybe_invalid (false),
|
||||
m_cell_inst_service (false),
|
||||
m_flags (flags),
|
||||
|
|
@ -91,7 +91,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
db::Object (manager),
|
||||
mp_view (view),
|
||||
mp_transient_marker (0),
|
||||
m_editing (false), m_immediate (false),
|
||||
m_mouse_in_view (false), m_editing (false), m_immediate (false),
|
||||
m_selection_maybe_invalid (false),
|
||||
m_cell_inst_service (true),
|
||||
m_flags (db::ShapeIterator::Nothing),
|
||||
|
|
@ -882,6 +882,8 @@ Service::move_cancel ()
|
|||
bool
|
||||
Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
m_mouse_pos = p;
|
||||
|
||||
if (view ()->is_editable () && prio) {
|
||||
|
||||
if (m_editing || m_immediate) {
|
||||
|
|
@ -948,6 +950,20 @@ Service::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Service::leave_event (bool /*prio*/)
|
||||
{
|
||||
m_mouse_in_view = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Service::enter_event (bool /*prio*/)
|
||||
{
|
||||
m_mouse_in_view = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int buttons, bool prio)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -352,6 +352,16 @@ public:
|
|||
*/
|
||||
virtual bool mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
|
||||
/**
|
||||
* @brief Mouse leave event handler
|
||||
*/
|
||||
virtual bool leave_event (bool prio);
|
||||
|
||||
/**
|
||||
* @brief Mouse enter event handler
|
||||
*/
|
||||
virtual bool enter_event (bool prio);
|
||||
|
||||
/**
|
||||
* @brief Implements the key handler
|
||||
*/
|
||||
|
|
@ -623,6 +633,21 @@ protected:
|
|||
return m_editing;
|
||||
}
|
||||
|
||||
bool top_level_sel () const
|
||||
{
|
||||
return m_top_level_sel;
|
||||
}
|
||||
|
||||
bool mouse_in_view () const
|
||||
{
|
||||
return m_mouse_in_view;
|
||||
}
|
||||
|
||||
const db::DPoint &mouse_pos () const
|
||||
{
|
||||
return m_mouse_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Point snapping with detailed return value
|
||||
*/
|
||||
|
|
@ -643,6 +668,12 @@ private:
|
|||
// The marker representing the object to be edited
|
||||
std::vector<lay::ViewObject *> m_edit_markers;
|
||||
|
||||
// The last mouse position
|
||||
db::DPoint m_mouse_pos;
|
||||
|
||||
// A flag indicating whether the mouse is inside the view
|
||||
bool m_mouse_in_view;
|
||||
|
||||
// True, if editing is in progress.
|
||||
bool m_editing;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "layMarker.h"
|
||||
#include "layLayerProperties.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layFinder.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include "layLayoutView.h"
|
||||
|
|
@ -177,22 +178,31 @@ ShapeEditService::change_edit_layer (const db::LayerProperties &lp)
|
|||
void
|
||||
ShapeEditService::set_layer (const db::LayerProperties &lp, unsigned int cv_index)
|
||||
{
|
||||
if (! mp_layout) {
|
||||
const lay::CellView &cv = view ()->cellview (cv_index);
|
||||
if (! cv.is_valid ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int layer = mp_layout->get_layer_maybe (lp);
|
||||
int layer = cv->layout ().get_layer_maybe (lp);
|
||||
if (layer < 0) {
|
||||
layer = mp_layout->insert_layer (lp);
|
||||
layer = cv->layout ().insert_layer (lp);
|
||||
}
|
||||
|
||||
m_layer = (unsigned int) layer;
|
||||
m_cv_index = cv_index;
|
||||
mp_layout = &(cv->layout ());
|
||||
mp_cell = cv.cell ();
|
||||
|
||||
m_update_edit_layer_enabled = false;
|
||||
|
||||
try {
|
||||
|
||||
view ()->set_current_layer (cv_index, lp);
|
||||
auto cl = view ()->current_layer ();
|
||||
m_trans = (cl->trans ().front () * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans ()).inverted ();
|
||||
|
||||
m_update_edit_layer_enabled = true;
|
||||
|
||||
} catch (...) {
|
||||
m_update_edit_layer_enabled = true;
|
||||
throw;
|
||||
|
|
@ -1489,31 +1499,33 @@ PathService::selection_applies (const lay::ObjectInstPath &sel) const
|
|||
void
|
||||
PathService::via (int dir)
|
||||
{
|
||||
#if ! defined(HAVE_QT)
|
||||
tl_assert (false); // see TODO
|
||||
#endif
|
||||
|
||||
if (! editing ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// not enough points to form a path
|
||||
if (m_points.size () < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// see TODO below
|
||||
#if defined(HAVE_QT)
|
||||
if (combine_mode () != CM_Add) {
|
||||
throw tl::Exception (tl::to_string (tr ("Vias are only available in 'Add' combination mode")));
|
||||
}
|
||||
|
||||
db::LayerProperties lp = layout ().get_properties (layer ());
|
||||
std::vector<db::SelectedViaDefinition> via_defs = db::find_via_definitions_for (layout ().technology_name (), lp, dir);
|
||||
if (editing ()) {
|
||||
via_editing (dir);
|
||||
} else {
|
||||
via_initial (dir);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
db::SelectedViaDefinition via_def;
|
||||
bool
|
||||
PathService::get_via_for (const db::LayerProperties &lp, unsigned int cv_index, int dir, db::SelectedViaDefinition &via_def)
|
||||
{
|
||||
const lay::CellView &cv = view ()->cellview (cv_index);
|
||||
if (! cv.is_valid ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<db::SelectedViaDefinition> via_defs = db::find_via_definitions_for (cv->layout ().technology_name (), lp, dir);
|
||||
|
||||
if (via_defs.size () == 0) {
|
||||
|
||||
return;
|
||||
return false;
|
||||
|
||||
} else if (via_defs.size () == 1) {
|
||||
|
||||
|
|
@ -1522,11 +1534,12 @@ PathService::via (int dir)
|
|||
} else if (via_defs.size () > 1) {
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
// TODO: what to do here in Qt-less case? Store results in configuration so they can be retrieved externally?
|
||||
// present a menu with the available vias.
|
||||
// TODO: what to do here in Qt-less case?
|
||||
|
||||
QWidget *view_widget = lay::widget_from_view (view ());
|
||||
if (! view_widget) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<QMenu> menu (new QMenu (view_widget));
|
||||
|
|
@ -1542,7 +1555,7 @@ PathService::via (int dir)
|
|||
|
||||
QAction *action = menu->exec (mp);
|
||||
if (! action) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
via_def = via_defs [action->data ().toInt ()];
|
||||
|
|
@ -1550,6 +1563,97 @@ PathService::via (int dir)
|
|||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PathService::via_initial (int dir)
|
||||
{
|
||||
if (! mouse_in_view ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compute search box
|
||||
double l = catch_distance ();
|
||||
db::DPoint pos = mouse_pos ();
|
||||
db::DBox search_box = db::DBox (pos, pos).enlarged (db::DVector (l, l));
|
||||
|
||||
lay::ShapeFinder finder (true, false, db::ShapeIterator::Regions);
|
||||
|
||||
// go through all visible layers of all cellviews
|
||||
finder.find (view (), search_box);
|
||||
|
||||
// collect the founds from the finder
|
||||
lay::ShapeFinder::iterator r = finder.begin ();
|
||||
if (r == finder.end ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lay::CellView &cv = view ()->cellview (r->cv_index ());
|
||||
if (! cv.is_valid ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::LayerProperties lp = cv->layout ().get_properties (r->layer ());
|
||||
|
||||
db::SelectedViaDefinition via_def;
|
||||
if (! get_via_for (lp, r->cv_index (), dir, via_def)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_layer (lp, r->cv_index ());
|
||||
|
||||
bool is_bottom = via_def.via_type.bottom.log_equal (lp);
|
||||
db::LayerProperties lp_new = is_bottom ? via_def.via_type.top : via_def.via_type.bottom;
|
||||
|
||||
{
|
||||
db::Transaction transaction (manager (), tl::to_string (tr ("Create path segment")));
|
||||
|
||||
change_edit_layer (lp_new);
|
||||
begin_edit (pos);
|
||||
|
||||
db::DPoint via_pos = m_last;
|
||||
|
||||
// create the via cell
|
||||
// (using 0.0 for all dimensions to indicate "place here")
|
||||
|
||||
double w_bottom = 0.0, h_bottom = 0.0, w_top = 0.0, h_top = 0.0;
|
||||
|
||||
std::map<std::string, tl::Variant> params;
|
||||
params.insert (std::make_pair ("via", tl::Variant (via_def.via_type.name)));
|
||||
params.insert (std::make_pair ("w_bottom", tl::Variant (w_bottom)));
|
||||
params.insert (std::make_pair ("w_top", tl::Variant (w_top)));
|
||||
params.insert (std::make_pair ("h_bottom", tl::Variant (h_bottom)));
|
||||
params.insert (std::make_pair ("h_top", tl::Variant (h_top)));
|
||||
|
||||
auto via_lib_cell = via_def.lib->layout ().get_pcell_variant_dict (via_def.pcell, params);
|
||||
auto via_cell = layout ().get_lib_proxy (via_def.lib, via_lib_cell);
|
||||
|
||||
db::Instance via_instance = cell ().insert (db::CellInstArray (db::CellInst (via_cell), db::Trans (trans () * via_pos - db::Point ())));
|
||||
push_segment (db::Shape (), via_instance, via_def.via_type, transaction.id ());
|
||||
|
||||
if (! via_def.via_type.cut.is_null ()) {
|
||||
edt::set_or_request_current_layer (view (), via_def.via_type.cut, cv_index (), false /*don't make current*/);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PathService::via_editing (int dir)
|
||||
{
|
||||
// not enough points to form a path
|
||||
if (m_points.size () < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::LayerProperties lp = layout ().get_properties (layer ());
|
||||
|
||||
db::SelectedViaDefinition via_def;
|
||||
if (! get_via_for (lp, cv_index (), dir, via_def)) {
|
||||
return;
|
||||
}
|
||||
|
||||
commit_recent (view ());
|
||||
|
||||
// produce the path up to the current point
|
||||
|
|
|
|||
|
|
@ -274,6 +274,9 @@ private:
|
|||
db::Path get_path () const;
|
||||
void set_last_point (const db::DPoint &p);
|
||||
void update_via ();
|
||||
void via_initial (int dir);
|
||||
void via_editing (int dir);
|
||||
bool get_via_for (const db::LayerProperties &lp, unsigned int cv_index, int dir, db::SelectedViaDefinition &via_def);
|
||||
void push_segment (const db::Shape &shape, const db::Instance &instance, const db::ViaType &via_type, db::Manager::transaction_id_t transaction_id);
|
||||
void pop_segment ();
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue