Commit a9d52fcb authored by Jan Hambrecht's avatar Jan Hambrecht

I promised to deliver something, so here it is:

A connection shape which is a parameter shape and 
which can be manipulated with the standard path
tool. You can change the type of the connection 
and connect/disconnect to and from other shapes.
Loading and saving is not implemented yet.
You can change the stroke of the connection like 
with every other shape by using the stroke docker.


svn path=/trunk/koffice/; revision=733107
parent 8e6e5b08
......@@ -48,6 +48,7 @@ set(flake_SRCS
KoPathTool.cpp
KoPathPointRubberSelectStrategy.cpp
KoPathPointMoveStrategy.cpp
KoPathConnectionPointStrategy.cpp
KoPathControlPointMoveStrategy.cpp
KoPointGroup.cpp
KoParameterShape.cpp
......@@ -81,6 +82,9 @@ set(flake_SRCS
KoShapeConfigWidgetBase.cpp
KoDrag.cpp
KoDragOdfSaveHelper.cpp
KoConnectionShape.cpp
KoConnectionShapeFactory.cpp
KoConnectionShapeConfigWidget.cpp
commands/KoShapeGroupCommand.cpp
commands/KoShapeAlignCommand.cpp
commands/KoShapeBackgroundCommand.cpp
......@@ -113,11 +117,13 @@ set(flake_SRCS
commands/KoParameterToPathCommand.cpp
commands/KoShapeTransformCommand.cpp
commands/KoPathFillRuleCommand.cpp
commands/KoConnectionShapeTypeCommand.cpp
)
kde4_add_ui_files(flake_SRCS
KoInteractionToolWidget.ui
PathToolOptionWidgetBase.ui
KoConnectionShapeConfigWidget.ui
)
......
This diff is collapsed.
/* This file is part of the KDE project
* Copyright (C) 2007 Boudewijn Rempt <boud@kde.org>
* Copyright (C) 2007 Thorsten Zachmann <zachmann@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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.
*/
#ifndef KO_CONNECTION_SHAPE_H
#define KO_CONNECTION_SHAPE_H
#include <KoParameterShape.h>
#define KOCONNECTIONSHAPEID "KoConnectionShape"
/// A connection to a connection point of a shape
typedef QPair<KoShape*,int> KoConnection;
class KoConnectionShape : public KoParameterShape
{
public:
enum Type {
Standard, ///< escapes connected shapes with straight lines, connects with perpendicular lines
Lines, ///< escapes connected shapes with straight lines, connects with straight line
Straight, ///< one straight line between connected shapes
Curve ///< a single curved line between connected shapes
};
explicit KoConnectionShape();
virtual ~KoConnectionShape();
// reimplemented
virtual void paint( QPainter& painter, const KoViewConverter& converter );
// reimplemented
virtual void saveOdf( KoShapeSavingContext & context ) const;
// reimplemented
virtual bool loadOdf( const KoXmlElement & element, KoShapeLoadingContext &context );
// reimplemented
inline QString pathShapeId() const
{
return KOCONNECTIONSHAPEID;
}
/// Sets the first shape the connector is connected to
void setConnection1( KoShape * shape1, int connectionPointIndex );
/// Sets the second shape the connector is connected to
void setConnection2( KoShape * shape2, int connectionPointIndex );
/// Returns the connection to the first shape
KoConnection connection1() const;
/// Returns the connection to the second shape
KoConnection connection2() const;
/// Updates connections to shapes
void updateConnections();
/// Returns connection type
Type connectionType() const;
/// Sets the connection type
void setConnectionType( Type connectionType );
protected:
/// reimplemented
void moveHandleAction( int handleId, const QPointF & point, Qt::KeyboardModifiers modifiers = Qt::NoModifier );
/// reimplemented
void updatePath( const QSizeF &size );
/// Returns if given handle is connected to a shape
bool handleConnected( int handleId ) const;
enum Quadrant { None, Left, Bottom, Right, Top };
/// Returns escape direction of given handle
QPointF escapeDirection( int handleId ) const;
/// Checks if rays from given points into given directions intersect
bool intersects( const QPointF &p1, const QPointF &d1, const QPointF &p2, const QPointF &d2, QPointF &isect );
/// Returns perpendicular direction from given point p1 and direction d1 toward point p2
QPointF perpendicularDirection( const QPointF &p1, const QPointF &d1, const QPointF &p2 );
private:
double scalarProd( const QPointF &v1, const QPointF &v2 );
double crossProd( const QPointF &v1, const QPointF &v2 );
struct Private;
Private * const d;
};
#endif
/* This file is part of the KDE project
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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 "KoConnectionShapeConfigWidget.h"
#include "commands/KoConnectionShapeTypeCommand.h"
#include <klocale.h>
KoConnectionShapeConfigWidget::KoConnectionShapeConfigWidget()
{
widget.setupUi( this );
layout()->setContentsMargins( 0,0,0,0 );
widget.connectionType->clear();
widget.connectionType->addItem( i18n("Standard") );
widget.connectionType->addItem( i18n("Lines") );
widget.connectionType->addItem( i18n("Straight") );
widget.connectionType->addItem( i18n("Curve") );
connect( widget.connectionType, SIGNAL(currentIndexChanged(int)), this, SIGNAL(propertyChanged()));
}
void KoConnectionShapeConfigWidget::open(KoShape *shape)
{
m_connection = dynamic_cast<KoConnectionShape*>( shape );
if( ! m_connection )
return;
widget.connectionType->blockSignals( true );
widget.connectionType->setCurrentIndex( m_connection->connectionType() );
widget.connectionType->blockSignals( false );
}
void KoConnectionShapeConfigWidget::save()
{
if( ! m_connection )
return;
m_connection->setConnectionType( static_cast<KoConnectionShape::Type>( widget.connectionType->currentIndex() ) );
}
QUndoCommand * KoConnectionShapeConfigWidget::createCommand()
{
if( ! m_connection )
return 0;
else
{
KoConnectionShape::Type type = static_cast<KoConnectionShape::Type>( widget.connectionType->currentIndex() );
return new KoConnectionShapeTypeCommand( m_connection, type );
}
}
#include "KoConnectionShapeConfigWidget.moc"
/* This file is part of the KDE project
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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.
*/
#ifndef KOCONNECTIONSHAPECONFIGWIDGET_H
#define KOCONNECTIONSHAPECONFIGWIDGET_H
#include "KoConnectionShape.h"
#include "ui_KoConnectionShapeConfigWidget.h"
#include <KoShapeConfigWidgetBase.h>
class KoConnectionShapeConfigWidget : public KoShapeConfigWidgetBase
{
Q_OBJECT
public:
KoConnectionShapeConfigWidget();
/// reimplemented
virtual void open(KoShape *shape);
/// reimplemented
virtual void save();
/// reimplemented
virtual bool showOnShapeCreate() { return false; }
/// reimplemented
virtual QUndoCommand * createCommand();
private:
Ui::KoConnectionShapeConfigWidget widget;
KoConnectionShape * m_connection;
};
#endif // KOCONNECTIONSHAPECONFIGWIDGET_H
<ui version="4.0" >
<class>KoConnectionShapeConfigWidget</class>
<widget class="QWidget" name="KoConnectionShapeConfigWidget" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>187</width>
<height>173</height>
</rect>
</property>
<property name="windowTitle" >
<string>Ellipse Shape</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Properties</string>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QComboBox" name="connectionType" />
</item>
<item row="1" column="1" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
/* This file is part of the KDE project
*
* Copyright (C) 2007 Boudewijn Rempt <boud@kde.org>
* Copyright (C) 2007 Thorsten Zachmann <zachmann@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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 "KoConnectionShapeFactory.h"
#include "KoConnectionShape.h"
#include "KoConnectionShapeConfigWidget.h"
#include <KoXmlNS.h>
#include <klocale.h>
#include <KoLineBorder.h>
KoConnectionShapeFactory::KoConnectionShapeFactory( QObject* parent)
: KoShapeFactory( parent, KOCONNECTIONSHAPEID, i18n( "Connection Shape" ) )
{
setToolTip( i18n( "A shape which displays a connection between two other shapes" ) );
///@todo setIcon( "connectionshape" );
//setIcon( "" );
setOdfElementNames( KoXmlNS::draw, QStringList( "connector" ) );
setLoadingPriority( 1 );
}
KoShape* KoConnectionShapeFactory::createDefaultShape() const
{
KoConnectionShape * shape = new KoConnectionShape();
shape->setBorder( new KoLineBorder() );
shape->setShapeId( KoPathShapeId );
return shape;
}
KoShape* KoConnectionShapeFactory::createShape( const KoProperties* params ) const
{
Q_UNUSED(params);
return createDefaultShape();
}
bool KoConnectionShapeFactory::supports(const KoXmlElement & e) const
{
return ( e.localName() == "image" && e.namespaceURI() == KoXmlNS::draw );
}
QList<KoShapeConfigWidgetBase*> KoConnectionShapeFactory::createShapeOptionPanels()
{
QList<KoShapeConfigWidgetBase*> panels;
panels.append( new KoConnectionShapeConfigWidget() );
return panels;
}
/* This file is part of the KDE project
* Copyright (C) 2007 Boudewijn Rempt <boud@kde.org>
* Copyright (C) 2007 Thorsten Zachmann <zachmann@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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.
*/
#ifndef CONNECTIONSHAPEFACTORY_H
#define CONNECTIONSHAPEFACTORY_H
#include <KoShapeFactory.h>
class KoShape;
class KoConnectionShapeFactory : public KoShapeFactory
{
public:
KoConnectionShapeFactory( QObject* parent);
~KoConnectionShapeFactory() {}
virtual KoShape* createDefaultShape() const;
virtual KoShape* createShape( const KoProperties* params ) const;
virtual bool supports(const KoXmlElement & e) const;
virtual QList<KoShapeConfigWidgetBase*> createShapeOptionPanels();
};
#endif
/* This file is part of the KDE project
*
* Copyright (C) 2007 Boudewijn Rempt <boud@kde.org>
* Copyright (C) 2007 Thorsten Zachmann <zachmann@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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 "KoPathConnectionPointStrategy.h"
#include "KoPathTool.h"
#include "KoCanvasBase.h"
#include "KoShapeManager.h"
#include "KoFlake.h"
#include <kdebug.h>
#include <float.h>
#include <math.h>
//#include "commands/KoPathConnectionPointMoveCommand.h"
KoPathConnectionPointStrategy::KoPathConnectionPointStrategy( KoPathTool *tool, KoCanvasBase *canvas,
KoConnectionShape * shape, int handleId )
: KoParameterChangeStrategy( tool, canvas, shape, handleId )
, m_tool( tool )
, m_connectionShape( shape )
, m_handleId( handleId )
, m_startPoint( m_connectionShape->shapeToDocument( m_connectionShape->handlePosition( handleId ) ) )
{
if( handleId == 0 )
m_oldConnection = m_connectionShape->connection1();
else
m_oldConnection = m_connectionShape->connection2();
}
KoPathConnectionPointStrategy::~KoPathConnectionPointStrategy()
{
}
void KoPathConnectionPointStrategy::handleMouseMove( const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers )
{
const double MAX_DISTANCE = 20.0; // TODO make user definable
const double MAX_DISTANCE_SQR = MAX_DISTANCE*MAX_DISTANCE;
m_newConnection = KoConnection(0,-1);
QRectF roi( mouseLocation-QPointF(MAX_DISTANCE,MAX_DISTANCE), QSizeF(2*MAX_DISTANCE,2*MAX_DISTANCE ) );
QList<KoShape*> shapes = m_canvas->shapeManager()->shapesAt( roi, true );
if( shapes.count() < 2 )
KoParameterChangeStrategy::handleMouseMove( mouseLocation, modifiers );
else
{
double minimalDistance = DBL_MAX;
QPointF nearestPoint;
KoShape *nearestShape = 0;
int nearestPointIndex = -1;
bool nearestAlreadyPresent = false;
foreach( KoShape* shape, shapes )
{
// we do not want to connect to ourself
if( shape == m_connectionShape )
continue;
bool alreadyPresent = true;
QMatrix m = shape->absoluteTransformation(0);
QList<QPointF> connectionPoints = shape->connectionPoints();
if( ! connectionPoints.count() )
{
QSizeF size = shape->size();
connectionPoints.append( QPointF( 0.0, 0.0 ) );
connectionPoints.append( QPointF( size.width(), 0.0 ) );
connectionPoints.append( QPointF(size.width(), size.height() ) );
connectionPoints.append( QPointF( 0.0, size.height() ) );
connectionPoints.append( 0.5 * (connectionPoints[0] + connectionPoints[1] ) );
connectionPoints.append( 0.5 * (connectionPoints[1] + connectionPoints[2] ) );
connectionPoints.append( 0.5 * (connectionPoints[2] + connectionPoints[3] ) );
connectionPoints.append( 0.5 * (connectionPoints[3] + connectionPoints[0] ) );
alreadyPresent = false;
}
QPointF localMousePosition = shape->absoluteTransformation(0).inverted().map( mouseLocation );
int connectionPointCount = connectionPoints.count();
for( int i = 0; i < connectionPointCount; ++i )
{
QPointF difference = localMousePosition-connectionPoints[i];
double distance = difference.x()*difference.x() + difference.y()*difference.y();
if( distance > MAX_DISTANCE_SQR )
continue;
if( distance < minimalDistance )
{
nearestShape = shape;
nearestPoint = connectionPoints[i];
nearestPointIndex = i;
nearestAlreadyPresent = alreadyPresent;
minimalDistance = distance;
}
}
}
if( nearestShape )
{
if( ! nearestAlreadyPresent )
{
//nearestShape->addConnectionPoint( nearestPoint );
nearestPointIndex = -1;
}
nearestPoint = nearestShape->absoluteTransformation(0).map( nearestPoint );
}
else
{
nearestPoint = mouseLocation;
nearestPointIndex = -1;
}
m_newConnection = KoConnection( nearestShape, nearestPointIndex );
if( m_handleId == 0 )
m_connectionShape->setConnection1( m_newConnection.first, m_newConnection.second );
else
m_connectionShape->setConnection2( m_newConnection.first, m_newConnection.second );
KoParameterChangeStrategy::handleMouseMove( nearestPoint, modifiers );
}
}
void KoPathConnectionPointStrategy::finishInteraction( Qt::KeyboardModifiers modifiers )
{
KoParameterChangeStrategy::finishInteraction( modifiers );
}
QUndoCommand* KoPathConnectionPointStrategy::createCommand()
{
// check if we connect to a shape and if the connection point is already present
if( m_newConnection.first && m_newConnection.second == -1 )
{
// map handle position into document coordinates
QPointF p = m_connectionShape->shapeToDocument( m_connectionShape->handlePosition( m_handleId ) );
// and add as connection point in shape coordinates
m_newConnection.first->addConnectionPoint( m_newConnection.first->absoluteTransformation(0).inverted().map( p ) );
m_newConnection.second = m_newConnection.first->connectionPoints().count()-1;
}
// set the connection corresponding to the handle we are working on
if( m_handleId == 0 )
m_connectionShape->setConnection1( m_newConnection.first, m_newConnection.second );
else
m_connectionShape->setConnection2( m_newConnection.first, m_newConnection.second );
// TODO create a connection command
return KoParameterChangeStrategy::createCommand();
}
/* This file is part of the KDE project
*
* Copyright (C) 2007 Boudewijn Rempt <boud@kde.org>
* Copyright (C) 2007 Thorsten Zachmann <zachmann@kde.org>
* Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
*
* 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.
*/
#ifndef KO_PATH_CONNECTION_POINT_STRATEGY
#define KO_PATH_CONNECTION_POINT_STRATEGY
#include <QPointF>
#include "KoParameterChangeStrategy.h"
#include "KoConnectionShape.h"
class KoParameterShape;
class KoCanvasBase;
class KoPathTool;
/**
* /internal
* @brief Strategy for moving points of a path shape.
*/
class KoPathConnectionPointStrategy : public KoParameterChangeStrategy
{
public:
KoPathConnectionPointStrategy( KoPathTool *tool, KoCanvasBase *canvas,
KoConnectionShape * parameterShape, int handleId );
virtual ~KoPathConnectionPointStrategy();
virtual void handleMouseMove( const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers );
virtual void finishInteraction( Qt::KeyboardModifiers modifiers );
virtual QUndoCommand* createCommand();