1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "qmlgraphicsitemnodeinstance.h"
35 #include <invalidnodeinstanceexception.h>
37 #include "bindingproperty.h"
38 #include "variantproperty.h"
40 #include <QDeclarativeExpression>
42 #include <private/qdeclarativeanchors_p.h>
43 #include <private/qdeclarativeanchors_p_p.h>
44 #include <private/qdeclarativeitem_p.h>
45 #include <private/qdeclarativeproperty_p.h>
46 #include <private/qdeclarativerectangle_p.h>
47 #include <private/qdeclarativepositioners_p.h>
48 #include <private/qdeclarativestategroup_p.h>
55 namespace QmlDesigner {
58 QmlGraphicsItemNodeInstance::QmlGraphicsItemNodeInstance(QDeclarativeItem *item)
59 : GraphicsObjectNodeInstance(item),
70 QmlGraphicsItemNodeInstance::~QmlGraphicsItemNodeInstance()
74 bool anyItemHasContent(QGraphicsItem *graphicsItem)
76 if (!graphicsItem->flags().testFlag(QGraphicsItem::ItemHasNoContents))
79 foreach (QGraphicsItem *childItem, graphicsItem->childItems()) {
80 if (anyItemHasContent(childItem))
87 QmlGraphicsItemNodeInstance::Pointer QmlGraphicsItemNodeInstance::create(QObject *object)
89 QDeclarativeItem *qmlGraphicsItem = dynamic_cast<QDeclarativeItem*>(object);
91 if (qmlGraphicsItem == 0)
92 throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
94 Pointer instance(new QmlGraphicsItemNodeInstance(qmlGraphicsItem));
96 instance->setHasContent(anyItemHasContent(qmlGraphicsItem));
97 qmlGraphicsItem->setFlag(QGraphicsItem::ItemHasNoContents, false);
99 if (qmlGraphicsItem->inherits("QDeclarativeText"))
100 instance->setResizable(false);
102 static_cast<QDeclarativeParserStatus*>(qmlGraphicsItem)->classBegin();
104 instance->populateResetValueHash();
109 bool QmlGraphicsItemNodeInstance::isQmlGraphicsItem() const
114 QSizeF QmlGraphicsItemNodeInstance::size() const
117 double implicitWidth = qmlGraphicsItem()->implicitWidth();
119 && implicitWidth // WORKAROUND
120 && qmlGraphicsItem()->width() <= 0
121 && implicitWidth != qmlGraphicsItem()->width()
122 && !hasBindingForProperty("width")) {
123 qmlGraphicsItem()->blockSignals(true);
124 qmlGraphicsItem()->setWidth(implicitWidth);
125 qmlGraphicsItem()->blockSignals(false);
128 double implicitHeight = qmlGraphicsItem()->implicitHeight();
130 && implicitWidth // WORKAROUND
131 && qmlGraphicsItem()->height() <= 0
132 && implicitHeight != qmlGraphicsItem()->height()
133 && !hasBindingForProperty("height")) {
134 qmlGraphicsItem()->blockSignals(true);
135 qmlGraphicsItem()->setHeight(implicitHeight);
136 qmlGraphicsItem()->blockSignals(false);
141 if (isRootNodeInstance()) {
143 qmlGraphicsItem()->blockSignals(true);
144 if (qmlGraphicsItem()->width() < 10.)
145 qmlGraphicsItem()->setWidth(100.);
146 qmlGraphicsItem()->blockSignals(false);
150 qmlGraphicsItem()->blockSignals(true);
151 if (qmlGraphicsItem()->height() < 10.)
152 qmlGraphicsItem()->setHeight(100.);
153 qmlGraphicsItem()->blockSignals(false);
157 return QSizeF(qmlGraphicsItem()->width(), qmlGraphicsItem()->height());
160 QRectF QmlGraphicsItemNodeInstance::boundingRect() const
163 double implicitWidth = qmlGraphicsItem()->implicitWidth();
165 && implicitWidth // WORKAROUND
166 && qmlGraphicsItem()->width() <= 0
167 && implicitWidth != qmlGraphicsItem()->width()
168 && !hasBindingForProperty("width")) {
169 qmlGraphicsItem()->blockSignals(true);
170 qmlGraphicsItem()->setWidth(implicitWidth);
171 qmlGraphicsItem()->blockSignals(false);
174 double implicitHeight = qmlGraphicsItem()->implicitHeight();
176 && implicitWidth // WORKAROUND
177 && qmlGraphicsItem()->height() <= 0
178 && implicitHeight != qmlGraphicsItem()->height()
179 && !hasBindingForProperty("height")) {
180 qmlGraphicsItem()->blockSignals(true);
181 qmlGraphicsItem()->setHeight(implicitHeight);
182 qmlGraphicsItem()->blockSignals(false);
187 if (isRootNodeInstance()) {
189 qmlGraphicsItem()->blockSignals(true);
190 if (qmlGraphicsItem()->width() < 10.)
191 qmlGraphicsItem()->setWidth(100.);
192 qmlGraphicsItem()->blockSignals(false);
196 qmlGraphicsItem()->blockSignals(true);
197 if (qmlGraphicsItem()->height() < 10.)
198 qmlGraphicsItem()->setHeight(100.);
199 qmlGraphicsItem()->blockSignals(false);
203 if (qmlGraphicsItem())
204 return qmlGraphicsItem()->boundingRect();
209 void QmlGraphicsItemNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
212 return; // states are only set by us
214 if (name == "height") {
215 m_height = value.toDouble();
222 if (name == "width") {
223 m_width = value.toDouble();
231 m_x = value.toDouble();
234 m_y = value.toDouble();
236 GraphicsObjectNodeInstance::setPropertyVariant(name, value);
241 void QmlGraphicsItemNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
244 return; // states are only set by us
246 GraphicsObjectNodeInstance::setPropertyBinding(name, expression);
249 QVariant QmlGraphicsItemNodeInstance::property(const QString &name) const
251 if (name == "width" && !hasBindingForProperty("width")) {
252 double implicitWidth = qmlGraphicsItem()->implicitWidth();
254 && implicitWidth // WORKAROUND
255 && qmlGraphicsItem()->width() <= 0
256 && implicitWidth != qmlGraphicsItem()->width()) {
257 qmlGraphicsItem()->blockSignals(true);
258 qmlGraphicsItem()->setWidth(implicitWidth);
259 qmlGraphicsItem()->blockSignals(false);
263 if (name == "height" && !hasBindingForProperty("height")) {
264 double implicitHeight = qmlGraphicsItem()->implicitHeight();
266 && implicitHeight // WORKAROUND
267 && qmlGraphicsItem()->width() <= 0
268 && implicitHeight != qmlGraphicsItem()->height()) {
269 qmlGraphicsItem()->blockSignals(true);
270 qmlGraphicsItem()->setHeight(implicitHeight);
271 qmlGraphicsItem()->blockSignals(false);
275 return GraphicsObjectNodeInstance::property(name);
278 void QmlGraphicsItemNodeInstance::resetHorizontal()
280 setPropertyVariant("x", m_x);
282 setPropertyVariant("width", m_width);
284 setPropertyVariant("width", qmlGraphicsItem()->implicitWidth());
288 void QmlGraphicsItemNodeInstance::resetVertical()
290 setPropertyVariant("y", m_y);
291 if (m_height > 0.0) {
292 setPropertyVariant("height", m_height);
294 setPropertyVariant("height", qmlGraphicsItem()->implicitWidth());
298 static void repositioning(QDeclarativeItem *item)
303 // QDeclarativeBasePositioner *positioner = qobject_cast<QDeclarativeBasePositioner*>(item);
305 // positioner->rePositioning();
307 if (item->parentObject())
308 repositioning(qobject_cast<QDeclarativeItem*>(item->parentObject()));
311 void QmlGraphicsItemNodeInstance::refresh()
313 repositioning(qmlGraphicsItem());
316 void QmlGraphicsItemNodeInstance::doComponentComplete()
318 if (qmlGraphicsItem()) {
319 if (static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(qmlGraphicsItem()))->componentComplete)
321 static_cast<QDeclarativeParserStatus*>(qmlGraphicsItem())->componentComplete();
322 QGraphicsItemPrivate::get(qmlGraphicsItem())->sendParentChangeNotification = 1;
325 graphicsObject()->update();
328 bool QmlGraphicsItemNodeInstance::isResizable() const
330 return m_isResizable && qmlGraphicsItem() && qmlGraphicsItem()->parentItem();
333 void QmlGraphicsItemNodeInstance::setResizable(bool resizeable)
335 m_isResizable = resizeable;
338 int QmlGraphicsItemNodeInstance::penWidth() const
340 QDeclarativeRectangle *rectangle = qobject_cast<QDeclarativeRectangle*>(object());
342 return rectangle->border()->width();
344 return GraphicsObjectNodeInstance::penWidth();
347 void QmlGraphicsItemNodeInstance::resetProperty(const QString &name)
349 if (name == "height") {
354 if (name == "width") {
366 if (name == "anchors.fill") {
367 anchors()->resetFill();
370 } else if (name == "anchors.centerIn") {
371 anchors()->resetCenterIn();
374 } else if (name == "anchors.top") {
375 anchors()->resetTop();
377 } else if (name == "anchors.left") {
378 anchors()->resetLeft();
380 } else if (name == "anchors.right") {
381 anchors()->resetRight();
383 } else if (name == "anchors.bottom") {
384 anchors()->resetBottom();
386 } else if (name == "anchors.horizontalCenter") {
387 anchors()->resetHorizontalCenter();
389 } else if (name == "anchors.verticalCenter") {
390 anchors()->resetVerticalCenter();
392 } else if (name == "anchors.baseline") {
393 anchors()->resetBaseline();
397 GraphicsObjectNodeInstance::resetProperty(name);
400 void QmlGraphicsItemNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const QString &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const QString &newParentProperty)
402 if (oldParentInstance && oldParentInstance->isPositioner()) {
403 setInPositioner(false);
407 GraphicsObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
409 if (newParentInstance && newParentInstance->isPositioner()) {
410 setInPositioner(true);
414 if (oldParentInstance && oldParentInstance->isPositioner() && !(newParentInstance && newParentInstance->isPositioner())) {
415 if (!hasBindingForProperty("x"))
416 setPropertyVariant("x", m_x);
418 if (!hasBindingForProperty("y"))
419 setPropertyVariant("y", m_y);
425 QDeclarativeAnchors::Anchor anchorLineFlagForName(const QString &name)
427 if (name == "anchors.top")
428 return QDeclarativeAnchors::TopAnchor;
430 if (name == "anchors.left")
431 return QDeclarativeAnchors::LeftAnchor;
433 if (name == "anchors.bottom")
434 return QDeclarativeAnchors::BottomAnchor;
436 if (name == "anchors.right")
437 return QDeclarativeAnchors::RightAnchor;
439 if (name == "anchors.horizontalCenter")
440 return QDeclarativeAnchors::HCenterAnchor;
442 if (name == "anchors.verticalCenter")
443 return QDeclarativeAnchors::VCenterAnchor;
445 if (name == "anchors.baseline")
446 return QDeclarativeAnchors::BaselineAnchor;
449 Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
450 return QDeclarativeAnchors::LeftAnchor;
453 QString propertyNameForAnchorLine(const QDeclarativeAnchorLine::AnchorLine &anchorLine)
456 case QDeclarativeAnchorLine::Left: return "left";
457 case QDeclarativeAnchorLine::Right: return "right";
458 case QDeclarativeAnchorLine::Top: return "top";
459 case QDeclarativeAnchorLine::Bottom: return "bottom";
460 case QDeclarativeAnchorLine::HCenter: return "horizontalCenter";
461 case QDeclarativeAnchorLine::VCenter: return "verticalCenter";
462 case QDeclarativeAnchorLine::Baseline: return "baseline";
463 case QDeclarativeAnchorLine::Invalid:
464 default: return QString();
468 bool isValidAnchorName(const QString &name)
470 static QStringList anchorNameList(QStringList() << "anchors.top"
474 << "anchors.verticalCenter"
475 << "anchors.horizontalCenter"
477 << "anchors.centerIn"
478 << "anchors.baseline");
480 return anchorNameList.contains(name);
483 QPair<QString, ServerNodeInstance> QmlGraphicsItemNodeInstance::anchor(const QString &name) const
485 if (!isValidAnchorName(name) || !hasAnchor(name))
486 return GraphicsObjectNodeInstance::anchor(name);
488 QObject *targetObject = 0;
491 if (name == "anchors.fill") {
492 targetObject = anchors()->fill();
493 } else if (name == "anchors.centerIn") {
494 targetObject = anchors()->centerIn();
496 QDeclarativeProperty metaProperty(object(), name, context());
497 if (!metaProperty.isValid())
498 return GraphicsObjectNodeInstance::anchor(name);
500 QDeclarativeAnchorLine anchorLine = metaProperty.read().value<QDeclarativeAnchorLine>();
501 if (anchorLine.anchorLine != QDeclarativeAnchorLine::Invalid) {
502 targetObject = anchorLine.item;
503 targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
508 if (targetObject && nodeInstanceServer()->hasInstanceForObject(targetObject)) {
509 return qMakePair(targetName, nodeInstanceServer()->instanceForObject(targetObject));
511 return GraphicsObjectNodeInstance::anchor(name);
515 QList<ServerNodeInstance> QmlGraphicsItemNodeInstance::stateInstances() const
517 QList<ServerNodeInstance> instanceList;
518 QList<QDeclarativeState *> stateList = QDeclarativeItemPrivate::get(qmlGraphicsItem())->_states()->states();
519 foreach(QDeclarativeState *state, stateList)
521 if (state && nodeInstanceServer()->hasInstanceForObject(state))
522 instanceList.append(nodeInstanceServer()->instanceForObject(state));
528 bool QmlGraphicsItemNodeInstance::hasAnchor(const QString &name) const
530 if (!isValidAnchorName(name))
533 if (name == "anchors.fill")
534 return anchors()->fill() != 0;
536 if (name == "anchors.centerIn")
537 return anchors()->centerIn() != 0;
539 if (name == "anchors.right")
540 return anchors()->right().item != 0;
542 if (name == "anchors.top")
543 return anchors()->top().item != 0;
545 if (name == "anchors.left")
546 return anchors()->left().item != 0;
548 if (name == "anchors.bottom")
549 return anchors()->bottom().item != 0;
551 if (name == "anchors.horizontalCenter")
552 return anchors()->horizontalCenter().item != 0;
554 if (name == "anchors.verticalCenter")
555 return anchors()->verticalCenter().item != 0;
557 if (name == "anchors.baseline")
558 return anchors()->baseline().item != 0;
560 return anchors()->usedAnchors().testFlag(anchorLineFlagForName(name));
563 bool isAnchoredTo(QDeclarativeItem *fromItem, QDeclarativeItem *toItem)
565 Q_ASSERT(dynamic_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(fromItem)));
566 QDeclarativeItemPrivate *fromItemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(fromItem));
567 QDeclarativeAnchors *anchors = fromItemPrivate->anchors();
568 return anchors->fill() == toItem
569 || anchors->centerIn() == toItem
570 || anchors->bottom().item == toItem
571 || anchors->top().item == toItem
572 || anchors->left().item == toItem
573 || anchors->right().item == toItem
574 || anchors->verticalCenter().item == toItem
575 || anchors->horizontalCenter().item == toItem
576 || anchors->baseline().item == toItem;
579 bool areChildrenAnchoredTo(QDeclarativeItem *fromItem, QDeclarativeItem *toItem)
581 foreach(QGraphicsItem *childGraphicsItem, fromItem->childItems()) {
582 QDeclarativeItem *childItem = qobject_cast<QDeclarativeItem*>(childGraphicsItem->toGraphicsObject());
584 if (isAnchoredTo(childItem, toItem))
587 if (areChildrenAnchoredTo(childItem, toItem))
595 bool QmlGraphicsItemNodeInstance::isAnchoredBySibling() const
597 if (qmlGraphicsItem()->parentItem()) {
598 foreach(QGraphicsItem *siblingGraphicsItem, qmlGraphicsItem()->parentItem()->childItems()) { // search in siblings for a anchor to this item
599 QDeclarativeItem *siblingItem = qobject_cast<QDeclarativeItem*>(siblingGraphicsItem->toGraphicsObject());
601 if (isAnchoredTo(siblingItem, qmlGraphicsItem()))
610 bool QmlGraphicsItemNodeInstance::isAnchoredByChildren() const
612 if (areChildrenAnchoredTo(qmlGraphicsItem(), qmlGraphicsItem())) // search in children for a anchor to this item
618 QDeclarativeItem *QmlGraphicsItemNodeInstance::qmlGraphicsItem() const
623 Q_ASSERT(qobject_cast<QDeclarativeItem*>(object()));
624 return static_cast<QDeclarativeItem*>(object());
627 QDeclarativeAnchors *QmlGraphicsItemNodeInstance::anchors() const
629 Q_ASSERT(dynamic_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(qmlGraphicsItem())));
630 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(qmlGraphicsItem()));
631 return itemPrivate->anchors();
634 } // namespace Internal
635 } // namespace QmlDesigner