Warning, file /office/calligra/libs/flake/KoSnapGuide.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2008-2009 Jan Hambrecht <jaham@gmx.net> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Library General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Library General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Library General Public License 0015 * along with this library; see the file COPYING.LIB. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KoSnapGuide.h" 0021 #include "KoSnapProxy.h" 0022 #include "KoSnapStrategy.h" 0023 0024 #include <KoPathShape.h> 0025 #include <KoPathPoint.h> 0026 #include <KoViewConverter.h> 0027 #include <KoCanvasBase.h> 0028 0029 #include <QPainter> 0030 #include <QPainterPath> 0031 0032 #include <math.h> 0033 0034 0035 class Q_DECL_HIDDEN KoSnapGuide::Private 0036 { 0037 public: 0038 Private(KoCanvasBase *parentCanvas) 0039 : canvas(parentCanvas), editedShape(0), currentStrategy(0), 0040 active(true), 0041 snapDistance(10) 0042 { 0043 } 0044 0045 ~Private() 0046 { 0047 qDeleteAll(strategies); 0048 strategies.clear(); 0049 } 0050 0051 KoCanvasBase *canvas; 0052 KoShape *editedShape; 0053 0054 QList<KoSnapStrategy*> strategies; 0055 KoSnapStrategy *currentStrategy; 0056 0057 KoSnapGuide::Strategies usedStrategies; 0058 bool active; 0059 int snapDistance; 0060 QList<KoPathPoint*> ignoredPoints; 0061 QList<KoShape*> ignoredShapes; 0062 }; 0063 0064 KoSnapGuide::KoSnapGuide(KoCanvasBase *canvas) 0065 : d(new Private(canvas)) 0066 { 0067 d->strategies.append(new GridSnapStrategy()); 0068 d->strategies.append(new NodeSnapStrategy()); 0069 d->strategies.append(new OrthogonalSnapStrategy()); 0070 d->strategies.append(new ExtensionSnapStrategy()); 0071 d->strategies.append(new IntersectionSnapStrategy()); 0072 d->strategies.append(new BoundingBoxSnapStrategy()); 0073 d->strategies.append(new LineGuideSnapStrategy()); 0074 } 0075 0076 KoSnapGuide::~KoSnapGuide() 0077 { 0078 delete d; 0079 } 0080 0081 void KoSnapGuide::setEditedShape(KoShape *shape) 0082 { 0083 d->editedShape = shape; 0084 } 0085 0086 KoShape *KoSnapGuide::editedShape() const 0087 { 0088 return d->editedShape; 0089 } 0090 0091 void KoSnapGuide::enableSnapStrategies(Strategies strategies) 0092 { 0093 d->usedStrategies = strategies; 0094 } 0095 0096 KoSnapGuide::Strategies KoSnapGuide::enabledSnapStrategies() const 0097 { 0098 return d->usedStrategies; 0099 } 0100 0101 bool KoSnapGuide::addCustomSnapStrategy(KoSnapStrategy *customStrategy) 0102 { 0103 if (!customStrategy || customStrategy->type() != CustomSnapping) 0104 return false; 0105 0106 d->strategies.append(customStrategy); 0107 return true; 0108 } 0109 0110 void KoSnapGuide::enableSnapping(bool on) 0111 { 0112 d->active = on; 0113 } 0114 0115 bool KoSnapGuide::isSnapping() const 0116 { 0117 return d->active; 0118 } 0119 0120 void KoSnapGuide::setSnapDistance(int distance) 0121 { 0122 d->snapDistance = qAbs(distance); 0123 } 0124 0125 int KoSnapGuide::snapDistance() const 0126 { 0127 return d->snapDistance; 0128 } 0129 0130 QPointF KoSnapGuide::snap(const QPointF &mousePosition, Qt::KeyboardModifiers modifiers) 0131 { 0132 d->currentStrategy = 0; 0133 0134 if (! d->active || (modifiers & Qt::ShiftModifier)) 0135 return mousePosition; 0136 0137 KoSnapProxy proxy(this); 0138 0139 qreal minDistance = HUGE_VAL; 0140 0141 qreal maxSnapDistance = d->canvas->viewConverter()->viewToDocument(QSizeF(d->snapDistance, 0142 d->snapDistance)).width(); 0143 0144 foreach (KoSnapStrategy *strategy, d->strategies) { 0145 if (d->usedStrategies & strategy->type() 0146 || strategy->type() == GridSnapping || strategy->type() == CustomSnapping) { 0147 if (! strategy->snap(mousePosition, &proxy, maxSnapDistance)) 0148 continue; 0149 0150 QPointF snapCandidate = strategy->snappedPosition(); 0151 qreal distance = KoSnapStrategy::squareDistance(snapCandidate, mousePosition); 0152 if (distance < minDistance) { 0153 d->currentStrategy = strategy; 0154 minDistance = distance; 0155 } 0156 } 0157 } 0158 0159 if (! d->currentStrategy) 0160 return mousePosition; 0161 0162 return d->currentStrategy->snappedPosition(); 0163 } 0164 0165 QRectF KoSnapGuide::boundingRect() const 0166 { 0167 QRectF rect; 0168 0169 if (d->currentStrategy) { 0170 rect = d->currentStrategy->decoration(*d->canvas->viewConverter()).boundingRect(); 0171 return rect.adjusted(-2, -2, 2, 2); 0172 } else { 0173 return rect; 0174 } 0175 } 0176 0177 void KoSnapGuide::paint(QPainter &painter, const KoViewConverter &converter) 0178 { 0179 if (! d->currentStrategy || ! d->active) 0180 return; 0181 0182 QPainterPath decoration = d->currentStrategy->decoration(converter); 0183 0184 painter.setBrush(Qt::NoBrush); 0185 0186 QPen whitePen(Qt::white, 0); 0187 whitePen.setStyle(Qt::SolidLine); 0188 painter.setPen(whitePen); 0189 painter.drawPath(decoration); 0190 0191 QPen redPen(Qt::red, 0); 0192 redPen.setStyle(Qt::DotLine); 0193 painter.setPen(redPen); 0194 painter.drawPath(decoration); 0195 } 0196 0197 KoCanvasBase *KoSnapGuide::canvas() const 0198 { 0199 return d->canvas; 0200 } 0201 0202 void KoSnapGuide::setIgnoredPathPoints(const QList<KoPathPoint*> &ignoredPoints) 0203 { 0204 d->ignoredPoints = ignoredPoints; 0205 } 0206 0207 QList<KoPathPoint*> KoSnapGuide::ignoredPathPoints() const 0208 { 0209 return d->ignoredPoints; 0210 } 0211 0212 void KoSnapGuide::setIgnoredShapes(const QList<KoShape*> &ignoredShapes) 0213 { 0214 d->ignoredShapes = ignoredShapes; 0215 } 0216 0217 QList<KoShape*> KoSnapGuide::ignoredShapes() const 0218 { 0219 return d->ignoredShapes; 0220 } 0221 0222 void KoSnapGuide::reset() 0223 { 0224 d->currentStrategy = 0; 0225 d->editedShape = 0; 0226 d->ignoredPoints.clear(); 0227 d->ignoredShapes.clear(); 0228 // remove all custom strategies 0229 int strategyCount = d->strategies.count(); 0230 for (int i = strategyCount-1; i >= 0; --i) { 0231 if (d->strategies[i]->type() == CustomSnapping) { 0232 delete d->strategies[i]; 0233 d->strategies.removeAt(i); 0234 } 0235 } 0236 } 0237