~ubuntu-branches/ubuntu/oneiric/kolourpaint/oneiric-proposed

« back to all changes in this revision

Viewing changes to tools/selection/kpAbstractSelectionTool_ResizeScale.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Harald Sitter
  • Date: 2011-07-10 12:20:39 UTC
  • Revision ID: james.westby@ubuntu.com-20110710122039-a7bokz6isao1ldt2
Tags: upstream-4.6.90+repack
ImportĀ upstreamĀ versionĀ 4.6.90+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
   Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
 
4
   All rights reserved.
 
5
 
 
6
   Redistribution and use in source and binary forms, with or without
 
7
   modification, are permitted provided that the following conditions
 
8
   are met:
 
9
 
 
10
   1. Redistributions of source code must retain the above copyright
 
11
      notice, this list of conditions and the following disclaimer.
 
12
   2. Redistributions in binary form must reproduce the above copyright
 
13
      notice, this list of conditions and the following disclaimer in the
 
14
      documentation and/or other materials provided with the distribution.
 
15
 
 
16
   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
17
   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
18
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
19
   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
20
   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
21
   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
22
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
23
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
24
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
25
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
*/
 
27
 
 
28
 
 
29
#define DEBUG_KP_TOOL_SELECTION 0
 
30
 
 
31
 
 
32
#include <kpAbstractSelectionTool.h>
 
33
#include <kpAbstractSelectionToolPrivate.h>
 
34
 
 
35
#include <qapplication.h>
 
36
#include <qbitmap.h>
 
37
#include <qcursor.h>
 
38
#include <qevent.h>
 
39
#include <qmenu.h>
 
40
#include <qpainter.h>
 
41
#include <qpixmap.h>
 
42
#include <qpolygon.h>
 
43
#include <qtimer.h>
 
44
 
 
45
#include <kdebug.h>
 
46
#include <klocale.h>
 
47
 
 
48
#include <kpAbstractImageSelection.h>
 
49
#include <kpAbstractSelection.h>
 
50
#include <kpCommandHistory.h>
 
51
#include <kpDefs.h>
 
52
#include <kpDocument.h>
 
53
#include <kpMacroCommand.h>
 
54
#include <kpToolSelectionCreateCommand.h>
 
55
#include <kpToolSelectionDestroyCommand.h>
 
56
#include <kpToolSelectionEnvironment.h>
 
57
#include <kpToolSelectionMoveCommand.h>
 
58
#include <kpToolSelectionResizeScaleCommand.h>
 
59
#include <kpToolImageSelectionTransparencyCommand.h>
 
60
#include <kpToolToolBar.h>
 
61
#include <kpToolWidgetOpaqueOrTransparent.h>
 
62
#include <kpView.h>
 
63
#include <kpViewManager.h>
 
64
 
 
65
 
 
66
// private
 
67
int kpAbstractSelectionTool::onSelectionResizeHandle () const
 
68
{
 
69
    kpView *v = viewManager ()->viewUnderCursor ();
 
70
    if (!v)
 
71
        return 0;
 
72
 
 
73
    return v->mouseOnSelectionResizeHandle (currentViewPoint ());
 
74
}
 
75
 
 
76
//---------------------------------------------------------------------
 
77
 
 
78
// private
 
79
void kpAbstractSelectionTool::initResizeScale ()
 
80
{
 
81
    d->currentResizeScaleCommand = 0;
 
82
 
 
83
   // d->resizeScaleType
 
84
}
 
85
 
 
86
// private
 
87
void kpAbstractSelectionTool::uninitResizeScale ()
 
88
{
 
89
    // (state must be after construction, or after some time after endResizeScale())
 
90
    Q_ASSERT (!d->currentResizeScaleCommand);
 
91
 
 
92
    // d->resizeScaleType
 
93
}
 
94
 
 
95
 
 
96
// private
 
97
void kpAbstractSelectionTool::beginResizeScale ()
 
98
{
 
99
    // (state must be after construction, or after some time after endResizeScale())
 
100
    Q_ASSERT (!d->currentResizeScaleCommand);
 
101
 
 
102
    // d->resizeScaleType
 
103
}
 
104
 
 
105
// private
 
106
void kpAbstractSelectionTool::endResizeScale ()
 
107
{
 
108
    // (should have been killed by cancelResizeScale() or endResizeScale())
 
109
    Q_ASSERT (!d->currentResizeScaleCommand);
 
110
 
 
111
    // d->resizeScaleType
 
112
}
 
