compile
[kdegraphics.git] / kolourpaint / tools / rectangular / kpToolRectangularBase.cpp
blobada27f6d046688a139f52edc1fd667da0b3c0130
2 /*
3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
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.
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.
29 #define DEBUG_KP_TOOL_RECTANGULAR_BASE 0
32 #include <kpToolRectangularBase.h>
34 #include <qbitmap.h>
35 #include <qcursor.h>
36 #include <qevent.h>
37 #include <qpainter.h>
38 #include <qpixmap.h>
40 #include <kdebug.h>
41 #include <klocale.h>
43 #include <kpBug.h>
44 #include <kpColor.h>
45 #include <kpCommandHistory.h>
46 #include <kpDefs.h>
47 #include <kpDocument.h>
48 #include <kpPainter.h>
49 #include <kpPixmapFX.h>
50 #include <kpTempImage.h>
51 #include <kpToolEnvironment.h>
52 #include <kpToolRectangularCommand.h>
53 #include <kpToolToolBar.h>
54 #include <kpToolWidgetFillStyle.h>
55 #include <kpToolWidgetLineWidth.h>
56 #include <kpView.h>
57 #include <kpViewManager.h>
60 struct kpToolRectangularBasePrivate
62 kpToolRectangularBase::DrawShapeFunc drawShapeFunc;
64 kpToolWidgetLineWidth *toolWidgetLineWidth;
65 kpToolWidgetFillStyle *toolWidgetFillStyle;
67 QRect toolRectangleRect;
71 kpToolRectangularBase::kpToolRectangularBase (
72 const QString &text,
73 const QString &description,
74 DrawShapeFunc drawShapeFunc,
75 int key,
76 kpToolEnvironment *environ, QObject *parent,
77 const QString &name)
79 : kpTool (text, description, key, environ, parent, name),
80 d (new kpToolRectangularBasePrivate ())
82 d->drawShapeFunc = drawShapeFunc;
84 d->toolWidgetLineWidth = 0, d->toolWidgetFillStyle = 0;
88 kpToolRectangularBase::~kpToolRectangularBase ()
90 delete d;
94 // private slot virtual
95 void kpToolRectangularBase::slotLineWidthChanged ()
97 if (hasBegunDraw ())
98 updateShape ();
101 // private slot virtual
102 void kpToolRectangularBase::slotFillStyleChanged ()
104 if (hasBegunDraw ())
105 updateShape ();
109 // private
110 QString kpToolRectangularBase::haventBegunDrawUserMessage () const
112 return i18n ("Drag to draw.");
115 // virtual
116 void kpToolRectangularBase::begin ()
118 #if DEBUG_KP_TOOL_RECTANGULAR_BASE
119 kDebug () << "kpToolRectangularBase::begin ()";
120 #endif
122 kpToolToolBar *tb = toolToolBar ();
123 Q_ASSERT (tb);
125 #if DEBUG_KP_TOOL_RECTANGULAR_BASE
126 kDebug () << "\ttoolToolBar=" << tb;
127 #endif
129 d->toolWidgetLineWidth = tb->toolWidgetLineWidth ();
130 connect (d->toolWidgetLineWidth,
131 SIGNAL (lineWidthChanged (int)),
132 this,
133 SLOT (slotLineWidthChanged ()));
134 d->toolWidgetLineWidth->show ();
136 d->toolWidgetFillStyle = tb->toolWidgetFillStyle ();
137 connect (d->toolWidgetFillStyle,
138 SIGNAL (fillStyleChanged (kpToolWidgetFillStyle::FillStyle)),
139 this,
140 SLOT (slotFillStyleChanged ()));
141 d->toolWidgetFillStyle->show ();
143 viewManager ()->setCursor (QCursor (Qt::CrossCursor));
145 setUserMessage (haventBegunDrawUserMessage ());
148 // virtual
149 void kpToolRectangularBase::end ()
151 #if DEBUG_KP_TOOL_RECTANGULAR_BASE
152 kDebug () << "kpToolRectangularBase::end ()";
153 #endif
155 if (d->toolWidgetLineWidth)
157 disconnect (d->toolWidgetLineWidth,
158 SIGNAL (lineWidthChanged (int)),
159 this,
160 SLOT (slotLineWidthChanged ()));
161 d->toolWidgetLineWidth = 0;
164 if (d->toolWidgetFillStyle)
166 disconnect (d->toolWidgetFillStyle,
167 SIGNAL (fillStyleChanged (kpToolWidgetFillStyle::FillStyle)),
168 this,
169 SLOT (slotFillStyleChanged ()));
170 d->toolWidgetFillStyle = 0;
173 viewManager ()->unsetCursor ();
176 void kpToolRectangularBase::applyModifiers ()
178 QRect rect = normalizedRect ();
180 #if DEBUG_KP_TOOL_RECTANGULAR_BASE
181 kDebug () << "kpToolRectangularBase::applyModifiers(" << rect
182 << ") shift=" << shiftPressed ()
183 << " ctrl=" << controlPressed ()
184 << endl;
185 #endif
187 // user wants to startPoint () == center
188 if (controlPressed ())
190 int xdiff = qAbs (startPoint ().x () - currentPoint ().x ());
191 int ydiff = qAbs (startPoint ().y () - currentPoint ().y ());
192 rect = QRect (startPoint ().x () - xdiff, startPoint ().y () - ydiff,
193 xdiff * 2 + 1, ydiff * 2 + 1);
196 // user wants major axis == minor axis:
197 // rectangle --> square
198 // rounded rectangle --> rounded square
199 // ellipse --> circle
200 if (shiftPressed ())
202 if (!controlPressed ())
204 if (rect.width () < rect.height ())
206 if (startPoint ().y () == rect.y ())
207 rect.setHeight (rect.width ());
208 else
209 rect.setY (rect.bottom () - rect.width () + 1);
211 else
213 if (startPoint ().x () == rect.x ())
214 rect.setWidth (rect.height ());
215 else
216 rect.setX (rect.right () - rect.height () + 1);
219 // have to maintain the center
220 else
222 if (rect.width () < rect.height ())
224 QPoint center = rect.center ();
225 rect.setHeight (rect.width ());
226 rect.moveCenter (center);
228 else
230 QPoint center = rect.center ();
231 rect.setWidth (rect.height ());
232 rect.moveCenter (center);
237 d->toolRectangleRect = rect;
240 void kpToolRectangularBase::beginDraw ()
242 setUserMessage (cancelUserMessage ());
246 // private
247 kpColor kpToolRectangularBase::drawingForegroundColor () const
249 return color (mouseButton ());
252 // private
253 kpColor kpToolRectangularBase::drawingBackgroundColor () const
255 const kpColor foregroundColor = color (mouseButton ());
256 const kpColor backgroundColor = color (1 - mouseButton ());
258 return d->toolWidgetFillStyle->drawingBackgroundColor (
259 foregroundColor, backgroundColor);
262 // private
263 void kpToolRectangularBase::updateShape ()
265 kpImage image = document ()->getImageAt (d->toolRectangleRect);
267 // Invoke shape drawing function passed in ctor.
268 (*d->drawShapeFunc) (&image,
269 0, 0, d->toolRectangleRect.width (), d->toolRectangleRect.height (),
270 drawingForegroundColor (), d->toolWidgetLineWidth->lineWidth (),
271 drawingBackgroundColor ());
273 kpTempImage newTempImage (false/*always display*/,
274 kpTempImage::SetImage/*render mode*/,
275 d->toolRectangleRect.topLeft (),
276 image);
278 viewManager ()->setFastUpdates ();
280 viewManager ()->setTempImage (newTempImage);
282 viewManager ()->restoreFastUpdates ();
286 void kpToolRectangularBase::draw (const QPoint &, const QPoint &, const QRect &)
288 applyModifiers ();
291 updateShape ();
294 // Recover the start and end points from the transformed & normalized d->toolRectangleRect
296 // S. or S or SC or S == C
297 // .C C
298 if (currentPoint ().x () >= startPoint ().x () &&
299 currentPoint ().y () >= startPoint ().y ())
301 setUserShapePoints (d->toolRectangleRect.topLeft (),
302 d->toolRectangleRect.bottomRight ());
304 // .C or C
305 // S. S
306 else if (currentPoint ().x () >= startPoint ().x () &&
307 currentPoint ().y () < startPoint ().y ())
309 setUserShapePoints (d->toolRectangleRect.bottomLeft (),
310 d->toolRectangleRect.topRight ());
312 // .S or CS
313 // C.
314 else if (currentPoint ().x () < startPoint ().x () &&
315 currentPoint ().y () >= startPoint ().y ())
317 setUserShapePoints (d->toolRectangleRect.topRight (),
318 d->toolRectangleRect.bottomLeft ());
320 // C.
321 // .S
322 else
324 setUserShapePoints (d->toolRectangleRect.bottomRight (),
325 d->toolRectangleRect.topLeft ());
329 void kpToolRectangularBase::cancelShape ()
331 viewManager ()->invalidateTempImage ();
333 setUserMessage (i18n ("Let go of all the mouse buttons."));
336 void kpToolRectangularBase::releasedAllButtons ()
338 setUserMessage (haventBegunDrawUserMessage ());
341 void kpToolRectangularBase::endDraw (const QPoint &, const QRect &)
343 applyModifiers ();
345 // TODO: flicker
346 // Later: So why can't we use kpViewManager::setQueueUpdates()? Check SVN
347 // log to see if this method was not available at the time of the
348 // TODO, hence justifying the TODO.
349 // Later2: kpToolPolygonalBase, and perhaps, other shapes will have the
350 // same problem.
351 viewManager ()->invalidateTempImage ();
353 environ ()->commandHistory ()->addCommand (
354 new kpToolRectangularCommand (
355 text (),
356 d->drawShapeFunc, d->toolRectangleRect,
357 drawingForegroundColor (), d->toolWidgetLineWidth->lineWidth (),
358 drawingBackgroundColor (),
359 environ ()->commandEnvironment ()));
361 setUserMessage (haventBegunDrawUserMessage ());
365 #include <kpToolRectangularBase.moc>