1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "qmlgraphicsitemnodeinstance.h"
36 #include <invalidnodeinstanceexception.h>
38 #include "bindingproperty.h"
39 #include "variantproperty.h"
41 #include <QDeclarativeExpression>
43 #include <private/qdeclarativeanchors_p.h>
44 #include <private/qdeclarativeanchors_p_p.h>
45 #include <private/qdeclarativeitem_p.h>
46 #include <private/qdeclarativeproperty_p.h>
47 #include <private/qdeclarativerectangle_p.h>
48 #include <private/qdeclarativepositioners_p.h>
49 #include <private/qdeclarativestategroup_p.h>
56 namespace QmlDesigner {
59 QmlGraphicsItemNodeInstance::QmlGraphicsItemNodeInstance(QDeclarativeItem *item)
60 : GraphicsObjectNodeInstance(item),
71 QmlGraphicsItemNodeInstance::~QmlGraphicsItemNodeInstance()
75 bool anyItemHasContent(QGraphicsItem *graphicsItem)
77 if (!graphicsItem->flags().testFlag(QGraphicsItem::ItemHasNoContents))
80 foreach (QGraphicsItem *childItem, graphicsItem->childItems()) {
81 if (anyItemHasContent(childItem))
88 QmlGraphicsItemNodeInstance::Pointer QmlGraphicsItemNodeInstance::create(QObject *object)
90 QDeclarativeItem *qmlGraphicsItem = dynamic_cast<QDeclarativeItem*>(object);
92 if (qmlGraphicsItem == 0)
93 throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
95 Pointer instance(new QmlGraphicsItemNodeInstance(qmlGraphicsItem));
97 instance->setHasContent(anyItemHasContent(qmlGraphicsItem));
98 qmlGraphicsItem->setFlag(QGraphicsItem::ItemHasNoContents, false);
100 if (qmlGraphicsItem->inherits("QDeclarativeText"))
101 instance->setResizable(false);
103 static_cast<QDeclarativeParserStatus*>(qmlGraphicsItem)->classBegin();
105 instance->populateResetValueHash();
110 bool QmlGraphicsItemNodeInstance::isQmlGraphicsItem() const
115 QSizeF QmlGraphicsItemNodeInstance::size() const
118 double implicitWidth = qmlGraphicsItem()->implicitWidth();
120 && implicitWidth // WORKAROUND
121 && qmlGraphicsItem()->width() <= 0
122 && implicitWidth != qmlGraphicsItem()->width()
123 && !hasBindingForProperty("width")) {
124 qmlGraphicsItem()->blockSignals(true);
125 qmlGraphicsItem()->setWidth(implicitWidth);
126 qmlGraphicsItem()->blockSignals(false);
129 double implicitHeight = qmlGraphicsItem()->implicitHeight();
131 && implicitWidth // WORKAROUND
132 && qmlGraphicsItem()->height() <= 0
133 && implicitHeight != qmlGraphicsItem()->height()
134 && !hasBindingForProperty("height")) {
135 qmlGraphicsItem()->blockSignals(true);
136 qmlGraphicsItem()->setHeight(implicitHeight);
137 qmlGraphicsItem()->blockSignals(false);
142 if (isRootNodeInstance()) {
144 qmlGraphicsItem()->blockSignals(true);
145 if (qmlGraphicsItem()->width() < 10.)
146 qmlGraphicsItem()->setWidth(100.);
147 qmlGraphicsItem()->blockSignals(false);
151 qmlGraphicsItem()->blockSignals(true);
152 if (qmlGraphicsItem()->height() < 10.)
153 qmlGraphicsItem()->setHeight(100.);
154 qmlGraphicsItem()->blockSignals(false);
158 return QSizeF(qmlGraphicsItem()->width(), qmlGraphicsItem()->height());
161 QRectF QmlGraphicsItemNodeInstance::boundingRect() const
164 double implicitWidth = qmlGraphicsItem()->implicitWidth();
166 && implicitWidth // WORKAROUND
167 && qmlGraphicsItem()->width() <= 0
168 && implicitWidth != qmlGraphicsItem()->width()
169 && !hasBindingForProperty("width")) {
170 qmlGraphicsItem()->blockSignals(true);
171 qmlGraphicsItem()->setWidth(implicitWidth);
172 qmlGraphicsItem()->blockSignals(false);
175 double implicitHeight = qmlGraphicsItem()->implicitHeight();
177 && implicitWidth // WORKAROUND
178 && qmlGraphicsItem()->height() <= 0
179 && implicitHeight != qmlGraphicsItem()->height()
180 && !hasBindingForProperty("height")) {
181 qmlGraphicsItem()->blockSignals(true);
182 qmlGraphicsItem()->setHeight(implicitHeight);
183 qmlGraphicsItem()->blockSignals(false);
188 if (isRootNodeInstance()) {
190 qmlGraphicsItem()->blockSignals(true);
191 if (qmlGraphicsItem()->width() < 10.)
192 qmlGraphicsItem()->setWidth(100.);
193 qmlGraphicsItem()->blockSignals(false);
197 qmlGraphicsItem()->blockSignals(true);
198 if (qmlGraphicsItem()->height() < 10.)
199 qmlGraphicsItem()->setHeight(100.);
200 qmlGraphicsItem()->blockSignals(false);
204 if (qmlGraphicsItem())
205 return qmlGraphicsItem()->boundingRect();
210 void QmlGraphicsItemNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
213 return; // states are only set by us
215 if (name == "height") {
216 m_height = value.toDouble();
223 if (name == "width") {
224 m_width = value.toDouble();
232 m_x = value.toDouble();
235 m_y = value.toDouble();
237 GraphicsObjectNodeInstance::setPropertyVariant(name, value);
242 void QmlGraphicsItemNodeInstance::setPropertyBinding(const QString &name, const QString &expression)
245 return; // states are only set by us
247 GraphicsObjectNodeInstance::setPropertyBinding(name, expression);
250 QVariant QmlGraphicsItemNodeInstance::property(const QString &name) const
252 if (name == "width" && !hasBindingForProperty("width")) {
253 double implicitWidth = qmlGraphicsItem()->implicitWidth();
255 && implicitWidth // WORKAROUND
256 && qmlGraphicsItem()->width() <= 0
257 && implicitWidth != qmlGraphicsItem()->width()) {
258 qmlGraphicsItem()->blockSignals(true);
259 qmlGraphicsItem()->setWidth(implicitWidth);
260 qmlGraphicsItem()->blockSignals(false);
264 if (name == "height" && !hasBindingForProperty("height")) {
265 double implicitHeight = qmlGraphicsItem()->implicitHeight();
267 && implicitHeight // WORKAROUND
268 && qmlGraphicsItem()->width() <= 0
269 && implicitHeight != qmlGraphicsItem()->height()) {
270 qmlGraphicsItem()->blockSignals(true);
271 qmlGraphicsItem()->setHeight(implicitHeight);
272 qmlGraphicsItem()->blockSignals(false);
276 return GraphicsObjectNodeInstance::property(name);
279 void QmlGraphicsItemNodeInstance::resetHorizontal()
281 setPropertyVariant("x", m_x);
283 setPropertyVariant("width", m_width);
285 setPropertyVariant("width", qmlGraphicsItem()->implicitWidth());
289 void QmlGraphicsItemNodeInstance::resetVertical()
291 setPropertyVariant("y", m_y);
292 if (m_height > 0.0) {
293 setPropertyVariant("height", m_height);
295 setPropertyVariant("height", qmlGraphicsItem()->implicitWidth());
299 static void repositioning(QDeclarativeItem *item)
304 // QDeclarativeBasePositioner *positioner = qobject_cast<QDeclarativeBasePositioner*>(item);
306 // positioner->rePositioning();
308 if (item->parentObject())
309 repositioning(qobject_cast<QDeclarativeItem*>(item->parentObject()));
312 void QmlGraphicsItemNodeInstance::refresh()
314 repositioning(qmlGraphicsItem());
317 void QmlGraphicsItemNodeInstance::doComponentComplete()
319 if (qmlGraphicsItem()) {
320 if (static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(qmlGraphicsItem()))->componentComplete)
322 static_cast<QDeclarativeParserStatus*>(qmlGraphicsItem())->componentComplete();
323 QGraphicsItemPrivate::get(qmlGraphicsItem())->sendParentChangeNotification = 1;
326 graphicsObject()->update();
329 bool QmlGraphicsItemNodeInstance::isResizable() const
331 return m_isResizable && qmlGraphicsItem() && qmlGraphicsItem()->parentItem();
334 void QmlGraphicsItemNodeInstance::setResizable(bool resizeable)
336 m_isResizable = resizeable;
339 int QmlGraphicsItemNodeInstance::penWidth() const
341 QDeclarativeRectangle *rectangle = qobject_cast<QDeclarativeRectangle*>(object());
343 return rectangle->border()->width();
345 return GraphicsObjectNodeInstance::penWidth();
348 void QmlGraphicsItemNodeInstance::resetProperty(const QString &name)
350 if (name == "height") {
355 if (name == "width") {
367 if (name == "anchors.fill") {
368 anchors()->resetFill();
371 } else if (name == "anchors.centerIn") {
372 anchors()->resetCenterIn();
375 } else if (name == "anchors.top") {
376 anchors()->resetTop();
378 } else if (name == "anchors.left") {
379 anchors()->resetLeft();
381 } else if (name == "anchors.right") {
382 anchors()->resetRight();
384 } else if (name == "anchors.bottom") {
385 anchors()->resetBottom();
387 } else if (name == "anchors.horizontalCenter") {
388 anchors()->resetHorizontalCenter();
390 } else if (name == "anchors.verticalCenter") {
391 anchors()->resetVerticalCenter();
393 } else if (name == "anchors.baseline") {
394 anchors()->resetBaseline();
398 GraphicsObjectNodeInstance::resetProperty(name);
401 void QmlGraphicsItemNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParentInstance, const QString &oldParentProperty, const ObjectNodeInstance::Pointer &newParentInstance, const QString &newParentProperty)
403 if (oldParentInstance && oldParentInstance->isPositioner()) {
404 setInPositioner(false);
408 GraphicsObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
410 if (newParentInstance && newParentInstance->isPositioner()) {
411 setInPositioner(true);
415 if (oldParentInstance && oldParentInstance->isPositioner() && !(newParentInstance && newParentInstance->isPositioner())) {
416 if (!hasBindingForProperty("x"))
417 setPropertyVariant("x", m_x);
419 if (!hasBindingForProperty("y"))
420 setPropertyVariant("y", m_y);
426 QDeclarativeAnchors::Anchor anchorLineFlagForName(const QString &name)
428 if (name == "anchors.top")
429 return QDeclarativeAnchors::TopAnchor;
431 if (name == "anchors.left")
432 return QDeclarativeAnchors::LeftAnchor;
434 if (name == "anchors.bottom")
435 return QDeclarativeAnchors::BottomAnchor;
437 if (name == "anchors.right")
438 return QDeclarativeAnchors::RightAnchor;
440 if (name == "anchors.horizontalCenter")
441 return QDeclarativeAnchors::HCenterAnchor;
443 if (name == "anchors.verticalCenter")
444 return QDeclarativeAnchors::VCenterAnchor;
446 if (name == "anchors.baseline")
447 return QDeclarativeAnchors::BaselineAnchor;
450 Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
451 return QDeclarativeAnchors::LeftAnchor;
454 QString propertyNameForAnchorLine(const QDeclarativeAnchorLine::AnchorLine &anchorLine)
457 case QDeclarativeAnchorLine::Left: return "left";
458 case QDeclarativeAnchorLine::Right: return "right";
459 case QDeclarativeAnchorLine::Top: return "top";
460 case QDeclarativeAnchorLine::Bottom: return "bottom";
461 case QDeclarativeAnchorLine::HCenter: return "horizontalCenter";
462 case QDeclarativeAnchorLine::VCenter: return "verticalCenter";
463 case QDeclarativeAnchorLine::Baseline: return "baseline";
464 case QDeclarativeAnchorLine::Invalid:
465 default: return QString();
469 bool isValidAnchorName(const QString &name)
471 static QStringList anchorNameList(QStringList() << "anchors.top"
475 << "anchors.verticalCenter"
476 << "anchors.horizontalCenter"
478 << "anchors.centerIn"
479 << "anchors.baseline");
481 return anchorNameList.contains(name);
484 QPair<QString, ServerNodeInstance> QmlGraphicsItemNodeInstance::anchor(const QString &name) const
486 if (!isValidAnchorName(name) || !hasAnchor(name))
487 return GraphicsObjectNodeInstance::anchor(name);
489 QObject *targetObject = 0;
492 if (name == "anchors.fill") {
493 targetObject = anchors()->fill();
494 } else if (name == "anchors.centerIn") {
495 targetObject = anchors()->centerIn();
497 QDeclarativeProperty metaProperty(object(), name, context());
498 if (!metaProperty.isValid())
499 return GraphicsObjectNodeInstance::anchor(name);
501 QDeclarativeAnchorLine anchorLine = metaProperty.read().value<QDeclarativeAnchorLine>();
502 if (anchorLine.anchorLine != QDeclarativeAnchorLine::Invalid) {
503 targetObject = anchorLine.item;
504 targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
509 if (targetObject && nodeInstanceServer()->hasInstanceForObject(targetObject)) {
510 return qMakePair(targetName, nodeInstanceServer()->instanceForObject(targetObject));
512 return GraphicsObjectNodeInstance::anchor(name);
516 QList<ServerNodeInstance> QmlGraphicsItemNodeInstance::stateInstances() const
518 QList<ServerNodeInstance> instanceList;
519 QList<QDeclarativeState *> stateList = QDeclarativeItemPrivate::get(qmlGraphicsItem())->_states()->states();
520 foreach(QDeclarativeState *state, stateList)
522 if (state && nodeInstanceServer()->hasInstanceForObject(state))
523 instanceList.append(nodeInstanceServer()->instanceForObject(state));
529 bool QmlGraphicsItemNodeInstance::hasAnchor(const QString &name) const
531 if (!isValidAnchorName(name))
534 if (name == "anchors.fill")
535 return anchors()->fill() != 0;
537 if (name == "anchors.centerIn")
538 return anchors()->centerIn() != 0;
540 if (name == "anchors.right")
541 return anchors()->right().item != 0;
543 if (name == "anchors.top")
544 return anchors()->top().item != 0;
546 if (name == "anchors.left")
547 return anchors()->left().item != 0;
549 if (name == "anchors.bottom")
550 return anchors()->bottom().item != 0;
552 if (name == "anchors.horizontalCenter")
553 return anchors()->horizontalCenter().item != 0;
555 if (name == "anchors.verticalCenter")
556 return anchors()->verticalCenter().item != 0;
558 if (name == "anchors.baseline")
559 return anchors()->baseline().item != 0;
561 return anchors()->usedAnchors().testFlag(anchorLineFlagForName(name));
564 bool isAnchoredTo(QDeclarativeItem *fromItem, QDeclarativeItem *toItem)
566 Q_ASSERT(dynamic_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(fromItem)));
567 QDeclarativeItemPrivate *fromItemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(fromItem));
568 QDeclarativeAnchors *anchors = fromItemPrivate->anchors();
569 return anchors->fill() == toItem
570 || anchors->centerIn() == toItem
571 || anchors->bottom().item == toItem
572 || anchors->top().item == toItem
573 || anchors->left().item == toItem
574 || anchors->right().item == toItem
575 || anchors->verticalCenter().item == toItem
576 || anchors->horizontalCenter().item == toItem
577 || anchors->baseline().item == toItem;
580 bool areChildrenAnchoredTo(QDeclarativeItem *fromItem, QDeclarativeItem *toItem)
582 foreach(QGraphicsItem *childGraphicsItem, fromItem->childItems()) {
583 QDeclarativeItem *childItem = qobject_cast<QDeclarativeItem*>(childGraphicsItem->toGraphicsObject());
585 if (isAnchoredTo(childItem, toItem))
588 if (areChildrenAnchoredTo(childItem, toItem))
596 bool QmlGraphicsItemNodeInstance::isAnchoredBySibling() const
598 if (qmlGraphicsItem()->parentItem()) {
599 foreach(QGraphicsItem *siblingGraphicsItem, qmlGraphicsItem()->parentItem()->childItems()) { // search in siblings for a anchor to this item
600 QDeclarativeItem *siblingItem = qobject_cast<QDeclarativeItem*>(siblingGraphicsItem->toGraphicsObject());
602 if (isAnchoredTo(siblingItem, qmlGraphicsItem()))
611 bool QmlGraphicsItemNodeInstance::isAnchoredByChildren() const
613 if (areChildrenAnchoredTo(qmlGraphicsItem(), qmlGraphicsItem())) // search in children for a anchor to this item
619 QDeclarativeItem *QmlGraphicsItemNodeInstance::qmlGraphicsItem() const
624 Q_ASSERT(qobject_cast<QDeclarativeItem*>(object()));
625 return static_cast<QDeclarativeItem*>(object());
628 QDeclarativeAnchors *QmlGraphicsItemNodeInstance::anchors() const
630 Q_ASSERT(dynamic_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(qmlGraphicsItem())));
631 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(qmlGraphicsItem()));
632 return itemPrivate->anchors();
635 } // namespace Internal
636 } // namespace QmlDesigner