File indexing completed on 2024-04-28 04:20:27
0001 /* 0002 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0003 All rights reserved. 0004 0005 Redistribution and use in source and binary forms, with or without 0006 modification, are permitted provided that the following conditions 0007 are met: 0008 0009 1. Redistributions of source code must retain the above copyright 0010 notice, this list of conditions and the following disclaimer. 0011 2. Redistributions in binary form must reproduce the above copyright 0012 notice, this list of conditions and the following disclaimer in the 0013 documentation and/or other materials provided with the distribution. 0014 0015 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0016 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0017 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0018 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0019 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0020 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0022 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0024 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 0027 0028 #define DEBUG_KP_TOOL_ZOOM 0 0029 0030 0031 #include "kpToolZoom.h" 0032 0033 #include "kpDefs.h" 0034 #include "document/kpDocument.h" 0035 #include "pixmapfx/kpPixmapFX.h" 0036 #include "generic/kpSetOverrideCursorSaver.h" 0037 #include "layers/tempImage/kpTempImage.h" 0038 #include "environments/tools/kpToolEnvironment.h" 0039 #include "views/manager/kpViewManager.h" 0040 #include "kpLogCategories.h" 0041 0042 #include <KLocalizedString> 0043 #include <KToggleAction> 0044 0045 #include <QIcon> 0046 #include <QWidget> 0047 0048 //--------------------------------------------------------------------- 0049 0050 struct DrawZoomRectPackage 0051 { 0052 QRect normalizedRect; 0053 }; 0054 0055 static void DrawZoomRect (kpImage *destImage, 0056 const QPoint &topLeft, 0057 void *userData) 0058 { 0059 auto *pack = static_cast <DrawZoomRectPackage *> (userData); 0060 0061 kpPixmapFX::drawStippleRect(destImage, 0062 topLeft.x (), topLeft.y (), pack->normalizedRect.width (), pack->normalizedRect.height (), 0063 kpColor::Yellow, 0064 kpColor::Green); 0065 } 0066 0067 0068 struct kpToolZoomPrivate 0069 { 0070 bool dragHasBegun{}, dragCompleted{}; 0071 DrawZoomRectPackage drawPackage; 0072 }; 0073 0074 kpToolZoom::kpToolZoom (kpToolEnvironment *environ, QWidget *parent) 0075 : kpTool (i18n ("Zoom"), i18n ("Zooms in and out of the image"), 0076 Qt::Key_Z, 0077 environ, parent, QStringLiteral("tool_zoom")), 0078 d (new kpToolZoomPrivate ()) 0079 { 0080 // different from objectName() 0081 action()->setIcon(QIcon::fromTheme(QStringLiteral("zoom-original"))); 0082 } 0083 0084 //--------------------------------------------------------------------- 0085 0086 kpToolZoom::~kpToolZoom () 0087 { 0088 delete d; 0089 } 0090 0091 //--------------------------------------------------------------------- 0092 // public virtual [base kpTool] 0093 0094 bool kpToolZoom::returnToPreviousToolAfterEndDraw () const 0095 { 0096 // If the user clicks to zoom in or out, s/he generally wants to click 0097 // some more to get the exact zoom level wanted. 0098 // 0099 // However, if they drag out a rectangle to zoom into a particular area, 0100 // they probably don't need to do any further zooming so we can return 0101 // them to their previous tool. 0102 // 0103 // Note that if they cancel a drag (cancelShape()), we do _not_ return 0104 // them to their previous tool, unlike the Color Picker. This is because 0105 // cancelling a drag generally means that the user got the top-left of 0106 // the drag wrong and wants to try a different top-left. In contrast, 0107 // with the Color Picket, if you've made a mistake while pressing the 0108 // mouse, you can just keep holding down the mouse and drag to the intended 0109 // color -- a cancel with a Color Picker really means "I've decided not 0110 // to pick another color after all", not "I got the start of the drag wrong" 0111 // because you can correct that drag. 0112 return d->dragCompleted; 0113 } 0114 0115 0116 // private 0117 QString kpToolZoom::haventBegunDrawUserMessage () const 0118 { 0119 return i18n ("Click to zoom in/out or left drag to zoom into a specific area."); 0120 } 0121 0122 0123 // public virtual [base kpTool] 0124 void kpToolZoom::begin () 0125 { 0126 viewManager ()->setCursor (Qt::CrossCursor); 0127 0128 setUserMessage (haventBegunDrawUserMessage ()); 0129 } 0130 0131 // public virtual [base kpTool] 0132 void kpToolZoom::end () 0133 { 0134 viewManager ()->unsetCursor (); 0135 } 0136 0137 0138 // public virtual [base kpTool] 0139 void kpToolZoom::globalDraw () 0140 { 0141 #if DEBUG_KP_TOOL_ZOOM 0142 qCDebug(kpLogTools) << "CALL"; 0143 #endif 0144 environ ()->fitToPage (); 0145 } 0146 0147 0148 // public virtual [base kpTool] 0149 void kpToolZoom::beginDraw () 0150 { 0151 d->dragHasBegun = false; 0152 d->dragCompleted = false; 0153 0154 setUserMessage (cancelUserMessage ()); 0155 } 0156 0157 // public virtual [base kpTool] 0158 void kpToolZoom::draw (const QPoint &thisPoint, const QPoint &, const QRect &normalizedRect) 0159 { 0160 #if DEBUG_KP_TOOL_ZOOM 0161 qCDebug(kpLogTools) << "kpToomZoom::draw() currentPoint=" << currentPoint () 0162 << " lastPoint=" << lastPoint () 0163 << endl; 0164 #endif 0165 0166 // TODO: Need accidental drag detection from selection tool (when dragging 0167 // out new selection) 0168 0169 if (!d->dragHasBegun) 0170 { 0171 if (thisPoint == startPoint ()) { 0172 return; 0173 } 0174 0175 // Left mouse drags select an area to zoom into. 0176 // However, it wouldn't make sense to select an area to "zoom out of" 0177 // (using the right mouse button). Therefore, make RMB drags do the 0178 // same as RMB clicks i.e. a simple zoom out, with no "area" to worry 0179 // about. 0180 if (mouseButton () == 1/*RMB*/) { 0181 return; 0182 } 0183 0184 d->dragHasBegun = true; 0185 } 0186 0187 0188 d->drawPackage.normalizedRect = normalizedRect; 0189 0190 kpTempImage newTempImage (false/*always display*/, 0191 normalizedRect.topLeft (), 0192 &::DrawZoomRect, &d->drawPackage, 0193 normalizedRect.width (), normalizedRect.height ()); 0194 0195 viewManager ()->setFastUpdates (); 0196 { 0197 viewManager ()->setTempImage (newTempImage); 0198 } 0199 viewManager ()->restoreFastUpdates (); 0200 } 0201 0202 // public virtual [base kpTool] 0203 void kpToolZoom::cancelShape () 0204 { 0205 viewManager ()->invalidateTempImage (); 0206 0207 // LOREFACTOR: A lot of tools use this - push up to kpTool? 0208 setUserMessage (i18n ("Let go of all the mouse buttons.")); 0209 } 0210 0211 // public virtual [base kpTool] 0212 void kpToolZoom::releasedAllButtons () 0213 { 0214 setUserMessage (haventBegunDrawUserMessage ()); 0215 } 0216 0217 // public virtual [base kpTool] 0218 void kpToolZoom::endDraw (const QPoint &, const QRect &normalizedRect) 0219 { 0220 #if DEBUG_KP_TOOL_ZOOM 0221 qCDebug(kpLogTools) << "kpToolZoom::endDraw(rect=" << normalizedRect << ")" 0222 << " dragHasBegun=" << d->dragHasBegun << endl; 0223 #endif 0224 0225 // TODO: This cursor doesn't stay on for long enough because zooming uses 0226 // event loop tricks. 0227 kpSetOverrideCursorSaver cursorSaver (Qt::WaitCursor); 0228 0229 viewManager ()->invalidateTempImage (); 0230 0231 // Click? 0232 if (!d->dragHasBegun) 0233 { 0234 if (mouseButton () == 0/*LMB*/) { 0235 environ ()->zoomIn (true/*center under cursor*/); 0236 } 0237 else { 0238 environ ()->zoomOut (false/*don't center under cursor - as is 0239 confusing behaviour when zooming 0240 out*/); 0241 } 0242 } 0243 // Drag? 0244 else if (normalizedRect.isValid()) 0245 { 0246 environ ()->zoomToRect ( 0247 normalizedRect, 0248 false/*don't account for grips*/, 0249 true/*care about width*/, true/*care about height*/); 0250 0251 d->dragCompleted = true; 0252 } 0253 } 0254 0255 #include "moc_kpToolZoom.cpp"