1 /*
2  * Copyright (c) 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_ng/pattern/marquee/marquee_model_ng.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components_ng/base/frame_node.h"
20 #include "core/components_ng/base/view_stack_processor.h"
21 #include "core/components_ng/pattern/marquee/marquee_paint_property.h"
22 #include "core/components_ng/pattern/marquee/marquee_pattern.h"
23 #include "core/components_ng/pattern/text/text_layout_property.h"
24 #include "core/components_ng/pattern/text/text_pattern.h"
25 #include "core/components_ng/property/property.h"
26 
27 namespace OHOS::Ace::NG {
28 constexpr int32_t TEXT_MAX_LINES = 1;
Create()29 void MarqueeModelNG::Create()
30 {
31     auto* stack = ViewStackProcessor::GetInstance();
32     auto nodeId = stack->ClaimNodeId();
33     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::MARQUEE_ETS_TAG, nodeId);
34     auto frameNode = FrameNode::GetOrCreateFrameNode(
35         V2::MARQUEE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<MarqueePattern>(); });
36     if (frameNode->GetChildren().empty()) {
37         auto textNode = FrameNode::CreateFrameNode(
38             V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
39         auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
40         textLayoutProperty->UpdateMaxLines(1);
41         frameNode->AddChild(textNode);
42     } else {
43         auto textChild = AceType::DynamicCast<FrameNode>(frameNode->GetChildren().front());
44         CHECK_NULL_VOID(textChild);
45         auto textLayoutProperty = textChild->GetLayoutProperty<TextLayoutProperty>();
46         CHECK_NULL_VOID(textLayoutProperty);
47         textLayoutProperty->UpdateMaxLines(1);
48     }
49     stack->Push(frameNode);
50 }
51 
SetValue(const std::optional<std::string> & srcValue)52 void MarqueeModelNG::SetValue(const std::optional<std::string>& srcValue)
53 {
54     if (srcValue.has_value()) {
55         ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, Src, srcValue.value());
56     } else {
57         ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, Src, PROPERTY_UPDATE_MEASURE);
58     }
59 }
60 
SetPlayerStatus(const std::optional<bool> & playerStatus)61 void MarqueeModelNG::SetPlayerStatus(const std::optional<bool>& playerStatus)
62 {
63     if (playerStatus.has_value()) {
64         ACE_UPDATE_PAINT_PROPERTY(MarqueePaintProperty, PlayerStatus, playerStatus.value());
65     } else {
66         ACE_RESET_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, PlayerStatus, PROPERTY_UPDATE_RENDER);
67     }
68 }
69 
SetScrollAmount(const std::optional<double> & scrollAmount)70 void MarqueeModelNG::SetScrollAmount(const std::optional<double>& scrollAmount)
71 {
72     if (scrollAmount.has_value()) {
73         ACE_UPDATE_PAINT_PROPERTY(MarqueePaintProperty, ScrollAmount, scrollAmount.value());
74     } else {
75         ACE_RESET_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, ScrollAmount, PROPERTY_UPDATE_RENDER);
76     }
77 }
78 
SetLoop(const std::optional<int32_t> & loop)79 void MarqueeModelNG::SetLoop(const std::optional<int32_t>& loop)
80 {
81     if (loop.has_value()) {
82         ACE_UPDATE_PAINT_PROPERTY(MarqueePaintProperty, Loop, loop.value());
83     } else {
84         ACE_RESET_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, Loop, PROPERTY_UPDATE_RENDER);
85     }
86 }
87 
SetDirection(const std::optional<MarqueeDirection> & direction)88 void MarqueeModelNG::SetDirection(const std::optional<MarqueeDirection>& direction)
89 {
90     if (direction.has_value()) {
91         ACE_UPDATE_PAINT_PROPERTY(MarqueePaintProperty, Direction, direction.value());
92     } else {
93         ACE_RESET_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, Direction, PROPERTY_UPDATE_RENDER);
94     }
95 }
96 
SetAllowScale(const std::optional<bool> & allowScale)97 void MarqueeModelNG::SetAllowScale(const std::optional<bool>& allowScale)
98 {
99     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
100     CHECK_NULL_VOID(frameNode);
101     auto textChild = AceType::DynamicCast<FrameNode>(frameNode->GetChildren().front());
102     ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, AllowScale, allowScale.value_or(true));
103     CHECK_NULL_VOID(textChild);
104     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TextLayoutProperty, AllowScale, allowScale.value_or(true), textChild);
105 }
106 
SetTextColor(const std::optional<Color> & textColor)107 void MarqueeModelNG::SetTextColor(const std::optional<Color>& textColor)
108 {
109     ACE_UPDATE_RENDER_CONTEXT(ForegroundColor, textColor.value_or(Color()));
110     ACE_RESET_RENDER_CONTEXT(RenderContext, ForegroundColorStrategy);
111     ACE_UPDATE_RENDER_CONTEXT(ForegroundColorFlag, true);
112     if (textColor.has_value()) {
113         ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontColor, textColor.value());
114     } else {
115         ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, FontColor, PROPERTY_UPDATE_MEASURE);
116     }
117 }
118 
SetFontSize(const std::optional<Dimension> & fontSize)119 void MarqueeModelNG::SetFontSize(const std::optional<Dimension>& fontSize)
120 {
121     if (fontSize.has_value()) {
122         ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontSize, fontSize.value());
123     } else {
124         ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, FontSize, PROPERTY_UPDATE_MEASURE);
125     }
126 }
127 
SetFontWeight(const std::optional<FontWeight> & fontWeight)128 void MarqueeModelNG::SetFontWeight(const std::optional<FontWeight>& fontWeight)
129 {
130     if (fontWeight.has_value()) {
131         ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontWeight, fontWeight.value());
132     } else {
133         ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, FontWeight, PROPERTY_UPDATE_MEASURE);
134     }
135 }
136 
SetFontFamily(const std::optional<std::vector<std::string>> & fontFamilies)137 void MarqueeModelNG::SetFontFamily(const std::optional<std::vector<std::string>>& fontFamilies)
138 {
139     if (fontFamilies.has_value()) {
140         ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontFamily, fontFamilies.value());
141     } else {
142         ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, FontFamily, PROPERTY_UPDATE_MEASURE);
143     }
144 }
145 
SetMarqueeUpdateStrategy(const std::optional<MarqueeUpdateStrategy> & marqueeUpdateStrategy)146 void MarqueeModelNG::SetMarqueeUpdateStrategy(const std::optional<MarqueeUpdateStrategy>& marqueeUpdateStrategy)
147 {
148     if (marqueeUpdateStrategy.has_value()) {
149         ACE_UPDATE_LAYOUT_PROPERTY(MarqueeLayoutProperty, MarqueeUpdateStrategy, marqueeUpdateStrategy.value());
150     } else {
151         ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, MarqueeUpdateStrategy, PROPERTY_UPDATE_NORMAL);
152     }
153 }
154 
SetOnStart(std::function<void ()> && onChange)155 void MarqueeModelNG::SetOnStart(std::function<void()>&& onChange)
156 {
157     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
158     CHECK_NULL_VOID(frameNode);
159     auto eventHub = frameNode->GetEventHub<MarqueeEventHub>();
160     CHECK_NULL_VOID(eventHub);
161     eventHub->SetOnStart(std::move(onChange));
162 }
163 
SetOnBounce(std::function<void ()> && onChange)164 void MarqueeModelNG::SetOnBounce(std::function<void()>&& onChange)
165 {
166     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
167     CHECK_NULL_VOID(frameNode);
168     auto eventHub = frameNode->GetEventHub<MarqueeEventHub>();
169     CHECK_NULL_VOID(eventHub);
170     eventHub->SetOnBounce(std::move(onChange));
171 }
172 
SetOnFinish(std::function<void ()> && onChange)173 void MarqueeModelNG::SetOnFinish(std::function<void()>&& onChange)
174 {
175     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
176     CHECK_NULL_VOID(frameNode);
177     auto eventHub = frameNode->GetEventHub<MarqueeEventHub>();
178     CHECK_NULL_VOID(eventHub);
179     eventHub->SetOnFinish(std::move(onChange));
180 }
181 
CreateFrameNode(int32_t nodeId)182 RefPtr<FrameNode> MarqueeModelNG::CreateFrameNode(int32_t nodeId)
183 {
184     auto frameNode = FrameNode::CreateFrameNode(V2::MARQUEE_ETS_TAG, nodeId, AceType::MakeRefPtr<MarqueePattern>());
185     CHECK_NULL_RETURN(frameNode, nullptr);
186     if (frameNode->GetChildren().empty()) {
187         auto textNode = FrameNode::CreateFrameNode(
188             V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
189         CHECK_NULL_RETURN(textNode, nullptr);
190         auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
191         CHECK_NULL_RETURN(textLayoutProperty, nullptr);
192         textLayoutProperty->UpdateMaxLines(TEXT_MAX_LINES);
193         frameNode->AddChild(textNode);
194     } else {
195         auto textChild = AceType::DynamicCast<FrameNode>(frameNode->GetChildren().front());
196         CHECK_NULL_RETURN(textChild, nullptr);
197         auto textLayoutProperty = textChild->GetLayoutProperty<TextLayoutProperty>();
198         CHECK_NULL_RETURN(textLayoutProperty, nullptr);
199         textLayoutProperty->UpdateMaxLines(TEXT_MAX_LINES);
200     }
201     return frameNode;
202 }
203 
SetAllowScale(FrameNode * frameNode,const bool allowScale)204 void MarqueeModelNG::SetAllowScale(FrameNode* frameNode, const bool allowScale)
205 {
206     CHECK_NULL_VOID(frameNode);
207     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MarqueeLayoutProperty, AllowScale, allowScale, frameNode);
208     auto textChild = AceType::DynamicCast<FrameNode>(frameNode->GetChildren().front());
209     CHECK_NULL_VOID(textChild);
210     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TextLayoutProperty, AllowScale, allowScale, textChild);
211 }
212 
SetFontWeight(FrameNode * frameNode,const std::optional<FontWeight> & fontWeight)213 void MarqueeModelNG::SetFontWeight(FrameNode* frameNode, const std::optional<FontWeight>& fontWeight)
214 {
215     CHECK_NULL_VOID(frameNode);
216     if (fontWeight.has_value()) {
217         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontWeight, fontWeight.value(), frameNode);
218     } else {
219         ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, FontWeight,
220             PROPERTY_UPDATE_MEASURE, frameNode);
221     }
222 }
223 
SetFontFamily(FrameNode * frameNode,const std::optional<std::vector<std::string>> & fontFamilies)224 void MarqueeModelNG::SetFontFamily(FrameNode* frameNode, const std::optional<std::vector<std::string>>& fontFamilies)
225 {
226     CHECK_NULL_VOID(frameNode);
227     if (fontFamilies.has_value()) {
228         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontFamily, fontFamilies.value(), frameNode);
229     } else {
230         ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, FontFamily,
231             PROPERTY_UPDATE_MEASURE, frameNode);
232     }
233 }
234 
SetFontSize(FrameNode * frameNode,const std::optional<Dimension> & fontSize)235 void MarqueeModelNG::SetFontSize(FrameNode* frameNode, const std::optional<Dimension>& fontSize)
236 {
237     if (fontSize.has_value()) {
238         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontSize, fontSize.value(), frameNode);
239     } else {
240         ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(
241             MarqueeLayoutProperty, FontSize, PROPERTY_UPDATE_MEASURE, frameNode);
242     }
243 }
244 
SetTextColor(FrameNode * frameNode,const std::optional<Color> & textColor)245 void MarqueeModelNG::SetTextColor(FrameNode* frameNode, const std::optional<Color>& textColor)
246 {
247     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, textColor.value_or(Color()), frameNode);
248     ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, ForegroundColorStrategy, frameNode);
249     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode);
250     if (textColor.has_value()) {
251         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MarqueeLayoutProperty, FontColor, textColor.value(), frameNode);
252     } else {
253         ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(
254             MarqueeLayoutProperty, FontColor, PROPERTY_UPDATE_MEASURE, frameNode);
255     }
256 }
257 
SetMarqueeUpdateStrategy(FrameNode * frameNode,const std::optional<MarqueeUpdateStrategy> & marqueeUpdateStrategy)258 void MarqueeModelNG::SetMarqueeUpdateStrategy(
259     FrameNode* frameNode, const std::optional<MarqueeUpdateStrategy>& marqueeUpdateStrategy)
260 {
261     CHECK_NULL_VOID(frameNode);
262     if (marqueeUpdateStrategy.has_value()) {
263         ACE_UPDATE_NODE_LAYOUT_PROPERTY(
264             MarqueeLayoutProperty, MarqueeUpdateStrategy, marqueeUpdateStrategy.value(), frameNode);
265     } else {
266         ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(
267             MarqueeLayoutProperty, MarqueeUpdateStrategy, PROPERTY_UPDATE_MEASURE, frameNode);
268     }
269 }
270 
SetOnStart(FrameNode * frameNode,std::function<void ()> && onChange)271 void MarqueeModelNG::SetOnStart(FrameNode* frameNode, std::function<void()>&& onChange)
272 {
273     CHECK_NULL_VOID(frameNode);
274     auto eventHub = frameNode->GetEventHub<MarqueeEventHub>();
275     CHECK_NULL_VOID(eventHub);
276     eventHub->SetOnStart(std::move(onChange));
277 }
278 
SetOnBounce(FrameNode * frameNode,std::function<void ()> && onChange)279 void MarqueeModelNG::SetOnBounce(FrameNode* frameNode, std::function<void()>&& onChange)
280 {
281     CHECK_NULL_VOID(frameNode);
282     auto eventHub = frameNode->GetEventHub<MarqueeEventHub>();
283     CHECK_NULL_VOID(eventHub);
284     eventHub->SetOnBounce(std::move(onChange));
285 }
286 
SetOnFinish(FrameNode * frameNode,std::function<void ()> && onChange)287 void MarqueeModelNG::SetOnFinish(FrameNode* frameNode, std::function<void()>&& onChange)
288 {
289     CHECK_NULL_VOID(frameNode);
290     auto eventHub = frameNode->GetEventHub<MarqueeEventHub>();
291     CHECK_NULL_VOID(eventHub);
292     eventHub->SetOnFinish(std::move(onChange));
293 }
294 
SetMarqueeFrameRateRange(FrameNode * frameNode,const RefPtr<FrameRateRange> & rateRange,MarqueeDynamicSyncSceneType type)295 void MarqueeModelNG::SetMarqueeFrameRateRange(
296     FrameNode* frameNode, const RefPtr<FrameRateRange>& rateRange, MarqueeDynamicSyncSceneType type)
297 {
298     CHECK_NULL_VOID(frameNode);
299     auto pattern = frameNode->GetPattern<MarqueePattern>();
300     CHECK_NULL_VOID(pattern);
301     pattern->SetMarqueeFrameRateRange(rateRange, type);
302 }
303 
SetValue(FrameNode * frameNode,const std::optional<std::string> & srcValue)304 void MarqueeModelNG::SetValue(FrameNode* frameNode, const std::optional<std::string>& srcValue)
305 {
306     if (srcValue.has_value()) {
307         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MarqueeLayoutProperty, Src, srcValue.value(), frameNode);
308     }
309 }
310 
ResetValue(FrameNode * frameNode)311 void MarqueeModelNG::ResetValue(FrameNode* frameNode)
312 {
313     ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(MarqueeLayoutProperty, Src, PROPERTY_UPDATE_MEASURE, frameNode);
314 }
315 
SetPlayerStatus(FrameNode * frameNode,const std::optional<bool> & playerStatus)316 void MarqueeModelNG::SetPlayerStatus(FrameNode* frameNode, const std::optional<bool>& playerStatus)
317 {
318     if (playerStatus.has_value()) {
319         ACE_UPDATE_NODE_PAINT_PROPERTY(MarqueePaintProperty, PlayerStatus, playerStatus.value(), frameNode);
320     }
321 }
322 
ResetPlayerStatus(FrameNode * frameNode)323 void MarqueeModelNG::ResetPlayerStatus(FrameNode* frameNode)
324 {
325     ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, PlayerStatus, PROPERTY_UPDATE_RENDER, frameNode);
326 }
327 
SetScrollAmount(FrameNode * frameNode,const std::optional<double> & scrollAmount)328 void MarqueeModelNG::SetScrollAmount(FrameNode* frameNode, const std::optional<double>& scrollAmount)
329 {
330     if (scrollAmount.has_value()) {
331         ACE_UPDATE_NODE_PAINT_PROPERTY(MarqueePaintProperty, ScrollAmount, scrollAmount.value(), frameNode);
332     }
333 }
334 
ResetScrollAmount(FrameNode * frameNode)335 void MarqueeModelNG::ResetScrollAmount(FrameNode* frameNode)
336 {
337     ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, ScrollAmount, PROPERTY_UPDATE_RENDER, frameNode);
338 }
339 
SetLoop(FrameNode * frameNode,const std::optional<int32_t> & loop)340 void MarqueeModelNG::SetLoop(FrameNode* frameNode, const std::optional<int32_t>& loop)
341 {
342     if (loop.has_value()) {
343         ACE_UPDATE_NODE_PAINT_PROPERTY(MarqueePaintProperty, Loop, loop.value(), frameNode);
344     }
345 }
346 
ResetLoop(FrameNode * frameNode)347 void MarqueeModelNG::ResetLoop(FrameNode* frameNode)
348 {
349     ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, Loop, PROPERTY_UPDATE_RENDER, frameNode);
350 }
351 
SetDirection(FrameNode * frameNode,const std::optional<MarqueeDirection> & direction)352 void MarqueeModelNG::SetDirection(FrameNode* frameNode, const std::optional<MarqueeDirection>& direction)
353 {
354     if (direction.has_value()) {
355         ACE_UPDATE_NODE_PAINT_PROPERTY(MarqueePaintProperty, Direction, direction.value(), frameNode);
356     }
357 }
358 
ResetDirection(FrameNode * frameNode)359 void MarqueeModelNG::ResetDirection(FrameNode* frameNode)
360 {
361     ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(MarqueePaintProperty, Direction, PROPERTY_UPDATE_RENDER, frameNode);
362 }
363 } // namespace OHOS::Ace::NG
364