/*************************************************************************** source::worx raDIYo Copyright © 2020-2022 c.holzheuer chris@sourceworx.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ***************************************************************************/ /** * contains copy-writen material from qt example code: * @see shaped clock example * @see embedded/flipdigits example * * **/ #include #include #include #include #include #include #include #include SWFlipDigit::SWFlipDigit( QWidget *parent ) : QWidget( parent ), _transition( Slide ) { setFocusPolicy( Qt::StrongFocus ); //setAttribute( Qt::WA_OpaquePaintEvent, true ); setAttribute( Qt::WA_NoSystemBackground, true ); connect(&_animator, SIGNAL(frameChanged(int)), SLOT(update())); _animator.setFrameRange( 0, 100 ); _animator.setDuration( 600 ); _animator.setEasingCurve( ( QEasingCurve( QEasingCurve::InOutQuad ) ) ); _fontFamily = SWDEFAULTFONT; } SWFlipDigit::~SWFlipDigit() { } void SWFlipDigit::setTransition( FlipMode tr) { _transition = tr; } SWFlipDigit::FlipMode SWFlipDigit::transition() const { return _transition; } void SWFlipDigit::setValue( int value ) { if( _value != value ) { _value = qBound( _rangeFrom, value, _rangeTo ); preparePixmap(); update(); } } void SWFlipDigit::flipTo( int n ) { if( _value != n ) { _value = qBound( _rangeFrom, n, _rangeTo ); _lastPixmap = _pixmap; preparePixmap(); _animator.stop(); _animator.start(); } } void SWFlipDigit::drawFrame( QPainter* painter, const QRect &rect ) { painter->setPen(Qt::NoPen); QLinearGradient gradient( rect.topLeft(), rect.bottomLeft() ); gradient.setColorAt(0.00, QColor(245, 245, 245) ); gradient.setColorAt(0.49, QColor(192, 192, 192) ); gradient.setColorAt(0.51, QColor(245, 245, 245) ); gradient.setColorAt(1.00, QColor(192, 192, 192) ); painter->setBrush( gradient ); QRect r = rect; painter->drawRoundedRect( r, 15, 15, Qt::RelativeSize ); r.adjust( 1, 4, -1, -4 ); painter->setPen (QColor( 181, 181, 181 ) ); painter->setBrush( Qt::NoBrush ); painter->drawRoundedRect( r, 15, 15, Qt::RelativeSize ); painter->setPen( QColor( 159, 159, 159 )); int y = rect.top() + rect.height() / 2 - 1; painter->drawLine( rect.left(), y, rect.right(), y ); } QPixmap SWFlipDigit::drawDigits( int digit, const QRect &rect ) { QString strDigit = QString::number( digit ); if( strDigit.length() == 1 ) strDigit.prepend( '0' ); // FIX! QFont font; font.setFamily( _fontFamily ); int fontHeight = _scaleFactor * _fontScale * rect.height(); font.setPixelSize( fontHeight ); //font.setBold( true ); QPixmap pixmap( rect.size() * _scaleFactor ); pixmap.fill( Qt::transparent ); QLinearGradient gradient( QPoint( 0, 0 ), QPoint( 0, pixmap.height() ) ); gradient.setColorAt( 0.00, QColor(128, 128, 128) ); gradient.setColorAt( 0.49, QColor(64, 64, 64) ); gradient.setColorAt( 0.51, QColor(128, 128, 128) ); gradient.setColorAt( 1.00, QColor(16, 16, 16) ); QPainter painter; painter.begin( &pixmap ); painter.setFont( font ); QPen pen; pen.setBrush( QBrush( gradient ) ); painter.setPen( pen ); QRect pos = pixmap.rect(); pos.adjust( 0, -100, 0, 0 ); painter.drawText( pos, Qt::AlignCenter, strDigit ); painter.end(); return pixmap.scaledToWidth( width(), Qt::SmoothTransformation ); } void SWFlipDigit::preparePixmap() { _pixmap = QPixmap( size() ); _pixmap.fill(Qt::transparent); QPainter painter( &_pixmap ); painter.drawPixmap( 0, 0, drawDigits( _value, rect() ) ); } void SWFlipDigit::resizeEvent( QResizeEvent* ) { preparePixmap(); update(); } void SWFlipDigit::paintStatic() { QPainter painter( this ); drawFrame( &painter, rect() ); painter.drawPixmap( 0, 0, _pixmap ); } void SWFlipDigit::paintSlide() { QPainter painter( this ); painter.fillRect( rect(), Qt::black ); //int pad = SWPADWIDTH; //QRect fr = rect().adjusted( pad, pad, -pad, -pad ); drawFrame( &painter, rect() ); painter.setClipRect( rect() ); int y = height() * _animator.currentFrame() / 100; painter.drawPixmap( 0, y, _lastPixmap ); painter.drawPixmap( 0, y - height(), _pixmap ); } void SWFlipDigit::paintFlip() { QPainter painter( this ); painter.setRenderHint( QPainter::SmoothPixmapTransform, true ); painter.setRenderHint( QPainter::Antialiasing, true ); int hw = width() / 2; int hh = height() / 2; // behind is the new pixmap // int pad = SWPADWIDTH; QRect fr = rect();//.adjusted( pad, pad, -pad, -pad ); drawFrame( &painter, fr ); painter.drawPixmap( 0, 0, _pixmap ); int index = _animator.currentFrame(); if( index <= 50 ) { // the top part of the old pixmap is flipping int angle = -180 * index / 100; QTransform transform; transform.translate(hw, hh); transform.rotate( angle, Qt::XAxis ); painter.setTransform(transform); drawFrame( &painter, fr.adjusted(-hw, -hh, -hw, -hh ) ); painter.drawPixmap(-hw, -hh, _lastPixmap); // the bottom part is still the old pixmap painter.resetTransform(); painter.setClipRect(0, hh, width(), hh); drawFrame( &painter, fr ); painter.drawPixmap( 0, 0, _lastPixmap ); return; } painter.setClipRect( 0, hh, width(), hh ); // the bottom part is still the old pixmap drawFrame( &painter, fr ); painter.drawPixmap(0, 0, _lastPixmap ); // the bottom part of the new pixmap is flipping int angle = 180 - 180 * _animator.currentFrame() / 100; QTransform transform; transform.translate( hw, hh); transform.rotate( angle, Qt::XAxis ); painter.setTransform( transform ); drawFrame( &painter, fr.adjusted( -hw, -hh, -hw, -hh ) ); painter.drawPixmap( -hw, -hh, _pixmap ); } void SWFlipDigit::paintRotate() { QPainter p(this); //int pad = SWPADWIDTH; QRect fr = rect();//.adjusted(pad, pad, -pad, -pad); drawFrame(&p, fr); p.setClipRect(fr); int angle1 = -180 * _animator.currentFrame() / 100; int angle2 = 180 - 180 * _animator.currentFrame() / 100; int angle = ( _animator.currentFrame() <= 50 ) ? angle1 : angle2; QPixmap pix = ( _animator.currentFrame() <= 50 ) ? _lastPixmap : _pixmap; QTransform transform; transform.translate( width() / 2, height() / 2 ); transform.rotate( angle, Qt::XAxis ); p.setTransform(transform); p.setRenderHint( QPainter::SmoothPixmapTransform, true ); p.drawPixmap(-width() / 2, -height() / 2, pix); } void SWFlipDigit::paintEvent( QPaintEvent* ) { QPainter painter( this ); painter.fillRect( rect(), Qt::black ); if( _animator.state() == QTimeLine::Running ) { if(_transition == Slide ) paintSlide(); if(_transition == Flip ) paintFlip(); if(_transition == Rotate ) paintRotate(); } else { paintStatic(); } drawMark( this ); } void SWFlipDigit::onDialDeltaChanged( int delta ) { // gültigkeit sicherstellen int newval = _value + delta; newval = qBound( _rangeFrom, newval, _rangeTo ); if( _value == newval ) return; setValue( newval ); update(); }