Ejemplo n.º 1
0
KoShape* KoConnectionShapeFactory::createDefaultShape(KoDocumentResourceManager *) const
{
    KoConnectionShape * shape = new KoConnectionShape();
    shape->setStroke(new KoShapeStroke());
    shape->setShapeId(KoPathShapeId);
    return shape;
}
Ejemplo n.º 2
0
int ConnectionTool::handleAtPoint(KoShape *shape, const QPointF &mousePoint) const
{
    if (!shape)
        return -1;

    const QPointF shapePoint = shape->documentToShape(mousePoint);

    KoConnectionShape * connectionShape = dynamic_cast<KoConnectionShape*>(shape);
    if (connectionShape) {
        // check connection shape handles
        return connectionShape->handleIdAt(handleGrabRect(shapePoint));
    } else {
        // check connection points
        int grabDistance = grabSensitivity();
        qreal minDistance = HUGE_VAL;
        int handleId = -1;
        KoConnectionPoints connectionPoints = shape->connectionPoints();
        KoConnectionPoints::const_iterator cp = connectionPoints.constBegin();
        KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd();
        for(; cp != lastCp; ++cp) {
            qreal d = squareDistance(shapePoint, cp.value().position);
            if (d <= grabDistance && d < minDistance) {
                handleId = cp.key();
                minDistance = d;
            }
        }
        return handleId;
    }
}
Ejemplo n.º 3
0
KoConnectionShape * ConnectionTool::nearestConnectionShape(const QList<KoShape*> &shapes, const QPointF &mousePos) const
{
    int grabDistance = grabSensitivity();

    KoConnectionShape * nearestConnectionShape = 0;
    qreal minSquaredDistance = HUGE_VAL;
    const qreal maxSquaredDistance = grabDistance*grabDistance;

    foreach(KoShape *shape, shapes) {
        KoConnectionShape * connectionShape = dynamic_cast<KoConnectionShape*>(shape);
        if (!connectionShape || !connectionShape->isParametricShape())
            continue;

        // convert document point to shape coordinates
        QPointF p = connectionShape->documentToShape(mousePos);
        // our region of interest, i.e. a region around our mouse position
        QRectF roi = handleGrabRect(p);

        // check all segments of this shape which intersect the region of interest
        QList<KoPathSegment> segments = connectionShape->segmentsAt(roi);
        foreach (const KoPathSegment &s, segments) {
            qreal nearestPointParam = s.nearestPoint(p);
            QPointF nearestPoint = s.pointAt(nearestPointParam);
            QPointF diff = p - nearestPoint;
            qreal squaredDistance = diff.x()*diff.x() + diff.y()*diff.y();
            // are we within the allowed distance ?
            if (squaredDistance > maxSquaredDistance)
                continue;
            // are we closer to the last closest point ?
            if (squaredDistance < minSquaredDistance) {
                nearestConnectionShape = connectionShape;
                minSquaredDistance = squaredDistance;
            }
        }
Ejemplo n.º 4
0
void Layout::add(KoShape *shape)
{
    Q_ASSERT(!m_children.contains(shape));
    TreeShape *tree = dynamic_cast<TreeShape*>(shape);
    if (tree) {
        tree->setZIndex(m_container->zIndex()+1);
        if (tree->nextShape()) {
            Q_ASSERT(m_children.contains(tree->nextShape()));
            int pos = m_children.indexOf(tree->nextShape());
            if (pos != 0) {
                TreeShape *prev = dynamic_cast<TreeShape*>(m_children[pos-1]);
                prev->setNextShape(shape);
            }
            m_children.insert(pos, shape);
        } else {
            if (!m_children.isEmpty()) {
                TreeShape *prev = dynamic_cast<TreeShape*>(m_children.last());
                prev->setNextShape(shape);
            }
            m_children.append(shape);
        }
        tree->setStructure(tree->structure());
    }

    KoConnectionShape *connector = dynamic_cast<KoConnectionShape*>(shape);
    if (connector) {
        Q_ASSERT(!m_connectors.contains(connector));
        m_connectors.append(shape);
        connector->setType(m_connectionType);
    }

    scheduleRelayout();
}
Ejemplo n.º 5
0
void ConnectionTool::paint(QPainter &painter, const KoViewConverter &converter)
{
    // get the correctly sized rect for painting handles
    QRectF handleRect = handlePaintRect(QPointF());

    painter.setRenderHint(QPainter::Antialiasing, true);

    if (m_currentStrategy) {
        painter.save();
        m_currentStrategy->paint(painter, converter);
        painter.restore();
    }

    QList<KoShape*> shapes = canvas()->shapeManager()->shapes();
    for (QList<KoShape*>::const_iterator end = shapes.constBegin(); end !=  shapes.constEnd(); ++end) {
        KoShape* shape = *end;
        if (!dynamic_cast<KoConnectionShape*>(shape)) {
            // only paint connection points of textShapes not inside a tos container and other shapes
            if (shape->shapeId() == TextShape_SHAPEID && dynamic_cast<KoTosContainer*>(shape->parent())) continue;

            painter.save();
            painter.setPen(Qt::black);
            QTransform transform = shape->absoluteTransformation(0);
            KoShape::applyConversion(painter, converter);
            // Draw all the connection points of the shape
            KoConnectionPoints connectionPoints = shape->connectionPoints();
            KoConnectionPoints::const_iterator cp = connectionPoints.constBegin();
            KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd();
            for(; cp != lastCp; ++cp) {
                if (shape == findNonConnectionShapeAtPosition(transform.map(cp.value().position)) ) {
                    handleRect.moveCenter(transform.map(cp.value().position));
                    painter.setBrush(cp.key() == m_activeHandle && shape == m_currentShape ?
                                     Qt::red : Qt::white);
                    painter.drawRect(handleRect);
                }
            }
            painter.restore();
        }
    }
    // paint connection points or connection handles depending
    // on the shape the mouse is currently
    if (m_currentShape && m_editMode == EditConnection) {
        KoConnectionShape *connectionShape = dynamic_cast<KoConnectionShape*>(m_currentShape);
        if (connectionShape) {
            int radius = handleRadius()+1;
            int handleCount = connectionShape->handleCount();
            for(int i = 0; i < handleCount; ++i) {
                painter.save();
                painter.setPen(Qt::blue);
                painter.setBrush(i == m_activeHandle ? Qt::red : Qt::white);
                painter.setTransform(connectionShape->absoluteTransformation(&converter) * painter.transform());
                connectionShape->paintHandle(painter, converter, i, radius);
                painter.restore();
            }
        }
    }
}
Ejemplo n.º 6
0
void ConnectionTool::repaintDecorations()
{
    const qreal radius = handleRadius();
    QRectF repaintRect;

    if (m_currentShape) {
        repaintRect = m_currentShape->boundingRect();
        canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius));
        KoConnectionShape * connectionShape = dynamic_cast<KoConnectionShape*>(m_currentShape);
        if (!m_resetPaint && m_currentShape->isVisible(true) && !connectionShape) {
            // only paint connection points of textShapes not inside a tos container and other shapes
            if ( !(m_currentShape->shapeId() == TextShape_SHAPEID &&
                    dynamic_cast<KoTosContainer*>(m_currentShape->parent())) ) {
                KoConnectionPoints connectionPoints = m_currentShape->connectionPoints();
                KoConnectionPoints::const_iterator cp = connectionPoints.constBegin();
                KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd();
                for(; cp != lastCp; ++cp) {
                    repaintRect = handleGrabRect(m_currentShape->shapeToDocument(cp.value().position));
                    canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius));
                }
            }
        }
        if (m_editMode == EditConnection) {
            if (connectionShape) {
                QPointF handlePos = connectionShape->handlePosition(m_activeHandle);
                handlePos = connectionShape->shapeToDocument(handlePos);
                repaintRect = handlePaintRect(handlePos);
                canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius));
            }
        }
    }
    if (m_resetPaint) {
        QList<KoShape*> shapes = canvas()->shapeManager()->shapes();
        for (QList<KoShape*>::const_iterator end = shapes.constBegin(); end !=  shapes.constEnd(); ++end) {
            KoShape* shape = *end;
            if (!dynamic_cast<KoConnectionShape*>(shape)) {
                // only paint connection points of textShapes not inside a tos container and other shapes
                if (shape->shapeId() == TextShape_SHAPEID && dynamic_cast<KoTosContainer*>(shape->parent()))
                    continue;

                KoConnectionPoints connectionPoints = shape->connectionPoints();
                KoConnectionPoints::const_iterator cp = connectionPoints.constBegin();
                KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd();
                for(; cp != lastCp; ++cp) {
                    repaintRect = handleGrabRect(shape->shapeToDocument(cp.value().position));
                    canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius));
                }
            }
        }
    }
    m_resetPaint = false;
}
Ejemplo n.º 7
0
void ConnectionTool::mouseReleaseEvent(KoPointerEvent *event)
{
    if (m_currentStrategy) {
        if (m_editMode == CreateConnection) {
            // check if connection handles have a minimal distance
            KoConnectionShape * connectionShape = dynamic_cast<KoConnectionShape*>(m_currentShape);
            Q_ASSERT(connectionShape);
            // get both handle positions in document coordinates
            QPointF p1 = connectionShape->shapeToDocument(connectionShape->handlePosition(0));
            QPointF p2 = connectionShape->shapeToDocument(connectionShape->handlePosition(1));
            int grabDistance = grabSensitivity();
            // use grabbing sensitivity as minimal distance threshold
            if (squareDistance(p1, p2) < grabDistance*grabDistance) {
                // minimal distance was not reached, so we have to undo the started work:
                // - cleanup and delete the strategy
                // - remove connection shape from shape manager and delete it
                // - reset edit mode to last state
                delete m_currentStrategy;
                m_currentStrategy = 0;
                repaintDecorations();
                canvas()->shapeManager()->remove(m_currentShape);
                setEditMode(m_editMode, connectionShape->firstShape(), connectionShape->firstConnectionId());
                repaintDecorations();
                delete connectionShape;
                return;
            } else {
                // finalize adding the new connection shape with an undo command
                KUndo2Command * cmd = canvas()->shapeController()->addShape(m_currentShape);
                canvas()->addCommand(cmd);
                setEditMode(EditConnection, m_currentShape, KoConnectionShape::StartHandle);
            }
        }
        m_currentStrategy->finishInteraction(event->modifiers());
        // TODO: Add parent command to KoInteractionStrategy::createCommand
        // so that we can have a single command to undo for the user
        KUndo2Command *command = m_currentStrategy->createCommand();
        if (command)
            canvas()->addCommand(command);
        delete m_currentStrategy;
        m_currentStrategy = 0;
    }
    updateStatusText();
}
Ejemplo n.º 8
0
void ConnectionTool::mousePressEvent(KoPointerEvent * event)
{

    if (!m_currentShape) {
        return;
    }

    KoShape * hitShape = findShapeAtPosition(event->point);
    int hitHandle = handleAtPoint(m_currentShape, event->point);

    if (m_editMode == EditConnection && hitHandle >= 0) {
        // create connection handle change strategy
        m_currentStrategy = new KoPathConnectionPointStrategy(this, dynamic_cast<KoConnectionShape*>(m_currentShape), hitHandle);
    } else if (m_editMode == EditConnectionPoint) {
        if (hitHandle >= KoConnectionPoint::FirstCustomConnectionPoint) {
            // start moving custom connection point
            m_currentStrategy = new MoveConnectionPointStrategy(m_currentShape, hitHandle, this);
        }
    } else if (m_editMode == CreateConnection) {
        // create new connection shape, connect it to the active connection point
        // and start editing the new connection
        // create the new connection shape
        KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value("KoConnectionShape");
        KoShape *shape = factory->createDefaultShape(canvas()->shapeController()->resourceManager());
        KoConnectionShape * connectionShape = dynamic_cast<KoConnectionShape*>(shape);
        if (!connectionShape) {
            delete shape;
            resetEditMode();
            return;
        }
        //set connection type
        connectionShape->setType(m_connectionType);
        // get the position of the connection point we start our connection from
        QPointF cp = m_currentShape->shapeToDocument(m_currentShape->connectionPoint(m_activeHandle).position);
        // move both handles to that point
        connectionShape->moveHandle(0, cp);
        connectionShape->moveHandle(1, cp);
        // connect the first handle of the connection shape to our connection point
        if (!connectionShape->connectFirst(m_currentShape, m_activeHandle)) {
            delete shape;
            resetEditMode();
            return;
        }
        //add connector label
        connectionShape->createTextShape(canvas()->shapeController()->resourceManager());
        connectionShape->setPlainText("");
        // create the connection edit strategy from the path tool
        m_currentStrategy = new KoPathConnectionPointStrategy(this, connectionShape, 1);
        if (!m_currentStrategy) {
            delete shape;
            resetEditMode();
            return;
        }
        // update our handle data
        setEditMode(m_editMode, shape, 1);
        // add connection shape to the shape manager so it gets painted
        canvas()->shapeManager()->addShape(connectionShape);
    } else {
        // pressing on a shape in idle mode switches to corresponding edit mode
        if (hitShape) {
            if (dynamic_cast<KoConnectionShape*>(hitShape)) {
                int hitHandle = handleAtPoint(hitShape, event->point);
                setEditMode(EditConnection, hitShape, hitHandle);
                if (hitHandle >= 0) {
                    // start editing connection shape
                    m_currentStrategy = new KoPathConnectionPointStrategy(this, dynamic_cast<KoConnectionShape*>(m_currentShape), m_activeHandle);
                }
            }
        } else {
            resetEditMode();
        }
    }
}