Files
raDIYo/swflipdigit.cpp
2025-08-05 22:36:00 +02:00

330 lines
7.7 KiB
C++

/***************************************************************************
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 <QWidget>
#include <QtCore>
#include <QPainter>
#include <QFontDatabase>
#include <QColor>
#include <QPen>
#include <swflipdigit.h>
#include <raDIYoglobals.h>
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();
}