1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NAVIGATION_BAR_NAVIGATION_BAR_COMPONENT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NAVIGATION_BAR_NAVIGATION_BAR_COMPONENT_H
18 
19 #include <cstdint>
20 #include "core/components/button/button_component.h"
21 #include "core/components/flex/flex_component.h"
22 #include "core/components/navigation_bar/navigation_bar_component_base.h"
23 #include "core/components/navigation_bar/navigation_bar_theme.h"
24 #include "core/components/text/text_component.h"
25 #ifndef WEARABLE_PRODUCT
26 #include "core/components/menu/menu_component.h"
27 #include "core/components/navigation_bar/render_collapsing_navigation_bar.h"
28 #include "core/components/select/select_component.h"
29 #include "core/components/tab_bar/tab_bar_component.h"
30 #endif
31 
32 namespace OHOS::Ace {
33 namespace {
34 constexpr int32_t DEFAULT_HEIGHT_DIMENSION = 112; // default height in vp
35 } // namespace
36 
37 using NavigationBarShowFunc = std::function<void()>;
38 using NavigationBarHideFunc = std::function<void()>;
39 
40 class NavigationBarController : public virtual AceType {
41     DECLARE_ACE_TYPE(NavigationBarController, AceType);
42 
43 public:
Show()44     void Show() const
45     {
46         if (showFunc_) {
47             showFunc_();
48         }
49     }
50 
Hide()51     void Hide() const
52     {
53         if (hideFunc_) {
54             hideFunc_();
55         }
56     }
57 
SetFunction(const NavigationBarShowFunc & showFunc,const NavigationBarHideFunc & hideFunc)58     void SetFunction(const NavigationBarShowFunc& showFunc, const NavigationBarHideFunc& hideFunc)
59     {
60         showFunc_ = showFunc;
61         hideFunc_ = hideFunc;
62     }
63 
64 private:
65     NavigationBarShowFunc showFunc_;
66     NavigationBarHideFunc hideFunc_;
67 };
68 
69 enum class NavigationBarType {
70     NORMAL = 0,
71     EMPHASIZE,
72 };
73 
74 class TitleBarBuilder;
75 
76 struct NavigationBarData : public virtual AceType {
77     DECLARE_ACE_TYPE(NavigationBarData, AceType);
78 
79 public:
80     NavigationBarData() = default;
81     ~NavigationBarData() = default;
82 
83     std::string header;
84     std::string title;
85     std::string subTitle;
86     bool backEnabled = false;
87     EventMarker backClickMarker;
88     std::string logo;
89     std::string startIcon;
90     EventMarker startClickMarker;
91     std::string endIcon;
92     EventMarker endClickMarker;
93     Color titleColor;
94     Color subTitleColor;
95     std::optional<Color> imageFill;
96     NavigationBarType type = NavigationBarType::NORMAL;
97 
98 #ifndef WEARABLE_PRODUCT
99     RefPtr<TabBarComponent> tabBar;
100     RefPtr<SelectComponent> selectPopup;
101     RefPtr<MenuComponent> menu;
102     std::list<RefPtr<OptionComponent>> allMenuItems;
103 #endif
104 
105     RefPtr<NavigationBarController> controller;
106     RefPtr<NavigationBarTheme> theme;
107 };
108 
109 class NavigationBarComponent : public ComposedComponent {
110     DECLARE_ACE_TYPE(NavigationBarComponent, ComposedComponent);
111 
112 public:
113     struct MenuItemInBar {
114         std::string value;
115         EventMarker clickEvent;
116         RefPtr<ButtonComponent> button;
117     };
118 
119     NavigationBarComponent(const ComposeId& id, const std::string& name);
120     ~NavigationBarComponent() override = default;
121 
122     void InitStyle(const RefPtr<NavigationBarTheme>& theme);
123     RefPtr<Element> CreateElement() override;
124     RefPtr<Component> Build(const WeakPtr<PipelineContext>& context);
125 
126 #ifndef WEARABLE_PRODUCT
GetMenu()127     RefPtr<MenuComponent> GetMenu() const
128     {
129         return data_->menu;
130     }
131 
GetMenuItemsInBar()132     const std::map<std::string, NavigationBarComponent::MenuItemInBar>& GetMenuItemsInBar() const
133     {
134         return menuItemsInBar_;
135     }
136 
GetMoreButton()137     const RefPtr<ButtonComponent>& GetMoreButton() const
138     {
139         return moreButton_;
140     }
141 #endif
GetData()142     const RefPtr<NavigationBarData>& GetData() const
143     {
144         return data_;
145     }
146 
147 private:
148     WeakPtr<PipelineContext> context_;
149     RefPtr<NavigationBarData> data_;
150 #ifndef WEARABLE_PRODUCT
151     std::map<std::string, NavigationBarComponent::MenuItemInBar> menuItemsInBar_;
152     RefPtr<ButtonComponent> moreButton_;
153 #endif
154 };
155 
156 class CommonBuilder : public NavigationBarComponentBase {
157 public:
158     CommonBuilder() = delete;
159     virtual ~CommonBuilder() = default;
CommonBuilder(const RefPtr<NavigationBarTheme> & theme)160     explicit CommonBuilder(const RefPtr<NavigationBarTheme>& theme)
161         : theme_(theme), menuZoneSize_(theme_->GetMenuZoneSize()), menuIconSize_(theme_->GetMenuIconSize())
162     {}
SetContext(const WeakPtr<PipelineContext> & context)163     void SetContext(const WeakPtr<PipelineContext>& context)
164     {
165         context_ = context;
166     }
SetId(const ComposeId & id)167     void SetId(const ComposeId& id)
168     {
169         id_ = id;
170     }
SetTextDirection(const TextDirection & direction)171     void SetTextDirection(const TextDirection& direction)
172     {
173         direction_ = direction;
174     }
175 
176 protected:
177     RefPtr<NavigationBarTheme> theme_;
178     ComposeId id_;
179     Dimension menuZoneSize_;
180     Dimension menuIconSize_;
181     TextDirection direction_ = TextDirection::LTR;
182 };
183 
184 class TitleBarBuilder : public virtual AceType, public virtual CommonBuilder {
185     DECLARE_ACE_TYPE(TitleBarBuilder, AceType);
186 
187 public:
TitleBarBuilder(const RefPtr<NavigationBarData> & data)188     explicit TitleBarBuilder(const RefPtr<NavigationBarData>& data)
189         : CommonBuilder(data->theme), height_(data->theme->GetHeight()), title_(data->title),
190           titleColor_(data->titleColor), subTitle_(data->subTitle), subTitleColor_(data->subTitleColor),
191           subTitleFontSize_(data->theme->GetSubTitleFontSize())
192     {}
193     virtual ~TitleBarBuilder() = default;
194     virtual RefPtr<Component> Build() = 0;
195 
196 protected:
197 #ifndef WEARABLE_PRODUCT
BuildContainer(const RefPtr<Component> & child)198     RefPtr<BoxComponent> BuildContainer(const RefPtr<Component>& child)
199     {
200         auto boxContainer = AceType::MakeRefPtr<BoxComponent>();
201         boxContainer->SetHeight(height_.Value(), height_.Unit());
202         boxContainer->SetChild(child);
203         boxContainer->SetPadding(padding_);
204         return boxContainer;
205     }
206 #endif
207 
208     Edge padding_;
209     Dimension height_;
210 
211     std::string title_;
212     Color titleColor_;
213     Dimension titleFontSize_;
214 
215     std::string subTitle_;
216     Color subTitleColor_;
217     Dimension subTitleFontSize_;
218 };
219 
220 class WatchTitleBarBuilder : public TitleBarBuilder {
221     DECLARE_ACE_TYPE(WatchTitleBarBuilder, TitleBarBuilder);
222 
223 public:
WatchTitleBarBuilder(const RefPtr<NavigationBarData> & data)224     explicit WatchTitleBarBuilder(const RefPtr<NavigationBarData>& data)
225         : CommonBuilder(data->theme), TitleBarBuilder(data), logoSrc_(data->logo)
226     {}
227     ~WatchTitleBarBuilder() = default;
228     RefPtr<Component> Build() override;
229 
230 private:
231     void BuildTitle(const RefPtr<ComponentGroup>& parent);
232     void BuildSubTitle(const RefPtr<ComponentGroup>& parent);
233     void BuildLogo(const RefPtr<ComponentGroup>& parent);
234 
235     std::string logoSrc_;
236 };
237 
238 #ifndef WEARABLE_PRODUCT
239 class TabBarBuilder : public virtual CommonBuilder {
240 public:
TabBarBuilder(const RefPtr<NavigationBarData> & data)241     explicit TabBarBuilder(const RefPtr<NavigationBarData>& data) : CommonBuilder(data->theme), tabBar_(data->tabBar) {}
242     ~TabBarBuilder() = default;
243 
244     void BuildTabBar(const RefPtr<ComponentGroup>& parent);
245 
246 protected:
247     RefPtr<TabBarComponent> tabBar_;
248 };
249 
250 class TitleBarMenuBuilder : public virtual AceType, public virtual CommonBuilder {
251     DECLARE_ACE_TYPE(TitleBarMenuBuilder, AceType);
252 
253 public:
TitleBarMenuBuilder(const RefPtr<NavigationBarData> & data)254     explicit TitleBarMenuBuilder(const RefPtr<NavigationBarData>& data)
255         : CommonBuilder(data->theme), menu_(data->menu), imageFill_(data->imageFill),
256           allMenuItems_(data->allMenuItems) {}
257     ~TitleBarMenuBuilder() = default;
258 
GetMenuItemsInBar()259     const std::map<std::string, NavigationBarComponent::MenuItemInBar>& GetMenuItemsInBar() const
260     {
261         return menuItemsInBar_;
262     }
GetMoreButton()263     const RefPtr<ButtonComponent>& GetMoreButton() const
264     {
265         return moreButton_;
266     }
GetMenu()267     const RefPtr<MenuComponent>& GetMenu() const
268     {
269         return menu_;
270     }
271 
272 protected:
273     bool AddMenu(const RefPtr<ComponentGroup>& container, bool canCollapse = true);
274 
275     RefPtr<MenuComponent> menu_;
276     std::optional<Color> imageFill_;
277 
278 private:
279     void MoveMenuItemsToBar(const RefPtr<ComponentGroup>& container);
280     void AddCollapseMenu(const RefPtr<ComponentGroup>& container);
281 
282     std::map<std::string, NavigationBarComponent::MenuItemInBar> menuItemsInBar_;
283     std::list<RefPtr<OptionComponent>> allMenuItems_;
284     RefPtr<ButtonComponent> moreButton_;
285 };
286 
287 class TVTitleBarBuilder : public TitleBarBuilder, public TitleBarMenuBuilder {
288     DECLARE_ACE_TYPE(TVTitleBarBuilder, TitleBarBuilder, TitleBarMenuBuilder);
289 
290 public:
TVTitleBarBuilder(const RefPtr<NavigationBarData> & data)291     explicit TVTitleBarBuilder(const RefPtr<NavigationBarData>& data)
292         : CommonBuilder(data->theme), TitleBarBuilder(data), TitleBarMenuBuilder(data)
293     {}
294     ~TVTitleBarBuilder() = default;
295 
296     RefPtr<Component> Build() override;
297 
298 private:
299     void BuildTitle(const RefPtr<ComponentGroup>& parent);
300     void BuildSubTitle(const RefPtr<ComponentGroup>& parent, const RefPtr<ComponentGroup>& leftContainer);
301 };
302 
303 class PhoneTitleBarBuilder : public TitleBarBuilder, public TitleBarMenuBuilder, public TabBarBuilder {
304     DECLARE_ACE_TYPE(PhoneTitleBarBuilder, TitleBarBuilder, TitleBarMenuBuilder);
305 
306 public:
PhoneTitleBarBuilder(const RefPtr<NavigationBarData> & data)307     explicit PhoneTitleBarBuilder(const RefPtr<NavigationBarData>& data)
308         : CommonBuilder(data->theme), TitleBarBuilder(data), TitleBarMenuBuilder(data), TabBarBuilder(data),
309           selectPopup_(data->selectPopup)
310     {
311         titleFontSize_ = data->theme->GetTitleFontSize();
312     }
313     ~PhoneTitleBarBuilder() = default;
314 
315     RefPtr<Component> Build() override = 0;
GetTitleComposed()316     const RefPtr<ComposedComponent>& GetTitleComposed() const
317     {
318         return titleComposed_;
319     }
GetSubtitleComposed()320     const RefPtr<ComposedComponent>& GetSubtitleComposed() const
321     {
322         return subTitleComposed_;
323     }
324 
325 protected:
326     RefPtr<Component> BuildTitle(double padding = 0.0);
327     void BuildSelectPopup(const RefPtr<ComponentGroup>& parent);
328     void BuildTitleZone(const RefPtr<ComponentGroup>& parent, double padding = 0.0);
329 
330     RefPtr<SelectComponent> selectPopup_;
331     std::string header_;
332     RefPtr<ComposedComponent> titleComposed_;
333     RefPtr<ComposedComponent> subTitleComposed_;
334 };
335 
336 class EmphasizeTitleBarBuilder : public PhoneTitleBarBuilder {
337     DECLARE_ACE_TYPE(EmphasizeTitleBarBuilder, PhoneTitleBarBuilder);
338 
339 public:
EmphasizeTitleBarBuilder(const RefPtr<NavigationBarData> & data)340     explicit EmphasizeTitleBarBuilder(const RefPtr<NavigationBarData>& data)
341         : CommonBuilder(data->theme), PhoneTitleBarBuilder(data)
342     {
343         height_ = Dimension(DEFAULT_HEIGHT_DIMENSION, DimensionUnit::VP);
344         padding_.SetLeft(theme_->GetMaxPaddingStart());
345         padding_.SetRight(theme_->GetDefaultPaddingEnd());
346         titleFontSize_ = theme_->GetTitleFontSizeBig();
347         header_ = data->header;
348     }
349     ~EmphasizeTitleBarBuilder() = default;
350 
351     RefPtr<Component> Build() override;
352 };
353 
354 class NormalTitleBarBuilder : public PhoneTitleBarBuilder {
355     DECLARE_ACE_TYPE(NormalTitleBarBuilder, PhoneTitleBarBuilder);
356 
357 public:
NormalTitleBarBuilder(const RefPtr<NavigationBarData> & data)358     explicit NormalTitleBarBuilder(const RefPtr<NavigationBarData>& data)
359         : CommonBuilder(data->theme), PhoneTitleBarBuilder(data), backEnabled_(data->backEnabled),
360           backClickMarker_(data->backClickMarker), logoSrc_(data->logo), startIconSrc_(data->startIcon),
361           startClickMarker_(data->startClickMarker), endIconSrc_(data->endIcon), endClickMarker_(data->endClickMarker),
362           imageFill_(data->imageFill)
363     {}
364     ~NormalTitleBarBuilder() = default;
365 
366     RefPtr<Component> Build() override;
367     void BindDefaultBackEvent(const WeakPtr<PipelineContext>& context);
368 
369 private:
370     void BuildStartZone(const RefPtr<RowComponent>& parent);
371     void BuildLogo(const RefPtr<RowComponent>& parent);
372     void BuildEndZone(const RefPtr<RowComponent>& parent);
373 
374     bool backEnabled_ = false;
375     EventMarker backClickMarker_;
376     std::string logoSrc_;
377     std::string startIconSrc_;
378     EventMarker startClickMarker_;
379     std::string endIconSrc_;
380     EventMarker endClickMarker_;
381     std::optional<Color> imageFill_;
382 };
383 
384 class CollapsingNavigationBarComponent : public ComponentGroup {
385     DECLARE_ACE_TYPE(CollapsingNavigationBarComponent, ComponentGroup);
386 
387 public:
388     CollapsingNavigationBarComponent() = default;
CollapsingNavigationBarComponent(const RefPtr<ComposedComponent> & title,const RefPtr<ComposedComponent> & subTitle,const EventMarker & changeEvent)389     CollapsingNavigationBarComponent(const RefPtr<ComposedComponent>& title, const RefPtr<ComposedComponent>& subTitle,
390         const EventMarker& changeEvent)
391         : titleComposed_(title), subTitleComposed_(subTitle), titleModeChangedEvent_(changeEvent)
392     {}
CollapsingNavigationBarComponent(const RefPtr<EmphasizeTitleBarBuilder> & builder)393     explicit CollapsingNavigationBarComponent(const RefPtr<EmphasizeTitleBarBuilder>& builder)
394     {
395         titleComposed_ = builder->GetTitleComposed();
396         subTitleComposed_ = builder->GetSubtitleComposed();
397     }
398     ~CollapsingNavigationBarComponent() override = default;
CreateElement()399     RefPtr<Element> CreateElement() override
400     {
401         return AceType::MakeRefPtr<ComponentGroupElement>();
402     }
403 
CreateRenderNode()404     RefPtr<RenderNode> CreateRenderNode() override
405     {
406         return AceType::MakeRefPtr<RenderCollapsingNavigationBar>();
407     }
GetTitleComposed()408     const RefPtr<ComposedComponent>& GetTitleComposed() const
409     {
410         return titleComposed_;
411     }
GetSubtitleComposed()412     const RefPtr<ComposedComponent>& GetSubtitleComposed() const
413     {
414         return subTitleComposed_;
415     }
GetMinHeight()416     const Dimension& GetMinHeight() const
417     {
418         return minHeight_;
419     }
SetMinHeight(const Dimension & minHeight)420     void SetMinHeight(const Dimension& minHeight)
421     {
422         minHeight_ = minHeight;
423     }
GetTitleModeChangedEvent()424     const EventMarker& GetTitleModeChangedEvent() const
425     {
426         return titleModeChangedEvent_;
427     }
428 
429 private:
430     RefPtr<TextComponent> titleComponent_;
431     RefPtr<ComposedComponent> titleComposed_;
432     RefPtr<ComposedComponent> subTitleComposed_;
433     Dimension minHeight_;
434     EventMarker titleModeChangedEvent_;
435 };
436 
437 #endif
438 
439 } // namespace OHOS::Ace
440 
441 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NAVIGATION_BAR_NAVIGATION_BAR_COMPONENT_H
442