source: psi/trunk/libpsi/psiwidgets/busywidget.cpp@ 150

Last change on this file since 150 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 11.9 KB
Line 
1/*
2 * busywidget.cpp - cool animating widget
3 * Copyright (C) 2001, 2002 Justin Karneges
4 * Hideaki Omuro
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include"busywidget.h"
23
24#include<qtimer.h>
25#include<qpainter.h>
26#include<math.h>
27
28/////////////////////////////////////////////////////////////////////////////
29// common defines
30//
31#define FPS 20 // frequency of update
32
33#define SPINRATE 24 // 1024ths of a revolution per frame
34#define SPINOFFSET 4 // frames each panel is offset by
35
36#define COLORSTOPPED 0xFFFFFF // color when stopped
37#define COLORSPINNING 0xFFFFFF // color when spinning
38#define COLORSHADOW 0x000000 // color of shadow
39
40/////////////////////////////////////////////////////////////////////////////
41// derived defines
42//
43#define MSECSPERFRAME (1000 / FPS)
44
45/////////////////////////////////////////////////////////////////////////////
46// declared later
47//
48extern char psigraphic[];
49
50// panel class
51class CPanel
52{
53public:
54 int angle;
55 int height;
56 bool spinning;
57 int alpha;
58
59 CPanel(int height = 1);
60 int GetModHeight();
61 int GetShade();
62 void Spin(int n);
63
64 void SetAngle(int _angle) { angle = _angle % 1024; }
65 void SetHeight(int _height) { height = _height; }
66 int GetAngle() { return angle % 1024; }
67 int GetHeight() { return height; }
68 int GetModOffset() { return (height - GetModHeight()) / 2; }
69};
70
71// color class
72class CColor
73{
74public:
75 int m_clr;
76
77 CColor(int _r, int _g, int _b)
78 {
79 SetColor(_r, _g, _b);
80 }
81 CColor(int _clr)
82 {
83 SetColor(_clr);
84 }
85 inline void SetColor(int _r, int _g, int _b)
86 {
87 SetColor((_r << 16) + (_g << 8) + _b);
88 }
89 inline void SetColor(int _clr)
90 {
91 m_clr = _clr;
92 }
93 inline short GetR()
94 {
95 return m_clr >> 16;
96 }
97 inline short GetG()
98 {
99 return (m_clr >> 8) & 255;
100 }
101 inline short GetB()
102 {
103 return m_clr & 255;
104 }
105 CColor Alpha(CColor clr, int alpha = 256);
106};
107
108class BusyWidget::Private : public QObject
109{
110 Q_OBJECT
111private:
112 BusyWidget *busy;
113
114public:
115 Private(BusyWidget *b)
116 {
117 t = 0;
118 busy = b;
119 stopInProgress = false;
120 }
121
122 bool stopInProgress;
123 bool isActive;
124 int frame;
125 int at;
126 QPixmap pix;
127 QTimer *t;
128
129 // data
130 CPanel panel[5];
131 int pcountdown;
132 int ocountdown;
133
134 void render()
135 {
136 QPainter p(busy);
137 p.drawPixmap(0,0, pix);
138 }
139
140 void renderPixmap()
141 {
142 pix.resize(busy->width(), busy->height());
143 pix.fill(QColor("#406080"));
144
145 QPainter p(&pix);
146
147 int i, j, k, l;
148 int row;
149
150 for(i = 0; i < 5; i++)
151 {
152 int o = panel[i].GetModOffset();
153
154 CColor c1(COLORSPINNING), c2(COLORSTOPPED), c3(COLORSHADOW);
155 CColor b = c1.Alpha(c2, panel[i].alpha * 8);
156
157 CColor a = b.Alpha(c3, panel[i].GetShade());
158
159 l = panel[i].GetModHeight();
160
161 double radangle = (double) 3.1415926f * (double) panel[i].GetAngle() / (double) 512;
162 int step = (int)((double)1024 / cos(radangle));
163 step = step < 0 ? -step : step;
164
165 int n = (int)((double)1024 * cos(radangle) * 17 / 2);
166 n = n < 0 ? -n : n;
167
168 row = 8192 - step * n / 1024;
169
170 QColor clr(a.GetR(), a.GetG(), a.GetB());
171
172 for(j = 0; j < l; j++)
173 {
174 int m = row / 1024 + 1;
175 for(k = 0; k < 16; k++)
176 {
177 p.setPen(psigraphic[i * 304 + m * 16 + k] ? Qt::black : clr);
178 p.drawPoint(i * 16 + k + 1, o + j + 1);
179 }
180 row += step;
181 }
182 }
183
184 p.setPen(Qt::black);
185 p.drawRect(0, 0, busy->width(), busy->height());
186 }
187
188public slots:
189 void stop()
190 {
191 if ( stopInProgress ) {
192 stopInProgress = false;
193
194 isActive = FALSE;
195 if( !ocountdown )
196 ocountdown = SPINOFFSET * 4 + 1;
197 }
198 }
199};
200
201/////////////////////////////////////////////////////////////////////////////
202// code
203//
204BusyWidget::BusyWidget(QWidget *parent, const char *name)
205:QWidget(parent, name)
206{
207 d = new Private(this);
208
209 d->isActive = FALSE;
210 d->frame = 0;
211 d->at = 0;
212
213 d->pcountdown = 0;
214 d->ocountdown = 0;
215
216 setFixedWidth(82);
217 setFixedHeight(19);
218 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
219
220 int i;
221 for(i = 0; i < 5; i++)
222 d->panel[i].SetHeight(17);
223
224 d->renderPixmap();
225}
226
227BusyWidget::~BusyWidget()
228{
229 delete d;
230}
231
232bool BusyWidget::isActive() const
233{
234 return (d->isActive && !d->stopInProgress);
235}
236
237void BusyWidget::setActive(bool a)
238{
239 if ( a )
240 start();
241 else
242 stop();
243}
244
245void BusyWidget::start()
246{
247 d->stopInProgress = false;
248
249 if(d->isActive)
250 return;
251
252 d->isActive = TRUE;
253
254 if(!d->pcountdown)
255 d->pcountdown = SPINOFFSET * 4 + 1;
256
257 if(!d->t)
258 {
259 d->t = new QTimer(this);
260 connect(d->t, SIGNAL(timeout()), SLOT(animate()));
261 animate();
262 d->t->start(MSECSPERFRAME);
263 }
264}
265
266void BusyWidget::stop()
267{
268 if(!d->isActive)
269 return;
270
271 if ( d->stopInProgress )
272 return;
273
274 d->stopInProgress = true;
275 QTimer::singleShot(0, d, SLOT(stop()));
276}
277
278void BusyWidget::animate()
279{
280 int i;
281 for(i = 0; i < 5; i++)
282 d->panel[i].Spin(SPINRATE);
283
284 if(d->pcountdown)
285 if(!(--d->pcountdown % SPINOFFSET))
286 d->panel[d->pcountdown / SPINOFFSET].spinning = true;
287
288 if(d->ocountdown)
289 if(!(--d->ocountdown % SPINOFFSET))
290 d->panel[d->ocountdown / SPINOFFSET].spinning = false;
291
292 if(!d->isActive)
293 {
294 bool isValid = false;
295 for(i = 0; i < 5; i++)
296 if(d->panel[i].spinning || d->panel[i].GetAngle() != 0 || d->panel[i].alpha != 0)
297 isValid = true;
298
299 if(!isValid)
300 {
301 delete d->t;
302 d->t = 0;
303 }
304 }
305
306 d->renderPixmap();
307 d->render();
308}
309
310void BusyWidget::paintEvent(QPaintEvent *)
311{
312 d->render();
313}
314
315void BusyWidget::resizeEvent(QResizeEvent *)
316{
317 d->renderPixmap();
318}
319
320/////////////////////////////////////////////////////////////////////////
321// stuff beyond here for animating rotating psi panels
322//
323
324// color stuff
325CColor CColor::Alpha(CColor clr, int alpha)
326{
327 int ialpha = 256 - alpha;
328
329 int r, g, b;
330 r = (alpha * GetR() + ialpha * clr.GetR()) / 256;
331 g = (alpha * GetG() + ialpha * clr.GetG()) / 256;
332 b = (alpha * GetB() + ialpha * clr.GetB()) / 256;
333
334 return CColor(r, g, b);
335}
336
337// panel stuff
338CPanel::CPanel(int _height)
339{
340 height = _height;
341 spinning = false;
342 angle = 0;
343 alpha = 0;
344}
345
346int CPanel::GetModHeight()
347{
348 int l = GetAngle();
349 if(l > 512)
350 l = 1024 - l;
351 double radangle = (double) 3.1415926f * (double) l / (double) 512;
352 int tmp = (int)(cos(radangle)* (double) height);
353 return tmp < 0 ? -tmp : tmp;
354}
355
356int CPanel::GetShade()
357{
358 int l = GetAngle() + 128;
359 if(GetAngle() >= 256 && GetAngle() < 768)
360 l += 512;
361 if(l >= 1024)
362 l %= 1024;
363 if(l == 0)
364 l += 1024;
365 double radangle = (double) 3.1415926f * (double) l / (double) 512;
366 return 128 + (int)(cos(radangle)* (double) 128);
367}
368
369void CPanel::Spin(int n)
370{
371 int i = angle + n;
372 if(!spinning)
373 {
374 if(i >= 1024)
375 SetAngle(0);
376 if(angle < 512 && i >= 512)
377 SetAngle(0);
378 if(angle)
379 SetAngle(i);
380 }
381 else
382 SetAngle(i);
383 if(spinning)
384 {
385 if(alpha < 32)
386 alpha+=2;
387 }
388 else
389 {
390 if(alpha)
391 alpha-=2;
392 }
393}
394
395char psigraphic[304*5] =
396{
397 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
400 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
416
417 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
420 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
421 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
422 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
423 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
424 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
425 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
426 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
427 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
428 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
429 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
430 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
431 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
432 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
433 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
436
437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
438 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
439 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
440 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
441 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
442 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
443 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
444 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
445 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
446 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
447 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
448 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
449 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
450 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
451 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
453 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
454 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
456
457 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
460 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
461 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
462 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
463 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
464 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
465 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
466 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
467 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
468 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
469 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
470 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
471 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
472 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
473 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
474 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
475 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
476
477 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
478 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
479 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
480 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
481 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
482 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
483 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
484 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
485 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
486 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
487 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
488 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
489 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
490 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
491 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
492 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
493 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
494 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
495 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
496};
497
498#include "busywidget.moc"
Note: See TracBrowser for help on using the repository browser.