00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00294
00295 if ( !selectSet( e->pos() ) ) {
00296
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
00348
00349
00350
00351 }
00352 lastPoint = e->pos();
00353 }
00354 }
00355 }
00356
00357 void QIMPenWidget::paintEvent( QPaintEvent * )
00358 {
00359 QPainter paint( this );
00360
00361
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
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
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
00429
00430
00431
00432
00433
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