1// Aseprite
2// Copyright (C) 2019-2020 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifndef APP_UI_EDITOR_SELECT_BOX_STATE_H_INCLUDED
9#define APP_UI_EDITOR_SELECT_BOX_STATE_H_INCLUDED
10#pragma once
11
12#include "app/ui/editor/editor_decorator.h"
13#include "app/ui/editor/ruler.h"
14#include "app/ui/editor/standby_state.h"
15#include "gfx/fwd.h"
16#include "ui/cursor_type.h"
17#include "ui/mouse_button.h"
18
19#include <string>
20#include <vector>
21
22namespace app {
23
24 class SelectBoxDelegate {
25 public:
26 virtual ~SelectBoxDelegate() { }
27
28 // Called each time the selected box is modified (e.g. rulers are
29 // moved).
30 virtual void onChangeRectangle(const gfx::Rect& rect) { }
31 virtual void onChangePadding(const gfx::Size& padding) { }
32
33 // Called only in QUICKBOX mode, when the user released the mouse
34 // button.
35 virtual void onQuickboxEnd(Editor* editor, const gfx::Rect& rect, ui::MouseButton button) { }
36 virtual void onQuickboxCancel(Editor* editor) { }
37
38 // Help text to be shown in the ContextBar
39 virtual std::string onGetContextBarHelp() { return ""; }
40 };
41
42 class SelectBoxState : public StandbyState
43 , public EditorDecorator {
44 enum { H1, H2, V1, V2, PH, PV };
45
46 public:
47 enum class Flags {
48 // Draw rulers at each edge of the current box
49 Rulers = 1,
50
51 // The outside of the current box must be darker (used in "Canvas Size" command)
52 DarkOutside = 2,
53
54 // Show a horizontal array of boxes starting from the current box
55 HGrid = 4,
56
57 // Show a vertical array of boxes starting from the current box
58 VGrid = 8,
59
60 // Show a grid starting from the current box
61 Grid = (HGrid | VGrid),
62
63 // Select the box as in selection tool, drawing a boxu
64 QuickBox = 16,
65
66 // Adding 2 rules more for padding. Used in Import Sprite Sheet render
67 PaddingRulers = 32,
68
69 // Include Partial Tiles at the end of the sprite? Used in Import Sprite Sheet render
70 IncludePartialTiles = 64
71 };
72
73 SelectBoxState(SelectBoxDelegate* delegate,
74 const gfx::Rect& rc,
75 Flags flags);
76 ~SelectBoxState();
77
78 Flags getFlags();
79 void setFlags(Flags flags);
80 void setFlag(Flags flag);
81 void clearFlag(Flags flag);
82
83 // Returns the bounding box arranged by the rulers.
84 gfx::Rect getBoxBounds() const;
85 void setBoxBounds(const gfx::Rect& rc);
86
87 // Get & Set the size of the padding rulers during Import Sprite Sheet Dialog
88 gfx::Size getPaddingBounds() const;
89 void setPaddingBounds(const gfx::Size& padding);
90
91 // EditorState overrides
92 virtual void onEnterState(Editor* editor) override;
93 virtual void onBeforePopState(Editor* editor) override;
94 virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override;
95 virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
96 virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
97 virtual bool onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) override;
98 virtual bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override;
99 virtual bool acceptQuickTool(tools::Tool* tool) override;
100 virtual bool requireBrushPreview() override;
101 virtual tools::Ink* getStateInk() const override;
102
103 // EditorDecorator overrides
104 virtual void postRenderDecorator(EditorPostRender* render) override;
105 virtual void getInvalidDecoratoredRegion(Editor* editor, gfx::Region& region) override;
106
107 // Disable Shift+click to draw straight lines with the Pencil tool
108 bool canCheckStartDrawingStraightLine() override { return false; }
109
110 private:
111 typedef std::vector<Ruler> Rulers;
112
113 void updateContextBar();
114 Ruler& oppositeRuler(const int rulerIndex);
115
116 // This returns a ui align value (e.g. LEFT for the ruler)
117 int hitTestRulers(Editor* editor,
118 const gfx::Point& mousePos,
119 const bool updateMovingRulers);
120
121 // Returns 0 if the mouse position on screen (mousePos) is not
122 // touching any ruler, or in other case returns the alignment of
123 // the ruler being touch (useful to show a proper mouse cursor).
124 int hitTestRuler(Editor* editor,
125 const Ruler& ruler,
126 const Ruler& oppRuler,
127 const gfx::Point& mousePos);
128
129 ui::CursorType cursorFromAlign(const int align) const;
130
131 bool hasFlag(Flags flag) const;
132
133 SelectBoxDelegate* m_delegate;
134 Rulers m_rulers;
135 Rulers m_startRulers;
136 int m_rulersDragAlign; // Used to calculate the correct mouse cursor
137 std::vector<int> m_movingRulers;
138 bool m_selectingBox;
139 ui::MouseButton m_selectingButton;
140 gfx::Point m_startingPos;
141 Flags m_flags;
142 };
143
144} // namespace app
145
146#endif // APP_UI_EDITOR_SELECT_BOX_STATE_H_INCLUDED
147