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/counter/counter_component.h"
17
18 #include "core/components/counter/counter_element.h"
19
20 namespace OHOS::Ace {
21 namespace {
22
23 constexpr uint32_t CLICKED_BLEND_COLOR = 0x19000000;
24 constexpr char COUNTER_BUTTON_ADD[] = "+";
25 constexpr char COUNTER_BUTTON_LESS[] = "-";
26 constexpr double COUNTER_BORDER_WIDTH = 1.0;
27 constexpr double COUNTER_RADIUS_DELTA = 2.0;
28 constexpr int32_t COUNTER_ITEM_SIZE_DIFF = 2;
29 constexpr double STATE_FAIELD_OPACITY = 0.3;
30
31 } // namespace
32
CreateRenderNode()33 RefPtr<RenderNode> CounterComponent::CreateRenderNode()
34 {
35 return RenderCounter::Create();
36 }
37
CreateElement()38 RefPtr<Element> CounterComponent::CreateElement()
39 {
40 return AceType::MakeRefPtr<CounterElement>();
41 }
42
BuildChild(const RefPtr<ThemeManager> & themeManager)43 RefPtr<Component> CounterComponent::BuildChild(const RefPtr<ThemeManager>& themeManager)
44 {
45 if (!themeManager) {
46 return nullptr;
47 }
48
49 counterTheme_ = AceType::DynamicCast<CounterTheme>(themeManager->GetTheme(CounterTheme::TypeId()));
50 if (!counterTheme_) {
51 return nullptr;
52 }
53
54 // build up counter_component.
55 RefPtr<BoxComponent> counterBox = AceType::MakeRefPtr<BoxComponent>();
56 auto backDecoration = AceType::MakeRefPtr<Decoration>();
57 BorderEdge edge(Color::GRAY, Dimension(COUNTER_BORDER_WIDTH, DimensionUnit::VP), BorderStyle::NONE);
58 Border border(edge);
59 border.SetBorderRadius(Radius(GetControlRadius()));
60 backDecoration->SetBorder(border);
61 counterBox->SetBackDecoration(backDecoration);
62 counterBox->SetHeight(GetHeight());
63 counterBox->SetWidth(GetWidth());
64 std::list<RefPtr<Component>> rowChildren;
65 RefPtr<RowComponent> counterRow =
66 AceType::MakeRefPtr<RowComponent>(FlexAlign::FLEX_START, FlexAlign::CENTER, rowChildren);
67 counterRow->SetMainAxisSize(MainAxisSize::MIN);
68 BuildControl(counterTheme_, counterRow, decreButtonComponent_, std::string(COUNTER_BUTTON_LESS), true);
69 counterRow->AppendChild(BuildDivider());
70 RefPtr<BoxComponent> contentBox = AceType::MakeRefPtr<BoxComponent>();
71 BuildContent(counterTheme_, counterRow, contentBox);
72 counterRow->AppendChild(BuildDivider());
73 BuildControl(counterTheme_, counterRow, increButtonComponent_, std::string(COUNTER_BUTTON_ADD), false);
74 counterBox->SetChild(counterRow);
75
76 displayComponent_ = AceType::MakeRefPtr<DisplayComponent>(counterBox);
77 if (propState_ == false) {
78 displayComponent_->SetOpacity(STATE_FAIELD_OPACITY);
79 }
80
81 return displayComponent_;
82 }
83
BuildDivider()84 RefPtr<DividerComponent> CounterComponent::BuildDivider()
85 {
86 auto divider = AceType::MakeRefPtr<DividerComponent>();
87 divider->SetStrokeWidth(Dimension(COUNTER_BORDER_WIDTH, DimensionUnit::VP));
88 divider->SetVertical(true);
89 divider->SetDividerColor(Color::GRAY);
90 return divider;
91 }
92
BuildControl(const RefPtr<CounterTheme> & counterTheme,const RefPtr<RowComponent> & row,RefPtr<ButtonComponent> & button,std::string content,bool isLeft)93 void CounterComponent::BuildControl(const RefPtr<CounterTheme>& counterTheme, const RefPtr<RowComponent>& row,
94 RefPtr<ButtonComponent>& button, std::string content, bool isLeft)
95 {
96 std::list<RefPtr<Component>> buttonChildren;
97 auto textComponent = AceType::MakeRefPtr<TextComponent>(content);
98 textComponent->SetTextStyle(counterTheme->GetContentTextStyle());
99 buttonChildren.emplace_back(textComponent);
100 button = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
101 button->SetHeight(Dimension(GetHeight().Value() - COUNTER_RADIUS_DELTA * COUNTER_BORDER_WIDTH, GetHeight().Unit()));
102 button->SetWidth(
103 Dimension(GetControlWidth().Value() - COUNTER_RADIUS_DELTA * COUNTER_BORDER_WIDTH, GetControlWidth().Unit()));
104 button->SetBackgroundColor(propBackgroundColor_);
105 button->SetClickedColor(Color(CLICKED_BLEND_COLOR));
106 button->SetType(ButtonType::CUSTOM);
107
108 // set up radius and click function for button.
109 if (isLeft) {
110 std::array<Radius, 4> radii = {
111 Radius(Dimension(GetControlRadius().Value() - COUNTER_BORDER_WIDTH, GetControlRadius().Unit())),
112 Radius(0.0_vp),
113 Radius(0.0_vp),
114 Radius(Dimension(GetControlRadius().Value() - COUNTER_BORDER_WIDTH, GetControlRadius().Unit()))
115 };
116 button->SetRectRadii(radii);
117 if (propState_) {
118 button->SetClickFunction([weak = AceType::WeakClaim(this)] {
119 auto spThis = weak.Upgrade();
120 if (spThis) {
121 V2::ResumeEventCallback(spThis, &CounterComponent::GetOnDec);
122 }
123 });
124 } else {
125 button->SetBackgroundColor(Color::GRAY);
126 }
127 } else {
128 std::array<Radius, 4> radii = {
129 Radius(0.0_vp),
130 Radius(Dimension(GetControlRadius().Value() - COUNTER_BORDER_WIDTH, GetControlRadius().Unit())),
131 Radius(Dimension(GetControlRadius().Value() - COUNTER_BORDER_WIDTH, GetControlRadius().Unit())),
132 Radius(0.0_vp)
133 };
134 button->SetRectRadii(radii);
135 if (propState_) {
136 button->SetClickFunction([weak = AceType::WeakClaim(this)] {
137 auto spThis = weak.Upgrade();
138 if (spThis) {
139 V2::ResumeEventCallback(spThis, &CounterComponent::GetOnInc);
140 }
141 });
142 } else {
143 button->SetBackgroundColor(Color::GRAY);
144 }
145 }
146
147 row->AppendChild(button);
148 }
149
BuildContent(const RefPtr<CounterTheme> & counterTheme,const RefPtr<RowComponent> & row,RefPtr<BoxComponent> & box)150 void CounterComponent::BuildContent(
151 const RefPtr<CounterTheme>& counterTheme, const RefPtr<RowComponent>& row, RefPtr<BoxComponent>& box)
152 {
153 box->SetAlignment(Alignment::CENTER);
154 if (!GetChildren().empty()) {
155 box->SetChild(GetChildren().front());
156 }
157
158 if (GreatNotEqual(GetHeight().Value() - COUNTER_RADIUS_DELTA * COUNTER_BORDER_WIDTH, 0.0)) {
159 box->SetHeight(
160 Dimension(GetHeight().Value() - COUNTER_RADIUS_DELTA * COUNTER_BORDER_WIDTH, GetHeight().Unit()));
161 } else {
162 box->SetHeight(Dimension(0.0, DimensionUnit::VP));
163 }
164 if (GreatNotEqual(GetWidth().Value() - COUNTER_ITEM_SIZE_DIFF * GetControlWidth().Value(), 0.0)) {
165 box->SetWidth(
166 Dimension(GetWidth().Value() - COUNTER_ITEM_SIZE_DIFF * GetControlWidth().Value(), GetWidth().Unit()));
167 } else {
168 box->SetWidth(Dimension(0.0, DimensionUnit::VP));
169 }
170
171 box->SetOverflow(Overflow::FORCE_CLIP);
172 auto backDecoration = AceType::MakeRefPtr<Decoration>();
173 backDecoration->SetBackgroundColor(propBackgroundColor_);
174 box->SetBackDecoration(backDecoration);
175 row->AppendChild(box);
176 }
177
178 } // namespace OHOS::Ace
179