/* This file is part of the KDE project Copyright (C) 2001, 2002, 2003 The Karbon Developers This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vpolylinetool.h" #include #include #include VPolylineTool::VPolylineTool( KarbonView *view ) : VTool( view, "tool_polyline" ) { m_bezierPoints.setAutoDelete( true ); registerTool( this ); m_crossCursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) ); } VPolylineTool::~VPolylineTool() { delete m_crossCursor; } QString VPolylineTool::contextHelp() { QString s = i18n( "Polyline tool:
" ); s += i18n( "- Click to add a node and drag to set its bezier vector.
" ); s += i18n( "- Press Ctrl while dragging to edit the previous bezier vector.
" ); s += i18n( "- Press Shift while dragging to change the curve in a straight line.
" ); s += i18n( "- Press Backspace to cancel the last curve.
" ); s += i18n( "- Press Esc to cancel the whole polyline.
" ); s += i18n( "- Press Enter or double click to end the polyline.
" ); return s; } void VPolylineTool::activate() { VTool::activate(); view()->statusMessage()->setText( i18n( "Polyline Tool" ) ); view()->setCursor( *m_crossCursor ); m_bezierPoints.clear(); m_close = false; connect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) ); } void VPolylineTool::initializePath( VPath &path ) { KoPoint* p1 = m_bezierPoints.first(); KoPoint* p2; KoPoint* p3; KoPoint* p4; path.moveTo( *p1 ); while( ( p2 = m_bezierPoints.next() ) && ( p3 = m_bezierPoints.next() ) && ( p4 = m_bezierPoints.next() ) ) { if ( *p1 == *p2 ) if ( *p3 == *p4 ) path.lineTo( *p4 ); else //polyline->curve1To( *p3, *p4 ); path.curveTo( *p3, *p4, *p4 ); else if ( *p3 == *p4 ) //polyline->curve2To( *p2, *p4 ); path.curveTo( *p2, *p2, *p4 ); else path.curveTo( *p2, *p3, *p4 ); p1 = p4; } } void VPolylineTool::createObject() { VPath* polyline = 0L; if( m_bezierPoints.count() > 2 ) { polyline = new VPath( 0L ); if( polyline ) { initializePath( *polyline ); if( m_close ) polyline->close(); VShapeCmd* cmd = new VShapeCmd( &view()->part()->document(), i18n( "Polyline" ), polyline, "14_polyline" ); view()->part()->addCommand( cmd, true ); } } m_bezierPoints.clear(); m_close = false; } void VPolylineTool::deactivate() { m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); createObject(); disconnect( view()->part()->commandHistory(), SIGNAL(commandExecuted()), this, SLOT(commandExecuted()) ); } void VPolylineTool::draw() { VPainter* painter = view()->painterFactory()->editpainter(); painter->setRasterOp( Qt::NotROP ); if( m_bezierPoints.count() > 2 ) { VPath polyline( 0L ); initializePath( polyline ); polyline.setState( VObject::edit ); polyline.draw( painter, &polyline.boundingBox() ); } } void VPolylineTool::drawBezierVector( KoPoint& start, KoPoint& end ) { VPainter* painter = view()->painterFactory()->editpainter(); painter->save(); float zoomFactor = view()->zoom(); painter->setRasterOp( Qt::NotROP ); painter->newPath(); /* VStroke stroke( Qt::blue, 0L, 1.0 ); QValueList array; array << 2.0 << 3.0; stroke.dashPattern().setArray( array );*/ painter->setPen( Qt::DotLine /*stroke*/ ); painter->setBrush( Qt::NoBrush ); painter->moveTo( start ); painter->lineTo( end ); painter->strokePath(); painter->setRasterOp( Qt::XorROP ); painter->newPath(); painter->setPen( Qt::yellow ); float width = 2.0; painter->moveTo( KoPoint( end.x() - width / zoomFactor, end.y() - width / zoomFactor ) ); painter->lineTo( KoPoint( end.x() + width / zoomFactor, end.y() - width / zoomFactor ) ); painter->lineTo( KoPoint( end.x() + width / zoomFactor, end.y() + width / zoomFactor ) ); painter->lineTo( KoPoint( end.x() - width / zoomFactor, end.y() + width / zoomFactor ) ); painter->lineTo( KoPoint( end.x() - width / zoomFactor, end.y() - width / zoomFactor ) ); painter->strokePath(); painter->restore(); } void VPolylineTool::mouseMove() { if( m_bezierPoints.count() != 0 ) { KoPoint _last = view()->canvasWidget()->snapToGrid( last() ); draw(); m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( _last ) ); draw(); } } void VPolylineTool::mouseButtonPress() { KoPoint _last = view()->canvasWidget()->snapToGrid( last() ); if( m_bezierPoints.count() != 0 ) { draw(); m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( _last ) ); } m_lastVectorEnd = m_lastVectorStart = _last; m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( _last ) ); drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); draw(); } void VPolylineTool::mouseButtonRelease() { KoPoint _last = view()->canvasWidget()->snapToGrid( last() ); if( m_bezierPoints.count() == 2 ) { drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( _last ) ); VPainter* painter = view()->painterFactory()->editpainter(); painter->save(); painter->setZoomFactor( view()->zoom() ); painter->setRasterOp( Qt::XorROP ); VStroke stroke( Qt::yellow, 0L, 1.0 ); painter->setPen( stroke ); painter->setBrush( Qt::yellow ); painter->newPath(); painter->drawNode( m_lastVectorStart, 2 ); painter->strokePath(); painter->restore(); } else { drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); draw(); m_bezierPoints.removeLast(); KoPoint* p = new KoPoint( *m_bezierPoints.last() ); m_bezierPoints.removeLast(); KoPoint* b = new KoPoint( *m_bezierPoints.last() ); m_bezierPoints.removeLast(); if( shiftPressed() ) { m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_lastVectorStart = m_lastVectorEnd = *p; } else if( ctrlPressed() ) { m_bezierPoints.removeLast(); m_lastVectorStart = *m_bezierPoints.last(); m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( *b ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) ); m_lastVectorEnd = _last; } else { m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) ); m_lastVectorStart = *p; m_lastVectorEnd = _last; } if( m_bezierPoints.count() > 2 && p->isNear( *m_bezierPoints.first(), 3 ) ) { m_bezierPoints.append( new KoPoint( _last ) ); m_close = true; createObject(); return; } } m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( _last ) ); draw(); } void VPolylineTool::rightMouseButtonRelease() { // end line without adding new points m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); createObject(); } void VPolylineTool::mouseButtonDblClick() { createObject(); } void VPolylineTool::mouseDrag() { KoPoint _last = view()->canvasWidget()->snapToGrid( last() ); if( m_bezierPoints.count() == 2 ) { drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( _last ) ); m_lastVectorEnd = _last; drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); } else { drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); draw(); m_bezierPoints.removeLast(); KoPoint* p = new KoPoint( *m_bezierPoints.last() ); m_bezierPoints.removeLast(); KoPoint* b = new KoPoint( *m_bezierPoints.last() ); m_bezierPoints.removeLast(); if( shiftPressed() ) { m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( *m_bezierPoints.last() ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_lastVectorStart = m_lastVectorEnd = *p; } else if( ctrlPressed() ) { m_bezierPoints.removeLast(); m_lastVectorStart = *m_bezierPoints.last(); m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( *b ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p - ( *b - *p ) ) ); m_lastVectorEnd = _last; } else { m_bezierPoints.append( new KoPoint( _last ) ); m_bezierPoints.append( new KoPoint( *p ) ); m_bezierPoints.append( new KoPoint( *p - ( _last - *p ) ) ); m_lastVectorStart = *p; m_lastVectorEnd = _last; } draw(); drawBezierVector( m_lastVectorStart, m_lastVectorEnd ); } } void VPolylineTool::mouseDragRelease() { mouseButtonRelease(); } void VPolylineTool::mouseDragShiftPressed() { } void VPolylineTool::mouseDragCtrlPressed() { // Moves the mouse to the other bezier vector position. if( m_bezierPoints.count() > 3 ) { KoPoint p; p = *m_bezierPoints.at( m_bezierPoints.count() - 4) - *m_bezierPoints.at( m_bezierPoints.count() - 3 ); view()->setPos( p ); } } void VPolylineTool::mouseDragShiftReleased() { } void VPolylineTool::mouseDragCtrlReleased() { if( m_bezierPoints.count() > 3 ) { KoPoint p; p = *m_bezierPoints.at( m_bezierPoints.count() - 3) - *m_bezierPoints.at( m_bezierPoints.count() - 4 ); view()->setPos( p ); } } void VPolylineTool::cancel() { draw(); m_bezierPoints.clear(); } void VPolylineTool::cancelStep() { draw(); if ( m_bezierPoints.count() > 6 ) { m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); KoPoint p1 = *m_bezierPoints.last(); m_bezierPoints.removeLast(); m_bezierPoints.removeLast(); m_bezierPoints.append( new KoPoint( p1 ) ); m_bezierPoints.append( new KoPoint( p1 ) ); view()->setPos( p1 ); } else { m_bezierPoints.clear(); } draw(); } void VPolylineTool::accept() { activate(); } void VPolylineTool::setup( KActionCollection *collection ) { m_action = static_cast(collection -> action( name() ) ); if( m_action == 0 ) { KShortcut shortcut( Qt::Key_Plus ); shortcut.append( KShortcut( Qt::Key_F9 ) ); m_action = new KRadioAction( i18n( "Polyline Tool" ), "14_polyline", shortcut, this, SLOT( activate() ), collection, name() ); m_action->setToolTip( i18n( "Polyline" ) ); m_action->setExclusiveGroup( "freehand" ); //m_ownAction = true; } } void VPolylineTool::commandExecuted() { cancel(); } #include "vpolylinetool.moc"