File indexing completed on 2024-05-12 16:30:49
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2008,2010 Jan Hambrecht <jaham@gmx.net> 0003 * Copyright (C) 2010 Boudewijn Rempt <boud@kogmbh.com> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (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 GNU 0013 * 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, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KarbonZoomController.h" 0022 0023 #include <KarbonCanvas.h> 0024 #include <KoZoomAction.h> 0025 #include <KoCanvasController.h> 0026 #include <KoCanvasBase.h> 0027 #include <KoZoomHandler.h> 0028 #include <KoCanvasResourceManager.h> 0029 #include <KoShapeManager.h> 0030 #include <KoSelection.h> 0031 0032 #include <kactioncollection.h> 0033 #include <klocalizedstring.h> 0034 0035 #include <math.h> 0036 0037 class KarbonZoomController::Private 0038 { 0039 public: 0040 Private() 0041 : canvasController(0), canvas(0), zoomHandler(0), action(0) 0042 , fitMargin(25) 0043 { 0044 } 0045 0046 ~Private() 0047 { 0048 delete action; 0049 } 0050 0051 KoCanvasController * canvasController; 0052 KarbonCanvas * canvas; 0053 KoZoomHandler * zoomHandler; 0054 KoZoomAction * action; 0055 QSizeF pageSize; 0056 int fitMargin; 0057 }; 0058 0059 KarbonZoomController::KarbonZoomController(KoCanvasController *controller, KActionCollection *actionCollection, QObject *parent) 0060 : QObject(parent), d(new Private()) 0061 { 0062 d->canvasController = controller; 0063 0064 d->action = new KoZoomAction(KoZoomMode::ZOOM_WIDTH | KoZoomMode::ZOOM_PAGE, i18n("Zoom"), this); 0065 d->action->setSpecialButtons(KoZoomAction::ZoomToSelection | KoZoomAction::ZoomToAll); 0066 connect(d->action, SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)), 0067 this, SLOT(setZoom(KoZoomMode::Mode,qreal))); 0068 connect(d->action, SIGNAL(zoomedToSelection()), 0069 this, SIGNAL(zoomedToSelection())); 0070 connect(d->action, SIGNAL(zoomedToAll()), 0071 this, SIGNAL(zoomedToAll())); 0072 0073 actionCollection->addAction("view_zoom", d->action); 0074 actionCollection->addAction(KStandardAction::ZoomIn, "zoom_in", this, SLOT(zoomInRelative())); 0075 actionCollection->addAction(KStandardAction::ZoomOut, "zoom_out", this, SLOT(zoomOutRelative())); 0076 0077 d->canvas = dynamic_cast<KarbonCanvas*>(d->canvasController->canvas()); 0078 d->zoomHandler = dynamic_cast<KoZoomHandler*>(const_cast<KoViewConverter*>(d->canvas->viewConverter())); 0079 0080 connect(d->canvasController->proxyObject, SIGNAL(sizeChanged(QSize)), this, SLOT(setAvailableSize())); 0081 connect(d->canvasController->proxyObject, SIGNAL(zoomRelative(qreal,QPointF)), this, SLOT(requestZoomRelative(qreal,QPointF))); 0082 connect(d->canvasController->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), 0083 d->canvas, SLOT(setDocumentOffset(QPoint))); 0084 0085 connect(d->canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), 0086 this, SLOT(canvasResourceChanged(int,QVariant))); 0087 } 0088 0089 KarbonZoomController::~KarbonZoomController() 0090 { 0091 delete d; 0092 } 0093 0094 KoZoomAction * KarbonZoomController::zoomAction() const 0095 { 0096 return d->action; 0097 } 0098 0099 void KarbonZoomController::setZoomMode(KoZoomMode::Mode mode) 0100 { 0101 setZoom(mode, 1.0); 0102 } 0103 0104 void KarbonZoomController::setZoom(KoZoomMode::Mode mode, qreal zoom) 0105 { 0106 setZoom(mode, zoom, d->canvasController->preferredCenter()); 0107 } 0108 0109 void KarbonZoomController::setZoom(KoZoomMode::Mode mode, qreal zoom, const QPointF &stillPoint) 0110 { 0111 if (d->zoomHandler->zoomMode() == mode && d->zoomHandler->zoom() == zoom) 0112 return; // no change 0113 0114 qreal oldEffectiveZoom = d->action->effectiveZoom(); 0115 0116 d->zoomHandler->setZoomMode(mode); 0117 0118 if (mode == KoZoomMode::ZOOM_CONSTANT) { 0119 if (zoom == 0.0) return; 0120 d->action->setZoom(zoom); 0121 } else if (mode == KoZoomMode::ZOOM_WIDTH) { 0122 zoom = (d->canvasController->viewportSize().width() - 2 * d->fitMargin) 0123 / (d->zoomHandler->resolutionX() * d->pageSize.width()); 0124 d->action->setSelectedZoomMode(mode); 0125 d->action->setEffectiveZoom(zoom); 0126 } else if (mode == KoZoomMode::ZOOM_PAGE) { 0127 zoom = (d->canvasController->viewportSize().width() - 2 * d->fitMargin) 0128 / (d->zoomHandler->resolutionX() * d->pageSize.width()); 0129 zoom = qMin(zoom, (d->canvasController->viewportSize().height() - 2 * d->fitMargin) 0130 / (d->zoomHandler->resolutionY() * d->pageSize.height())); 0131 0132 d->action->setSelectedZoomMode(mode); 0133 d->action->setEffectiveZoom(zoom); 0134 } 0135 0136 d->zoomHandler->setZoom(zoom); 0137 0138 // Tell the canvasController that the zoom has changed 0139 // Actually canvasController doesn't know about zoom, but the document in pixels 0140 // has change as a result of the zoom change 0141 QRectF documentRect = d->canvas->documentViewRect(); 0142 QSizeF viewSize = d->zoomHandler->documentToView(documentRect).size(); 0143 d->canvasController->updateDocumentSize(QSize(qRound(viewSize.width()), qRound(viewSize.height())), true); 0144 0145 d->canvas->adjustOrigin(); 0146 0147 // Finally ask the canvasController to recenter 0148 QPointF documentCenter; 0149 if (mode == KoZoomMode::ZOOM_CONSTANT) { 0150 KoSelection * selection = d->canvas->shapeManager()->selection(); 0151 if (selection->count()) { 0152 QPointF docCenter = selection->boundingRect().center(); 0153 documentCenter = d->canvas->documentOrigin() + d->zoomHandler->documentToView(docCenter); 0154 } else { 0155 qreal zoomCoeff = d->action->effectiveZoom() / oldEffectiveZoom; 0156 QPointF oldCenter = d->canvasController->preferredCenter(); 0157 documentCenter = stillPoint * zoomCoeff - (stillPoint - 1.0 / zoomCoeff * oldCenter); 0158 } 0159 } else { 0160 // center the page rect when change the zoom mode to ZOOM_PAGE or ZOOM_WIDTH 0161 QRectF pageRect(-documentRect.topLeft(), d->pageSize); 0162 documentCenter = d->zoomHandler->documentToView(pageRect.center()); 0163 } 0164 d->canvasController->setPreferredCenter(documentCenter); 0165 d->canvas->update(); 0166 } 0167 0168 void KarbonZoomController::setAvailableSize() 0169 { 0170 if (d->zoomHandler->zoomMode() == KoZoomMode::ZOOM_WIDTH) 0171 setZoom(KoZoomMode::ZOOM_WIDTH, -1); 0172 if (d->zoomHandler->zoomMode() == KoZoomMode::ZOOM_PAGE) 0173 setZoom(KoZoomMode::ZOOM_PAGE, -1); 0174 } 0175 0176 void KarbonZoomController::requestZoomRelative(const qreal factor, const QPointF &stillPoint) 0177 { 0178 qreal zoom = d->zoomHandler->zoom(); 0179 setZoom(KoZoomMode::ZOOM_CONSTANT, factor*zoom, stillPoint); 0180 } 0181 0182 void KarbonZoomController::requestZoomBy(const qreal factor) 0183 { 0184 qreal zoom = d->zoomHandler->zoom(); 0185 setZoom(KoZoomMode::ZOOM_CONSTANT, factor*zoom); 0186 } 0187 0188 void KarbonZoomController::setPageSize(const QSizeF &pageSize) 0189 { 0190 if (d->pageSize == pageSize) 0191 return; 0192 d->pageSize = pageSize; 0193 0194 if (d->zoomHandler->zoomMode() == KoZoomMode::ZOOM_WIDTH) 0195 setZoom(KoZoomMode::ZOOM_WIDTH, -1); 0196 if (d->zoomHandler->zoomMode() == KoZoomMode::ZOOM_PAGE) 0197 setZoom(KoZoomMode::ZOOM_PAGE, -1); 0198 } 0199 0200 void KarbonZoomController::canvasResourceChanged(int key, const QVariant &value) 0201 { 0202 if (key == KoCanvasResourceManager::PageSize) { 0203 setPageSize(value.toSizeF()); 0204 0205 // Tell the canvasController that the document in pixels 0206 // has changed as a result of the page layout change 0207 QRectF documentRect = d->canvas->documentViewRect(); 0208 QSizeF viewSize = d->zoomHandler->documentToView(documentRect).size(); 0209 d->canvasController->updateDocumentSize(QSize(qRound(viewSize.width()), qRound(viewSize.height())), true); 0210 d->canvas->adjustOrigin(); 0211 d->canvas->update(); 0212 } 0213 } 0214 0215 void KarbonZoomController::zoomInRelative() 0216 { 0217 requestZoomBy(sqrt(2.0)); 0218 0219 } 0220 0221 void KarbonZoomController::zoomOutRelative() 0222 { 0223 requestZoomBy(sqrt(0.5)); 0224 } 0225