00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "KoShapeResizeStrategy.h"
00021 #include "KoShapeManager.h"
00022 #include "KoPointerEvent.h"
00023 #include "KoCanvasBase.h"
00024 #include "KoCommand.h"
00025
00026 #include <kdebug.h>
00027
00028 KoShapeResizeStrategy::KoShapeResizeStrategy( KoTool *tool, KoCanvasBase *canvas,
00029 const QPointF &clicked, KoFlake::SelectionHandle direction )
00030 : KoInteractionStrategy(tool, canvas)
00031 {
00032 Q_ASSERT( canvas->shapeManager()->selection()->count() > 0);
00033 KoSelectionSet selectedShapes = canvas->shapeManager()->selection()->selectedShapes(KoFlake::StrippedSelection);
00034 foreach(KoShape *shape, selectedShapes) {
00035 m_selectedShapes << shape;
00036 m_startPositions << shape->position();
00037 m_startAbsolutePositions << shape->absolutePosition();
00038 m_startSizes << shape->size();
00039 m_startShearXs << shape->shearX();
00040 m_startShearYs << shape->shearY();
00041 }
00042 m_start = clicked;
00043
00044 KoShape *shp = 0;
00045 if(canvas->shapeManager()->selection()->count()>1)
00046 shp = canvas->shapeManager()->selection();
00047 if(canvas->shapeManager()->selection()->count()==1)
00048 shp = canvas->shapeManager()->selection()->firstSelectedShape();
00049
00050 m_unwindMatrix = QMatrix();
00051 if (shp)
00052 m_unwindMatrix.rotate( - shp->rotation());
00053 m_windMatrix = QMatrix();
00054 if (shp)
00055 m_windMatrix.rotate(shp->rotation());
00056 if (shp)
00057 m_initialSize = shp->size();
00058 if (shp)
00059 m_initialPosition = shp->transformationMatrix(0).map(QPointF());
00060
00061 switch(direction) {
00062 case KoFlake::TopMiddleHandle:
00063 m_top = true; m_bottom = false; m_left = false; m_right = false; break;
00064 case KoFlake::TopRightHandle:
00065 m_top = true; m_bottom = false; m_left = false; m_right = true; break;
00066 case KoFlake::RightMiddleHandle:
00067 m_top = false; m_bottom = false; m_left = false; m_right = true; break;
00068 case KoFlake::BottomRightHandle:
00069 m_top = false; m_bottom = true; m_left = false; m_right = true; break;
00070 case KoFlake::BottomMiddleHandle:
00071 m_top = false; m_bottom = true; m_left = false; m_right = false; break;
00072 case KoFlake::BottomLeftHandle:
00073 m_top = false; m_bottom = true; m_left = true; m_right = false; break;
00074 case KoFlake::LeftMiddleHandle:
00075 m_top = false; m_bottom = false; m_left = true; m_right = false; break;
00076 case KoFlake::TopLeftHandle:
00077 m_top = true; m_bottom = false; m_left = true; m_right = false; break;
00078 default:
00079 ;
00080 }
00081 }
00082
00083 void KoShapeResizeStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModifiers modifiers) {
00084 QPointF newPos = point;
00085 if(m_canvas->snapToGrid() && (modifiers & Qt::ShiftModifier) == 0)
00086 applyGrid(newPos);
00087 QPointF distance = newPos - m_start;
00088
00089 bool keepAspect = modifiers & Qt::AltModifier;
00090 foreach(KoShape *shape, m_selectedShapes)
00091 keepAspect = keepAspect || shape->keepAspectRatio();
00092
00093 double startWidth = m_initialSize.width();
00094 double startHeight = m_initialSize.height();
00095 distance = m_unwindMatrix.map(distance);
00096
00097 double zoomX=1, zoomY=1;
00098 if(keepAspect) {
00099 double ratio = startWidth / startHeight;
00100 double width = startWidth - distance.x();
00101 double height = startHeight - distance.y();
00102 int toLargestEdge = (m_bottom?1:0) + (m_top?1:0) +
00103 (m_left?1:0) + (m_right?1:0);
00104 bool horizontal = m_left || m_right;
00105
00106 if(toLargestEdge != 1) {
00107 if (width < height)
00108 width = height * ratio;
00109 else
00110 height = width / ratio;
00111 } else {
00112 if (horizontal)
00113 height = width / ratio;
00114 else
00115 width = height * ratio;
00116 }
00117 zoomX = startWidth / width;
00118 zoomY = startHeight / height;
00119 }
00120 else {
00121 if(m_left)
00122 zoomX = (startWidth - distance.x()) / startWidth;
00123 else if(m_right)
00124 zoomX = (startWidth + distance.x()) / startWidth;
00125 if(m_top)
00126 zoomY = (startHeight - distance.y()) / startHeight;
00127 else if(m_bottom)
00128 zoomY = (startHeight + distance.y()) / startHeight;
00129 }
00130
00131 bool scaleFromCenter = modifiers & Qt::ControlModifier;
00132 QPointF move;
00133 QMatrix matrix;
00134
00135 if(scaleFromCenter)
00136 {
00137 move = QPointF(startWidth / 2.0, startHeight / 2.0);
00138 }
00139 else
00140 {
00141 move = QPointF(m_left?startWidth:0, m_top?startHeight:0);
00142 }
00143 matrix.translate(move.x(), move.y());
00144 matrix.scale(qMax(0.0, zoomX), qMax(0.0, zoomY));
00145 matrix.translate(-move.x(), -move.y());
00146
00147 matrix = m_unwindMatrix * matrix * m_windMatrix;
00148 int i=0;
00149 foreach(KoShape *shape, m_selectedShapes) {
00150 QPointF pos(m_startAbsolutePositions[i] - m_initialPosition);
00151 pos = matrix.map(pos);
00152
00153
00154 QMatrix m = (QMatrix().rotate(shape->rotation())) * matrix * (QMatrix().rotate(-shape->rotation()));
00155 QSizeF size(m.m11() * m_startSizes[i].width(), m.m22() * m_startSizes[i].height());
00156 size.setWidth(qMax(4.0, size.width()));
00157 size.setHeight(qMax(4.0, size.height()));
00158
00159 shape->repaint();
00160
00161 shape->resize( size );
00162 shape->shear(m_startShearXs[i] + m.m12() / m.m22(), m_startShearYs[i] + m.m21() / m.m11());
00163 shape->setAbsolutePosition( pos + m_initialPosition );
00164 shape->repaint();
00165 i++;
00166 }
00167 }
00168
00169 KCommand* KoShapeResizeStrategy::createCommand() {
00170 KMacroCommand *cmd = new KMacroCommand("Resize");
00171 QList<QPointF> newPositions;
00172 QList<QSizeF> newSizes;
00173 foreach(KoShape *shape, m_selectedShapes) {
00174 newPositions << shape->position();
00175 newSizes << shape->size();
00176 }
00177 cmd->addCommand(new KoShapeMoveCommand(m_selectedShapes, m_startPositions, newPositions));
00178 cmd->addCommand(new KoShapeSizeCommand(m_selectedShapes, m_startSizes, newSizes));
00179 return cmd;
00180 }
00181
00182 void KoShapeResizeStrategy::paint( QPainter &painter, KoViewConverter &converter) {
00183 SelectionDecorator decorator (KoFlake::NoHandle, false, false);
00184 decorator.setSelection(m_canvas->shapeManager()->selection());
00185 decorator.paint(painter, converter);
00186 }