Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

analogclock.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
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; // pi/180
00033 
00034 AnalogClock::AnalogClock( QWidget *parent, const char *name )
00035     : QFrame( parent, name )
00036 {
00037     setMinimumSize(50,50);
00038 
00039     /* initial the buffer pixmap */
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     /* no need to draw... */
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     /* resize the buffer */
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     /* fill the pixmap */
00095     _pixmap->fill( this, 0, 0 );
00096 
00097 
00098     // draw ticks
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     // draw hour pointer
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     // draw minute pointer
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     // draw second pointer
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     // cap
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     /* leave */
00138 }
00139 
00140 // Dijkstra's bisection algorithm to find the square root as an integer.
00141 
00142 static uint int_sqrt(uint n)
00143 {
00144     if ( n >= UINT_MAX>>2 ) // n must be in the range 0...UINT_MAX/2-1
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     // rounding dependent on sign
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 }

Generated on Sat Nov 5 16:18:01 2005 for OPIE by  doxygen 1.4.2