Transient mode for auto-measure ruler

This commit is contained in:
Matthias Koefferlein 2024-01-28 18:25:02 +01:00
parent 4b7c117cfd
commit 9184bef6f8
6 changed files with 200 additions and 49 deletions

View File

@ -1056,8 +1056,18 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
m_drawing (false), m_current (),
m_move_mode (MoveNone),
m_seg_index (0),
m_current_template (0)
{
m_current_template (0),
m_hover (false),
m_hover_wait (false),
m_hover_buttons (0),
m_mouse_in_window (false)
{
#if defined(HAVE_QT)
m_timer.setInterval (100 /*hover time*/);
m_timer.setSingleShot (true);
connect (&m_timer, SIGNAL (timeout ()), this, SLOT (timeout ()));
#endif
mp_view->annotations_changed_event.add (this, &Service::annotations_changed);
}
@ -1809,9 +1819,36 @@ Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int button
return false;
}
lay::TwoPointSnapToObjectResult
Service::auto_measure (const db::DPoint &p, lay::angle_constraint_type ac, const ant::Template &tpl)
{
// for auto-metric we need some cutline constraint - any or global won't do.
if (ac == lay::AC_Global) {
ac = tpl.angle_constraint ();
}
if (ac == lay::AC_Global) {
ac = m_snap_mode;
}
if (ac == lay::AC_Global) {
ac = lay::AC_Diagonal;
}
db::DVector g;
if (m_grid_snap) {
g = db::DVector (m_grid, m_grid);
}
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (m_snap_range);
snap_range *= 0.5;
return lay::obj_snap2 (mp_view, p, g, ac, snap_range, snap_range * 1000.0);
}
bool
Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
hover_reset ();
if (prio && (buttons & lay::LeftButton) != 0) {
const ant::Template &tpl = current_template ();
@ -1852,27 +1889,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
} else if (tpl.mode () == ant::Template::RulerAutoMetric) {
// for auto-metric we need some cutline constraint - any or global won't do.
lay::angle_constraint_type ac = ac_from_buttons (buttons);
if (ac == lay::AC_Global) {
ac = tpl.angle_constraint ();
}
if (ac == lay::AC_Global) {
ac = m_snap_mode;
}
if (ac == lay::AC_Global) {
ac = lay::AC_Diagonal;
}
db::DVector g;
if (m_grid_snap) {
g = db::DVector (m_grid, m_grid);
}
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (m_snap_range);
snap_range *= 0.5;
lay::TwoPointSnapToObjectResult ee = lay::obj_snap2 (mp_view, p, g, ac, snap_range, snap_range * 1000.0);
lay::TwoPointSnapToObjectResult ee = auto_measure (p, ac_from_buttons (buttons), tpl);
if (ee.any) {
// begin the transaction
@ -1968,21 +1985,33 @@ Service::create_measure_ruler (const db::DPoint &pt, lay::angle_constraint_type
bool
Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
if (prio) {
if (! prio) {
return false;
}
lay::PointSnapToObjectResult snap_details;
if (m_drawing) {
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons));
} else {
const ant::Template &tpl = current_template ();
snap_details = snap1_details (p, m_obj_snap && tpl.snap ());
}
if (! m_drawing && m_mouse_in_window && view ()->transient_selection_mode ()) {
mouse_cursor_from_snap_details (snap_details);
// Restart hover timer
m_hover_wait = true;
#if defined(HAVE_QT)
m_timer.start ();
#endif
m_hover_point = p;
m_hover_buttons = buttons;
}
if (m_drawing && prio) {
lay::PointSnapToObjectResult snap_details;
if (m_drawing) {
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons));
} else {
const ant::Template &tpl = current_template ();
snap_details = snap1_details (p, m_obj_snap && tpl.snap ());
}
mouse_cursor_from_snap_details (snap_details);
if (m_drawing) {
set_cursor (lay::Cursor::cross);
@ -2284,6 +2313,70 @@ Service::click_proximity (const db::DPoint &pos, lay::Editable::SelectionMode mo
}
}
bool
Service::enter_event (bool /*prio*/)
{
m_mouse_in_window = true;
return false;
}
bool
Service::leave_event (bool)
{
m_mouse_in_window = false;
hover_reset ();
return false;
}
void
Service::hover_reset ()
{
if (m_hover_wait) {
#if defined(HAVE_QT)
m_timer.stop ();
#endif
m_hover_wait = false;
}
if (m_hover) {
// as we use the transient selection for the hover ruler, we have to remove it here
clear_transient_selection ();
m_hover = false;
}
}
#if defined(HAVE_QT)
void
Service::timeout ()
{
m_hover_wait = false;
m_hover = true;
// as we use the transient selection for the hover ruler, we have to remove it here
clear_transient_selection ();
// transiently create an auto-metric ruler if requested
const ant::Template &tpl = current_template ();
if (tpl.mode () == ant::Template::RulerAutoMetric) {
lay::TwoPointSnapToObjectResult ee = auto_measure (m_hover_point, ac_from_buttons (m_hover_buttons), tpl);
if (ee.any) {
m_current = ant::Object (ee.first, ee.second, 0, tpl);
// HINT: there is no special style for "transient selection on rulers"
mp_transient_ruler = new ant::View (this, &m_current, true /*not selected*/);
if (! editables ()->has_selection ()) {
display_status (true);
}
}
}
}
#endif
bool
Service::transient_select (const db::DPoint &pos)
{

View File

@ -39,6 +39,11 @@
#include <map>
#include <vector>
#if defined (HAVE_QT)
# include <QTimer>
# include <QObject>
#endif
namespace ant {
class LayoutViewBase;
@ -177,12 +182,19 @@ private:
// -------------------------------------------------------------
class ANT_PUBLIC Service
: public lay::EditorServiceBase,
class ANT_PUBLIC Service :
#if defined (HAVE_QT)
public QObject,
#endif
public lay::EditorServiceBase,
public lay::Drawing,
public db::Object
{
public:
#if defined (HAVE_QT)
Q_OBJECT
#endif
public:
typedef lay::AnnotationShapes::iterator obj_iterator;
/**
@ -341,6 +353,21 @@ public:
*/
virtual db::DBox selection_bbox ();
/**
* @brief Implementation of the editables API
*/
virtual bool enter_event (bool);
/**
* @brief Implementation of the editables API
*/
virtual bool leave_event (bool);
/**
* @brief Implementation of the editables API
*/
virtual void hover_reset ();
/**
* @brief Transform the selection (reimplementation of lay::Editable interface)
*/
@ -506,6 +533,11 @@ public:
*/
tl::Event annotation_selection_changed_event;
#if defined (HAVE_QT)
public slots:
void timeout ();
#endif
private:
// Ruler display and snapping configuration
tl::Color m_color;
@ -551,10 +583,22 @@ private:
std::vector<ant::Template> m_ruler_templates;
unsigned int m_current_template;
// Hover detector
bool m_hover;
bool m_hover_wait;
db::DPoint m_hover_point;
unsigned int m_hover_buttons;
#if defined (HAVE_QT)
QTimer m_timer;
#endif
bool m_mouse_in_window;
std::pair<bool, db::DPoint> snap1 (const db::DPoint &p, bool obj_snap);
lay::PointSnapToObjectResult snap1_details (const db::DPoint &p, bool obj_snap);
std::pair<bool, db::DPoint> snap2 (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
lay::TwoPointSnapToObjectResult auto_measure (const db::DPoint &p, lay::angle_constraint_type ac, const ant::Template &tpl);
const ant::Template &current_template () const;

View File

@ -305,10 +305,7 @@ MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_
if (mp_editables->begin_move (p, ac_from_buttons (buttons))) {
lay::SelectionService *selector = mp_view->selection_service ();
if (selector) {
selector->hover_reset ();
}
ui ()->hover_reset ();
mp_view->clear_transient_selection ();

View File

@ -69,14 +69,7 @@ public:
virtual bool mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual bool mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
virtual bool wheel_event (int delta, bool horizontal, const db::DPoint &p, unsigned int buttons, bool prio);
/**
* @brief Reset the hover timer for the transient selection
*
* This method may be used by other services (in particular Move) to avoid the transient to
* be triggered from a move operation.
*/
void hover_reset ();
virtual void hover_reset ();
#if defined (HAVE_QT)
public slots:

View File

@ -1051,7 +1051,15 @@ ViewObjectUI::drag_cancel ()
}
}
namespace
void
ViewObjectUI::hover_reset ()
{
for (service_iterator svc = begin_services (); svc != end_services (); ++svc) {
(*svc)->hover_reset ();
}
}
namespace
{
struct z_order_compare_f
{

View File

@ -147,6 +147,17 @@ public:
virtual bool drop_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
#endif
/**
* @brief Hover reset request
*
* This event is issued for services providing some "hover" mode - i.e. capture
* mouse move events and start a timer on them.
*
* The implementation of this event should cancel this timer and
* not raise a hover condition.
*/
virtual void hover_reset () { }
/**
* @brief Mouse press event handler
*
@ -605,6 +616,11 @@ public:
*/
void drag_cancel ();
/**
* @brief Calls hover_reset on all services
*/
void hover_reset ();
/**
* @brief CanvasPlane rendering
*