1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9 
10 #include "base/unique_qptr.h"
11 #include "editor/photo_editor_inner_common.h"
12 
13 #include <QGraphicsItem>
14 
15 class QGraphicsSceneHoverEvent;
16 class QGraphicsSceneMouseEvent;
17 class QStyleOptionGraphicsItem;
18 
19 namespace Ui {
20 class PopupMenu;
21 } // namespace Ui
22 
23 namespace Editor {
24 
25 class NumberedItem : public QGraphicsItem {
26 public:
27 	enum class Status {
28 		Normal,
29 		Undid,
30 		Removed,
31 	};
32 
33 	enum { Type = UserType + 1 };
34 	using QGraphicsItem::QGraphicsItem;
35 
36 	int type() const override;
37 	void setNumber(int number);
38 	[[nodiscard]] int number() const;
39 
40 	[[nodiscard]] Status status() const;
41 	void setStatus(Status status);
42 	[[nodiscard]] bool isNormalStatus() const;
43 	[[nodiscard]] bool isUndidStatus() const;
44 	[[nodiscard]] bool isRemovedStatus() const;
45 
46 	virtual void save(SaveState state);
47 	virtual void restore(SaveState state);
48 	virtual bool hasState(SaveState state) const;
49 private:
50 	int _number = 0;
51 	Status _status = Status::Normal;
52 };
53 
54 class ItemBase : public NumberedItem {
55 public:
56 	enum { Type = UserType + 2 };
57 
58 	struct Data {
59 		float64 initialZoom = 0.;
60 		std::shared_ptr<float64> zPtr;
61 		int size = 0;
62 		int x = 0;
63 		int y = 0;
64 		bool flipped = false;
65 		int rotation = 0;
66 		QSize imageSize;
67 	};
68 
69 	ItemBase(Data data);
70 	QRectF boundingRect() const override;
71 	void paint(
72 		QPainter *p,
73 		const QStyleOptionGraphicsItem *option,
74 		QWidget *widget) override;
75 	int type() const override;
76 
77 	bool flipped() const;
78 	void setFlip(bool value);
79 
80 	void updateZoom(float64 zoom);
81 
82 	bool hasState(SaveState state) const override;
83 	void save(SaveState state) override;
84 	void restore(SaveState state) override;
85 protected:
86 	enum HandleType {
87 		None,
88 		Left,
89 		Right,
90 	};
91 	void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
92 	void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
93 	void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
94 	void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
95 	void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
96 	void keyPressEvent(QKeyEvent *e) override;
97 
98 	using Action = void(ItemBase::*)();
99 	void performForSelectedItems(Action action);
100 	void actionFlip();
101 	void actionDelete();
102 	void actionDuplicate();
103 
104 	QRectF contentRect() const;
105 	QRectF innerRect() const;
106 	float64 size() const;
107 	float64 horizontalSize() const;
108 	float64 verticalSize() const;
109 	void setAspectRatio(float64 aspectRatio);
110 
111 	virtual void performFlip();
112 	virtual std::shared_ptr<ItemBase> duplicate(Data data) const = 0;
113 private:
114 	HandleType handleType(const QPointF &pos) const;
115 	QRectF rightHandleRect() const;
116 	QRectF leftHandleRect() const;
117 	bool isHandling() const;
118 	void updateVerticalSize();
119 	void updatePens(QPen pen);
120 	void handleActionKey(not_null<QKeyEvent*> e);
121 
122 	Data generateData() const;
123 	void applyData(const Data &data);
124 
125 	const std::shared_ptr<float64> _lastZ;
126 	const QSize _imageSize;
127 
128 	struct {
129 		QPen select;
130 		QPen selectInactive;
131 		QPen handle;
132 		QPen handleInactive;
133 	} _pens;
134 
135 	base::unique_qptr<Ui::PopupMenu> _menu;
136 
137 	struct {
138 		Data data;
139 		float64 zValue = 0.;
140 		NumberedItem::Status status;
141 	} _saved, _keeped;
142 
143 	struct {
144 		int min = 0;
145 		int max = 0;
146 	} _sizeLimits;
147 	float64 _scaledHandleSize = 1.0;
148 	QMarginsF _scaledInnerMargins;
149 
150 	float64 _horizontalSize = 0;
151 	float64 _verticalSize = 0;
152 	float64 _aspectRatio = 1.0;
153 	HandleType _handle = HandleType::None;
154 
155 	bool _flipped = false;
156 
157 };
158 
159 } // namespace Editor
160