karbon

vpolylinetool.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, 2002, 2003 The Karbon Developers
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
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                     //polyline->curve1To( *p3, *p4 );
00109                     polyline->curveTo( *p3, *p4, *p4 );
00110             else
00111                 if ( *p3 == *p4 )
00112                     //polyline->curve2To( *p2, *p4 );
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 /*  VStroke stroke( Qt::blue, 0L, 1.0 );
00179     QValueList<float> array;
00180     array << 2.0 << 3.0;
00181     stroke.dashPattern().setArray( array );*/
00182     painter->setPen( Qt::DotLine /*stroke*/ );
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     // end line without adding new points
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     // Moves the mouse to the other bezier vector position.
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         //m_ownAction = true;
00492     }
00493 }
00494 
00495 void 
00496 VPolylineTool::commandExecuted()
00497 {
00498     cancel();
00499 }
00500 
00501 #include "vpolylinetool.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys