00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "analogclock.h"
00022
00023 #include <qtopia/global.h>
00024
00025 #include <qlayout.h>
00026 #include <qpainter.h>
00027 #include <qpixmap.h>
00028
00029
00030 #include <math.h>
00031
00032 const double deg2rad = 0.017453292519943295769;
00033
00034 AnalogClock::AnalogClock( QWidget *parent, const char *name )
00035 : QFrame( parent, name )
00036 {
00037 setMinimumSize(50,50);
00038
00039
00040 QRect r = contentsRect();
00041 _pixmap = new QPixmap( r.width(), r.height() );
00042 }
00043
00044 AnalogClock::~AnalogClock() {
00045 delete _pixmap;
00046 }
00047
00048 QSizePolicy AnalogClock::sizePolicy() const
00049 {
00050 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
00051 }
00052
00053 void AnalogClock::drawContents( QPainter * )
00054 {
00055
00056 if ( !isVisible() )
00057 return;
00058
00059
00060 QRect r = contentsRect();
00061
00062 if ( r.width() < r.height() ) {
00063 r.setY( (r.height() - r.width())/2 );
00064 r.setHeight( r.width() );
00065 }
00066
00067
00068 if ( r.width() != _pixmap->width() ||
00069 r.height() != _pixmap->height() )
00070 _pixmap->resize( r.width(), r.height() );
00071
00072 QPainter p;
00073 p.begin( _pixmap );
00074
00075
00076 QPoint center( r.x() + r.width() / 2, r.y() + r.height() / 2 );
00077
00078 const int w_tick = r.width()/300+1;
00079 const int w_sec = r.width()/400+1;
00080 const int w_hour = r.width()/80+1;
00081
00082 QPoint l1( r.x() + r.width() / 2, r.y() + 2 );
00083 QPoint l2( r.x() + r.width() / 2, r.y() + 8 );
00084
00085 QPoint h1( r.x() + r.width() / 2, r.y() + r.height() / 4 );
00086 QPoint h2( r.x() + r.width() / 2, r.y() + r.height() / 2 );
00087
00088 QPoint m1( r.x() + r.width() / 2, r.y() + r.height() / 9 );
00089 QPoint m2( r.x() + r.width() / 2, r.y() + r.height() / 2 );
00090
00091 QPoint s1( r.x() + r.width() / 2, r.y() + 8 );
00092 QPoint s2( r.x() + r.width() / 2, r.y() + r.height() / 2 );
00093
00094
00095 _pixmap->fill( this, 0, 0 );
00096
00097
00098
00099 QColor color = black;
00100 p.setPen( QPen( color, w_tick ) );
00101 for ( int i = 0; i < 12; i++ )
00102 p.drawLine( rotate( center, l1, i * 30 ), rotate( center, l2, i * 30 ) );
00103
00104
00105
00106 h1 = rotate( center, h1, 30 * ( currTime.hour() % 12 ) + currTime.minute() / 2 );
00107 h2 = rotate( center, h2, 30 * ( currTime.hour() % 12 ) + currTime.minute() / 2 );
00108 p.setPen( color );
00109 p.setBrush( color );
00110 drawHand( &p, h1, h2 );
00111
00112
00113
00114 m1 = rotate( center, m1, currTime.minute() * 6 );
00115 m2 = rotate( center, m2, currTime.minute() * 6 );
00116 p.setPen( color );
00117 p.setBrush( color );
00118 drawHand( &p, m1, m2 );
00119
00120
00121 s1 = rotate( center, s1, currTime.second() * 6 );
00122 s2 = rotate( center, s2, currTime.second() * 6 );
00123 p.setPen( QPen( color, w_sec ) );
00124 p.drawLine( s1, s2 );
00125
00126
00127 p.setBrush(color);
00128 p.drawEllipse( center.x()-w_hour/2, center.y()-w_hour/2, w_hour, w_hour );
00129
00130 prevTime = currTime;
00131
00132 p.end();
00133
00134 p.begin( this );
00135 p.drawPixmap( 0, 0, *_pixmap );
00136
00137
00138 }
00139
00140
00141
00142 static uint int_sqrt(uint n)
00143 {
00144 if ( n >= UINT_MAX>>2 )
00145 return 2*int_sqrt( n/4 );
00146 uint h, p= 0, q= 1, r= n;
00147 while ( q <= n )
00148 q <<= 2;
00149 while ( q != 1 ) {
00150 q >>= 2;
00151 h= p + q;
00152 p >>= 1;
00153 if ( r >= h ) {
00154 p += q;
00155 r -= h;
00156 }
00157 }
00158 return p;
00159 }
00160
00161 void AnalogClock::drawHand( QPainter *p, QPoint p1, QPoint p2 )
00162 {
00163 int hw = 7;
00164 if ( contentsRect().height() < 100 )
00165 hw = 5;
00166
00167 int dx = p2.x() - p1.x();
00168 int dy = p2.y() - p1.y();
00169 int w = dx*dx+dy*dy;
00170 int ix,iy;
00171 w = int_sqrt(w*256);
00172 iy = w ? (hw * dy * 16)/ w : dy ? 0 : hw;
00173 ix = w ? (hw * dx * 16)/ w : dx ? 0 : hw;
00174
00175
00176 int nix, niy;
00177 if ( ix < 0 ) {
00178 nix = ix/2;
00179 ix = (ix-1)/2;
00180 } else {
00181 nix = (ix+1)/2;
00182 ix = ix/2;
00183 }
00184 if ( iy < 0 ) {
00185 niy = iy/2;
00186 iy = (iy-1)/2;
00187 } else {
00188 niy = (iy+1)/2;
00189 iy = iy/2;
00190 }
00191
00192 QPointArray pa(4);
00193 pa[0] = p1;
00194 pa[1] = QPoint( p2.x()+iy, p2.y()-nix );
00195 pa[2] = QPoint( p2.x()-niy, p2.y()+ix );
00196 pa[3] = p1;
00197
00198 p->drawPolygon( pa );
00199 }
00200
00201 void AnalogClock::display( const QTime& t )
00202 {
00203 currTime = t;
00204 repaint( false );
00205 }
00206
00207 QPoint AnalogClock::rotate( QPoint c, QPoint p, int a )
00208 {
00209 double angle = deg2rad * ( - a + 180 );
00210 double nx = c.x() - ( p.x() - c.x() ) * cos( angle ) -
00211 ( p.y() - c.y() ) * sin( angle );
00212 double ny = c.y() - ( p.y() - c.y() ) * cos( angle ) +
00213 ( p.x() - c.x() ) * sin( angle );
00214 return QPoint( int(nx), int(ny) );
00215 }