1 /*
2  * Copyright (c) 2021 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/select/select_component.h"
17 
18 #include "core/components/clip/clip_component.h"
19 #include "core/components/flex/flex_item_component.h"
20 #include "core/components/select/render_select.h"
21 #include "core/components/select/select_element.h"
22 #include "core/components/triangle/triangle_component.h"
23 
24 namespace OHOS::Ace {
25 namespace {
26 
27 constexpr uint32_t SELECT_ITSELF_TEXT_LINES = 1;
28 
29 }
30 
SelectComponent()31 SelectComponent::SelectComponent() : SoleChildComponent()
32 {
33     popup_ = AceType::MakeRefPtr<SelectPopupComponent>();
34     // the round radius is half of height which is 40dp.
35     border_.SetBorderRadius(Radius(20.0_vp));
36 }
37 
InitTheme(const RefPtr<ThemeManager> & themeManager)38 void SelectComponent::InitTheme(const RefPtr<ThemeManager>& themeManager)
39 {
40     if (!themeManager) {
41         return;
42     }
43     popup_->InitTheme(themeManager);
44 #if defined(PREVIEW)
45     popup_->SetSelectPopupId(GetNodeId());
46 #endif
47     auto selectTheme = themeManager->GetTheme<SelectTheme>();
48     if (!selectTheme) {
49         return;
50     }
51     theme_ = selectTheme->clone();
52     theme_->SetFontWeight(FontWeight::W500);
53 
54     innerPadding_ =
55         Edge(8.0, 9.25, 8.0, 9.25, DimensionUnit::VP); // the best effect for round triangle.
56 }
57 
Initialize()58 bool SelectComponent::Initialize()
59 {
60     if (!tipText_) {
61         LOGE("can not initialize, tip text is null.");
62         return false;
63     }
64 
65     RefPtr<TriangleComponent> icon = AceType::MakeRefPtr<TriangleComponent>();
66     icon->SetWidth(10.0_vp); // the with is 10dp from doc.
67     icon->SetHeight(6.0_vp); // the height is 7dp from doc. reduce 1dp for triangle inner.
68 
69     RefPtr<BoxComponent> space = AceType::MakeRefPtr<BoxComponent>();
70     space->SetDeliverMinToChild(false);
71     space->SetAlignment(Alignment::CENTER);
72     // the space between text and triangle is 8dp from doc.
73     Edge spaceEdge(8.0, 0.0, 0.0, 0.0, DimensionUnit::VP);
74     if (GetTextDirection() == TextDirection::RTL) {
75         spaceEdge.SetRight(spaceEdge.Left());
76         spaceEdge.SetLeft(0.0_vp);
77     }
78     space->SetPadding(spaceEdge);
79     space->SetChild(icon);
80 
81     auto container = Container::Current();
82     if (!container) {
83         return false;
84     }
85     auto context = container->GetPipelineContext();
86     if (!context) {
87         return false;
88     }
89     TextStyle textStyle;
90     if (context->GetIsDeclarative()) {
91         textStyle = GetSelectStyle();
92         if (disabled_) {
93             textStyle.SetTextColor(theme_->GetDisabledColor());
94         }
95     } else {
96         textStyle = tipText_->GetTextStyle();
97         textStyle.SetFontSize(theme_->GetFontSize());
98         textStyle.SetFontWeight(theme_->GetFontWeight());
99         if (disabled_) {
100             textStyle.SetTextColor(theme_->GetDisabledColor());
101         } else {
102             textStyle.SetTextColor(theme_->GetFontColor());
103         }
104         std::vector<std::string> fontFamilies;
105         StringUtils::StringSplitter(theme_->GetFontFamily(), ',', fontFamilies);
106         if (!fontFamilies.empty()) {
107             textStyle.SetFontFamilies(fontFamilies);
108         }
109     }
110 
111     textStyle.SetAllowScale(theme_->IsAllowScale());
112     textStyle.SetTextDecoration(theme_->GetTextDecoration());
113     textStyle.SetMaxLines(SELECT_ITSELF_TEXT_LINES);
114     textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
115     tipText_->SetTextStyle(textStyle);
116     tipText_->SetFocusColor(textStyle.GetTextColor());
117     icon->SetColor(textStyle.GetTextColor());
118     RefPtr<FlexItemComponent> textItem = AceType::MakeRefPtr<FlexItemComponent>(0.0, 1.0, 0.0, tipText_);
119 
120     RefPtr<RowComponent> row =
121         AceType::MakeRefPtr<RowComponent>(FlexAlign::CENTER, FlexAlign::CENTER, std::list<RefPtr<Component>>());
122     row->SetMainAxisSize(MainAxisSize::MIN);
123     if (GetTextDirection() == TextDirection::RTL) {
124         row->AppendChild(space);
125         row->AppendChild(textItem);
126     } else {
127         row->AppendChild(textItem);
128         row->AppendChild(space);
129     }
130 
131     RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
132     backDecoration->SetBackgroundColor(backgroundColor_);
133     backDecoration->SetBorder(border_);
134 
135     RefPtr<BoxComponent> box = AceType::MakeRefPtr<BoxComponent>();
136     box->SetDeliverMinToChild(false);
137     box->SetAlignment(Alignment::CENTER);
138     box->SetBackDecoration(backDecoration);
139     box->SetPadding(innerPadding_);
140     box->SetWidth(width_.Value(), width_.Unit());
141     box->SetHeight(height_.Value(), height_.Unit());
142     box->SetChild(AceType::MakeRefPtr<ClipComponent>(row));
143     boxComponent_ = box;
144     boxComponent_->SetMouseAnimationType(HoverAnimationType::OPACITY);
145     SetChild(box);
146     return true;
147 }
148 
CreateRenderNode()149 RefPtr<RenderNode> SelectComponent::CreateRenderNode()
150 {
151     return AceType::MakeRefPtr<RenderSelect>();
152 }
153 
CreateElement()154 RefPtr<Element> SelectComponent::CreateElement()
155 {
156     auto refPtr = AceType::MakeRefPtr<SelectElement>();
157     flushRefreshCallback_ = [weakPtr = WeakPtr<SelectElement>(refPtr)]() {
158         auto element = weakPtr.Upgrade();
159         if (!element) {
160             return;
161         }
162         element->FlushRefresh();
163     };
164     return refPtr;
165 }
166 
SetClicked(bool clicked,const Color & pressColor)167 void SelectComponent::SetClicked(bool clicked, const Color& pressColor)
168 {
169     clicked_ = clicked;
170     if (!boxComponent_) {
171         LOGE("select: box is null, can not set background color when click changed.");
172         return;
173     }
174 
175     auto backDecoration = boxComponent_->GetBackDecoration();
176     if (!backDecoration) {
177         backDecoration = AceType::MakeRefPtr<Decoration>();
178     }
179     backDecoration->SetBackgroundColor(backgroundColor_.BlendColor(pressColor));
180     boxComponent_->SetBackDecoration(backDecoration);
181 }
182 
GetPopup() const183 RefPtr<SelectPopupComponent> SelectComponent::GetPopup() const
184 {
185     if (!popup_) {
186         LOGE("select: popup is null now.");
187         return nullptr;
188     }
189 
190     return popup_;
191 }
192 
GetBoxComponent() const193 RefPtr<BoxComponent> SelectComponent::GetBoxComponent() const
194 {
195     if (!boxComponent_) {
196         LOGE("select: box component of background color is null.");
197         return nullptr;
198     }
199 
200     return boxComponent_;
201 }
202 
203 } // namespace OHOS::Ace
204