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

List:       kde-commits
Subject:    [tikzkit] qtikzgui: first success of resizing an Ellipse Path
From:       Dominik Haumann <dhaumann () kde ! org>
Date:       2013-12-31 18:40:45
Message-ID: E1Vy4FB-0000pn-GG () scm ! kde ! org
[Download RAW message or body]

Git commit 86c1d35b59e0d8e3033e8670749cb66d5d5ea962 by Dominik Haumann.
Committed on 31/12/2013 at 15:34.
Pushed by dhaumann into branch 'master'.

first success of resizing an Ellipse Path

M  +2    -0    qtikzgui/CMakeLists.txt
M  +3    -2    qtikzgui/TikzPath.cpp
M  +7    -0    qtikzgui/TikzPath.h
M  +1    -1    qtikzgui/TikzScene.cpp
M  +5    -0    qtikzgui/paths/AbstractTikzPath.cpp
M  +6    -0    qtikzgui/paths/AbstractTikzPath.h
A  +93   -0    qtikzgui/paths/PathHandle.cpp     [License: LGPL (v2+)]
A  +89   -0    qtikzgui/paths/PathHandle.h     [License: LGPL (v2+)]
M  +121  -6    qtikzgui/paths/ellipse/TikzEllipsePath.cpp
M  +29   -11   qtikzgui/paths/ellipse/TikzEllipsePath.h

http://commits.kde.org/tikzkit/86c1d35b59e0d8e3033e8670749cb66d5d5ea962

