[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: koffice/libs/flake/tools
From: Jan Hambrecht <jaham () gmx ! net>
Date: 2008-01-31 22:25:35
Message-ID: 1201818335.362719.28858.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 769235 by jaham:
implemnented a new snaping guide which snaps to the
direction of the line/path at its end points
M +5 -3 KoCreatePathTool.cpp
M +14 -13 SnapGuide.cpp
M +4 -9 SnapGuide.h
M +10 -4 SnapGuideConfigWidget.cpp
M +11 -4 SnapGuideConfigWidget.ui
M +143 -6 SnapStrategy.cpp
M +23 -3 SnapStrategy.h
--- trunk/koffice/libs/flake/tools/KoCreatePathTool.cpp #769234:769235
@@ -21,6 +21,7 @@
#include "KoCreatePathTool.h"
#include "SnapGuide.h"
+#include "SnapStrategy.h"
#include "SnapGuideConfigWidget.h"
#include "KoPathShape.h"
@@ -48,7 +49,8 @@
, m_mouseOverFirstPoint(false)
, m_snapGuide( new SnapGuide(canvas) )
{
- m_snapGuide->enableSnapStrategies( SnapGuide::Orthogonal|SnapGuide::Node );
+ m_snapGuide->enableSnapStrategies( SnapStrategy::Orthogonal|SnapStrategy::Node|SnapStrategy::Extension );
+ //m_snapGuide->enableSnapStrategies( SnapStrategy::Node|SnapStrategy::Extension );
}
KoCreatePathTool::~KoCreatePathTool()
@@ -147,7 +149,7 @@
m_canvas->updateCanvas( m_shape->boundingRect() );
m_canvas->updateCanvas( m_snapGuide->boundingRect() );
- m_snapGuide->setExtraShape( m_shape );
+ m_snapGuide->setEditedShape( m_shape );
}
}
@@ -256,7 +258,7 @@
{
m_shape->normalize();
- m_snapGuide->setExtraShape(0);
+ m_snapGuide->setEditedShape(0);
// this is done so that nothing happens when the mouseReleaseEvent for the this event is received
KoPathShape *pathShape = m_shape;
--- trunk/koffice/libs/flake/tools/SnapGuide.cpp #769234:769235
@@ -32,25 +32,26 @@
SnapGuide::SnapGuide( KoCanvasBase * canvas )
- : m_canvas(canvas), m_extraShape(0), m_currentStrategy(0)
+ : m_canvas(canvas), m_editedShape(0), m_currentStrategy(0)
, m_active(true), m_snapDistance(10)
{
m_strategies.append( new NodeSnapStrategy() );
m_strategies.append( new OrthogonalSnapStrategy() );
+ m_strategies.append( new ExtensionSnapStrategy() );
}
SnapGuide::~SnapGuide()
{
}
-void SnapGuide::setExtraShape( KoShape * shape )
+void SnapGuide::setEditedShape( KoShape * shape )
{
- m_extraShape = shape;
+ m_editedShape = shape;
}
-KoShape * SnapGuide::extraShape() const
+KoShape * SnapGuide::editedShape() const
{
- return m_extraShape;
+ return m_editedShape;
}
void SnapGuide::enableSnapStrategies( int strategies )
@@ -130,7 +131,7 @@
void SnapGuide::paint( QPainter &painter, const KoViewConverter &converter )
{
- if( ! m_currentStrategy )
+ if( ! m_currentStrategy || ! m_active )
return;
QPen pen( Qt::red );
@@ -174,11 +175,11 @@
{
QList<KoShape*> shapes = m_snapGuide->canvas()->shapeManager()->shapesAt( rect );
- if( m_snapGuide->extraShape() )
+ if( m_snapGuide->editedShape() )
{
- QRectF bound = m_snapGuide->extraShape()->boundingRect();
+ QRectF bound = m_snapGuide->editedShape()->boundingRect();
if( rect.intersects( bound ) || rect.contains( bound ) )
- shapes.append( m_snapGuide->extraShape() );
+ shapes.append( m_snapGuide->editedShape() );
}
return shapes;
}
@@ -207,16 +208,16 @@
}
}
- if( shape == m_snapGuide->extraShape() )
+ if( shape == m_snapGuide->editedShape() )
pathPoints.removeLast();
return pathPoints;
}
-QList<KoShape*> SnapProxy::shapes()
+QList<KoShape*> SnapProxy::shapes( bool omitEditedShape )
{
QList<KoShape*> shapes = m_snapGuide->canvas()->shapeManager()->shapes();
- if( m_snapGuide->extraShape() )
- shapes.append( m_snapGuide->extraShape() );
+ if( ! omitEditedShape && m_snapGuide->editedShape() )
+ shapes.append( m_snapGuide->editedShape() );
return shapes;
}
--- trunk/koffice/libs/flake/tools/SnapGuide.h #769234:769235
@@ -36,11 +36,6 @@
class SnapGuide
{
public:
- /// the different possible snap types
- enum SnapType {
- Orthogonal = 1,
- Node = 2
- };
/// Creates the snap guide to work on the given canvas
SnapGuide( KoCanvasBase * canvas );
@@ -57,10 +52,10 @@
QRectF boundingRect();
/// Adds an additional shape to snap to (useful when creating a path)
- void setExtraShape( KoShape * shape );
+ void setEditedShape( KoShape * shape );
/// returns the extra shapes to use
- KoShape * extraShape() const;
+ KoShape * editedShape() const;
/// enables the strategies used for snapping
void enableSnapStrategies( int strategies );
@@ -85,7 +80,7 @@
private:
KoCanvasBase * m_canvas;
- KoShape * m_extraShape;
+ KoShape * m_editedShape;
QList<SnapStrategy*> m_strategies;
SnapStrategy * m_currentStrategy;
@@ -110,7 +105,7 @@
QList<QPointF> pointsFromShape( KoShape * shape );
/// returns list of all shapes
- QList<KoShape*> shapes();
+ QList<KoShape*> shapes( bool omitEditedShape = false );
private:
SnapGuide * m_snapGuide;
--- trunk/koffice/libs/flake/tools/SnapGuideConfigWidget.cpp #769234:769235
@@ -19,22 +19,26 @@
#include "SnapGuideConfigWidget.h"
#include "SnapGuide.h"
+#include "SnapStrategy.h"
SnapGuideConfigWidget::SnapGuideConfigWidget( SnapGuide * snapGuide, QWidget * parent )
:QWidget(parent), m_snapGuide(snapGuide)
{
widget.setupUi(this);
- if( snapGuide->enabledSnapStrategies() & SnapGuide::Orthogonal )
+ if( snapGuide->enabledSnapStrategies() & SnapStrategy::Orthogonal )
widget.orthogonalSnapGuide->setCheckState( Qt::Checked );
- if( snapGuide->enabledSnapStrategies() & SnapGuide::Node )
+ if( snapGuide->enabledSnapStrategies() & SnapStrategy::Node )
widget.nodeSnapGuide->setCheckState( Qt::Checked );
+ if( snapGuide->enabledSnapStrategies() & SnapStrategy::Extension )
+ widget.extensionSnapGuide->setCheckState( Qt::Checked );
widget.snapDistance->setValue( m_snapGuide->snapDistance() );
connect( widget.useSnapGuides, SIGNAL(stateChanged(int)), this, SLOT(snappingEnabled(int)));
connect( widget.orthogonalSnapGuide, SIGNAL(stateChanged(int)), this, SLOT(strategyChanged()));
connect( widget.nodeSnapGuide, SIGNAL(stateChanged(int)), this, SLOT(strategyChanged()));
+ connect( widget.extensionSnapGuide, SIGNAL(stateChanged(int)), this, SLOT(strategyChanged()));
connect( widget.snapDistance, SIGNAL(valueChanged(int)), this, SLOT(distanceChanged(int)));
widget.useSnapGuides->setCheckState( snapGuide->isSnapping() ? Qt::Checked : Qt::Unchecked );
@@ -54,9 +58,11 @@
{
int strategies = 0;
if( widget.orthogonalSnapGuide->checkState() == Qt::Checked )
- strategies |= SnapGuide::Orthogonal;
+ strategies |= SnapStrategy::Orthogonal;
if( widget.nodeSnapGuide->checkState() == Qt::Checked )
- strategies |= SnapGuide::Node;
+ strategies |= SnapStrategy::Node;
+ if( widget.extensionSnapGuide->checkState() == Qt::Checked )
+ strategies |= SnapStrategy::Extension;
m_snapGuide->enableSnapStrategies( strategies );
}
--- trunk/koffice/libs/flake/tools/SnapGuideConfigWidget.ui #769234:769235
@@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>255</width>
- <height>187</height>
+ <height>229</height>
</rect>
</property>
<property name="windowTitle" >
@@ -38,16 +38,23 @@
</widget>
</item>
<item row="2" column="0" colspan="2" >
+ <widget class="QCheckBox" name="extensionSnapGuide" >
+ <property name="text" >
+ <string>Enable Extension Guide</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>Snap Distance (px)</string>
</property>
</widget>
</item>
- <item row="3" column="0" >
+ <item row="4" column="0" >
<widget class="QSpinBox" name="snapDistance" />
</item>
- <item row="3" column="1" >
+ <item row="4" column="1" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
@@ -60,7 +67,7 @@
</property>
</spacer>
</item>
- <item row="4" column="0" >
+ <item row="5" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
--- trunk/koffice/libs/flake/tools/SnapStrategy.cpp #769234:769235
@@ -18,11 +18,13 @@
*/
#include "SnapStrategy.h"
+#include <KoPathShape.h>
+#include <KoPathPoint.h>
#include <math.h>
-SnapStrategy::SnapStrategy( SnapGuide::SnapType type )
+SnapStrategy::SnapStrategy( SnapStrategy::SnapType type )
: m_snapType(type)
{
}
@@ -47,7 +49,7 @@
m_snappedPosition= position;
}
-SnapGuide::SnapType SnapStrategy::type() const
+SnapStrategy::SnapType SnapStrategy::type() const
{
return m_snapType;
}
@@ -60,7 +62,7 @@
}
OrthogonalSnapStrategy::OrthogonalSnapStrategy()
- : SnapStrategy( SnapGuide::Orthogonal )
+ : SnapStrategy( SnapStrategy::Orthogonal )
{
}
@@ -119,7 +121,7 @@
}
NodeSnapStrategy::NodeSnapStrategy()
- : SnapStrategy( SnapGuide::Node )
+ : SnapStrategy( SnapStrategy::Node )
{
}
@@ -136,8 +138,7 @@
foreach( QPointF point, points )
{
- QPointF diffVec = mousePosition-point;
- double distance = diffVec.x()*diffVec.x() + diffVec.y()*diffVec.y();
+ double distance = fastDistance( mousePosition, point );
if( distance < maxDistance && distance < minDistance )
{
snappedPoint = point;
@@ -159,3 +160,139 @@
return (minDistance < HUGE_VAL);
}
+
+ExtensionSnapStrategy::ExtensionSnapStrategy()
+ : SnapStrategy( SnapStrategy::Extension )
+{
+}
+
+bool ExtensionSnapStrategy::snapToPoints( const QPointF &mousePosition, SnapProxy * proxy, double maxSnapDistance )
+{
+ double maxDistance = maxSnapDistance*maxSnapDistance;
+ double minDistance = HUGE_VAL;
+
+ QPointF snappedPoint = mousePosition;
+ QPointF startPoint;
+
+ QList<KoShape*> shapes = proxy->shapes( true );
+ foreach( KoShape * shape, shapes )
+ {
+ KoPathShape * path = dynamic_cast<KoPathShape*>( shape );
+ if( ! path )
+ continue;
+
+ QMatrix matrix = path->absoluteTransformation(0);
+
+ int subpathCount = path->subpathCount();
+ for( int subpathIndex = 0; subpathIndex < subpathCount; ++subpathIndex )
+ {
+ if( path->isClosedSubpath( subpathIndex ) )
+ continue;
+
+ int pointCount = path->pointCountSubpath( subpathIndex );
+
+ // check the extension from the start point
+ KoPathPoint * first = path->pointByIndex( KoPathPointIndex( subpathIndex, 0 ) );
+ QPointF firstSnapPosition = mousePosition;
+ if( snapToExtension( firstSnapPosition, first, matrix ) )
+ {
+ double distance = fastDistance( firstSnapPosition, mousePosition );
+ if( distance < maxDistance && distance < minDistance )
+ {
+ minDistance = distance;
+ snappedPoint = firstSnapPosition;
+ startPoint = matrix.map( first->point() );
+ }
+ }
+
+ // now check the extension from the last point
+ KoPathPoint * last = path->pointByIndex( KoPathPointIndex( subpathIndex, pointCount-1 ) );
+ QPointF lastSnapPosition = mousePosition;
+ if( snapToExtension( lastSnapPosition, last, matrix ) )
+ {
+ double distance = fastDistance( lastSnapPosition, mousePosition );
+ if( distance < maxDistance && distance < minDistance )
+ {
+ minDistance = distance;
+ snappedPoint = lastSnapPosition;
+ startPoint = matrix.map( last->point() );
+ }
+ }
+ }
+ }
+
+ QPainterPath decoration;
+
+ if( minDistance < HUGE_VAL )
+ {
+ decoration.moveTo( startPoint );
+ decoration.lineTo( snappedPoint );
+ }
+
+ setDecoration( decoration );
+ setSnappedPosition( snappedPoint );
+
+ return (minDistance < HUGE_VAL);
+}
+
+bool ExtensionSnapStrategy::snapToExtension( QPointF &position, KoPathPoint * point, const QMatrix &matrix )
+{
+ QPointF direction = extensionDirection( point, matrix );
+ QPointF extensionStart = matrix.map( point->point() );
+ QPointF extensionStop = matrix.map( point->point() ) + direction;
+ float posOnExtension = project( extensionStart, extensionStop, position );
+ if( posOnExtension < 0.0 )
+ return false;
+
+ position = extensionStart + posOnExtension * direction;
+ return true;
+}
+
+double ExtensionSnapStrategy::project( const QPointF &lineStart, const QPointF &lineEnd, const QPointF &point )
+{
+ QPointF diff = lineEnd - lineStart;
+ QPointF relPoint = point - lineStart;
+ double diffLength = sqrt( diff.x()*diff.x() + diff.y()*diff.y() );
+ diff /= diffLength;
+ // project mouse position relative to stop position on extension line
+ double scalar = relPoint.x()*diff.x() + relPoint.y()*diff.y();
+ return scalar /= diffLength;
+}
+
+QPointF ExtensionSnapStrategy::extensionDirection( KoPathPoint * point, const QMatrix &matrix )
+{
+ KoPathShape * path = point->parent();
+ KoPathPointIndex index = path->pathPointIndex( point );
+
+ /// check if it is a start point
+ if( point->properties() & KoPathPoint::StartSubpath )
+ {
+ if( point->properties() & KoPathPoint::HasControlPoint2 )
+ {
+ return matrix.map(point->point()) - matrix.map(point->controlPoint2());
+ }
+ else
+ {
+ KoPathPoint * next = path->pointByIndex( KoPathPointIndex( index.first, index.second+1 ) );
+ if( next->properties() & KoPathPoint::HasControlPoint1 )
+ return matrix.map(point->point()) - matrix.map(next->controlPoint1());
+ else
+ return matrix.map(point->point()) - matrix.map(next->point());
+ }
+ }
+ else
+ {
+ if( point->properties() & KoPathPoint::HasControlPoint1 )
+ {
+ return matrix.map(point->point()) - matrix.map(point->controlPoint1());
+ }
+ else
+ {
+ KoPathPoint * prev = path->pointByIndex( KoPathPointIndex( index.first, index.second-1 ) );
+ if( prev->properties() & KoPathPoint::HasControlPoint2 )
+ return matrix.map(point->point()) - matrix.map(prev->controlPoint2());
+ else
+ return matrix.map(point->point()) - matrix.map(prev->point());
+ }
+ }
+}
--- trunk/koffice/libs/flake/tools/SnapStrategy.h #769234:769235
@@ -25,10 +25,19 @@
#include <QtCore/QPointF>
#include <QtGui/QPainterPath>
+class KoPathPoint;
+
class SnapStrategy
{
public:
- SnapStrategy( SnapGuide::SnapType type );
+ /// the different possible snap types
+ enum SnapType {
+ Orthogonal = 1,
+ Node = 2,
+ Extension = 4
+ };
+
+ SnapStrategy( SnapType type );
virtual ~SnapStrategy() {};
virtual bool snapToPoints( const QPointF &mousePosition, SnapProxy * proxy, double maxSnapDistance ) = 0;
@@ -37,7 +46,7 @@
QPainterPath decoration() const;
/// returns the strategies type
- SnapGuide::SnapType type() const;
+ SnapType type() const;
static double fastDistance( const QPointF &p1, const QPointF &p2 );
@@ -53,7 +62,7 @@
private:
QPainterPath m_decoration;
- SnapGuide::SnapType m_snapType;
+ SnapType m_snapType;
QPointF m_snappedPosition;
};
@@ -71,4 +80,15 @@
virtual bool snapToPoints( const QPointF &mousePosition, SnapProxy * proxy, double maxSnapDistance );
};
+class ExtensionSnapStrategy : public SnapStrategy
+{
+public:
+ ExtensionSnapStrategy();
+ virtual bool snapToPoints( const QPointF &mousePosition, SnapProxy * proxy, double maxSnapDistance );
+private:
+ double project( const QPointF &lineStart , const QPointF &lineEnd, const QPointF &point );
+ QPointF extensionDirection( KoPathPoint * point, const QMatrix &matrix );
+ bool snapToExtension( QPointF &position, KoPathPoint * point, const QMatrix &matrix );
+};
+
#endif // SNAPSTRATEGY_H
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic