[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice-devel
Subject:    Re: Flake vector shapes
From:       Thomas Zander <zander () kde ! org>
Date:       2006-09-02 21:58:32
Message-ID: 200609022358.33483.zander () kde ! org
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


On Tuesday 29 August 2006 12:01, Thomas Zander wrote:
> On Thursday 24 August 2006 23:57, Sven Langkamp wrote:
> > The first approach to implement this was to have a KoPathShape
> > combined with a KoUserData object.
>
> I think this is the only correct way to do so to avoid a lot of
> duplicate code and other nastiness.
>
> As I stated before, Flake is not meant to be a 'final' API at all, any
> new feature needed or refactor can be accepted.

Ok, I have some test code. With extra emphasis on test!
Its here to show the structures and effects, not to be perfect. I broke 
the big rule to not put all classes in one file for example.

The idea is that shapes like a 'Rectangle', 'Star', 'Circle' etc will have 
a UserData object which stores the properies specific for that type and 
it will update or regenerate the path based on these items. So, 
underwater the path is fully constructed (avoiding separate paint etc) 
but the user never notices this.

The tool uses the userData to create a strategy for the current object 
which then does things specific for the shape type. I implemented the 
Star object to do something different. Its a silly example but the point 
is that there _is_ a strategy, not how accurate it is doing things.

What I didn't do yet is add a couple of widgets. A widget to alter the 
number of points a star has, for example. This GUI would be shown on 
creation time, among others.

Again, this is the most beta code you have seen in quite some time as its 
meant to be a quick way to explain the ideas. Not a final solution.
-- 
Thomas Zander

["Rect-Star.diff" (text/x-diff)]

Index: libs/flake/KoPathTool.cpp
===================================================================
--- libs/flake/KoPathTool.cpp	(revision 580172)
+++ libs/flake/KoPathTool.cpp	(working copy)
@@ -1,6 +1,7 @@
 /* This file is part of the KDE project
  * Copyright (C) 2006 Jan Hambrecht <jaham@gmx.net>
  * Copyright (C) 2006 Thorsten Zachmann <zachmann@kde.org>
+ * Copyright (C) 2006 Thomas Zander <zander@kde.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -18,18 +19,20 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#include <KoPathTool.h>
-#include <KoCanvasBase.h>
-#include <KoSelection.h>
-#include <KoShapeManager.h>
-#include <KoPointerEvent.h>
-#include <KoPathCommand.h>
+#include "KoPathTool.h"
+#include "KoCanvasBase.h"
+#include "KoSelection.h"
+#include "KoShapeManager.h"
+#include "KoPointerEvent.h"
+#include "KoPathCommand.h"
+#include "KoInteractionStrategy.h"
+#include "KoRectanglePathStrategy.h"
 
 #include <kdebug.h>
 #include <QKeyEvent>
 
 KoPathTool::KoPathTool(KoCanvasBase *canvas)
-: KoTool(canvas)
+: KoInteractionTool(canvas)
 , m_pathShape(0)
 , m_activePoint(0)
 , m_handleRadius( 3 )
@@ -75,6 +78,25 @@
 }
 
 void KoPathTool::mousePressEvent( KoPointerEvent *event ) {
+    Q_ASSERT(m_currentStrategy == 0);
+
+    QRectF roi = handleRect( untransformed( event->point ) );
+    foreach(KoShape *shape, m_canvas->shapeManager()->selection()->selectedShapes()) \
{ +        KoPathShape *ps = dynamic_cast<KoPathShape*> (shape);
+        if(ps == 0)
+            continue;
+        QList<KoPathPoint*> points = ps->pointsAt( roi );
+        if( points.empty() )
+            continue;
+
+        KoPathStrategyBase *pathStrategy = dynamic_cast<KoPathStrategyBase*> \
(ps->userData()); +        if(pathStrategy)
+            m_currentStrategy = pathStrategy->createInterationStrategy(this, \
m_canvas, ps, points[0]); +    }
+    if(m_currentStrategy)
+        return;
+
+    // the rest here should probably be moved to a strategy of itself..
     m_pointMoving = m_activePoint;
     m_lastPosition = event->point;
     m_move = QPointF( 0, 0 );
@@ -106,10 +128,13 @@
     }
 }
 
-void KoPathTool::mouseDoubleClickEvent( KoPointerEvent * ) {
-}
+void KoPathTool::mouseMoveEvent( KoPointerEvent *event ) {
+    if(m_currentStrategy) {
+        KoInteractionTool::mouseMoveEvent(event);
+        return;
+    }
 
-void KoPathTool::mouseMoveEvent( KoPointerEvent *event ) {
+    // rest should probably be moved to its own strategy
     if( m_pointMoving )
     {
         QPointF docPoint = snapToGrid( event->point, event->modifiers() );
@@ -155,7 +180,14 @@
     }
 }
 
-void KoPathTool::mouseReleaseEvent( KoPointerEvent * ) {
+void KoPathTool::mouseReleaseEvent( KoPointerEvent *event ) {
+    if ( m_currentStrategy ) {
+        KoInteractionTool::mouseReleaseEvent(event);
+        return;
+    }
+
+    // rest should probably be moved to a strategy of its own
+
     // TODO
     m_pointMoving = false;
     if( ! m_move.isNull() )
@@ -166,26 +198,20 @@
 }
 
 void KoPathTool::keyPressEvent(QKeyEvent *event) {
-    switch(event->key()) 
+    switch(event->key())
     {
         case Qt::Key_I:
-            if(event->modifiers() & Qt::ControlModifier) 
-            {
-                if( m_handleRadius > 3 )
-                    m_handleRadius--;
-            }
+            if((event->modifiers() & Qt::ControlModifier) && m_handleRadius > 3 )
+                m_handleRadius--;
             else
                 m_handleRadius++;
             repaint( transformed( m_pathShape->outline().controlPointRect() ) );
-        break;
+            break;
+        default:
+            event->ignore();
     }
-    event->accept();
 }
 
-void KoPathTool::keyReleaseEvent(QKeyEvent *event) {
-    event->accept();
-}
-
 void KoPathTool::activate (bool temporary) {
     Q_UNUSED(temporary);
     KoShape *shape = m_canvas->shapeManager()->selection()->firstSelectedShape();
@@ -230,6 +256,7 @@
     return m_pathShape->transformationMatrix(0).inverted().map( p );
 }
 
+// ugh thats copy paste from the interactionStrategy. Better move the usage to its \
own strategy  QPointF KoPathTool::snapToGrid( const QPointF &p, Qt::KeyboardModifiers \
modifiers ) {  if( ! m_canvas->snapToGrid() || modifiers & Qt::ShiftModifier )
         return p;
@@ -239,3 +266,5 @@
     return QPointF( static_cast<int>( p.x() / gridX + 1e-10 ) * gridX,
                     static_cast<int>( p.y() / gridY + 1e-10 ) * gridY );
 }
+
+#include <KoPathTool.moc>
Index: libs/flake/KoRectanglePathStrategy.cpp
===================================================================
--- libs/flake/KoRectanglePathStrategy.cpp	(revision 0)
+++ libs/flake/KoRectanglePathStrategy.cpp	(revision 0)
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2006 Thomas Zander <zander@kde.org>
+ *
+ * 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 "KoRectanglePathStrategy.h"
+#include "KoPathShape.h"
+
+#include <kdebug.h>
+
+KoRectanglePathStrategy::KoRectanglePathStrategy(KoPathShape *shape)
+{
+    m_width = 100;
+    m_height = 100;
+    updateShapeData(shape);
+}
+
+void KoRectanglePathStrategy::updateShapeData(KoPathShape *shape) {
+    shape->m_points.clear(); // TODO use a nice 'remove point' way
+    shape->moveTo(QPointF(0.0, 0.0));
+    shape->lineTo(QPointF(m_width, 0.0));
+    shape->lineTo(QPointF(m_width, m_height));
+    shape->lineTo(QPointF(0, m_height));
+    shape->close();
+}
+
+KoStarPathStrategy::KoStarPathStrategy(KoPathShape *shape)
+    : m_points(5),
+    m_innerSize(40.0),
+    m_outerSize(90)
+{
+    updateShapeData(shape);
+}
+
+
+void KoStarPathStrategy::updateShapeData(KoPathShape *shape) {
+    shape->m_points.clear(); // TODO use a nice 'remove point' way
+    // this is demo code, guys. Don't expect me to do the sin() stuff when I can be \
lazy.. +    shape->moveTo(QPointF(50, 0));
+    shape->lineTo(QPointF(60, 38));
+    shape->lineTo(QPointF(100, 42));
+    shape->lineTo(QPointF(65, 62));
+    shape->lineTo(QPointF(75, 100));
+    shape->lineTo(QPointF(50, 80));
+    shape->lineTo(QPointF(20, 100));
+    shape->lineTo(QPointF(35, 62));
+    shape->lineTo(QPointF(0, 42));
+    shape->lineTo(QPointF(40, 38));
+    shape->close();
+}
+
+KoInteractionStrategy *KoStarPathStrategy::createInterationStrategy(KoTool *parent, \
KoCanvasBase *canvas, KoPathShape *shape, KoPathPoint *point) { +    return new \
StarInteractionStategy(parent, canvas, shape, point); +}
+
+// StarInteractionStategy
+KoStarPathStrategy::StarInteractionStategy::StarInteractionStategy(KoTool *parent, \
KoCanvasBase *canvas, KoPathShape *shape, KoPathPoint *point) +    : \
KoInteractionStrategy(parent, canvas) +    , m_shape(shape)
+    , m_point(point->point() + m_shape->position())
+{
+    m_innerNode = shape->points().indexOf(point) % 2;
+}
+
+void KoStarPathStrategy::StarInteractionStategy::handleMouseMove(const QPointF \
&mouseLocation, Qt::KeyboardModifiers modifiers) { +    // normally you'd adjust the \
radius and regenerate the shape. But the generation +    // is hardcoded for demo so \
that won't have much effect. So, I alter the nodes a little. +    QPointF diff = \
mouseLocation - m_point ; +    int i=0;
+    foreach(KoPathPoint *pp, m_shape->points()) {
+        if(i++ % 2 == m_innerNode?0:1)
+            continue;
+        pp->setPoint(pp->point() + diff);
+    }
+    m_point = mouseLocation;
+    m_shape->normalize();
+    m_shape->repaint();
+}
Index: libs/flake/KoPathTool.h
===================================================================
--- libs/flake/KoPathTool.h	(revision 580090)
+++ libs/flake/KoPathTool.h	(working copy)
@@ -22,9 +22,10 @@
 
 #include "KoPathShape.h"
 
-#include <KoTool.h>
+#include <KoInteractionTool.h>
 
-class KoPathTool : public KoTool {
+class KoPathTool : public KoInteractionTool {
+    Q_OBJECT
 public:
     KoPathTool(KoCanvasBase *canvas);
     ~KoPathTool();
@@ -32,15 +33,16 @@
     void paint( QPainter &painter, KoViewConverter &converter );
 
     void mousePressEvent( KoPointerEvent *event ) ;
-    void mouseDoubleClickEvent( KoPointerEvent *event );
     void mouseMoveEvent( KoPointerEvent *event );
     void mouseReleaseEvent( KoPointerEvent *event );
     void keyPressEvent(QKeyEvent *event);
-    void keyReleaseEvent(QKeyEvent *event);
 
     void activate (bool temporary=false);
     void deactivate();
 
+signals:
+    void sigDone();
+
 private:
     /// repaints the specified rect
     void repaint( const QRectF &repaintRect );
Index: libs/flake/KoRectanglePathStrategy.h
===================================================================
--- libs/flake/KoRectanglePathStrategy.h	(revision 0)
+++ libs/flake/KoRectanglePathStrategy.h	(revision 0)
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2006 Thomas Zander <zander@kde.org>
+ *
+ * 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 KORECTANGLEPATHSHAPE_H
+#define KORECTANGLEPATHSHAPE_H
+
+#include "KoShapeUserData.h"
+#include "KoInteractionStrategy.h"
+
+class KoPathShape;
+class KoPathPoint;
+
+class KoPathStrategyBase : public KoShapeUserData {
+public:
+    KoPathStrategyBase() {}
+    virtual ~KoPathStrategyBase() {}
+
+    virtual void updateShapeData(KoPathShape *shape) = 0;
+    virtual KoInteractionStrategy *createInterationStrategy(KoTool *parent, \
KoCanvasBase *canvas, KoPathShape *shape, KoPathPoint *point) = 0; +};
+
+class KoRectanglePathStrategy : public KoPathStrategyBase {
+public:
+    KoRectanglePathStrategy(KoPathShape *shape);
+    ~KoRectanglePathStrategy() {}
+
+    void updateShapeData(KoPathShape *shape);
+    KoInteractionStrategy *createInterationStrategy(KoTool *parent, KoCanvasBase \
*canvas, KoPathShape *shape, KoPathPoint *point) +    { return 0; }
+
+private:
+    double m_width, m_height;
+};
+
+class KoStarPathStrategy : public KoPathStrategyBase {
+public:
+    KoStarPathStrategy(KoPathShape *shape);
+    ~KoStarPathStrategy() {}
+
+    void updateShapeData(KoPathShape *shape);
+
+    KoInteractionStrategy *createInterationStrategy(KoTool *parent, KoCanvasBase \
*canvas, KoPathShape *shape, KoPathPoint *point); +
+private:
+    class StarInteractionStategy : public KoInteractionStrategy {
+    public:
+        StarInteractionStategy(KoTool *parent, KoCanvasBase *canvas, KoPathShape \
*shape, KoPathPoint *point); +        void handleMouseMove(const QPointF \
&mouseLocation, Qt::KeyboardModifiers modifiers); +        KCommand *createCommand () \
{ return 0; } +        void cancelInteraction() {}
+        void finishInteraction() {}
+    private:
+        KoPathShape *m_shape;
+        QPointF m_point;
+        bool m_innerNode;
+    };
+
+    int m_points;
+    double m_innerSize, m_outerSize;
+};
+
+#endif
Index: libs/flake/KoPathShape.h
===================================================================
--- libs/flake/KoPathShape.h	(revision 580090)
+++ libs/flake/KoPathShape.h	(working copy)
@@ -335,6 +335,15 @@
      */
     QList<KoPathPoint*> pointsAt( const QRectF &r );
 
+    QList<KoPathPoint*> points() const {
+        QList<KoPathPoint*> answer;
+        foreach(QList<KoPathPoint*> subpath, m_points) {
+            foreach(KoPathPoint *pp, subpath)
+                answer.append(pp);
+        }
+        return answer;
+    }
+
 private:
     void map( const QMatrix &matrix );
 
@@ -348,6 +357,10 @@
     /// a KoSubpath contains a path from a moveTo until a close or a new moveTo
     typedef QList<KoPathPoint *> KoSubpath;
     QList<KoSubpath> m_points;
+
+// stupid solution, needs a proper 'remove' but this is easier for demo purposes
+friend class KoRectanglePathStrategy;
+friend class KoStarPathStrategy;
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS( KoPathPoint::KoPointProperties )
Index: libs/flake/CMakeLists.txt
===================================================================
--- libs/flake/CMakeLists.txt	(revision 580090)
+++ libs/flake/CMakeLists.txt	(working copy)
@@ -32,6 +32,7 @@
     KoPathToolFactory.cpp
     KoPathTool.cpp
     KoPathCommand.cpp
+    KoRectanglePathStrategy.cpp
 )
 
 kde4_automoc(${flake_SRCS})