113
 
 
114
//---------------------------------------------------------------------
 
115
 
 
116
// private
 
117
void kpAbstractSelectionTool::setCursorResizeScale ()
 
118
{
 
119
#if DEBUG_KP_TOOL_SELECTION && 0
 
120
    kDebug () << "\tonSelectionResizeHandle="
 
121
                << onSelectionResizeHandle () << endl;
 
122
#endif
 
123
    Qt::CursorShape shape = Qt::ArrowCursor;
 
124
 
 
125
    switch (onSelectionResizeHandle ())
 
126
    {
 
127
    case (kpView::Top | kpView::Left):
 
128
    case (kpView::Bottom | kpView::Right):
 
129
        shape = Qt::SizeFDiagCursor;
 
130
        break;
 
131
 
 
132
    case (kpView::Bottom | kpView::Left):
 
133
    case (kpView::Top | kpView::Right):
 
134
        shape = Qt::SizeBDiagCursor;
 
135
        break;
 
136
 
 
137
    case kpView::Top:
 
138
    case kpView::Bottom:
 
139
        shape = Qt::SizeVerCursor;
 
140
        break;
 
141
 
 
142
    case kpView::Left:
 
143
    case kpView::Right:
 
144
        shape = Qt::SizeHorCursor;
 
145
        break;
 
146
    }
 
147
 
 
148
    viewManager ()->setCursor (shape);
 
149
}
 
150
 
 
151
//---------------------------------------------------------------------
 
152
 
 
153
// protected virtual
 
154
void kpAbstractSelectionTool::setSelectionBorderForBeginDrawResizeScale ()
 
155
{
 
156
    viewManager ()->setQueueUpdates ();
 
157
    {
 
158
        viewManager ()->setSelectionBorderVisible (true);
 
159
        viewManager ()->setSelectionBorderFinished (true);
 
160
    }
 
161
    viewManager ()->restoreQueueUpdates ();
 
162
}
 
163
 
 
164
//---------------------------------------------------------------------
 
165
 
 
166
// private
 
167
void kpAbstractSelectionTool::beginDrawResizeScale ()
 
168
{
 
169
    d->resizeScaleType = onSelectionResizeHandle ();
 
170
 
 
171
    /*virtual*/setSelectionBorderForBeginDrawResizeScale ();
 
172
 
 
173
    setUserMessage (cancelUserMessage ());
 
174
}
 
175
 
 
176
//---------------------------------------------------------------------
 
177
 
 
178
 
 
179
// private
 
180
void kpAbstractSelectionTool::drawResizeScaleTryKeepAspect (
 
181
        int newWidth, int newHeight,
 
182
        bool horizontalGripDragged, bool verticalGripDragged,
 
183
        const kpAbstractSelection &originalSelection,
 
184
        int *newWidthOut, int *newHeightOut)
 
185
{
 
186
    const int oldWidth = originalSelection.width (),
 
187
        oldHeight = originalSelection.height ();
 
188
 
 
189
    // Width changed more than height?  At equality, favor width.
 
190
    // Fix width, change height.
 
191
    //
 
192
    // We use <horizontalGripDragged> and <verticalGripDragged> to prevent
 
193
    // e.g. the situation where we've dragged such that newWidth < oldWidth but
 
194
    // we're not dragging a vertical grip.  We certainly don't want this
 
195
    // code to modify the width - we want to fix the width and change the
 
196
    // height.
 
197
    if ((horizontalGripDragged ? double (newWidth) / oldWidth : 0) >=
 
198
        (verticalGripDragged ? double (newHeight) / oldHeight : 0))
 
199
    {
 
200
        *newHeightOut = newWidth * oldHeight / oldWidth;
 
201
        *newHeightOut = qMax (originalSelection.minimumHeight (), *newHeightOut);
 
202
    }
 
203
    // Height changed more than width?
 
204
    // Fix height, change width.
 
205
    else
 
206
    {
 
207
        *newWidthOut = newHeight * oldWidth / oldHeight;
 
208
        *newWidthOut = qMax (originalSelection.minimumWidth (), *newWidthOut);
 
209
    }
 
210
}
 
211
 
 
212
//---------------------------------------------------------------------
 
213
 
 
214
// private
 
215
void kpAbstractSelectionTool::drawResizeScaleCalculateNewSelectionPosSize (
 
216
        const kpAbstractSelection &originalSelection,
 
217
        int *newX, int *newY,
 
218
        int *newWidth, int *newHeight)
 
