Loading files
ce705b508This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "cmddragselectedsymbolitems.h"
#include "../../cmd/cmdcircleedit.h"
#include "../../cmd/cmdimageedit.h"
#include "../../cmd/cmdpolygonedit.h"
#include "../../cmd/cmdtextedit.h"
#include "../../graphics/circlegraphicsitem.h"
#include "../../graphics/graphicsscene.h"
#include "../../graphics/imagegraphicsitem.h"
#include "../../graphics/polygongraphicsitem.h"
#include "../../graphics/textgraphicsitem.h"
#include "../cmd/cmdsymbolpinedit.h"
#include "../sym/symbolgraphicsitem.h"
#include "../sym/symbolpingraphicsitem.h"
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
CmdDragSelectedSymbolItems::CmdDragSelectedSymbolItems(
SymbolGraphicsItem& item, const PositiveLength& grid) noexcept
: UndoCommandGroup(tr("Drag Symbol Elements")),
mCenterPos(0, 0),
mDeltaPos(0, 0),
mDeltaRot(0),
mMirrored(false),
mSnappedToGrid(false),
mHasOffTheGridElements(false) {
int count = 0;
QList<std::shared_ptr<SymbolPinGraphicsItem>> pins = item.getSelectedPins();
foreach (const std::shared_ptr<SymbolPinGraphicsItem>& pin, pins) {
Q_ASSERT(pin);
mPinEditCmds.append(new CmdSymbolPinEdit(pin->getPtr()));
mCenterPos += pin->getObj().getPosition();
if (!pin->getObj().getPosition().isOnGrid(grid)) {
mHasOffTheGridElements = true;
}
++count;
}
QList<std::shared_ptr<CircleGraphicsItem>> circles =
item.getSelectedCircles();
foreach (const std::shared_ptr<CircleGraphicsItem>& circle, circles) {
Q_ASSERT(circle);
mCircleEditCmds.append(new CmdCircleEdit(circle->getObj()));
mCenterPos += circle->getObj().getCenter();
if (!circle->getObj().getCenter().isOnGrid(grid)) {
mHasOffTheGridElements = true;
}
++count;
}
QList<std::shared_ptr<PolygonGraphicsItem>> polygons =
item.getSelectedPolygons();
foreach (const std::shared_ptr<PolygonGraphicsItem>& polygon, polygons) {
Q_ASSERT(polygon);
mPolygonEditCmds.append(new CmdPolygonEdit(polygon->getObj()));
foreach (const Vertex& vertex, polygon->getObj().getPath().getVertices()) {
mCenterPos += vertex.getPos();
if (!vertex.getPos().isOnGrid(grid)) {
mHasOffTheGridElements = true;
}
++count;
}
}
QList<std::shared_ptr<TextGraphicsItem>> texts = item.getSelectedTexts();
foreach (const std::shared_ptr<TextGraphicsItem>& text, texts) {
Q_ASSERT(text);
mTextEditCmds.append(new CmdTextEdit(text->getObj()));
mCenterPos += text->getObj().getPosition();
if (!text->getObj().getPosition().isOnGrid(grid)) {
mHasOffTheGridElements = true;
}
++count;
}
QList<std::shared_ptr<ImageGraphicsItem>> images = item.getSelectedImages();
foreach (const std::shared_ptr<ImageGraphicsItem>& image, images) {
Q_ASSERT(image);
mImageEditCmds.append(new CmdImageEdit(*image->getObj()));
// As the image does not support mirroring, its origin will move when
// mirror is invoked. TO avoid drifting away, we its the center point here.
mCenterPos += image->getObj()->getCenter();
if (!image->getObj()->getPosition().isOnGrid(grid)) {
mHasOffTheGridElements = true;
}
++count;
}
// Note: If only 1 item is selected, use its exact position as center.
if (count > 1) {
mCenterPos /= count;
mCenterPos.mapToGrid(grid);
}
}
CmdDragSelectedSymbolItems::~CmdDragSelectedSymbolItems() noexcept {
deleteAllCommands();
}
/*******************************************************************************
* Getters
******************************************************************************/
int CmdDragSelectedSymbolItems::getSelectedItemsCount() const noexcept {
return mPinEditCmds.count() + mCircleEditCmds.count() +
mPolygonEditCmds.count() + mTextEditCmds.count() + mImageEditCmds.count();
}
/*******************************************************************************
* General Methods
******************************************************************************/
void CmdDragSelectedSymbolItems::snapToGrid(
const PositiveLength& grid) noexcept {
foreach (CmdSymbolPinEdit* cmd, mPinEditCmds) {
cmd->snapToGrid(grid, true);
}
foreach (CmdCircleEdit* cmd, mCircleEditCmds) {
cmd->snapToGrid(grid, true);
}
foreach (CmdPolygonEdit* cmd, mPolygonEditCmds) {
cmd->snapToGrid(grid, true);
}
foreach (CmdTextEdit* cmd, mTextEditCmds) {
cmd->snapToGrid(grid, true);
}
foreach (CmdImageEdit* cmd, mImageEditCmds) {
cmd->snapToGrid(grid, true);
}
mSnappedToGrid = true;
}
void CmdDragSelectedSymbolItems::setDeltaToStartPos(
const Point& delta) noexcept {
translate(delta - mDeltaPos);
}
void CmdDragSelectedSymbolItems::translate(const Point& deltaPos) noexcept {
if (!deltaPos.isOrigin()) {
foreach (CmdSymbolPinEdit* cmd, mPinEditCmds) {
cmd->translate(deltaPos, true);
}
foreach (CmdCircleEdit* cmd, mCircleEditCmds) {
cmd->translate(deltaPos, true);
}
foreach (CmdPolygonEdit* cmd, mPolygonEditCmds) {
cmd->translate(deltaPos, true);
}
foreach (CmdTextEdit* cmd, mTextEditCmds) {
cmd->translate(deltaPos, true);
}
foreach (CmdImageEdit* cmd, mImageEditCmds) {
cmd->translate(deltaPos, true);
}
mDeltaPos += deltaPos;
mCenterPos += deltaPos;
}
}
void CmdDragSelectedSymbolItems::rotate(const Angle& angle) noexcept {
foreach (CmdSymbolPinEdit* cmd, mPinEditCmds) {
cmd->rotate(angle, mCenterPos, true);
}
foreach (CmdCircleEdit* cmd, mCircleEditCmds) {
cmd->rotate(angle, mCenterPos, true);
}
foreach (CmdPolygonEdit* cmd, mPolygonEditCmds) {
cmd->rotate(angle, mCenterPos, true);
}
foreach (CmdTextEdit* cmd, mTextEditCmds) {
cmd->rotate(angle, mCenterPos, true);
}
foreach (CmdImageEdit* cmd, mImageEditCmds) {
cmd->rotate(angle, mCenterPos, true);
}
mDeltaRot += angle;
}
void CmdDragSelectedSymbolItems::mirror(Qt::Orientation orientation) noexcept {
foreach (CmdSymbolPinEdit* cmd, mPinEditCmds) {
cmd->mirror(orientation, mCenterPos, true);
}
foreach (CmdCircleEdit* cmd, mCircleEditCmds) {
cmd->mirrorGeometry(orientation, mCenterPos, true);
}
foreach (CmdPolygonEdit* cmd, mPolygonEditCmds) {
cmd->mirrorGeometry(orientation, mCenterPos, true);
}
foreach (CmdTextEdit* cmd, mTextEditCmds) {
cmd->mirror(orientation, mCenterPos, true);
}
foreach (CmdImageEdit* cmd, mImageEditCmds) {
cmd->mirror(orientation, mCenterPos, true);
}
mMirrored = !mMirrored;
}
/*******************************************************************************
* Inherited from UndoCommand
******************************************************************************/
bool CmdDragSelectedSymbolItems::performExecute() {
if (mDeltaPos.isOrigin() && (mDeltaRot == 0) && (!mMirrored) &&
(!mSnappedToGrid)) {
// no movement required --> discard all move commands
deleteAllCommands();
return false;
}
// move all child commands to parent class
while (mPinEditCmds.count() > 0) {
appendChild(mPinEditCmds.takeLast());
}
while (mCircleEditCmds.count() > 0) {
appendChild(mCircleEditCmds.takeLast());
}
while (mPolygonEditCmds.count() > 0) {
appendChild(mPolygonEditCmds.takeLast());
}
while (mTextEditCmds.count() > 0) {
appendChild(mTextEditCmds.takeLast());
}
while (mImageEditCmds.count() > 0) {
appendChild(mImageEditCmds.takeLast());
}
// execute all child commands
return UndoCommandGroup::performExecute(); // can throw
}
/*******************************************************************************
* Private Methods
******************************************************************************/
void CmdDragSelectedSymbolItems::deleteAllCommands() noexcept {
qDeleteAll(mPinEditCmds);
mPinEditCmds.clear();
qDeleteAll(mCircleEditCmds);
mCircleEditCmds.clear();
qDeleteAll(mPolygonEditCmds);
mPolygonEditCmds.clear();
qDeleteAll(mTextEditCmds);
mTextEditCmds.clear();
qDeleteAll(mImageEditCmds);
mImageEditCmds.clear();
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb