00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qcursor.h>
00022 #include <qevent.h>
00023 #include <qlabel.h>
00024
00025 #include <klocale.h>
00026
00027 #include <karbon_part.h>
00028 #include <karbon_view.h>
00029 #include <core/vcolor.h>
00030 #include <core/vcomposite.h>
00031 #include <core/vfill.h>
00032 #include <core/vstroke.h>
00033 #include <core/vglobal.h>
00034 #include <core/vcursor.h>
00035 #include <render/vpainter.h>
00036 #include <render/vpainterfactory.h>
00037 #include "vpolylinetool.h"
00038 #include <commands/vshapecmd.h>
00039 #include <commands/vcommand.h>
00040 #include <widgets/vcanvas.h>
00041
00042 VPolylineTool::VPolylineTool( KarbonView *view )
00043 : VTool( view, "tool_polyline" )
00044 {
00045 m_bezierPoints.setAutoDelete( true );
00046 registerTool( this );
00047 m_crossCursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
00048 }
00049
00050 VPolylineTool::~VPolylineTool()
00051 {
00052 delete m_crossCursor;
00053 }
00054
00055 QString
00056 VPolylineTool::contextHelp()
00057 {
00058 QString s = i18n( "<qt><b>Polyline tool:</b><br>" );
00059 s += i18n( "- <i>Click</i> to add a node and <i>drag</i> to set its bezier vector.<br>" );
00060 s += i18n( "- Press <i>Ctrl</i> while dragging to edit the previous bezier vector.<br>" );
00061 s += i18n( "- Press <i>Shift</i> while dragging to change the curve in a straight line.<br>" );
00062 s += i18n( "- Press <i>Backspace</i> to cancel the last curve.<br>" );
00063 s += i18n( "- Press <i>Esc</i> to cancel the whole polyline.<br>" );
00064 s += i18n( "- Press <i>Enter</i> or <i>double click</i> to end the polyline.</qt>" );
00065
00066 return s;
00067 }
00068
00069 void
00070 VPolylineTool::activate()
00071 {
00072 VTool::activate();
00073 view()->statusMessage()->setText( i18n( "Polyline Tool" ) );
00074 view()->setCursor( *m_crossCursor );
00075
00076 m_bezierPoints.clear();
00077 m_close = false;
00078
00079 connect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) );
00080 }
00081
00082 void
00083 VPolylineTool::deactivate()
00084 {
00085 m_bezierPoints.removeLast();
00086 m_bezierPoints.removeLast();
00087
00088 VPath* polyline = 0L;
00089 if( m_bezierPoints.count() > 2 )
00090 {
00091 polyline = new VPath( 0L );
00092 KoPoint* p1 = m_bezierPoints.first();
00093 KoPoint* p2;
00094 KoPoint* p3;
00095 KoPoint* p4;
00096
00097 polyline->moveTo( *p1 );
00098
00099 while(
00100 ( p2 = m_bezierPoints.next() ) &&
00101 ( p3 = m_bezierPoints.next() ) &&
00102 ( p4 = m_bezierPoints.next() ) )
00103 {
00104 if ( *p1 == *p2 )
00105 if ( *p3 == *p4 )
00106 polyline->lineTo( *p4 );
00107 else
00108
00109 polyline->curveTo( *p3, *p4, *p4 );
00110 else
00111 if ( *p3 == *p4 )
00112
00113 polyline->curveTo( *p2, *p2, *p4 );
00114 else
00115 polyline->curveTo( *p2, *p3, *p4 );
00116 p1 = p4;
00117 }
00118
00119 if( m_close )
00120 polyline->close();
00121 }
00122
00123 m_bezierPoints.clear();
00124
00125 if( polyline )
00126 {
00127 VShapeCmd* cmd = new VShapeCmd(
00128 &view()->part()->document(),
00129 i18n( "Polyline" ),
00130 polyline,
00131 "14_polyline" );
00132
00133 view()->part()->addCommand( cmd, true );
00134 }
00135
00136 disconnect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) );
00137 }
00138
00139 void
00140 VPolylineTool::draw()
00141 {
00142 VPainter* painter = view()->painterFactory()->editpainter();
00143 painter->setRasterOp( Qt::NotROP );
00144
00145 if( m_bezierPoints.count() > 2 )
00146 {
00147 VPath polyline( 0L );
00148 polyline.moveTo( *m_bezierPoints.first() );
00149
00150 KoPoint* p2;
00151 KoPoint *p3;
00152 KoPoint *p4;
00153
00154 while(
00155 ( p2 = m_bezierPoints.next() ) &&
00156 ( p3 = m_bezierPoints.next() ) &&
00157 ( p4 = m_bezierPoints.next() ) )
00158 {
00159 polyline.curveTo( *p2, *p3, *p4 );
00160 }
00161
00162 polyline.setState( VObject::edit );
00163 polyline.draw( painter, &polyline.boundingBox() );
00164 }
00165 }
00166
00167 void
00168 VPolylineTool::drawBezierVector( KoPoint& start, KoPoint& end )
00169 {
00170 VPainter* painter = view()->painterFactory()->editpainter();
00171
00172 painter->save();
00173
00174 float zoomFactor = view()->zoom();
00175
00176 painter->setRasterOp( Qt::NotROP );
00177 painter->newPath();
00178
00179
00180
00181
00182 painter->setPen( Qt::DotLine );
00183 painter->setBrush( Qt::NoBrush );
00184
00185 painter->moveTo( start );
00186 painter->lineTo( end );
00187 painter->strokePath();
00188 painter->setRasterOp( Qt::XorROP );
00189 painter->newPath();
00190 painter->setPen( Qt::yellow );
00191
00192 float width = 2.0;
00193
00194 painter->moveTo( KoPoint(
00195 end.x() - width / zoomFactor,
00196 end.y() - width / zoomFactor ) );
00197 painter->lineTo( KoPoint(
00198 end.x() + width / zoomFactor,
00199 end.y() - width / zoomFactor ) );
00200 painter->lineTo( KoPoint(
00201 end.x() + width / zoomFactor,
00202 end.y() + width / zoomFactor ) );
00203 painter->lineTo( KoPoint(
00204 end.x() - width / zoomFactor,
00205 end.y() + width / zoomFactor ) );
00206 painter->lineTo( KoPoint(
00207 end.x() - width / zoomFactor,
00208 end.y() - width / zoomFactor ) );
00209
00210 painter->strokePath();
00211 painter->restore();
00212 }
00213
00214 void
00215 VPolylineTool::mouseMove()
00216 {
00217 if( m_bezierPoints.count() != 0 )
00218 {
00219 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00220 draw();
00221
00222 m_bezierPoints.removeLast();
00223 m_bezierPoints.removeLast();
00224 m_bezierPoints.append( new KoPoint( _last ) );
00225 m_bezierPoints.append( new KoPoint( _last ) );
00226
00227 draw();
00228 }
00229 }
00230
00231 void
00232 VPolylineTool::mouseButtonPress()
00233 {
00234 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00235 if( m_bezierPoints.count() != 0 )
00236 {
00237 draw();
00238 m_bezierPoints.removeLast();
00239 m_bezierPoints.removeLast();
00240 m_bezierPoints.append( new KoPoint( _last ) );
00241 }
00242
00243 m_lastVectorEnd = m_lastVectorStart = _last;
00244
00245 m_bezierPoints.append( new KoPoint( _last ) );
00246 m_bezierPoints.append( new KoPoint( _last ) );
00247 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00248 draw();
00249 }
00250
00251 void
00252 VPolylineTool::mouseButtonRelease()
00253 {
00254 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00255 if( m_bezierPoints.count() == 2 )
00256 {
00257 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00258
00259 m_bezierPoints.removeLast();
00260 m_bezierPoints.append( new KoPoint( _last ) );
00261
00262 VPainter* painter = view()->painterFactory()->editpainter();
00263 painter->save();
00264 painter->setZoomFactor( view()->zoom() );
00265 painter->setRasterOp( Qt::XorROP );
00266 VStroke stroke( Qt::yellow, 0L, 1.0 );
00267 painter->setPen( stroke );
00268 painter->setBrush( Qt::yellow );
00269 painter->newPath();
00270 painter->drawNode( m_lastVectorStart, 2 );
00271 painter->strokePath();
00272 painter->restore();
00273 }
00274 else
00275 {
00276 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00277 draw();
00278 m_bezierPoints.removeLast();
00279 KoPoint* p = new KoPoint( *m_bezierPoints.last() );
00280 m_bezierPoints.removeLast();
00281 KoPoint* b = new KoPoint( *m_bezierPoints.last() );
00282 m_bezierPoints.removeLast();
00283
00284 if( shiftPressed() )
00285 {
00286 m_bezierPoints.removeLast();
00287 m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) );
00288 m_bezierPoints.append( new KoPoint( *p ) );
00289 m_bezierPoints.append( new KoPoint( *p ) );
00290 m_bezierPoints.append( new KoPoint( *p ) );
00291 m_lastVectorStart = m_lastVectorEnd = *p;
00292 }
00293 else if( ctrlPressed() )
00294 {
00295 m_bezierPoints.removeLast();
00296 m_lastVectorStart = *m_bezierPoints.last();
00297 m_bezierPoints.append( new KoPoint( _last ) );
00298 m_bezierPoints.append( new KoPoint( *b ) );
00299 m_bezierPoints.append( new KoPoint( *p ) );
00300 m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) );
00301 m_lastVectorEnd = _last;
00302 }
00303 else
00304 {
00305 m_bezierPoints.append( new KoPoint( _last ) );
00306 m_bezierPoints.append( new KoPoint( *p ) );
00307 m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) );
00308 m_lastVectorStart = *p;
00309 m_lastVectorEnd = _last;
00310 }
00311 if( m_bezierPoints.count() > 2 && p->isNear( *m_bezierPoints.first(), 3 ) )
00312 {
00313 m_bezierPoints.append( new KoPoint( _last ) );
00314 m_close = true;
00315 accept();
00316 return;
00317 }
00318 }
00319
00320 m_bezierPoints.append( new KoPoint( _last ) );
00321 m_bezierPoints.append( new KoPoint( _last ) );
00322
00323 draw();
00324 }
00325
00326 void
00327 VPolylineTool::rightMouseButtonRelease()
00328 {
00329
00330 accept();
00331 }
00332
00333 void
00334 VPolylineTool::mouseButtonDblClick()
00335 {
00336 accept();
00337 }
00338
00339 void
00340 VPolylineTool::mouseDrag()
00341 {
00342 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00343
00344 if( m_bezierPoints.count() == 2 )
00345 {
00346 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00347
00348 m_bezierPoints.removeLast();
00349 m_bezierPoints.append( new KoPoint( _last ) );
00350 m_lastVectorEnd = _last;
00351
00352 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00353 }
00354 else
00355 {
00356 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00357 draw();
00358
00359 m_bezierPoints.removeLast();
00360 KoPoint* p = new KoPoint( *m_bezierPoints.last() );
00361 m_bezierPoints.removeLast();
00362 KoPoint* b = new KoPoint( *m_bezierPoints.last() );
00363 m_bezierPoints.removeLast();
00364
00365 if( shiftPressed() )
00366 {
00367 m_bezierPoints.removeLast();
00368 m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) );
00369 m_bezierPoints.append( new KoPoint( *p ) );
00370 m_bezierPoints.append( new KoPoint( *p ) );
00371 m_bezierPoints.append( new KoPoint( *p ) );
00372 m_lastVectorStart = m_lastVectorEnd = *p;
00373 }
00374 else if( ctrlPressed() )
00375 {
00376 m_bezierPoints.removeLast();
00377 m_lastVectorStart = *m_bezierPoints.last();
00378 m_bezierPoints.append( new KoPoint( _last ) );
00379 m_bezierPoints.append( new KoPoint( *b ) );
00380 m_bezierPoints.append( new KoPoint( *p ) );
00381 m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) );
00382 m_lastVectorEnd = _last;
00383 }
00384 else
00385 {
00386 m_bezierPoints.append( new KoPoint( _last ) );
00387 m_bezierPoints.append( new KoPoint( *p ) );
00388 m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) );
00389 m_lastVectorStart = *p;
00390 m_lastVectorEnd = _last;
00391 }
00392
00393 draw();
00394 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00395 }
00396 }
00397
00398 void
00399 VPolylineTool::mouseDragRelease()
00400 {
00401 mouseButtonRelease();
00402 }
00403
00404 void
00405 VPolylineTool::mouseDragShiftPressed()
00406 {
00407 }
00408
00409 void
00410 VPolylineTool::mouseDragCtrlPressed()
00411 {
00412
00413 if( m_bezierPoints.count() > 3 )
00414 {
00415 KoPoint p;
00416 p = *m_bezierPoints.at( m_bezierPoints.count() - 4) - *m_bezierPoints.at( m_bezierPoints.count() - 3 );
00417
00418 view()->setPos( p );
00419 }
00420 }
00421
00422 void
00423 VPolylineTool::mouseDragShiftReleased()
00424 {
00425 }
00426
00427 void
00428 VPolylineTool::mouseDragCtrlReleased()
00429 {
00430 if( m_bezierPoints.count() > 3 )
00431 {
00432 KoPoint p;
00433 p = *m_bezierPoints.at( m_bezierPoints.count() - 3) - *m_bezierPoints.at( m_bezierPoints.count() - 4 );
00434
00435 view()->setPos( p );
00436 }
00437 }
00438
00439 void
00440 VPolylineTool::cancel()
00441 {
00442 draw();
00443
00444 m_bezierPoints.clear();
00445 }
00446
00447 void
00448 VPolylineTool::cancelStep()
00449 {
00450 draw();
00451
00452 if ( m_bezierPoints.count() > 6 )
00453 {
00454 m_bezierPoints.removeLast();
00455 m_bezierPoints.removeLast();
00456 m_bezierPoints.removeLast();
00457 KoPoint p1 = *m_bezierPoints.last();
00458 m_bezierPoints.removeLast();
00459 m_bezierPoints.removeLast();
00460 m_bezierPoints.append( new KoPoint( p1 ) );
00461 m_bezierPoints.append( new KoPoint( p1 ) );
00462
00463 view()->setPos( p1 );
00464 }
00465 else
00466 {
00467 m_bezierPoints.clear();
00468 }
00469
00470 draw();
00471 }
00472
00473 void
00474 VPolylineTool::accept()
00475 {
00476 activate();
00477 }
00478
00479 void
00480 VPolylineTool::setup( KActionCollection *collection )
00481 {
00482 m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00483
00484 if( m_action == 0 )
00485 {
00486 KShortcut shortcut( Qt::Key_Plus );
00487 shortcut.append( KShortcut( Qt::Key_F9 ) );
00488 m_action = new KRadioAction( i18n( "Polyline Tool" ), "14_polyline", shortcut, this, SLOT( activate() ), collection, name() );
00489 m_action->setToolTip( i18n( "Polyline" ) );
00490 m_action->setExclusiveGroup( "freehand" );
00491
00492 }
00493 }
00494
00495 void
00496 VPolylineTool::commandExecuted()
00497 {
00498 cancel();
00499 }
00500
00501 #include "vpolylinetool.moc"