raDIYo 0.4
swflipdigit.cpp
1/***************************************************************************
2
3 source::worx raDIYo
4 Copyright © 2020-2022 c.holzheuer
5 c.holzheuer@sourceworx.org
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12***************************************************************************/
13
14/*+
15 * contains copy-writen material from qt example code:
16 * @see shaped clock example
17 * @see embedded/flipdigits example
18 *
19 * **/
20
21
22#include <QWidget>
23#include <QtCore>
24#include <QPainter>
25#include <QFontDatabase>
26
27#include <swflipdigit.h>
28
29
30SWFlipDigit::SWFlipDigit( QWidget *parent )
31 : QWidget( parent ),
32 _number( 0 ),
33 _transition( Slide )
34{
35
36
37 //setAttribute( Qt::WA_OpaquePaintEvent, true );
38 setAttribute( Qt::WA_NoSystemBackground, true );
39 connect(&_animator, SIGNAL(frameChanged(int)), SLOT(update()));
40 _animator.setFrameRange( 0, 100 );
41 _animator.setDuration( 600 );
42 _animator.setEasingCurve( ( QEasingCurve( QEasingCurve::InOutQuad ) ) );
43
44
45}
46
47SWFlipDigit::~SWFlipDigit()
48{
49
50}
51
52void SWFlipDigit::setTransition( SWFlipMode tr)
53{
54 _transition = tr;
55}
56
57
58SWFlipDigit::SWFlipMode SWFlipDigit::transition() const
59{
60 return _transition;
61}
62
63
64void SWFlipDigit::setRange( int from, int to )
65{
66 _rangeFrom = from;
67 _rangeTo = to;
68}
69
70void SWFlipDigit::setNumber( int n )
71{
72 if (_number != n) {
73 _number = qBound( _rangeFrom, n, _rangeTo );
74 preparePixmap();
75 update();
76 }
77}
78
79void SWFlipDigit::flipTo( int n )
80{
81 if (_number != n) {
82 _number = qBound( _rangeFrom, n, _rangeTo );
83 _lastPixmap = _pixmap;
84 preparePixmap();
85 _animator.stop();
86 _animator.start();
87 }
88}
89
90void SWFlipDigit::drawFrame( QPainter *p, const QRect &rect )
91{
92 p->setPen(Qt::NoPen);
93
94 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
95 gradient.setColorAt(0.00, QColor(245, 245, 245));
96 gradient.setColorAt(0.49, QColor(192, 192, 192));
97 gradient.setColorAt(0.51, QColor(245, 245, 245));
98 gradient.setColorAt(1.00, QColor(192, 192, 192));
99 p->setBrush( gradient );
100
101 QRect r = rect;
102 p->drawRoundedRect( r, 15, 15, Qt::RelativeSize );
103 r.adjust( 1, 4, -1, -4 );
104 p->setPen (QColor( 181, 181, 181 ) );
105 p->setBrush( Qt::NoBrush );
106 p->drawRoundedRect( r, 15, 15, Qt::RelativeSize );
107 p->setPen( QColor( 159, 159, 159 ));
108 int y = rect.top() + rect.height() / 2 - 1;
109 p->drawLine( rect.left(), y, rect.right(), y );
110}
111
112
113QPixmap SWFlipDigit::drawDigits( int digit, const QRect &rect )
114{
115
116 QString strDigit = QString::number( digit );
117 if( strDigit.length() == 1 )
118 strDigit.prepend( '0' );
119
120 // FIX!
121 QFont font;
122
123 //font.setFamily("CorelDraw");
124 font.setFamily( "Grado Gradoo Nf" );
125 //font.setFamily("Selznick Remix NF");
126 //font.setFamily( "Valley Grrrl NF" );
127
128 //static const double SWSCALEFACTOR = 2.2;
129
130 int fontHeight = SWSCALEFACTOR * SWFONTSCALE * rect.height();
131 font.setPixelSize( fontHeight );
132 //font.setBold( true );
133
134 QPixmap pixmap( rect.size() * SWSCALEFACTOR );
135 pixmap.fill( Qt::transparent );
136
137 QLinearGradient gradient( QPoint( 0, 0 ), QPoint( 0, pixmap.height() ) );
138 gradient.setColorAt( 0.00, QColor(128, 128, 128) );
139 gradient.setColorAt( 0.49, QColor(64, 64, 64) );
140 gradient.setColorAt( 0.51, QColor(128, 128, 128) );
141 gradient.setColorAt( 1.00, QColor(16, 16, 16) );
142
143 QPainter painter;
144 painter.begin( &pixmap );
145 painter.setFont( font );
146 QPen pen;
147 pen.setBrush( QBrush( gradient ) );
148 painter.setPen( pen );
149
150 QRect pos = pixmap.rect();
151 pos.adjust( 0, -100, 0, 0 );
152
153 /*
154 painter.drawRect( pixmap.rect() );
155 painter.setPen( Qt::darkGray );
156 painter.drawRect( pos );
157 //painter.setPen( pen );
158 */
159
160 painter.drawText( pos, Qt::AlignCenter, strDigit );
161 painter.end();
162
163 return pixmap.scaledToWidth( width(), Qt::SmoothTransformation );
164
165}
166
167
168void SWFlipDigit::preparePixmap()
169{
170 _pixmap = QPixmap(size());
171 _pixmap.fill(Qt::transparent);
172 QPainter painter;
173 painter.begin(&_pixmap);
174 painter.drawPixmap( 0, 0, drawDigits( _number, rect() ) );
175 painter.end();
176}
177
178
179void SWFlipDigit::resizeEvent(QResizeEvent*)
180{
181 preparePixmap();
182 update();
183}
184
185
186void SWFlipDigit::paintStatic()
187{
188 QPainter painter( this );
189 painter.fillRect( rect(), Qt::black );
190 //painter.fillRect( rect(), Qt::green );
191 drawFrame( &painter, rect() );
192 painter.drawPixmap( 0, 0, _pixmap );
193}
194
195
196void SWFlipDigit::paintSlide()
197{
198 QPainter painter( this );
199 painter.fillRect( rect(), Qt::black );
200
201 //int pad = SWPADWIDTH;
202 //QRect fr = rect().adjusted( pad, pad, -pad, -pad );
203 drawFrame( &painter, rect() );
204 painter.setClipRect( rect() );
205
206 int y = height() * _animator.currentFrame() / 100;
207 painter.drawPixmap( 0, y, _lastPixmap );
208 painter.drawPixmap( 0, y - height(), _pixmap );
209}
210
211
212void SWFlipDigit::paintFlip()
213{
214 QPainter painter( this );
215 painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
216 painter.setRenderHint(QPainter::Antialiasing, true);
217 painter.fillRect(rect(), Qt::black);
218
219 int hw = width() / 2;
220 int hh = height() / 2;
221
222 // behind is the new pixmap
223
224 // int pad = SWPADWIDTH;
225 QRect fr = rect();//.adjusted( pad, pad, -pad, -pad );
226 drawFrame( &painter, fr );
227 painter.drawPixmap( 0, 0, _pixmap );
228
229 int index = _animator.currentFrame();
230
231 if( index <= 50 )
232 {
233
234 // the top part of the old pixmap is flipping
235 int angle = -180 * index / 100;
236 QTransform transform;
237 transform.translate(hw, hh);
238 transform.rotate( angle, Qt::XAxis );
239 painter.setTransform(transform);
240 drawFrame( &painter, fr.adjusted(-hw, -hh, -hw, -hh ) );
241 painter.drawPixmap(-hw, -hh, _lastPixmap);
242
243 // the bottom part is still the old pixmap
244 painter.resetTransform();
245 painter.setClipRect(0, hh, width(), hh);
246 drawFrame( &painter, fr );
247 painter.drawPixmap( 0, 0, _lastPixmap );
248 }
249 else
250 {
251
252 painter.setClipRect( 0, hh, width(), hh );
253
254 // the bottom part is still the old pixmap
255 drawFrame( &painter, fr );
256 painter.drawPixmap(0, 0, _lastPixmap );
257
258 // the bottom part of the new pixmap is flipping
259 int angle = 180 - 180 * _animator.currentFrame() / 100;
260 QTransform transform;
261 transform.translate( hw, hh);
262 transform.rotate( angle, Qt::XAxis );
263 painter.setTransform( transform );
264 drawFrame( &painter, fr.adjusted( -hw, -hh, -hw, -hh ) );
265 painter.drawPixmap( -hw, -hh, _pixmap );
266
267 }
268
269}
270
271
272void SWFlipDigit::paintRotate()
273{
274 QPainter p(this);
275
276 //int pad = SWPADWIDTH;
277 QRect fr = rect();//.adjusted(pad, pad, -pad, -pad);
278 drawFrame(&p, fr);
279 p.setClipRect(fr);
280
281 int angle1 = -180 * _animator.currentFrame() / 100;
282 int angle2 = 180 - 180 * _animator.currentFrame() / 100;
283 int angle = ( _animator.currentFrame() <= 50 ) ? angle1 : angle2;
284 QPixmap pix = ( _animator.currentFrame() <= 50 ) ? _lastPixmap : _pixmap;
285
286 QTransform transform;
287 transform.translate( width() / 2, height() / 2 );
288 transform.rotate( angle, Qt::XAxis );
289
290 p.setTransform(transform);
291 p.setRenderHint( QPainter::SmoothPixmapTransform, true );
292 p.drawPixmap(-width() / 2, -height() / 2, pix);
293}
294
295
296void SWFlipDigit::paintEvent( QPaintEvent *event )
297{
298 Q_UNUSED( event );
299
300 if (_animator.state() == QTimeLine::Running)
301 {
302 if(_transition == Slide )
303 paintSlide();
304 if(_transition == Flip )
305 paintFlip();
306 if(_transition == Rotate )
307 paintRotate();
308 }
309 else
310 {
311 paintStatic();
312 }
313
314}
315
316
317
318