1 /* 2 * Xournal++ 3 * 4 * Handles Tools 5 * 6 * @author Xournal++ Team 7 * https://github.com/xournalpp/xournalpp 8 * 9 * @license GNU GPLv2 or later 10 */ 11 12 #pragma once 13 14 #include <array> 15 #include <functional> 16 #include <memory> 17 #include <string> 18 #include <vector> 19 20 #include <util/Color.h> 21 22 #include "settings/Settings.h" 23 #include "settings/SettingsEnums.h" 24 25 #include "Tool.h" 26 #include "XournalType.h" 27 28 // enum for ptrs that are dynamically pointing to different tools 29 /** 30 * @brief Enum for ptrs that are dynamically pointing to different tools 31 * - active: describes the currently active tool used for drawing 32 * - toolbar: describes the tool currently selected in the toolbar 33 * 34 * These tools are to be distinguished from ButtonTools which are mostly static 35 * apart from changes to the Config 36 * 37 */ 38 enum SelectedTool { active, toolbar }; 39 40 class ToolListener { 41 public: 42 /** 43 * @brief Update the Cursor and the Toolbar based on the active color 44 * 45 */ 46 virtual void toolColorChanged() = 0; 47 /** 48 * @brief Change the color of the current selection based on the active Tool 49 * 50 */ 51 virtual void changeColorOfSelection() = 0; 52 virtual void setCustomColorSelected() = 0; 53 virtual void toolSizeChanged() = 0; 54 virtual void toolFillChanged() = 0; 55 virtual void toolLineStyleChanged() = 0; 56 virtual void toolChanged() = 0; 57 58 virtual ~ToolListener(); 59 }; 60 61 class ActionHandler; 62 63 class ToolHandler { 64 public: 65 using ToolChangedCallback = std::function<void(ToolType)>; 66 ToolHandler(ToolListener* stateChangedListener, ActionHandler* actionHandler, Settings* settings); 67 virtual ~ToolHandler(); 68 69 /** 70 * @brief Reset the Button tool with a new tooltype 71 * 72 * @param type Tooltype to be set for the button 73 * @param button button which should be set 74 */ 75 void resetButtonTool(ToolType type, Button button); 76 77 /** 78 * Select the color for the active tool and under certain circumstances toolbar selected tool 79 * 80 * If the current tool does not have the color capability but the toolbar selected tool has 81 * the color can be set for the toolbar selected tool. 82 * This is indicated by a little pen shown on top of the color in the UI. 83 * 84 * @param color Color 85 * @param userSelection 86 * true if the user selected the color 87 * false if the color is selected by a tool change 88 * and therefore should not be applied to a selection 89 */ 90 void setColor(Color color, bool userSelection); 91 92 /** 93 * @brief Set the color for a Button 94 * This is a separate function from `setColor` to prevent mixup of different usecases. 95 * 96 * @param color color to be set 97 * @param button button to set color for 98 */ 99 void setButtonColor(Color color, Button button); 100 101 /** 102 * @brief Get the Color of the active tool 103 * 104 * @return Color of active tool 105 */ 106 Color getColor(); 107 108 /** 109 * @brief Get the Fill of the active tool 110 * 111 * @return -1 if fill is disabled 112 * @return int > 0 otherwise 113 */ 114 int getFill(); 115 116 /** 117 * @brief Get the Drawing Type one of selected tools 118 * 119 * @param selectedTool by the default the active one 120 * @return DrawingType 121 */ 122 DrawingType getDrawingType(SelectedTool selectedTool = SelectedTool::active); 123 124 /** 125 * @brief Set the Drawing Type of the toolbar selected tool 126 * @note It is safer to always set the toolbar tool as the active tool could be pointing to a button tool which 127 * could lead to hard to debug behaviour 128 * 129 * @param drawingType 130 */ 131 void setDrawingType(DrawingType drawingType); 132 133 /** 134 * @brief Set the Button Drawing Type of the button tool 135 * 136 * @param drawingType 137 * @param button button tool to be selected 138 */ 139 void setButtonDrawingType(DrawingType drawingType, Button button); 140 141 /** 142 * @brief Get the Line Style of active tool 143 * 144 * @return const LineStyle& 145 */ 146 const LineStyle& getLineStyle(); 147 148 /** 149 * @brief Get the Size of one of the selected tools 150 * 151 * @param selectedTool 152 * @return ToolSize 153 */ 154 ToolSize getSize(SelectedTool selectedTool = SelectedTool::active); 155 156 /** 157 * @brief Set the Size of toolbar selected tool 158 * @note It is safer to always set the toolbar tool as the active tool could be pointing to a button tool which 159 * could lead to hard to debug behaviour 160 * 161 * @param size is clamped to be within the defined range [0,5) 162 */ 163 void setSize(ToolSize size); 164 165 /** 166 * @brief Set the Button Size 167 * 168 * @param size is clamped to be within the defined range [0,5) 169 * @param button size will be applied to 170 */ 171 void setButtonSize(ToolSize size, Button button); 172 173 /** 174 * @brief Get the Thickness of the active tool 175 * 176 * @return double 177 */ 178 double getThickness(); 179 180 void setLineStyle(const LineStyle& style); 181 182 ToolSize getPenSize(); 183 ToolSize getEraserSize(); 184 ToolSize getHighlighterSize(); 185 void setPenSize(ToolSize size); 186 void setEraserSize(ToolSize size); 187 void setHighlighterSize(ToolSize size); 188 189 void setPenFillEnabled(bool fill, bool fireEvent = true); 190 bool getPenFillEnabled(); 191 void setPenFill(int alpha); 192 int getPenFill(); 193 194 void setHighlighterFillEnabled(bool fill, bool fireEvent = true); 195 bool getHighlighterFillEnabled(); 196 void setHighlighterFill(int alpha); 197 int getHighlighterFill(); 198 199 /** 200 * @brief Set the toolbar selected tool to the type 201 * This will also point the active tool to the same tool as the toolbar selected tool. 202 * This ensure that the toolbar and the cursor are correctly updated right after selecting the tool in the toolbar. 203 * 204 * @param type 205 */ 206 void selectTool(ToolType type); 207 208 /** 209 * @brief Get the Tool Type of active tool 210 * 211 * @return ToolType 212 */ 213 ToolType getToolType(); 214 215 /** 216 * @brief Update the Toolbar and the cursor based on the active Tool 217 * 218 */ 219 void fireToolChanged(); 220 221 /** 222 * @brief Listen for tool changes. 223 * 224 * Different from the listener given to the constructor -- [listener] 225 * here only listens for when the current tool is changed to another. 226 * 227 * @param listener A callback, called when the user/client 228 * changes tools. 229 */ 230 void addToolChangedListener(ToolChangedCallback listener); 231 232 /** 233 * @brief Get the Tool of a certain type 234 * 235 * @param type 236 * @return Tool& 237 */ 238 Tool& getTool(ToolType type); 239 240 /** 241 * @brief Set the Eraser Type of the Eraser in the toolbar 242 * @note Here the Eraser Tool in the toolbar is changed regardless of the the tool currently selected. 243 * This is necessary to allow users to change the Eraser type for their Button Tools while having another tool 244 * active. This is relevant in case of Eraser Type being set to "Don't Change" for the button. 245 * 246 * @param eraserType 247 */ 248 void setEraserType(EraserType eraserType); 249 250 /** 251 * @brief Set the Button Eraser Type 252 * 253 * @param eraserType 254 * @param button 255 */ 256 void setButtonEraserType(EraserType eraserType, Button button); 257 258 /** 259 * @brief Get the Eraser Type 260 * If the currently active Tool is an eraser it's type is returned (relevant for Buttontools). 261 * If the currently active Tool is not a eraser the erasertype of the eraser in the toolbar is obtained. 262 * 263 * @param selectedTool 264 * @return EraserType 265 */ 266 EraserType getEraserType(); 267 268 /** 269 * @brief Update the toolbar based on the Eraser type of the active tool 270 * 271 */ 272 void eraserTypeChanged(); 273 274 /** 275 * @brief Check whether the selectedTool has a certain capability 276 * 277 * @param cap 278 * @param selectedTool 279 * @return true if tool has the capability 280 * @return false if tool does not have the capability 281 */ 282 bool hasCapability(ToolCapabilities cap, SelectedTool selectedTool = SelectedTool::active); 283 284 /** 285 * @brief Check whether the active tool is a Drawing tool. 286 * Drawing tools are considered all tools that directly change the canvas. 287 * Right now these are: 288 * - Highlighter 289 * - Pen 290 * - Eraser 291 * 292 * @return true if active tool is a drawing tool 293 * @return false if active tool is no drawing tool 294 */ 295 bool isDrawingTool(); 296 297 void saveSettings(); 298 void loadSettings(); 299 300 /** 301 * @brief Point the active tool to the corresponding button tool if it is not already pointing to it 302 * 303 * @param button Button tool which should be pointed to 304 * @return true if the active toolpointer was changed 305 * @return false if the active toolpointer was not changed (it was already pointing to the right button) 306 */ 307 bool pointActiveToolToButtonTool(Button button); 308 /** 309 * @brief Point the active tool to tool selected in the toolbar 310 * 311 * @return true if the active toolpointer was changed 312 * @return false if the active toolpointer was not changed (it was already pointing to the toolbar-tool) 313 */ 314 bool pointActiveToolToToolbarTool(); 315 316 [[maybe_unused]] std::array<std::unique_ptr<Tool>, TOOL_COUNT> const& getTools() const; 317 318 /** 319 * Change the selection tools capabilities, depending on the selected elements 320 */ 321 void setSelectionEditTools(bool setColor, bool setSize, bool setFill); 322 323 const double* getToolThickness(ToolType type); 324 325 /** 326 * Returns whether the current tool will create an element that may only reside on a single page even when the 327 * pointer moves to another 328 * @return 329 */ 330 bool isSinglePageTool(); 331 332 protected: 333 void initTools(); 334 335 private: 336 std::array<std::unique_ptr<Tool>, TOOL_COUNT> tools; 337 338 /** 339 * @brief Get the Button Tool pointer based on enum 340 * 341 * @param button 342 * @return Tool* 343 */ 344 Tool* getButtonTool(Button button); 345 346 /** 347 * @brief Get the Selected Tool pointer based on enum 348 * 349 * @param selectedTool 350 * @return Tool* 351 */ 352 Tool* getSelectedTool(SelectedTool selectedTool); 353 354 // active Tool which is used for drawing 355 Tool* activeTool = nullptr; 356 357 // tool which is selected in the toolbar 358 Tool* toolbarSelectedTool = nullptr; 359 360 // tools set for the different Buttons 361 std::unique_ptr<Tool> stylusButton1Tool; 362 std::unique_ptr<Tool> stylusButton2Tool; 363 std::unique_ptr<Tool> eraserButtonTool; 364 std::unique_ptr<Tool> mouseMiddleButtonTool; 365 std::unique_ptr<Tool> mouseRightButtonTool; 366 std::unique_ptr<Tool> touchDrawingButtonTool; 367 368 std::vector<ToolChangedCallback> toolChangeListeners; 369 370 ToolListener* stateChangeListener = nullptr; 371 ActionHandler* actionHandler = nullptr; 372 Settings* settings = nullptr; 373 }; 374