1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #pragma once
8
9 #include "ui/rp_widget.h"
10 #include "ui/effects/animations.h"
11 #include "base/object_ptr.h"
12 #include "base/flags.h"
13
14 namespace Window {
15 class SectionMemento;
16 struct SectionShow;
17 } // namespace Window
18
19 namespace style {
20 struct Box;
21 } // namespace style
22
23 namespace Ui {
24
25 class BoxContent;
26
27 enum class LayerOption {
28 CloseOther = (1 << 0),
29 KeepOther = (1 << 1),
30 ShowAfterOther = (1 << 2),
31 };
32 using LayerOptions = base::flags<LayerOption>;
is_flag_type(LayerOption)33 inline constexpr auto is_flag_type(LayerOption) { return true; };
34
35 class LayerWidget : public Ui::RpWidget {
36 public:
37 using RpWidget::RpWidget;
38
39 virtual void parentResized() = 0;
showFinished()40 virtual void showFinished() {
41 }
42 void setInnerFocus();
setClosing()43 bool setClosing() {
44 if (!_closing) {
45 _closing = true;
46 closeHook();
47 return true;
48 }
49 return false;
50 }
51
52 bool overlaps(const QRect &globalRect);
53
setClosedCallback(Fn<void ()> callback)54 void setClosedCallback(Fn<void()> callback) {
55 _closedCallback = std::move(callback);
56 }
setResizedCallback(Fn<void ()> callback)57 void setResizedCallback(Fn<void()> callback) {
58 _resizedCallback = std::move(callback);
59 }
takeToThirdSection()60 virtual bool takeToThirdSection() {
61 return false;
62 }
showSectionInternal(not_null<::Window::SectionMemento * > memento,const::Window::SectionShow & params)63 virtual bool showSectionInternal(
64 not_null<::Window::SectionMemento*> memento,
65 const ::Window::SectionShow ¶ms) {
66 return false;
67 }
closeByOutsideClick()68 virtual bool closeByOutsideClick() const {
69 return true;
70 }
71
72 protected:
closeLayer()73 void closeLayer() {
74 if (const auto callback = base::take(_closedCallback)) {
75 callback();
76 }
77 }
78 void mousePressEvent(QMouseEvent *e) override;
79 void resizeEvent(QResizeEvent *e) override;
doSetInnerFocus()80 virtual void doSetInnerFocus() {
81 setFocus();
82 }
closeHook()83 virtual void closeHook() {
84 }
85
86 private:
87 bool _closing = false;
88 Fn<void()> _closedCallback;
89 Fn<void()> _resizedCallback;
90
91 };
92
93 class LayerStackWidget : public Ui::RpWidget {
94 public:
95 LayerStackWidget(QWidget *parent);
96
97 void finishAnimating();
98 rpl::producer<> hideFinishEvents() const;
99
100 void setStyleOverrides(
101 const style::Box *boxSt,
102 const style::Box *layerSt);
boxStyleOverrideLayer()103 [[nodiscard]] const style::Box *boxStyleOverrideLayer() const {
104 return _layerSt;
105 }
boxStyleOverride()106 [[nodiscard]] const style::Box *boxStyleOverride() const {
107 return _boxSt;
108 }
109
110 void showBox(
111 object_ptr<BoxContent> box,
112 LayerOptions options,
113 anim::type animated);
114 void showLayer(
115 std::unique_ptr<LayerWidget> layer,
116 LayerOptions options,
117 anim::type animated);
118 void showSpecialLayer(
119 object_ptr<LayerWidget> layer,
120 anim::type animated);
121 void showMainMenu(
122 object_ptr<LayerWidget> menu,
123 anim::type animated);
124 bool takeToThirdSection();
125
126 bool canSetFocus() const;
127 void setInnerFocus();
128
129 bool contentOverlapped(const QRect &globalRect);
130
131 void hideSpecialLayer(anim::type animated);
132 void hideLayers(anim::type animated);
133 void hideAll(anim::type animated);
134 void hideTopLayer(anim::type animated);
135 void setHideByBackgroundClick(bool hide);
136 void removeBodyCache();
137
138 // If you need to divide animated hideAll().
139 void hideAllAnimatedPrepare();
140 void hideAllAnimatedRun();
141
142 bool showSectionInternal(
143 not_null<::Window::SectionMemento*> memento,
144 const ::Window::SectionShow ¶ms);
145
146 bool layerShown() const;
147 const LayerWidget *topShownLayer() const;
148
149 ~LayerStackWidget();
150
151 protected:
152 void keyPressEvent(QKeyEvent *e) override;
153 void mousePressEvent(QMouseEvent *e) override;
154 void resizeEvent(QResizeEvent *e) override;
155
156 private:
157 void appendLayer(
158 std::unique_ptr<LayerWidget> layer,
159 anim::type animated);
160 void prependLayer(
161 std::unique_ptr<LayerWidget> layer,
162 anim::type animated);
163 void replaceLayer(
164 std::unique_ptr<LayerWidget> layer,
165 anim::type animated);
166 void backgroundClicked();
167
168 LayerWidget *pushLayer(
169 std::unique_ptr<LayerWidget> layer,
170 anim::type animated);
171 void showFinished();
172 void hideCurrent(anim::type animated);
173 void closeLayer(not_null<LayerWidget*> layer);
174
175 enum class Action {
176 ShowMainMenu,
177 ShowSpecialLayer,
178 ShowLayer,
179 HideSpecialLayer,
180 HideLayer,
181 HideAll,
182 };
183 template <typename SetupNew, typename ClearOld>
184 bool prepareAnimation(
185 SetupNew &&setupNewWidgets,
186 ClearOld &&clearOldWidgets,
187 Action action,
188 anim::type animated);
189 template <typename SetupNew, typename ClearOld>
190 void startAnimation(
191 SetupNew &&setupNewWidgets,
192 ClearOld &&clearOldWidgets,
193 Action action,
194 anim::type animated);
195
196 void prepareForAnimation();
197 void animationDone();
198
199 void setCacheImages();
200 void clearLayers();
201 void clearSpecialLayer();
202 void initChildLayer(LayerWidget *layer);
203 void updateLayerBoxes();
204 void fixOrder();
205 void sendFakeMouseEvent();
206 void clearClosingLayers();
207
currentLayer()208 LayerWidget *currentLayer() {
209 return _layers.empty() ? nullptr : _layers.back().get();
210 }
currentLayer()211 const LayerWidget *currentLayer() const {
212 return const_cast<LayerStackWidget*>(this)->currentLayer();
213 }
214
215 std::vector<std::unique_ptr<LayerWidget>> _layers;
216 std::vector<std::unique_ptr<LayerWidget>> _closingLayers;
217
218 object_ptr<LayerWidget> _specialLayer = { nullptr };
219 object_ptr<LayerWidget> _mainMenu = { nullptr };
220
221 class BackgroundWidget;
222 object_ptr<BackgroundWidget> _background;
223
224 const style::Box *_boxSt = nullptr;
225 const style::Box *_layerSt = nullptr;
226 bool _hideByBackgroundClick = true;
227
228 rpl::event_stream<> _hideFinishStream;
229
230 };
231
232 } // namespace Ui
233