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 #include "core/components/tab_bar/tab_bar_component.h"
17 
18 #include "core/components/tab_bar/render_tab_bar.h"
19 #include "core/components/tab_bar/tab_bar_element.h"
20 
21 namespace OHOS::Ace {
22 namespace {
23 
24 constexpr int32_t ACTIVE_TEXT_SIZE = 24;
25 constexpr int32_t INACTIVE_TEXT_SIZE = 18;
26 constexpr double ACTIVE_TEXT_OPACITY = 0.9;
27 constexpr double INACTIVE_TEXT_OPACITY = 0.6;
28 constexpr Dimension BOTTOM_PADING(12, DimensionUnit::VP);
29 
30 constexpr int32_t BOTTOM_TAB_TEXT_SIZE = 10;
31 constexpr double BOTTOM_TAB_INACTIVE_TEXT_OPACITY = 0.4;
32 
33 } // namespace
34 
TabBarComponent(const std::list<RefPtr<Component>> & tabItems,const RefPtr<TabController> & controller,const RefPtr<BoxComponent> & indicator)35 TabBarComponent::TabBarComponent(const std::list<RefPtr<Component>>& tabItems, const RefPtr<TabController>& controller,
36     const RefPtr<BoxComponent>& indicator)
37     : ComponentGroup(tabItems)
38 {
39     controller_ = controller;
40     indicator_ = indicator;
41     focusIndicator_ = indicator;
42 }
43 
CreateElement()44 RefPtr<Element> TabBarComponent::CreateElement()
45 {
46     return AceType::MakeRefPtr<TabBarElement>();
47 }
48 
CreateRenderNode()49 RefPtr<RenderNode> TabBarComponent::CreateRenderNode()
50 {
51     return RenderTabBar::Create();
52 }
53 
InitStyle(const RefPtr<TabTheme> & theme)54 void TabBarComponent::InitStyle(const RefPtr<TabTheme>& theme)
55 {
56     if (!theme) {
57         return;
58     }
59 
60     focusRadiusDimension_ = theme->GetFocusIndicatorRadius();
61     focusAnimationColor_ = theme->GetFocusIndicatorColor();
62     gradientWidth_ = theme->GetGradientWidth();
63     activeIndicatorMinWidth_ = theme->GetActiveIndicatorMinWidth();
64 
65     Dimension labelPaddingDimension = theme->GetLabelPadding();
66     SetLabelPadding(
67         Edge(labelPaddingDimension.Value(), 0.0, labelPaddingDimension.Value(), 0.0, labelPaddingDimension.Unit()));
68 
69     auto paddingDimension = theme->GetPadding();
70     SetPadding(Edge(paddingDimension.Value(), 0.0, paddingDimension.Value(), 0.0, paddingDimension.Unit()));
71 
72     auto indicatorPadding = Edge(0.0, theme->GetActiveIndicatorPadding().Value(), 0.0,
73         theme->GetActiveIndicatorPadding().Value(), theme->GetActiveIndicatorPadding().Unit());
74     Color activeIndicatorColor = HasIndicatorColor() ? GetIndicatorColor() : theme->GetActiveIndicatorColor();
75     indicator_ = AceType::MakeRefPtr<TabBarIndicatorComponent>(
76         indicatorPadding, activeIndicatorColor, theme->GetActiveIndicatorWidth());
77     indicator_->SetPadding(indicatorPadding);
78 
79     auto deviceType = SystemProperties::GetDeviceType();
80     if (deviceType == DeviceType::TV) {
81         RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
82         Border border;
83         border.SetBorderRadius(Radius(theme->GetFocusIndicatorRadius()));
84         backDecoration->SetBorder(border);
85         backDecoration->SetBackgroundColor(theme->GetFocusIndicatorColor());
86 
87         focusIndicator_ = AceType::MakeRefPtr<TabBarIndicatorComponent>(backDecoration);
88         auto focusIndicatorPadding = Edge(theme->GetFocusIndicatorHorizontalPadding().Value(),
89             theme->GetFocusIndicatorVerticalPadding().Value(), theme->GetFocusIndicatorHorizontalPadding().Value(),
90             theme->GetFocusIndicatorVerticalPadding().Value(), theme->GetFocusIndicatorVerticalPadding().Unit());
91         focusIndicator_->SetPadding(focusIndicatorPadding);
92     } else if (deviceType == DeviceType::PHONE) {
93         focusIndicator_->SetPadding(indicatorPadding);
94     }
95 }
96 
InitNavigationBarStyle()97 void TabBarComponent::InitNavigationBarStyle()
98 {
99     usingDefaultStyle_ = true;
100     indicator_ = nullptr;
101     activeTextStyle_.SetTextColor(Color::FromRGBO(0, 0, 0, ACTIVE_TEXT_OPACITY));
102     activeTextStyle_.SetFontSize(Dimension(ACTIVE_TEXT_SIZE, DimensionUnit::VP));
103     activeTextStyle_.SetMaxLines(1);
104     activeTextStyle_.SetTextOverflow(TextOverflow::CLIP);
105 
106     inactiveTextStyle_.SetTextColor(Color::FromRGBO(0, 0, 0, BOTTOM_TAB_INACTIVE_TEXT_OPACITY));
107     inactiveTextStyle_.SetFontSize(Dimension(INACTIVE_TEXT_SIZE, DimensionUnit::VP));
108     inactiveTextStyle_.SetMaxLines(1);
109     inactiveTextStyle_.SetTextOverflow(TextOverflow::CLIP);
110     labelPadding_.SetBottom(BOTTOM_PADING);
111     itemAlignment_ = Alignment::BOTTOM_CENTER;
112     mode_ = TabBarMode::FIXED_START;
113 }
114 
InitBottomTabStyle(const RefPtr<TabTheme> & theme)115 void TabBarComponent::InitBottomTabStyle(const RefPtr<TabTheme>& theme)
116 {
117     usingDefaultStyle_ = true;
118     indicator_ = nullptr;
119     activeColor_ = theme->GetActiveIndicatorColor();
120     activeTextStyle_.SetTextColor(activeColor_);
121     activeTextStyle_.SetFontSize(Dimension(BOTTOM_TAB_TEXT_SIZE, DimensionUnit::VP));
122     activeTextStyle_.SetMaxLines(1);
123     activeTextStyle_.SetTextOverflow(TextOverflow::CLIP);
124 
125     inactiveColor_ = Color::FromRGBO(0, 0, 0, INACTIVE_TEXT_OPACITY);
126     inactiveTextStyle_.SetTextColor(inactiveColor_);
127     inactiveTextStyle_.SetFontSize(Dimension(BOTTOM_TAB_TEXT_SIZE, DimensionUnit::VP));
128     inactiveTextStyle_.SetMaxLines(1);
129     inactiveTextStyle_.SetTextOverflow(TextOverflow::CLIP);
130 }
131 
BuildItems(std::list<RefPtr<TabBarItemComponent>> & items)132 void TabBarComponent::BuildItems(std::list<RefPtr<TabBarItemComponent>>& items)
133 {
134     int32_t currentIndex = 0;
135     int32_t activeIndex = controller_ ? controller_->GetIndex() : 0;
136     for (const auto& pos : GetChildren()) {
137         RefPtr<TabBarItemComponent> box = AceType::DynamicCast<TabBarItemComponent>(pos);
138         if (!box) {
139             box = AceType::MakeRefPtr<TabBarItemComponent>(pos);
140         }
141         if (usingDefaultStyle_) {
142             if (currentIndex++ == activeIndex) {
143                 box->UpdateStyle(activeTextStyle_, activeColor_);
144             } else {
145                 box->UpdateStyle(inactiveTextStyle_, inactiveColor_);
146             }
147         }
148         box->SetEnableDebugBoundary(true);
149         box->SetPadding(labelPadding_);
150         if (mode_ == TabBarMode::FIXED) {
151             box->SetFlex(BoxFlex::FLEX_XY);
152         } else {
153             if (vertical_) {
154                 box->SetFlex(BoxFlex::FLEX_X);
155             } else {
156                 box->SetFlex(BoxFlex::FLEX_Y);
157             }
158         }
159         box->SetDeliverMinToChild(false);
160         box->SetAlignment(itemAlignment_);
161         items.push_back(box);
162     }
163 }
164 
UpdateItemStyle(const RefPtr<TabBarItemComponent> & item)165 void TabBarComponent::UpdateItemStyle(const RefPtr<TabBarItemComponent>& item)
166 {
167     RefPtr<TabBarItemComponent> box = item;
168     if (usingDefaultStyle_) {
169         box->UpdateStyle(inactiveTextStyle_, inactiveColor_);
170     }
171     box->SetPadding(labelPadding_);
172     if (mode_ == TabBarMode::FIXED) {
173         box->SetFlex(BoxFlex::FLEX_XY);
174     } else {
175         if (vertical_) {
176             box->SetFlex(BoxFlex::FLEX_X);
177         } else {
178             box->SetFlex(BoxFlex::FLEX_Y);
179         }
180     }
181     box->SetDeliverMinToChild(false);
182     box->SetAlignment(itemAlignment_);
183 }
184 
185 } // namespace OHOS::Ace