diff --git a/qtikzgui/CMakeLists.txt b/qtikzgui/CMakeLists.txt
index 8377c67..094de59 100644
--- a/qtikzgui/CMakeLists.txt
+++ b/qtikzgui/CMakeLists.txt
@@ -30,6 +30,7 @@ set(qtikzgui_SOURCES
 
     paths/AbstractTikzPath.cpp
     paths/ellipse/TikzEllipsePath.cpp
+    paths/PathHandle.cpp
 
     TikzScene.cpp
     TikzView.cpp
@@ -73,6 +74,7 @@ set(qtikzgui_HEADERS
 
     paths/AbstractTikzPath.h
     paths/ellipse/TikzEllipsePath.h
+    paths/PathHandle.h
 
     TikzScene.h
     TikzView.h
diff --git a/qtikzgui/TikzPath.cpp b/qtikzgui/TikzPath.cpp
index e704cf7..d8fd2ce 100644
--- a/qtikzgui/TikzPath.cpp
+++ b/qtikzgui/TikzPath.cpp
@@ -135,11 +135,13 @@ void TikzPath::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
 void TikzPath::mousePressEvent(QGraphicsSceneMouseEvent * event)
 {
     d->backendPath->mousePressEvent(event);
+    TikzItem::mousePressEvent(event);
 }
 
 void TikzPath::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
 {
     d->backendPath->mouseReleaseEvent(event);
+    TikzItem::mouseReleaseEvent(event);
 }
 
 QVariant TikzPath::itemChange(GraphicsItemChange change, const QVariant & value)
@@ -147,8 +149,7 @@ QVariant TikzPath::itemChange(GraphicsItemChange change, const QVariant & value)
     if (change == ItemSelectedHasChanged) {
         // show / hide handles if selected
         const bool selected = value.toBool();
-
-        // FIXME: implement ?
+        emit itemSelected(selected);
     }
 
     return QGraphicsObject::itemChange(change, value);
diff --git a/qtikzgui/TikzPath.h b/qtikzgui/TikzPath.h
index 59a43ef..56c9b1e 100644
--- a/qtikzgui/TikzPath.h
+++ b/qtikzgui/TikzPath.h
@@ -105,6 +105,13 @@ class TIKZGUI_EXPORT TikzPath :  public TikzItem
          */
         bool contains(const QPointF & point) const;
 
+    Q_SIGNALS:
+        /**
+         * This signal is emitted whenever the item selection changes.
+         * @param selected @p true, if the item is selected, otherwise @p false
+         */
+        void itemSelected(bool selected);
+
     //
     // Mouse handling and overrides
     //
diff --git a/qtikzgui/TikzScene.cpp b/qtikzgui/TikzScene.cpp
index 59aae4e..57153dd 100644
--- a/qtikzgui/TikzScene.cpp
+++ b/qtikzgui/TikzScene.cpp
@@ -191,7 +191,7 @@ void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
 
     const QRectF br(itemsBoundingRect());
     if (br.isValid()) {
-        setSceneRect(itemsBoundingRect());
+//         setSceneRect(itemsBoundingRect()); // FIXME: needed?
     } else {
         qWarning() << "TikzScene::mouseMoveEvent: invalid bounding rect, ignoring";
     }
diff --git a/qtikzgui/paths/AbstractTikzPath.cpp b/qtikzgui/paths/AbstractTikzPath.cpp
index 98c133e..66f8875 100644
--- a/qtikzgui/paths/AbstractTikzPath.cpp
+++ b/qtikzgui/paths/AbstractTikzPath.cpp
@@ -54,6 +54,11 @@ tikz::EdgeStyle* AbstractTikzPath::style() const
     return m_path->style();
 }
 
+QGraphicsScene * AbstractTikzPath::scene() const
+{
+    return m_path->scene();
+}
+
 void AbstractTikzPath::update()
 {
     m_path->update();
diff --git a/qtikzgui/paths/AbstractTikzPath.h b/qtikzgui/paths/AbstractTikzPath.h
index 6e94e0c..e26842a 100644
--- a/qtikzgui/paths/AbstractTikzPath.h
+++ b/qtikzgui/paths/AbstractTikzPath.h
@@ -33,6 +33,7 @@ namespace tikz {
 class QPainter;
 class QStyleOptionGraphicsItem;
 class QGraphicsSceneMouseEvent;
+class QGraphicsScene;
 
 class TikzDocument;
 class TikzPath;
@@ -75,6 +76,11 @@ class AbstractTikzPath : public QObject
 
     public:
         /**
+         * Get the graphics scene this item is associated with.
+         */
+        QGraphicsScene * scene() const;
+
+        /**
          * Request a repaint of this item.
          */
         void update();
diff --git a/qtikzgui/paths/PathHandle.cpp b/qtikzgui/paths/PathHandle.cpp
new file mode 100644
index 0000000..281995a
--- /dev/null
+++ b/qtikzgui/paths/PathHandle.cpp
@@ -0,0 +1,93 @@
+/* This file is part of the TikZKit project.
+ *
+ * Copyright (C) 2013 Dominik Haumann <dhaumann@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, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "PathHandle.h"
+#include "TikzPath.h"
+
+#include <QPainter>
+#include <QStyleOptionGraphicsItem>
+#include <QEvent>
+#include <QGraphicsSceneMouseEvent>
+
+#include <QDebug>
+
+PathHandle::PathHandle(TikzPath * path)
+    : TikzItem(path)
+{
+    // show above paths
+    setZValue(10.0);
+
+    setFlag(QGraphicsItem::ItemIsSelectable, true);
+}
+
+PathHandle::~PathHandle()
+{
+}
+
+int PathHandle::type() const
+{
+    return UserType + 5;
+}
+
+void PathHandle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    Q_UNUSED(widget);
+    Q_UNUSED(option);
+
+    // debugging
+//     painter->drawRect(boundingRect());
+
+    painter->save();
+    painter->setRenderHints(QPainter::Antialiasing);
+
+    painter->setPen(isHovered() || isSelected() ? Qt::green : Qt::blue);
+    painter->setBrush(isHovered() || isSelected() ? QColor(0, 255, 0, 125) : QColor(0, 0, 255, 125));
+    painter->drawEllipse(QPointF(0, 0), 0.2, 0.2);
+
+    painter->restore();
+}
+
+QRectF PathHandle::boundingRect() const
+{
+    return QRectF(-0.25, -0.25, 0.5, 0.5);
+}
+
+bool PathHandle::contains(const QPointF &point) const
+{
+    // within circle of 2.5 mm?
+    return (point.x() * point.x() + point.y() * point.y()) <= (0.25 * 0.25);
+}
+
+void PathHandle::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
+{
+    event->accept();
+    emit positionChanged(this, event->scenePos());
+}
+
+void PathHandle::mousePressEvent(QGraphicsSceneMouseEvent * event)
+{
+    event->accept();
+}
+
+void PathHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
+{
+    event->accept();
+}
+
+// kate: indent-width 4; replace-tabs on;
diff --git a/qtikzgui/paths/PathHandle.h b/qtikzgui/paths/PathHandle.h
new file mode 100644
index 0000000..44712b6
--- /dev/null
+++ b/qtikzgui/paths/PathHandle.h
@@ -0,0 +1,89 @@
+/* This file is part of the TikZKit project.
+ *
+ * Copyright (C) 2013 Dominik Haumann <dhaumann@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, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TIKZ_PATH_HANDLE_H
+#define TIKZ_PATH_HANDLE_H
+
+#include "tikzgui_export.h"
+#include "tikz.h"
+
+#include "TikzItem.h"
+
+class QPainter;
+class TikzPath;
+class PathHandlePrivate;
+
+class PathHandle : public TikzItem
+{
+    Q_OBJECT
+
+    public:
+        /**
+         * Constructor.
+         */
+        PathHandle(TikzPath * path = 0);
+
+        /**
+         * Destructor
+         */
+        virtual ~PathHandle();
+
+        /**
+         * Reimplment to return a proper UserType + 4.
+         */
+        int type() const override;
+
+    Q_SIGNALS:
+        /**
+         * This signal is emitted whenever the position of this handle
+         * changed through user interaction.
+         */
+        void positionChanged(PathHandle * handle, const QPointF & pos);
+
+    //
+    // reimplemented from QGraphicsItem
+    //
+    public:
+        /**
+         * Paint this item.
+         */
+        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+        /**
+         * Returns the bounding rect of this item.
+         */
+        QRectF boundingRect() const override;
+
+        /**
+         * Returns @p true, if @p point is contained in this handle.
+         */
+        bool contains(const QPointF &point) const override;
+
+    //
+    // protected overrides
+    //
+    protected:
+        virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
+        virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
+        virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event);
+};
+
+#endif // TIKZ_PATH_HANDLE_H
+
+// kate: indent-width 4; replace-tabs on;
diff --git a/qtikzgui/paths/ellipse/TikzEllipsePath.cpp b/qtikzgui/paths/ellipse/TikzEllipsePath.cpp
index ad74071..007752c 100644
--- a/qtikzgui/paths/ellipse/TikzEllipsePath.cpp
+++ b/qtikzgui/paths/ellipse/TikzEllipsePath.cpp
@@ -25,6 +25,7 @@
 #include "TikzNode.h"
 #include "TikzDocument.h"
 #include "EdgeStyle.h"
+#include "PathHandle.h"
 
 #include <QPainter>
 #include <QGraphicsScene>
@@ -37,6 +38,16 @@
 TikzEllipsePath::TikzEllipsePath(TikzPath * path)
     : AbstractTikzPath(path)
 {
+    m_topLeft = 0;
+    m_top = 0;
+    m_topRight = 0;
+    m_left = 0;
+    m_center = 0;
+    m_right = 0;
+    m_bottomLeft = 0;
+    m_bottom = 0;
+    m_bottomRight = 0;
+
     // FIXME: some sort of init needed?
 //     init();
 
@@ -46,6 +57,7 @@ TikzEllipsePath::TikzEllipsePath(TikzPath * path)
             this, SLOT(updateNode(tikz::Node*)));
 
     connect(path->path(), SIGNAL(changed()), this, SLOT(slotUpdate()));
+    connect(path, SIGNAL(itemSelected(bool)), this, SLOT(setShowHandles(bool)));
 }
 
 TikzEllipsePath::~TikzEllipsePath()
