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::initializePath( VPath &path )
00084 {
00085 KoPoint* p1 = m_bezierPoints.first();
00086 KoPoint* p2;
00087 KoPoint* p3;
00088 KoPoint* p4;
00089
00090 path.moveTo( *p1 );
00091
00092 while(
00093 ( p2 = m_bezierPoints.next() ) &&
00094 ( p3 = m_bezierPoints.next() ) &&
00095 ( p4 = m_bezierPoints.next() ) )
00096 {
00097 if ( *p1 == *p2 )
00098 if ( *p3 == *p4 )
00099 path.lineTo( *p4 );
00100 else
00101
00102 path.curveTo( *p3, *p4, *p4 );
00103 else
00104 if ( *p3 == *p4 )
00105
00106 path.curveTo( *p2, *p2, *p4 );
00107 else
00108 path.curveTo( *p2, *p3, *p4 );
00109 p1 = p4;
00110 }
00111 }
00112
00113 void
00114 VPolylineTool::createObject()
00115 {
00116 VPath* polyline = 0L;
00117 if( m_bezierPoints.count() > 2 )
00118 {
00119 polyline = new VPath( 0L );
00120 if( polyline )
00121 {
00122 initializePath( *polyline );
00123 if( m_close )
00124 polyline->close();
00125
00126 VShapeCmd* cmd = new VShapeCmd(
00127 &view()->part()->document(),
00128 i18n( "Polyline" ),
00129 polyline,
00130 "14_polyline" );
00131
00132 view()->part()->addCommand( cmd, true );
00133 }
00134 }
00135
00136 m_bezierPoints.clear();
00137 m_close = false;
00138 }
00139
00140 void
00141 VPolylineTool::deactivate()
00142 {
00143 m_bezierPoints.removeLast();
00144 m_bezierPoints.removeLast();
00145
00146 createObject();
00147
00148 disconnect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) );
00149 }
00150
00151 void
00152 VPolylineTool::draw()
00153 {
00154 VPainter* painter = view()->painterFactory()->editpainter();
00155 painter->setRasterOp( Qt::NotROP );
00156
00157 if( m_bezierPoints.count() > 2 )
00158 {
00159 VPath polyline( 0L );
00160 initializePath( polyline );
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 createObject();
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 m_bezierPoints.removeLast();
00331 m_bezierPoints.removeLast();
00332
00333 createObject();
00334 }
00335
00336 void
00337 VPolylineTool::mouseButtonDblClick()
00338 {
00339 createObject();
00340 }
00341
00342 void
00343 VPolylineTool::mouseDrag()
00344 {
00345 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00346
00347 if( m_bezierPoints.count() == 2 )
00348 {
00349 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00350
00351 m_bezierPoints.removeLast();
00352 m_bezierPoints.append( new KoPoint( _last ) );
00353 m_lastVectorEnd = _last;
00354
00355 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00356 }
00357 else
00358 {
00359 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00360 draw();
00361
00362 m_bezierPoints.removeLast();
00363 KoPoint* p = new KoPoint( *m_bezierPoints.last() );
00364 m_bezierPoints.removeLast();
00365 KoPoint* b = new KoPoint( *m_bezierPoints.last() );
00366 m_bezierPoints.removeLast();
00367
00368 if( shiftPressed() )
00369 {
00370 m_bezierPoints.removeLast();
00371 m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) );
00372 m_bezierPoints.append( new KoPoint( *p ) );
00373 m_bezierPoints.append( new KoPoint( *p ) );
00374 m_bezierPoints.append( new KoPoint( *p ) );
00375 m_lastVectorStart = m_lastVectorEnd = *p;
00376 }
00377 else if( ctrlPressed() )
00378 {
00379 m_bezierPoints.removeLast();
00380 m_lastVectorStart = *m_bezierPoints.last();
00381 m_bezierPoints.append( new KoPoint( _last ) );
00382 m_bezierPoints.append( new KoPoint( *b ) );
00383 m_bezierPoints.append( new KoPoint( *p ) );
00384 m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) );
00385 m_lastVectorEnd = _last;
00386 }
00387 else
00388 {
00389 m_bezierPoints.append( new KoPoint( _last ) );
00390 m_bezierPoints.append( new KoPoint( *p ) );
00391 m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) );
00392 m_lastVectorStart = *p;
00393 m_lastVectorEnd = _last;
00394 }
00395
00396 draw();
00397 drawBezierVector( m_lastVectorStart, m_lastVectorEnd );
00398 }
00399 }
00400
00401 void
00402 VPolylineTool::mouseDragRelease()
00403 {
00404 mouseButtonRelease();
00405 }
00406
00407 void
00408 VPolylineTool::mouseDragShiftPressed()
00409 {
00410 }
00411
00412 void
00413 VPolylineTool::mouseDragCtrlPressed()
00414 {
00415
00416 if( m_bezierPoints.count() > 3 )
00417 {
00418 KoPoint p;
00419 p = *m_bezierPoints.at( m_bezierPoints.count() - 4) - *m_bezierPoints.at( m_bezierPoints.count() - 3 );
00420
00421 view()->setPos( p );
00422 }
00423 }
00424
00425 void
00426 VPolylineTool::mouseDragShiftReleased()
00427 {
00428 }
00429
00430 void
00431 VPolylineTool::mouseDragCtrlReleased()
00432 {
00433 if( m_bezierPoints.count() > 3 )
00434 {
00435 KoPoint p;
00436 p = *m_bezierPoints.at( m_bezierPoints.count() - 3) - *m_bezierPoints.at( m_bezierPoints.count() - 4 );
00437
00438 view()->setPos( p );
00439 }
00440 }
00441
00442 void
00443 VPolylineTool::cancel()
00444 {
00445 draw();
00446
00447 m_bezierPoints.clear();
00448 }
00449
00450 void
00451 VPolylineTool::cancelStep()
00452 {
00453 draw();
00454
00455 if ( m_bezierPoints.count() > 6 )
00456 {
00457 m_bezierPoints.removeLast();
00458 m_bezierPoints.removeLast();
00459 m_bezierPoints.removeLast();
00460 KoPoint p1 = *m_bezierPoints.last();
00461 m_bezierPoints.removeLast();
00462 m_bezierPoints.removeLast();
00463 m_bezierPoints.append( new KoPoint( p1 ) );
00464 m_bezierPoints.append( new KoPoint( p1 ) );
00465
00466 view()->setPos( p1 );
00467 }
00468 else
00469 {
00470 m_bezierPoints.clear();
00471 }
00472
00473 draw();
00474 }
00475
00476 void
00477 VPolylineTool::accept()
00478 {
00479 activate();
00480 }
00481
00482 void
00483 VPolylineTool::setup( KActionCollection *collection )
00484 {
00485 m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00486
00487 if( m_action == 0 )
00488 {
00489 KShortcut shortcut( Qt::Key_Plus );
00490 shortcut.append( KShortcut( Qt::Key_F9 ) );
00491 m_action = new KRadioAction( i18n( "Polyline Tool" ), "14_polyline", shortcut, this, SLOT( activate() ), collection, name() );
00492 m_action->setToolTip( i18n( "Polyline" ) );
00493 m_action->setExclusiveGroup( "freehand" );
00494
00495 }
00496 }
00497
00498 void
00499 VPolylineTool::commandExecuted()
00500 {
00501 cancel();
00502 }
00503
00504 #include "vpolylinetool.moc"