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

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
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 #ifndef kpToolPolygonalBase_H
0030 #define kpToolPolygonalBase_H
0031 
0032 
0033 #include <QPoint>
0034 #include <QRect>
0035 
0036 #include "imagelib/kpColor.h"
0037 #include "imagelib/kpImage.h"
0038 #include "tools/kpTool.h"
0039 #include "widgets/toolbars/options/kpToolWidgetFillStyle.h"
0040 
0041 
0042 class QPolygon;
0043 class QString;
0044 
0045 
0046 class kpToolWidgetFillStyle;
0047 
0048 
0049 struct kpToolPolygonalBasePrivate;
0050 
0051 //
0052 // This tool base class is for shapes that contain at least an initial line that
0053 // is dragged out (i.e. at least 2 control points).
0054 //
0055 // The tool can also choose to allow an additional point to be added for each
0056 // additional drag or click.
0057 //
0058 // To specify whichever behavior, subclasses must implement endDraw() from
0059 // kpTool and use points():
0060 //
0061 // 1. If the shape is incomplete, call setUserMessage() with a message
0062 //    telling the user what can be done next.
0063 // 2. If the shape is complete, call endShape().  See also MaxPoints.
0064 //
0065 // If additional points are supported by the user's implementation of endDraw(),
0066 // beginDraw() will enforce the following behavior:
0067 //
0068 //     Clicking the mouse button not used for the initial line drag will
0069 //     end the shape.
0070 //
0071 // This behavior cannot be altered by a subclass.
0072 //
0073 // beginDraw() will ensure that points() contains 2 points on the initial line
0074 // drag.  It will add an extra point for each additional point that is dragged.
0075 //
0076 // You may wish to reimplement drawingALine() if your shape does not consist of
0077 // just connected lines e.g. while the Curve tool, on the initial drag, creates
0078 // a line (consisting of the 2 points returned by points()), future drags do not
0079 // create extra lines - they actually modify the Bezier control points.
0080 //
0081 // The actual rendering is performed by the <drawShapeFunc> function passed in
0082 // the constructor.
0083 //
0084 class kpToolPolygonalBase : public kpTool
0085 {
0086 Q_OBJECT
0087 
0088 public:
0089     typedef void (*DrawShapeFunc) (kpImage * /*image*/,
0090         const QPolygon &/*points*/,
0091         const kpColor &/*fcolor*/, int /*penWidth = 1*/,
0092         const kpColor &/*bcolor = kpColor::Invalid*/,
0093         bool /*isFinal*/);
0094 
0095     // <drawShapeFunc>
0096     kpToolPolygonalBase (const QString &text, const QString &description,
0097         DrawShapeFunc drawShapeFunc,
0098         int key,
0099         kpToolEnvironment *environ, QObject *parent,
0100         const QString &name);
0101     ~kpToolPolygonalBase () override;
0102 
0103     bool careAboutModifierState () const override { return true; }
0104 
0105 protected:
0106     // The maximum number of points() we should allow (mainly, to ensure
0107     // good performance).  Enforced by implementors of endShape().
0108     static const int MaxPoints = 50;
0109 
0110     virtual QString haventBegunShapeUserMessage () const = 0;
0111 
0112 public:
0113     void begin () override;
0114     void end () override;
0115 
0116     void beginDraw () override;
0117 
0118 protected:
0119     // Adjusts the current line (end points given by the last 2 points of points())
0120     // in response to keyboard modifiers:
0121     //
0122     // No modifiers: Does nothing
0123     // Shift       : Clamps the line to 45 degrees increments
0124     // Ctrl        : Clamps the line to 30 degrees increments
0125     // Alt         : [currently disabled] Makes the starting point the center
0126     //               point of the line.
0127     //
0128     // It is possible to depress multiple modifiers for combined effects e.g.
0129     // Ctrl+Shift clamps the line to 30 and 45 degree increments i.e.
0130     // 0, 30, 45, 60, 90, 120, 135, 150, 180, 210, ... degrees.
0131     //
0132     // This really only makes sense if drawingALine() returns true, where draw()
0133     // will call applyModifiers() automatically.  Otherwise, if it returns false,
0134     // it doesn't really make sense to call applyModifiers() (in a hypothetical
0135     // reimplementation of draw()) because you're not manipulating a line - but
0136     // you can still call applyModifiers() if you want.
0137     void applyModifiers ();
0138 
0139     // Returns the current points in the shape.  It is updated by beginDraw()
0140     // (see the class description).
0141     //
0142     // draw() sets the last point to the currentPoint().  If drawingALine(),
0143     // draw() then calls applyModifiers().
0144     QPolygon *points () const;
0145 
0146     // Returns the mouse button for the drag that created the initial line.
0147     // Use this - instead of mouseButton() - for determining whether you should
0148     // use the left mouse button's or right mouse button's color.  This is because
0149     // the user presses the other mouse button to finish the shape (so mouseButton()
0150     // will return the wrong one, after the initial line).
0151     //
0152     // Only valid if kpTool::hasBegunShape() returns true.
0153     int originatingMouseButton () const;
0154 
0155     // Returns true if the current drag is visually a line from the 2nd last point
0156     // of points() to the last point of points() e.g. the initial line drag for
0157     // a Curve and all drags for a Polygon or Polyline.  draw() will call
0158     // applyModifiers() and update the statusbar with those 2 points.
0159     //
0160     // Returns false if the current drag only draws something based on the last
0161     // point of points() e.g. a control point of a Bezier curve.  draw() will
0162     // _not_ call applyModifiers().  It will update the statubar with just that
0163     // point.
0164     //
0165     // Reimplement this if not all points are used to construct connected lines.
0166     // For instance, the Curve tool will return "true" to construct a line, on
0167     // the initial drag.  However, for the following 2 control points, it returns
0168     // "false".  The Curve tool realizes it is an initial drag if points() only
0169     // returns 2 points.
0170     virtual bool drawingALine () const { return true; }
0171 public:
0172     void draw (const QPoint &, const QPoint &, const QRect &) override;
0173 private:
0174     kpColor drawingForegroundColor () const;
0175 protected:
0176     // This returns the invalid color so that there is never a fill.
0177     // This is in contrast to kpToolRectangularBase, which sometimes fills by
0178     // returning a valid color.
0179     //
0180     // Reimplemented in the Polygon tool for a fill.
0181     virtual kpColor drawingBackgroundColor () const;
0182 protected Q_SLOTS:
0183     void updateShape ();
0184 public:
0185     void cancelShape () override;
0186     void releasedAllButtons () override;
0187     void endShape (const QPoint & = QPoint (), const QRect & = QRect ()) override;
0188 
0189     bool hasBegunShape () const override;
0190 
0191 protected Q_SLOTS:
0192     void slotForegroundColorChanged (const kpColor &) override;
0193     void slotBackgroundColorChanged (const kpColor &) override;
0194 
0195 private:
0196     kpToolPolygonalBasePrivate * const d;
0197 };
0198 
0199 
0200 #endif  // kpToolPolygonalBase_H