コード例 #1
0
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.") );
}
コード例 #2
0
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;
}