Commit 6ad28e04 authored by Jan Hambrecht's avatar Jan Hambrecht

gone are the days where KoShape::connectionPoints returned a simple list of points;

we now are required to always refer to connection points by their id;
renamed some variables and functions to reflect that change in out API
parent c00a0c4f
......@@ -588,7 +588,7 @@ KoShape *KoConnectionShape::firstShape() const
return d->shape1;
}
int KoConnectionShape::firstConnectionIndex() const
int KoConnectionShape::firstConnectionId() const
{
Q_D(const KoConnectionShape);
return d->connectionPointId1;
......@@ -600,7 +600,7 @@ KoShape *KoConnectionShape::secondShape() const
return d->shape2;
}
int KoConnectionShape::secondConnectionIndex() const
int KoConnectionShape::secondConnectionId() const
{
Q_D(const KoConnectionShape);
return d->connectionPointId2;
......
......@@ -82,11 +82,11 @@ public:
KoShape *firstShape() const;
/**
* Return the connection-index in the first shape we are connected to.
* Return the connection point id of the first shape we are connected to.
* In case we are not connected to a first shape the return value is undefined.
* @see firstShape(), KoShape::connectionPoints()
*/
int firstConnectionIndex() const;
int firstConnectionId() const;
/**
* Return the second shape this connection is attached to, or null if none.
......@@ -94,11 +94,11 @@ public:
KoShape *secondShape() const;
/**
* Return the connection-index in the second shape we are connected to.
* Return the connection point id of the second shape we are connected to.
* In case we are not connected to a second shape the return value is undefined.
* @see firstShape(), KoShape::connectionPoints()
*/
int secondConnectionIndex() const;
int secondConnectionId() const;
/**
* Finishes the loading of a connection.
......
......@@ -34,9 +34,9 @@ KoConnectionShapeLoadingUpdater::~KoConnectionShapeLoadingUpdater()
void KoConnectionShapeLoadingUpdater::update(KoShape * shape)
{
if (m_position == First) {
m_connectionShape->connectFirst(shape, m_connectionShape->firstConnectionIndex());
m_connectionShape->connectFirst(shape, m_connectionShape->firstConnectionId());
} else {
m_connectionShape->connectSecond(shape, m_connectionShape->secondConnectionIndex());
m_connectionShape->connectSecond(shape, m_connectionShape->secondConnectionId());
}
m_connectionShape->finishLoadingConnection();
}
......@@ -785,14 +785,18 @@ QPointF KoShape::connectionPoint(int connectionPointId) const
return p;
}
QList<QPointF> KoShape::connectionPoints() const
KoConnectionPoints KoShape::connectionPoints() const
{
Q_D(const KoShape);
QList<QPointF> points;
QSizeF s = size();
KoConnectionPoints points = d->connectors;
KoConnectionPoints::iterator point = points.begin();
KoConnectionPoints::iterator lastPoint = points.end();
// convert glue points to shape coordinates
foreach(const QPointF &cp, d->connectors)
points.append(QPointF(s.width() * cp.x(), s.height() * cp.y()));
for(; point != lastPoint; ++point) {
point->rx() *= s.width();
point->ry() *= s.height();
}
return points;
}
......
......@@ -61,6 +61,9 @@ class KoShapePrivate;
class KoFilterEffectStack;
class KoSnapData;
/// Connection point container with id, position
typedef QMap<int, QPointF> KoConnectionPoints;
/**
*
* Base class for all flake shapes. Shapes extend this class
......@@ -333,7 +336,7 @@ public:
* All the points are relative to the shape position, see absolutePosition().
* @return a list of the connectors that have been added to this shape.
*/
QList<QPointF> connectionPoints() const;
KoConnectionPoints connectionPoints() const;
/// Removes connection point with specified id
void removeConnectionPoint(int connectionPointId);
......
......@@ -89,7 +89,7 @@ public:
QTransform localMatrix; ///< the shapes local transformation matrix
QMap<int, QPointF> connectors; ///< glue point id and position in percent of size [0..1]
KoConnectionPoints connectors; ///< glue point id and position in percent of size [0..1]
KoShapeContainer *parent;
QSet<KoShapeManager *> shapeManagers;
......
......@@ -32,6 +32,8 @@
#include <float.h>
#include <math.h>
const int InvalidConnectionPointId = INT_MIN;
KoPathConnectionPointStrategy::KoPathConnectionPointStrategy(KoPathTool *tool,
KoConnectionShape *shape, int handleId)
: KoParameterChangeStrategy(tool, shape, handleId)
......@@ -42,10 +44,10 @@ KoPathConnectionPointStrategy::KoPathConnectionPointStrategy(KoPathTool *tool,
{
if (handleId == 0) {
m_oldConnectionShape = m_connectionShape->firstShape();
m_oldConnectionIndex = m_connectionShape->firstConnectionIndex();
m_oldConnectionId = m_connectionShape->firstConnectionId();
} else {
m_oldConnectionShape = m_connectionShape->secondShape();
m_oldConnectionIndex = m_connectionShape->secondConnectionIndex();
m_oldConnectionId = m_connectionShape->secondConnectionId();
}
}
......@@ -59,78 +61,70 @@ void KoPathConnectionPointStrategy::handleMouseMove(const QPointF &mouseLocation
const qreal MAX_DISTANCE_SQR = MAX_DISTANCE * MAX_DISTANCE;
m_newConnectionShape = 0;
m_newConnectionIndex = -1;
m_newConnectionId = InvalidConnectionPointId;
QRectF roi(mouseLocation - QPointF(MAX_DISTANCE, MAX_DISTANCE), QSizeF(2*MAX_DISTANCE, 2*MAX_DISTANCE));
QList<KoShape*> shapes = m_tool->canvas()->shapeManager()->shapesAt(roi, true);
if (shapes.count() < 2) {
// we are not near any other shape, so remove the corresponding connection
if (m_handleId == 0)
m_connectionShape->connectFirst(0, -1);
m_connectionShape->connectFirst(0, InvalidConnectionPointId);
else
m_connectionShape->connectSecond(0, -1);
m_connectionShape->connectSecond(0, InvalidConnectionPointId);
KoParameterChangeStrategy::handleMouseMove(mouseLocation, modifiers);
} else {
qreal minimalDistance = DBL_MAX;
QPointF nearestPoint;
KoShape *nearestShape = 0;
int nearestPointIndex = -1;
bool nearestAlreadyPresent = false;
int nearestPointId = InvalidConnectionPointId;
foreach(KoShape* shape, shapes) {
// we do not want to connect to ourself
if (shape == m_connectionShape)
continue;
bool alreadyPresent = true;
QTransform m = shape->absoluteTransformation(0);
QList<QPointF> connectionPoints = shape->connectionPoints();
KoConnectionPoints connectionPoints = shape->connectionPoints();
if (! connectionPoints.count()) {
QSizeF size = shape->size();
connectionPoints.append(QPointF(0.0, 0.0));
connectionPoints.append(QPointF(size.width(), 0.0));
connectionPoints.append(QPointF(size.width(), size.height()));
connectionPoints.append(QPointF(0.0, size.height()));
connectionPoints.append(0.5 * (connectionPoints[0] + connectionPoints[1]));
connectionPoints.append(0.5 * (connectionPoints[1] + connectionPoints[2]));
connectionPoints.append(0.5 * (connectionPoints[2] + connectionPoints[3]));
connectionPoints.append(0.5 * (connectionPoints[3] + connectionPoints[0]));
alreadyPresent = false;
connectionPoints[-1] = QPointF(0.0, 0.0);
connectionPoints[-2] = QPointF(size.width(), 0.0);
connectionPoints[-3] = QPointF(size.width(), size.height());
connectionPoints[-4] = QPointF(0.0, size.height());
connectionPoints[-5] = 0.5 * (connectionPoints[-1] + connectionPoints[-2]);
connectionPoints[-6] = 0.5 * (connectionPoints[-2] + connectionPoints[-3]);
connectionPoints[-7] = 0.5 * (connectionPoints[-3] + connectionPoints[-4]);
connectionPoints[-8] = 0.5 * (connectionPoints[-4] + connectionPoints[-1]);
}
QPointF localMousePosition = shape->absoluteTransformation(0).inverted().map(mouseLocation);
int connectionPointCount = connectionPoints.count();
for (int i = 0; i < connectionPointCount; ++i) {
QPointF difference = localMousePosition - connectionPoints[i];
KoConnectionPoints::const_iterator cp = connectionPoints.constBegin();
KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd();
for(; cp != lastCp; ++cp) {
QPointF difference = localMousePosition - cp.value();
qreal distance = difference.x() * difference.x() + difference.y() * difference.y();
if (distance > MAX_DISTANCE_SQR)
continue;
if (distance < minimalDistance) {
nearestShape = shape;
nearestPoint = connectionPoints[i];
nearestPointIndex = i;
nearestAlreadyPresent = alreadyPresent;
nearestPoint = cp.value();
nearestPointId = cp.key();
minimalDistance = distance;
}
}
}
if (nearestShape) {
if (! nearestAlreadyPresent) {
//nearestShape->addConnectionPoint(nearestPoint);
nearestPointIndex = -1;
}
nearestPoint = nearestShape->absoluteTransformation(0).map(nearestPoint);
} else {
nearestPoint = mouseLocation;
nearestPointIndex = -1;
}
m_newConnectionShape = nearestShape;
m_newConnectionIndex = nearestPointIndex;
m_newConnectionId = nearestPointId;
if (m_handleId == 0)
m_connectionShape->connectFirst(nearestShape, nearestPointIndex);
m_connectionShape->connectFirst(nearestShape, nearestPointId);
else
m_connectionShape->connectSecond(nearestShape, nearestPointIndex);
m_connectionShape->connectSecond(nearestShape, nearestPointId);
KoParameterChangeStrategy::handleMouseMove(nearestPoint, modifiers);
}
}
......@@ -143,19 +137,18 @@ void KoPathConnectionPointStrategy::finishInteraction(Qt::KeyboardModifiers modi
QUndoCommand* KoPathConnectionPointStrategy::createCommand()
{
// check if we connect to a shape and if the connection point is already present
if (m_newConnectionShape && m_newConnectionIndex == -1) {
if (m_newConnectionShape && m_newConnectionId < 0 && m_newConnectionId != InvalidConnectionPointId) {
// map handle position into document coordinates
QPointF p = m_connectionShape->shapeToDocument(m_connectionShape->handlePosition(m_handleId));
// and add as connection point in shape coordinates
m_newConnectionShape->addConnectionPoint(m_newConnectionShape->absoluteTransformation(0).inverted().map(p));
m_newConnectionIndex = m_newConnectionShape->connectionPoints().count() - 1;
m_newConnectionId = m_newConnectionShape->addConnectionPoint(m_newConnectionShape->absoluteTransformation(0).inverted().map(p));
}
// set the connection corresponding to the handle we are working on
if (m_handleId == 0)
m_connectionShape->connectFirst(m_newConnectionShape, m_newConnectionIndex);
m_connectionShape->connectFirst(m_newConnectionShape, m_newConnectionId);
else
m_connectionShape->connectSecond(m_newConnectionShape, m_newConnectionIndex);
m_connectionShape->connectSecond(m_newConnectionShape, m_newConnectionId);
// TODO create a connection command
return KoParameterChangeStrategy::createCommand();
......
......@@ -50,9 +50,9 @@ private:
int m_handleId; ///< the id of the control point
QPointF m_startPoint; ///< the starting position of the control point
KoShape *m_oldConnectionShape;
int m_oldConnectionIndex;
int m_oldConnectionId;
KoShape *m_newConnectionShape;
int m_newConnectionIndex;
int m_newConnectionId;
};
......
......@@ -85,7 +85,7 @@ void ConnectionTool::paint(QPainter &painter, const KoViewConverter &converter)
// Apply the conversion make by the matrix transformation
QTransform transform = m_lastShapeOn->absoluteTransformation(0);
KoShape::applyConversion(painter, converter);
QPointF pointSelected = m_lastShapeOn->connectionPoints().value(getConnectionIndex(m_lastShapeOn, m_mouse));
QPointF pointSelected = m_lastShapeOn->connectionPoints().value(getConnectionId(m_lastShapeOn, m_mouse));
handleRect.moveCenter(transform.map(pointSelected));
painter.fillRect(handleRect, QColor(Qt::blue));
......@@ -160,7 +160,7 @@ void ConnectionTool::mousePressEvent(KoPointerEvent *event)
KoConnectionShape * connectionShapeTest = dynamic_cast<KoConnectionShape*>(tempShape);
if(isInRoi()) {
m_shape1 = tempShape;
m_firstHandleIndex = getConnectionIndex(tempShape, m_mouse);
m_firstHandleIndex = getConnectionId(tempShape, m_mouse);
m_connectionShape->connectFirst(m_shape1, m_firstHandleIndex);
m_isTied->first = true;
......@@ -191,7 +191,7 @@ void ConnectionTool::mousePressEvent(KoPointerEvent *event)
if(tempShape != 0) {
if(isInRoi()) {
// If everything is good, we connect the line to the shape
m_connectionShape->connectSecond(tempShape, getConnectionIndex(tempShape, m_mouse));
m_connectionShape->connectSecond(tempShape, getConnectionId(tempShape, m_mouse));
m_isTied->second = true;
} else {
m_connectionShape->connectSecond(tempShape, 0);
......@@ -201,7 +201,7 @@ void ConnectionTool::mousePressEvent(KoPointerEvent *event)
// If the cursor points the background
if(isInRoi()) {
// If everything is good, we connect the line to the shape
m_connectionShape->connectSecond(tempShape, getConnectionIndex(tempShape, m_mouse));
m_connectionShape->connectSecond(tempShape, getConnectionId(tempShape, m_mouse));
m_isTied->second = true;
} else {
m_connectionShape->moveHandle(m_connectionShape->handleCount(), event->point);
......@@ -234,7 +234,7 @@ void ConnectionTool::mouseMoveEvent(KoPointerEvent *event)
if(m_connectionShape != 0) {
if(isInRoi()) {
// Make the connection to the specific point
m_connectionShape->connectSecond(m_lastShapeOn, getConnectionIndex(m_lastShapeOn, m_mouse));
m_connectionShape->connectSecond(m_lastShapeOn, getConnectionId(m_lastShapeOn, m_mouse));
m_connectionShape->updateConnections();
} else if(m_shapeOn != 0) {
// Make the connection to the first handle of the shape
......@@ -263,9 +263,9 @@ void ConnectionTool::mouseMoveEvent(KoPointerEvent *event)
// We have to know what handle is actually moving
// Connection with the specific handle
if(m_activeHandle == 0){
m_lastConnectionShapeOn->connectFirst(m_lastShapeOn, getConnectionIndex(m_lastShapeOn, m_mouse));
m_lastConnectionShapeOn->connectFirst(m_lastShapeOn, getConnectionId(m_lastShapeOn, m_mouse));
}else if(m_activeHandle == 1){
m_lastConnectionShapeOn->connectSecond(m_lastShapeOn, getConnectionIndex(m_lastShapeOn, m_mouse));
m_lastConnectionShapeOn->connectSecond(m_lastShapeOn, getConnectionId(m_lastShapeOn, m_mouse));
}
}
}else if(m_shapeOn != 0 ){
......@@ -289,7 +289,7 @@ void ConnectionTool::mouseReleaseEvent(KoPointerEvent *event)
if(event->modifiers() & Qt::ControlModifier) {
if(isInRoi()) {
// delete a connection Point
m_shapeOn->removeConnectionPoint(getConnectionIndex(m_lastShapeOn, m_mouse));
m_shapeOn->removeConnectionPoint(getConnectionId(m_lastShapeOn, m_mouse));
}else{
// add a connection Point
m_shapeOn = canvas()->shapeManager()->shapeAt(event->point);
......@@ -342,49 +342,48 @@ void ConnectionTool::updateConnections()
KoShape *shape1 = m_connectionShape->firstShape();
KoShape *shape2 = m_connectionShape->secondShape();
if(!m_isTied->first){
m_connectionShape->connectFirst(shape1 , getConnectionIndex(shape1, shape2->absolutePosition()));
m_connectionShape->connectFirst(shape1 , getConnectionId(shape1, shape2->absolutePosition()));
}
if(!m_isTied->second){
m_connectionShape->connectSecond(shape2 , getConnectionIndex(shape2, shape1->absolutePosition()));
m_connectionShape->connectSecond(shape2 , getConnectionId(shape2, shape1->absolutePosition()));
}
// If only the first item of the connection is a shape
} else if(m_connectionShape->firstShape()) {
KoShape *shape = m_connectionShape->firstShape();
QPointF point = m_connectionShape->handlePosition(m_connectionShape->handleCount()) + m_connectionShape->absolutePosition();
if(!m_isTied->first) {
m_connectionShape->connectFirst(shape , getConnectionIndex(shape, point));
m_connectionShape->connectFirst(shape , getConnectionId(shape, point));
}
// If only the second item of the connection is a shape
} else if(m_connectionShape->secondShape()) {
KoShape* shape = m_connectionShape->secondShape();
QPointF point = m_connectionShape->handlePosition(0) + m_connectionShape->absolutePosition();
if(!m_isTied->second)
m_connectionShape->connectSecond(shape , getConnectionIndex(shape, point));
m_connectionShape->connectSecond(shape , getConnectionId(shape, point));
}
// The connection is now done, so update and put everything to 0
m_connectionShape->updateConnections();
}
int ConnectionTool::getConnectionIndex(KoShape * shape, QPointF point)
int ConnectionTool::getConnectionId(KoShape * shape, QPointF point)
{
float minDistance = HUGE_VAL;
int nearestPointIndex = -1, i;
// Get all the points
QList<QPointF> connectionPoints = shape->connectionPoints();
int connectionPointsCount = connectionPoints.count();
int nearestPointId = -1, i;
point = shape->documentToShape(point);
// Find the nearest point and stock the index
for(i = 0; i < connectionPointsCount; i++)
{
float distance = distanceSquare(connectionPoints[i], point);
// Get all the points
KoConnectionPoints connectionPoints = shape->connectionPoints();
KoConnectionPoints::const_iterator cp = connectionPoints.constBegin();
KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd();
// Find the nearest point and stock the id
for(; cp != lastCp; ++cp) {
float distance = distanceSquare(cp.value(), point);
if(distance < minDistance) {
minDistance = distance;
nearestPointIndex = i;
nearestPointId = cp.key();
}
}
// return the nearest point index
return nearestPointIndex;
// return the nearest point id
return nearestPointId;
}
float ConnectionTool::distanceSquare(QPointF p1, QPointF p2)
......
......@@ -68,7 +68,7 @@ public:
* @param point The point to connect
* @return The index of the nearest point
*/
int getConnectionIndex( KoShape * shape, QPointF point );
int getConnectionId( KoShape * shape, QPointF point );
/**
* @brief Return the square of the absolute distance between p1 and p2
*
......
......@@ -198,7 +198,7 @@ KoShape* Layout::proposePosition(KoShape* shape)
QPointF pos;
switch (m_structure) {
case TreeShape::OrgDown:
pos = shape->shapeToDocument(shape->connectionPoints()[0]);
pos = shape->shapeToDocument(shape->connectionPoints().value(0));
pos = m_container->documentToShape(pos);
nextShape = m_children.first();
......@@ -211,7 +211,7 @@ KoShape* Layout::proposePosition(KoShape* shape)
nextShape = 0;
break;
case TreeShape::OrgUp:
pos = shape->shapeToDocument(shape->connectionPoints()[2]);
pos = shape->shapeToDocument(shape->connectionPoints().value(2));
pos = m_container->documentToShape(pos);
nextShape = m_children.first();
......@@ -224,7 +224,7 @@ KoShape* Layout::proposePosition(KoShape* shape)
nextShape = 0;
break;
case TreeShape::OrgLeft:
pos = shape->shapeToDocument(shape->connectionPoints()[1]);
pos = shape->shapeToDocument(shape->connectionPoints().value(1));
pos = m_container->documentToShape(pos);
nextShape = m_children.first();
......@@ -237,7 +237,7 @@ KoShape* Layout::proposePosition(KoShape* shape)
nextShape = 0;
break;
case TreeShape::OrgRight:
pos = shape->shapeToDocument(shape->connectionPoints()[3]);
pos = shape->shapeToDocument(shape->connectionPoints().value(3));
pos = m_container->documentToShape(pos);
nextShape = m_children.first();
......
......@@ -168,11 +168,11 @@ TreeShape* TreeShapeMoveStrategy::proposeParent()
qreal minDistance = 10000, distance;
// down
pos = m_movable->shapeToDocument(m_movable->connectionPoints()[0]);
pos = m_movable->shapeToDocument(m_movable->connectionPoints().value(0));
rect = QRectF(pos-QPointF(0,length), QSizeF(1,length));
tree = propose(rect, TreeShape::OrgDown);
if (tree) {
treePos = tree->root()->shapeToDocument(tree->root()->connectionPoints()[2]);
treePos = tree->root()->shapeToDocument(tree->root()->connectionPoints().value(2));
distance = (pos.x() - treePos.x())*(pos.x() - treePos.x())
+ (pos.y() - treePos.y())*(pos.y() - treePos.y());
if (distance<minDistance) {
......@@ -182,11 +182,11 @@ TreeShape* TreeShapeMoveStrategy::proposeParent()
}
// up
pos = m_movable->shapeToDocument(m_movable->connectionPoints()[2]);
pos = m_movable->shapeToDocument(m_movable->connectionPoints().value(2));
rect = QRectF(pos, QSizeF(1,length));
tree = propose(rect, TreeShape::OrgUp);
if (tree) {
treePos = tree->root()->shapeToDocument(tree->root()->connectionPoints()[0]);
treePos = tree->root()->shapeToDocument(tree->root()->connectionPoints().value(0));
distance = (pos.x() - treePos.x())*(pos.x() - treePos.x())
+ (pos.y() - treePos.y())*(pos.y() - treePos.y());
if (distance<minDistance) {
......@@ -196,11 +196,11 @@ TreeShape* TreeShapeMoveStrategy::proposeParent()
}
// right
pos = m_movable->shapeToDocument(m_movable->connectionPoints()[3]);
pos = m_movable->shapeToDocument(m_movable->connectionPoints().value(3));
rect = QRectF(pos-QPointF(length,0), QSizeF(length,1));
tree = propose(rect, TreeShape::OrgRight);
if (tree) {
treePos = tree->root()->shapeToDocument(tree->root()->connectionPoints()[1]);
treePos = tree->root()->shapeToDocument(tree->root()->connectionPoints().value(1));
distance = (pos.x() - treePos.x())*(pos.x() - treePos.x())
+ (pos.y() - treePos.y())*(pos.y() - treePos.y());
if (distance<minDistance) {
......@@ -210,7 +210,7 @@ TreeShape* TreeShapeMoveStrategy::proposeParent()
}
// left
pos = m_movable->shapeToDocument(m_movable->connectionPoints()[1]);
pos = m_movable->shapeToDocument(m_movable->connectionPoints().value(1));
rect = QRectF(pos, QSizeF(length,1));
tree = propose(rect, TreeShape::OrgLeft);
if (tree) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment