kpToolZoom.cpp 7.48 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
   Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   1. Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
   2. Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


Clarence Dang's avatar
Clarence Dang committed
28
#define DEBUG_KP_TOOL_ZOOM 0
29
30


31
#include "kpToolZoom.h"
32

33
34
35
36
37
38
39
40
#include "kpDefs.h"
#include "document/kpDocument.h"
#include "pixmapfx/kpPixmapFX.h"
#include "generic/kpSetOverrideCursorSaver.h"
#include "layers/tempImage/kpTempImage.h"
#include "environments/tools/kpToolEnvironment.h"
#include "tools/kpToolAction.h"
#include "views/manager/kpViewManager.h"
41
#include "kpLogCategories.h"
42

43
#include <QWidget>
44

45
46
#include <KLocalizedString>

47
//---------------------------------------------------------------------
48
49
50
51
52
53
54
55
56
57

struct DrawZoomRectPackage
{
    QRect normalizedRect;
};

static void DrawZoomRect (kpImage *destImage,
        const QPoint &topLeft,
        void *userData)
{
58
    auto *pack = static_cast <DrawZoomRectPackage *> (userData);
59

60
    kpPixmapFX::drawStippleRect(destImage,
61
        topLeft.x (), topLeft.y (), pack->normalizedRect.width (), pack->normalizedRect.height (),
62
        kpColor::Yellow,
Martin Koller's avatar
Martin Koller committed
63
        kpColor::Green);
64
65
66
67
68
}


struct kpToolZoomPrivate
{
69
    bool dragHasBegun{}, dragCompleted{};
70
71
72
73
74
75
    DrawZoomRectPackage drawPackage;
};

kpToolZoom::kpToolZoom (kpToolEnvironment *environ, QWidget *parent)
    : kpTool (i18n ("Zoom"), i18n ("Zooms in and out of the image"),
              Qt::Key_Z,
Laurent Montel's avatar
Laurent Montel committed
76
              environ, parent, QStringLiteral("tool_zoom")),
77
78
      d (new kpToolZoomPrivate ())
{
79
  // different from objectName()
David Faure's avatar
David Faure committed
80
  action()->setIcon(QIcon::fromTheme(QStringLiteral("zoom-original")));
81
82
}

83
84
//---------------------------------------------------------------------

85
86
87
88
89
kpToolZoom::~kpToolZoom ()
{
    delete d;
}

90
//---------------------------------------------------------------------
91
92
// public virtual [base kpTool]

93
94
bool kpToolZoom::returnToPreviousToolAfterEndDraw () const
{
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    // If the user clicks to zoom in or out, s/he generally wants to click
    // some more to get the exact zoom level wanted.
    //
    // However, if they drag out a rectangle to zoom into a particular area,
    // they probably don't need to do any further zooming so we can return
    // them to their previous tool.
    //
    // Note that if they cancel a drag (cancelShape()), we do _not_ return
    // them to their previous tool, unlike the Color Picker.  This is because
    // cancelling a drag generally means that the user got the top-left of
    // the drag wrong and wants to try a different top-left.  In contrast,
    // with the Color Picket, if you've made a mistake while pressing the
    // mouse, you can just keep holding down the mouse and drag to the intended
    // color -- a cancel with a Color Picker really means "I've decided not
    // to pick another color after all", not "I got the start of the drag wrong"
    // because you can correct that drag.
    return d->dragCompleted;
112
113
114
115
116
117
118
119
120
121
122
123
124
}


// private
QString kpToolZoom::haventBegunDrawUserMessage () const
{
    return i18n ("Click to zoom in/out or left drag to zoom into a specific area.");
}


// public virtual [base kpTool]
void kpToolZoom::begin ()
{
Urs Wolfer's avatar
Urs Wolfer committed
125
    viewManager ()->setCursor (Qt::CrossCursor);
126
127
128
129
130
131
132
133
134
135
136

    setUserMessage (haventBegunDrawUserMessage ());
}

// public virtual [base kpTool]
void kpToolZoom::end ()
{
    viewManager ()->unsetCursor ();
}


137
138
139
// public virtual [base kpTool]
void kpToolZoom::globalDraw ()
{
140
#if DEBUG_KP_TOOL_ZOOM
141
    qCDebug(kpLogTools) << "CALL";
142
#endif
Clarence Dang's avatar
Clarence Dang committed
143
    environ ()->fitToPage ();
144
145
146
}


147
148
149
150
// public virtual [base kpTool]
void kpToolZoom::beginDraw ()
{
    d->dragHasBegun = false;
151
    d->dragCompleted = false;
152
153
154
155
156
157
158

    setUserMessage (cancelUserMessage ());
}

// public virtual [base kpTool]
void kpToolZoom::draw (const QPoint &thisPoint, const QPoint &, const QRect &normalizedRect)
{
159
#if DEBUG_KP_TOOL_ZOOM
160
    qCDebug(kpLogTools) << "kpToomZoom::draw() currentPoint=" << currentPoint ()
161
162
163
              << " lastPoint=" << lastPoint ()
              << endl;
#endif
164
165
166
167
168
169

    // TODO: Need accidental drag detection from selection tool (when dragging
    //       out new selection)

    if (!d->dragHasBegun)
    {
170
        if (thisPoint == startPoint ()) {
171
            return;
172
        }
173
174
175
176
177
178

        // Left mouse drags select an area to zoom into.
        // However, it wouldn't make sense to select an area to "zoom out of"
        // (using the right mouse button).  Therefore, make RMB drags do the
        // same as RMB clicks i.e. a simple zoom out, with no "area" to worry
        // about.
179
        if (mouseButton () == 1/*RMB*/) {
180
            return;
181
        }
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

        d->dragHasBegun = true;
    }


    d->drawPackage.normalizedRect = normalizedRect;

    kpTempImage newTempImage (false/*always display*/,
        normalizedRect.topLeft (),
        &::DrawZoomRect, &d->drawPackage,
        normalizedRect.width (), normalizedRect.height ());

    viewManager ()->setFastUpdates ();
    {
        viewManager ()->setTempImage (newTempImage);
    }
    viewManager ()->restoreFastUpdates ();
}

// public virtual [base kpTool]
void kpToolZoom::cancelShape ()
{
    viewManager ()->invalidateTempImage ();

    // LOREFACTOR: A lot of tools use this - push up to kpTool?
    setUserMessage (i18n ("Let go of all the mouse buttons."));
}

// public virtual [base kpTool]
void kpToolZoom::releasedAllButtons ()
{
    setUserMessage (haventBegunDrawUserMessage ());
}

// public virtual [base kpTool]
217
void kpToolZoom::endDraw (const QPoint &, const QRect &normalizedRect)
218
{
219
#if DEBUG_KP_TOOL_ZOOM
220
    qCDebug(kpLogTools) << "kpToolZoom::endDraw(rect=" << normalizedRect << ")"
221
222
        << " dragHasBegun=" << d->dragHasBegun << endl;
#endif
223

224
225
    // TODO: This cursor doesn't stay on for long enough because zooming uses
    //       event loop tricks.
Urs Wolfer's avatar
Urs Wolfer committed
226
    kpSetOverrideCursorSaver cursorSaver (Qt::WaitCursor);
227
228
229
230
231
232

    viewManager ()->invalidateTempImage ();

    // Click?
    if (!d->dragHasBegun)
    {
233
        if (mouseButton () == 0/*LMB*/) {
234
            environ ()->zoomIn (true/*center under cursor*/);
235
236
        }
        else {
237
238
239
            environ ()->zoomOut (false/*don't center under cursor - as is
                                        confusing behaviour when zooming
                                        out*/);
240
        }
241
242
    }
    // Drag?
243
    else if (normalizedRect.isValid())
244
    {
Clarence Dang's avatar
Clarence Dang committed
245
246
247
248
        environ ()->zoomToRect (
            normalizedRect,
            false/*don't account for grips*/,
            true/*care about width*/, true/*care about height*/);
249
250

        d->dragCompleted = true;
251
252
253
254
    }
}