1 /* This file is part of the KDE project
2  * Copyright (C) 2006 Jan Hambrecht <jaham@gmx.net>
3  * Copyright (C) 2006,2007 Thorsten Zachmann <zachmann@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "KoPathControlPointMoveCommand.h"
22 #include <klocalizedstring.h>
23 #include <math.h>
24 
KoPathControlPointMoveCommand(const KoPathPointData & pointData,const QPointF & offset,KoPathPoint::PointType pointType,KUndo2Command * parent)25 KoPathControlPointMoveCommand::KoPathControlPointMoveCommand(
26     const KoPathPointData &pointData,
27     const QPointF &offset,
28     KoPathPoint::PointType pointType,
29     KUndo2Command *parent)
30         : KUndo2Command(parent)
31         , m_pointData(pointData)
32         , m_pointType(pointType)
33 {
34     Q_ASSERT(offset.x() < 1e14 && offset.y() < 1e14);
35     KoPathShape * pathShape = m_pointData.pathShape;
36     KoPathPoint * point = pathShape->pointByIndex(m_pointData.pointIndex);
37     if (point) {
38         m_offset = point->parent()->documentToShape(offset) - point->parent()->documentToShape(QPointF(0, 0));
39     }
40 
41     setText(kundo2_i18n("Move control point"));
42 }
43 
redo()44 void KoPathControlPointMoveCommand::redo()
45 {
46     KUndo2Command::redo();
47     KoPathShape * pathShape = m_pointData.pathShape;
48     KoPathPoint * point = pathShape->pointByIndex(m_pointData.pointIndex);
49     if (point) {
50         pathShape->update();
51 
52         if (m_pointType == KoPathPoint::ControlPoint1) {
53             point->setControlPoint1(point->controlPoint1() + m_offset);
54             if (point->properties() & KoPathPoint::IsSymmetric) {
55                 // set the other control point so that it lies on the line between the moved
56                 // control point and the point, with the same distance to the point as the moved point
57                 point->setControlPoint2(2.0 * point->point() - point->controlPoint1());
58             } else if (point->properties() & KoPathPoint::IsSmooth) {
59                 // move the other control point so that it lies on the line through point and control point
60                 // keeping its distance to the point
61                 QPointF direction = point->point() - point->controlPoint1();
62                 direction /= sqrt(direction.x() * direction.x() + direction.y() * direction.y());
63                 QPointF distance = point->point() - point->controlPoint2();
64                 qreal length = sqrt(distance.x() * distance.x() + distance.y() * distance.y());
65                 point->setControlPoint2(point->point() + length * direction);
66             }
67         } else if (m_pointType == KoPathPoint::ControlPoint2) {
68             point->setControlPoint2(point->controlPoint2() + m_offset);
69             if (point->properties() & KoPathPoint::IsSymmetric) {
70                 // set the other control point so that it lies on the line between the moved
71                 // control point and the point, with the same distance to the point as the moved point
72                 point->setControlPoint1(2.0 * point->point() - point->controlPoint2());
73             } else if (point->properties() & KoPathPoint::IsSmooth) {
74                 // move the other control point so that it lies on the line through point and control point
75                 // keeping its distance to the point
76                 QPointF direction = point->point() - point->controlPoint2();
77                 direction /= sqrt(direction.x() * direction.x() + direction.y() * direction.y());
78                 QPointF distance = point->point() - point->controlPoint1();
79                 qreal length = sqrt(distance.x() * distance.x() + distance.y() * distance.y());
80                 point->setControlPoint1(point->point() + length * direction);
81             }
82         }
83 
84         pathShape->normalize();
85         pathShape->update();
86     }
87 }
88 
undo()89 void KoPathControlPointMoveCommand::undo()
90 {
91     KUndo2Command::undo();
92     m_offset *= -1.0;
93     redo();
94     m_offset *= -1.0;
95 }
96 
97