Skip to content

Commit

Permalink
Better integration of partial mode - for example 'interactive move' n…
Browse files Browse the repository at this point in the history
…ow also acts on partial selection
  • Loading branch information
Matthias Koefferlein committed Sep 3, 2023
1 parent 10f3380 commit b2ab892
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 2 deletions.
158 changes: 156 additions & 2 deletions src/edt/edt/edtPartialService.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1146,8 +1146,6 @@ PartialService::move_ac () const
void
PartialService::deactivated ()
{
// clear selection when this mode is left
partial_select (db::DBox (), lay::Editable::Reset);
clear_partial_transient_selection ();
}

Expand Down Expand Up @@ -2169,6 +2167,110 @@ PartialService::mouse_release_event (const db::DPoint &p, unsigned int buttons,
return false;
}

bool
PartialService::begin_move (MoveMode mode, const db::DPoint &p, lay::angle_constraint_type ac)
{
if (has_selection () && mode == lay::Editable::Selected) {

m_alt_ac = ac;

m_dragging = true;
m_keep_selection = true;

if (is_single_point_selection ()) {
// for a single selected point we use the original point as the start location which
// allows bringing it to grid
m_current = m_start = single_selected_point ();
} else if (is_single_edge_selection ()) {
// for an edge selection use the point projected to edge as the start location which
// allows bringing it to grid
m_current = m_start = projected_to_edge (single_selected_edge (), p);
} else {
m_current = m_start = p;
}

m_alt_ac = lay::AC_Global;

return true;

} else {
return false;
}
}

void
PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac)
{
m_alt_ac = ac;

set_cursor (lay::Cursor::size_all);

// drag the vertex or edge/segment
if (is_single_point_selection () || is_single_edge_selection ()) {

lay::PointSnapToObjectResult snap_details;

// for a single selected point or edge, m_start is the original position and we snap the target -
// thus, we can bring the point on grid or to an object's edge or vertex
snap_details = snap2 (p);
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
m_current = m_start + snap (p - m_start);
} else {
m_current = snap_details.snapped_point;
mouse_cursor_from_snap_details (snap_details);
}

} else {

// snap movement to angle and grid without object
m_current = m_start + snap (p - m_start);
clear_mouse_cursors ();

}

selection_to_view ();

m_alt_ac = lay::AC_Global;
}

void
PartialService::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type ac)
{
m_alt_ac = ac;

if (m_current != m_start) {

// stop dragging
ui ()->ungrab_mouse (this);

if (manager ()) {
manager ()->transaction (tl::to_string (tr ("Partial move")));
}

// heuristically, if there is just one edge selected: do not confine to the movement
// angle constraint - the edge usually is confined enough
db::DTrans move_trans = db::DTrans (m_current - m_start);

transform_selection (move_trans);

if (manager ()) {
manager ()->commit ();
}

}

if (! m_keep_selection) {
m_selection.clear ();
}

m_dragging = false;
selection_to_view ();

clear_mouse_cursors ();

m_alt_ac = lay::AC_Global;
}

bool
PartialService::has_selection ()
{
Expand All @@ -2181,6 +2283,58 @@ PartialService::selection_size ()
return m_selection.size ();
}

db::DBox
PartialService::selection_bbox ()
{
// build the transformation variants cache
// TODO: this is done multiple times - once for each service!
TransformationVariants tv (view ());
const db::DCplxTrans &vp = view ()->viewport ().trans ();

lay::TextInfo text_info (view ());

db::DBox box;
for (partial_objects::const_iterator r = m_selection.begin (); r != m_selection.end (); ++r) {

const lay::CellView &cv = view ()->cellview (r->first.cv_index ());
const db::Layout &layout = cv->layout ();

db::CplxTrans ctx_trans = db::CplxTrans (layout.dbu ()) * cv.context_trans () * r->first.trans ();

db::box_convert<db::CellInst> bc (layout);
if (! r->first.is_cell_inst ()) {

const std::vector<db::DCplxTrans> *tv_list = tv.per_cv_and_layer (r->first.cv_index (), r->first.layer ());
if (tv_list != 0) {
for (std::vector<db::DCplxTrans>::const_iterator t = tv_list->begin (); t != tv_list->end (); ++t) {
if (r->first.shape ().is_text ()) {
db::Text text;
r->first.shape ().text (text);
box += *t * text_info.bbox (ctx_trans * text, vp * *t);
} else {
for (auto e = r->second.begin (); e != r->second.end (); ++e) {
box += *t * (ctx_trans * e->bbox ());
}
}
}
}

} else {

const std::vector<db::DCplxTrans> *tv_list = tv.per_cv (r->first.cv_index ());
if (tv_list != 0) {
for (std::vector<db::DCplxTrans>::const_iterator t = tv_list->begin (); t != tv_list->end (); ++t) {
box += *t * (ctx_trans * r->first.back ().bbox (bc));
}
}

}

}

return box;
}

bool
PartialService::has_transient_selection ()
{
Expand Down
20 changes: 20 additions & 0 deletions src/edt/edt/edtPartialService.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,26 @@ Q_OBJECT
*/
virtual bool has_transient_selection ();

/**
* @brief Gets the selection bounding box
*/
virtual db::DBox selection_bbox ();

/**
* @brief Start a "move" operation
*/
virtual bool begin_move (MoveMode sel, const db::DPoint &p, lay::angle_constraint_type ac);

/**
* @brief Continue a "move" operation
*/
virtual void move (const db::DPoint &p, lay::angle_constraint_type ac);

/**
* @brief Terminate a "move" operation
*/
virtual void end_move (const db::DPoint &p, lay::angle_constraint_type ac);

/**
* @brief Implement the "select" method at least to clear the selection
*/
Expand Down

0 comments on commit b2ab892

Please sign in to comment.