summaryrefslogtreecommitdiff
path: root/noncore/tools/clock/analogclock.cpp
Unidiff
Diffstat (limited to 'noncore/tools/clock/analogclock.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/tools/clock/analogclock.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/noncore/tools/clock/analogclock.cpp b/noncore/tools/clock/analogclock.cpp
new file mode 100644
index 0000000..bf358e2
--- a/dev/null
+++ b/noncore/tools/clock/analogclock.cpp
@@ -0,0 +1,203 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of the Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "analogclock.h"
22
23#include <qlayout.h>
24#include <qpainter.h>
25#include <qtopia/global.h>
26
27#include <math.h>
28
29 const double deg2rad = 0.017453292519943295769;// pi/180
30
31AnalogClock::AnalogClock( QWidget *parent, const char *name )
32 : QFrame( parent, name ), clear(false)
33{
34 setMinimumSize(50,50);
35}
36
37QSizePolicy AnalogClock::sizePolicy() const
38{
39 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
40}
41
42void AnalogClock::drawContents( QPainter *p )
43{
44#if !defined(NO_DEBUG)
45 static bool first = true;
46 if ( first ) {
47 QTOPIA_PROFILE("first paint event");
48 first = false;
49 }
50#endif
51
52 QRect r = contentsRect();
53
54 if ( r.width() < r.height() ) {
55 r.setY( (r.height() - r.width())/2 );
56 r.setHeight( r.width() );
57 }
58
59 QPoint center( r.x() + r.width() / 2, r.y() + r.height() / 2 );
60
61 const int w_tick = r.width()/300+1;
62 const int w_sec = r.width()/400+1;
63 const int w_hour = r.width()/80+1;
64
65 QPoint l1( r.x() + r.width() / 2, r.y() + 2 );
66 QPoint l2( r.x() + r.width() / 2, r.y() + 8 );
67
68 QPoint h1( r.x() + r.width() / 2, r.y() + r.height() / 4 );
69 QPoint h2( r.x() + r.width() / 2, r.y() + r.height() / 2 );
70
71 QPoint m1( r.x() + r.width() / 2, r.y() + r.height() / 9 );
72 QPoint m2( r.x() + r.width() / 2, r.y() + r.height() / 2 );
73
74 QPoint s1( r.x() + r.width() / 2, r.y() + 8 );
75 QPoint s2( r.x() + r.width() / 2, r.y() + r.height() / 2 );
76
77 QColor color( clear ? backgroundColor() : black );
78 QTime time = clear ? prevTime : currTime;
79
80 if ( clear && prevTime.secsTo(currTime) > 1 ) {
81 p->eraseRect( rect() );
82 return;
83 }
84
85 if ( !clear ) {
86 // draw ticks
87 p->setPen( QPen( color, w_tick ) );
88 for ( int i = 0; i < 12; i++ )
89 p->drawLine( rotate( center, l1, i * 30 ), rotate( center, l2, i * 30 ) );
90 }
91
92 if ( !clear || prevTime.minute() != currTime.minute() ||
93 prevTime.hour() != currTime.hour() ) {
94 // draw hour pointer
95 h1 = rotate( center, h1, 30 * ( time.hour() % 12 ) + time.minute() / 2 );
96 h2 = rotate( center, h2, 30 * ( time.hour() % 12 ) + time.minute() / 2 );
97 p->setPen( color );
98 p->setBrush( color );
99 drawHand( p, h1, h2 );
100 }
101
102 if ( !clear || prevTime.minute() != currTime.minute() ) {
103 // draw minute pointer
104 m1 = rotate( center, m1, time.minute() * 6 );
105 m2 = rotate( center, m2, time.minute() * 6 );
106 p->setPen( color );
107 p->setBrush( color );
108 drawHand( p, m1, m2 );
109 }
110
111 // draw second pointer
112 s1 = rotate( center, s1, time.second() * 6 );
113 s2 = rotate( center, s2, time.second() * 6 );
114 p->setPen( QPen( color, w_sec ) );
115 p->drawLine( s1, s2 );
116
117 // cap
118 p->setBrush(color);
119 p->drawEllipse( center.x()-w_hour/2, center.y()-w_hour/2, w_hour, w_hour );
120
121 if ( !clear )
122 prevTime = currTime;
123}
124
125// Dijkstra's bisection algorithm to find the square root as an integer.
126
127static uint int_sqrt(uint n)
128{
129 if ( n >= UINT_MAX>>2 ) // n must be in the range 0...UINT_MAX/2-1
130 return 2*int_sqrt( n/4 );
131 uint h, p= 0, q= 1, r= n;
132 while ( q <= n )
133 q <<= 2;
134 while ( q != 1 ) {
135 q >>= 2;
136 h= p + q;
137 p >>= 1;
138 if ( r >= h ) {
139 p += q;
140 r -= h;
141 }
142 }
143 return p;
144}
145
146void AnalogClock::drawHand( QPainter *p, QPoint p1, QPoint p2 )
147{
148 int hw = 7;
149 if ( contentsRect().height() < 100 )
150 hw = 5;
151
152 int dx = p2.x() - p1.x();
153 int dy = p2.y() - p1.y();
154 int w = dx*dx+dy*dy;
155 int ix,iy;
156 w = int_sqrt(w*256);
157 iy = w ? (hw * dy * 16)/ w : dy ? 0 : hw;
158 ix = w ? (hw * dx * 16)/ w : dx ? 0 : hw;
159
160 // rounding dependent on sign
161 int nix, niy;
162 if ( ix < 0 ) {
163 nix = ix/2;
164 ix = (ix-1)/2;
165 } else {
166 nix = (ix+1)/2;
167 ix = ix/2;
168 }
169 if ( iy < 0 ) {
170 niy = iy/2;
171 iy = (iy-1)/2;
172 } else {
173 niy = (iy+1)/2;
174 iy = iy/2;
175 }
176
177 QPointArray pa(4);
178 pa[0] = p1;
179 pa[1] = QPoint( p2.x()+iy, p2.y()-nix );
180 pa[2] = QPoint( p2.x()-niy, p2.y()+ix );
181 pa[3] = p1;
182
183 p->drawPolygon( pa );
184}
185
186void AnalogClock::display( const QTime& t )
187{
188 currTime = t;
189 clear = true;
190 repaint( false );
191 clear = false;
192 repaint( false );
193}
194
195QPoint AnalogClock::rotate( QPoint c, QPoint p, int a )
196{
197 double angle = deg2rad * ( - a + 180 );
198 double nx = c.x() - ( p.x() - c.x() ) * cos( angle ) -
199 ( p.y() - c.y() ) * sin( angle );
200 double ny = c.y() - ( p.y() - c.y() ) * cos( angle ) +
201 ( p.x() - c.x() ) * sin( angle );
202 return QPoint( int(nx), int(ny) );
203}