libs/flake

KoShapeGroupCommand.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  * Copyright (C) 2006 Thomas Zander <zander@kde.org>
00003  * Copyright (C) 2006,2007 Jan Hambrecht <jaham@gmx.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "KoShapeGroupCommand.h"
00022 #include "KoShape.h"
00023 #include "KoShapeGroup.h"
00024 #include "KoShapeContainer.h"
00025 
00026 #include <klocale.h>
00027 
00028 KoShapeGroupCommand * KoShapeGroupCommand::createCommand(KoShapeGroup *container, QList<KoShape *> shapes, QUndoCommand *parent)
00029 {
00030     QList<KoShape*> orderedShapes(shapes);
00031     qSort(orderedShapes.begin(), orderedShapes.end(), KoShape::compareShapeZIndex);
00032     if (!orderedShapes.isEmpty()) {
00033         KoShape * top = orderedShapes.last();
00034         container->setParent(top->parent());
00035         container->setZIndex(top->zIndex());
00036     }
00037 
00038     return new KoShapeGroupCommand(container, orderedShapes, parent);
00039 }
00040 
00041 
00042 KoShapeGroupCommand::KoShapeGroupCommand(KoShapeContainer *container, QList<KoShape *> shapes, QList<bool> clipped,
00043         QUndoCommand *parent)
00044         : QUndoCommand(parent)
00045         , m_shapes(shapes)
00046         , m_clipped(clipped)
00047         , m_container(container)
00048 {
00049     Q_ASSERT(m_clipped.count() == m_shapes.count());
00050     init();
00051 }
00052 
00053 KoShapeGroupCommand::KoShapeGroupCommand(KoShapeGroup *container, QList<KoShape *> shapes, QUndoCommand *parent)
00054         : QUndoCommand(parent)
00055         , m_shapes(shapes)
00056         , m_container(container)
00057 {
00058     for (int i = 0; i < shapes.count(); ++i) {
00059         m_clipped.append(false);
00060     }
00061     init();
00062 }
00063 
00064 KoShapeGroupCommand::KoShapeGroupCommand(QUndoCommand *parent)
00065         : QUndoCommand(parent)
00066 {
00067 }
00068 
00069 void KoShapeGroupCommand::init()
00070 {
00071     foreach(KoShape* shape, m_shapes) {
00072         m_oldParents.append(shape->parent());
00073         m_oldClipped.append(shape->parent() && shape->parent()->childClipped(shape));
00074         m_oldZIndex.append(shape->zIndex());
00075     }
00076 
00077     if (m_container->childShapes().isEmpty()) {
00078         setText(i18n("Group shapes"));
00079     }
00080     else {
00081         setText(i18n("Group shapes")); // TODO 2.2 replace text with "Add shapes to group"
00082     }
00083 }
00084 
00085 void KoShapeGroupCommand::redo()
00086 {
00087     QUndoCommand::redo();
00088 
00089     if (dynamic_cast<KoShapeGroup*>(m_container)) {
00090         QRectF bound = containerBoundingRect();
00091         QPointF oldGroupPosition = m_container->absolutePosition(KoFlake::TopLeftCorner);
00092         m_container->setAbsolutePosition(bound.topLeft(), KoFlake::TopLeftCorner);
00093         m_container->setSize(bound.size());
00094 
00095         if (m_container->childCount() > 0) {
00096             // the group has changed position and so have the group child shapes
00097             // -> we need compensate the group position change
00098             QPointF positionOffset = oldGroupPosition - bound.topLeft();
00099             foreach(KoShape * child, m_container->childShapes())
00100                 child->setAbsolutePosition(child->absolutePosition() + positionOffset);
00101         }
00102     }
00103 
00104     QMatrix groupTransform = m_container->absoluteTransformation(0).inverted();
00105 
00106     int zIndex=0;
00107     QList<KoShape*> childShapes(m_container->childShapes());
00108     if (!childShapes.isEmpty()) {
00109         qSort(childShapes.begin(), childShapes.end(), KoShape::compareShapeZIndex);
00110         zIndex = childShapes.last()->zIndex();
00111     }
00112 
00113     uint shapeCount = m_shapes.count();
00114     for (uint i = 0; i < shapeCount; ++i) {
00115         KoShape * shape = m_shapes[i];
00116         shape->setZIndex(zIndex++);
00117         shape->applyAbsoluteTransformation(groupTransform);
00118         m_container->addChild(shape);
00119         m_container->setClipping(shape, m_clipped[i]);
00120     }
00121 }
00122 
00123 void KoShapeGroupCommand::undo()
00124 {
00125     QUndoCommand::undo();
00126 
00127     QMatrix ungroupTransform = m_container->absoluteTransformation(0);
00128     for (int i = 0; i < m_shapes.count(); i++) {
00129         KoShape * shape = m_shapes[i];
00130         m_container->removeChild(shape);
00131         if (m_oldParents.at(i)) {
00132             m_oldParents.at(i)->addChild(shape);
00133             m_oldParents.at(i)->setClipping(shape, m_oldClipped.at(i));
00134         }
00135         shape->applyAbsoluteTransformation(ungroupTransform);
00136         shape->setZIndex(m_oldZIndex[i]);
00137     }
00138 
00139     if (dynamic_cast<KoShapeGroup*>(m_container)) {
00140         QPointF oldGroupPosition = m_container->absolutePosition(KoFlake::TopLeftCorner);
00141         if (m_container->childCount() > 0) {
00142             bool boundingRectInitialized = false;
00143             QRectF bound;
00144             foreach(KoShape * shape, m_container->childShapes()) {
00145                 if (! boundingRectInitialized) {
00146                     bound = shape->boundingRect();
00147                     boundingRectInitialized = true;
00148                 } else
00149                     bound = bound.unite(shape->boundingRect());
00150             }
00151             // the group has changed position and so have the group child shapes
00152             // -> we need compensate the group position change
00153             QPointF positionOffset = oldGroupPosition - bound.topLeft();
00154             foreach(KoShape * child, m_container->childShapes())
00155                 child->setAbsolutePosition(child->absolutePosition() + positionOffset);
00156 
00157             m_container->setAbsolutePosition(bound.topLeft(), KoFlake::TopLeftCorner);
00158             m_container->setSize(bound.size());
00159         }
00160     }
00161 }
00162 
00163 QRectF KoShapeGroupCommand::containerBoundingRect()
00164 {
00165     bool boundingRectInitialized = true;
00166     QRectF bound;
00167     if (m_container->childCount() > 0)
00168         bound = m_container->boundingRect();
00169     else
00170         boundingRectInitialized = false;
00171 
00172     foreach(KoShape *shape, m_shapes) {
00173         if (boundingRectInitialized)
00174             bound = bound.unite(shape->boundingRect());
00175         else {
00176             bound = shape->boundingRect();
00177             boundingRectInitialized = true;
00178         }
00179     }
00180     return bound;
00181 }