219
{
 
220
    //
 
221
    // Determine new width.
 
222
    //
 
223
 
 
224
    // Dragging left or right grip?
 
225
    // If left, positive X drags decrease width.
 
226
    // If right, positive X drags increase width.
 
227
    int userXSign = 0;
 
228
    if (d->resizeScaleType & kpView::Left)
 
229
        userXSign = -1;
 
230
    else if (d->resizeScaleType & kpView::Right)
 
231
        userXSign = +1;
 
232
 
 
233
    // Calcluate new width.
 
234
    *newWidth = originalSelection.width () +
 
235
        userXSign * (currentPoint ().x () - startPoint ().x ());
 
236
 
 
237
    // Don't allow new width to be less than that kind of selection type's
 
238
    // minimum.
 
239
    *newWidth = qMax (originalSelection.minimumWidth (), *newWidth);
 
240
 
 
241
 
 
242
    //
 
243
    // Determine new height.
 
244
    //
 
245
 
 
246
    // Dragging top or bottom grip?
 
247
    // If top, positive Y drags decrease height.
 
248
    // If bottom, positive Y drags increase height.
 
249
    int userYSign = 0;
 
250
    if (d->resizeScaleType & kpView::Top)
 
251
        userYSign = -1;
 
252
    else if (d->resizeScaleType & kpView::Bottom)
 
253
        userYSign = +1;
 
254
 
 
255
    // Calcluate new height.
 
256
    *newHeight = originalSelection.height () +
 
257
        userYSign * (currentPoint ().y () - startPoint ().y ());
 
258
 
 
259
    // Don't allow new height to be less than that kind of selection type's
 
260
    // minimum.
 
261
    *newHeight = qMax (originalSelection.minimumHeight (), *newHeight);
 
262
 
 
263
 
 
264
    // Keep aspect ratio?
 
265
    if (shiftPressed ())
 
266
    {
 
267
        drawResizeScaleTryKeepAspect (*newWidth, *newHeight,
 
268
            (userXSign != 0)/*X or XY grip dragged*/,
 
269
                (userYSign != 0)/*Y or XY grip dragged*/,
 
270
            originalSelection,
 
271
            newWidth/*ptr*/, newHeight/*ptr*/);
 
272
    }
 
273
 
 
274
 
 
275
    *newX = originalSelection.x ();
 
276
    *newY = originalSelection.y ();
 
277
 
 
278
 
 
279
    //
 
280
    // Adjust x/y to new width/height for left/top resizes.
 
281
    //
 
282
 
 
283
    if (d->resizeScaleType & kpView::Left)
 
284
    {
 
285
        *newX -= (*newWidth - originalSelection.width ());
 
286
    }
 
287
 
 
288
    if (d->resizeScaleType & kpView::Top)
 
289
    {
 
290
        *newY -= (*newHeight - originalSelection.height ());
 
291
    }
 
292
 
 
293
#if DEBUG_KP_TOOL_SELECTION && 1
 
294
    kDebug () << "\t\tnewX=" << *newX
 
295
                << " newY=" << *newY
 
296
                << " newWidth=" << *newWidth
 
297
                << " newHeight=" << *newHeight
 
298
                << endl;
 
299
#endif
 
300
}
 
301
 
 
302
//---------------------------------------------------------------------
 
303
 
 
304
// private
 
305
void kpAbstractSelectionTool::drawResizeScale (
 
306
        const QPoint &thisPoint,
 
307
        const QRect &/*normalizedRect*/)
 
308
{
 
309
#if DEBUG_KP_TOOL_SELECTION && 1
 
310
    kDebug () << "\tresize/scale";
 
311
#endif
 
312
 
 
313
    kpAbstractSelection *sel = document ()->selection ();
 
314
 
 
315
    if (!d->dragAccepted && thisPoint == startPoint ())
 
316
    {
 
317
    #if DEBUG_KP_TOOL_SELECTION && 1
 
318
        kDebug () << "\t\tnop";
 
319
    #endif
 
320
 
 
321
        setUserShapePoints (QPoint (sel->width (), sel->height ()));
 
322
        return;
 
323
    }
 
324
 
 
325
 
 
326
    giveContentIfNeeded ();
 
327
 
 
328
 
 
329
    if (!d->currentResizeScaleCommand)
 
330
    {
 
331
        d->currentResizeScaleCommand
 
332
            = new kpToolSelectionResizeScaleCommand (environ ()->commandEnvironment ());
 
333
    }
 
334
 
 
335
 
 
336
    const kpAbstractSelection *originalSelection =
 
337
        d->currentResizeScaleCommand->originalSelection ();
 
338
 
 
339
 
 
340
    // There is nothing illegal about position (-1,-1) but why not.
 
341
    int newX = -1, newY = -1,
 
342
        newWidth = 0, newHeight = 0;
 
343
 
 
344
    // This should change all of the above values.
 
345
    drawResizeScaleCalculateNewSelectionPosSize (
 
346
        *originalSelection,
 
347
        &newX, &newY,
 
348
        &newWidth, &newHeight);
 
349
 
 
350
 
 
351
    viewManager ()->setFastUpdates ();
 
352
    {
 
353
        d->currentResizeScaleCommand->resizeAndMoveTo (
 
354
            newWidth, newHeight,
 
355
            QPoint (newX, newY),
 
356
            true/*smooth scale delayed*/);
 
357
    }
 
358
    viewManager ()->restoreFastUpdates ();
 
359
 
 
360
    setUserShapePoints (QPoint (originalSelection->width (),
 
361
                                originalSelection->height ()),
 
362
                        QPoint (newWidth,
 
363
                                newHeight),
 
364
                        false/*don't set size*/);
 
365
    setUserShapeSize (newWidth - originalSelection->width (),
 
366
                        newHeight - originalSelection->height ());
 
367
 
 
368
 
 
369
    d->dragAccepted = true;
 
370
}
 
371
 
 
372
//---------------------------------------------------------------------
 
373
 
 
374
 
 
375
// private
 
376
void kpAbstractSelectionTool::cancelResizeScale ()
 
377
{
 
378
#if DEBUG_KP_TOOL_SELECTION
 
379
    kDebug () << "\twas resize/scale sel - kill";
 
380
#endif
 
381
 
 
382
    // NOP drag?
 
383
    if (!d->currentResizeScaleCommand)
 
384
        return;
 
385
 
 
386
#if DEBUG_KP_TOOL_SELECTION
 
387
    kDebug () << "\t\tundo currentResizeScaleCommand";
 
388
#endif
 
389
    d->currentResizeScaleCommand->finalize ();  // (unneeded but let's be safe)
 
390
    d->currentResizeScaleCommand->unexecute ();
 
391
    delete d->currentResizeScaleCommand;
 
392
    d->currentResizeScaleCommand = 0;
 
393
}
 
394
 
 
395
//---------------------------------------------------------------------
 
396
 
 
397
// private
 
398
void kpAbstractSelectionTool::endDrawResizeScale ()
 
399
{
 
400
    // NOP drag?
 
401
    if (!d->currentResizeScaleCommand)
 
402
        return;
 
403
 
 
404
    d->currentResizeScaleCommand->finalize ();
 
405
 
 
406
    addNeedingContentCommand (d->currentResizeScaleCommand);
 
407
    d->currentResizeScaleCommand = 0;
 
408
}
 
409
 
 
410
//---------------------------------------------------------------------
 
411
 
 
412
// private
 
413
QVariant kpAbstractSelectionTool::operationResizeScale (Operation op,
 
414
        const QVariant &data1, const QVariant &data2)
 
415
{
 
416
    (void) data1;
 
417
    (void) data2;
 
418
 
 
419
 
 
420
    switch (op)
 
421
    {
 
422
    case HaventBegunDrawUserMessage:
 
423
        return /*virtual*/haventBegunDrawUserMessageResizeScale ();
 
424
 
 
425
    case SetCursor:
 
426
        setCursorResizeScale ();
 
427
        break;
 
428
 
 
429
    case BeginDraw:
 
430
        beginDrawResizeScale ();
 
431
        break;
 
432
 
 
433
    case Draw:
 
434
        drawResizeScale (currentPoint (), normalizedRect ());
 
435
        break;
 
436
 
 
437
    case Cancel:
 
438
        cancelResizeScale ();
 
439
        break;
 
440
 
 
441
    case EndDraw:
 
442
        endDrawResizeScale ();
 
443
        break;
 
444
 
 
445
    default:
 
446
        Q_ASSERT (!"Unhandled operation");
 
447
        break;
 
448
    }
 
449
 
 
450
 
 
451
    return QVariant ();
 
452
}
 
453
 
 
454
//---------------------------------------------------------------------