From ed5d5f6f04cda1f7aa3ea66be5fefc0a85429794 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 27 May 2009 17:00:37 +1000 Subject: Better gradient support for Rect. --- demos/declarative/flickr/content/Progress.qml | 14 ++- demos/declarative/flickr/content/Slider.qml | 15 ++- doc/src/declarative/pics/gradient.png | Bin 0 -> 364 bytes doc/src/snippets/declarative/gradient.qml | 8 ++ examples/declarative/dial/dial.qml | 11 +- examples/declarative/xmldata/yahoonews.qml | 6 +- src/declarative/fx/qfxrect.cpp | 157 +++++++++++++++++--------- src/declarative/fx/qfxrect.h | 51 ++++++++- src/declarative/fx/qfxrect_p.h | 6 +- 9 files changed, 196 insertions(+), 72 deletions(-) create mode 100644 doc/src/declarative/pics/gradient.png create mode 100644 doc/src/snippets/declarative/gradient.qml diff --git a/demos/declarative/flickr/content/Progress.qml b/demos/declarative/flickr/content/Progress.qml index aa2a2e6..743c45e 100644 --- a/demos/declarative/flickr/content/Progress.qml +++ b/demos/declarative/flickr/content/Progress.qml @@ -4,8 +4,12 @@ Item { property var progress: 0 Rect { - id: Container; anchors.fill: parent; gradientColor: "#66000000"; - pen.color: "white"; pen.width: 0; color: "#66343434"; radius: height/2 - 2 + id: Container; anchors.fill: parent + pen.color: "white"; pen.width: 0; radius: height/2 - 2 + gradient: Gradient { + GradientStop { position: 0; color: "#66343434" } + GradientStop { position: 1.0; color: "#66000000" } + } } Rect { @@ -13,7 +17,11 @@ Item { y: 2; height: parent.height-4; x: 2; width: Math.max(parent.width * progress - 4, 0); opacity: width < 1 ? 0 : 1 - color: "lightsteelblue"; gradientColor: "steelblue"; radius: height/2 - 2 + gradient: Gradient { + GradientStop { position: 0; color: "lightsteelblue" } + GradientStop { position: 1.0; color: "steelblue" } + } + radius: height/2 - 2 } Text { diff --git a/demos/declarative/flickr/content/Slider.qml b/demos/declarative/flickr/content/Slider.qml index aae4631..6aff225 100644 --- a/demos/declarative/flickr/content/Slider.qml +++ b/demos/declarative/flickr/content/Slider.qml @@ -9,14 +9,21 @@ Item { property int xMax: Slider.width - Handle.width - 4 Rect { - id: Container; anchors.fill: parent; gradientColor: "#66000000"; - pen.color: "white"; pen.width: 0; color: "#66343434"; radius: 8 + id: Container; anchors.fill: parent + pen.color: "white"; pen.width: 0; radius: 8 + gradient: Gradient { + GradientStop { position: 0.0; color: "#66343434" }, + GradientStop { position: 1.0; color: "#66000000" } + } } Rect { id: Handle - x: Slider.width / 2 - Handle.width / 2; y: 2; width: 30; height: Slider.height-4 - color: "lightgray"; gradientColor: "gray"; radius: 6 + x: Slider.width / 2 - Handle.width / 2; y: 2; width: 30; height: Slider.height-4; radius: 6 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightgray" }, + GradientStop { position: 1.0; color: "gray" } + } MouseRegion { anchors.fill: parent; drag.target: parent diff --git a/doc/src/declarative/pics/gradient.png b/doc/src/declarative/pics/gradient.png new file mode 100644 index 0000000..5eefdd2 Binary files /dev/null and b/doc/src/declarative/pics/gradient.png differ diff --git a/doc/src/snippets/declarative/gradient.qml b/doc/src/snippets/declarative/gradient.qml new file mode 100644 index 0000000..28018b8 --- /dev/null +++ b/doc/src/snippets/declarative/gradient.qml @@ -0,0 +1,8 @@ +Rect { + width: 100; height: 100 + gradient: Gradient { + GradientStop { position: 0.0; color: "red" } + GradientStop { position: 0.33; color: "yellow" } + GradientStop { position: 1.0; color: "green" } + } +} diff --git a/examples/declarative/dial/dial.qml b/examples/declarative/dial/dial.qml index 5e09171..b183798 100644 --- a/examples/declarative/dial/dial.qml +++ b/examples/declarative/dial/dial.qml @@ -9,12 +9,19 @@ Rect { Rect { anchors.top: Dial.bottom x: 20; width: 160; height: 16 - color: "steelblue"; gradientColor: "lightsteelblue" + gradient: Gradient { + GradientStop { position: 0.0; color: "steelblue" } + GradientStop { position: 1.0; color: "lightsteelblue" } + } radius: 8; opacity: 0.7 Rect { id: Slider x: 2; y: 2; width: 30; height: 12 - color: "lightgray"; gradientColor: "gray"; radius: 6 + radius: 6 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightgray" } + GradientStop { position: 1.0; color: "gray" } + } MouseRegion { anchors.fill: parent drag.target: parent; drag.axis: "x"; drag.xmin: 2; drag.xmax: 128 diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml index a465cdd..206c85f 100644 --- a/examples/declarative/xmldata/yahoonews.qml +++ b/examples/declarative/xmldata/yahoonews.qml @@ -1,6 +1,8 @@ Rect { - color: "black" - gradientColor: "#AAAAAA" + gradient: Gradient { + GradientStop { position: 0; color: "black" } + GradientStop { position: 1.0; color: "#AAAAAA" } + } width: 600 height: 600 resources: [ diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index cc5afc3..4271022 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -45,6 +45,8 @@ QT_BEGIN_NAMESPACE QML_DEFINE_TYPE(QFxPen,Pen) +QML_DEFINE_TYPE(QFxGradientStop,GradientStop) +QML_DEFINE_TYPE(QFxGradient,Gradient) /*! \internal @@ -117,6 +119,57 @@ void QFxPen::setWidth(int w) } +/*! + \qmlclass GradientStop QFxGradientStop + \brief The GradientStop item defines the color at a position in a Gradient + + \sa Gradient +*/ + +/*! + \qmlproperty real GradientStop::position + \qmlproperty color GradientStop::color + + Sets a \e color at a \e position in a gradient. +*/ + +/*! + \qmlclass Gradient QFxGradient + \brief The Gradient item defines a gradient fill. + + A gradient is defined by two or more colors, which will be blended seemlessly. The + colors are specified at their position in the range 0.0 - 1.0 via + the GradientStop item. For example, the following code paints a + Rect with a gradient starting with red, blending to yellow at 1/3 of the + size of the Rect, and ending with Green: + + \table + \row + \o \image gradient.png + \o \quotefile doc/src/snippets/declarative/gradient.qml + \endtable + + \sa GradientStop +*/ + +/*! + \qmlproperty list Gradient::stops + This property holds the gradient stops describing the gradient. +*/ + +const QGradient *QFxGradient::gradient() const +{ + if (!m_gradient && !m_stops.isEmpty()) { + m_gradient = new QLinearGradient(0,0,0,1.0); + for (int i = 0; i < m_stops.count(); ++i) { + const QFxGradientStop *stop = m_stops.at(i); + m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode); + m_gradient->setColorAt(stop->position(), stop->color()); + } + } + + return m_gradient; +} QML_DEFINE_TYPE(QFxRect,Rect) @@ -215,6 +268,51 @@ QFxPen *QFxRect::pen() } /*! + \qmlproperty Gradient Rect::gradient + + The gradient to use to fill the rect. + + This property allows for the construction of simple vertical gradients. + Other gradients may by formed by adding rotation to the rect. + + \table + \row + \o \image declarative-rect_gradient.png + \o + \qml + Rect { y: 0; width: 80; height: 80; color: "lightsteelblue" } + Rect { y: 100; width: 80; height: 80 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightsteelblue" } + GradientStop { position: 1.0; color: "blue" } + } + } + Rect { rotation: 90; x: 80; y: 200; width: 80; height: 80 + gradient: Gradient { + GradientStop { position: 0.0; color: "lightsteelblue" } + GradientStop { position: 1.0; color: "blue" } + } + } + // The x offset is needed because the rotation is from the top left corner + \endqml + \endtable + + \sa Gradient, color +*/ +QFxGradient *QFxRect::gradient() const +{ + Q_D(const QFxRect); + return d->gradient; +} + +void QFxRect::setGradient(QFxGradient *gradient) +{ + Q_D(QFxRect); + d->gradient = gradient; +} + + +/*! \qmlproperty real Rect::radius This property holds the corner radius used to draw a rounded rect. @@ -358,42 +456,6 @@ QColor QFxRectPrivate::getColor() } } -/*! - \qmlproperty color Rect::gradientColor - This property holds the color to use at the base of the rectangle and blend upwards. - - This property allows for the easy construction of simple horizontal gradients. Other gradients may by formed by adding rotation to the rect. The gradient will blend linearly from the rect's main color to the color specified for gradient color. - - \qml - Rect { y: 0; width: 80; height: 80; color: "lightsteelblue" } - Rect { y: 100; width: 80; height: 80; color: "lightsteelblue"; gradientColor="blue" } - Rect { rotation: 90; x: 80; y: 200; width: 80; height: 80; color="lightsteelblue" - gradientColor: "blue" } - // The x offset is needed because the rotation is from the top left corner - \endqml - \image declarative-rect_gradient.png -*/ - -/*! - \property QFxRect::gradientColor - \brief The color to use at the base of the rectangle and blend upwards. -*/ - -QColor QFxRect::gradientColor() const -{ - Q_D(const QFxRect); - return d->_gradcolor; -} - -void QFxRect::setGradientColor(const QColor &c) -{ - Q_D(QFxRect); - if (d->_gradcolor == c) - return; - - d->_gradcolor = c; - update(); -} #if defined(QFX_RENDER_QPAINTER) void QFxRect::generateRoundedRect() @@ -485,16 +547,8 @@ void QFxRect::paintContents(QPainter &p) { Q_D(QFxRect); if (d->_radius > 0 || (d->_pen && d->_pen->isValid()) - || d->_gradcolor.isValid()) + || (d->gradient && d->gradient->gradient()) ) drawRect(p); - /* - QLinearGradient grad(0, 0, 0, height()); - grad.setColorAt(0, d->_color); - grad.setColorAt(1, d->_gradcolor); - p.setBrush(grad); - p.drawRect(0, 0, width(), height()); - p.setBrush(QBrush()); - */ else p.fillRect(QRect(0, 0, width(), height()), d->getColor()); } @@ -502,7 +556,7 @@ void QFxRect::paintContents(QPainter &p) void QFxRect::drawRect(QPainter &p) { Q_D(QFxRect); - if (d->_gradcolor.isValid() /*|| p.usingQt() */) { + if (d->gradient && d->gradient->gradient() /*|| p.usingQt() */) { // XXX This path is still slower than the image path // Image path won't work for gradients though QPainter::RenderHints oldHints = p.renderHints(); @@ -513,15 +567,8 @@ void QFxRect::drawRect(QPainter &p) } else { p.setPen(Qt::NoPen); } - if (d->_gradcolor.isValid()){ - QLinearGradient grad(0, 0, 0, height()); - grad.setColorAt(0, d->_color); - grad.setColorAt(1, d->_gradcolor); - p.setBrush(grad); - }else{ - p.setBrush(d->_color); - } - if (d->_radius) + p.setBrush(*d->gradient->gradient()); + if (d->_radius > 0.) p.drawRoundedRect(0, 0, width(), height(), d->_radius, d->_radius); else p.drawRect(0, 0, width(), height()); diff --git a/src/declarative/fx/qfxrect.h b/src/declarative/fx/qfxrect.h index 209a8ef..2c59914 100644 --- a/src/declarative/fx/qfxrect.h +++ b/src/declarative/fx/qfxrect.h @@ -79,6 +79,49 @@ private: }; QML_DECLARE_TYPE(QFxPen) +class Q_DECLARATIVE_EXPORT QFxGradientStop : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal position READ position WRITE setPosition) + Q_PROPERTY(QColor color READ color WRITE setColor) + +public: + QFxGradientStop(QObject *parent=0) : QObject(parent) {} + + qreal position() const { return m_position; } + void setPosition(qreal position) { m_position = position; } + + QColor color() const { return m_color; } + void setColor(const QColor &color) { m_color = color; } + +private: + qreal m_position; + QColor m_color; +}; +QML_DECLARE_TYPE(QFxGradientStop) + +class Q_DECLARATIVE_EXPORT QFxGradient : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QList *stops READ stops) + Q_CLASSINFO("DefaultProperty", "stops") + +public: + QFxGradient(QObject *parent=0) : QObject(parent), m_gradient(0), m_created(false) {} + + QList *stops() { return &m_stops; } + + const QGradient *gradient() const; + +private: + QList m_stops; + mutable QGradient *m_gradient; + mutable bool m_created; +}; +QML_DECLARE_TYPE(QFxGradient) + class QFxRectPrivate; class Q_DECLARATIVE_EXPORT QFxRect : public QFxItem { @@ -86,7 +129,7 @@ class Q_DECLARATIVE_EXPORT QFxRect : public QFxItem Q_PROPERTY(QColor color READ color WRITE setColor) Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor) - Q_PROPERTY(QColor gradientColor READ gradientColor WRITE setGradientColor) + Q_PROPERTY(QFxGradient *gradient READ gradient WRITE setGradient) Q_PROPERTY(QFxPen * pen READ pen) Q_PROPERTY(qreal radius READ radius WRITE setRadius) public: @@ -98,11 +141,11 @@ public: QColor tintColor() const; void setTintColor(const QColor &); - QColor gradientColor() const; - void setGradientColor(const QColor &); - QFxPen *pen(); + QFxGradient *gradient() const; + void setGradient(QFxGradient *gradient); + qreal radius() const; void setRadius(qreal radius); diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index 2fd555f..8faaa38 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -61,13 +61,15 @@ QT_BEGIN_NAMESPACE +class QFxGradient; + class QFxRectPrivate : public QFxItemPrivate { Q_DECLARE_PUBLIC(QFxRect) public: QFxRectPrivate() - : _pen(0), _radius(0) + : gradient(0), _pen(0), _radius(0) { } @@ -85,7 +87,7 @@ public: #endif QColor getColor(); QColor _color; - QColor _gradcolor; + QFxGradient *gradient; QColor _tintColor; QFxPen *pen() { if (!_pen) { -- cgit v0.12