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 "cmddeviceinstanceedit.h"
24 
25 #include "../items/bi_device.h"
26 
27 #include <QtCore>
28 
29 /*******************************************************************************
30  *  Namespace
31  ******************************************************************************/
32 namespace librepcb {
33 namespace project {
34 
35 /*******************************************************************************
36  *  Constructors / Destructor
37  ******************************************************************************/
38 
CmdDeviceInstanceEdit(BI_Device & dev)39 CmdDeviceInstanceEdit::CmdDeviceInstanceEdit(BI_Device& dev) noexcept
40   : UndoCommand(tr("Edit device instance")),
41     mDevice(dev),
42     mOldPos(mDevice.getPosition()),
43     mNewPos(mOldPos),
44     mOldRotation(mDevice.getRotation()),
45     mNewRotation(mOldRotation),
46     mOldMirrored(mDevice.getIsMirrored()),
47     mNewMirrored(mOldMirrored) {
48 }
49 
~CmdDeviceInstanceEdit()50 CmdDeviceInstanceEdit::~CmdDeviceInstanceEdit() noexcept {
51   if (!wasEverExecuted()) {
52     try {
53       mDevice.setPosition(mOldPos);
54       mDevice.setRotation(mOldRotation);
55       mDevice.setIsMirrored(mOldMirrored);  // can throw
56     } catch (Exception& e) {
57       qCritical() << "Could not revert all changes:" << e.getMsg();
58     }
59   }
60 }
61 
62 /*******************************************************************************
63  *  General Methods
64  ******************************************************************************/
65 
setPosition(const Point & pos,bool immediate)66 void CmdDeviceInstanceEdit::setPosition(const Point& pos,
67                                         bool immediate) noexcept {
68   Q_ASSERT(!wasEverExecuted());
69   mNewPos = pos;
70   if (immediate) mDevice.setPosition(mNewPos);
71 }
72 
translate(const Point & deltaPos,bool immediate)73 void CmdDeviceInstanceEdit::translate(const Point& deltaPos,
74                                       bool immediate) noexcept {
75   Q_ASSERT(!wasEverExecuted());
76   mNewPos += deltaPos;
77   if (immediate) mDevice.setPosition(mNewPos);
78 }
79 
setRotation(const Angle & angle,bool immediate)80 void CmdDeviceInstanceEdit::setRotation(const Angle& angle,
81                                         bool immediate) noexcept {
82   Q_ASSERT(!wasEverExecuted());
83   mNewRotation = angle;
84   if (immediate) mDevice.setRotation(mNewRotation);
85 }
86 
rotate(const Angle & angle,const Point & center,bool immediate)87 void CmdDeviceInstanceEdit::rotate(const Angle& angle, const Point& center,
88                                    bool immediate) noexcept {
89   Q_ASSERT(!wasEverExecuted());
90   mNewPos.rotate(angle, center);
91   mNewRotation += mNewMirrored
92       ? -angle
93       : angle;  // mirror --> rotation direction is inverted!
94   if (immediate) {
95     mDevice.setPosition(mNewPos);
96     mDevice.setRotation(mNewRotation);
97   }
98 }
99 
setMirrored(bool mirrored,bool immediate)100 void CmdDeviceInstanceEdit::setMirrored(bool mirrored, bool immediate) {
101   Q_ASSERT(!wasEverExecuted());
102   if (immediate) {
103     mDevice.setIsMirrored(mirrored);  // can throw
104   }
105   mNewMirrored = mirrored;
106 }
107 
mirror(const Point & center,Qt::Orientation orientation,bool immediate)108 void CmdDeviceInstanceEdit::mirror(const Point& center,
109                                    Qt::Orientation orientation,
110                                    bool immediate) {
111   Q_ASSERT(!wasEverExecuted());
112   bool mirror = !mNewMirrored;
113   Point position = mNewPos;
114   Angle rotation = mNewRotation;
115   switch (orientation) {
116     case Qt::Vertical: {
117       position.setY(position.getY() +
118                     Length(2) * (center.getY() - position.getY()));
119       rotation += Angle::deg180();
120       break;
121     }
122     case Qt::Horizontal: {
123       position.setX(position.getX() +
124                     Length(2) * (center.getX() - position.getX()));
125       break;
126     }
127     default: {
128       qCritical() << "Invalid orientation:" << orientation;
129       break;
130     }
131   }
132   if (immediate) {
133     mDevice.setIsMirrored(mirror);  // can throw
134     mDevice.setPosition(position);
135     mDevice.setRotation(rotation);
136   }
137   mNewMirrored = mirror;
138   mNewPos = position;
139   mNewRotation = rotation;
140 }
141 
142 /*******************************************************************************
143  *  Inherited from UndoCommand
144  ******************************************************************************/
145 
performExecute()146 bool CmdDeviceInstanceEdit::performExecute() {
147   performRedo();  // can throw
148 
149   if (mNewPos != mOldPos) return true;
150   if (mNewRotation != mOldRotation) return true;
151   if (mNewMirrored != mOldMirrored) return true;
152   return false;
153 }
154 
performUndo()155 void CmdDeviceInstanceEdit::performUndo() {
156   mDevice.setIsMirrored(mOldMirrored);  // can throw
157   mDevice.setPosition(mOldPos);
158   mDevice.setRotation(mOldRotation);
159 }
160 
performRedo()161 void CmdDeviceInstanceEdit::performRedo() {
162   mDevice.setIsMirrored(mNewMirrored);  // can throw
163   mDevice.setPosition(mNewPos);
164   mDevice.setRotation(mNewRotation);
165 }
166 
167 /*******************************************************************************
168  *  End of File
169  ******************************************************************************/
170 
171 }  // namespace project
172 }  // namespace librepcb
173