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