@@ -103,6 +115,8 @@ void TikzEllipsePath::slotUpdate()
     path()->prepareGeometryChange();
 
     m_dirty = true;
+
+    updateHandlePositions();
 }
 
 void TikzEllipsePath::paint(QPainter *painter,
@@ -133,8 +147,6 @@ void TikzEllipsePath::paint(QPainter *painter,
         painter->setPen(p);
         painter->drawPath(m_ellipse);
     }
-
-    painter->restore();
 }
 
 QRectF TikzEllipsePath::boundingRect() const
@@ -158,16 +170,18 @@ bool TikzEllipsePath::contains(const QPointF & point) const
     const_cast<TikzEllipsePath*>(this)->updateCache();
 
     // contains depends on the type of fill color/brush
-    if (style()->fillColor() == Qt::transparent) {
-        return m_hoverPath.contains(point);
-    } else {
+//     if (style()->fillColor() == Qt::transparent) {
+//         return m_hoverPath.contains(point);
+//     } else {
         return m_ellipse.contains(point)
             || m_hoverPath.contains(point);
-    }
+//     }
 }
 
 void TikzEllipsePath::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
 {
+    ellipsePath()->setPos(event->scenePos());
+    updateHandlePositions();
 //     if (!d->dragging) {
 //         event->ignore();
 //         TikzItem::mouseMoveEvent(event);
@@ -224,6 +238,10 @@ void TikzEllipsePath::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
 
 void TikzEllipsePath::mousePressEvent(QGraphicsSceneMouseEvent * event)
 {
+    qDebug() << "Path selected" << path()->isSelected();
+    if (path()->isSelected()) {
+        updateHandlePositions();
+    }
     /*if (!contains(event->pos()) || !isSelected()) {
         TikzItem::mousePressEvent(event);
     } else*/ {
@@ -300,4 +318,101 @@ tikz::EllipsePath * TikzEllipsePath::ellipsePath() const
     return p;
 }
 
+void TikzEllipsePath::setShowHandles(bool show)
+{
+    // handles already visible?
+    if (show && m_topLeft != nullptr) {
+        return;
+    }
+
+    // delete handles, if hide
+    if (!show && m_topLeft != nullptr) {
+        delete m_topLeft;
+        delete m_top;
+        delete m_topRight;
+        delete m_left;
+        delete m_center;
+        delete m_right;
+        delete m_bottomLeft;
+        delete m_bottom;
+        delete m_bottomRight;
+
+        m_topLeft = 0;
+        m_top = 0;
+        m_topRight = 0;
+        m_left = 0;
+        m_center = 0;
+        m_right = 0;
+        m_bottomLeft = 0;
+        m_bottom = 0;
+        m_bottomRight = 0;
+
+        return;
+    }
+
+    m_topLeft = new PathHandle();
+    m_top = new PathHandle();
+    m_topRight = new PathHandle();
+    m_left = new PathHandle();
+    m_center = new PathHandle();
+    m_right = new PathHandle();
+    m_bottomLeft = new PathHandle();
+    m_bottom = new PathHandle();
+    m_bottomRight = new PathHandle();
+
+    QGraphicsScene * s = scene();
+    s->addItem(m_topLeft);
+    s->addItem(m_top);
+    s->addItem(m_topRight);
+    s->addItem(m_left);
+    s->addItem(m_center);
+    s->addItem(m_right);
+    s->addItem(m_bottomLeft);
+    s->addItem(m_bottom);
+    s->addItem(m_bottomRight);
+
+    updateHandlePositions();
+
+    m_topLeft->show();
+    m_top->show();
+    m_topRight->show();
+    m_left->show();
+    m_center->show();
+    m_right->show();
+    m_bottomLeft->show();
+    m_bottom->show();
+    m_bottomRight->show();
+    connect(m_topLeft, SIGNAL(positionChanged(PathHandle *, const QPointF &)),
+            this, SLOT(handleMoved(PathHandle *, const QPointF &)));
+}
+
+void TikzEllipsePath::updateHandlePositions()
+{
+    if (!m_topLeft) return;
+
+    const qreal rx = style()->radiusX();
+    const qreal ry = style()->radiusY();
+
+    m_topLeft->setPos(ellipsePath()->pos() + QPointF(-rx, ry));
+    m_top->setPos(ellipsePath()->pos() + QPointF(0, ry));
+    m_topRight->setPos(ellipsePath()->pos() + QPointF(rx, ry));
+    m_left->setPos(ellipsePath()->pos() + QPointF(-rx, 0));
+    m_center->setPos(ellipsePath()->pos() + QPointF(0, 0));
+    m_right->setPos(ellipsePath()->pos() + QPointF(rx, 0));
+    m_bottomLeft->setPos(ellipsePath()->pos() + QPointF(-rx, -ry));
+    m_bottom->setPos(ellipsePath()->pos() + QPointF(0, -ry));
+    m_bottomRight->setPos(ellipsePath()->pos() + QPointF(rx, -ry));
+}
+
+void TikzEllipsePath::handleMoved(PathHandle * handle, const QPointF & pos)
+{
+    const QPointF center = ellipsePath()->pos();
+    const qreal dx = qAbs(center.x() - pos.x());
+    const qreal dy = qAbs(center.y() - pos.y());
+
+    qDebug() << "updating: " << dx << dy;
+    style()->setRadiusX(dx);
+    style()->setRadiusY(dy);
+}
+
 // kate: indent-width 4; replace-tabs on;
diff --git a/qtikzgui/paths/ellipse/TikzEllipsePath.h b/qtikzgui/paths/ellipse/TikzEllipsePath.h
index 3ece25c..32e788d 100644
--- a/qtikzgui/paths/ellipse/TikzEllipsePath.h
+++ b/qtikzgui/paths/ellipse/TikzEllipsePath.h
@@ -32,7 +32,7 @@ namespace tikz {
 
 class QPainter;
 
-class CurveHandle;
+class PathHandle;
 class TikzDocument;
 class TikzNode;
 class TikzPath;
@@ -138,13 +138,31 @@ class TikzEllipsePath : public AbstractTikzPath
          */
         void updateNode(tikz::Node * node);
 
-    private:
+    private Q_SLOTS:
         /**
          * Updates the cache of the ellipse.
          */
         void updateCache();
 
         /**
+         * Show / hide resize, move and rotate handles according to @p show.
+         */
+        void setShowHandles(bool show);
+
+        /**
+         * set the handle positions.
+         */
+        void updateHandlePositions();
+
+        /**
+         * This slot is called whenever a handle moved.
+         * The ellipse then is either moved, resized or rotated according to
+         * the sender @p handle.
+         */
+        void handleMoved(PathHandle * handle, const QPointF & pos);
+
+    private:
+        /**
          * Returns the tikz::Path object, casted to tikz::EllipsePath
          */
         tikz::EllipsePath * ellipsePath() const;
@@ -171,15 +189,15 @@ class TikzEllipsePath : public AbstractTikzPath
         QRectF m_boundingRect;
 
     private:
-        CurveHandle * m_topLeft;
-        CurveHandle * m_top;
-        CurveHandle * m_topRight;
-        CurveHandle * m_left;
-        CurveHandle * m_center;
-        CurveHandle * m_right;
-        CurveHandle * m_bottomLeft;
-        CurveHandle * m_bottom;
-        CurveHandle * m_bottomRight;
+        PathHandle * m_topLeft;
+        PathHandle * m_top;
+        PathHandle * m_topRight;
+        PathHandle * m_left;
+        PathHandle * m_center;
+        PathHandle * m_right;
+        PathHandle * m_bottomLeft;
+        PathHandle * m_bottom;
+        PathHandle * m_bottomRight;
 };
 
 #endif // GUI_TIKZ_ELLIPSE_PATH_H
[prev in list] [next in list] [prev in thread] [next in thread] 

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