File indexing completed on 2024-05-12 04:21:26

0001 /*
0002    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0003    Copyright (c) 2017      Martin Koller <kollix@aon.at>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 
0029 #define DEBUG_KP_TOOL_POLYGON 0
0030 
0031 
0032 #include "kpToolPolygon.h"
0033 #include "widgets/toolbars/kpToolToolBar.h"
0034 #include "environments/tools/kpToolEnvironment.h"
0035 #include "imagelib/kpColor.h"
0036 #include "pixmapfx/kpPixmapFX.h"
0037 
0038 #include <KLocalizedString>
0039 
0040 #include <QPainter>
0041 #include <QPen>
0042 
0043 //--------------------------------------------------------------------------------
0044 
0045 static void DrawPolygonShape (kpImage *image,
0046         const QPolygon &points,
0047         const kpColor &fcolor, int penWidth,
0048         const kpColor &bcolor,
0049         bool isFinal)
0050 {
0051   QPainter painter(image);
0052   painter.setRenderHint(QPainter::Antialiasing, kpToolEnvironment::drawAntiAliased);
0053 
0054   painter.setPen(QPen(fcolor.toQColor(), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
0055 
0056   if ( kpPixmapFX::Only1PixelInPointArray(points) )
0057   {
0058     painter.drawPoint(points[0]);
0059     return;
0060   }
0061 
0062   if ( bcolor.isValid() ) {
0063     painter.setBrush(QBrush(bcolor.toQColor()));
0064   }
0065   else {
0066     painter.setBrush(Qt::NoBrush);
0067   }
0068 
0069   painter.drawPolygon(points, Qt::OddEvenFill);
0070 
0071   if ( isFinal ) {
0072     return;
0073   }
0074 
0075   if ( points.count() <= 2 ) {
0076     return;
0077   }
0078 
0079   painter.setCompositionMode(QPainter::RasterOp_SourceXorDestination);
0080   painter.setPen(QPen(Qt::white));
0081   painter.drawLine(points[0], points[points.count() - 1]);
0082 }
0083 
0084 //--------------------------------------------------------------------------------
0085 
0086 struct kpToolPolygonPrivate
0087 {
0088     kpToolWidgetFillStyle *toolWidgetFillStyle;
0089 };
0090 
0091 kpToolPolygon::kpToolPolygon (kpToolEnvironment *environ, QObject *parent)
0092     : kpToolPolygonalBase (
0093         i18n ("Polygon"),
0094         i18n ("Draws polygons"),
0095         &::DrawPolygonShape,
0096         Qt::Key_G,
0097         environ, parent,
0098         QStringLiteral("tool_polygon")),
0099       d (new kpToolPolygonPrivate ())
0100 {
0101 }
0102 
0103 kpToolPolygon::~kpToolPolygon ()
0104 {
0105     delete d;
0106 }
0107 
0108 
0109 // private virtual [base kpToolPolygonBase]
0110 QString kpToolPolygon::haventBegunShapeUserMessage () const
0111 {
0112     return i18n ("Drag to draw the first line.");
0113 }
0114 
0115 
0116 // public virtual [base kpToolPolygonalBase]
0117 void kpToolPolygon::begin ()
0118 {
0119     kpToolPolygonalBase::begin ();
0120 
0121     kpToolToolBar *tb = toolToolBar ();
0122     Q_ASSERT (tb);
0123 
0124     d->toolWidgetFillStyle = tb->toolWidgetFillStyle ();
0125     connect (d->toolWidgetFillStyle, &kpToolWidgetFillStyle::fillStyleChanged,
0126              this, &kpToolPolygon::updateShape);
0127     d->toolWidgetFillStyle->show ();
0128 }
0129 
0130 // public virtual [base kpToolPolygonalBase]
0131 void kpToolPolygon::end ()
0132 {
0133     kpToolPolygonalBase::end ();
0134 
0135     disconnect (d->toolWidgetFillStyle, &kpToolWidgetFillStyle::fillStyleChanged,
0136                 this, &kpToolPolygon::updateShape);
0137     d->toolWidgetFillStyle = nullptr;
0138 }
0139 
0140 
0141 // TODO: code dup with kpToolRectangle
0142 // protected virtual [base kpToolPolygonalBase]
0143 kpColor kpToolPolygon::drawingBackgroundColor () const
0144 {
0145     const kpColor foregroundColor = color (originatingMouseButton ());
0146     const kpColor backgroundColor = color (1 - originatingMouseButton ());
0147 
0148     return d->toolWidgetFillStyle->drawingBackgroundColor (
0149         foregroundColor, backgroundColor);
0150 }
0151 
0152 
0153 // public virtual [base kpTool]
0154 // TODO: dup with kpToolPolyline but we don't want to create another level of
0155 //       inheritance and readability.
0156 void kpToolPolygon::endDraw (const QPoint &, const QRect &)
0157 {
0158 #if DEBUG_KP_TOOL_POLYGON
0159     qCDebug(kpLogTools) << "kpToolPolygon::endDraw()  points="
0160         << points ()->toList ();
0161 #endif
0162 
0163     // A click of the other mouse button (to finish shape, instead of adding
0164     // another control point) would have caused endShape() to have been
0165     // called in kpToolPolygonalBase::beginDraw().  The points list would now
0166     // be empty.  We are being called by kpTool::mouseReleaseEvent().
0167     if (points ()->count () == 0) {
0168         return;
0169     }
0170 
0171     if (points ()->count () >= kpToolPolygonalBase::MaxPoints)
0172     {
0173     #if DEBUG_KP_TOOL_POLYGON
0174         qCDebug(kpLogTools) << "\tending shape";
0175     #endif
0176         endShape ();
0177         return;
0178     }
0179 
0180     if (originatingMouseButton () == 0)
0181     {
0182         setUserMessage (i18n ("Left drag another line or right click to finish."));
0183     }
0184     else
0185     {
0186         setUserMessage (i18n ("Right drag another line or left click to finish."));
0187     }
0188 }
0189 
0190 #include "moc_kpToolPolygon.cpp"