Commit 1c78b233 authored by Thorsten Zachmann's avatar Thorsten Zachmann

o Added a repaint method to KoPathPointSelection

o Split KoPointMoveCommand in KoPointMoveCommand for moving points and
  KoControlPointMoveCommand for changing a control point
o Implement support for moving points of different KoPathShapes at the
  same time
o Fix repainting of objects  


svn path=/trunk/koffice/; revision=595615
parent 59976832
......@@ -41,92 +41,113 @@ void KoPathBaseCommand::repaint( const QRectF &oldControlPointRect )
m_shape->repaint( repaintRect );
}
KoPointMoveCommand::KoPointMoveCommand( KoPathShape *shape, KoPathPoint *point, const QPointF &offset, KoPathPoint::KoPointType pointType )
: KoPathBaseCommand( shape )
, m_offset( offset )
, m_pointType( pointType )
{
m_points << point;
}
KoPointMoveCommand::KoPointMoveCommand( KoPathShape *shape, const QList<KoPathPoint*> &points, const QPointF &offset )
: KoPathBaseCommand( shape )
, m_points( points )
KoPointMoveCommand::KoPointMoveCommand( const KoPathShapePointMap &pointMap, const QPointF &offset )
: m_pointMap( pointMap )
, m_offset( offset )
, m_pointType( KoPathPoint::Node )
{
}
void KoPointMoveCommand::execute()
{
QRectF oldControlRect = m_shape->outline().controlPointRect();
if( m_pointType == KoPathPoint::Node )
KoPathShapePointMap::iterator it( m_pointMap.begin() );
for ( ; it != m_pointMap.end(); ++it )
{
QPointF offset = it.key()->documentToShape( m_offset ) - it.key()->documentToShape( QPointF( 0, 0 ) );
QMatrix matrix;
matrix.translate( m_offset.x(), m_offset.y() );
matrix.translate( offset.x(), offset.y() );
foreach( KoPathPoint *p, m_points )
// repaint old bounding rect
it.key()->repaint();
foreach( KoPathPoint *p, it.value() )
{
p->map( matrix, true );
p->map( matrix, true );
}
it.key()->normalize();
// repaint new bounding rect
it.key()->repaint();
}
else if( m_pointType == KoPathPoint::ControlPoint1 )
}
void KoPointMoveCommand::unexecute()
{
m_offset *= -1.0;
execute();
m_offset *= -1.0;
}
QString KoPointMoveCommand::name() const
{
return i18n( "Move points" );
}
KoControlPointMoveCommand::KoControlPointMoveCommand( KoPathPoint *point, const QPointF &offset, KoPathPoint::KoPointType pointType )
: m_point( point )
, m_offset( point->parent()->documentToShape( offset ) - point->parent()->documentToShape( QPointF( 0, 0 ) ) )
, m_pointType( pointType )
{
}
void KoControlPointMoveCommand::execute()
{
KoPathShape * pathShape = m_point->parent();
pathShape->repaint();
if ( m_pointType == KoPathPoint::ControlPoint1 )
{
KoPathPoint *p = m_points.first();
p->setControlPoint1( p->controlPoint1() + m_offset );
if( p->properties() & KoPathPoint::IsSymmetric )
m_point->setControlPoint1( m_point->controlPoint1() + m_offset );
if( m_point->properties() & KoPathPoint::IsSymmetric )
{
// set the other control point so that it lies on the line between the moved
// control point and the point, with the same distance to the point as the moved point
p->setControlPoint2( 2.0 * p->point() - p->controlPoint1() );
m_point->setControlPoint2( 2.0 * m_point->point() - m_point->controlPoint1() );
}
else if( p->properties() & KoPathPoint::IsSmooth )
else if( m_point->properties() & KoPathPoint::IsSmooth )
{
// move the other control point so that it lies on the line through point and control point
// keeping its distance to the point
QPointF direction = p->point() - p->controlPoint1();
QPointF direction = m_point->point() - m_point->controlPoint1();
direction /= sqrt( direction.x()*direction.x() + direction.y()*direction.y() );
QPointF distance = p->point() - p->controlPoint2();
QPointF distance = m_point->point() - m_point->controlPoint2();
qreal length = sqrt( distance.x()*distance.x() + distance.y()*distance.y() );
p->setControlPoint2( p->point() + length * direction );
m_point->setControlPoint2( m_point->point() + length * direction );
}
}
else if( m_pointType == KoPathPoint::ControlPoint2 )
{
KoPathPoint *p = m_points.first();
p->setControlPoint2( p->controlPoint2() + m_offset );
if( p->properties() & KoPathPoint::IsSymmetric )
m_point->setControlPoint2( m_point->controlPoint2() + m_offset );
if( m_point->properties() & KoPathPoint::IsSymmetric )
{
// set the other control point so that it lies on the line between the moved
// control point and the point, with the same distance to the point as the moved point
p->setControlPoint1( 2.0 * p->point() - p->controlPoint2() );
m_point->setControlPoint1( 2.0 * m_point->point() - m_point->controlPoint2() );
}
else if( p->properties() & KoPathPoint::IsSmooth )
else if( m_point->properties() & KoPathPoint::IsSmooth )
{
// move the other control point so that it lies on the line through point and control point
// keeping its distance to the point
QPointF direction = p->point() - p->controlPoint2();
QPointF direction = m_point->point() - m_point->controlPoint2();
direction /= sqrt( direction.x()*direction.x() + direction.y()*direction.y() );
QPointF distance = p->point() - p->controlPoint1();
QPointF distance = m_point->point() - m_point->controlPoint1();
qreal length = sqrt( distance.x()*distance.x() + distance.y()*distance.y() );
p->setControlPoint1( p->point() + length * direction );
m_point->setControlPoint1( m_point->point() + length * direction );
}
}
repaint( oldControlRect );
pathShape->normalize();
pathShape->repaint();
}
void KoPointMoveCommand::unexecute()
void KoControlPointMoveCommand::unexecute()
{
m_offset *= -1.0;
execute();
m_offset *= -1.0;
}
QString KoPointMoveCommand::name() const
QString KoControlPointMoveCommand::name() const
{
return i18n( "Move points" );
return i18n( "Move control point" );
}
KoPointPropertyCommand::KoPointPropertyCommand( KoPathShape *shape, KoPathPoint *point, KoPathPoint::KoPointProperties property )
......
......@@ -24,7 +24,7 @@
#include <QList>
#include <QMap>
#include <QPointF>
#include <KoPathShape.h>
#include "KoPathShape.h"
/// the base command for commands altering a path shape
class KoPathBaseCommand : public KCommand {
......@@ -41,23 +41,38 @@ protected:
};
/// The undo / redo command for path point moving.
class KoPointMoveCommand : public KoPathBaseCommand {
class KoPointMoveCommand : public KCommand
{
public:
/**
* Command to move single path point.
* @param shape the path shape containing the point
* @param point the path point to move
* @param offset the offset by which the point is moved
* @param pointType the type of the point to move
* Command to move path point.
* @param pointMap map of the path point to move
* @param offset the offset by which the point is moved in document coordinates
*/
KoPointMoveCommand( KoPathShape *shape, KoPathPoint *point, const QPointF &offset, KoPathPoint::KoPointType pointType );
KoPointMoveCommand( const KoPathShapePointMap &pointMap, const QPointF &offset );
/// execute the command
void execute();
/// revert the actions done in execute
void unexecute();
/// return the name of this command
QString name() const;
private:
KoPathShapePointMap m_pointMap;
QPointF m_offset;
};
/// The undo / redo command for path point moving.
class KoControlPointMoveCommand : public KCommand
{
public:
/**
* Command to move multiple points at once.
* @param shape the path shape containing the points
* @param points the path points to move
* @param offset the offset by which the points are moved
* Command to move one control path point.
* @param point the path point to control point belongs to
* @param offset the offset by which the point is moved in document coordinates
* @param pointType the type of the point to move
*/
KoPointMoveCommand( KoPathShape *shape, const QList<KoPathPoint*> &points, const QPointF &offset );
KoControlPointMoveCommand( KoPathPoint *point, const QPointF &offset, KoPathPoint::KoPointType pointType );
/// execute the command
void execute();
/// revert the actions done in execute
......@@ -65,7 +80,8 @@ public:
/// return the name of this command
QString name() const;
private:
QList<KoPathPoint*> m_points;
KoPathPoint * m_point;
// the offset in shape coordinates
QPointF m_offset;
KoPathPoint::KoPointType m_pointType;
};
......@@ -308,4 +324,5 @@ private:
QList<KoPathShape*> m_separatedPaths;
bool m_isSeparated;
};
#endif
......@@ -37,31 +37,24 @@ KoPathPointMoveStrategy::~KoPathPointMoveStrategy()
void KoPathPointMoveStrategy::handleMouseMove( const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers )
{
// TODO remove this constrained
if ( m_tool->m_pointSelection.objectCount() == 1 )
{
QList<KoPathPoint*> selectedPoints = m_tool->m_pointSelection.selectedPoints().toList();
KoPathShape * pathShape = selectedPoints[0]->parent();
QPointF docPoint = m_tool->snapToGrid( mouseLocation, modifiers );
QPointF move = pathShape->documentToShape( docPoint ) - pathShape->documentToShape( m_lastPosition );
// as the last position can change when the top left is changed we have
// to save it in document pos and not in shape pos
m_lastPosition = docPoint;
QPointF docPoint = m_tool->snapToGrid( mouseLocation, modifiers );
QPointF move = docPoint - m_lastPosition;
// as the last position can change when the top left is changed we have
// to save it in document pos and not in shape pos
m_lastPosition = docPoint;
m_move += move;
m_move += move;
// only multiple nodes can be moved at once
if( m_tool->m_activeHandle.m_activePointType == KoPathPoint::Node )
{
KoPointMoveCommand cmd( pathShape, selectedPoints, move );
cmd.execute();
}
else
{
KoPointMoveCommand cmd( pathShape, m_tool->m_activeHandle.m_activePoint, move, m_tool->m_activeHandle.m_activePointType );
cmd.execute();
}
// only multiple nodes can be moved at once
if( m_tool->m_activeHandle.m_activePointType == KoPathPoint::Node )
{
KoPointMoveCommand cmd( m_tool->m_pointSelection.selectedPointMap(), move );
cmd.execute();
}
else
{
KoControlPointMoveCommand cmd( m_tool->m_activeHandle.m_activePoint, move, m_tool->m_activeHandle.m_activePointType );
cmd.execute();
}
}
......@@ -72,21 +65,17 @@ void KoPathPointMoveStrategy::finishInteraction( Qt::KeyboardModifiers modifiers
KCommand* KoPathPointMoveStrategy::createCommand()
{
if ( m_tool->m_pointSelection.objectCount() == 1 )
{
QList<KoPathPoint*> selectedPoints = m_tool->m_pointSelection.selectedPoints().toList();
KoPathShape * pathShape = selectedPoints[0]->parent();
QList<KoPathPoint*> selectedPoints = m_tool->m_pointSelection.selectedPoints().toList();
KoPathShape * pathShape = selectedPoints[0]->parent();
KoPointMoveCommand *cmd = 0;
if( !m_move.isNull() )
{
// only multiple nodes can be moved at once
if( m_tool->m_activeHandle.m_activePointType == KoPathPoint::Node )
cmd = new KoPointMoveCommand( pathShape, selectedPoints, m_move );
else
cmd = new KoPointMoveCommand( pathShape, m_tool->m_activeHandle.m_activePoint, m_move, m_tool->m_activeHandle.m_activePointType );
}
return cmd;
KCommand *cmd = 0;
if( !m_move.isNull() )
{
// only multiple nodes can be moved at once
if( m_tool->m_activeHandle.m_activePointType == KoPathPoint::Node )
cmd = new KoPointMoveCommand( m_tool->m_pointSelection.selectedPointMap(), m_move );
else
cmd = new KoControlPointMoveCommand( m_tool->m_activeHandle.m_activePoint, m_move, m_tool->m_activeHandle.m_activePointType );
}
return 0;
return cmd;
}
......@@ -25,7 +25,6 @@
#include <KoInteractionStrategy.h>
class KoCommand;
class KoPathTool;
class KoCanvasBase;
......
......@@ -33,6 +33,9 @@
class KoPathShape;
class KoPointGroup;
class KoPathPoint;
typedef QMap<KoPathShape *, QSet<KoPathPoint *> > KoPathShapePointMap;
/**
* @brief A KoPathPoint represents a point in a path.
......
......@@ -113,11 +113,7 @@ void KoPathTool::mousePressEvent( KoPointerEvent *event ) {
m_pointSelection.add( m_activeHandle.m_activePoint, true );
}
}
// TODO remove this constrained
if ( m_pointSelection.objectCount() == 1 )
{
m_currentStrategy = new KoPathPointMoveStrategy( this, m_canvas, event->point );
}
m_currentStrategy = new KoPathPointMoveStrategy( this, m_canvas, event->point );
}
else if( event->button() & Qt::RightButton )
{
......@@ -162,6 +158,12 @@ void KoPathTool::mouseMoveEvent( KoPointerEvent *event ) {
if( event->button() & Qt::RightButton )
return;
m_pointSelection.repaint();
if ( m_activeHandle.isActive() )
{
repaint( m_activeHandle.m_activePoint->boundingRect() );
}
if ( m_currentStrategy )
{
m_lastPoint = event->point;
......@@ -203,7 +205,6 @@ void KoPathTool::mouseMoveEvent( KoPointerEvent *event ) {
useCursor(Qt::ArrowCursor);
if ( m_activeHandle.isActive() )
{
repaint( m_activeHandle.m_activePoint->parent()->shapeToDocument( m_activeHandle.m_activePoint->parent()->outline().controlPointRect() ) );
m_activeHandle.deactivate();
}
}
......@@ -436,7 +437,7 @@ void KoPathTool::ActiveHandle::paint( QPainter &painter, KoViewConverter &conver
void KoPathTool::KoPathPointSelection::paint( QPainter &painter, KoViewConverter &converter )
{
KoSelectedPointMap::iterator it( m_shapePointMap.begin() );
KoPathShapePointMap::iterator it( m_shapePointMap.begin() );
for ( ; it != m_shapePointMap.end(); ++it )
{
painter.save();
......@@ -481,7 +482,7 @@ void KoPathTool::KoPathPointSelection::add( KoPathPoint * point, bool clear )
{
m_selectedPoints.insert( point );
KoPathShape * pathShape = point->parent();
KoSelectedPointMap::iterator it( m_shapePointMap.find( pathShape ) );
KoPathShapePointMap::iterator it( m_shapePointMap.find( pathShape ) );
if ( it == m_shapePointMap.end() )
{
it = m_shapePointMap.insert( pathShape, QSet<KoPathPoint *>() );
......@@ -506,11 +507,16 @@ void KoPathTool::KoPathPointSelection::remove( KoPathPoint * point )
}
void KoPathTool::KoPathPointSelection::clear()
{
repaint();
m_selectedPoints.clear();
m_shapePointMap.clear();
}
void KoPathTool::KoPathPointSelection::repaint()
{
foreach ( KoPathPoint *p, m_selectedPoints )
{
m_tool->repaint( p->boundingRect() );
}
m_selectedPoints.clear();
m_shapePointMap.clear();
}
......@@ -92,7 +92,6 @@ private:
class KoPathPointSelection
{
public:
typedef QMap<KoPathShape *, QSet<KoPathPoint *> > KoSelectedPointMap;
KoPathPointSelection( KoPathTool * tool )
: m_tool( tool )
{}
......@@ -155,11 +154,16 @@ private:
* @return KoSelectedPointMap containing all objects and selected points
* typedef QMap<KoPathShape *, QSet<KoPathPoint *> > KoSelectedPointMap;
*/
const KoSelectedPointMap & selectedPointMap() const { return m_shapePointMap; }
const KoPathShapePointMap & selectedPointMap() const { return m_shapePointMap; }
/**
* @brief trigger a repaint
*/
void repaint();
private:
QSet<KoPathPoint *> m_selectedPoints;
KoSelectedPointMap m_shapePointMap;
KoPathShapePointMap m_shapePointMap;
KoPathTool * m_tool;
};
......
......@@ -225,7 +225,7 @@ void KoShape::repaint() const {
{
foreach( KoShapeManager * manager, m_shapeManagers )
{
QRectF rect(QPointF(0, 0), m_size);
QRectF rect(QPointF(0, 0), size() );
if(m_border) {
KoInsets insets(0, 0, 0, 0);
m_border->borderInsets(this, insets);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment