cd33115cc1ef255114d9a1d1bd37d256736c4ad8
[profile/ivi/qtdeclarative.git] / src / qtquick1 / graphicsitems / qdeclarativepath.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "QtQuick1/private/qdeclarativepath_p.h"
43 #include "QtQuick1/private/qdeclarativepath_p_p.h"
44
45 #include <QSet>
46 #include <QTime>
47
48 #include <private/qbezier_p.h>
49 #include <QtCore/qmath.h>
50 #include <QtCore/qnumeric.h>
51
52 QT_BEGIN_NAMESPACE
53
54
55
56 /*!
57     \qmlclass PathElement QDeclarative1PathElement
58     \inqmlmodule QtQuick 1
59     \ingroup qml-view-elements
60     \since QtQuick 1.0
61     \brief PathElement is the base path type.
62
63     This type is the base for all path types.  It cannot
64     be instantiated.
65
66     \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
67 */
68
69 /*!
70     \qmlclass Path QDeclarative1Path
71     \inqmlmodule QtQuick 1
72     \ingroup qml-view-elements
73     \since QtQuick 1.0
74     \brief A Path object defines a path for use by \l PathView.
75
76     A Path is composed of one or more path segments - PathLine, PathQuad,
77     PathCubic.
78
79     The spacing of the items along the Path can be adjusted via a
80     PathPercent object.
81
82     PathAttribute allows named attributes with values to be defined
83     along the path.
84
85     \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
86 */
87 QDeclarative1Path::QDeclarative1Path(QObject *parent)
88  : QObject(*(new QDeclarative1PathPrivate), parent)
89 {
90 }
91
92 QDeclarative1Path::~QDeclarative1Path()
93 {
94 }
95
96 /*!
97     \qmlproperty real QtQuick1::Path::startX
98     \qmlproperty real QtQuick1::Path::startY
99     These properties hold the starting position of the path.
100 */
101 qreal QDeclarative1Path::startX() const
102 {
103     Q_D(const QDeclarative1Path);
104     return d->startX;
105 }
106
107 void QDeclarative1Path::setStartX(qreal x)
108 {
109     Q_D(QDeclarative1Path);
110     if (qFuzzyCompare(x, d->startX))
111         return;
112     d->startX = x;
113     emit startXChanged();
114     processPath();
115 }
116
117 qreal QDeclarative1Path::startY() const
118 {
119     Q_D(const QDeclarative1Path);
120     return d->startY;
121 }
122
123 void QDeclarative1Path::setStartY(qreal y)
124 {
125     Q_D(QDeclarative1Path);
126     if (qFuzzyCompare(y, d->startY))
127         return;
128     d->startY = y;
129     emit startYChanged();
130     processPath();
131 }
132
133 /*!
134     \qmlproperty bool QtQuick1::Path::closed
135     This property holds whether the start and end of the path are identical.
136 */
137 bool QDeclarative1Path::isClosed() const
138 {
139     Q_D(const QDeclarative1Path);
140     return d->closed;
141 }
142
143 /*!
144     \qmlproperty list<PathElement> QtQuick1::Path::pathElements
145     This property holds the objects composing the path.
146
147     \default
148
149     A path can contain the following path objects:
150     \list
151         \i \l PathLine - a straight line to a given position.
152         \i \l PathQuad - a quadratic Bezier curve to a given position with a control point.
153         \i \l PathCubic - a cubic Bezier curve to a given position with two control points.
154         \i \l PathAttribute - an attribute at a given position in the path.
155         \i \l PathPercent - a way to spread out items along various segments of the path.
156     \endlist
157
158     \snippet doc/src/snippets/qtquick1/pathview/pathattributes.qml 2
159 */
160
161 QDeclarativeListProperty<QDeclarative1PathElement> QDeclarative1Path::pathElements()
162 {
163     Q_D(QDeclarative1Path);
164     return QDeclarativeListProperty<QDeclarative1PathElement>(this, d->_pathElements);
165 }
166
167 void QDeclarative1Path::interpolate(int idx, const QString &name, qreal value)
168 {
169     Q_D(QDeclarative1Path);
170     if (!idx)
171         return;
172
173     qreal lastValue = 0;
174     qreal lastPercent = 0;
175     int search = idx - 1;
176     while(search >= 0) {
177         const AttributePoint &point = d->_attributePoints.at(search);
178         if (point.values.contains(name)) {
179             lastValue = point.values.value(name);
180             lastPercent = point.origpercent;
181             break;
182         }
183         --search;
184     }
185
186     ++search;
187
188     const AttributePoint &curPoint = d->_attributePoints.at(idx);
189
190     for (int ii = search; ii < idx; ++ii) {
191         AttributePoint &point = d->_attributePoints[ii];
192
193         qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
194         point.values.insert(name, val);
195     }
196 }
197
198 void QDeclarative1Path::endpoint(const QString &name)
199 {
200     Q_D(QDeclarative1Path);
201     const AttributePoint &first = d->_attributePoints.first();
202     qreal val = first.values.value(name);
203     for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
204         const AttributePoint &point = d->_attributePoints.at(ii);
205         if (point.values.contains(name)) {
206             for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
207                 AttributePoint &setPoint = d->_attributePoints[jj];
208                 setPoint.values.insert(name, val);
209             }
210             return;
211         }
212     }
213 }
214
215 void QDeclarative1Path::processPath()
216 {
217     Q_D(QDeclarative1Path);
218
219     if (!d->componentComplete)
220         return;
221
222     d->_pointCache.clear();
223     d->_attributePoints.clear();
224     d->_path = QPainterPath();
225
226     AttributePoint first;
227     for (int ii = 0; ii < d->_attributes.count(); ++ii)
228         first.values[d->_attributes.at(ii)] = 0;
229     d->_attributePoints << first;
230
231     d->_path.moveTo(d->startX, d->startY);
232
233     QDeclarative1Curve *lastCurve = 0;
234     foreach (QDeclarative1PathElement *pathElement, d->_pathElements) {
235         if (QDeclarative1Curve *curve = qobject_cast<QDeclarative1Curve *>(pathElement)) {
236             curve->addToPath(d->_path);
237             AttributePoint p;
238             p.origpercent = d->_path.length();
239             d->_attributePoints << p;
240             lastCurve = curve;
241         } else if (QDeclarative1PathAttribute *attribute = qobject_cast<QDeclarative1PathAttribute *>(pathElement)) {
242             AttributePoint &point = d->_attributePoints.last();
243             point.values[attribute->name()] = attribute->value();
244             interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
245         } else if (QDeclarative1PathPercent *percent = qobject_cast<QDeclarative1PathPercent *>(pathElement)) {
246             AttributePoint &point = d->_attributePoints.last();
247             point.values[QLatin1String("_qfx_percent")] = percent->value();
248             interpolate(d->_attributePoints.count() - 1, QLatin1String("_qfx_percent"), percent->value());
249         }
250     }
251
252     // Fixup end points
253     const AttributePoint &last = d->_attributePoints.last();
254     for (int ii = 0; ii < d->_attributes.count(); ++ii) {
255         if (!last.values.contains(d->_attributes.at(ii)))
256             endpoint(d->_attributes.at(ii));
257     }
258
259     // Adjust percent
260     qreal length = d->_path.length();
261     qreal prevpercent = 0;
262     qreal prevorigpercent = 0;
263     for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
264         const AttributePoint &point = d->_attributePoints.at(ii);
265         if (point.values.contains(QLatin1String("_qfx_percent"))) { //special string for QDeclarative1PathPercent
266             if ( ii > 0) {
267                 qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
268                             (point.values.value(QLatin1String("_qfx_percent"))-prevpercent);
269                 d->_attributePoints[ii].scale = scale;
270             }
271             d->_attributePoints[ii].origpercent /= length;
272             d->_attributePoints[ii].percent = point.values.value(QLatin1String("_qfx_percent"));
273             prevorigpercent = d->_attributePoints[ii].origpercent;
274             prevpercent = d->_attributePoints[ii].percent;
275         } else {
276             d->_attributePoints[ii].origpercent /= length;
277             d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
278         }
279     }
280
281     d->closed = lastCurve && d->startX == lastCurve->x() && d->startY == lastCurve->y();
282
283     emit changed();
284 }
285
286 void QDeclarative1Path::classBegin()
287 {
288     Q_D(QDeclarative1Path);
289     d->componentComplete = false;
290 }
291
292 void QDeclarative1Path::componentComplete()
293 {
294     Q_D(QDeclarative1Path);
295     QSet<QString> attrs;
296     d->componentComplete = true;
297
298     // First gather up all the attributes
299     foreach (QDeclarative1PathElement *pathElement, d->_pathElements) {
300         if (QDeclarative1PathAttribute *attribute =
301             qobject_cast<QDeclarative1PathAttribute *>(pathElement))
302             attrs.insert(attribute->name());
303     }
304     d->_attributes = attrs.toList();
305
306     processPath();
307
308     foreach (QDeclarative1PathElement *pathElement, d->_pathElements)
309         connect(pathElement, SIGNAL(changed()), this, SLOT(processPath()));
310 }
311
312 QPainterPath QDeclarative1Path::path() const
313 {
314     Q_D(const QDeclarative1Path);
315     return d->_path;
316 }
317
318 QStringList QDeclarative1Path::attributes() const
319 {
320     Q_D(const QDeclarative1Path);
321     if (!d->componentComplete) {
322         QSet<QString> attrs;
323
324         // First gather up all the attributes
325         foreach (QDeclarative1PathElement *pathElement, d->_pathElements) {
326             if (QDeclarative1PathAttribute *attribute =
327                 qobject_cast<QDeclarative1PathAttribute *>(pathElement))
328                 attrs.insert(attribute->name());
329         }
330         return attrs.toList();
331     }
332     return d->_attributes;
333 }
334
335 static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
336 {
337     const int lastElement = path.elementCount() - 1;
338     for (int i=*from; i <= lastElement; ++i) {
339         const QPainterPath::Element &e = path.elementAt(i);
340
341         switch (e.type) {
342         case QPainterPath::MoveToElement:
343             break;
344         case QPainterPath::LineToElement:
345         {
346             QLineF line(path.elementAt(i-1), e);
347             *bezLength = line.length();
348             QPointF a = path.elementAt(i-1);
349             QPointF delta = e - a;
350             *from = i+1;
351             return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
352         }
353         case QPainterPath::CurveToElement:
354         {
355             QBezier b = QBezier::fromPoints(path.elementAt(i-1),
356                                             e,
357                                             path.elementAt(i+1),
358                                             path.elementAt(i+2));
359             *bezLength = b.length();
360             *from = i+3;
361             return b;
362         }
363         default:
364             break;
365         }
366     }
367     *from = lastElement;
368     *bezLength = 0;
369     return QBezier();
370 }
371
372 void QDeclarative1Path::createPointCache() const
373 {
374     Q_D(const QDeclarative1Path);
375     qreal pathLength = d->_path.length();
376     if (pathLength <= 0 || qIsNaN(pathLength))
377         return;
378     // more points means less jitter between items as they move along the
379     // path, but takes longer to generate
380     const int points = qCeil(pathLength*5);
381     const int lastElement = d->_path.elementCount() - 1;
382     d->_pointCache.resize(points+1);
383
384     int currElement = 0;
385     qreal bezLength = 0;
386     QBezier currBez = nextBezier(d->_path, &currElement, &bezLength);
387     qreal currLength = bezLength;
388     qreal epc = currLength / pathLength;
389
390     for (int i = 0; i < d->_pointCache.size(); i++) {
391         //find which set we are in
392         qreal prevPercent = 0;
393         qreal prevOrigPercent = 0;
394         for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
395             qreal percent = qreal(i)/points;
396             const AttributePoint &point = d->_attributePoints.at(ii);
397             if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
398                 qreal elementPercent = (percent - prevPercent);
399
400                 qreal spc = prevOrigPercent + elementPercent * point.scale;
401
402                 while (spc > epc) {
403                     if (currElement > lastElement)
404                         break;
405                     currBez = nextBezier(d->_path, &currElement, &bezLength);
406                     if (bezLength == 0.0) {
407                         currLength = pathLength;
408                         epc = 1.0;
409                         break;
410                     }
411                     currLength += bezLength;
412                     epc = currLength / pathLength;
413                 }
414                 qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
415                 d->_pointCache[i] = currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
416                 break;
417             }
418             prevOrigPercent = point.origpercent;
419             prevPercent = point.percent;
420         }
421     }
422 }
423
424 QPointF QDeclarative1Path::pointAt(qreal p) const
425 {
426     Q_D(const QDeclarative1Path);
427     if (d->_pointCache.isEmpty()) {
428         createPointCache();
429         if (d->_pointCache.isEmpty())
430             return QPointF();
431     }
432     int idx = qRound(p*d->_pointCache.size());
433     if (idx >= d->_pointCache.size())
434         idx = d->_pointCache.size() - 1;
435     else if (idx < 0)
436         idx = 0;
437     return d->_pointCache.at(idx);
438 }
439
440 qreal QDeclarative1Path::attributeAt(const QString &name, qreal percent) const
441 {
442     Q_D(const QDeclarative1Path);
443     if (percent < 0 || percent > 1)
444         return 0;
445
446     for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
447         const AttributePoint &point = d->_attributePoints.at(ii);
448
449         if (point.percent == percent) {
450             return point.values.value(name);
451         } else if (point.percent > percent) {
452             qreal lastValue =
453                 ii?(d->_attributePoints.at(ii - 1).values.value(name)):0;
454             qreal lastPercent =
455                 ii?(d->_attributePoints.at(ii - 1).percent):0;
456             qreal curValue = point.values.value(name);
457             qreal curPercent = point.percent;
458
459             return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
460         }
461     }
462
463     return 0;
464 }
465
466 /****************************************************************************/
467
468 qreal QDeclarative1Curve::x() const
469 {
470     return _x;
471 }
472
473 void QDeclarative1Curve::setX(qreal x)
474 {
475     if (_x != x) {
476         _x = x;
477         emit xChanged();
478         emit changed();
479     }
480 }
481
482 qreal QDeclarative1Curve::y() const
483 {
484     return _y;
485 }
486
487 void QDeclarative1Curve::setY(qreal y)
488 {
489     if (_y != y) {
490         _y = y;
491         emit yChanged();
492         emit changed();
493     }
494 }
495
496 /****************************************************************************/
497
498 /*!
499     \qmlclass PathAttribute QDeclarative1PathAttribute
500     \inqmlmodule QtQuick 1
501     \ingroup qml-view-elements
502     \since QtQuick 1.0
503     \brief The PathAttribute allows setting an attribute at a given position in a Path.
504
505     The PathAttribute object allows attributes consisting of a name and
506     a value to be specified for various points along a path.  The
507     attributes are exposed to the delegate as
508     \l{qdeclarativeintroduction.html#attached-properties} {Attached Properties}.
509     The value of an attribute at any particular point along the path is interpolated
510     from the PathAttributes bounding that point.
511
512     The example below shows a path with the items scaled to 30% with
513     opacity 50% at the top of the path and scaled 100% with opacity
514     100% at the bottom.  Note the use of the PathView.iconScale and
515     PathView.iconOpacity attached properties to set the scale and opacity
516     of the delegate.
517
518     \table
519     \row
520     \o \image declarative-pathattribute.png
521     \o
522     \snippet doc/src/snippets/qtquick1/pathview/pathattributes.qml 0
523     (see the PathView documentation for the specification of ContactModel.qml
524      used for ContactModel above.)
525     \endtable
526
527
528     \sa Path
529 */
530
531 /*!
532     \qmlproperty string QtQuick1::PathAttribute::name
533     This property holds the name of the attribute to change.
534
535     This attribute will be available to the delegate as PathView.<name>
536
537     Note that using an existing Item property name such as "opacity" as an
538     attribute is allowed.  This is because path attributes add a new
539     \l{qdeclarativeintroduction.html#attached-properties} {Attached Property}
540     which in no way clashes with existing properties.
541 */
542
543 /*!
544     the name of the attribute to change.
545 */
546
547 QString QDeclarative1PathAttribute::name() const
548 {
549     return _name;
550 }
551
552 void QDeclarative1PathAttribute::setName(const QString &name)
553 {
554     if (_name == name)
555         return;
556      _name = name;
557     emit nameChanged();
558 }
559
560 /*!
561    \qmlproperty real QtQuick1::PathAttribute::value
562    This property holds the value for the attribute.
563
564    The value specified can be used to influence the visual appearance
565    of an item along the path. For example, the following Path specifies
566    an attribute named \e itemRotation, which has the value \e 0 at the
567    beginning of the path, and the value 90 at the end of the path.
568
569    \qml
570    Path {
571        startX: 0
572        startY: 0
573        PathAttribute { name: "itemRotation"; value: 0 }
574        PathLine { x: 100; y: 100 }
575        PathAttribute { name: "itemRotation"; value: 90 }
576    }
577    \endqml
578
579    In our delegate, we can then bind the \e rotation property to the
580    \l{qdeclarativeintroduction.html#attached-properties} {Attached Property}
581    \e PathView.itemRotation created for this attribute.
582
583    \qml
584    Rectangle {
585        width: 10; height: 10
586        rotation: PathView.itemRotation
587    }
588    \endqml
589
590    As each item is positioned along the path, it will be rotated accordingly:
591    an item at the beginning of the path with be not be rotated, an item at
592    the end of the path will be rotated 90 degrees, and an item mid-way along
593    the path will be rotated 45 degrees.
594 */
595
596 /*!
597     the new value of the attribute.
598 */
599 qreal QDeclarative1PathAttribute::value() const
600 {
601     return _value;
602 }
603
604 void QDeclarative1PathAttribute::setValue(qreal value)
605 {
606     if (_value != value) {
607         _value = value;
608         emit valueChanged();
609         emit changed();
610     }
611 }
612
613 /****************************************************************************/
614
615 /*!
616     \qmlclass PathLine QDeclarative1PathLine
617     \inqmlmodule QtQuick 1
618     \ingroup qml-view-elements
619     \since QtQuick 1.0
620     \brief The PathLine defines a straight line.
621
622     The example below creates a path consisting of a straight line from
623     0,100 to 200,100:
624
625     \qml
626     Path {
627         startX: 0; startY: 100
628         PathLine { x: 200; y: 100 }
629     }
630     \endqml
631
632     \sa Path, PathQuad, PathCubic
633 */
634
635 /*!
636     \qmlproperty real QtQuick1::PathLine::x
637     \qmlproperty real QtQuick1::PathLine::y
638
639     Defines the end point of the line.
640 */
641
642 void QDeclarative1PathLine::addToPath(QPainterPath &path)
643 {
644     path.lineTo(x(), y());
645 }
646
647 /****************************************************************************/
648
649 /*!
650     \qmlclass PathQuad QDeclarative1PathQuad
651     \inqmlmodule QtQuick 1
652     \ingroup qml-view-elements
653     \since QtQuick 1.0
654     \brief The PathQuad defines a quadratic Bezier curve with a control point.
655
656     The following QML produces the path shown below:
657     \table
658     \row
659     \o \image declarative-pathquad.png
660     \o
661     \qml
662     Path {
663         startX: 0; startY: 0
664         PathQuad { x: 200; y: 0; controlX: 100; controlY: 150 }
665     }
666     \endqml
667     \endtable
668
669     \sa Path, PathCubic, PathLine
670 */
671
672 /*!
673     \qmlproperty real QtQuick1::PathQuad::x
674     \qmlproperty real QtQuick1::PathQuad::y
675
676     Defines the end point of the curve.
677 */
678
679 /*!
680    \qmlproperty real QtQuick1::PathQuad::controlX
681    \qmlproperty real QtQuick1::PathQuad::controlY
682
683    Defines the position of the control point.
684 */
685
686 /*!
687     the x position of the control point.
688 */
689 qreal QDeclarative1PathQuad::controlX() const
690 {
691     return _controlX;
692 }
693
694 void QDeclarative1PathQuad::setControlX(qreal x)
695 {
696     if (_controlX != x) {
697         _controlX = x;
698         emit controlXChanged();
699         emit changed();
700     }
701 }
702
703
704 /*!
705     the y position of the control point.
706 */
707 qreal QDeclarative1PathQuad::controlY() const
708 {
709     return _controlY;
710 }
711
712 void QDeclarative1PathQuad::setControlY(qreal y)
713 {
714     if (_controlY != y) {
715         _controlY = y;
716         emit controlYChanged();
717         emit changed();
718     }
719 }
720
721 void QDeclarative1PathQuad::addToPath(QPainterPath &path)
722 {
723     path.quadTo(controlX(), controlY(), x(), y());
724 }
725
726 /****************************************************************************/
727
728 /*!
729    \qmlclass PathCubic QDeclarative1PathCubic
730     \inqmlmodule QtQuick 1
731     \ingroup qml-view-elements
732     \since QtQuick 1.0
733    \brief The PathCubic defines a cubic Bezier curve with two control points.
734
735     The following QML produces the path shown below:
736     \table
737     \row
738     \o \image declarative-pathcubic.png
739     \o
740     \qml
741     Path {
742         startX: 20; startY: 0
743         PathCubic {
744             x: 180; y: 0
745             control1X: -10; control1Y: 90
746             control2X: 210; control2Y: 90
747         }
748     }
749     \endqml
750     \endtable
751
752     \sa Path, PathQuad, PathLine
753 */
754
755 /*!
756     \qmlproperty real QtQuick1::PathCubic::x
757     \qmlproperty real QtQuick1::PathCubic::y
758
759     Defines the end point of the curve.
760 */
761
762 /*!
763    \qmlproperty real QtQuick1::PathCubic::control1X
764    \qmlproperty real QtQuick1::PathCubic::control1Y
765
766     Defines the position of the first control point.
767 */
768 qreal QDeclarative1PathCubic::control1X() const
769 {
770     return _control1X;
771 }
772
773 void QDeclarative1PathCubic::setControl1X(qreal x)
774 {
775     if (_control1X != x) {
776         _control1X = x;
777         emit control1XChanged();
778         emit changed();
779     }
780 }
781
782 qreal QDeclarative1PathCubic::control1Y() const
783 {
784     return _control1Y;
785 }
786
787 void QDeclarative1PathCubic::setControl1Y(qreal y)
788 {
789     if (_control1Y != y) {
790         _control1Y = y;
791         emit control1YChanged();
792         emit changed();
793     }
794 }
795
796 /*!
797    \qmlproperty real QtQuick1::PathCubic::control2X
798    \qmlproperty real QtQuick1::PathCubic::control2Y
799
800     Defines the position of the second control point.
801 */
802 qreal QDeclarative1PathCubic::control2X() const
803 {
804     return _control2X;
805 }
806
807 void QDeclarative1PathCubic::setControl2X(qreal x)
808 {
809     if (_control2X != x) {
810         _control2X = x;
811         emit control2XChanged();
812         emit changed();
813     }
814 }
815
816 qreal QDeclarative1PathCubic::control2Y() const
817 {
818     return _control2Y;
819 }
820
821 void QDeclarative1PathCubic::setControl2Y(qreal y)
822 {
823     if (_control2Y != y) {
824         _control2Y = y;
825         emit control2YChanged();
826         emit changed();
827     }
828 }
829
830 void QDeclarative1PathCubic::addToPath(QPainterPath &path)
831 {
832     path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
833 }
834
835 /****************************************************************************/
836
837 /*!
838     \qmlclass PathPercent QDeclarative1PathPercent
839     \inqmlmodule QtQuick 1
840     \ingroup qml-view-elements
841     \since QtQuick 1.0
842     \brief The PathPercent manipulates the way a path is interpreted.
843
844     PathPercent allows you to manipulate the spacing between items on a
845     PathView's path. You can use it to bunch together items on part of
846     the path, and spread them out on other parts of the path.
847
848     The examples below show the normal distrubution of items along a path
849     compared to a distribution which places 50% of the items along the
850     PathLine section of the path.
851     \table
852     \row
853     \o \image declarative-nopercent.png
854     \o
855     \qml
856     PathView {
857         // ...
858         Path {
859             startX: 20; startY: 0
860             PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
861             PathLine { x: 150; y: 80 }
862             PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
863         }
864     }
865     \endqml
866     \row
867     \o \image declarative-percent.png
868     \o
869     \qml
870     PathView {
871         // ...
872         Path {
873             startX: 20; startY: 0
874             PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
875             PathPercent { value: 0.25 }
876             PathLine { x: 150; y: 80 }
877             PathPercent { value: 0.75 }
878             PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
879             PathPercent { value: 1 }
880         }
881     }
882     \endqml
883     \endtable
884
885     \sa Path
886 */
887
888 /*!
889     \qmlproperty real QtQuick1::PathPercent::value
890     The proporation of items that should be laid out up to this point.
891
892     This value should always be higher than the last value specified
893     by a PathPercent at a previous position in the Path.
894
895     In the following example we have a Path made up of three PathLines.
896     Normally, the items of the PathView would be laid out equally along
897     this path, with an equal number of items per line segment. PathPercent
898     allows us to specify that the first and third lines should each hold
899     10% of the laid out items, while the second line should hold the remaining
900     80%.
901
902     \qml
903     PathView {
904         // ...
905         Path {
906             startX: 0; startY: 0
907             PathLine { x:100; y: 0; }
908             PathPercent { value: 0.1 }
909             PathLine { x: 100; y: 100 }
910             PathPercent { value: 0.9 }
911             PathLine { x: 100; y: 0 }
912             PathPercent { value: 1 }
913         }
914     }
915     \endqml
916 */
917
918 qreal QDeclarative1PathPercent::value() const
919 {
920     return _value;
921 }
922
923 void QDeclarative1PathPercent::setValue(qreal value)
924 {
925     if (_value != value) {
926         _value = value;
927         emit valueChanged();
928         emit changed();
929     }
930 }
931
932
933 QT_END_NAMESPACE