Engauge Digitizer 2
Loading...
Searching...
No Matches
Guidelines.cpp
Go to the documentation of this file.
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 "CmdMediator.h"
8#include "Document.h"
10#include "EngaugeAssert.h"
11#include "GraphicsScene.h"
12#include "GuidelineAbstract.h"
13#include "GuidelineEllipse.h"
14#include "GuidelineFactory.h"
15#include "GuidelineLine.h"
16#include "Guidelines.h"
17#include "GuidelineState.h"
18#include "Logger.h"
19#include "MainWindow.h"
20#include "MainWindowModel.h"
21#include <QGraphicsItem>
22#include <QGraphicsScene>
23#include <QMap>
24#include <qmath.h>
25#include <QTextStream>
26
28 m_mainWindow (mainWindow),
29 m_guidelineFactory (nullptr)
30{
31}
32
34{
35 clear ();
36 delete m_guidelineFactory;
37}
38
40{
41 GuidelineContainerPrivate::iterator itr;
42
43 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
44 GuidelineAbstract *guideline = *itr;
45
46 // Remove the guideline from its scene
47 QGraphicsScene *scene = &guideline->scene();
48
49 if (scene != nullptr) {
50
51 guideline->removeFromScene (scene);
52
53 }
54 }
55
56 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
57 GuidelineAbstract *guideline = *itr;
58
59 // Remove the guideline from its scene
60 QGraphicsScene *scene = &guideline->scene();
61
62 if (scene != nullptr) {
63
64 guideline->removeFromScene (scene);
65
66 }
67 }
68
69 m_guidelineContainerXT.clear ();
70 m_guidelineContainerYR.clear ();
71}
72
74{
75 return m_mainWindow.cmdMediator()->document().modelGuideline ().lineColor();
76}
77
79{
80 return m_mainWindow.cmdMediator()->document().modelCoords().coordsType();
81}
82
84 GuidelineState stateInitial)
85{
86 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::createGuideline"
87 << " identifier=" << identifier.toLatin1().data()
88 << " state=" << guidelineStateAsString (stateInitial).toLatin1().data();
89
90 GuidelineAbstract *guideline = m_guidelineFactory->createGuideline (*this,
91 stateInitial,
92 m_mainWindow,
93 identifier);
94
95 return guideline;
96}
97
98void Guidelines::createGuidelineR (const QString &identifier,
99 double r)
100{
101 GuidelineAbstract *guideline = createGuideline (identifier,
103 if (guideline) {
104 guideline->updateGeometry (r);
105 }
106
107 m_guidelineContainerYR.append (guideline);
108}
109
110void Guidelines::createGuidelineR (const QString &identifier,
111 const QPointF &posScreen)
112{
113 GuidelineAbstract *guideline = createGuideline (identifier,
115 if (guideline) {
116 guideline->updateGeometry (posScreen);
117 }
118
119 m_guidelineContainerYR.append (guideline);
120}
121
122void Guidelines::createGuidelineT (const QString &identifier,
123 double t)
124{
125 GuidelineAbstract *guideline = createGuideline (identifier,
127 if (guideline) {
128 guideline->updateGeometry (t);
129 }
130
131 m_guidelineContainerXT.append (guideline);
132}
133
134void Guidelines::createGuidelineT (const QString &identifier,
135 const QPointF &posScreen)
136{
137 GuidelineAbstract *guideline = createGuideline (identifier,
139 if (guideline) {
140 guideline->updateGeometry (posScreen);
141 }
142
143 m_guidelineContainerXT.append (guideline);
144}
145
146void Guidelines::createGuidelineX (const QString &identifier,
147 double x)
148{
149 GuidelineAbstract *guideline = createGuideline (identifier,
151 if (guideline) {
152 guideline->updateGeometry (x);
153 }
154
155 m_guidelineContainerXT.append (guideline);
156}
157
158void Guidelines::createGuidelineX (const QString &identifier,
159 const QPointF &posScreen)
160{
161 GuidelineAbstract *guideline = createGuideline (identifier,
163 if (guideline) {
164 guideline->updateGeometry (posScreen);
165 }
166
167 m_guidelineContainerXT.append (guideline);
168}
169
170void Guidelines::createGuidelineY (const QString &identifier,
171 double y)
172{
173 GuidelineAbstract *guideline = createGuideline (identifier,
175 if (guideline) {
176 guideline->updateGeometry (y);
177 }
178
179 m_guidelineContainerYR.append (guideline);
180}
181
182void Guidelines::createGuidelineY (const QString &identifier,
183 const QPointF &posScreen)
184{
185 GuidelineAbstract *guideline = createGuideline (identifier,
187 if (guideline) {
188 guideline->updateGeometry (posScreen);
189 }
190
191 m_guidelineContainerYR.append (guideline);
192}
193
194void Guidelines::createReplacementGuideline (const QString &identifierReplaced,
195 double newValue,
196 GuidelineState guidelineStateForReplacement)
197{
198 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::createReplacementGuideline";
199
200 // Out with the old. Since it is still on the stack we only unregister, versus remove, it
201 unregisterGuideline (identifierReplaced);
202
203 // And in with the new
204 switch (guidelineStateForReplacement) {
206 createGuidelineR (identifierReplaced,
207 newValue);
208 break;
209
211 createGuidelineT(identifierReplaced,
212 newValue);
213 break;
214
216 createGuidelineX(identifierReplaced,
217 newValue);
218 break;
219
221 createGuidelineY(identifierReplaced,
222 newValue);
223 break;
224
225 default:
226 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::createReplacementGuideline encountered unexpected state "
227 << guidelineStateAsString (guidelineStateForReplacement).toLatin1().data();
228
229 }
230}
231
232GuidelineContainerPrivate::iterator Guidelines::findIdentifierXT (const QString &identifier)
233{
234 GuidelineContainerPrivate::iterator itr;
235
236 // Find the closest point
237 for (itr = m_guidelineContainerXT.begin (); itr != m_guidelineContainerXT.end (); itr++) {
238 GuidelineAbstract *guideline = *itr;
239 if (identifier == guideline->identifier()) {
240 return itr;
241 }
242 }
243
244 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::findIdentifierXT could not find " << identifier.toLatin1().data();
245
246 return m_guidelineContainerXT.end();
247}
248
249GuidelineContainerPrivate::iterator Guidelines::findIdentifierYR (const QString &identifier)
250{
251 GuidelineContainerPrivate::iterator itr;
252
253 // Find the closest point
254 for (itr = m_guidelineContainerYR.begin (); itr != m_guidelineContainerYR.end (); itr++) {
255 GuidelineAbstract *guideline = *itr;
256 if (identifier == guideline->identifier()) {
257 return itr;
258 }
259 }
260
261 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::findIdentifierYR could not find " << identifier.toLatin1().data();
262
263 return m_guidelineContainerYR.end(); // Return something
264}
265
266const GuidelineContainerPrivate &Guidelines::guidelineContainerPrivateXT () const
267{
268 return m_guidelineContainerXT;
269}
270
271const GuidelineContainerPrivate &Guidelines::guidelineContainerPrivateYR () const
272{
273 return m_guidelineContainerYR;
274}
275
277{
278 GuidelineContainerPrivate::iterator itr;
279
280 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
281 GuidelineAbstract *guideline = *itr;
282
283 guideline->handleActiveChange (active);
284 }
285
286 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
287 GuidelineAbstract *guideline = *itr;
288
289 guideline->handleActiveChange (active);
290 }
291}
292
294 bool isLocked)
295{
296 GuidelineContainerPrivate::iterator itr;
297
298 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
299 GuidelineAbstract *guideline = *itr;
300
301 guideline->handleGuidelineMode (visible,
302 isLocked);
303 }
304
305 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
306 GuidelineAbstract *guideline = *itr;
307
308 guideline->handleGuidelineMode (visible,
309 isLocked);
310 }
311}
312
314{
315 m_guidelineFactory = new GuidelineFactory (&scene);
316}
317
319{
320 GuidelineValues valuesXT, valuesYR;
321
322 GuidelineContainerPrivate::const_iterator itr;
323
324 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
325 const GuidelineAbstract *guideline = *itr;
326 QString identifier = guideline->identifier();
327 double value = guideline->posCursorGraph().x();
328 valuesXT [identifier] = value;
329 }
330
331 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
332 const GuidelineAbstract *guideline = *itr;
333 QString identifier = guideline->identifier();
334 double value = guideline->posCursorGraph().y();
335 valuesYR [identifier] = value;
336 }
337
338 // Returned model
339 DocumentModelGuideline modelGuidelineNew (modelGuidelineOld);
340 modelGuidelineNew.setValuesX (valuesXT);
341 modelGuidelineNew.setValuesY (valuesYR);
342
343 return modelGuidelineNew;
344}
345
346void Guidelines::moveGuidelineXT (const QString &identifier,
347 double valueAfter)
348{
349 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::moveGuidelineXT"
350 << " identifier=" << identifier.toLatin1().data()
351 << " value=" << valueAfter;
352
353 GuidelineContainerPrivate::iterator itr = findIdentifierXT (identifier);
354
355 if (itr== m_guidelineContainerXT.end ()) {
356 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::moveGuidelineXT";
357 } else {
358 // Move it
359 GuidelineAbstract *guideline = *itr;
360 guideline->updateGeometry (valueAfter);
361 }
362}
363
364void Guidelines::moveGuidelineYR (const QString &identifier,
365 double valueAfter)
366{
367 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::moveGuidelineYR"
368 << " identifier=" << identifier.toLatin1().data()
369 << " value=" << valueAfter;
370
371 GuidelineContainerPrivate::iterator itr = findIdentifierYR (identifier);
372
373 if (itr == m_guidelineContainerYR.end ()) {
374 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::moveGuidelineYR";
375 } else {
376 // Move it
377 GuidelineAbstract *guideline = *itr;
378 guideline->updateGeometry (valueAfter);
379 }
380}
381
382void Guidelines::registerGuidelineXT (GuidelineAbstract *guideline)
383{
384 m_guidelineContainerXT.push_back (guideline);
385}
386
387void Guidelines::registerGuidelineYR (GuidelineAbstract *guideline)
388{
389 m_guidelineContainerYR.push_back (guideline);
390}
391
392void Guidelines::removeGuideline (const QString &identifier)
393{
394 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::removeGuideline"
395 << " identifier=" << identifier.toLatin1().data();
396
397 GuidelineAbstract *guideline = unregisterGuideline (identifier);
398
399 if (guideline != nullptr) {
400 delete guideline;
401 }
402}
403
405 const DocumentModelGuideline &modelGuideline)
406{
407 clear ();
408
409 GuidelineValues valuesXT = modelGuideline.valuesX();
410 GuidelineValues valuesYR = modelGuideline.valuesY();
411
412 GuidelineValues::const_iterator itr;
413
414 for (itr = valuesXT.begin(); itr != valuesXT.end(); itr++) {
415 QString identifier = itr.key();
416 double value = itr.value();
417
419 createGuidelineX (identifier,
420 value);
421 } else {
422 createGuidelineT (identifier,
423 value);
424 }
425 }
426
427 for (itr = valuesYR.begin(); itr != valuesYR.end(); itr++) {
428 QString identifier = itr.key();
429 double value = itr.value();
430
432 createGuidelineY (identifier,
433 value);
434 } else {
435 createGuidelineR (identifier,
436 value);
437 }
438 }
439}
440
441QString Guidelines::stateDump () const
442{
443 // Sort the entries
444 QStringList sortedXT, sortedYR;
445 GuidelineContainerPrivate::const_iterator itrSort;
446
447 for (itrSort = m_guidelineContainerXT.begin(); itrSort != m_guidelineContainerXT.end(); itrSort++) {
448 GuidelineAbstract *guideline = *itrSort;
449 sortedXT << guideline->stateDump ();
450 }
451
452 for (itrSort = m_guidelineContainerYR.begin(); itrSort != m_guidelineContainerYR.end(); itrSort++) {
453 GuidelineAbstract *guideline = *itrSort;
454 sortedYR << guideline->stateDump ();
455 }
456
457 std::sort (sortedXT.begin(),
458 sortedXT.end());
459 std::sort (sortedYR.begin(),
460 sortedYR.end());
461
462 // Convert entries to output text
463 QString out;
464 QTextStream str (&out);
465
466 str << "Guidelines::stateDump:\n";
467
468 QStringList::const_iterator itrOut;
469
470 for (itrOut = sortedXT.begin(); itrOut != sortedXT.end(); itrOut++) {
471 QString entry = *itrOut;
472 str << " " << entry << "\n";
473 }
474
475 for (itrOut = sortedYR.begin(); itrOut != sortedYR.end(); itrOut++) {
476 QString entry = *itrOut;
477 str << " " << entry << "\n";
478 }
479
480 return out;
481}
482
484{
485 return m_mainWindow.transformation ();
486}
487
488GuidelineAbstract *Guidelines::unregisterGuideline (const QString &identifier)
489{
490 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::unregisterGuideline"
491 << " identifier=" << identifier.toLatin1().data();
492
493 // Try to unregister XT entry
494 GuidelineContainerPrivate::iterator itrXT = findIdentifierXT (identifier);
495 if (itrXT != m_guidelineContainerXT.end ()) {
496 m_guidelineContainerXT.erase (itrXT);
497
498 return *itrXT;
499 }
500
501 // Try to remove YR entry
502 GuidelineContainerPrivate::iterator itrYR = findIdentifierYR (identifier);
503 if (itrYR != m_guidelineContainerYR.end ()) {
504 m_guidelineContainerYR.erase (itrYR);
505
506 return *itrYR;
507 }
508
509 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::unregisterGuideline cannot find "
510 << identifier.toLatin1().data();
511 return nullptr;
512}
513
515{
516 GuidelineContainerPrivate::const_iterator itr;
517
518 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
519 GuidelineAbstract *guideline = *itr;
520 guideline->updateColor ();
521 }
522
523 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
524 GuidelineAbstract *guideline = *itr;
525 guideline->updateColor ();
526 }
527}
528
530{
531 GuidelineContainerPrivate::iterator itr;
532
533 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
534 GuidelineAbstract *guideline = *itr;
535 guideline->updateWithLatestTransformation ();
536 }
537
538 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
539 GuidelineAbstract *guideline = *itr;
540 guideline->updateWithLatestTransformation ();
541 }
542}
ColorPalette
CoordsType
Definition CoordsType.h:12
@ COORDS_TYPE_CARTESIAN
Definition CoordsType.h:13
QString guidelineStateAsString(GuidelineState state)
GuidelineState
Set of possible Guideline states. See class Guideline for more information.
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_X_SELECT_EDIT_APPEARING
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_T_SELECT_EDIT
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_Y_SELECT_EDIT_APPEARING
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_R_SELECT_EDIT_APPEARING
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_Y_SELECT_EDIT
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_R_SELECT_EDIT
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_T_SELECT_EDIT_APPEARING
@ GUIDELINE_STATE_DEPLOYED_CONSTANT_X_SELECT_EDIT
QMap< QString, double > GuidelineValues
QList< GuidelineAbstract * > GuidelineContainerPrivate
Definition Guidelines.h:24
log4cpp::Category * mainCat
Definition Logger.cpp:14
Model for managing the coordinate values corresponding Guidelines.
GuidelineValues valuesY() const
Get method for y/r values.
GuidelineValues valuesX() const
Get method for x/t values.
void setValuesY(const GuidelineValues &valuesY)
Set method for y/r values.
void setValuesX(const GuidelineValues &valuesX)
Set method for x/t values.
Add point and line handling to generic QGraphicsScene.
This class is a special case of the standard QGraphicsLineItem for guidelines, and serves as the base...
virtual QString identifier() const =0
Unique identifier from QGraphicsItem.
QGraphicsScene & scene()
GraphicsScene that owns this class.
QPointF posCursorGraph() const
Get position in graph coordinates.
virtual void updateGeometry(double valueGraph)=0
Update the geometry so it passes through the specified coordinate value in graph coordinates.
void updateWithLatestTransformation()
Update given Transformation in GuidelineStateContext. This is called after a command has been execute...
void handleGuidelineMode(bool visible, bool locked)
User toggled Guideline visibility and/or locked mode.
virtual void removeFromScene(QGraphicsScene *scene)=0
Make graphics item remove itself from the scene.
void handleActiveChange(bool active)
DigitizeState change so active status may (or may not) be toggled.
QString stateDump() const
Dump of state as a string for debugging only. Context like the QGraphicsItem flags is included.
virtual void updateColor()=0
Force a color update.
Factory for generating Guideline objects.
void setModelGuideline(CoordsType coordsType, const DocumentModelGuideline &modelGuideline)
Load Guidelines from Document.
void createGuidelineY(const QString &identifier, double y)
Factory method for creating a new GUIDELINE_STATE_DEPLOYED_CONSTANT_Y_ACTIVE.
void createGuidelineR(const QString &identifier, double r)
Factory method for creating a new GUIDELINE_STATE_DEPLOYED_CONSTANT_R_ACTIVE.
void createReplacementGuideline(const QString &identifierReplaced, double newValue, GuidelineState guidelineStateForReplacement)
Factory method for creating a new replacement Guideline, which replaces one handle and one visible Gu...
void clear()
Remove guidelines since the current Document is about to be closed.
CoordsType coordsType() const
Return cartesian or polar.
void createGuidelineT(const QString &identifier, double t)
Factory method for creating a new GUIDELINE_STATE_DEPLOYED_CONSTANT_T_ACTIVE.
GuidelineAbstract * createGuideline(const QString &identifier, GuidelineState stateInitial)
Factory method for creating a new Guideline.
void moveGuidelineYR(const QString &identifier, double valueAfter)
Move an Y/R guideline from one value to another. Closest value wins.
ColorPalette color() const
Color to be used for guidelines.
Transformation transformation() const
Return copy of transformation owned by MainWindow.
DocumentModelGuideline updateValues(const DocumentModelGuideline &modelGuidelineOld) const
Updates the guideline values for later storing in Document. Only the values are updated.
Guidelines(MainWindow &mainWindow)
Single constructor.
void handleGuidelineMode(bool visible, bool locked)
User toggled guideline mode.
void removeGuideline(const QString &identifier)
Remove an X/T or Y/R guideline.
void updateWithLatestTransformation()
Update transformation. This is called after a command has been executed.
void moveGuidelineXT(const QString &identifier, double valueAfter)
Move an X/T guideline from one value to another. Closest value wins.
void initialize(GraphicsScene &scene)
Initialize Guideline factory.
void createGuidelineX(const QString &identifier, double x)
Factory method for creating a new GUIDELINE_STATE_DEPLOYED_CONSTANT_X_ACTIVE.
void handleActiveChange(bool active)
DigitizeState change so active status may (or may not) be toggled.
QString stateDump() const
States listed as a string for debugging only.
void updateColor()
Force a color update.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition MainWindow.h:95
Affine transformation between screen and graph coordinates, based on digitized axis points.
#define LOG4CPP_DEBUG_S(logger)
Definition convenience.h:20
#define LOG4CPP_ERROR_S(logger)
Definition convenience.h:12