Index: libs/flake/KoPathShapeFactory.cpp
===================================================================
--- libs/flake/KoPathShapeFactory.cpp	(revision 580090)
+++ libs/flake/KoPathShapeFactory.cpp	(working copy)
@@ -20,7 +20,10 @@
 #include "KoPathShapeFactory.h"
 #include "KoPathShape.h"
 #include "KoLineBorder.h"
+#include "KoRectanglePathStrategy.h"
 
+#include <KoProperties.h>
+
 #include <klocale.h>
 
 KoPathShapeFactory::KoPathShapeFactory(QObject *parent, const QStringList&)
@@ -28,6 +31,20 @@
 {
     setToolTip("A simple path shape");
     setIcon("pathshape");
+
+    KoShapeTemplate t;
+    t.name = "Rectangle";
+    t.toolTip = "Rectangle";
+    t.properties = new KoProperties();
+    t.properties->setProperty("type", "rect");
+    addTemplate(t);
+
+    KoShapeTemplate t2;
+    t2.name = "Star";
+    t2.toolTip = "Star";
+    t2.properties = new KoProperties();
+    t2.properties->setProperty("type", "star");
+    addTemplate(t2);
 }
 
 KoShape * KoPathShapeFactory::createDefaultShape() {
@@ -42,7 +59,15 @@
 }
 
 KoShape * KoPathShapeFactory::createShape(const KoProperties * params) const {
-    Q_UNUSED(params);
-    return new KoPathShape();
+    KoPathShape *shape = new KoPathShape();
+    if(params->getProperty("type") == "rect")
+        shape->setUserData(new KoRectanglePathStrategy(shape));
+    else if(params->getProperty("type") == "star")
+        shape->setUserData(new KoStarPathStrategy(shape));
+
+    shape->setBorder(new KoLineBorder());
+    shape->setShapeId(shapeId());
+
+    return shape;
 }
 


[Attachment #8 (application/pgp-signature)]

_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic