ShapeResizeStrategy::ShapeResizeStrategy(KoToolBase *tool, const QPointF &clicked, KoFlake::SelectionHandle direction ) : KoInteractionStrategy(tool), m_lastScale(1.0,1.0) { Q_ASSERT(tool->canvas()->shapeManager()->selection()->count() > 0); QList<KoShape*> selectedShapes = tool->canvas()->shapeManager()->selection()->selectedShapes(KoFlake::StrippedSelection); foreach(KoShape *shape, selectedShapes) { if ( ! shape->isEditable() ) continue; m_selectedShapes << shape; m_startPositions << shape->position(); m_oldTransforms << shape->transformation(); m_transformations << QTransform(); m_startSizes << shape->size(); } m_start = clicked; KoShape *shp = 0; if (tool->canvas()->shapeManager()->selection()->count()>1) shp = tool->canvas()->shapeManager()->selection(); if (tool->canvas()->shapeManager()->selection()->count()==1) shp = tool->canvas()->shapeManager()->selection()->firstSelectedShape(); if ( shp ) { m_windMatrix = shp->absoluteTransformation(0); m_unwindMatrix = m_windMatrix.inverted(); m_initialSize = shp->size(); m_initialPosition = m_windMatrix.map(QPointF()); } switch(direction) { case KoFlake::TopMiddleHandle: m_start = 0.5 * (shp->absolutePosition(KoFlake::TopLeftCorner) + shp->absolutePosition(KoFlake::TopRightCorner) ); m_top = true; m_bottom = false; m_left = false; m_right = false; break; case KoFlake::TopRightHandle: m_start = shp->absolutePosition(KoFlake::TopRightCorner); m_top = true; m_bottom = false; m_left = false; m_right = true; break; case KoFlake::RightMiddleHandle: m_start = 0.5 * ( shp->absolutePosition(KoFlake::TopRightCorner) + shp->absolutePosition(KoFlake::BottomRightCorner) ); m_top = false; m_bottom = false; m_left = false; m_right = true; break; case KoFlake::BottomRightHandle: m_start = shp->absolutePosition(KoFlake::BottomRightCorner); m_top = false; m_bottom = true; m_left = false; m_right = true; break; case KoFlake::BottomMiddleHandle: m_start = 0.5 * ( shp->absolutePosition(KoFlake::BottomRightCorner) + shp->absolutePosition(KoFlake::BottomLeftCorner) ); m_top = false; m_bottom = true; m_left = false; m_right = false; break; case KoFlake::BottomLeftHandle: m_start = shp->absolutePosition(KoFlake::BottomLeftCorner); m_top = false; m_bottom = true; m_left = true; m_right = false; break; case KoFlake::LeftMiddleHandle: m_start = 0.5 * ( shp->absolutePosition(KoFlake::BottomLeftCorner) + shp->absolutePosition(KoFlake::TopLeftCorner) ); m_top = false; m_bottom = false; m_left = true; m_right = false; break; case KoFlake::TopLeftHandle: m_start = shp->absolutePosition(KoFlake::TopLeftCorner); m_top = true; m_bottom = false; m_left = true; m_right = false; break; default: Q_ASSERT(0); // illegal 'corner' } tool->setStatusText( i18n("Press CTRL to resize from center.") ); }
QPointF KoConnectionShapePrivate::escapeDirection(int handleId) const { Q_Q(const KoConnectionShape); QPointF direction; if (handleConnected(handleId)) { KoShape *attachedShape = handleId == KoConnectionShape::StartHandle ? shape1 : shape2; int connectionPointId = handleId == KoConnectionShape::StartHandle ? connectionPointId1 : connectionPointId2; KoConnectionPoint::EscapeDirection ed = attachedShape->connectionPoint(connectionPointId).escapeDirection; if (ed == KoConnectionPoint::AllDirections) { QPointF handlePoint = q->shapeToDocument(handles[handleId]); QPointF centerPoint = attachedShape->absolutePosition(KoFlake::CenteredPosition); /* * Determine the best escape direction from the position of the handle point * and the position and orientation of the attached shape. * The idea is to define 4 sectors, one for each edge of the attached shape. * Each sector starts at the center point of the attached shape and has it * left and right edge going through the two points which define the edge. * Then we check which sector contains our handle point, for which we can * simply calculate the corresponding direction which is orthogonal to the * corresponding bounding box edge. * From that we derive the escape direction from looking at the main coordinate * of the orthogonal direction. */ // define our edge points in the right order const KoFlake::Position corners[4] = { KoFlake::BottomRightCorner, KoFlake::BottomLeftCorner, KoFlake::TopLeftCorner, KoFlake::TopRightCorner }; QPointF vHandle = handlePoint-centerPoint; for (int i = 0; i < 4; ++i) { // first point of bounding box edge QPointF p1 = attachedShape->absolutePosition(corners[i]); // second point of bounding box edge QPointF p2 = attachedShape->absolutePosition(corners[(i+1)%4]); // check on which side of the first sector edge our second sector edge is const qreal c0 = crossProd(p1-centerPoint, p2-centerPoint); // check on which side of the first sector edge our handle point is const qreal c1 = crossProd(p1-centerPoint, vHandle); // second egde and handle point must be on the same side of first edge if ((c0 < 0 && c1 > 0) || (c0 > 0 && c1 < 0)) continue; // check on which side of the handle point our second sector edge is const qreal c2 = crossProd(vHandle, p2-centerPoint); // second edge must be on the same side of the handle point as on first edge if ((c0 < 0 && c2 > 0) || (c0 > 0 && c2 < 0)) continue; // now we found the correct edge QPointF vDir = 0.5 *(p1+p2) - centerPoint; // look at coordinate with the greatest absolute value // and construct our escape direction accordingly const qreal xabs = qAbs<qreal>(vDir.x()); const qreal yabs = qAbs<qreal>(vDir.y()); if (xabs > yabs) { direction.rx() = vDir.x() > 0 ? 1.0 : -1.0; direction.ry() = 0.0; } else { direction.rx() = 0.0; direction.ry() = vDir.y() > 0 ? 1.0 : -1.0; } break; } } else if (ed == KoConnectionPoint::HorizontalDirections) { QPointF handlePoint = q->shapeToDocument(handles[handleId]); QPointF centerPoint = attachedShape->absolutePosition(KoFlake::CenteredPosition); // use horizontal direction pointing away from center point if (handlePoint.x() < centerPoint.x()) direction = QPointF(-1.0, 0.0); else direction = QPointF(1.0, 0.0); } else if (ed == KoConnectionPoint::VerticalDirections) { QPointF handlePoint = q->shapeToDocument(handles[handleId]); QPointF centerPoint = attachedShape->absolutePosition(KoFlake::CenteredPosition); // use vertical direction pointing away from center point if (handlePoint.y() < centerPoint.y()) direction = QPointF(0.0, -1.0); else direction = QPointF(0.0, 1.0); } else if (ed == KoConnectionPoint::LeftDirection) { direction = QPointF(-1.0, 0.0); } else if (ed == KoConnectionPoint::RightDirection) { direction = QPointF(1.0, 0.0); } else if (ed == KoConnectionPoint::UpDirection) { direction = QPointF(0.0, -1.0); } else if (ed == KoConnectionPoint::DownDirection) { direction = QPointF(0.0, 1.0); } // transform escape direction by using our own transformation matrix QTransform invMatrix = q->absoluteTransformation(0).inverted(); direction = invMatrix.map(direction) - invMatrix.map(QPointF()); direction /= sqrt(direction.x() * direction.x() + direction.y() * direction.y()); } return direction; }