WIP: better highlighting of snap objects.

This commit is contained in:
Matthias Koefferlein 2020-09-07 22:35:06 +02:00
parent e42136ee27
commit 307c10f184
6 changed files with 296 additions and 91 deletions

View File

@ -61,8 +61,7 @@ ac_from_buttons (unsigned int buttons)
// -------------------------------------------------------------
Service::Service (db::Manager *manager, lay::LayoutView *view, db::ShapeIterator::flags_type flags)
: lay::ViewService (view->view_object_widget ()),
lay::Editable (view),
: lay::EditorServiceBase (view),
lay::Plugin (view),
db::Object (manager),
mp_view (view),
@ -83,8 +82,7 @@ Service::Service (db::Manager *manager, lay::LayoutView *view, db::ShapeIterator
}
Service::Service (db::Manager *manager, lay::LayoutView *view)
: lay::ViewService (view->view_object_widget ()),
lay::Editable (view),
: lay::EditorServiceBase (view),
lay::Plugin (view),
db::Object (manager),
mp_view (view),
@ -116,7 +114,6 @@ Service::~Service ()
}
m_edit_markers.clear ();
reset_mouse_cursor ();
clear_transient_selection ();
}
@ -480,71 +477,6 @@ Service::selection_bbox ()
return box;
}
namespace
{
class MouseCursorViewObject
: public lay::ViewObject
{
public:
MouseCursorViewObject (lay::ViewObjectWidget *widget, const db::DPoint &pt)
: lay::ViewObject (widget, false), m_pt (pt)
{ }
virtual void render (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas)
{
int dither_pattern = 0; // solid
int lw = int (0.5 + 1.0 / canvas.resolution ());
std::vector <lay::ViewOp> ops;
ops.resize (1);
ops[0] = lay::ViewOp (canvas.foreground_color ().rgb (), lay::ViewOp::Copy, 0, (unsigned int) dither_pattern, 0, lay::ViewOp::Rect, lw, 0);
lay::CanvasPlane *plane = canvas.plane (ops);
lay::Renderer &r = canvas.renderer ();
double rad = 4.0 / canvas.resolution () / vp.trans ().mag ();
const size_t num_pts = 16;
db::DPoint pts [num_pts];
for (size_t i = 0; i < num_pts; ++i) {
double x = rad * cos (M_PI * 2.0 * double (i) / double (num_pts));
double y = rad * sin (M_PI * 2.0 * double (i) / double (num_pts));
pts [i] = m_pt + db::DVector (x, y);
}
db::DPolygon circle;
circle.assign_hull (pts, pts + num_pts);
r.draw (circle, vp.trans (), 0, plane, 0, 0);
r.draw (db::DEdge (m_pt + db::DVector (0, rad * 0.5), m_pt + db::DVector (0, rad * 4)), vp.trans (), 0, plane, 0, 0);
r.draw (db::DEdge (m_pt + db::DVector (rad * 0.5, 0), m_pt + db::DVector (rad * 4, 0)), vp.trans (), 0, plane, 0, 0);
r.draw (db::DEdge (m_pt + db::DVector (0, -rad * 0.5), m_pt + db::DVector (0, -rad * 4)), vp.trans (), 0, plane, 0, 0);
r.draw (db::DEdge (m_pt + db::DVector (-rad * 0.5, 0), m_pt + db::DVector (-rad * 4, 0)), vp.trans (), 0, plane, 0, 0);
}
private:
db::DPoint m_pt;
};
}
void
Service::set_mouse_cursor (const db::DPoint &pt)
{
reset_mouse_cursor ();
m_mouse_cursor_markers.push_back (new MouseCursorViewObject (widget (), pt));
}
void
Service::reset_mouse_cursor ()
{
for (std::vector<lay::ViewObject *>::iterator r = m_mouse_cursor_markers.begin (); r != m_mouse_cursor_markers.end (); ++r) {
delete *r;
}
m_mouse_cursor_markers.clear ();
}
void
Service::set_edit_marker (lay::ViewObject *edit_marker)
{
@ -881,7 +813,7 @@ Service::activated ()
void
Service::deactivated ()
{
reset_mouse_cursor ();
clear_mouse_cursors ();
edit_cancel ();

View File

@ -27,9 +27,8 @@
#include "edtCommon.h"
#include "layEditable.h"
#include "layEditorServiceBase.h"
#include "layPlugin.h"
#include "layViewObject.h"
#include "layMarker.h"
#include "laySnap.h"
#include "layObjectInstPath.h"
@ -72,8 +71,7 @@ std::map<std::string, tl::Variant> pcell_parameters_from_string (const std::stri
// -------------------------------------------------------------
class EDT_PUBLIC Service
: public lay::ViewService,
public lay::Editable,
: public lay::EditorServiceBase,
public lay::Plugin,
public db::Object
{
@ -458,16 +456,6 @@ protected:
*/
virtual void service_configuration_changed ();
/**
* @brief Sets the mouse cursor to the given point
*/
void set_mouse_cursor (const db::DPoint &pt);
/**
* @brief Resets the mouse cursor
*/
void reset_mouse_cursor ();
/**
* @brief Install a marker for representing the edited object
*
@ -578,9 +566,6 @@ private:
// The marker representing the object to be edited
std::vector<lay::ViewObject *> m_edit_markers;
// The marker representing the mouse cursor
std::vector<lay::ViewObject *> m_mouse_cursor_markers;
// True, if editing is in progress.
bool m_editing;

View File

@ -417,14 +417,23 @@ void
PolygonService::do_mouse_move_inactive (const db::DPoint &p)
{
lay::PointSnapToObjectResult snap_details = snap2_details (p);
set_mouse_cursor (snap_details.snapped_point);
clear_mouse_cursors ();
add_mouse_cursor (snap_details.snapped_point,
snap_details.object_snap == lay::PointSnapToObjectResult::ObjectVertex ||
(snap_details.object_snap == lay::PointSnapToObjectResult::ObjectUnspecific && snap_details.object_ref.is_degenerate ()));
if (snap_details.object_snap == lay::PointSnapToObjectResult::ObjectEdge ||
(snap_details.object_snap == lay::PointSnapToObjectResult::ObjectUnspecific && ! snap_details.object_ref.is_degenerate ())) {
add_edge_marker (snap_details.object_ref, false);
}
}
void
PolygonService::do_mouse_move (const db::DPoint &p)
{
lay::PointSnapToObjectResult snap_details = snap2_details (p);
set_mouse_cursor (snap_details.snapped_point);
do_mouse_move_inactive (p);
set_cursor (lay::Cursor::cross);
if (m_points.size () >= 2) {

View File

@ -0,0 +1,200 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 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 "layEditorServiceBase.h"
#include "layViewport.h"
#include "layLayoutView.h"
namespace lay
{
// --------------------------------------------------------------------------------------
template <size_t num_pts>
static void
make_circle (double r, const db::DPoint &center, db::DPolygon &poly, bool as_hole)
{
db::DPoint pts [num_pts];
for (size_t i = 0; i < num_pts; ++i) {
double x = r * cos (M_PI * 2.0 * double (i) / double (num_pts));
double y = r * sin (M_PI * 2.0 * double (i) / double (num_pts));
pts [i] = center + db::DVector (x, y);
}
if (! as_hole) {
poly.assign_hull (pts, pts + num_pts);
} else {
poly.insert_hole (pts, pts + num_pts);
}
}
class MouseCursorViewObject
: public lay::ViewObject
{
public:
MouseCursorViewObject (lay::ViewObjectWidget *widget, const db::DPoint &pt, bool solid)
: lay::ViewObject (widget, false), m_pt (pt), m_solid (solid)
{ }
virtual void render (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas)
{
int dither_pattern = 0; // solid
int cross_dither_pattern = 6; // dotted
int lw = int (0.5 + 1.0 / canvas.resolution ());
std::vector <lay::ViewOp> ops;
ops.resize (1);
ops[0] = lay::ViewOp (canvas.foreground_color ().rgb (), lay::ViewOp::Copy, 0, (unsigned int) dither_pattern, 0, lay::ViewOp::Rect, lw, 0);
lay::CanvasPlane *plane = canvas.plane (ops);
ops[0] = lay::ViewOp (canvas.foreground_color ().rgb (), lay::ViewOp::Copy, 0, (unsigned int) cross_dither_pattern, 0, lay::ViewOp::Rect, lw, 0);
lay::CanvasPlane *cross_plane = canvas.plane (ops);
lay::Renderer &r = canvas.renderer ();
double rad = 4.0 / canvas.resolution () / vp.trans ().mag ();
db::DPolygon c;
if (! m_solid) {
make_circle<size_t (16)> (rad, m_pt, c, false);
r.draw (c, vp.trans (), 0, plane, 0, 0);
} else {
make_circle<size_t (16)> (rad * 2, m_pt, c, false);
r.draw (c, vp.trans (), 0, plane, 0, 0);
make_circle<size_t (16)> (rad, m_pt, c, false);
r.draw (c, vp.trans (), 0, plane, 0, 0);
}
r.draw (db::DEdge (m_pt + db::DVector (0, -rad * 4), m_pt + db::DVector (0, rad * 4)), vp.trans (), 0, cross_plane, 0, 0);
r.draw (db::DEdge (m_pt + db::DVector (-rad * 4, 0), m_pt + db::DVector (rad * 4, 0)), vp.trans (), 0, cross_plane, 0, 0);
}
private:
db::DPoint m_pt;
bool m_solid;
};
class EdgeMarkerViewObject
: public lay::ViewObject
{
public:
EdgeMarkerViewObject (lay::ViewObjectWidget *widget, const db::DEdge &edge, bool solid)
: lay::ViewObject (widget, false), m_edge (edge), m_solid (solid)
{ }
virtual void render (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas)
{
if (m_edge.is_degenerate ()) {
return;
}
int dashed_style = 2;
int solid_style = 0;
int lw = int (0.5 + 1.0 / canvas.resolution ());
std::vector <lay::ViewOp> ops;
ops.resize (1);
ops[0] = lay::ViewOp (canvas.foreground_color ().rgb (), lay::ViewOp::Copy, solid_style, 0, 0, lay::ViewOp::Rect, lw, 0);
lay::CanvasPlane *arrow_plane = canvas.plane (ops);
ops[0] = lay::ViewOp (canvas.foreground_color ().rgb (), lay::ViewOp::Copy, m_solid ? solid_style : dashed_style, 1, 0, lay::ViewOp::Rect, lw, 0);
lay::CanvasPlane *edge_plane = canvas.plane (ops);
lay::Renderer &r = canvas.renderer ();
r.draw (m_edge, vp.trans (), 0, edge_plane, 0, 0);
double arrow_length = 12.0 / canvas.resolution () / vp.trans ().mag ();
double arrow_width_half = arrow_length * 0.25882; // sin(15 deg)
db::DVector n = db::DVector (m_edge.dy (), -m_edge.dx ()) * (arrow_width_half / m_edge.length ());
db::DVector d = db::DVector (m_edge.dx (), m_edge.dy ()) * (arrow_length / m_edge.length ());
if (m_edge.length () < 2 * arrow_length) {
r.draw (db::DEdge (m_edge.p1 () - n, m_edge.p1 () + n), vp.trans (), 0, arrow_plane, 0, 0);
r.draw (db::DEdge (m_edge.p2 () - n, m_edge.p2 () + n), vp.trans (), 0, arrow_plane, 0, 0);
} else {
db::DPoint pts[3];
db::DPolygon p;
pts[0] = m_edge.p1 ();
pts[1] = m_edge.p1 () + d - n;
pts[2] = m_edge.p1 () + d + n;
p.assign_hull (pts, pts + 3);
r.draw (p, vp.trans (), 0, arrow_plane, 0, 0);
pts[0] = m_edge.p2 ();
pts[1] = m_edge.p2 () - d + n;
pts[2] = m_edge.p2 () - d - n;
p.assign_hull (pts, pts + 3);
r.draw (p, vp.trans (), 0, arrow_plane, 0, 0);
}
}
private:
db::DEdge m_edge;
bool m_solid;
};
// --------------------------------------------------------------------------------------
EditorServiceBase::EditorServiceBase (lay::LayoutView *view)
: lay::ViewService (view->view_object_widget ()),
lay::Editable (view)
{
// .. nothing yet ..
}
EditorServiceBase::~EditorServiceBase ()
{
clear_mouse_cursors ();
}
void
EditorServiceBase::add_mouse_cursor (const db::DPoint &pt, bool emphasize)
{
m_mouse_cursor_markers.push_back (new MouseCursorViewObject (widget (), pt, emphasize));
}
void
EditorServiceBase::add_edge_marker (const db::DEdge &e, bool emphasize)
{
m_mouse_cursor_markers.push_back (new EdgeMarkerViewObject (widget (), e, emphasize));
}
void
EditorServiceBase::clear_mouse_cursors ()
{
for (std::vector<lay::ViewObject *>::iterator r = m_mouse_cursor_markers.begin (); r != m_mouse_cursor_markers.end (); ++r) {
delete *r;
}
m_mouse_cursor_markers.clear ();
}
}

View File

@ -0,0 +1,77 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 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_layEditorServiceBase
#define HDR_layEditorServiceBase
#include "laybasicCommon.h"
#include "layEditable.h"
#include "layViewObject.h"
namespace lay
{
/**
* @brief A generic base class for an editor service
*
* This class offers common services such as a mouse cursor.
*/
class LAYBASIC_PUBLIC EditorServiceBase
: public lay::ViewService,
public lay::Editable
{
public:
/**
* @brief Constructor
*/
EditorServiceBase (lay::LayoutView *view);
/**
* @brief Destructor
*/
~EditorServiceBase ();
/**
* @brief Adds a mouse cursor to the given point
*/
void add_mouse_cursor (const db::DPoint &pt, bool emphasize = false);
/**
* @brief Adds an edge marker for the given edge
*/
void add_edge_marker (const db::DEdge &e, bool emphasize);
/**
* @brief Resets the mouse cursor
*/
void clear_mouse_cursors ();
private:
// The marker representing the mouse cursor
std::vector<lay::ViewObject *> m_mouse_cursor_markers;
};
}
#endif

View File

@ -118,6 +118,7 @@ SOURCES = \
layEditorOptionsFrame.cc \
layEditorOptionsPage.cc \
layEditorOptionsPages.cc \
layEditorServiceBase.cc \
layFileDialog.cc \
layFinder.cc \
layFixedFont.cc \
@ -222,6 +223,7 @@ HEADERS = \
layEditorOptionsFrame.h \
layEditorOptionsPage.h \
layEditorOptionsPages.h \
layEditorServiceBase.h \
layFileDialog.h \
layFinder.h \
layFixedFont.h \