1 /* 2 * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #ifndef KIS_TOOL_H_ 20 #define KIS_TOOL_H_ 21 22 #include <QCursor> 23 24 #include <KoColor.h> 25 #include <KoToolBase.h> 26 #include <KoID.h> 27 #include <KoCanvasResourceProvider.h> 28 #include <kritaui_export.h> 29 #include <kis_types.h> 30 31 #ifdef __GNUC__ 32 #define WARN_WRONG_MODE(_mode) warnKrita << "Unexpected tool event has come to" << __func__ << "while being mode" << _mode << "!" 33 #else 34 #define WARN_WRONG_MODE(_mode) warnKrita << "Unexpected tool event has come while being mode" << _mode << "!" 35 #endif 36 37 #define CHECK_MODE_SANITY_OR_RETURN(_mode) if (mode() != _mode) { WARN_WRONG_MODE(mode()); return; } 38 39 class KoCanvasBase; 40 class KoPattern; 41 class KoAbstractGradient; 42 class KisFilterConfiguration; 43 class QPainter; 44 class QPainterPath; 45 class QPolygonF; 46 47 /// Definitions of the toolgroups of Krita 48 static const QString TOOL_TYPE_SHAPE = "0 Krita/Shape"; // Geometric shapes like ellipses and lines 49 static const QString TOOL_TYPE_TRANSFORM = "2 Krita/Transform"; // Tools that transform the layer; 50 static const QString TOOL_TYPE_FILL = "3 Krita/Fill"; // Tools that fill parts of the canvas 51 static const QString TOOL_TYPE_VIEW = "4 Krita/View"; // Tools that affect the canvas: pan, zoom, etc. 52 static const QString TOOL_TYPE_SELECTION = "5 Krita/Select"; // Tools that select pixels 53 54 //activation id for Krita tools, Krita tools are always active and handle locked and invisible layers by themself 55 static const QString KRITA_TOOL_ACTIVATION_ID = "flake/always"; 56 57 class KRITAUI_EXPORT KisTool 58 : public KoToolBase 59 { 60 Q_OBJECT 61 62 Q_PROPERTY(bool isActive READ isActive NOTIFY isActiveChanged) 63 64 public: 65 enum { FLAG_USES_CUSTOM_PRESET=0x01, FLAG_USES_CUSTOM_COMPOSITEOP=0x02, FLAG_USES_CUSTOM_SIZE=0x04 }; 66 67 KisTool(KoCanvasBase * canvas, const QCursor & cursor); 68 ~KisTool() override; 69 flags()70 virtual int flags() const { return 0; } 71 72 void deleteSelection() override; 73 // KoToolBase Implementation. 74 75 public: 76 77 /** 78 * Called by KisToolProxy when the primary action of the tool is 79 * going to be started now, that is when all the modifiers are 80 * pressed and the only thing left is just to press the mouse 81 * button. On coming of this callback the tool is supposed to 82 * prepare the cursor and/or the outline to show the user shat is 83 * going to happen next 84 */ 85 virtual void activatePrimaryAction(); 86 87 /** 88 * Called by KisToolProxy when the primary is no longer possible 89 * to be started now, e.g. when its modifiers and released. The 90 * tool is supposed to revert all the preparations it has done in 91 * activatePrimaryAction(). 92 */ 93 virtual void deactivatePrimaryAction(); 94 95 /** 96 * Called by KisToolProxy when a primary action for the tool is 97 * started. The \p event stores the original event that 98 * started the stroke. The \p event is _accepted_ by default. If 99 * the tool decides to ignore this particular action (e.g. when 100 * the node is not editable), it should call event->ignore(). Then 101 * no further continuePrimaryAction() or endPrimaryAction() will 102 * be called until the next user action. 103 */ 104 virtual void beginPrimaryAction(KoPointerEvent *event); 105 106 /** 107 * Called by KisToolProxy when the primary action is in progress 108 * of pointer movement. If the tool has ignored the event in 109 * beginPrimaryAction(), this method will not be called. 110 */ 111 virtual void continuePrimaryAction(KoPointerEvent *event); 112 113 /** 114 * Called by KisToolProxy when the primary action is being 115 * finished, that is while mouseRelease or tabletRelease event. 116 * If the tool has ignored the event in beginPrimaryAction(), this 117 * method will not be called. 118 */ 119 virtual void endPrimaryAction(KoPointerEvent *event); 120 121 /** 122 * The same as beginPrimaryAction(), but called when the stroke is 123 * started by a double-click 124 * 125 * \see beginPrimaryAction() 126 */ 127 virtual void beginPrimaryDoubleClickAction(KoPointerEvent *event); 128 129 /** 130 * Returns true if the tool can handle (and wants to handle) a 131 * very tight flow of input events from the tablet 132 */ 133 virtual bool primaryActionSupportsHiResEvents() const; 134 135 enum ToolAction { 136 Primary, 137 AlternateChangeSize, 138 AlternateChangeSizeSnap, 139 AlternatePickFgNode, 140 AlternatePickBgNode, 141 AlternatePickFgImage, 142 AlternatePickBgImage, 143 AlternateSecondary, 144 AlternateThird, 145 AlternateFourth, 146 AlternateFifth, 147 Alternate_NONE = 10000 148 }; 149 150 // Technically users are allowed to configure this, but nobody ever would do that. 151 // So these can basically be thought of as aliases to ctrl+click, etc. 152 enum AlternateAction { 153 ChangeSize = AlternateChangeSize, // Default: Shift+Left click 154 ChangeSizeSnap = AlternateChangeSizeSnap, // Default: Shift+Z+Left click 155 PickFgNode = AlternatePickFgNode, // Default: Ctrl+Alt+Left click 156 PickBgNode = AlternatePickBgNode, // Default: Ctrl+Alt+Right click 157 PickFgImage = AlternatePickFgImage, // Default: Ctrl+Left click 158 PickBgImage = AlternatePickBgImage, // Default: Ctrl+Right click 159 Secondary = AlternateSecondary, 160 Third = AlternateThird, 161 Fourth = AlternateFourth, 162 Fifth = AlternateFifth, 163 NONE = 10000 164 }; 165 166 enum NodePaintAbility { 167 VECTOR, 168 CLONE, 169 PAINT, 170 UNPAINTABLE 171 }; 172 Q_ENUMS(NodePaintAbility) 173 174 static AlternateAction actionToAlternateAction(ToolAction action); 175 176 virtual void activateAlternateAction(AlternateAction action); 177 virtual void deactivateAlternateAction(AlternateAction action); 178 179 virtual void beginAlternateAction(KoPointerEvent *event, AlternateAction action); 180 virtual void continueAlternateAction(KoPointerEvent *event, AlternateAction action); 181 virtual void endAlternateAction(KoPointerEvent *event, AlternateAction action); 182 virtual void beginAlternateDoubleClickAction(KoPointerEvent *event, AlternateAction action); 183 virtual bool alternateActionSupportsHiResEvents(AlternateAction action) const; 184 185 void mousePressEvent(KoPointerEvent *event) override; 186 void mouseDoubleClickEvent(KoPointerEvent *event) override; 187 void mouseTripleClickEvent(KoPointerEvent *event) override; 188 void mouseReleaseEvent(KoPointerEvent *event) override; 189 void mouseMoveEvent(KoPointerEvent *event) override; 190 191 bool isActive() const; 192 193 KisTool::NodePaintAbility nodePaintAbility(); 194 195 public Q_SLOTS: 196 void activate(ToolActivation activation, const QSet<KoShape*> &shapes) override; 197 void deactivate() override; 198 void canvasResourceChanged(int key, const QVariant & res) override; 199 // Implement this slot in case there are any widgets or properties which need 200 // to be updated after certain operations, to reflect the inner state correctly. 201 // At the moment this is used for smoothing options in the freehand brush, but 202 // this will likely be expanded. 203 virtual void updateSettingsViews(); 204 205 Q_SIGNALS: 206 void isActiveChanged(bool isActivated); 207 208 protected: 209 // conversion methods are also needed by the paint information builder 210 friend class KisToolPaintingInformationBuilder; 211 212 /// Convert from native (postscript points) to image pixel 213 /// coordinates. 214 QPointF convertToPixelCoord(KoPointerEvent *e); 215 QPointF convertToPixelCoord(const QPointF& pt); 216 217 QPointF convertToPixelCoordAndAlignOnWidget(const QPointF& pt); 218 219 QPointF convertToPixelCoordAndSnap(KoPointerEvent *e, const QPointF &offset = QPointF(), bool useModifiers = true); 220 QPointF convertToPixelCoordAndSnap(const QPointF& pt, const QPointF &offset = QPointF()); 221 222 protected: 223 QPointF widgetCenterInWidgetPixels(); 224 QPointF convertDocumentToWidget(const QPointF& pt); 225 226 /// Convert from native (postscript points) to integer image pixel 227 /// coordinates. This rounds down (not truncate) the pixel coordinates and 228 /// should be used in preference to QPointF::toPoint(), which rounds, 229 /// to ensure the cursor acts on the pixel it is visually over. 230 QPoint convertToImagePixelCoordFloored(KoPointerEvent *e); 231 232 QRectF convertToPt(const QRectF &rect); 233 qreal convertToPt(qreal value); 234 235 QPointF viewToPixel(const QPointF &viewCoord) const; 236 /// Convert an integer pixel coordinate into a view coordinate. 237 /// The view coordinate is at the centre of the pixel. 238 QPointF pixelToView(const QPoint &pixelCoord) const; 239 240 /// Convert a floating point pixel coordinate into a view coordinate. 241 QPointF pixelToView(const QPointF &pixelCoord) const; 242 243 /// Convert a pixel rectangle into a view rectangle. 244 QRectF pixelToView(const QRectF &pixelRect) const; 245 246 /// Convert a pixel path into a view path 247 QPainterPath pixelToView(const QPainterPath &pixelPath) const; 248 249 /// Convert a pixel polygon into a view path 250 QPolygonF pixelToView(const QPolygonF &pixelPolygon) const; 251 252 /// Update the canvas for the given rectangle in image pixel coordinates. 253 void updateCanvasPixelRect(const QRectF &pixelRect); 254 255 /// Update the canvas for the given rectangle in view coordinates. 256 void updateCanvasViewRect(const QRectF &viewRect); 257 258 QWidget* createOptionWidget() override; 259 260 /** 261 * To determine whether this tool will change its behavior when 262 * modifier keys are pressed 263 */ 264 virtual bool listeningToModifiers(); 265 /** 266 * Request that this tool no longer listen to modifier keys 267 * (Responding to the request is optional) 268 */ 269 virtual void listenToModifiers(bool listen); 270 271 protected: 272 KisImageWSP image() const; 273 QCursor cursor() const; 274 275 /// Call this to set the document modified 276 void notifyModified() const; 277 278 KisImageWSP currentImage(); 279 KoPattern* currentPattern(); 280 KoAbstractGradient *currentGradient(); 281 KisNodeSP currentNode() const; 282 KisNodeList selectedNodes() const; 283 KoColor currentFgColor(); 284 KoColor currentBgColor(); 285 KisPaintOpPresetSP currentPaintOpPreset(); 286 KisFilterConfigurationSP currentGenerator(); 287 288 /// paint the path which is in view coordinates, default paint mode is XOR_MODE, BW_MODE is also possible 289 /// never apply transformations to the painter, they would be useless, if drawing in OpenGL mode. The coordinates in the path should be in view coordinates. 290 void paintToolOutline(QPainter * painter, const QPainterPath &path); 291 292 /// Checks checks if the current node is editable 293 bool nodeEditable(); 294 295 /// Checks checks if the selection is editable, only applies to local selection as global selection is always editable 296 bool selectionEditable(); 297 298 /// Override the cursor appropriately if current node is not editable 299 bool overrideCursorIfNotEditable(); 300 301 bool blockUntilOperationsFinished(); 302 void blockUntilOperationsFinishedForced(); 303 304 protected: 305 enum ToolMode: int { 306 HOVER_MODE, 307 PAINT_MODE, 308 SECONDARY_PAINT_MODE, 309 MIRROR_AXIS_SETUP_MODE, 310 GESTURE_MODE, 311 PAN_MODE, 312 OTHER, // tool-specific modes, like multibrush's symmetry axis setup 313 OTHER_1 314 }; 315 316 virtual void setMode(ToolMode mode); 317 virtual ToolMode mode() const; 318 void setCursor(const QCursor &cursor); 319 320 protected Q_SLOTS: 321 /** 322 * Called whenever the configuration settings change. 323 */ 324 virtual void resetCursorStyle(); 325 326 private: 327 struct Private; 328 Private* const d; 329 }; 330 331 332 333 #endif // KIS_TOOL_H_ 334