File indexing completed on 2024-05-19 04:36:38

0001 /* This file is part of the TikZKit project.
0002  *
0003  * Copyright (C) 2014 Dominik Haumann <dhaumann@kde.org>
0004  *
0005  * This library is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU Library General Public License as published
0007  * by the Free Software Foundation, either version 2 of the License, or
0008  * (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  * GNU Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, see
0017  * <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "AnchorManager.h"
0021 #include <NodeItem.h>
0022 #include <AnchorHandle.h>
0023 
0024 #include <QDebug>
0025 #include <QGraphicsScene>
0026 #include <QGraphicsView>
0027 
0028 #include "DocumentPrivate.h"
0029 
0030 namespace tikz {
0031 namespace ui {
0032 
0033 AnchorManager::AnchorManager(QGraphicsScene * scene, tikz::ui::DocumentPrivate * doc, QObject * parent)
0034     : QObject(parent)
0035     , m_doc(doc)
0036     , m_scene(scene)
0037 {
0038 }
0039 
0040 AnchorManager::~AnchorManager()
0041 {
0042     clear();
0043 }
0044 
0045 QGraphicsScene * AnchorManager::scene() const
0046 {
0047     return m_scene;
0048 }
0049 
0050 void AnchorManager::clear()
0051 {
0052     // just remove all anchors
0053     for (NodeItem * node : qAsConst(m_nodes)) {
0054         Q_ASSERT(m_handleMap.contains(node));
0055         qDeleteAll(m_handleMap[node]);
0056         m_handleMap.remove(node);
0057     }
0058 
0059     // now the handle map should be empty
0060     Q_ASSERT(m_handleMap.size() == 0);
0061 
0062     // clear all lists
0063     m_nodes.clear();
0064     m_handleMap.clear();
0065 }
0066 
0067 void AnchorManager::hideAnchors()
0068 {
0069     for (NodeItem * node : qAsConst(m_nodes)) {
0070         Q_ASSERT(m_handleMap.contains(node));
0071         for (AnchorHandle * handle : qAsConst(m_handleMap[node])) {
0072             handle->hide();
0073         }
0074     }
0075 }
0076 
0077 void AnchorManager::showAnchors()
0078 {
0079     for (NodeItem * node : qAsConst(m_nodes)) {
0080         Q_ASSERT(m_handleMap.contains(node));
0081         for (AnchorHandle * handle : qAsConst(m_handleMap[node])) {
0082             handle->show();
0083         }
0084     }
0085 }
0086 
0087 template <class T>
0088 static T *first(const QList<QGraphicsItem *> &items)
0089 {
0090     for (QGraphicsItem *item : items) {
0091         if (T * t = dynamic_cast<T*>(item)) {
0092             return t;
0093         }
0094     }
0095     return nullptr;
0096 }
0097 
0098 void AnchorManager::addAllNodes()
0099 {
0100     for (NodeItem * node : m_doc->nodeItems()) {
0101         addNode(node);
0102     }
0103 }
0104 
0105 void AnchorManager::addNode(NodeItem * node)
0106 {
0107     if (m_nodes.contains(node)) {
0108         return;
0109     }
0110 
0111     // register node
0112     m_nodes.append(node);
0113 
0114     // creade and add anchors to scene
0115     for (const QString & anchor : node->supportedAnchors()) {
0116         AnchorHandle * handle = new AnchorHandle(node, anchor);
0117         m_handleMap[node].append(handle);
0118         scene()->addItem(handle);
0119     }
0120 }
0121 
0122 void AnchorManager::removeNode(NodeItem * node)
0123 {
0124     const int index = m_nodes.indexOf(node);
0125     if (index < 0) {
0126         Q_ASSERT(false); // for now, be pedantic
0127         return;
0128     }
0129 
0130     // should be in the handle map
0131     Q_ASSERT(m_handleMap.contains(node));
0132 
0133     // remove handles and unregister node
0134     qDeleteAll(m_handleMap[node]);
0135     m_handleMap.remove(node);
0136     m_nodes.remove(index);
0137 }
0138 
0139 void AnchorManager::nodeDestroyed(QObject * obj)
0140 {
0141     // find deleted Node
0142     for (int i = 0; i < m_nodes.size(); ++i) {
0143         NodeItem * node = m_nodes[i];
0144         if (static_cast<QObject *>(node) == obj) {
0145             removeNode(node);
0146             return;
0147         }
0148     }
0149 
0150     // should never happen for now
0151     Q_ASSERT(false);
0152 }
0153 
0154 tikz::core::MetaPos AnchorManager::anchorAt(const QPointF & scenePos, QGraphicsView * view)
0155 {
0156     tikz::core::MetaPos metaPos(m_doc);
0157     metaPos.setPos(scenePos);
0158 
0159     if (view) {
0160         const QPoint p = view->viewportTransform().map(scenePos).toPoint();
0161         const QList<QGraphicsItem *> items = view->items(p);
0162         AnchorHandle * handle = first<AnchorHandle>(items);
0163         if (handle &&
0164             handle->contains(handle->mapFromScene(scenePos)))
0165         {
0166             metaPos = handle->metaPos();
0167         }
0168     }
0169 
0170     return metaPos;
0171 }
0172 
0173 }
0174 }
0175 
0176 // kate: indent-width 4; replace-tabs on;