1 /******************************************************************************************************
2  * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
5  ******************************************************************************************************/
6 
7 #include "DataKey.h"
8 #include "EngaugeAssert.h"
9 #include "EnumsToQt.h"
10 #include "GraphicsItemType.h"
11 #include "GuidelineAbstract.h"
12 #include "GuidelineAbstract.h"
13 #include "GuidelineFormat.h"
14 #include "Guidelines.h"
15 #include "GuidelineStateContext.h"
16 #include "Logger.h"
17 #include <QGraphicsLineItem>
18 #include <QGraphicsScene>
19 #include <QGraphicsSceneMouseEvent>
20 #include <QLineF>
21 #include <qmath.h>
22 #include <QMouseEvent>
23 #include <QPen>
24 #include <QTextStream>
25 #include <QWidget>
26 #include "Transformation.h"
27 #include "ZValues.h"
28 
GuidelineAbstract(QGraphicsScene & scene)29 GuidelineAbstract::GuidelineAbstract(QGraphicsScene &scene) :
30   m_scene (scene),
31   m_context (nullptr),
32   m_guidelineVisible (nullptr)
33 {
34 }
35 
~GuidelineAbstract()36 GuidelineAbstract::~GuidelineAbstract ()
37 {
38   delete m_context;
39 }
40 
bindGuidelineVisibleToInvisible(GuidelineAbstract * guidelineVisible)41 void GuidelineAbstract::bindGuidelineVisibleToInvisible (GuidelineAbstract *guidelineVisible)
42 {
43   LOG4CPP_INFO_S ((*mainCat)) << "GuidelineAbstract::bindGuidelineVisibleToInvisible";
44 
45   m_guidelineVisible = guidelineVisible;
46 
47   connect (this, SIGNAL (signalHandleMoved (QPointF)),
48            guidelineVisible, SLOT (slotHandleMoved (QPointF)));
49 }
50 
context()51 GuidelineStateContext *GuidelineAbstract::context ()
52 {
53   return m_context;
54 }
55 
context() const56 const GuidelineStateContext *GuidelineAbstract::context () const
57 {
58   return m_context;
59 }
60 
handleActiveChange(bool active)61 void GuidelineAbstract::handleActiveChange (bool active)
62 {
63   m_context->handleActiveChange (active);
64 }
65 
handleGuidelineMode(bool visible,bool locked)66 void GuidelineAbstract::handleGuidelineMode (bool visible,
67                                              bool locked)
68 {
69   m_context->handleGuidelineMode (visible,
70                                   locked);
71 }
72 
handleHoverEnterEvent()73 void GuidelineAbstract::handleHoverEnterEvent()
74 {
75   m_context->handleHoverEnterEvent ();
76 }
77 
handleHoverLeaveEvent()78 void GuidelineAbstract::handleHoverLeaveEvent()
79 {
80   m_context->handleHoverLeaveEvent ();
81 }
82 
handleMouseMoveEvent(const QPointF & posScene)83 void GuidelineAbstract::handleMouseMoveEvent (const QPointF &posScene)
84 {
85   LOG4CPP_INFO_S ((*mainCat)) << "GuidelineAbstract::handleMouseMoveEvent ("
86                               << posScene.x() << ", " << posScene.y() << ")";
87 
88   // Skip if there is no bound visible Guideline
89   if (m_guidelineVisible != nullptr) {
90 
91     emit signalHandleMoved (posScene);
92   }
93 }
94 
handleMousePressEvent(const QPointF & posScene)95 void GuidelineAbstract::handleMousePressEvent(const QPointF &posScene)
96 {
97   LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineAbstract::handleMousePressEvent";
98 
99   m_context->handleMousePress(posScene);
100 }
101 
handleMouseReleaseEvent(const QPointF & posScene)102 void GuidelineAbstract::handleMouseReleaseEvent (const QPointF &posScene)
103 {
104   LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineAbstract::handleMouseReleaseEvent";
105 
106   m_context->handleMouseRelease (posScene);
107 }
108 
sacrificeHandleAndVisibleGuidelines(const QPointF & posScene,GuidelineState guidelineStateForReplacement)109 void GuidelineAbstract::sacrificeHandleAndVisibleGuidelines (const QPointF &posScene,
110                                                              GuidelineState guidelineStateForReplacement)
111 {
112   LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineAbstract::sacrificeHandleAndVisibleGuidelines"
113                                << " keeping identifier=" << identifier().toLatin1().data()
114                                << " in " << stateName ().toLatin1().data();
115 
116   if (m_guidelineVisible != nullptr) {
117 
118     // If scene position is off-screen then user is removing the visible Guideline
119     bool offscreen = !m_scene.sceneRect().contains (posScene);
120 
121     // Remove transient Guideline, which was never registered with Guidelines
122     LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineAbstract::sacrificeHandleAndVisibleGuidelines identifierDeleting="
123                                  << m_guidelineVisible->identifier().toLatin1().data();
124     disconnect (this, SIGNAL (signalHandleMoved (QPointF)),
125                 m_guidelineVisible, SLOT (slotHandleMoved (QPointF)));
126     m_guidelineVisible->removeFromScene (&m_scene);
127     delete m_guidelineVisible;
128     m_guidelineVisible = nullptr;
129 
130     // Update Guideline value from cursor position
131     double value = context()->convertScreenPointToGraphCoordinate (posScene);
132 
133     emit signalGuidelineDragged(identifier (),
134                                 value,
135                                 offscreen,
136                                 guidelineStateForReplacement);
137   }
138 }
139 
scene()140 QGraphicsScene &GuidelineAbstract::scene ()
141 {
142   return m_scene;
143 }
144 
posCursorGraph() const145 QPointF GuidelineAbstract::posCursorGraph () const
146 {
147   return m_context->posCursorGraph ();
148 }
149 
setContext(GuidelineStateContext * context)150 void GuidelineAbstract::setContext (GuidelineStateContext *context)
151 {
152   m_context = context;
153 }
154 
slotHandleMoved(QPointF posScreen)155 void GuidelineAbstract::slotHandleMoved (QPointF posScreen)
156 {
157   // Update geometry
158   updateGeometry (posScreen);
159 }
160 
stateDump() const161 QString GuidelineAbstract::stateDump () const
162 {
163   // This is used by Guidelines::stateDump and GuidelineStateContext::stateDump
164   QString out;
165   QTextStream str (&out);
166 
167   str << " " << m_context->stateName ();
168   str << " (";
169   str << (getGraphicsItemSelected() ? "selected" : "unselected") << " ";
170   str << (getGraphicsItemAcceptHover() ? "hoverable" : "unhoverable") << " ";
171   str << ((graphicsItemFlags () & QGraphicsItem::ItemIsFocusable ) != 0 ? "focusable"  : "unfocusable") << " ";
172   str << ((graphicsItemFlags () & QGraphicsItem::ItemIsMovable   ) != 0 ? "movable"    : "unmovable") << " ";
173   str << ((graphicsItemFlags () & QGraphicsItem::ItemIsSelectable) != 0 ? "selectable" : "unselectable") << " ";
174   str << ")";
175 
176   return out;
177 }
178 
stateName() const179 QString GuidelineAbstract::stateName () const
180 {
181   return m_context->stateName ();
182 }
183 
updateWithLatestTransformation()184 void GuidelineAbstract::updateWithLatestTransformation ()
185 {
186   m_context->updateWithLatestTransformation ();
187 }
188