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::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                 //polyline->curve1To( *p3, *p4 );
00102                 path.curveTo( *p3, *p4, *p4 );
00103         else
00104             if ( *p3 == *p4 )
00105                 //polyline->curve2To( *p2, *p4 );
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 /*  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             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     // end line without adding new points
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     // Moves the mouse to the other bezier vector position.
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         //m_ownAction = true;
00495     }
00496 }
00497 
00498 void 
00499 VPolylineTool::commandExecuted()
00500 {
00501     cancel();
00502 }
00503 
00504 #include "vpolylinetool.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys