|
|
|
/* 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 <tqcursor.h>
|
|
|
|
#include <tqevent.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include <karbon_part.h>
|
|
|
|
#include <karbon_view.h>
|
|
|
|
#include <core/vcolor.h>
|
|
|
|
#include <core/vcomposite.h>
|
|
|
|
#include <core/vfill.h>
|
|
|
|
#include <core/vstroke.h>
|
|
|
|
#include <core/vglobal.h>
|
|
|
|
#include <core/vcursor.h>
|
|
|
|
#include <render/vpainter.h>
|
|
|
|
#include <render/vpainterfactory.h>
|
|
|
|
#include "vpolylinetool.h"
|
|
|
|
#include <commands/vshapecmd.h>
|
|
|
|
#include <commands/vcommand.h>
|
|
|
|
#include <widgets/vcanvas.h>
|
|
|
|
|
|
|
|
VPolylineTool::VPolylineTool( KarbonView *view )
|
|
|
|
: VTool( view, "tool_polyline" )
|
|
|
|
{
|
|
|
|
m_bezierPoints.setAutoDelete( true );
|
|
|
|
registerTool( this );
|
|
|
|
m_crossCursor = new TQCursor( VCursor::createCursor( VCursor::CrossHair ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
VPolylineTool::~VPolylineTool()
|
|
|
|
{
|
|
|
|
delete m_crossCursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString
|
|
|
|
VPolylineTool::contextHelp()
|
|
|
|
{
|
|
|
|
TQString s = i18n( "<qt><b>Polyline tool:</b><br>" );
|
|
|
|
s += i18n( "- <i>Click</i> to add a node and <i>drag</i> to set its bezier vector.<br>" );
|
|
|
|
s += i18n( "- Press <i>Ctrl</i> while dragging to edit the previous bezier vector.<br>" );
|
|
|
|
s += i18n( "- Press <i>Shift</i> while dragging to change the curve in a straight line.<br>" );
|
|
|
|
s += i18n( "- Press <i>Backspace</i> to cancel the last curve.<br>" );
|
|
|
|
s += i18n( "- Press <i>Esc</i> to cancel the whole polyline.<br>" );
|
|
|
|
s += i18n( "- Press <i>Enter</i> or <i>double click</i> to end the polyline.</qt>" );
|
|
|
|
|
|
|
|
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(), TQT_SIGNAL(commandExecuted()), this, TQT_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(), TQT_SIGNAL(commandExecuted()), this, TQT_SLOT(commandExecuted()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VPolylineTool::draw()
|
|
|
|
{
|
|
|
|
VPainter* painter = view()->painterFactory()->editpainter();
|
|
|
|
painter->setRasterOp( TQt::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( TQt::NotROP );
|
|
|
|
painter->newPath();
|
|
|
|
/* VStroke stroke( TQt::blue, 0L, 1.0 );
|
|
|
|
TQValueList<float> array;
|
|
|
|
array << 2.0 << 3.0;
|
|
|
|
stroke.dashPattern().setArray( array );*/
|
|
|
|
painter->setPen( TQt::DotLine /*stroke*/ );
|
|
|
|
painter->setBrush( TQt::NoBrush );
|
|
|
|
|
|
|
|
painter->moveTo( start );
|
|
|
|
painter->lineTo( end );
|
|
|
|
painter->strokePath();
|
|
|
|
painter->setRasterOp( TQt::XorROP );
|
|
|
|
painter->newPath();
|
|
|
|
painter->setPen( TQt::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( TQt::XorROP );
|
|
|
|
VStroke stroke( TQt::yellow, 0L, 1.0 );
|
|
|
|
painter->setPen( stroke );
|
|
|
|
painter->setBrush( TQt::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<KRadioAction *>(collection -> action( name() ) );
|
|
|
|
|
|
|
|
if( m_action == 0 )
|
|
|
|
{
|
|
|
|
KShortcut shortcut( TQt::Key_Plus );
|
|
|
|
shortcut.append( KShortcut( TQt::Key_F9 ) );
|
|
|
|
m_action = new KRadioAction( i18n( "Polyline Tool" ), "14_polyline", shortcut, this, TQT_SLOT( activate() ), collection, name() );
|
|
|
|
m_action->setToolTip( i18n( "Polyline" ) );
|
|
|
|
m_action->setExclusiveGroup( "freehand" );
|
|
|
|
//m_ownAction = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
VPolylineTool::commandExecuted()
|
|
|
|
{
|
|
|
|
cancel();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "vpolylinetool.moc"
|