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

qimpenwidget.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of 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 <qapplication.h>
00022 #include <qinputdialog.h>
00023 #include <qpainter.h>
00024 #include <qfile.h>
00025 #include <qdatastream.h>
00026 #include <qtimer.h>
00027 #include "qimpenchar.h"
00028 #include "qimpenwidget.h"
00029 
00030 #define TITLE_WIDTH     30  // ### magic
00031 
00038 QIMPenWidget::QIMPenWidget( QWidget *parent )
00039  : QWidget( parent )
00040 {
00041     charSets.setAutoDelete( TRUE );
00042     inputStroke = 0;
00043     outputChar = 0;
00044     outputStroke = 0;
00045     mode = Waiting;
00046     currCharSet = 0;
00047     readOnly = FALSE;
00048     strokes.setAutoDelete( TRUE );
00049 
00050     timer = new QTimer(this);
00051     connect( timer, SIGNAL(timeout()), SLOT(timeout()));
00052 
00053     setBackgroundColor( qApp->palette().color( QPalette::Active,
00054                                                QColorGroup::Base ) );
00055     strokeColor = black;
00056     setFixedHeight( 75 );
00057 }
00058 
00059 void QIMPenWidget::clear()
00060 {
00061     timer->stop();
00062     mode = Waiting;
00063     QRect r( dirtyRect );
00064     QIMPenStrokeIterator it( strokes );
00065     while ( it.current() ) {
00066         r |= it.current()->boundingRect();
00067         ++it;
00068     }
00069     outputChar = 0;
00070     outputStroke = 0;
00071     strokes.clear();
00072     if ( !r.isNull() ) {
00073         r.moveBy( -2, -2 );
00074         r.setSize( r.size() + QSize( 4, 4 ) );
00075         repaint( r );
00076     } else {
00077         repaint();
00078     }
00079 }
00080 
00081 void QIMPenWidget::removeStroke()
00082 {
00083     QRect r( dirtyRect );
00084     QIMPenStroke *st = strokes.getFirst();
00085     QRect strokeRect;
00086     if ( st )
00087        strokeRect = st->boundingRect();
00088     r |= strokeRect;
00089     strokes.removeFirst();
00090     if ( !r.isNull() ) {
00091         r.moveBy( -2, -2 );
00092         r.setSize( r.size() + QSize( 4, 4 ) );
00093         repaint( r );
00094     }
00095 }
00096 
00097 void QIMPenWidget::greyStroke()
00098 {
00099     QRect r( dirtyRect );
00100     QIMPenStroke *st = strokes.getLast();
00101     QRect strokeRect;
00102     if ( st )
00103        strokeRect = st->boundingRect();
00104     r |= strokeRect;
00105     QColor oldCol = strokeColor;
00106     strokeColor = gray;
00107     if ( !r.isNull() ) {
00108         r.moveBy( -2, -2 );
00109         r.setSize( r.size() + QSize( 4, 4 ) );
00110         repaint( r );
00111     }
00112     strokeColor = oldCol;
00113 }
00114 
00118 void QIMPenWidget::insertCharSet( QIMPenCharSet *cs, int stretch, int pos )
00119 {
00120     CharSetEntry *e = new CharSetEntry;
00121     e->cs = cs;
00122     e->stretch = stretch;
00123     if ( pos < 0 )
00124         pos = charSets.count();
00125     charSets.insert( pos, e );
00126     currCharSet = 0;
00127     emit changeCharSet( currCharSet );
00128     emit changeCharSet( charSets.at(currCharSet)->cs );
00129     totalStretch = 0;
00130     CharSetEntryIterator it( charSets );
00131     for ( ; it.current(); ++it )
00132         totalStretch += it.current()->stretch;
00133     update();
00134 }
00135 
00139 void QIMPenWidget::removeCharSet( int pos )
00140 {
00141     if ( pos >= 0 && pos < (int)charSets.count() ) {
00142         charSets.remove( pos );
00143         currCharSet = 0;
00144         if ( charSets.count() ) {
00145             emit changeCharSet( currCharSet );
00146             emit changeCharSet( charSets.at(currCharSet)->cs );
00147         }
00148         totalStretch = 0;
00149         CharSetEntryIterator it( charSets );
00150         for ( ; it.current(); ++it )
00151             totalStretch += it.current()->stretch;
00152         update();
00153     }
00154 }
00155 
00156 void QIMPenWidget::changeCharSet( QIMPenCharSet *cs, int pos )
00157 {
00158     if ( pos >= 0 && pos < (int)charSets.count() ) {
00159         CharSetEntry *e = new CharSetEntry;
00160         e->cs = cs;
00161         e->stretch = charSets.at(pos)->stretch;
00162         charSets.remove( pos );
00163         charSets.insert( pos, e );
00164         if ( pos == currCharSet ) {
00165             emit changeCharSet( charSets.at(currCharSet)->cs );
00166         }
00167         update();
00168     }
00169 }
00170 
00171 void QIMPenWidget::clearCharSets()
00172 {
00173     charSets.clear();
00174     currCharSet = 0;
00175     update();
00176 }
00177 
00182 void QIMPenWidget::showCharacter( QIMPenChar *ch, int speed )
00183 {
00184     outputChar = 0;
00185     outputStroke = 0;
00186     strokes.clear();
00187     mode = Output;
00188     repaint();
00189     if ( !ch || ch->isEmpty() ) {
00190         mode = Waiting;
00191         return;
00192     }
00193 
00194     outputChar = ch;
00195     outputStroke = outputChar->penStrokes().getFirst();
00196     if ( speed < 0 ) speed = 0;
00197     if ( speed > 20 ) speed = 20;
00198     speed = 50 - speed;
00199     pointIndex = 0;
00200     strokeIndex = 0;
00201     lastPoint = outputStroke->startingPoint();
00202     QRect br( outputChar->boundingRect() );
00203     lastPoint.setX( (width() - br.width()) / 2 + (lastPoint.x () - br.left()) );
00204     QPoint offset = lastPoint - outputStroke->startingPoint();
00205     br.moveBy( offset.x(), offset.y() );
00206     dirtyRect |= br;
00207     timer->start( speed );
00208 }
00209 
00213 void QIMPenWidget::timeout()
00214 {
00215     if ( mode == Output ) {
00216         const QArray<QIMPenGlyphLink> &chain = outputStroke->chain();
00217         if ( pointIndex < chain.count() ) {
00218             QPainter paint( this );
00219             paint.setBrush( Qt::black );
00220             for ( unsigned i = 0; i < 3 && pointIndex < chain.count(); i++ ) {
00221                 lastPoint.rx() += chain[pointIndex].dx;
00222                 lastPoint.ry() += chain[pointIndex].dy;
00223                 pointIndex++;
00224                 paint.drawRect( lastPoint.x()-1, lastPoint.y()-1, 2, 2 );
00225             }
00226         }
00227         if ( pointIndex >= chain.count() ) {
00228             QIMPenStrokeList strokes = outputChar->penStrokes();
00229             if ( strokeIndex < (int)strokes.count() - 1 ) {
00230                 pointIndex = 0;
00231                 strokeIndex++;
00232                 outputStroke = strokes.at( strokeIndex );
00233                 lastPoint = outputChar->startingPoint();
00234                 QRect br( outputChar->boundingRect() );
00235                 lastPoint.setX( (width() - br.width()) / 2
00236                                 + (lastPoint.x () - br.left()) );
00237                 QPoint off = lastPoint - outputChar->startingPoint();
00238                 lastPoint = outputStroke->startingPoint() + off;
00239             } else {
00240                 timer->stop();
00241                 mode = Waiting;
00242             }
00243         }
00244     } else if ( mode == Waiting ) {
00245         QRect r( dirtyRect );
00246         if ( !r.isNull() ) {
00247             r.moveBy( -2, -2 );
00248             r.setSize( r.size() + QSize( 4, 4 ) );
00249             repaint( r );
00250         }
00251     }
00252 }
00253 
00258 bool QIMPenWidget::selectSet( QPoint p )
00259 {
00260     if ( charSets.count() ) {
00261         CharSetEntryIterator it( charSets );
00262         int spos = 0;
00263         int idx = 0;
00264         for ( ; it.current(); ++it, idx++ ) {
00265             int setWidth = width() * it.current()->stretch / totalStretch;
00266             spos += setWidth;
00267             if ( p.x() < spos ) {
00268                 if ( idx != currCharSet ) {
00269                     currCharSet = idx;
00270                     update( 0, 0, width(), 12 );
00271                     emit changeCharSet( currCharSet );
00272                     emit changeCharSet( charSets.at(currCharSet)->cs );
00273                 }
00274                 break;
00275             }
00276         }
00277     }
00278 
00279     return FALSE;
00280 }
00281 
00285 QSize QIMPenWidget::sizeHint()
00286 {
00287     return QSize( TITLE_WIDTH * charSets.count(), 75 );
00288 }
00289 
00290 void QIMPenWidget::mousePressEvent( QMouseEvent *e )
00291 {
00292     if ( !readOnly && e->button() == LeftButton && mode == Waiting ) {
00293         // if selectSet returns false the click was not over the
00294         // char set selectors.
00295         if ( !selectSet( e->pos() ) ) {
00296             // start of character input
00297             timer->stop();
00298             if ( outputChar ) {
00299                 outputChar = 0;
00300                 outputStroke = 0;
00301                 repaint();
00302             }
00303             mode = Input;
00304             lastPoint = e->pos();
00305             emit beginStroke();
00306             inputStroke = new QIMPenStroke;
00307             strokes.append( inputStroke );
00308             inputStroke->beginInput( e->pos() );
00309             QPainter paint( this );
00310             paint.setBrush( Qt::black );
00311             paint.drawRect( lastPoint.x()-1, lastPoint.y()-1, 2, 2 );
00312         }
00313     }
00314 }
00315 
00316 void QIMPenWidget::mouseReleaseEvent( QMouseEvent *e )
00317 {
00318     if ( !readOnly && e->button() == LeftButton && mode == Input ) {
00319         mode = Waiting;
00320         inputStroke->endInput();
00321         if ( charSets.count() )
00322             emit stroke( inputStroke );
00323         inputStroke = 0;
00324     }
00325 }
00326 
00327 void QIMPenWidget::mouseMoveEvent( QMouseEvent *e )
00328 {
00329     if ( !readOnly && mode == Input ) {
00330         int dx = QABS( e->pos().x() - lastPoint.x() );
00331         int dy = QABS( e->pos().y() - lastPoint.y() );
00332         if ( dx + dy > 1 ) {
00333             if ( inputStroke->addPoint( e->pos() ) ) {
00334                 QPainter paint( this );
00335                 paint.setPen( Qt::black );
00336                 paint.setBrush( Qt::black );
00337                 const QArray<QIMPenGlyphLink> &chain = inputStroke->chain();
00338                 QPoint p( e->pos() );
00339                 for ( int i = (int)chain.count()-1; i >= 0; i-- ) {
00340                     paint.drawRect( p.x()-1, p.y()-1, 2, 2 );
00341                     p.rx() -= chain[i].dx;
00342                     p.ry() -= chain[i].dy;
00343                     if ( p == lastPoint )
00344                         break;
00345                 }
00346 
00347                 /* ### use this when thick lines work properly on all devices
00348                 paint.setPen( QPen( Qt::black, 2 ) );
00349                 paint.drawLine( lastPoint, e->pos() );
00350                 */
00351             }
00352             lastPoint = e->pos();
00353         }
00354     }
00355 }
00356 
00357 void QIMPenWidget::paintEvent( QPaintEvent * )
00358 {
00359     QPainter paint( this );
00360 
00361     // draw guidelines
00362     paint.setPen( Qt::gray );
00363     paint.drawLine( 0, 0, width(), 0 );
00364     int y = height() / 3;
00365     paint.drawLine( 0, y, width(), y );
00366     y *= 2;
00367     paint.setPen( blue );
00368     paint.drawLine( 0, y, width(), y );
00369     paint.setPen( Qt::gray );
00370 
00371     if ( !charSets.count() )
00372         return;
00373 
00374     // draw the character set titles
00375     QFont selFont( "helvetica", 8, QFont::Bold );
00376     QFont font( "helvetica", 8 );
00377     CharSetEntryIterator it( charSets );
00378     int spos = 0;
00379     for ( ; it.current(); ++it ) {
00380         int setWidth = width() * it.current()->stretch / totalStretch;
00381         spos += setWidth;
00382         if ( it.current() != charSets.getLast() ) {
00383             paint.drawLine( spos, 0, spos, 5 );
00384             paint.drawLine( spos, height()-1, spos, height()-6 );
00385         }
00386         paint.setFont( font );
00387         int w = paint.fontMetrics().width( it.current()->cs->title() );
00388         int tpos = spos - setWidth / 2;
00389         paint.drawText( tpos - w/2, 0, w, 12, QPainter::AlignCenter,
00390                         it.current()->cs->title() );
00391     }
00392 
00393     // draw any character that should be displayed when repainted.
00394     QPoint off;
00395     const QIMPenStrokeList *stk = 0;
00396     if ( outputChar && mode == Waiting ) {
00397         stk = &outputChar->penStrokes();
00398         QPoint p( outputChar->startingPoint() );
00399         QRect br( outputChar->boundingRect() );
00400         p.setX( (width() - br.width()) / 2 + (p.x () - br.left()) );
00401         off = p - outputChar->startingPoint();
00402     } else if ( mode == Waiting ) {
00403         stk = &strokes;
00404         strokeColor = gray;
00405     }
00406 
00407     if ( stk && !stk->isEmpty() ) {
00408         paint.setPen( strokeColor );
00409         paint.setBrush( strokeColor );
00410         QIMPenStrokeIterator it( *stk );
00411         while ( it.current() ) {
00412             QPoint p = it.current()->startingPoint() + off;
00413             paint.drawRect( p.x()-1, p.y()-1, 2, 2 );
00414             const QArray<QIMPenGlyphLink> &chain = it.current()->chain();
00415             for ( unsigned i = 0; i < chain.count(); i++ ) {
00416                     p.rx() += chain[i].dx;
00417                     p.ry() += chain[i].dy;
00418                     paint.drawRect( p.x()-1, p.y()-1, 2, 2 );
00419             }
00420             ++it;
00421             if ( it.atLast() && mode == Waiting )
00422                 strokeColor = black;
00423         }
00424     }
00425 
00426     dirtyRect = QRect();
00427 
00428     // debug
00429 /*
00430     if ( input ) {
00431         QArray<int> sig = input->sig();
00432         for ( unsigned i = 0; i < sig.count(); i++ ) {
00433             paint.drawPoint( 200 + i, height()/2 - sig[i] / 8 );
00434         }
00435     }
00436 */
00437 }
00438 
00439 void QIMPenWidget::resizeEvent( QResizeEvent *e )
00440 {
00441     if ( mode == Output )
00442         showCharacter( outputChar, 0 );
00443 
00444     QWidget::resizeEvent( e );
00445 }
00446 

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