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.modelMainWindow().guidelineColor();
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 DocumentModelGuidelines model (valuesXT,
339 valuesYR);
340
341 return model;
342}
343
344void Guidelines::moveGuidelineXT (const QString &identifier,
345 double valueAfter)
346{
347 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::moveGuidelineXT"
348 << " identifier=" << identifier.toLatin1().data()
349 << " value=" << valueAfter;
350
351 GuidelineContainerPrivate::iterator itr = findIdentifierXT (identifier);
352
353 if (itr== m_guidelineContainerXT.end ()) {
354 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::moveGuidelineXT";
355 } else {
356 // Move it
357 GuidelineAbstract *guideline = *itr;
358 guideline->updateGeometry (valueAfter);
359 }
360}
361
362void Guidelines::moveGuidelineYR (const QString &identifier,
363 double valueAfter)
364{
365 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::moveGuidelineYR"
366 << " identifier=" << identifier.toLatin1().data()
367 << " value=" << valueAfter;
368
369 GuidelineContainerPrivate::iterator itr = findIdentifierYR (identifier);
370
371 if (itr == m_guidelineContainerYR.end ()) {
372 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::moveGuidelineYR";
373 } else {
374 // Move it
375 GuidelineAbstract *guideline = *itr;
376 guideline->updateGeometry (valueAfter);
377 }
378}
379
380void Guidelines::registerGuidelineXT (GuidelineAbstract *guideline)
381{
382 m_guidelineContainerXT.push_back (guideline);
383}
384
385void Guidelines::registerGuidelineYR (GuidelineAbstract *guideline)
386{
387 m_guidelineContainerYR.push_back (guideline);
388}
389
390void Guidelines::removeGuideline (const QString &identifier)
391{
392 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::removeGuideline"
393 << " identifier=" << identifier.toLatin1().data();
394
395 GuidelineAbstract *guideline = unregisterGuideline (identifier);
396
397 if (guideline != nullptr) {
398 delete guideline;
399 }
400}
401
404{
405 clear ();
406
407 GuidelineValues valuesXT = modelGuidelines.valuesX();
408 GuidelineValues valuesYR = modelGuidelines.valuesY();
409
410 GuidelineValues::const_iterator itr;
411
412 for (itr = valuesXT.begin(); itr != valuesXT.end(); itr++) {
413 QString identifier = itr.key();
414 double value = itr.value();
415
417 createGuidelineX (identifier,
418 value);
419 } else {
420 createGuidelineT (identifier,
421 value);
422 }
423 }
424
425 for (itr = valuesYR.begin(); itr != valuesYR.end(); itr++) {
426 QString identifier = itr.key();
427 double value = itr.value();
428
430 createGuidelineY (identifier,
431 value);
432 } else {
433 createGuidelineR (identifier,
434 value);
435 }
436 }
437}
438
439QString Guidelines::stateDump () const
440{
441 // Sort the entries
442 QStringList sortedXT, sortedYR;
443 GuidelineContainerPrivate::const_iterator itrSort;
444
445 for (itrSort = m_guidelineContainerXT.begin(); itrSort != m_guidelineContainerXT.end(); itrSort++) {
446 GuidelineAbstract *guideline = *itrSort;
447 sortedXT << guideline->stateDump ();
448 }
449
450 for (itrSort = m_guidelineContainerYR.begin(); itrSort != m_guidelineContainerYR.end(); itrSort++) {
451 GuidelineAbstract *guideline = *itrSort;
452 sortedYR << guideline->stateDump ();
453 }
454
455 std::sort (sortedXT.begin(),
456 sortedXT.end());
457 std::sort (sortedYR.begin(),
458 sortedYR.end());
459
460 // Convert entries to output text
461 QString out;
462 QTextStream str (&out);
463
464 str << "Guidelines::stateDump:\n";
465
466 QStringList::const_iterator itrOut;
467
468 for (itrOut = sortedXT.begin(); itrOut != sortedXT.end(); itrOut++) {
469 QString entry = *itrOut;
470 str << " " << entry << "\n";
471 }
472
473 for (itrOut = sortedYR.begin(); itrOut != sortedYR.end(); itrOut++) {
474 QString entry = *itrOut;
475 str << " " << entry << "\n";
476 }
477
478 return out;
479}
480
482{
483 return m_mainWindow.transformation ();
484}
485
486GuidelineAbstract *Guidelines::unregisterGuideline (const QString &identifier)
487{
488 LOG4CPP_DEBUG_S ((*mainCat)) << "Guidelines::unregisterGuideline"
489 << " identifier=" << identifier.toLatin1().data();
490
491 // Try to unregister XT entry
492 GuidelineContainerPrivate::iterator itrXT = findIdentifierXT (identifier);
493 if (itrXT != m_guidelineContainerXT.end ()) {
494 m_guidelineContainerXT.erase (itrXT);
495
496 return *itrXT;
497 }
498
499 // Try to remove YR entry
500 GuidelineContainerPrivate::iterator itrYR = findIdentifierYR (identifier);
501 if (itrYR != m_guidelineContainerYR.end ()) {
502 m_guidelineContainerYR.erase (itrYR);
503
504 return *itrYR;
505 }
506
507 LOG4CPP_ERROR_S ((*mainCat)) << "Guidelines::unregisterGuideline cannot find "
508 << identifier.toLatin1().data();
509 return nullptr;
510}
511
513{
514 GuidelineContainerPrivate::const_iterator itr;
515
516 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
517 GuidelineAbstract *guideline = *itr;
518 guideline->updateColor ();
519 }
520
521 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
522 GuidelineAbstract *guideline = *itr;
523 guideline->updateColor ();
524 }
525}
526
528{
529 GuidelineContainerPrivate::iterator itr;
530
531 for (itr = m_guidelineContainerXT.begin(); itr != m_guidelineContainerXT.end(); itr++) {
532 GuidelineAbstract *guideline = *itr;
533 guideline->updateWithLatestTransformation ();
534 }
535
536 for (itr = m_guidelineContainerYR.begin(); itr != m_guidelineContainerYR.end(); itr++) {
537 GuidelineAbstract *guideline = *itr;
538 guideline->updateWithLatestTransformation ();
539 }
540}
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.
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 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 setModelGuidelines(CoordsType coordsType, const DocumentModelGuidelines &modelGuidelines)
Load Guidelines from Document.
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.
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.
DocumentModelGuidelines modelGuidelines() const
Return complete set of guidelines information for Document.
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:96
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