36 |
36 |
37 //Uncomment next define in order to get more debug prints. |
37 //Uncomment next define in order to get more debug prints. |
38 //Similar define exists also in the engine side. |
38 //Similar define exists also in the engine side. |
39 //#define HBANCHORLAYOUT_DEBUG |
39 //#define HBANCHORLAYOUT_DEBUG |
40 |
40 |
41 #ifdef HBANCHORLAYOUT_DEBUG |
|
42 #ifndef Q_WS_S60 |
|
43 #include "hbspaceritem_p.h" |
|
44 #endif |
|
45 #endif |
|
46 |
|
47 /*! |
41 /*! |
48 \class HbAnchorLayout |
42 \class HbAnchorLayout |
49 \brief HbAnchorLayout manages geometries of its child items with anchors |
43 \brief HbAnchorLayout manages geometries of its child items with anchors |
50 that connect the layout items with each other. |
44 that connect the layout items with each other. |
51 |
45 |
52 It also allows layout items to be missing and can fix anchor attachments. |
46 It also allows layout items to be missing and can fix anchor attachments. |
53 Here are some simple rules how anchor fixation can be created (the example |
47 Here is an example and some simple rules how anchor fixing works (the example is |
54 is only for horizontal direction - the same needs to be done for portrait as well). |
48 only for horizontal direction - the same needs to be done for portrait as well). |
55 |
49 |
56 If anchors set allow ambiguos positioning of items, then layout tries to set items size as |
50 If anchors set allow ambiguos positioning of items, then layout tries to set items |
57 close to preferred as possible. |
51 size as close to preferred as possible. |
58 |
52 |
59 \image html hbmeshlayout1.png |
53 \image html hbanchorlayout1.png |
60 |
54 |
61 From the image above, we have decided that the green node is always present. This |
55 From the image above, we have decided that the green node is always present. This |
62 means that all the other nodes in the horizontal graph can be optional. |
56 means that all the other nodes in the horizontal graph can be optional. |
63 |
57 |
64 \image html hbmeshlayout2.png |
58 \image html hbanchorlayout2.png |
65 |
59 |
66 Then, we create the anchors starting from the non-optional node and point towards |
60 Then, we create the anchors starting from the non-optional node and point towards |
67 the edges of the layout. The mesh layout definition in the WidgetML would look like: |
61 the edges of the layout. The anchor layout definition in the WidgetML would look like: |
68 |
62 |
69 \code |
63 \code |
70 |
64 |
71 <meshitem src="green_item" srcEdge="LEFT" dst="blue_item" dstEdge="RIGHT" /> |
65 <anchoritem srcId="green_item" srcEdge="LEFT" dstId="blue_item" dstEdge="RIGHT" /> |
72 <meshitem src="blue_item" srcEdge="LEFT" dst="" dstEdge="LEFT" /> |
66 <anchoritem srcId="blue_item" srcEdge="LEFT" dstId="" dstEdge="LEFT" /> |
73 <meshitem src="green_item" srcEdge="RIGHT" dst="red_item" dstEdge="LEFT" /> |
67 <anchoritem srcId="green_item" srcEdge="RIGHT" dstId="red_item" dstEdge="LEFT" /> |
74 <meshitem src="red_item" srcEdge="RIGHT" dst="yellow_item" dstEdge="LEFT" /> |
68 <anchoritem srcId="red_item" srcEdge="RIGHT" dstId="yellow_item" dstEdge="LEFT" /> |
75 <meshitem src="yellow_item" srcEdge="RIGHT" dst="" dstEdge="RIGHT" /> |
69 <anchoritem srcId="yellow_item" srcEdge="RIGHT" dstId="" dstEdge="RIGHT" /> |
76 |
70 |
77 \endcode |
71 \endcode |
78 |
72 |
79 As mentioned, the green node needs be present always. In practice, this means that the |
73 As mentioned, the green node needs be present always. In practice, this means that the |
80 parent widget, which owns this anchor layout, needs to have a child widget with item |
74 parent widget, which owns this anchor layout, needs to have a child widget with item |
81 name "green_item". \c HbStyle::setItemName for more details. |
75 name "green_item". \c HbStyle::setItemName for more details. |
82 |
76 |
83 If an optional node is missing, the anchors pointing to the node are |
77 If an optional node is missing, the anchors pointing to the node are |
84 changed to point to the node after (=towards the parent layout) the missing one - this |
78 changed to point to the node after (=towards the parent layout) the missing one. |
85 is called "fixing the mesh". |
79 |
86 |
80 \image html hbanchorlayout3.png |
87 \image html hbmeshlayout3.png |
|
88 |
81 |
89 In the picture above, the blue and yellow items are missing. The anchor is fixed by removing |
82 In the picture above, the blue and yellow items are missing. The anchor is fixed by removing |
90 the anchor definitions starting from the missing nodes. |
83 the anchor definitions starting from the missing nodes. |
91 |
84 |
92 \stable |
85 \stable |
143 void createEquations( EdgeType type ); |
140 void createEquations( EdgeType type ); |
144 |
141 |
145 int getEdgeIndex(QGraphicsLayoutItem *item, Hb::Edge edge); |
142 int getEdgeIndex(QGraphicsLayoutItem *item, Hb::Edge edge); |
146 |
143 |
147 bool findEndItem( |
144 bool findEndItem( |
148 QList<HbMeshEndItemResult> &resultList, |
145 QList<HbFixedEndItemResult> &resultList, |
149 const HbAnchor *anchor, |
146 const HbAnchor *anchor, |
150 QStringList &ids) const; |
147 QStringList &ids) const; |
151 void resolveAnchors(); |
148 void resolveAnchors(); |
152 void removeItemIfNeeded( QGraphicsLayoutItem *item ); |
149 void removeItemIfNeeded( QGraphicsLayoutItem *item ); |
153 |
150 |
154 bool setAnchor( HbAnchor *anchor ); |
151 HbAnchor *setAnchor( HbAnchor *anchor ); |
155 |
152 |
156 void setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type ); |
153 void setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type ); |
|
154 void setSizeProp( SizeProperty *v, HbAnchor *item ); |
157 GraphVertex *createCenterEdge( EdgeType type, QGraphicsLayoutItem *item, Hb::Edge edge ); |
155 GraphVertex *createCenterEdge( EdgeType type, QGraphicsLayoutItem *item, Hb::Edge edge ); |
158 void defineNextGeometry( const int itemIndexStart, const int itemIndexEnd, const int anchorIndex, const int definedItemIndex ); |
156 void defineNextGeometry( const int itemIndexStart, const int itemIndexEnd, const int anchorIndex, const int definedItemIndex ); |
159 |
157 |
160 |
158 |
161 QSizeF sizeHint(Qt::SizeHint which); |
159 QSizeF sizeHint(Qt::SizeHint which); |
209 |
206 |
210 }; |
207 }; |
211 |
208 |
212 |
209 |
213 |
210 |
214 |
211 /*! |
215 |
212 \internal functions |
216 |
213 */ |
217 /*! |
214 |
218 \internal |
215 inline bool idConditionStartStart( HbAnchor *anchor1, HbAnchor *anchor2 ) |
219 */ |
216 { |
220 HbAnchor::HbAnchor() |
217 return ( !anchor1->startNodeId().isNull() ) && ( anchor1->startNodeId() == anchor2->startNodeId() ); |
221 : mStartItem(0), |
218 } |
222 mStartEdge(Hb::LeftEdge), |
219 inline bool idConditionEndEnd( HbAnchor *anchor1, HbAnchor *anchor2 ) |
223 mEndItem(0), |
220 { |
224 mEndEdge(Hb::LeftEdge), |
221 return ( !anchor1->endNodeId().isNull() ) && ( anchor1->endNodeId() == anchor2->endNodeId() ); |
225 mValue(0) |
222 } |
226 { |
223 inline bool idConditionStartEnd( HbAnchor *anchor1, HbAnchor *anchor2 ) |
227 } |
224 { |
228 |
225 return ( !anchor1->startNodeId().isNull() ) && ( anchor1->startNodeId() == anchor2->endNodeId() ); |
229 HbAnchor::HbAnchor(const HbAnchor &anchor) |
226 } |
230 : mStartItem(anchor.mStartItem), |
227 inline bool idConditionEndStart( HbAnchor *anchor1, HbAnchor *anchor2 ) |
231 mStartEdge(anchor.mStartEdge), |
228 { |
232 mStartId(anchor.mStartId), |
229 return ( !anchor1->endNodeId().isNull() ) && ( anchor1->endNodeId() == anchor2->startNodeId() ); |
233 mEndItem(anchor.mEndItem), |
230 } |
234 mEndEdge(anchor.mEndEdge), |
231 |
235 mEndId(anchor.mEndId), |
232 inline bool itemConditionStartStart( HbAnchor *anchor1, HbAnchor *anchor2 ) |
236 mValue(anchor.mValue) |
233 { |
237 { |
234 return ( anchor1->startItem() != 0 ) && ( anchor1->startItem() == anchor2->startItem() ); |
238 } |
235 } |
239 |
236 inline bool itemConditionEndEnd( HbAnchor *anchor1, HbAnchor *anchor2 ) |
240 HbAnchor::HbAnchor( QGraphicsLayoutItem *startItem, |
237 { |
241 HbAnchorLayout::Edge startEdge, |
238 return ( anchor1->endItem() != 0 ) && ( anchor1->endItem() == anchor2->endItem() ); |
242 QGraphicsLayoutItem *endItem, |
239 } |
243 HbAnchorLayout::Edge endEdge, |
240 inline bool itemConditionStartEnd( HbAnchor *anchor1, HbAnchor *anchor2 ) |
244 qreal value ) |
241 { |
245 : mStartItem(startItem), |
242 return ( anchor1->startItem() != 0 ) && ( anchor1->startItem() == anchor2->endItem() ); |
246 mStartEdge(startEdge), |
243 } |
247 mEndItem(endItem), |
244 inline bool itemConditionEndStart( HbAnchor *anchor1, HbAnchor *anchor2 ) |
248 mEndEdge(endEdge), |
245 { |
249 mValue(value) |
246 return ( anchor1->endItem() != 0 ) && ( anchor1->endItem() == anchor2->startItem() ); |
250 { |
247 } |
251 } |
248 |
252 |
249 inline bool edgeConditionStartStart( HbAnchor *anchor1, HbAnchor *anchor2 ) |
253 |
250 { |
254 HbAnchor &HbAnchor::operator=(const HbAnchor &anchor) |
251 return anchor1->startEdge() == anchor2->startEdge(); |
255 { |
252 } |
256 if (this != &anchor) { |
253 inline bool edgeConditionEndEnd( HbAnchor *anchor1, HbAnchor *anchor2 ) |
257 mStartItem = anchor.mStartItem; |
254 { |
258 mStartId = anchor.mStartId; |
255 return anchor1->endEdge() == anchor2->endEdge(); |
259 mStartEdge = anchor.mStartEdge; |
256 } |
260 mEndItem = anchor.mEndItem; |
257 inline bool edgeConditionStartEnd( HbAnchor *anchor1, HbAnchor *anchor2 ) |
261 mEndId = anchor.mEndId; |
258 { |
262 mEndEdge = anchor.mEndEdge; |
259 return anchor1->startEdge() == anchor2->endEdge(); |
263 mValue = anchor.mValue; |
260 } |
264 } |
261 inline bool edgeConditionEndStart( HbAnchor *anchor1, HbAnchor *anchor2 ) |
265 return *this; |
262 { |
266 } |
263 return anchor1->endEdge() == anchor2->startEdge(); |
267 |
264 } |
268 |
265 |
269 |
266 inline int directionMultiplier( HbAnchor *anchor ) |
270 |
267 { |
271 |
268 return ( ( anchor->direction() == HbAnchor::Positive )?(1):(-1) ); |
272 /*! |
269 } |
273 \internal |
270 |
274 */ |
271 |
275 QList<HbAnchor*> HbAnchorLayoutDebug::getAnchors( HbAnchorLayout* layout ) |
272 /*! |
276 { |
273 Returns list of effective anchors - those which has mappings to QGraphicsItem |
277 layout->d_ptr->resolveAnchors(); |
274 \return list of effective anchors. |
278 return layout->d_ptr->mResolvedAnchors; |
275 */ |
279 } |
276 QList<HbAnchor*> HbAnchorLayout::effectiveAnchors() |
280 |
277 { |
281 QList<HbAnchor*> HbAnchorLayoutDebug::getOriginalAnchors( HbAnchorLayout* layout ) |
278 Q_D( HbAnchorLayout ); |
282 { |
279 d->resolveAnchors(); |
283 return layout->d_ptr->mAllAnchors; |
280 return d->mResolvedAnchors; |
|
281 } |
|
282 |
|
283 /*! |
|
284 Returns list of all anchors set to this layout |
|
285 \return list of all anchors. |
|
286 */ |
|
287 QList<HbAnchor*> HbAnchorLayout::anchors() const |
|
288 { |
|
289 Q_D( const HbAnchorLayout ); |
|
290 return d->mAllAnchors; |
284 } |
291 } |
285 |
292 |
286 /* |
293 /* |
287 \class HbAnchorLayoutPrivate |
294 \class HbAnchorLayoutPrivate |
288 \internal |
295 \internal |
397 resolveAnchors(); |
397 resolveAnchors(); |
398 |
398 |
399 #ifdef HBANCHORLAYOUT_DEBUG |
399 #ifdef HBANCHORLAYOUT_DEBUG |
400 QGraphicsWidget* w = HbLayoutUtils::parentWidget( q ); |
400 QGraphicsWidget* w = HbLayoutUtils::parentWidget( q ); |
401 if ( w ) { |
401 if ( w ) { |
402 qDebug() << "MeshLayout: Mesh anchors for" << w->metaObject()->className(); |
402 qDebug() << "AnchorLayout: Updating anchors for" << w->metaObject()->className(); |
403 } |
403 } |
404 const QString parentId = |
404 const QString parentId = |
405 mMeshMap.contains(q) ? mMeshMap.value(q) : QString(); |
405 mItemToNodeIdMap.contains(q) ? mItemToNodeIdMap.value(q) : QString(); |
406 qDebug() << "-- -- resolved"; |
406 qDebug() << "-- -- resolved"; |
407 qDebug() << "-- count: " << mResolvedAnchors.size() << ", parent: " << parentId; |
407 qDebug() << "-- count: " << mResolvedAnchors.size() << ", parent: " << parentId; |
408 foreach (const HbAnchor *item, mResolvedAnchors) { |
408 foreach (const HbAnchor *item, mResolvedAnchors) { |
409 const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7"); |
409 const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7"); |
410 qDebug() << |
410 qDebug() << |
411 itemTemplate |
411 itemTemplate |
412 .arg(item->mStartId) |
412 .arg(item->startNodeId()) |
413 .arg(itemAsText(item->mStartItem, q)) |
413 .arg(itemAsText(item->startItem(), q)) |
414 .arg(edgeAsText(item->mStartEdge)) |
414 .arg(edgeAsText(item->startEdge())) |
415 .arg(item->mEndId) |
415 .arg(item->endNodeId()) |
416 .arg(itemAsText(item->mEndItem, q)) |
416 .arg(itemAsText(item->endItem(), q)) |
417 .arg(edgeAsText(item->mEndEdge)) |
417 .arg(edgeAsText(item->endEdge())) |
418 .arg(item->mValue).toAscii().data(); |
418 .arg(item->preferredLength()).toAscii().data(); |
419 } |
419 } |
420 qDebug() << "-- -- all"; |
420 qDebug() << "-- -- all"; |
421 qDebug() << "-- count: " << mAllAnchors.size() << ", parent: " << parentId; |
421 qDebug() << "-- count: " << mAllAnchors.size() << ", parent: " << parentId; |
422 foreach (const HbAnchor *item, mAllAnchors) { |
422 foreach (const HbAnchor *item, mAllAnchors) { |
423 const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7"); |
423 const QString itemTemplate("-- (%1 [%2], %3) - (%4 [%5], %6) = %7"); |
424 qDebug() << |
424 qDebug() << |
425 itemTemplate |
425 itemTemplate |
426 .arg(item->mStartId) |
426 .arg(item->startNodeId()) |
427 .arg(itemAsText(item->mStartItem, q)) |
427 .arg(itemAsText(item->startItem(), q)) |
428 .arg(edgeAsText(item->mStartEdge)) |
428 .arg(edgeAsText(item->startEdge())) |
429 .arg(item->mEndId) |
429 .arg(item->endNodeId()) |
430 .arg(itemAsText(item->mEndItem, q)) |
430 .arg(itemAsText(item->endItem(), q)) |
431 .arg(edgeAsText(item->mEndEdge)) |
431 .arg(edgeAsText(item->endEdge())) |
432 .arg(item->mValue).toAscii().data(); |
432 .arg(item->preferredLength()).toAscii().data(); |
433 } |
433 } |
434 qDebug() << "-- "; |
434 qDebug() << "-- "; |
435 #endif // HBANCHORLAYOUT_DEBUG |
435 #endif // HBANCHORLAYOUT_DEBUG |
436 |
436 |
437 // HbAnchorLayout will only touch items that have anchors defined. |
437 // HbAnchorLayout will only touch items that have anchors defined. |
440 it != mResolvedAnchors.constEnd(); |
440 it != mResolvedAnchors.constEnd(); |
441 ++it) { |
441 ++it) { |
442 |
442 |
443 const HbAnchor* item = *it; |
443 const HbAnchor* item = *it; |
444 |
444 |
445 if (item->mStartItem != q && !mActualItems.contains(item->mStartItem)) { |
445 if (item->startItem() != q && !mActualItems.contains(item->startItem())) { |
446 mActualItems.append(item->mStartItem); |
446 mActualItems.append(item->startItem()); |
447 } |
447 } |
448 if (item->mEndItem != q && !mActualItems.contains(item->mEndItem)) { |
448 if (item->endItem() != q && !mActualItems.contains(item->endItem())) { |
449 mActualItems.append(item->mEndItem); |
449 mActualItems.append(item->endItem()); |
450 } |
450 } |
451 } |
451 } |
452 |
452 |
453 } |
453 } |
|
454 |
|
455 void HbAnchorLayoutPrivate::setSizeProp( SizeProperty *v, HbAnchor *item ) |
|
456 { |
|
457 const QSizePolicy::Policy policy = item->sizePolicy(); |
|
458 |
|
459 if ( policy & QSizePolicy::ShrinkFlag ) { |
|
460 v->min = item->minimumLength(); |
|
461 } else { |
|
462 v->min = item->preferredLength(); |
|
463 } |
|
464 |
|
465 if ( policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag) ) { |
|
466 v->max = item->maximumLength(); |
|
467 } else { |
|
468 v->max = item->preferredLength(); |
|
469 } |
|
470 |
|
471 v->pref = qBound( v->min, item->preferredLength(), v->max ); |
|
472 |
|
473 v->flags |= (v->min == v->max) ? SizeProperty::FlagFixed : 0; |
|
474 v->flags |= (policy & QSizePolicy::ExpandFlag) ? SizeProperty::FlagExpanding : 0; |
|
475 |
|
476 if( policy & QSizePolicy::IgnoreFlag ) { |
|
477 v->pref = v->min; |
|
478 v->flags |= SizeProperty::FlagExpanding; |
|
479 } |
|
480 } |
|
481 |
454 |
482 |
455 |
483 |
456 void HbAnchorLayoutPrivate::setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type ) |
484 void HbAnchorLayoutPrivate::setSizeProp( SizeProperty *v, QGraphicsLayoutItem *item, EdgeType type ) |
457 { |
485 { |
458 if( type == Vertical ) { |
486 if( type == Vertical ) { |
616 { |
644 { |
617 ItemGeometry *knownItemGeom, *unKnownItemGeom; |
645 ItemGeometry *knownItemGeom, *unKnownItemGeom; |
618 Hb::Edge knownEdge, unKnownEdge; |
646 Hb::Edge knownEdge, unKnownEdge; |
619 int sign; |
647 int sign; |
620 qreal itemSize; |
648 qreal itemSize; |
|
649 qreal anchorSize; |
621 bool isHorizontal; |
650 bool isHorizontal; |
622 HbAnchor *anchor = mResolvedAnchors.at( anchorIndex ); |
651 HbAnchor *anchor = mResolvedAnchors.at( anchorIndex ); |
623 qreal leftPoint(0), rightPoint(0), sourcePoint(0), dstPointLeft(0); |
652 qreal leftPoint(0), rightPoint(0), sourcePoint(0), dstPointLeft(0); |
624 |
653 |
625 mAnchorsVisited[ anchorIndex ] = true; |
654 mAnchorsVisited[ anchorIndex ] = true; |
626 |
655 |
627 if( edgeType( anchor->mStartEdge ) == Horizontal ) { |
656 if( edgeType( anchor->startEdge() ) == Horizontal ) { |
628 isHorizontal = true; |
657 isHorizontal = true; |
629 } else { |
658 } else { |
630 isHorizontal = false; |
659 isHorizontal = false; |
631 } |
660 } |
632 |
661 |
633 if( itemIndexEnd != definedItemIndex ) { |
662 if( itemIndexEnd != definedItemIndex ) { |
634 knownEdge = anchor->mStartEdge; |
663 knownEdge = anchor->startEdge(); |
635 unKnownEdge = anchor->mEndEdge; |
664 unKnownEdge = anchor->endEdge(); |
636 |
665 |
637 knownItemGeom = &mItemsGeometry[itemIndexStart]; |
666 knownItemGeom = &mItemsGeometry[itemIndexStart]; |
638 unKnownItemGeom = &mItemsGeometry[itemIndexEnd]; |
667 unKnownItemGeom = &mItemsGeometry[itemIndexEnd]; |
639 |
668 |
640 if( isHorizontal ) { |
669 if( isHorizontal ) { |
641 mGeometryDefinedH[itemIndexEnd] = true; |
670 mGeometryDefinedH[itemIndexEnd] = true; |
642 itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexEnd) ) ); |
671 itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexEnd) ) ); |
|
672 anchorSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( anchor ) ) * directionMultiplier( anchor ); |
643 } else { |
673 } else { |
644 mGeometryDefinedV[itemIndexEnd] = true; |
674 mGeometryDefinedV[itemIndexEnd] = true; |
645 itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexEnd) ) ); |
675 itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexEnd) ) ); |
|
676 anchorSize = mSolutionVertical.value( mVariablesVertical.findVariable( anchor ) ) * directionMultiplier( anchor ); |
646 } |
677 } |
647 |
678 |
648 sign = 1; |
679 sign = 1; |
649 } else { |
680 } else { |
650 knownEdge = anchor->mEndEdge; |
681 knownEdge = anchor->endEdge(); |
651 unKnownEdge = anchor->mStartEdge; |
682 unKnownEdge = anchor->startEdge(); |
652 |
683 |
653 knownItemGeom = &mItemsGeometry[itemIndexEnd]; |
684 knownItemGeom = &mItemsGeometry[itemIndexEnd]; |
654 unKnownItemGeom = &mItemsGeometry[itemIndexStart]; |
685 unKnownItemGeom = &mItemsGeometry[itemIndexStart]; |
655 |
686 |
656 if( isHorizontal ) { |
687 if( isHorizontal ) { |
657 mGeometryDefinedH[itemIndexStart] = true; |
688 mGeometryDefinedH[itemIndexStart] = true; |
658 itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexStart) ) ); |
689 itemSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( mActualItems.at(itemIndexStart) ) ); |
|
690 anchorSize = mSolutionHorizontal.value( mVariablesHorizontal.findVariable( anchor ) ) * directionMultiplier( anchor ); |
659 } else { |
691 } else { |
660 mGeometryDefinedV[itemIndexStart] = true; |
692 mGeometryDefinedV[itemIndexStart] = true; |
661 itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexStart) ) ); |
693 itemSize = mSolutionVertical.value( mVariablesVertical.findVariable( mActualItems.at(itemIndexStart) ) ); |
|
694 anchorSize = mSolutionVertical.value( mVariablesVertical.findVariable( anchor ) ) * directionMultiplier( anchor ); |
662 } |
695 } |
663 |
696 |
664 sign = -1; |
697 sign = -1; |
665 } |
698 } |
666 |
699 |
826 mGeometryDefinedV[i] = false; |
858 mGeometryDefinedV[i] = false; |
827 } |
859 } |
828 |
860 |
829 int layoutIndex = mActualItems.size(); |
861 int layoutIndex = mActualItems.size(); |
830 |
862 |
831 mItemsGeometry[ layoutIndex ].x1 = 0;//newRect.left(); |
863 mItemsGeometry[ layoutIndex ].x1 = 0; |
832 mItemsGeometry[ layoutIndex ].x2 = newRect.width();//newRect.right(); |
864 mItemsGeometry[ layoutIndex ].x2 = newRect.width(); |
833 mItemsGeometry[ layoutIndex ].y1 = 0;//newRect.top(); |
865 mItemsGeometry[ layoutIndex ].y1 = 0; |
834 mItemsGeometry[ layoutIndex ].y2 = newRect.height();//newRect.bottom(); |
866 mItemsGeometry[ layoutIndex ].y2 = newRect.height(); |
835 mGeometryDefinedH[ layoutIndex ] = true; |
867 mGeometryDefinedH[ layoutIndex ] = true; |
836 mGeometryDefinedV[ layoutIndex ] = true; |
868 mGeometryDefinedV[ layoutIndex ] = true; |
837 |
869 |
838 |
870 |
839 for( int i = 0; i < mAnchorsVisited.size(); i++ ) { |
871 for( int i = 0; i < mAnchorsVisited.size(); i++ ) { |
840 |
872 |
841 HbAnchor *anchor = mResolvedAnchors.at(i); |
873 HbAnchor *anchor = mResolvedAnchors.at(i); |
842 |
874 |
843 |
875 |
844 if( ( anchor->mStartItem != q ) && ( anchor->mEndItem != q ) ) { |
876 if( ( anchor->startItem() != q ) && ( anchor->endItem() != q ) ) { |
845 continue; |
877 continue; |
846 } |
878 } |
847 |
879 |
848 int startIndex = mActualItems.indexOf( anchor->mStartItem ); // returns -1 if not found => this is layout |
880 int startIndex = mActualItems.indexOf( anchor->startItem() ); // returns -1 if not found => this is layout |
849 int endIndex = mActualItems.indexOf( anchor->mEndItem ); |
881 int endIndex = mActualItems.indexOf( anchor->endItem() ); |
850 |
882 |
851 mAnchorsVisited[i] = true; // Temporary overkill, if both anchors connected to layout. Must be restricted on setAnchor() level |
883 mAnchorsVisited[i] = true; |
852 |
884 |
853 if( edgeType( anchor->mStartEdge ) == Horizontal ) { |
885 if( edgeType( anchor->startEdge() ) == Horizontal ) { |
854 if( startIndex > -1 ) { |
886 if( startIndex > -1 ) { |
855 if( ! mGeometryDefinedH.at( startIndex ) ) { |
887 if( ! mGeometryDefinedH.at( startIndex ) ) { |
856 defineNextGeometry( startIndex, layoutIndex, i, layoutIndex ); |
888 defineNextGeometry( startIndex, layoutIndex, i, layoutIndex ); |
857 } |
889 } |
858 } else if( endIndex > -1 ) { |
890 } else if( endIndex > -1 ) { |
885 if( mAnchorsVisited.at(i) ) { |
917 if( mAnchorsVisited.at(i) ) { |
886 continue; |
918 continue; |
887 } |
919 } |
888 HbAnchor *anchor = mResolvedAnchors.at(i); |
920 HbAnchor *anchor = mResolvedAnchors.at(i); |
889 |
921 |
890 startIndex = mActualItems.indexOf( anchor->mStartItem ); |
922 startIndex = mActualItems.indexOf( anchor->startItem() ); |
891 endIndex = mActualItems.indexOf( anchor->mEndItem ); |
923 endIndex = mActualItems.indexOf( anchor->endItem() ); |
892 #ifdef HBANCHORLAYOUT_DEBUG |
924 #ifdef HBANCHORLAYOUT_DEBUG |
893 qDebug() << "startIndex:" << startIndex << " endIndex" << endIndex; |
925 qDebug() << "startIndex:" << startIndex << " endIndex" << endIndex; |
894 #endif //HBANCHORLAYOUT_DEBUG |
926 #endif //HBANCHORLAYOUT_DEBUG |
895 if( edgeType( anchor->mStartEdge ) == Horizontal ) { |
927 if( edgeType( anchor->startEdge() ) == Horizontal ) { |
896 startDefined = mGeometryDefinedH.at( startIndex ); |
928 startDefined = mGeometryDefinedH.at( startIndex ); |
897 endDefined = mGeometryDefinedH.at( endIndex ); |
929 endDefined = mGeometryDefinedH.at( endIndex ); |
898 } else { |
930 } else { |
899 startDefined = mGeometryDefinedV.at( startIndex ); |
931 startDefined = mGeometryDefinedV.at( startIndex ); |
900 endDefined = mGeometryDefinedV.at( endIndex ); |
932 endDefined = mGeometryDefinedV.at( endIndex ); |
1059 v1->sizeProp.flags = SizeProperty::FlagFixed; |
1090 v1->sizeProp.flags = SizeProperty::FlagFixed; |
1060 |
1091 |
1061 |
1092 |
1062 for( int i = 0; i < mResolvedAnchors.count(); i++) { |
1093 for( int i = 0; i < mResolvedAnchors.count(); i++) { |
1063 HbAnchor* anchor = mResolvedAnchors.at(i); |
1094 HbAnchor* anchor = mResolvedAnchors.at(i); |
1064 if ( edgeType( anchor->mStartEdge ) == type ) { |
1095 if ( edgeType( anchor->startEdge() ) == type ) { |
1065 itemStart = 0; |
1096 itemStart = 0; |
1066 itemEnd = 0; |
1097 itemEnd = 0; |
1067 for( int j = 0; j < vertices->size(); j++ ) { |
1098 for( int j = 0; j < vertices->size(); j++ ) { |
1068 if( ( vertices->at(j)->itemRef == anchor->mStartItem ) && |
1099 if( ( vertices->at(j)->itemRef == anchor->startItem() ) && |
1069 ( vertices->at(j)->itemSide == anchor->mStartEdge ) ) { |
1100 ( vertices->at(j)->itemSide == anchor->startEdge() ) ) { |
1070 itemStart = vertices->at(j); |
1101 itemStart = vertices->at(j); |
1071 } else if( ( vertices->at(j)->itemRef == anchor->mEndItem ) && |
1102 } else if( ( vertices->at(j)->itemRef == anchor->endItem() ) && |
1072 ( vertices->at(j)->itemSide == anchor->mEndEdge ) ) { |
1103 ( vertices->at(j)->itemSide == anchor->endEdge() ) ) { |
1073 itemEnd = vertices->at(j); |
1104 itemEnd = vertices->at(j); |
1074 } |
1105 } |
1075 } |
1106 } |
1076 |
1107 |
1077 if( !itemStart ) { |
1108 if( !itemStart ) { |
1078 itemStart = createCenterEdge( type, anchor->mStartItem, anchor->mStartEdge ); |
1109 itemStart = createCenterEdge( type, anchor->startItem(), anchor->startEdge() ); |
1079 } |
1110 } |
1080 if( !itemEnd ) { |
1111 if( !itemEnd ) { |
1081 itemEnd = createCenterEdge( type, anchor->mEndItem, anchor->mEndEdge ); |
1112 itemEnd = createCenterEdge( type, anchor->endItem(), anchor->endEdge() ); |
1082 } |
1113 } |
1083 |
1114 |
1084 if( !itemStart ){ |
1115 if( !itemStart ){ |
1085 qWarning() << "HbAnchorLayout: internal error, line " << __LINE__; |
1116 qWarning() << "HbAnchorLayout: internal error, line " << __LINE__; |
1086 mWrongAnchors = true; |
1117 mWrongAnchors = true; |
1209 \a ids must be the exactly same in return. It is the array |
1243 \a ids must be the exactly same in return. It is the array |
1210 which nodes have already been visited - so in order to avoid |
1244 which nodes have already been visited - so in order to avoid |
1211 infinite recursion, don't visit already visited. |
1245 infinite recursion, don't visit already visited. |
1212 */ |
1246 */ |
1213 bool HbAnchorLayoutPrivate::findEndItem( |
1247 bool HbAnchorLayoutPrivate::findEndItem( |
1214 QList<HbMeshEndItemResult> &resultList, |
1248 QList<HbFixedEndItemResult> &resultList, |
1215 const HbAnchor *problem, |
1249 const HbAnchor *problem, |
1216 QStringList &ids) const |
1250 QStringList &ids) const |
1217 { |
1251 { |
1218 HbMeshEndItemResult result; |
1252 HbFixedEndItemResult result; |
1219 bool found = false; |
1253 bool found = false; |
1220 |
1254 |
1221 for (QList<HbAnchor*>::const_iterator it = mAllAnchors.constBegin(); |
1255 for (QList<HbAnchor*>::const_iterator it = mAllAnchors.constBegin(); |
1222 it != mAllAnchors.constEnd(); |
1256 it != mAllAnchors.constEnd(); |
1223 ++it) { |
1257 ++it) { |
1224 |
1258 |
1225 const HbAnchor* currentItem = *it; |
1259 const HbAnchor* currentItem = *it; |
1226 |
1260 |
1227 if (!currentItem->mStartId.isNull() && |
1261 if (!currentItem->startNodeId().isNull() && |
1228 currentItem->mStartId == problem->mEndId && |
1262 currentItem->startNodeId() == problem->endNodeId() && |
1229 currentItem->mStartEdge == problem->mStartEdge && |
1263 currentItem->startEdge() == problem->startEdge() && |
1230 !ids.contains(currentItem->mStartId)) { |
1264 !ids.contains(currentItem->startNodeId())) { |
1231 |
1265 |
1232 qreal currentSpacing = currentItem->mValue; |
1266 QGraphicsLayoutItem *item = currentItem->endItem(); |
1233 |
|
1234 QGraphicsLayoutItem *item = currentItem->mEndItem; |
|
1235 |
|
1236 |
1267 |
1237 if (item) { |
1268 if (item) { |
1238 found = true; |
1269 found = true; |
1239 result.mEdge = currentItem->mEndEdge; |
1270 result.mEdge = currentItem->endEdge(); |
1240 result.mItem = item; |
1271 result.mItem = item; |
1241 result.mValue = currentSpacing; |
1272 result.mMin = currentItem->minimumLength(); |
|
1273 result.mPref = currentItem->preferredLength(); |
|
1274 result.mMax = currentItem->maximumLength(); |
|
1275 result.mPolicy = currentItem->sizePolicy(); |
|
1276 result.mDirection = currentItem->direction(); |
1242 resultList.append( result ); |
1277 resultList.append( result ); |
1243 } else { |
1278 } else { |
1244 ids.append(currentItem->mStartId); |
1279 ids.append(currentItem->startNodeId()); |
1245 found |= findEndItem(resultList, currentItem, ids); |
1280 found |= findEndItem(resultList, currentItem, ids); |
1246 ids.takeLast(); |
1281 ids.takeLast(); |
1247 } |
1282 } |
1248 /* |
|
1249 if (found) { |
|
1250 // We have found an end item. There can be multiple end items, |
|
1251 // but (for now) the first one is selected. |
|
1252 return true; |
|
1253 }*/ |
|
1254 } |
1283 } |
1255 } |
1284 } |
1256 |
1285 |
1257 return found; |
1286 return found; |
1258 } |
1287 } |
1284 |
1313 |
1285 for ( int i = 0; i < mAllAnchors.size(); i++ ) { |
1314 for ( int i = 0; i < mAllAnchors.size(); i++ ) { |
1286 |
1315 |
1287 HbAnchor *anchor = mAllAnchors.at(i); |
1316 HbAnchor *anchor = mAllAnchors.at(i); |
1288 |
1317 |
1289 if( ( anchor->mStartItem ) && ( anchor->mEndItem ) ) { |
1318 if( ( anchor->startItem() ) && ( anchor->endItem() ) ) { |
1290 mResolvedStaticAnchors.append( anchor ); |
1319 mResolvedStaticAnchors.append( anchor ); |
1291 continue; |
1320 continue; |
1292 } |
1321 } |
1293 |
1322 |
1294 if (anchor->mStartItem && !anchor->mEndId.isNull()) { |
1323 if (anchor->startItem() && !anchor->endNodeId().isNull()) { |
1295 QList<HbMeshEndItemResult> resultList; |
1324 QList<HbFixedEndItemResult> resultList; |
1296 |
1325 |
1297 QStringList ids; |
1326 QStringList ids; |
1298 ids.append(anchor->mStartId); |
1327 ids.append(anchor->startNodeId()); |
1299 |
1328 |
1300 if (findEndItem(resultList, anchor, ids)) { |
1329 if (findEndItem(resultList, anchor, ids)) { |
1301 for( int j = 0; j < resultList.size(); j++ ) { |
1330 for( int j = 0; j < resultList.size(); j++ ) { |
1302 item = new HbAnchor(); |
1331 item = new HbAnchor( anchor->startItem(), anchor->startEdge(), resultList.at(j).mItem, resultList.at(j).mEdge ); |
1303 item->mStartItem = anchor->mStartItem; |
1332 item->setMinimumLength( resultList.at(j).mMin ); |
1304 item->mStartId = anchor->mStartId; |
1333 item->setPreferredLength( resultList.at(j).mPref ); |
1305 item->mStartEdge = anchor->mStartEdge; |
1334 item->setMaximumLength( resultList.at(j).mMax ); |
1306 item->mEndEdge = resultList.at(j).mEdge; |
1335 item->setSizePolicy( resultList.at(j).mPolicy ); |
1307 item->mEndItem = resultList.at(j).mItem; |
1336 item->setDirection( resultList.at(j).mDirection ); |
1308 item->mValue = resultList.at(j).mValue; |
|
1309 mResolvedDynamicAnchors.append(item); |
1337 mResolvedDynamicAnchors.append(item); |
1310 } |
1338 } |
1311 } |
1339 } |
1312 } else { |
1340 } else { |
1313 // Nothing needed. |
1341 // Nothing needed. |
1315 } |
1343 } |
1316 |
1344 |
1317 mResolvedAnchors = mResolvedDynamicAnchors + mResolvedStaticAnchors; |
1345 mResolvedAnchors = mResolvedDynamicAnchors + mResolvedStaticAnchors; |
1318 } |
1346 } |
1319 |
1347 |
1320 bool HbAnchorLayoutPrivate::setAnchor( HbAnchor *anchor ) |
1348 HbAnchor *HbAnchorLayoutPrivate::setAnchor( HbAnchor *anchor ) |
1321 { |
1349 { |
|
1350 Q_Q( HbAnchorLayout ); |
1322 // This method is called from HbAnchorLayout::setAnchor. |
1351 // This method is called from HbAnchorLayout::setAnchor. |
1323 |
1352 |
1324 if (HbAnchorLayoutPrivate::edgeType(anchor->mStartEdge) != |
1353 if (HbAnchorLayoutPrivate::edgeType(anchor->startEdge()) != |
1325 HbAnchorLayoutPrivate::edgeType(anchor->mEndEdge)) { |
1354 HbAnchorLayoutPrivate::edgeType(anchor->endEdge())) { |
1326 qWarning() << "HbAnchorLayout::setAnchor : You can't connect different type of edges"; |
1355 qWarning() << "HbAnchorLayout::setAnchor : You can't connect different type of edges"; |
1327 return false; |
1356 return 0; |
1328 } |
1357 } |
1329 |
1358 |
1330 if ( ( anchor->mStartId.isNull() && ( anchor->mStartItem == 0 ) ) || |
1359 if ( ( anchor->startNodeId().isNull() && ( anchor->startItem() == 0 ) ) || |
1331 ( anchor->mEndId.isNull() && ( anchor->mEndItem == 0 ) ) ){ |
1360 ( anchor->endNodeId().isNull() && ( anchor->endItem() == 0 ) ) ){ |
1332 qWarning() << "HbAnchorLayout::setAnchor : Both ids must be valid"; |
1361 qWarning() << "HbAnchorLayout::setAnchor : Both ids must be valid"; |
1333 return false; |
1362 return 0; |
1334 } |
1363 } |
1335 |
1364 |
1336 if ( ( anchor->mStartId == anchor->mEndId ) && ( ( anchor->mStartItem == anchor->mEndItem ) ) && |
1365 if ( ( anchor->startNodeId() == anchor->endNodeId() ) && ( ( anchor->startItem() == anchor->endItem() ) ) && |
1337 ( anchor->mStartEdge == anchor->mEndEdge ) ) { |
1366 ( anchor->startEdge() == anchor->endEdge() ) ) { |
1338 qWarning() << "HbAnchorLayout::setAnchor : You cannot set anchor between the same edge"; |
1367 qWarning() << "HbAnchorLayout::setAnchor : You cannot set anchor between the same edge"; |
1339 return false; |
1368 return 0; |
1340 } |
1369 } |
1341 |
|
1342 bool modified = false; |
|
1343 |
1370 |
1344 const int count = mAllAnchors.size(); |
1371 const int count = mAllAnchors.size(); |
1345 for (int i = 0; i < count; ++i) { |
1372 for (int i = 0; i < count; ++i) { |
1346 HbAnchor *item = mAllAnchors.at(i); |
1373 HbAnchor *item = mAllAnchors.at(i); |
1347 |
1374 |
1348 |
1375 if( ( idConditionStartStart( item, anchor ) || itemConditionStartStart( item, anchor ) ) && |
1349 bool idConditionStartStart = ( !item->mStartId.isNull() ) && ( item->mStartId == anchor->mStartId ); |
1376 ( idConditionEndEnd( item, anchor ) || itemConditionEndEnd( item, anchor ) ) && |
1350 bool idConditionEndEnd = ( !item->mEndId.isNull() ) && ( item->mEndId == anchor->mEndId ); |
1377 ( edgeConditionStartStart( item, anchor ) ) && |
1351 bool idConditionStartEnd = ( !item->mStartId.isNull() ) && ( item->mStartId == anchor->mEndId ); |
1378 ( edgeConditionEndEnd( item, anchor ) ) ){ |
1352 bool idConditionEndStart = ( !item->mEndId.isNull() ) && ( item->mEndId == anchor->mStartId ); |
1379 item->setSizePolicy( anchor->sizePolicy() ); |
1353 |
1380 item->setMinimumLength( anchor->minimumLength() ); |
1354 bool itemConditionStartStart = ( item->mStartItem != 0 ) && ( item->mStartItem == anchor->mStartItem ); |
1381 item->setPreferredLength( anchor->preferredLength() ); |
1355 bool itemConditionEndEnd = ( item->mEndItem != 0 ) && ( item->mEndItem == anchor->mEndItem ); |
1382 item->setMaximumLength( anchor->maximumLength() ); |
1356 bool itemConditionStartEnd = ( item->mStartItem != 0 ) && ( item->mStartItem == anchor->mEndItem ); |
1383 item->setDirection( anchor->direction() ); |
1357 bool itemConditionEndStart = ( item->mEndItem != 0 ) && ( item->mEndItem == anchor->mStartItem ); |
|
1358 |
|
1359 bool edgeConditionStartStart = item->mStartEdge == anchor->mStartEdge; |
|
1360 bool edgeConditionEndEnd = item->mEndEdge == anchor->mEndEdge; |
|
1361 bool edgeConditionStartEnd = item->mStartEdge == anchor->mEndEdge; |
|
1362 bool edgeConditionEndStart = item->mEndEdge == anchor->mStartEdge; |
|
1363 |
|
1364 |
|
1365 if((idConditionStartStart || itemConditionStartStart) && |
|
1366 (idConditionEndEnd || itemConditionEndEnd) && |
|
1367 (edgeConditionStartStart) && |
|
1368 (edgeConditionEndEnd) ){ |
|
1369 modified = true; |
|
1370 item->mValue = anchor->mValue; |
|
1371 delete anchor; |
1384 delete anchor; |
1372 break; |
1385 return item; |
1373 } else if( (idConditionStartEnd || itemConditionStartEnd) && |
1386 } else if( ( idConditionStartEnd( item, anchor ) || itemConditionStartEnd( item, anchor ) ) && |
1374 (idConditionEndStart || itemConditionEndStart) && |
1387 ( idConditionEndStart( item, anchor ) || itemConditionEndStart( item, anchor ) ) && |
1375 (edgeConditionStartEnd) && |
1388 ( edgeConditionStartEnd( item, anchor ) ) && |
1376 (edgeConditionEndStart) ){ |
1389 ( edgeConditionEndStart( item, anchor ) ) ){ |
1377 modified = true; |
1390 item->setSizePolicy( anchor->sizePolicy() ); |
1378 item->mValue = -anchor->mValue; |
1391 item->setMinimumLength( anchor->minimumLength() ); |
|
1392 item->setPreferredLength( anchor->preferredLength() ); |
|
1393 item->setMaximumLength( anchor->maximumLength() ); |
|
1394 item->setDirection( ( anchor->direction() == HbAnchor::Positive )?( HbAnchor::Negative ):( HbAnchor::Positive ) ); |
1379 delete anchor; |
1395 delete anchor; |
1380 break; |
1396 return item; |
1381 } |
1397 } |
1382 } |
1398 } |
1383 |
1399 |
1384 if (!modified) { |
1400 if( anchor->startItem() != 0 ){ |
1385 if( anchor->mStartItem != 0 ){ |
1401 anchor->d_ptr->mStartId = mItemToNodeIdMap.value( anchor->startItem() ); |
1386 anchor->mStartId = mMeshMap.value( anchor->mStartItem ); |
1402 } else if( ! anchor->startNodeId().isNull() ) { |
1387 } else if( ! anchor->mStartId.isNull() ) { |
1403 anchor->d_ptr->mStartItem = mItemToNodeIdMap.key( anchor->startNodeId() ); |
1388 anchor->mStartItem = mMeshMap.key( anchor->mStartId ); |
1404 } |
1389 } |
1405 |
1390 |
1406 if( anchor->endItem() != 0 ){ |
1391 if( anchor->mEndItem != 0 ){ |
1407 anchor->d_ptr->mEndId = mItemToNodeIdMap.value( anchor->endItem() ); |
1392 anchor->mEndId = mMeshMap.value( anchor->mEndItem ); |
1408 } else if( ! anchor->endNodeId().isNull() ) { |
1393 } else if( ! anchor->mEndId.isNull() ) { |
1409 anchor->d_ptr->mEndItem = mItemToNodeIdMap.key( anchor->endNodeId() ); |
1394 anchor->mEndItem = mMeshMap.key( anchor->mEndId ); |
1410 } |
1395 } |
1411 |
1396 |
1412 addItemIfNeeded( anchor->startItem() ); |
1397 addItemIfNeeded( anchor->mStartItem ); |
1413 addItemIfNeeded( anchor->endItem() ); |
1398 addItemIfNeeded( anchor->mEndItem ); |
1414 |
1399 |
1415 anchor->d_ptr->mParent = q; |
1400 mAllAnchors.append(anchor); |
1416 |
1401 } |
1417 mAllAnchors.append(anchor); |
1402 |
1418 |
1403 return true; |
1419 return anchor; |
1404 } |
1420 } |
1405 |
1421 |
1406 void HbAnchorLayoutPrivate::removeItemIfNeeded( QGraphicsLayoutItem *item ) |
1422 void HbAnchorLayoutPrivate::removeItemIfNeeded( QGraphicsLayoutItem *item ) |
1407 { |
1423 { |
1408 Q_Q( HbAnchorLayout ); |
1424 Q_Q( HbAnchorLayout ); |
1488 \param startItem source item. |
1504 \param startItem source item. |
1489 \param startEdge source edge. |
1505 \param startEdge source edge. |
1490 \param endItem target item. |
1506 \param endItem target item. |
1491 \param endEdge target edge. |
1507 \param endEdge target edge. |
1492 \param length spacing (in pixels). |
1508 \param length spacing (in pixels). |
1493 \return true if anchor was successfully added, false otherwise |
1509 \return created anchor if it was successfully added, or zero otherwise |
1494 */ |
1510 */ |
1495 bool HbAnchorLayout::setAnchor( QGraphicsLayoutItem *startItem, Edge startEdge, QGraphicsLayoutItem *endItem, Edge endEdge, qreal length ) |
1511 HbAnchor *HbAnchorLayout::setAnchor( QGraphicsLayoutItem *startItem, Edge startEdge, QGraphicsLayoutItem *endItem, Edge endEdge, qreal length ) |
1496 { |
1512 { |
1497 Q_D( HbAnchorLayout ); |
1513 Q_D( HbAnchorLayout ); |
1498 |
1514 |
1499 HbAnchor *anchor = new HbAnchor(); |
1515 |
1500 anchor->mStartItem = startItem; |
1516 HbAnchor *anchor = new HbAnchor( startItem, startEdge, endItem, endEdge, length ); |
1501 anchor->mStartEdge = startEdge; |
1517 |
1502 anchor->mEndItem = endItem; |
1518 HbAnchor *result = d->setAnchor( anchor ); |
1503 anchor->mEndEdge = endEdge; |
1519 |
1504 anchor->mValue = length; |
1520 if( result ) { |
1505 |
|
1506 if (d->setAnchor(anchor)) { |
|
1507 invalidate(); |
1521 invalidate(); |
1508 return true; |
1522 return result; |
1509 } |
1523 } |
1510 |
1524 |
1511 delete anchor; |
1525 delete anchor; |
1512 |
1526 |
1513 return false; |
1527 return 0; |
1514 } |
1528 } |
1515 |
1529 |
1516 /*! |
1530 /*! |
1517 Same as previous, but here it operates with node ids, instead of items itself. |
1531 Same as previous, but here it operates with node ids, instead of items itself. |
1518 |
1532 |
1519 \param startId start id. |
1533 \param startId start id. |
1520 \param startEdge start edge. |
1534 \param startEdge start edge. |
1521 \param endId end id. |
1535 \param endId end id. |
1522 \param endEdge end edge. |
1536 \param endEdge end edge. |
1523 \param length spacing value for all edges starting from (\a startId, \a startEdge). |
1537 \param length spacing value for all edges starting from (\a startId, \a startEdge). |
1524 \return true if success, false otherwise. |
1538 \return created anchor if it was successfully added, or zero otherwise |
1525 */ |
1539 */ |
1526 bool HbAnchorLayout::setAnchor( const QString& startId, Edge startEdge, const QString& endId, Edge endEdge, qreal length ) |
1540 HbAnchor *HbAnchorLayout::setAnchor( const QString& startId, Edge startEdge, const QString& endId, Edge endEdge, qreal length ) |
1527 { |
1541 { |
1528 Q_D( HbAnchorLayout ); |
1542 Q_D( HbAnchorLayout ); |
1529 |
1543 |
1530 HbAnchor *anchor = new HbAnchor(); |
1544 HbAnchor *anchor = new HbAnchor( startId, startEdge, endId, endEdge, length ); |
1531 anchor->mStartId = startId; |
1545 |
1532 anchor->mStartEdge = startEdge; |
1546 HbAnchor *result = d->setAnchor( anchor ); |
1533 anchor->mEndId = endId; |
1547 |
1534 anchor->mEndEdge = endEdge; |
1548 if( result ) { |
1535 anchor->mValue = length; |
|
1536 |
|
1537 if (d->setAnchor(anchor)) { |
|
1538 invalidate(); |
1549 invalidate(); |
1539 return true; |
1550 return result; |
1540 } |
1551 } |
1541 |
1552 |
1542 delete anchor; |
1553 delete anchor; |
1543 |
1554 |
1544 return false; |
1555 return 0; |
|
1556 } |
|
1557 |
|
1558 |
|
1559 /*! |
|
1560 Set previously created anchor. Ownership is passed to layout. |
|
1561 |
|
1562 \param anchor anchor, created somewhere outside |
|
1563 \return reference to updated/created anchor (not necessary the same as in input parameter), or zero if something was wrong. |
|
1564 */ |
|
1565 HbAnchor *HbAnchorLayout::setAnchor( HbAnchor *anchor ) |
|
1566 { |
|
1567 Q_D( HbAnchorLayout ); |
|
1568 |
|
1569 HbAnchor *result = d->setAnchor( anchor ); |
|
1570 |
|
1571 if( result ) { |
|
1572 invalidate(); |
|
1573 return result; |
|
1574 } |
|
1575 |
|
1576 return 0; |
1545 } |
1577 } |
1546 |
1578 |
1547 |
1579 |
1548 /*! |
1580 /*! |
1549 Removes anchor (\a startId, \a startEdge, \a endNodeId, \a endEdge). |
1581 Removes anchor (\a startId, \a startEdge, \a endNodeId, \a endEdge). |
1559 Q_D( HbAnchorLayout ); |
1591 Q_D( HbAnchorLayout ); |
1560 bool modified = false; |
1592 bool modified = false; |
1561 |
1593 |
1562 for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) { |
1594 for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) { |
1563 HbAnchor* anchor = d->mAllAnchors[i]; |
1595 HbAnchor* anchor = d->mAllAnchors[i]; |
1564 if( ( anchor->mStartId == startNodeId && anchor->mStartEdge == startEdge && |
1596 if( ( anchor->startNodeId() == startNodeId && anchor->startEdge() == startEdge && |
1565 anchor->mEndId == endNodeId && anchor->mEndEdge == endEdge ) || |
1597 anchor->endNodeId() == endNodeId && anchor->endEdge() == endEdge ) || |
1566 ( anchor->mStartId == endNodeId && anchor->mStartEdge == endEdge && |
1598 ( anchor->startNodeId() == endNodeId && anchor->startEdge() == endEdge && |
1567 anchor->mEndId == startNodeId && anchor->mEndEdge == startEdge ) ){ |
1599 anchor->endNodeId() == startNodeId && anchor->endEdge() == startEdge ) ){ |
1568 delete d->mAllAnchors.takeAt(i); |
1600 delete d->mAllAnchors.takeAt(i); |
1569 modified = true; |
1601 modified = true; |
1570 break; |
|
1571 } |
1602 } |
1572 } |
1603 } |
1573 |
1604 |
1574 if (modified) { |
1605 if (modified) { |
1575 d->removeItemIfNeeded( d->mMeshMap.key( startNodeId ) ); |
1606 d->removeItemIfNeeded( d->mItemToNodeIdMap.key( startNodeId ) ); |
1576 d->removeItemIfNeeded( d->mMeshMap.key( endNodeId ) ); |
1607 d->removeItemIfNeeded( d->mItemToNodeIdMap.key( endNodeId ) ); |
1577 invalidate(); |
1608 invalidate(); |
1578 return true; |
1609 return true; |
1579 } |
1610 } |
1580 return false; |
1611 return false; |
1581 } |
1612 } |
1619 } |
1649 } |
1620 return false; |
1650 return false; |
1621 } |
1651 } |
1622 |
1652 |
1623 |
1653 |
|
1654 /*! |
|
1655 |
|
1656 Removes and deletes an anchor (\a anchor) from layout. |
|
1657 |
|
1658 If layout contains exactly the same anchor, with the same reference, then only this |
|
1659 one is removed and deleted. Otherwise all anchors with the same start and end points |
|
1660 are removed and deleted ( \a anchor is not deleted in this case because this instance |
|
1661 is not in layout ). |
|
1662 |
|
1663 Notice: The item will be removed from the layout if this is the last |
|
1664 anchor connecting the item. |
|
1665 |
|
1666 \param anchor anchor to be removed. |
|
1667 \return true if anchor was successfully removed, false otherwise |
|
1668 */ |
|
1669 bool HbAnchorLayout::removeAnchor( HbAnchor *anchor ) |
|
1670 { |
|
1671 Q_D( HbAnchorLayout ); |
|
1672 |
|
1673 if( d->mAllAnchors.removeOne( anchor ) ) { |
|
1674 d->removeItemIfNeeded( anchor->startItem() ); |
|
1675 d->removeItemIfNeeded( anchor->endItem() ); |
|
1676 delete anchor; |
|
1677 invalidate(); |
|
1678 return true; |
|
1679 } |
|
1680 |
|
1681 bool modified = true; |
|
1682 |
|
1683 for (int i = d->mAllAnchors.size() - 1; i >= 0; --i) { |
|
1684 HbAnchor* item = d->mAllAnchors[i]; |
|
1685 if( ( ( idConditionStartStart( item, anchor ) || itemConditionStartStart( item, anchor ) ) && |
|
1686 ( idConditionEndEnd( item, anchor ) || itemConditionEndEnd( item, anchor ) ) && |
|
1687 ( edgeConditionStartStart( item, anchor ) ) && |
|
1688 ( edgeConditionEndEnd( item, anchor ) ) ) // condition for same direction anchor |
|
1689 |
|
1690 || |
|
1691 |
|
1692 ( ( idConditionStartEnd( item, anchor ) || itemConditionStartEnd( item, anchor ) ) && |
|
1693 ( idConditionEndStart( item, anchor ) || itemConditionEndStart( item, anchor ) ) && |
|
1694 ( edgeConditionStartEnd( item, anchor ) ) && |
|
1695 ( edgeConditionEndStart( item, anchor ) ) ) ){ // condition for opposite direction anchor |
|
1696 delete d->mAllAnchors.takeAt(i); |
|
1697 modified = true; |
|
1698 break; |
|
1699 } |
|
1700 } |
|
1701 |
|
1702 if( modified ) { |
|
1703 d->removeItemIfNeeded( anchor->startItem() ); |
|
1704 d->removeItemIfNeeded( anchor->endItem() ); |
|
1705 invalidate(); |
|
1706 return true; |
|
1707 } |
|
1708 |
|
1709 |
|
1710 return modified; |
|
1711 } |
1624 |
1712 |
1625 /*! |
1713 /*! |
1626 Removes all anchors starting or ending to \a nodeId. |
1714 Removes all anchors starting or ending to \a nodeId. |
1627 Same is done with associated item |
1715 Same is done with associated item |
1628 |
1716 |
1692 |
1780 |
1693 if ( !nodeId.isNull() && ( item != 0 ) ) { |
1781 if ( !nodeId.isNull() && ( item != 0 ) ) { |
1694 |
1782 |
1695 for( int i = 0; i < d->mAllAnchors.size(); i++ ) { |
1783 for( int i = 0; i < d->mAllAnchors.size(); i++ ) { |
1696 HbAnchor *anchor = d->mAllAnchors.at(i); |
1784 HbAnchor *anchor = d->mAllAnchors.at(i); |
1697 if( anchor->mStartItem == item ) { |
1785 if( anchor->startItem() == item ) { |
1698 anchor->mStartId = nodeId; |
1786 anchor->d_ptr->mStartId = nodeId; |
1699 modified = true; |
1787 modified = true; |
1700 } else if( anchor->mStartId == nodeId ) { |
1788 } else if( anchor->startNodeId() == nodeId ) { |
1701 anchor->mStartItem = item; |
1789 anchor->d_ptr->mStartItem = item; |
1702 modified = true; |
1790 modified = true; |
1703 } |
1791 } |
1704 |
1792 |
1705 if( anchor->mEndItem == item ) { |
1793 if( anchor->endItem() == item ) { |
1706 anchor->mEndId = nodeId; |
1794 anchor->d_ptr->mEndId = nodeId; |
1707 modified = true; |
1795 modified = true; |
1708 } else if( anchor->mEndId == nodeId ) { |
1796 } else if( anchor->endNodeId() == nodeId ) { |
1709 anchor->mEndItem = item; |
1797 anchor->d_ptr->mEndItem = item; |
1710 modified = true; |
1798 modified = true; |
1711 } |
1799 } |
1712 |
1800 |
1713 } |
1801 } |
1714 |
1802 |
1715 // Remove previous item -> id. |
1803 // Remove previous item -> id. |
1716 HbMeshItemMapIterator it = d->mMeshMap.begin(); |
1804 ItemToNodeIdMapIterator it = d->mItemToNodeIdMap.begin(); |
1717 while ( it != d->mMeshMap.end() ) { |
1805 while ( it != d->mItemToNodeIdMap.end() ) { |
1718 if ( it.value() == nodeId ) { |
1806 if ( it.value() == nodeId ) { |
1719 it = d->mMeshMap.erase( it ); |
1807 it = d->mItemToNodeIdMap.erase( it ); |
1720 } else { |
1808 } else { |
1721 ++it; |
1809 ++it; |
1722 } |
1810 } |
1723 } |
1811 } |
1724 d->addItemIfNeeded( item ); |
1812 d->addItemIfNeeded( item ); |
1725 d->mMeshMap.insert( item, nodeId ); |
1813 d->mItemToNodeIdMap.insert( item, nodeId ); |
1726 } else { |
1814 } else { |
1727 return false; |
1815 return false; |
1728 } |
1816 } |
1729 |
1817 |
1730 if( modified ){ |
1818 if( modified ){ |