Commit 70558a84 authored by Jan Hambrecht's avatar Jan Hambrecht

rewrite of flake transformation system to be based on matrices


svn path=/trunk/koffice/; revision=679758
parent 26438451
......@@ -99,6 +99,7 @@ set(flake_SRCS
commands/KoSubpathJoinCommand.cpp
commands/KoParameterHandleMoveCommand.cpp
commands/KoParameterToPathCommand.cpp
commands/KoShapeTransformCommand.cpp
)
kde4_automoc(${flake_SRCS})
......
......@@ -136,9 +136,9 @@ void KoInteractionTool::updateCursor() {
}
if(koSelection()->count()>1)
d->angle = koSelection()->rotation();
d->angle = 0.0; //koSelection()->rotation();
else
d->angle = koSelection()->firstSelectedShape()->rotation();
d->angle = 0.0; //koSelection()->firstSelectedShape()->rotation();
int rotOctant = 8 + int(8.5 + d->angle / 45);
......@@ -437,13 +437,13 @@ void KoInteractionTool::recalcSelectionBox() {
{
QMatrix matrix = koSelection()->transformationMatrix(0);
d->selectionOutline = matrix.map(QPolygonF(QRectF(QPointF(0, 0), koSelection()->size())));
d->angle = koSelection()->rotation();
d->angle = 0.0; //koSelection()->rotation();
}
else
{
QMatrix matrix = koSelection()->firstSelectedShape()->transformationMatrix(0);
d->selectionOutline = matrix.map(QPolygonF(QRectF(QPointF(0, 0), koSelection()->firstSelectedShape()->size())));
d->angle = koSelection()->firstSelectedShape()->rotation();
d->angle = 0.0; //koSelection()->firstSelectedShape()->rotation();
}
QPolygonF outline = d->selectionOutline; //shorter name in the following :)
d->selectionBox[KoFlake::TopMiddleHandle] = (outline.value(0)+outline.value(1))/2;
......@@ -456,6 +456,8 @@ void KoInteractionTool::recalcSelectionBox() {
d->selectionBox[KoFlake::TopLeftHandle] = outline.value(0);
if(koSelection()->count() == 1) {
KoShape *s = koSelection()->firstSelectedShape();
// TODO detect mirroring
/*
if(s->scaleX() < 0) { // vertically mirrored: swap left / right
qSwap(d->selectionBox[KoFlake::TopLeftHandle], d->selectionBox[KoFlake::TopRightHandle]);
qSwap(d->selectionBox[KoFlake::LeftMiddleHandle], d->selectionBox[KoFlake::RightMiddleHandle]);
......@@ -466,6 +468,7 @@ void KoInteractionTool::recalcSelectionBox() {
qSwap(d->selectionBox[KoFlake::TopMiddleHandle], d->selectionBox[KoFlake::BottomMiddleHandle]);
qSwap(d->selectionBox[KoFlake::TopRightHandle], d->selectionBox[KoFlake::BottomRightHandle]);
}
*/
}
}
......
......@@ -97,15 +97,12 @@ void KoSelection::select(KoShape * object)
}
if(d->selectedShapes.count() == 1)
{
rotate(object->rotation());
shear(object->shearX(), object->shearY());
}
setTransformation( object->transformationMatrix(0) );
else
{
rotate(0);
shear(0, 0);
}
setTransformation( QMatrix() );
updateSizeAndPosition();
requestSelectionChangedEvent();
}
......@@ -123,15 +120,16 @@ void KoSelection::deselect(KoShape * object)
d->selectedShapes.removeAll( object );
if(d->selectedShapes.count() == 1)
{
rotate(firstSelectedShape()->rotation());
shear(firstSelectedShape()->shearX(), firstSelectedShape()->shearY());
}
setTransformation( firstSelectedShape()->transformationMatrix(0) );
requestSelectionChangedEvent();
}
void KoSelection::deselectAll()
{
// reset the transformation matrix of the selection
setTransformation( QMatrix() );
if(d->selectedShapes.isEmpty())
return;
d->selectedShapes.clear();
......@@ -148,7 +146,8 @@ void KoSelection::requestSelectionChangedEvent() {
void KoSelection::selectionChangedEvent() {
d->eventTriggered = false;
scale(1,1);
boundingRect(); //has the side effect of updating the size and position
//just as well use the oppertunity to update the size and position
updateSizeAndPosition();
emit selectionChanged();
}
......@@ -169,14 +168,21 @@ bool KoSelection::hitTest( const QPointF &position ) const
else // count == 0
return false;
}
void KoSelection::updateSizeAndPosition()
{
QRectF bb = sizeRect();
QMatrix matrix = transformationMatrix(0);
resize( bb.size() );
QPointF p = matrix.map(bb.topLeft() + matrix.inverted().map( position()) );
setPosition( p );
}
QRectF KoSelection::boundingRect() const
QRectF KoSelection::sizeRect() const
{
bool first=true;
QRectF bb;
QMatrix tmat = transformationMatrix(0);
QMatrix itmat = tmat.inverted();
QMatrix itmat = transformationMatrix(0).inverted();
if ( !d->selectedShapes.isEmpty() )
{
......@@ -189,17 +195,16 @@ QRectF KoSelection::boundingRect() const
first = false;
}
else
bb = bb.unite(
((*it)->transformationMatrix(0) * itmat).mapRect(QRectF(QPointF(),(*it)->size())) );
bb = bb.unite( ((*it)->transformationMatrix(0) * itmat).mapRect(QRectF(QPointF(),(*it)->size())) );
}
}
//just as well use the oppertunity to update the size and position
(const_cast <KoSelection *>(this))->resize( bb.size() );
QPointF p = tmat.map(bb.topLeft() + itmat.map(position()));
(const_cast <KoSelection *>(this))->setPosition( p );
return bb;
}
return tmat.mapRect(bb);
QRectF KoSelection::boundingRect() const
{
return transformationMatrix(0).mapRect( sizeRect() );
}
const QList<KoShape*> KoSelection::selectedShapes(KoFlake::SelectionType strip) const {
......
......@@ -3,7 +3,7 @@
Copyright (C) 2006 Boudewijn Rempt <boud@valdyas.org>
Copyright (C) 2006 Thorsten Zachmann <zachmann@kde.org>
Copyright (C) 2007 Thomas Zander <zander@kde.org>
Copyright (C) 2006 Jan Hambrecht <jaham@gmx.net>
Copyright (C) 2006,2007 Jan Hambrecht <jaham@gmx.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
......@@ -106,6 +106,9 @@ public:
*/
KoShapeLayer* activeLayer() const;
/// Updates the size and position of the selection
void updateSizeAndPosition();
signals:
/// emitted when the selection is changed
void selectionChanged();
......@@ -119,6 +122,8 @@ private:
virtual void saveOdf( KoShapeSavingContext & ) const {}
virtual bool loadOdf( const KoXmlElement &, KoShapeLoadingContext &) { return true; }
QRectF sizeRect() const;
class Private;
Private * const d;
};
......
This diff is collapsed.
......@@ -170,12 +170,12 @@ public:
/**
* Return the current scaling adjustment over the X axis.
*/
double scaleX() const;
KDE_DEPRECATED double scaleX() const;
/**
* Return the current scaling adjustment over the Y axis.
*/
double scaleY() const;
KDE_DEPRECATED double scaleY() const;
/**
* @brief Rotate the shape
......@@ -189,7 +189,7 @@ public:
/**
* Return the current rotation in degrees.
*/
double rotation() const;
KDE_DEPRECATED double rotation() const;
/**
* @brief Shear the shape
......@@ -205,13 +205,13 @@ public:
* Return the current horizontal shearing angle for this shape.
* @return the current horizontal shearing angle for this shape.
*/
double shearX() const;
KDE_DEPRECATED double shearX() const;
/**
* Return the current vertical shearing angle for this shape.
* @return the current vertical shearing angle for this shape.
*/
double shearY() const;
KDE_DEPRECATED double shearY() const;
/**
* @brief Resize the shape
......@@ -537,6 +537,21 @@ public:
*/
QMatrix transformationMatrix(const KoViewConverter *converter) const;
/**
* Applies a transformation to this shape.
*
* The transformation given is relative to the global coordinate system, i.e. the document.
*
* @param matrix the transformation matrix to apply
*/
void applyTransformation(const QMatrix &matrix );
/**
* Sets a new transformation matrix describing the local transformations on this shape.
* @param matrix the new transformation matrix
*/
void setTransformation( const QMatrix &matrix );
/**
* Copy all the settings from the parameter shape and apply them to this shape.
* Settings like the position and rotation to visible and locked. The parent
......
/* This file is part of the KDE project
* Copyright (C) 2006-2007 Thomas Zander <zander@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -18,6 +19,7 @@
*/
#include "KoShapeContainer.h"
#include "KoShapeContainerModel.h"
#include "KoShapeBorderModel.h"
#include <QPointF>
#include <QPainter>
......@@ -181,7 +183,8 @@ void KoShapeContainer::paint(QPainter &painter, const KoViewConverter &converter
QList<KoShape*> sortedObjects = d->children->iterator();
qSort(sortedObjects.begin(), sortedObjects.end(), KoShape::compareShapeZIndex);
QMatrix baseMatrix = matrix().inverted() * painter.matrix();
QMatrix baseMatrix = transformationMatrix(0).inverted() * painter.matrix();
// clip the children to the parent outline.
QMatrix m;
......@@ -208,6 +211,12 @@ void KoShapeContainer::paint(QPainter &painter, const KoViewConverter &converter
painter.setMatrix( shape->transformationMatrix(&converter) * baseMatrix );
shape->paint(painter, converter);
painter.restore();
if(shape->border()) {
painter.save();
painter.setMatrix( shape->transformationMatrix(&converter) * baseMatrix );
shape->border()->paintBorder(shape, painter, converter);
painter.restore();
}
}
}
......
......@@ -392,6 +392,8 @@ void KoShapeManager::updateTree()
d->shapeIndexesBeforeUpdate.clear();
detector.fireSignals();
d->selection->updateSizeAndPosition();
}
const QList<KoShape *> & KoShapeManager::shapes() const {
......
......@@ -2,6 +2,7 @@
Copyright (C) 2006 Thorsten Zachmann <zachmann@kde.org>
Copyright (C) 2006 Thomas Zander <zander@kde.org>
Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
......@@ -29,9 +30,10 @@
#include "KoPointerEvent.h"
#include "KoCanvasResourceProvider.h"
#include "KoInteractionTool.h"
#include "commands/KoShapeMoveCommand.h"
#include "commands/KoShapeTransformCommand.h"
#include <kdebug.h>
#include <klocale.h>
#include <QPainter>
#include <QMouseEvent>
#include <QPainterPath>
......@@ -47,12 +49,9 @@ KoShapeMoveStrategy::KoShapeMoveStrategy( KoTool *tool, KoCanvasBase *canvas, co
if( ! isEditable( shape ) )
continue;
m_selectedShapes << shape;
m_previousPositions << shape->position();
m_newPositions << shape->position();
boundingRect = boundingRect.unite( shape->boundingRect() );
}
m_initialTopLeft = boundingRect.topLeft();
m_initialSelectionPosition = canvas->shapeManager()->selection()->position();
}
void KoShapeMoveStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModifiers modifiers) {
......@@ -71,29 +70,26 @@ void KoShapeMoveStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModi
diff.setY(0);
}
Q_ASSERT(m_newPositions.count());
QMatrix matrix;
matrix.translate( diff.x(), diff.y() );
QMatrix applyMatrix = matrix * m_translationMatrix.inverted();
m_diff = diff;
int i=0;
foreach(KoShape *shape, m_selectedShapes) {
diff = m_previousPositions.at(i) + m_diff - shape->position();
if(shape->parent())
shape->parent()->model()->proposeMove(shape, diff);
m_canvas->clipToDocument(shape, diff);
QPointF newPos (shape->position() + diff);
m_newPositions[i] = newPos;
foreach( KoShape * shape, m_selectedShapes ) {
shape->repaint();
shape->setPosition(newPos);
shape->applyTransformation( applyMatrix );
shape->repaint();
i++;
}
m_canvas->shapeManager()->selection()->setPosition(m_initialSelectionPosition + m_diff);
m_canvas->shapeManager()->selection()->applyTransformation( applyMatrix );
m_translationMatrix = matrix;
}
QUndoCommand* KoShapeMoveStrategy::createCommand() {
if(m_diff.x() == 0 && m_diff.y() == 0)
if( m_translationMatrix.isIdentity() )
return 0;
return new KoShapeMoveCommand(m_selectedShapes, m_previousPositions, m_newPositions);
KoShapeTransformCommand * cmd = new KoShapeTransformCommand( m_selectedShapes, m_translationMatrix );
cmd->setText( i18n( "Move shapes" ) );
cmd->undo();
return cmd;
}
void KoShapeMoveStrategy::paint( QPainter &painter, const KoViewConverter &converter) {
......
......@@ -50,9 +50,8 @@ public:
virtual void paint( QPainter &painter, const KoViewConverter &converter);
private:
QList<QPointF> m_previousPositions;
QList<QPointF> m_newPositions;
QPointF m_initialTopLeft, m_start, m_diff, m_initialSelectionPosition;
QPointF m_initialTopLeft, m_start, m_diff;
QMatrix m_translationMatrix;
};
#endif /* KODEFMOVE_H */
/* This file is part of the KDE project
* Copyright (C) 2006 Thomas Zander <zander@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -22,8 +23,8 @@
#include "KoPointerEvent.h"
#include "KoCanvasBase.h"
#include "KoCanvasResourceProvider.h"
#include "commands/KoShapeMoveCommand.h"
#include "commands/KoShapeSizeCommand.h"
#include "commands/KoShapeTransformCommand.h"
#include <klocale.h>
......@@ -38,12 +39,8 @@ KoShapeResizeStrategy::KoShapeResizeStrategy( KoTool *tool, KoCanvasBase *canvas
continue;
m_selectedShapes << shape;
m_startPositions << shape->position();
m_startAbsolutePositions << shape->absolutePosition();
m_lastTransforms << QMatrix();
m_startSizes << shape->size();
m_startShearXs << shape->shearX();
m_startShearYs << shape->shearY();
m_startScaleXs << shape->scaleX();
m_startScaleYs << shape->scaleY();
}
m_start = clicked;
......@@ -53,16 +50,13 @@ KoShapeResizeStrategy::KoShapeResizeStrategy( KoTool *tool, KoCanvasBase *canvas
if(canvas->shapeManager()->selection()->count()==1)
shp = canvas->shapeManager()->selection()->firstSelectedShape();
m_unwindMatrix = QMatrix();
if (shp)
m_unwindMatrix.rotate( - shp->rotation());
m_windMatrix = QMatrix();
if (shp)
m_windMatrix.rotate(shp->rotation());
if (shp)
if( shp )
{
m_windMatrix = shp->transformationMatrix(0);
m_unwindMatrix = m_windMatrix.inverted();
m_initialSize = shp->size();
if (shp)
m_initialPosition = shp->transformationMatrix(0).map(QPointF());
m_initialPosition = m_windMatrix.map(QPointF());
}
switch(direction) {
case KoFlake::TopMiddleHandle:
......@@ -90,7 +84,6 @@ void KoShapeResizeStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardMo
QPointF newPos = point;
if(m_canvas->snapToGrid() && (modifiers & Qt::ShiftModifier) == 0)
applyGrid(newPos);
QPointF distance = newPos - m_start;
bool keepAspect = modifiers & Qt::AltModifier;
foreach(KoShape *shape, m_selectedShapes)
......@@ -98,7 +91,8 @@ void KoShapeResizeStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardMo
double startWidth = m_initialSize.width();
double startHeight = m_initialSize.height();
distance = m_unwindMatrix.map(distance);
QPointF distance = m_unwindMatrix.map(newPos) - m_unwindMatrix.map( m_start );
double zoomX=1, zoomY=1;
if(keepAspect) {
......@@ -147,50 +141,86 @@ void KoShapeResizeStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardMo
matrix.scale(zoomX, zoomY);
matrix.translate(-move.x(), -move.y()); // and back
// that is the transformation we want to apply to the shapes
matrix = m_unwindMatrix * matrix * m_windMatrix;
int i=0;
foreach(KoShape *shape, m_selectedShapes) {
QPointF pos(m_startAbsolutePositions[i] - m_initialPosition);
pos = matrix.map(pos);
// construct the matrix tranformation we apply to the shape
QMatrix m = (QMatrix().rotate(shape->rotation())) * matrix * (QMatrix().rotate(-shape->rotation()));
QSizeF size(m.m11() * m_startSizes[i].width(), m.m22() * m_startSizes[i].height());
bool mirrorX = size.width() < 0;
bool mirrorY = size.height() < 0;
size.setWidth(qMax(4.0, qAbs(size.width())));
size.setHeight(qMax(4.0, qAbs(size.height())));
// the resizing transformation without the mirroring part
QMatrix resizeMatrix;
resizeMatrix.translate(move.x(), move.y()); // translate to
resizeMatrix.scale( qAbs(zoomX), qAbs(zoomY) );
resizeMatrix.translate(-move.x(), -move.y()); // and back
// the mirroring part of the resizing transformation
QMatrix mirrorMatrix;
mirrorMatrix.translate(move.x(), move.y()); // translate to
mirrorMatrix.scale( zoomX < 0 ? -1 : 1, zoomY < 0 ? -1 : 1 );
mirrorMatrix.translate(-move.x(), -move.y()); // and back
int i = 0;
foreach(KoShape *shape, m_selectedShapes)
{
shape->repaint();
// the position has to be set after the size as we set the center of the shape
// possibly mirror the shape
double x = m_startScaleXs[i];
double y = m_startScaleYs[i];
if(mirrorX)
x = x * -1;
if(mirrorY)
y = y * -1;
shape->scale(x, y);
// this uses resize for the zooming part
shape->applyTransformation( m_unwindMatrix );
/*
normally we would just apply the resizeMatrix now and be done with it, but
we want to resize instead of scale, so we have to separate the scaling part
of that transformation which can then be used to resize
*/
// undo the last resize transformation
shape->applyTransformation( m_lastTransforms[i].inverted() );
// save the shapes transformation matrix
QMatrix shapeMatrix = shape->transformationMatrix(0);
// calculate the matrix we would apply to the local shape matrix
// that tells us the effective scale values we have to use for the resizing
QMatrix localMatrix = shapeMatrix * resizeMatrix * shapeMatrix.inverted();
// save the effective scale values
double scaleX = localMatrix.m11();
double scaleY = localMatrix.m22();
// calculate the scale matrix which is equivalent to our resizing above
QMatrix scaleMatrix = (QMatrix().scale( scaleX, scaleY ));
scaleMatrix = shapeMatrix.inverted() * scaleMatrix * shapeMatrix;
// calculate the new size of the shape, using the effective scale values
QSizeF size( scaleX * m_startSizes[i].width(), scaleY * m_startSizes[i].height() );
// apply the transformation
shape->resize( size );
shape->shear(m_startShearXs[i] + m.m12() / m.m22(), m_startShearYs[i] + m.m21() / m.m11());
shape->setAbsolutePosition( pos + m_initialPosition );
// apply the rest of the transformation without the resizing part
shape->applyTransformation( scaleMatrix.inverted() * resizeMatrix );
shape->applyTransformation( mirrorMatrix );
// and remember the applied transformation later for later undoing
m_lastTransforms[i] = shapeMatrix.inverted() * shape->transformationMatrix(0);
shape->applyTransformation( m_windMatrix );
shape->repaint();
i++;
}
m_canvas->shapeManager()->selection()->applyTransformation( matrix * m_scaleMatrix.inverted() );
m_scaleMatrix = matrix;
}
QUndoCommand* KoShapeResizeStrategy::createCommand() {
QUndoCommand *cmd = new QUndoCommand(i18n("Resize"));
QList<QPointF> newPositions;
QList<QSizeF> newSizes;
foreach(KoShape *shape, m_selectedShapes) {
newPositions << shape->position();
newSizes << shape->size();
QList<QMatrix> transformations;
uint shapeCount = m_selectedShapes.count();
for( uint i = 0; i < shapeCount; ++i )
{
newSizes << m_selectedShapes[i]->size();
transformations << m_unwindMatrix * m_lastTransforms[i] * m_windMatrix;
}
new KoShapeMoveCommand(m_selectedShapes, m_startPositions, newPositions, cmd);
new KoShapeSizeCommand(m_selectedShapes, m_startSizes, newSizes, cmd);
QUndoCommand * cmd = new QUndoCommand(i18n("Resize"));
new KoShapeSizeCommand(m_selectedShapes, m_startSizes, newSizes, cmd );
new KoShapeTransformCommand( m_selectedShapes, transformations, cmd );
cmd->undo();
return cmd;
}
......
......@@ -50,16 +50,13 @@ public:
private:
QPointF m_start;
QList<QPointF> m_startPositions;
QList<QPointF> m_startAbsolutePositions;
QList<QSizeF> m_startSizes;
QList<double> m_startShearXs;
QList<double> m_startShearYs;
QList<double> m_startScaleXs;
QList<double> m_startScaleYs;
bool m_top, m_left, m_bottom, m_right;
QMatrix m_unwindMatrix, m_windMatrix;
QSizeF m_initialSize;
QPointF m_initialPosition;
QMatrix m_scaleMatrix;
QList<QMatrix> m_lastTransforms;
};
#endif /* KOSHAPESCALETRATEGY_H */
......
/* This file is part of the KDE project
* Copyright (C) 2006 Thomas Zander <zander@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -23,8 +24,7 @@
#include "KoPointerEvent.h"
#include "KoShapeManager.h"
#include "KoCanvasResourceProvider.h"
#include "commands/KoShapeMoveCommand.h"
#include "commands/KoShapeRotateCommand.h"
#include "commands/KoShapeTransformCommand.h"
#include <QPointF>
#include <math.h>
......@@ -40,12 +40,11 @@ KoShapeRotateStrategy::KoShapeRotateStrategy( KoTool *tool, KoCanvasBase *canvas
if( ! isEditable( shape ) )
continue;
m_selectedShapes << shape;
m_startPositions << shape->position();
m_startAbsolutePositions << shape->absolutePosition();
m_initialAngles << shape->rotation();
m_initialBoundingRect = m_initialBoundingRect.unite( shape->boundingRect() );
if( m_selectedShapes.count() == 1 )
m_initialBoundingRect = shape->boundingRect();
else
m_initialBoundingRect = m_initialBoundingRect.united( shape->boundingRect() );
}
m_initialSelectionAngle = canvas->shapeManager()->selection()->rotation();
}
void KoShapeRotateStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModifiers modifiers) {
......@@ -68,16 +67,14 @@ void KoShapeRotateStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardMo
matrix.rotate(angle);
matrix.translate(-center.x(), -center.y());
int counter=0;
foreach(KoShape *shape, m_selectedShapes) {
QMatrix applyMatrix = matrix * m_rotationMatrix.inverted();
m_rotationMatrix = matrix;
foreach( KoShape * shape, m_selectedShapes ) {
shape->repaint();
shape->setAbsolutePosition(matrix.map(m_startAbsolutePositions[counter]));
shape->rotate(m_initialAngles[counter] + angle);
shape->applyTransformation( applyMatrix );
shape->repaint();
counter++;
}
m_canvas->shapeManager()->selection()->rotate(m_initialSelectionAngle + angle);
m_canvas->shapeManager()->selection()->applyTransformation( applyMatrix );
}
void KoShapeRotateStrategy::paint( QPainter &painter, const KoViewConverter &converter) {
......@@ -85,17 +82,19 @@ void KoShapeRotateStrategy::paint( QPainter &painter, const KoViewConverter &con
decorator.setSelection(m_canvas->shapeManager()->selection());
decorator.setHandleRadius( m_canvas->resourceProvider()->handleRadius() );
decorator.paint(painter, converter);
// paint the rotation center
painter.setPen( QPen(Qt::red));
painter.setBrush( QBrush(Qt::red));
painter.setRenderHint( QPainter::Antialiasing, true );
QRectF circle( 0, 0, 5, 5 );
circle.moveCenter( converter.documentToView( m_initialBoundingRect.center() ) );
painter.drawEllipse( circle );
}
QUndoCommand* KoShapeRotateStrategy::createCommand() {
QUndoCommand *cmd = new QUndoCommand(i18n("Rotate"));
QList<QPointF> newPositions;
QList<double> newAngles;
foreach(KoShape *shape, m_selectedShapes) {
newPositions << shape->position();
newAngles << shape->rotation();
}
new KoShapeMoveCommand(m_selectedShapes, m_startPositions, newPositions, cmd);
new KoShapeRotateCommand(m_selectedShapes, m_initialAngles, newAngles, cmd);
KoShapeTransformCommand * cmd = new KoShapeTransformCommand( m_selectedShapes, m_rotationMatrix );
cmd->setText( i18n("Rotate") );
cmd->undo();
return cmd;
}
......@@ -52,10 +52,7 @@ public:
private:
QRectF m_initialBoundingRect;
QPointF m_start;
QList<QPointF> m_startPositions;
QList<QPointF> m_startAbsolutePositions;
QList<double> m_initialAngles;
double m_initialSelectionAngle;
QMatrix m_rotationMatrix;
};
#endif /* KOSHAPEROTATESTRATEGY_H */
......
/* This file is part of the KDE project
* Copyright (C) 2006 Thomas Zander <zander@kde.org>
* Copyright (C) 2006 casper Boemann <cbr@boemann.dk>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -26,6 +27,7 @@
#include "KoCanvasResourceProvider.h"
#include "commands/KoShapeShearCommand.h"
#include "commands/KoShapeMoveCommand.h"
#include "commands/KoShapeTransformCommand.h"
#include <QPointF>
......@@ -35,7 +37,6 @@
KoShapeShearStrategy::KoShapeShearStrategy( KoTool *tool, KoCanvasBase *canvas, const QPointF &clicked, KoFlake::SelectionHandle direction )
: KoInteractionStrategy(tool, canvas)
, m_initialBoundingRect()
, m_start(clicked)
{
QList<KoShape*> selectedShapes = canvas->shapeManager()->selection()->selectedShapes(KoFlake::StrippedSelection);
......@@ -43,14 +44,7 @@ KoShapeShearStrategy::KoShapeShearStrategy( KoTool *tool, KoCanvasBase *canvas,
if( ! isEditable( shape ) )
continue;
m_selectedShapes << shape;
m_startPositions << shape->position();
m_startMatrices << shape->transformationMatrix(0);
m_startRotationMatrices << QMatrix().rotate(shape->rotation());