Changeset View
Changeset View
Standalone View
Standalone View
libs/flake/KoConnectionShape.cpp
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Line(s) | 40 | KoConnectionShapePrivate::KoConnectionShapePrivate(KoConnectionShape *q) | |||
---|---|---|---|---|---|
44 | connectionPointId1(-1), | 44 | connectionPointId1(-1), | ||
45 | connectionPointId2(-1), | 45 | connectionPointId2(-1), | ||
46 | connectionType(KoConnectionShape::Standard), | 46 | connectionType(KoConnectionShape::Standard), | ||
47 | forceUpdate(false), | 47 | forceUpdate(false), | ||
48 | hasCustomPath(false) | 48 | hasCustomPath(false) | ||
49 | { | 49 | { | ||
50 | } | 50 | } | ||
51 | 51 | | |||
52 | KoConnectionShapePrivate::KoConnectionShapePrivate(const KoConnectionShapePrivate &rhs, KoConnectionShape *q) | ||||
53 | : KoParameterShapePrivate(rhs, q), | ||||
54 | path(rhs.path), | ||||
55 | shape1(0), // FIXME: it should point to the new shapes!!! | ||||
56 | shape2(0), // FIXME: it should point to the new shapes!!! | ||||
57 | connectionPointId1(rhs.connectionPointId1), | ||||
58 | connectionPointId2(rhs.connectionPointId2), | ||||
59 | connectionType(rhs.connectionType), | ||||
60 | forceUpdate(rhs.forceUpdate), | ||||
61 | hasCustomPath(rhs.hasCustomPath) | ||||
62 | { | ||||
63 | | ||||
64 | } | ||||
65 | | ||||
52 | QPointF KoConnectionShapePrivate::escapeDirection(int handleId) const | 66 | QPointF KoConnectionShapePrivate::escapeDirection(int handleId) const | ||
53 | { | 67 | { | ||
54 | Q_Q(const KoConnectionShape); | 68 | Q_Q(const KoConnectionShape); | ||
55 | QPointF direction; | 69 | QPointF direction; | ||
56 | if (handleConnected(handleId)) { | 70 | if (handleConnected(handleId)) { | ||
57 | KoShape *attachedShape = handleId == KoConnectionShape::StartHandle ? shape1 : shape2; | 71 | KoShape *attachedShape = handleId == KoConnectionShape::StartHandle ? shape1 : shape2; | ||
58 | int connectionPointId = handleId == KoConnectionShape::StartHandle ? connectionPointId1 : connectionPointId2; | 72 | int connectionPointId = handleId == KoConnectionShape::StartHandle ? connectionPointId1 : connectionPointId2; | ||
59 | KoConnectionPoint::EscapeDirection ed = attachedShape->connectionPoint(connectionPointId).escapeDirection; | 73 | KoConnectionPoint::EscapeDirection ed = attachedShape->connectionPoint(connectionPointId).escapeDirection; | ||
60 | if (ed == KoConnectionPoint::AllDirections) { | 74 | if (ed == KoConnectionPoint::AllDirections) { | ||
61 | QPointF handlePoint = q->shapeToDocument(handles[handleId]); | 75 | QPointF handlePoint = q->shapeToDocument(handles[handleId]); | ||
62 | QPointF centerPoint = attachedShape->absolutePosition(KoFlake::CenteredPosition); | 76 | QPointF centerPoint = attachedShape->absolutePosition(KoFlake::Center); | ||
63 | 77 | | |||
64 | /* | 78 | /* | ||
65 | * Determine the best escape direction from the position of the handle point | 79 | * Determine the best escape direction from the position of the handle point | ||
66 | * and the position and orientation of the attached shape. | 80 | * and the position and orientation of the attached shape. | ||
67 | * The idea is to define 4 sectors, one for each edge of the attached shape. | 81 | * The idea is to define 4 sectors, one for each edge of the attached shape. | ||
68 | * Each sector starts at the center point of the attached shape and has it | 82 | * Each sector starts at the center point of the attached shape and has it | ||
69 | * left and right edge going through the two points which define the edge. | 83 | * left and right edge going through the two points which define the edge. | ||
70 | * Then we check which sector contains our handle point, for which we can | 84 | * Then we check which sector contains our handle point, for which we can | ||
71 | * simply calculate the corresponding direction which is orthogonal to the | 85 | * simply calculate the corresponding direction which is orthogonal to the | ||
72 | * corresponding bounding box edge. | 86 | * corresponding bounding box edge. | ||
73 | * From that we derive the escape direction from looking at the main coordinate | 87 | * From that we derive the escape direction from looking at the main coordinate | ||
74 | * of the orthogonal direction. | 88 | * of the orthogonal direction. | ||
75 | */ | 89 | */ | ||
76 | // define our edge points in the right order | 90 | // define our edge points in the right order | ||
77 | const KoFlake::Position corners[4] = { | 91 | const KoFlake::AnchorPosition corners[4] = { | ||
78 | KoFlake::BottomRightCorner, | 92 | KoFlake::BottomRight, | ||
79 | KoFlake::BottomLeftCorner, | 93 | KoFlake::BottomLeft, | ||
80 | KoFlake::TopLeftCorner, | 94 | KoFlake::TopLeft, | ||
81 | KoFlake::TopRightCorner | 95 | KoFlake::TopRight | ||
82 | }; | 96 | }; | ||
83 | 97 | | |||
84 | QPointF vHandle = handlePoint-centerPoint; | 98 | QPointF vHandle = handlePoint-centerPoint; | ||
85 | for (int i = 0; i < 4; ++i) { | 99 | for (int i = 0; i < 4; ++i) { | ||
86 | // first point of bounding box edge | 100 | // first point of bounding box edge | ||
87 | QPointF p1 = attachedShape->absolutePosition(corners[i]); | 101 | QPointF p1 = attachedShape->absolutePosition(corners[i]); | ||
88 | // second point of bounding box edge | 102 | // second point of bounding box edge | ||
89 | QPointF p2 = attachedShape->absolutePosition(corners[(i+1)%4]); | 103 | QPointF p2 = attachedShape->absolutePosition(corners[(i+1)%4]); | ||
Show All 21 Lines | |||||
111 | } else { | 125 | } else { | ||
112 | direction.rx() = 0.0; | 126 | direction.rx() = 0.0; | ||
113 | direction.ry() = vDir.y() > 0 ? 1.0 : -1.0; | 127 | direction.ry() = vDir.y() > 0 ? 1.0 : -1.0; | ||
114 | } | 128 | } | ||
115 | break; | 129 | break; | ||
116 | } | 130 | } | ||
117 | } else if (ed == KoConnectionPoint::HorizontalDirections) { | 131 | } else if (ed == KoConnectionPoint::HorizontalDirections) { | ||
118 | QPointF handlePoint = q->shapeToDocument(handles[handleId]); | 132 | QPointF handlePoint = q->shapeToDocument(handles[handleId]); | ||
119 | QPointF centerPoint = attachedShape->absolutePosition(KoFlake::CenteredPosition); | 133 | QPointF centerPoint = attachedShape->absolutePosition(KoFlake::Center); | ||
120 | // use horizontal direction pointing away from center point | 134 | // use horizontal direction pointing away from center point | ||
121 | if (handlePoint.x() < centerPoint.x()) | 135 | if (handlePoint.x() < centerPoint.x()) | ||
122 | direction = QPointF(-1.0, 0.0); | 136 | direction = QPointF(-1.0, 0.0); | ||
123 | else | 137 | else | ||
124 | direction = QPointF(1.0, 0.0); | 138 | direction = QPointF(1.0, 0.0); | ||
125 | } else if (ed == KoConnectionPoint::VerticalDirections) { | 139 | } else if (ed == KoConnectionPoint::VerticalDirections) { | ||
126 | QPointF handlePoint = q->shapeToDocument(handles[handleId]); | 140 | QPointF handlePoint = q->shapeToDocument(handles[handleId]); | ||
127 | QPointF centerPoint = attachedShape->absolutePosition(KoFlake::CenteredPosition); | 141 | QPointF centerPoint = attachedShape->absolutePosition(KoFlake::Center); | ||
128 | // use vertical direction pointing away from center point | 142 | // use vertical direction pointing away from center point | ||
129 | if (handlePoint.y() < centerPoint.y()) | 143 | if (handlePoint.y() < centerPoint.y()) | ||
130 | direction = QPointF(0.0, -1.0); | 144 | direction = QPointF(0.0, -1.0); | ||
131 | else | 145 | else | ||
132 | direction = QPointF(0.0, 1.0); | 146 | direction = QPointF(0.0, 1.0); | ||
133 | } else if (ed == KoConnectionPoint::LeftDirection) { | 147 | } else if (ed == KoConnectionPoint::LeftDirection) { | ||
134 | direction = QPointF(-1.0, 0.0); | 148 | direction = QPointF(-1.0, 0.0); | ||
135 | } else if (ed == KoConnectionPoint::RightDirection) { | 149 | } else if (ed == KoConnectionPoint::RightDirection) { | ||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Line(s) | 307 | if (updateHandles || d->forceUpdate) { | |||
294 | update(); // ugly, for repainting the connection we just changed | 308 | update(); // ugly, for repainting the connection we just changed | ||
295 | updatePath(QSizeF()); | 309 | updatePath(QSizeF()); | ||
296 | update(); // ugly, for repainting the connection we just changed | 310 | update(); // ugly, for repainting the connection we just changed | ||
297 | d->forceUpdate = false; | 311 | d->forceUpdate = false; | ||
298 | } | 312 | } | ||
299 | } | 313 | } | ||
300 | 314 | | |||
301 | KoConnectionShape::KoConnectionShape() | 315 | KoConnectionShape::KoConnectionShape() | ||
302 | : KoParameterShape(*(new KoConnectionShapePrivate(this))) | 316 | : KoParameterShape(new KoConnectionShapePrivate(this)) | ||
303 | { | 317 | { | ||
304 | Q_D(KoConnectionShape); | 318 | Q_D(KoConnectionShape); | ||
305 | d->handles.push_back(QPointF(0, 0)); | 319 | d->handles.push_back(QPointF(0, 0)); | ||
306 | d->handles.push_back(QPointF(140, 140)); | 320 | d->handles.push_back(QPointF(140, 140)); | ||
307 | 321 | | |||
308 | moveTo(d->handles[StartHandle]); | 322 | moveTo(d->handles[StartHandle]); | ||
309 | lineTo(d->handles[EndHandle]); | 323 | lineTo(d->handles[EndHandle]); | ||
310 | 324 | | |||
311 | updatePath(QSizeF(140, 140)); | 325 | updatePath(QSizeF(140, 140)); | ||
312 | 326 | | |||
313 | clearConnectionPoints(); | 327 | clearConnectionPoints(); | ||
314 | } | 328 | } | ||
315 | 329 | | |||
330 | KoConnectionShape::KoConnectionShape(const KoConnectionShape &rhs) | ||||
331 | : KoParameterShape(new KoConnectionShapePrivate(*rhs.d_func(), this)) | ||||
332 | { | ||||
333 | } | ||||
334 | | ||||
335 | | ||||
316 | KoConnectionShape::~KoConnectionShape() | 336 | KoConnectionShape::~KoConnectionShape() | ||
317 | { | 337 | { | ||
318 | Q_D(KoConnectionShape); | 338 | Q_D(KoConnectionShape); | ||
319 | if (d->shape1) | 339 | if (d->shape1) | ||
320 | d->shape1->removeDependee(this); | 340 | d->shape1->removeDependee(this); | ||
321 | if (d->shape2) | 341 | if (d->shape2) | ||
322 | d->shape2->removeDependee(this); | 342 | d->shape2->removeDependee(this); | ||
323 | } | 343 | } | ||
324 | 344 | | |||
345 | KoShape *KoConnectionShape::cloneShape() const | ||||
346 | { | ||||
347 | return new KoConnectionShape(*this); | ||||
348 | } | ||||
349 | | ||||
325 | void KoConnectionShape::saveOdf(KoShapeSavingContext & context) const | 350 | void KoConnectionShape::saveOdf(KoShapeSavingContext & context) const | ||
326 | { | 351 | { | ||
327 | Q_D(const KoConnectionShape); | 352 | Q_D(const KoConnectionShape); | ||
328 | context.xmlWriter().startElement("draw:connector"); | 353 | context.xmlWriter().startElement("draw:connector"); | ||
329 | saveOdfAttributes(context, OdfMandatories | OdfAdditionalAttributes); | 354 | saveOdfAttributes(context, OdfMandatories | OdfAdditionalAttributes); | ||
330 | 355 | | |||
331 | switch (d->connectionType) { | 356 | switch (d->connectionType) { | ||
332 | case Lines: | 357 | case Lines: | ||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Line(s) | 399 | { | |||
440 | QStringList skewValues = skew.simplified().split(' ', QString::SkipEmptyParts); | 465 | QStringList skewValues = skew.simplified().split(' ', QString::SkipEmptyParts); | ||
441 | // TODO apply skew values once we support them | 466 | // TODO apply skew values once we support them | ||
442 | 467 | | |||
443 | // load the path data if there is any | 468 | // load the path data if there is any | ||
444 | d->hasCustomPath = element.hasAttributeNS(KoXmlNS::svg, "d"); | 469 | d->hasCustomPath = element.hasAttributeNS(KoXmlNS::svg, "d"); | ||
445 | if (d->hasCustomPath) { | 470 | if (d->hasCustomPath) { | ||
446 | KoPathShapeLoader loader(this); | 471 | KoPathShapeLoader loader(this); | ||
447 | loader.parseSvg(element.attributeNS(KoXmlNS::svg, "d"), true); | 472 | loader.parseSvg(element.attributeNS(KoXmlNS::svg, "d"), true); | ||
448 | if (m_subpaths.size() > 0) { | 473 | if (d->subpaths.size() > 0) { | ||
449 | QRectF viewBox = loadOdfViewbox(element); | 474 | QRectF viewBox = loadOdfViewbox(element); | ||
450 | if (viewBox.isEmpty()) { | 475 | if (viewBox.isEmpty()) { | ||
451 | // there should be a viewBox to transform the path data | 476 | // there should be a viewBox to transform the path data | ||
452 | // if there is none, use the bounding rectangle of the parsed path | 477 | // if there is none, use the bounding rectangle of the parsed path | ||
453 | viewBox = outline().boundingRect(); | 478 | viewBox = outline().boundingRect(); | ||
454 | } | 479 | } | ||
455 | // convert path to viewbox coordinates to have a bounding rect of (0,0 1x1) | 480 | // convert path to viewbox coordinates to have a bounding rect of (0,0 1x1) | ||
456 | // which can later be fitted back into the target rect once we have all | 481 | // which can later be fitted back into the target rect once we have all | ||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Line(s) | 514 | if (loadingFinished1 && loadingFinished2) { | |||
498 | if (d->handleConnected(EndHandle)) { | 523 | if (d->handleConnected(EndHandle)) { | ||
499 | if (d->shape2->hasConnectionPoint(d->connectionPointId2)) { | 524 | if (d->shape2->hasConnectionPoint(d->connectionPointId2)) { | ||
500 | p2 = d->shape2->absoluteTransformation(0).map(d->shape2->connectionPoint(d->connectionPointId2).position); | 525 | p2 = d->shape2->absoluteTransformation(0).map(d->shape2->connectionPoint(d->connectionPointId2).position); | ||
501 | } | 526 | } | ||
502 | } else { | 527 | } else { | ||
503 | p2 = d->handles[EndHandle]; | 528 | p2 = d->handles[EndHandle]; | ||
504 | } | 529 | } | ||
505 | 530 | | |||
506 | QPointF relativeBegin = m_subpaths.first()->first()->point(); | 531 | QPointF relativeBegin = d->subpaths.first()->first()->point(); | ||
507 | QPointF relativeEnd = m_subpaths.last()->last()->point(); | 532 | QPointF relativeEnd = d->subpaths.last()->last()->point(); | ||
508 | 533 | | |||
509 | QPointF diffRelative(relativeBegin - relativeEnd); | 534 | QPointF diffRelative(relativeBegin - relativeEnd); | ||
510 | QPointF diffAbsolute(p1 - p2); | 535 | QPointF diffAbsolute(p1 - p2); | ||
511 | 536 | | |||
512 | qreal factorX = diffRelative.x() ? diffAbsolute.x() / diffRelative.x(): 1.0; | 537 | qreal factorX = diffRelative.x() ? diffAbsolute.x() / diffRelative.x(): 1.0; | ||
513 | qreal factorY = diffRelative.y() ? diffAbsolute.y() / diffRelative.y(): 1.0; | 538 | qreal factorY = diffRelative.y() ? diffAbsolute.y() / diffRelative.y(): 1.0; | ||
514 | 539 | | |||
515 | p1.setX(p1.x() - relativeBegin.x() * factorX); | 540 | p1.setX(p1.x() - relativeBegin.x() * factorX); | ||
▲ Show 20 Lines • Show All 239 Lines • Show Last 20 Lines |