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