diff options
author | Anna Gadomska <agadomsk@agadomska.(none)> | 2010-06-24 14:43:35 +0300 |
---|---|---|
committer | Mike FABIAN <mike.fabian@basyskom.de> | 2010-06-29 15:58:18 +0200 |
commit | 6dac29bbf852283dfc1f7d684a1b22964ecb7024 (patch) | |
tree | 6a013eecb863f235610d0058a30c3a8a7b1b3c97 | |
parent | 74fa5eaf7e73eb41042e4f8f3bc5037dbee3c299 (diff) |
Changes: spinner animation view/animation reimplemented
RevBy: TrustMe
-rw-r--r-- | src/views/mspinnerview.cpp | 199 | ||||
-rw-r--r-- | src/views/mspinnerview.h | 6 | ||||
-rw-r--r-- | src/views/mspinnerview_p.h | 10 | ||||
-rw-r--r-- | src/views/style/mspinnerstyle.h | 35 |
4 files changed, 147 insertions, 103 deletions
diff --git a/src/views/mspinnerview.cpp b/src/views/mspinnerview.cpp index 52c636f2..eb88bc6f 100644 --- a/src/views/mspinnerview.cpp +++ b/src/views/mspinnerview.cpp @@ -21,6 +21,7 @@ #include <QTimeLine> #include <QTimer> #include <QGraphicsSceneResizeEvent> +#include <QBitmap> #include <math.h> #include "mspinnerview.h" @@ -43,8 +44,7 @@ const int SpinnerRefreshRate = 30; MSpinnerViewPrivate::MSpinnerViewPrivate() : q_ptr(0), controller(0), - inactiveElement(0), - activeElement(0), + pieImage(0), position(0), elapsed(0), timer(0) @@ -54,9 +54,6 @@ MSpinnerViewPrivate::MSpinnerViewPrivate() MSpinnerViewPrivate::~MSpinnerViewPrivate() { - MTheme::releasePixmap(activeElement); - MTheme::releasePixmap(inactiveElement); - delete timer; } @@ -68,6 +65,11 @@ MSpinnerView::MSpinnerView(MProgressIndicator *controller) : Q_D(MSpinnerView); d->q_ptr = this; d->controller = controller; + + d->bgRect = QRect(); + d->fgRect = QRect(); + d->pieImage = new QPixmap(); + connect(controller, SIGNAL(visibleChanged()), this, SLOT(visibilityChanged())); } @@ -82,19 +84,18 @@ void MSpinnerViewPrivate::animationTimeout() Q_Q(MSpinnerView); if (q->model()->unknownDuration()) { - - // calculate interval in secs and add it to elapsed time - qreal interval = (qreal) timer->interval() / 1000.0; + //calculate interval in secs and add it to elapsed time + qreal interval = static_cast<qreal>(timer->interval() / 1000.0); elapsed += interval; - // calculate how many steps we should take - int steps = (int)(elapsed * (qreal) q->style()->speed()); + //calculate how many steps we should take + int steps = static_cast<int>(elapsed * (qreal) q->style()->speed()); if (steps > 0) { - // subtract the amount we will step from the elapsed time + //subtract the amount we will step from the elapsed time elapsed -= steps * (1.0 / (qreal) q->style()->speed()); - // and perform the stepping - position = (position + steps) % elements.count(); - // redraw + //and perform the stepping + position = (position + steps) % 360; + //redraw q->update(); } } @@ -115,16 +116,18 @@ void MSpinnerView::updateData(const QList<const char *>& modifications) } if (d->controller->isVisible()) d->timer->start(SpinnerRefreshRate); - } else { - delete d->timer; - d->timer = NULL; + } else { + delete d->timer; + d->timer = NULL; + } } } - } + applyStyle(); update(); } + void MSpinnerView::setupModel() { MWidgetView::setupModel(); @@ -143,109 +146,136 @@ void MSpinnerView::setupModel() d->timer = NULL; } - update(); + update(); } -void MSpinnerView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const +void MSpinnerView::calculateSizes() { - Q_UNUSED(option); + Q_D(MSpinnerView); + QSize s; + //calculating sizes for background + if ( rect().toRect().height() >= rect().toRect().width() ) { + s = QSize(rect().toRect().width(), rect().toRect().width()); + } else { + s = QSize(rect().toRect().height(), rect().toRect().height()); + } - Q_D(const MSpinnerView); + QPoint bgDrawPoint(size().width() * 0.5 - s.width() * 0.5, size().height() * 0.5 - s.height() * 0.5 ); - const int elementsCount = d->elements.count(); - if (style()->inactiveImage() && style()->activeImage()) { + d->bgRect = QRect(bgDrawPoint, s); - // size of an element - QSize size(style()->elementSize(), style()->elementSize()); + //calculating foreground size: + d->fgRect = QRect( + QPoint((d->bgRect.topLeft().x() + style()->progressStripSize()), (d->bgRect.topLeft().y() + style()->progressStripSize())), + QPoint((d->bgRect.bottomRight().x() - style()->progressStripSize()), (d->bgRect.bottomRight().y() - style()->progressStripSize()))); - if (model()->unknownDuration()) { - // every n'th should be active - int span = (d->elements.count() / style()->activeElementCount()); - // this tells the active index within the span - int activeIndexInSpan = d->position % span; + *d->pieImage = QPixmap(d->bgRect.size()); + } - // draw all elements with proper image - for (int i = 0; i < elementsCount; ++i) { - if ((i % span) == activeIndexInSpan) { - painter->drawPixmap(QRect(d->elements[i], size), *style()->activeImage()); - } else { - painter->drawPixmap(QRect(d->elements[i], size), *style()->inactiveImage()); - } - } - } else { - // active element count - int active = (model()->value() - model()->minimum()) * d->elements.count() / - qMax(model()->maximum() - model()->minimum(), 1); - - // draw active elements - for (int i = 0; i < active; ++i) { - painter->drawPixmap(QRect(d->elements[i], size), *style()->activeImage()); - } +void MSpinnerView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const +{ + Q_D(const MSpinnerView); + Q_UNUSED(option); + Q_UNUSED(painter); - // draw inactive elements - for (int i = active; i < elementsCount; ++i) { - painter->drawPixmap(QRect(d->elements[i], size), *style()->inactiveImage()); - } - } - } + style()->bgImage()->draw(d->bgRect, painter); } -void MSpinnerViewPrivate::calculateShape(QSizeF size) +void MSpinnerView::drawForeground(QPainter *painter, const QStyleOptionGraphicsItem *option) const { - Q_Q(MSpinnerView); - - QSizeF s = size - QSizeF(q->style()->elementSize(), q->style()->elementSize()); + Q_UNUSED(option); + Q_UNUSED(painter); - qreal diameter = qMin(s.width(), s.height()); + /*previously drawing foreground was here, but it is drawing it incorrectly for some reason + drawing foreground is moved to drawContents temporary*/ +} - // clear existing elements - elements.clear(); +QRect centerScale( QRect const & r, double s ) +{ + int w = r.width() * s; + int h = r.height() * s; + int x = r.x() + (r.width() - w)/2; + int y = r.y() + (r.height() - h)/2; + return QRect(x, y, w, h); +} - if (q->style()->elementCount() > 0) { - // center point - QPoint center(size.width() * 0.5, size.height() * 0.5); +void MSpinnerView::createPieImage( int startAngle, int endAngle, QSize const & size, QPixmap const & image ) const +{ + Q_D(const MSpinnerView); + d->pieImage->rect().setSize( size ); + d->pieImage->fill( Qt::transparent); - // radius for the spinner - qreal radius = diameter * 0.5f; + QPainter piePainter( d->pieImage ); + piePainter.setBrush( QBrush(image) ); + piePainter.setPen( QPen(Qt::transparent) ); - // half element size - qreal halfElementSize = q->style()->elementSize() * 0.5; + // Qt starts at 3:00 and goes CCW, we provide values starting at 12:00 and going CW + piePainter.drawPie( centerScale(QRect(QPoint(),size), 1.5), + (90-endAngle)*16, + (endAngle-startAngle)*16 ); +} - qreal angle = 0; - qreal span = (M_PI * 2.0) / q->style()->elementCount(); +void MSpinnerView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const +{ + Q_UNUSED(option); - // calculate spherical shape and store points where the item should be drawn - const int elementsCount = q->style()->elementCount(); - for (int i = 0; i < elementsCount; ++i) { + Q_D(const MSpinnerView); - QPoint position; - position.setX(center.x() + (sinf(angle) * radius) - halfElementSize); - position.setY(center.y() - (cosf(angle) * radius) - halfElementSize); + // Temporary: these should be made as style parameters + static int const minScale = 75; // scale used for minimum size when growing/shrinking + static int const maxScale = 100; // maybe not needed as style + static int const sweepAngle = 90; // sweep angle for unknown duration + static int const resolution = 100; // number of divisions in circle for unknown duration mode + + // calculated values input into rendering + double startAngle = 0.0; + double endAngle = 0.0; + double scale = 1.0; + + // Calculate values depending on mode + if ( model()->unknownDuration() ) { + startAngle = d->position * 360/resolution; + endAngle = startAngle + sweepAngle; + scale = 1.0; + } + else { + startAngle = 0.0; + endAngle = 360*(model()->value() - model()->minimum()) / (model()->maximum() - model()->minimum()); - elements.append(position); + double growAngle = 1; //can be adjusted if grow/shrink animation for not uknown duration required + double angleIncrement = (maxScale-minScale)/growAngle; // conversion from angle to scale - angle += span; - } + scale = endAngle < growAngle ? minScale + endAngle * angleIncrement : + endAngle > 360-growAngle ? minScale + (360-endAngle) * angleIncrement : maxScale; + scale /= 100.0; } + + // Render the image + createPieImage( startAngle, endAngle, d->bgRect.size(), *style()->progressImage()->pixmap() ); + d->pieImage->setMask( style()->maskImage()->pixmap()->createHeuristicMask() ); + painter->drawPixmap( scale > .99 ? d->bgRect : centerScale(d->bgRect, scale), *d->pieImage, d->pieImage->rect() ); + + //drawing foreground here, because there's something wrong with drawForeground() + style()->fgImage()->draw( d->fgRect, painter); } void MSpinnerView::resizeEvent(QGraphicsSceneResizeEvent *event) { - Q_D(MSpinnerView); - d->calculateShape(event->newSize()); + MWidgetView::resizeEvent(event); + calculateSizes(); } void MSpinnerView::applyStyle() { - Q_D(MSpinnerView); - MWidgetView::applyStyle(); - d->calculateShape(size()); + MWidgetView::applyStyle(); + calculateSizes(); } void MSpinnerViewPrivate::visibilityChanged() { + Q_Q(MSpinnerView); if (timer) { if (controller->isVisible()) { timer->start(SpinnerRefreshRate); @@ -253,6 +283,7 @@ void MSpinnerViewPrivate::visibilityChanged() timer->stop(); } } + q->calculateSizes(); } #include "moc_mspinnerview.cpp" diff --git a/src/views/mspinnerview.h b/src/views/mspinnerview.h index 2ec95bed..670c5a0d 100644 --- a/src/views/mspinnerview.h +++ b/src/views/mspinnerview.h @@ -82,6 +82,9 @@ public: protected: //! \reimp virtual void drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const; + virtual void drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const; + virtual void drawForeground(QPainter *painter, const QStyleOptionGraphicsItem *option) const; + void resizeEvent(QGraphicsSceneResizeEvent *event); virtual void setupModel(); virtual void applyStyle(); @@ -94,6 +97,9 @@ protected slots: //! \reimp_end private: + void calculateSizes(); + void createPieImage( int startAngle, int endAngle, QSize const & size, QPixmap const & image ) const; + Q_DISABLE_COPY(MSpinnerView) Q_DECLARE_PRIVATE(MSpinnerView) diff --git a/src/views/mspinnerview_p.h b/src/views/mspinnerview_p.h index db5e0219..399bee2a 100644 --- a/src/views/mspinnerview_p.h +++ b/src/views/mspinnerview_p.h @@ -22,6 +22,7 @@ #include <QObject> #include <QPointF> +#include <QRect> class MStyle; class MProgressIndicator; @@ -42,17 +43,18 @@ public: void animationTimeout(); void visibilityChanged(); - void calculateShape(QSizeF size); MProgressIndicator *controller; + mutable QPixmap *pieImage; - const QPixmap *inactiveElement; - const QPixmap *activeElement; int position; qreal elapsed; QTimer *timer; - QVector<QPoint> elements; + + QRect bgRect; + QRect fgRect; + #ifdef M_UNIT_TEST M_UNIT_TEST; diff --git a/src/views/style/mspinnerstyle.h b/src/views/style/mspinnerstyle.h index 2211899d..f17e9f0b 100644 --- a/src/views/style/mspinnerstyle.h +++ b/src/views/style/mspinnerstyle.h @@ -35,35 +35,40 @@ class M_EXPORT MSpinnerStyle : public MWidgetStyle M_STYLE(MSpinnerStyle) /*! - \property MSpinnerStyle::activeImage - \brief Image of the active bar element. + \property MSpinnerStyle::fgImage + \brief Image of foreground of spinner */ - M_STYLE_PTR_ATTRIBUTE(QPixmap *, activeImage, ActiveImage) + M_STYLE_PTR_ATTRIBUTE(MScalableImage*, fgImage, FgImage) /*! - \property MSpinnerStyle::inactiveImage - \brief Image of the inactive bar element. + \property MSpinnerStyle:bgImage + \brief Image of background of spinner */ - M_STYLE_PTR_ATTRIBUTE(QPixmap *, inactiveImage, InactiveImage) + M_STYLE_PTR_ATTRIBUTE(MScalableImage *, bgImage, BgImage) /*! - \property MSpinnerStyle::speed - \brief Speed of unknown duration progress animation (distance/sec). + \property MSpinnerStyle::maskImage + \brief Image of mask for spinner background */ - M_STYLE_ATTRIBUTE(int, speed, Speed) + M_STYLE_PTR_ATTRIBUTE(MScalableImage *, maskImage, MaskImage) /*! - \property MSpinnerStyle::activeElementCount - \brief The number of active elements in circular progress indicator (unknown duration). + \property MSpinnerStyle::progressImage + \brief Image of progress bar for spinner */ - M_STYLE_ATTRIBUTE(int, activeElementCount, ActiveElementCount) + M_STYLE_PTR_ATTRIBUTE(MScalableImage *, progressImage, ProgressImage) /*! - \property MSpinnerStyle::elementSize - \brief Size of an element in the circle. + \property MSpinnerStyle::progressStripSize + \brief Size of the strip of progress indicator. */ - M_STYLE_ATTRIBUTE(qreal, elementSize, ElementSize) + M_STYLE_ATTRIBUTE(qreal, progressStripSize, ProgressStripSize) + /*! + \property MSpinnerStyle::speed + \brief Speed of unknown duration progress animation (distance/sec). + */ + M_STYLE_ATTRIBUTE(int, speed, Speed) /*! \property MSpinnerStyle::elementCount |