1 /*
2  * LibrePCB - Professional EDA for everyone!
3  * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
4  * https://librepcb.org/
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /*******************************************************************************
21  *  Includes
22  ******************************************************************************/
23 #include "cmdsymbolinstanceedit.h"
24 
25 #include "../items/si_symbol.h"
26 
27 #include <QtCore>
28 
29 /*******************************************************************************
30  *  Namespace
31  ******************************************************************************/
32 namespace librepcb {
33 namespace project {
34 
35 /*******************************************************************************
36  *  Constructors / Destructor
37  ******************************************************************************/
38 
CmdSymbolInstanceEdit(SI_Symbol & symbol)39 CmdSymbolInstanceEdit::CmdSymbolInstanceEdit(SI_Symbol& symbol) noexcept
40   : UndoCommand(tr("Edit symbol instance")),
41     mSymbol(symbol),
42     mOldPos(symbol.getPosition()),
43     mNewPos(mOldPos),
44     mOldRotation(symbol.getRotation()),
45     mNewRotation(mOldRotation),
46     mOldMirrored(symbol.getMirrored()),
47     mNewMirrored(mOldMirrored) {
48 }
49 
~CmdSymbolInstanceEdit()50 CmdSymbolInstanceEdit::~CmdSymbolInstanceEdit() noexcept {
51   if (!wasEverExecuted()) {
52     mSymbol.setPosition(mOldPos);
53     mSymbol.setRotation(mOldRotation);
54     mSymbol.setMirrored(mOldMirrored);
55   }
56 }
57 
58 /*******************************************************************************
59  *  General Methods
60  ******************************************************************************/
61 
setPosition(const Point & pos,bool immediate)62 void CmdSymbolInstanceEdit::setPosition(const Point& pos,
63                                         bool immediate) noexcept {
64   Q_ASSERT(!wasEverExecuted());
65   mNewPos = pos;
66   if (immediate) mSymbol.setPosition(mNewPos);
67 }
68 
translate(const Point & deltaPos,bool immediate)69 void CmdSymbolInstanceEdit::translate(const Point& deltaPos,
70                                       bool immediate) noexcept {
71   Q_ASSERT(!wasEverExecuted());
72   mNewPos += deltaPos;
73   if (immediate) mSymbol.setPosition(mNewPos);
74 }
75 
setRotation(const Angle & angle,bool immediate)76 void CmdSymbolInstanceEdit::setRotation(const Angle& angle,
77                                         bool immediate) noexcept {
78   Q_ASSERT(!wasEverExecuted());
79   mNewRotation = angle;
80   if (immediate) mSymbol.setRotation(mNewRotation);
81 }
82 
rotate(const Angle & angle,const Point & center,bool immediate)83 void CmdSymbolInstanceEdit::rotate(const Angle& angle, const Point& center,
84                                    bool immediate) noexcept {
85   Q_ASSERT(!wasEverExecuted());
86   mNewPos.rotate(angle, center);
87   mNewRotation += mNewMirrored
88       ? -angle
89       : angle;  // mirror --> rotation direction is inverted!
90   if (immediate) {
91     mSymbol.setPosition(mNewPos);
92     mSymbol.setRotation(mNewRotation);
93   }
94 }
95 
setMirrored(bool mirrored,bool immediate)96 void CmdSymbolInstanceEdit::setMirrored(bool mirrored,
97                                         bool immediate) noexcept {
98   Q_ASSERT(!wasEverExecuted());
99   mNewMirrored = mirrored;
100   if (immediate) mSymbol.setMirrored(mNewMirrored);
101 }
102 
mirror(const Point & center,Qt::Orientation orientation,bool immediate)103 void CmdSymbolInstanceEdit::mirror(const Point& center,
104                                    Qt::Orientation orientation,
105                                    bool immediate) noexcept {
106   Q_ASSERT(!wasEverExecuted());
107   bool mirror = !mNewMirrored;
108   Point position = mNewPos;
109   Angle rotation = mNewRotation;
110   switch (orientation) {
111     case Qt::Vertical: {
112       position.setY(position.getY() +
113                     Length(2) * (center.getY() - position.getY()));
114       rotation += Angle::deg180();
115       break;
116     }
117     case Qt::Horizontal: {
118       position.setX(position.getX() +
119                     Length(2) * (center.getX() - position.getX()));
120       break;
121     }
122     default: {
123       qCritical() << "Invalid orientation:" << orientation;
124       break;
125     }
126   }
127   if (immediate) {
128     mSymbol.setPosition(position);
129     mSymbol.setRotation(rotation);
130     mSymbol.setMirrored(mirror);
131   }
132   mNewMirrored = mirror;
133   mNewPos = position;
134   mNewRotation = rotation;
135 }
136 
137 /*******************************************************************************
138  *  Inherited from UndoCommand
139  ******************************************************************************/
140 
performExecute()141 bool CmdSymbolInstanceEdit::performExecute() {
142   performRedo();  // can throw
143 
144   if (mNewPos != mOldPos) return true;
145   if (mNewRotation != mOldRotation) return true;
146   if (mNewMirrored != mOldMirrored) return true;
147   return false;
148 }
149 
performUndo()150 void CmdSymbolInstanceEdit::performUndo() {
151   mSymbol.setPosition(mOldPos);
152   mSymbol.setRotation(mOldRotation);
153   mSymbol.setMirrored(mOldMirrored);
154 }
155 
performRedo()156 void CmdSymbolInstanceEdit::performRedo() {
157   mSymbol.setPosition(mNewPos);
158   mSymbol.setRotation(mNewRotation);
159   mSymbol.setMirrored(mNewMirrored);
160 }
161 
162 /*******************************************************************************
163  *  End of File
164  ******************************************************************************/
165 
166 }  // namespace project
167 }  // namespace librepcb
168