Initial import from qtquick2.
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgrectangle.cpp
1 // Commit: acc903853d5ac54d646d324b7386c998bc07d464
2 /****************************************************************************
3 **
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 **
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** No Commercial Usage
12 ** This file contains pre-release code and may not be distributed.
13 ** You may use this file in accordance with the terms and conditions
14 ** contained in the Technology Preview License Agreement accompanying
15 ** this package.
16 **
17 ** 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.
24 **
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.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 **
39 ** $QT_END_LICENSE$
40 **
41 ****************************************************************************/
42
43 #include "qsgrectangle_p.h"
44 #include "qsgrectangle_p_p.h"
45
46 #include <private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
48
49 #include <QtGui/qpixmapcache.h>
50 #include <QtCore/qstringbuilder.h>
51 #include <QtCore/qmath.h>
52
53 QT_BEGIN_NAMESPACE
54
55 // XXX todo - should we change rectangle to draw entirely within its width/height?
56
57 QSGPen::QSGPen(QObject *parent)
58 : QObject(parent), _width(1), _color("#000000"), _valid(false)
59 {
60 }
61
62 QColor QSGPen::color() const 
63
64     return _color; 
65 }
66
67 void QSGPen::setColor(const QColor &c)
68 {
69     _color = c;
70     _valid = (_color.alpha() && _width >= 1) ? true : false;
71     emit penChanged();
72 }
73
74 int QSGPen::width() const 
75
76     return _width; 
77 }
78
79 void QSGPen::setWidth(int w)
80 {
81     if (_width == w && _valid)
82         return;
83
84     _width = w;
85     _valid = (_color.alpha() && _width >= 1) ? true : false;
86     emit penChanged();
87 }
88
89 bool QSGPen::isValid() const
90
91     return _valid; 
92 }
93
94 QSGGradientStop::QSGGradientStop(QObject *parent) 
95 : QObject(parent) 
96 {
97 }
98
99 qreal QSGGradientStop::position() const 
100
101     return m_position; 
102 }
103
104 void QSGGradientStop::setPosition(qreal position) 
105
106     m_position = position; updateGradient(); 
107 }
108
109 QColor QSGGradientStop::color() const 
110
111     return m_color; 
112 }
113
114 void QSGGradientStop::setColor(const QColor &color) 
115
116     m_color = color; updateGradient(); 
117 }
118
119 void QSGGradientStop::updateGradient()
120 {
121     if (QSGGradient *grad = qobject_cast<QSGGradient*>(parent()))
122         grad->doUpdate();
123 }
124
125 QSGGradient::QSGGradient(QObject *parent) 
126 : QObject(parent), m_gradient(0) 
127 {
128 }
129
130 QSGGradient::~QSGGradient() 
131
132     delete m_gradient; 
133 }
134
135 QDeclarativeListProperty<QSGGradientStop> QSGGradient::stops() 
136
137     return QDeclarativeListProperty<QSGGradientStop>(this, m_stops); 
138 }
139
140 const QGradient *QSGGradient::gradient() const
141 {
142     if (!m_gradient && !m_stops.isEmpty()) {
143         m_gradient = new QLinearGradient(0,0,0,1.0);
144         for (int i = 0; i < m_stops.count(); ++i) {
145             const QSGGradientStop *stop = m_stops.at(i);
146             m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
147             m_gradient->setColorAt(stop->position(), stop->color());
148         }
149     }
150
151     return m_gradient;
152 }
153
154 void QSGGradient::doUpdate()
155 {
156     delete m_gradient;
157     m_gradient = 0;
158     emit updated();
159 }
160
161 int QSGRectanglePrivate::doUpdateSlotIdx = -1;
162
163 QSGRectangle::QSGRectangle(QSGItem *parent)
164 : QSGItem(*(new QSGRectanglePrivate), parent)
165 {
166     setFlag(ItemHasContents);
167 }
168
169 void QSGRectangle::doUpdate()
170 {
171     Q_D(QSGRectangle);
172     const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
173     d->setPaintMargin((pw+1)/2);
174     update();
175 }
176
177 QSGPen *QSGRectangle::border()
178 {
179     Q_D(QSGRectangle);
180     return d->getPen();
181 }
182
183 QSGGradient *QSGRectangle::gradient() const
184 {
185     Q_D(const QSGRectangle);
186     return d->gradient;
187 }
188
189 void QSGRectangle::setGradient(QSGGradient *gradient)
190 {
191     Q_D(QSGRectangle);
192     if (d->gradient == gradient)
193         return;
194     static int updatedSignalIdx = -1;
195     if (updatedSignalIdx < 0)
196         updatedSignalIdx = QSGGradient::staticMetaObject.indexOfSignal("updated()");
197     if (d->doUpdateSlotIdx < 0)
198         d->doUpdateSlotIdx = QSGRectangle::staticMetaObject.indexOfSlot("doUpdate()");
199     if (d->gradient)
200         QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
201     d->gradient = gradient;
202     if (d->gradient)
203         QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
204     update();
205 }
206
207 qreal QSGRectangle::radius() const
208 {
209     Q_D(const QSGRectangle);
210     return d->radius;
211 }
212
213 void QSGRectangle::setRadius(qreal radius)
214 {
215     Q_D(QSGRectangle);
216     if (d->radius == radius)
217         return;
218
219     d->radius = radius;
220     update();
221     emit radiusChanged();
222 }
223
224 QColor QSGRectangle::color() const
225 {
226     Q_D(const QSGRectangle);
227     return d->color;
228 }
229
230 void QSGRectangle::setColor(const QColor &c)
231 {
232     Q_D(QSGRectangle);
233     if (d->color == c)
234         return;
235
236     d->color = c;
237     update();
238     emit colorChanged();
239 }
240
241 QSGNode *QSGRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
242 {
243     Q_UNUSED(data);
244     Q_D(QSGRectangle);
245
246     if (width() <= 0 || height() <= 0) {
247         delete oldNode;
248         return 0;
249     }
250
251     QSGRectangleNode *rectangle = static_cast<QSGRectangleNode *>(oldNode);
252     if (!rectangle) rectangle = d->sceneGraphContext()->createRectangleNode();
253
254     rectangle->setRect(QRectF(0, 0, width(), height()));
255     rectangle->setColor(d->color);
256
257     if (d->pen && d->pen->isValid()) {
258         rectangle->setPenColor(d->pen->color());
259         rectangle->setPenWidth(d->pen->width());
260     } else {
261         rectangle->setPenColor(QColor());
262         rectangle->setPenWidth(0);
263     }
264
265     rectangle->setRadius(d->radius);
266
267     QGradientStops stops;
268     if (d->gradient) {
269         QList<QSGGradientStop *> qxstops = d->gradient->m_stops;
270         for (int i = 0; i < qxstops.size(); ++i)
271             stops.append(QGradientStop(qxstops.at(i)->position(), qxstops.at(i)->color()));
272     }
273     rectangle->setGradientStops(stops);
274
275     rectangle->update();
276
277     return rectangle;
278 }
279
280 QRectF QSGRectangle::boundingRect() const
281 {
282     Q_D(const QSGRectangle);
283     return QRectF(-d->paintmargin, -d->paintmargin, width()+d->paintmargin*2, height()+d->paintmargin*2);
284 }
285
286 QT_END_NAMESPACE