Better support for point-like handles

PCells have been featuring point-like handles but
they suffered some issues because they have been
mapped to degenerated boxes:

- hardly visible
- could be destroyed using partial editing

Now, the database offers points, hence it is
possible to store points explicitly, so no
tricks need to be played to make them visible.

Editing has been implemented to some extent,
so it is possible for example to configure
handles in the properties dialogs.
This commit is contained in:
Matthias Koefferlein 2023-07-29 01:01:50 +02:00
parent 6e4ac71442
commit e53d432117
4 changed files with 72 additions and 5 deletions

View File

@ -849,6 +849,14 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
}
} else if (shape->is_point ()) {
db::Point tp (shape->point ());
if (hit_box.contains (tp)) {
edges.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
}
} else if (shape->is_text ()) {
db::Point tp (shape->text_trans () * db::Point ());
@ -1000,6 +1008,17 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
}
} else if (shape->is_point ()) {
db::Point tp (shape->point ());
if (hit_box.contains (tp)) {
d = tp.distance (hit_box.center ());
edge_sel.clear ();
edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
match = true;
}
} else if (shape->is_text ()) {
db::Point tp (shape->text_trans () * db::Point ());
@ -1258,6 +1277,11 @@ PartialService::timeout ()
db::Point tp (r->first.shape ().text_trans () * db::Point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true);
} else if (r->first.shape ().is_point ()) {
db::Point tp (r->first.shape ().point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true);
}
}
@ -1479,6 +1503,17 @@ PartialService::transform_selection (const db::DTrans &move_trans)
shape = shapes.replace (shape, t);
}
} else if (shape.is_point ()) {
db::Point p;
shape.point (p);
std::map <PointWithIndex, db::Point>::const_iterator np = new_points.find (PointWithIndex (p, 0, 0));
if (np != new_points.end ()) {
shape = shapes.replace (shape, np->second);
}
}
// transform the selection
@ -2204,7 +2239,7 @@ PartialService::del ()
shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector <partial_objects::const_iterator> ())).first->second.push_back (r);
}
} else if (shape.is_text ()) {
} else if (shape.is_text () || shape.is_point ()) {
shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector <partial_objects::const_iterator> ())).first->second.push_back (r);
@ -2684,6 +2719,11 @@ PartialService::do_selection_to_view ()
db::Point tp (r->first.shape ().text_trans () * db::Point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false);
} else if (r->first.shape ().is_point ()) {
db::Point tp (r->first.shape ().point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false);
}
}

View File

@ -1108,7 +1108,20 @@ Service::transient_select (const db::DPoint &pos)
lay::ShapeMarker *marker = new lay::ShapeMarker (view (), r->cv_index ());
marker->set (r->shape (), gt, mp_view->cv_transform_variants (r->cv_index (), r->layer ()));
marker->set_vertex_size (0);
bool is_point = false;
if (r->shape ().is_edge () || r->shape ().is_box ()) {
is_point = r->shape ().bbox ().is_point ();
} else if (r->shape ().is_point ()) {
is_point = true;
}
if (is_point) {
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);
} else {
marker->set_vertex_size (0);
}
marker->set_line_width (1);
marker->set_halo (0);
@ -1602,7 +1615,15 @@ Service::do_selection_to_view ()
}
marker->set (r->shape (), gt, *tv_list);
if (r->shape ().is_text ()) {
bool is_point = false;
if (r->shape ().is_text () || r->shape ().is_point ()) {
is_point = true;
} else if (r->shape ().is_edge () || r->shape ().is_box ()) {
is_point = r->shape ().bbox ().is_point ();
}
if (is_point) {
// show the origins as crosses for texts
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);

View File

@ -606,7 +606,7 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db:
match = true;
}
} else if (shape->is_box () || shape->is_text ()) {
} else if (shape->is_box () || shape->is_point () || shape->is_text ()) {
db::Box box = shape->bbox ();
if (text_info () && shape->is_text ()) {

View File

@ -598,7 +598,7 @@ private:
const db::Shapes &shapes = cell.shapes (l);
db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel);
db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel);
while (! shape.at_end () && m_tests > 0) {
--m_tests;
@ -653,6 +653,12 @@ private:
test_edge (t * db::Edge (box.p2 (), db::Point (box.right (), box.bottom ())));
test_edge (t * db::Edge (db::Point (box.right (), box.bottom ()), box.p1 ()));
} else if (shape->is_point ()) {
const db::Point &p = shape->point ();
test_edge (t * db::Edge (p, p));
}
++shape;