• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 #include "component.h"
16 #include "ace_log.h"
17 #include "ace_mem_base.h"
18 #include "directive/descriptor_utils.h"
19 #include "fatal_handler.h"
20 #include "handler.h"
21 #include "js_ability_impl.h"
22 #include "js_app_context.h"
23 #include "js_app_environment.h"
24 #include "js_profiler.h"
25 #include "js_router.h"
26 #include "key_parser.h"
27 #include "keys.h"
28 #include "lazy_load_manager.h"
29 #include "securec.h"
30 #include "stylemgr/app_style.h"
31 #include "stylemgr/app_style_manager.h"
32 #include "time_util.h"
33 #include "wrapper/js.h"
34 
35 namespace OHOS {
36 namespace ACELite {
37 static Component::AnimationsNode *g_animationListHead = nullptr;
38 static bool g_isAnimatorStarted = false;
HandlerAnimations()39 void Component::HandlerAnimations()
40 {
41     Component::AnimationsNode *point = g_animationListHead;
42     while (point != nullptr && point->transitionImpl != nullptr) {
43         point->transitionImpl->Start();
44         point = point->next;
45     }
46     g_isAnimatorStarted = true;
47 }
48 
ReleaseAnimations()49 void Component::ReleaseAnimations()
50 {
51     Component::AnimationsNode *point = g_animationListHead;
52     while (point != nullptr) {
53         Component::AnimationsNode *temp = point->next;
54         if (point->transitionImpl) {
55             delete (point->transitionImpl);
56             point->transitionImpl = nullptr;
57         }
58         delete (point);
59         point = temp;
60     }
61     g_animationListHead = nullptr;
62     g_isAnimatorStarted = false;
63 }
64 
Component(jerry_value_t options,jerry_value_t children,AppStyleManager * styleManager)65 Component::Component(jerry_value_t options, jerry_value_t children, AppStyleManager *styleManager)
66     : childHead_(nullptr),
67       nextSibling_(nullptr),
68       parent_(nullptr),
69       styleManager_(styleManager),
70       options_(options),
71       children_(UNDEFINED),
72       onClickListener_(nullptr),
73       onLongPressListener_(nullptr),
74       onTouchListener_(nullptr),
75 #ifdef JS_EXTRA_EVENT_SUPPORT
76       onTouchCancelListener_(nullptr),
77       keyBoardEventListener_(nullptr),
78 #endif
79       viewId_(nullptr),
80       componentName_(K_UNKNOWN),
81       rendered_(false),
82       isAnimationKeyFramesSet_(false),
83       curTransitionImpl_(nullptr),
84       trans_(nullptr),
85       descriptors_(jerry_acquire_value(children)),
86       watchersHead_(nullptr),
87       height_(-1, DimensionType::TYPE_UNKNOWN),
88       width_(-1, DimensionType::TYPE_UNKNOWN),
89       top_(-1, DimensionType::TYPE_UNKNOWN),
90       left_(-1, DimensionType::TYPE_UNKNOWN),
91       marginTop_(-1, DimensionType::TYPE_UNKNOWN),
92       marginLeft_(-1, DimensionType::TYPE_UNKNOWN),
93       marginRight_(-1, DimensionType::TYPE_UNKNOWN),
94       marginBottom_(-1, DimensionType::TYPE_UNKNOWN)
95 {
96     JSValue attrs = JSObject::Get(options, ATTR_ATTRS);
97     if (JSUndefined::Is(attrs)) {
98         freeze_ = false;
99     } else {
100         freeze_ = JSObject::GetBoolean(attrs, ATTR_FREEZE);
101     }
102     JSRelease(attrs);
103     // create native element object before combining styles, as style data binding need it
104     nativeElement_ = jerry_create_object();
105     jerry_value_t global = jerry_get_global_object();
106     viewModel_ = jerryx_get_property_str(global, ATTR_ROOT);
107     jerry_release_value(global);
108 }
109 
110 /**
111  * @brief After construct a specific component, call this function to setup this component's native view
112  * and process attribute/events/style/children properly before binding it on an JS object.
113  * It generally calls a series of functions to complete the render work, some of which are needed to be
114  * implemented by child class. See step1~step6 function notes.
115  *
116  * NOTE: Caller should check the return result to decide if it's needed to recycle the component if the
117  * rendering failed.
118  *
119  * @return true if success, false if any error occurs
120  */
Render()121 bool Component::Render()
122 {
123     if (rendered_) {
124         HILOG_ERROR(HILOG_MODULE_ACE, "Render one component twice is not allowed.");
125         return false;
126     }
127 
128     PreRender();
129     // step1: create native view/views
130     START_TRACING_WITH_COMPONENT_NAME(RENDER_CREATE_COMPONENT, componentName_);
131     bool renderResult = CreateNativeViews();
132     if (!renderResult) {
133         return false;
134     }
135     STOP_TRACING();
136 
137     // The event bubbling mechanism is supported from API version 5, and events are bubbled by default.
138     // However, it should be compatible with the migrated old application (API version 4)
139     // so that it does not bubble by default.
140     const int32_t supportEventBubbleApiVersion = 5;
141     if (JsAppContext::GetInstance()->GetTargetApi() < supportEventBubbleApiVersion) {
142         UIView *view = GetComponentRootView();
143         if (view != nullptr) {
144             // make events non bubbling by default.
145             view->SetIntercept(true);
146         }
147     }
148 
149     SetViewExtraMsg();
150 
151     // step2: binding js object with this component
152     jerry_set_object_native_pointer(nativeElement_, this, nullptr);
153 
154     // step3: parse options for attributes and events, will call child class's according methods
155     ParseOptions();
156 
157     // step4:process this component's children
158     START_TRACING_WITH_COMPONENT_NAME(RENDER_PROCESS_CHILDREN, componentName_);
159     renderResult = ProcessChildren();
160     STOP_TRACING();
161     if (!renderResult) {
162         return false;
163     }
164     RecordAnimation();
165     PostRender();
166     rendered_ = true;
167 
168     return renderResult;
169 }
170 
SetViewExtraMsg()171 void Component::SetViewExtraMsg()
172 {
173     UIView *view = GetComponentRootView();
174     if (view == nullptr) {
175         HILOG_ERROR(HILOG_MODULE_ACE, "failed to set the extra message for view.");
176         return;
177     }
178     UIView::ViewExtraMsg *extraMsg = new UIView::ViewExtraMsg();
179     if (extraMsg == nullptr) {
180         HILOG_ERROR(HILOG_MODULE_ACE, "Failed to mapping native view with DOM element.");
181         return;
182     }
183     extraMsg->elementPtr = reinterpret_cast<void *>(&nativeElement_);
184     view->SetExtraMsg(extraMsg);
185 }
186 
ReleaseViewExtraMsg()187 void Component::ReleaseViewExtraMsg()
188 {
189     UIView *view = GetComponentRootView();
190     if (view == nullptr) {
191         return;
192     }
193     UIView::ViewExtraMsg *extraMsg = view->GetExtraMsg();
194     ACE_DELETE(extraMsg);
195     view->SetExtraMsg(nullptr);
196 }
197 
Release()198 void Component::Release()
199 {
200     // detach self from fatal handler monitoring
201     FatalHandler::GetInstance().DetachComponentNode(this);
202     RemoveAllChildren();
203 #if (FEATURE_LAZY_LOADING_MODULE == 1)
204     // detach from lazy pending list
205     JsAppContext *context = JsAppContext::GetInstance();
206     LazyLoadManager *lazyLoadManager = const_cast<LazyLoadManager *>(context->GetLazyLoadManager());
207     lazyLoadManager->RemoveLazyWatcher(nativeElement_);
208 #endif // FEATURE_LAZY_LOADING_MODULE
209     if (parent_ != nullptr) {
210         parent_->RemoveChild(this);
211     }
212 
213     // stop view animation
214     if (curTransitionImpl_) {
215         curTransitionImpl_->Stop();
216     }
217     ReleaseViewExtraMsg();
218     jerry_delete_object_native_pointer(nativeElement_, nullptr);
219     // release all native views
220     ReleaseNativeViews();
221     // release transition param
222     ReleaseTransitionParam();
223     // release the common event listeners if any
224     ReleaseCommonEventListeners();
225     // release children = jerry_create_array() in Init()
226     ClearWatchersCommon(watchersHead_);
227     // free viewId string if it's set
228     ACE_FREE(viewId_);
229     // release js object
230     jerry_release_value(nativeElement_);
231     jerry_release_value(descriptors_);
232     jerry_release_value(children_);
233     jerry_release_value(viewModel_);
234 }
235 
UpdateView(uint16_t attrKeyId,jerry_value_t attrValue)236 bool Component::UpdateView(uint16_t attrKeyId, jerry_value_t attrValue)
237 {
238     if (!KeyParser::IsKeyValid(attrKeyId)) {
239         return false;
240     }
241 
242     START_TRACING_WITH_EXTRA_INFO(SET_ATTR_SET_TO_NATIVE, componentName_, attrKeyId);
243     PreUpdate();
244 
245     // check if need to invalided self before changing in case component's area will be changed
246     InvalidateIfNeeded(attrKeyId, true);
247     bool updateResult = SetAttribute(attrKeyId, attrValue);
248     if (!updateResult) {
249         AppStyleItem *styleItem = AppStyleItem::CreateStyleItem(attrKeyId, attrValue);
250         if (styleItem != nullptr) {
251             updateResult = ApplyStyle(styleItem);
252             delete styleItem;
253             styleItem = nullptr;
254         }
255     }
256     // for root component case, it has no parent, need to use screen resolution as default
257     ConstrainedParameter parentParam(GetHorizontalResolution(), GetVerticalResolution());
258     if (parent_ != nullptr) {
259         parent_->GetConstrainedParam(parentParam);
260     }
261     AlignDimensions(parentParam);
262     AdaptBoxSizing(attrKeyId);
263     // force parent to relayout the children in case component's area is changed
264     InvalidateIfNeeded(attrKeyId, false);
265     if (updateResult) {
266         PostUpdate(attrKeyId);
267     }
268     StartAnimation();
269     STOP_TRACING();
270 
271     return updateResult;
272 }
RegisterNamedFunction(const char * const name,jerry_external_handler_t handler) const273 void Component::RegisterNamedFunction(const char * const name, jerry_external_handler_t handler) const
274 {
275     JerrySetFuncProperty(nativeElement_, name, handler);
276 }
277 // default implementation
SetAttribute(uint16_t attrKeyId,jerry_value_t attrValue)278 bool Component::SetAttribute(uint16_t attrKeyId, jerry_value_t attrValue)
279 {
280     UIView *uiView = GetComponentRootView();
281     if ((uiView == nullptr) || !KeyParser::IsKeyValid(attrKeyId) || IS_UNDEFINED(attrValue)) {
282         return false;
283     }
284 
285     // try private first
286     bool setResult = SetPrivateAttribute(attrKeyId, attrValue);
287     if (!setResult) {
288         // this means no private attributes matches, so need to try private ones
289         setResult = SetCommonAttribute(*uiView, attrKeyId, attrValue);
290     }
291 
292     return setResult;
293 }
294 
SetCommonAttribute(UIView & view,const uint16_t attrKeyId,const jerry_value_t attrValue)295 bool Component::SetCommonAttribute(UIView &view, const uint16_t attrKeyId, const jerry_value_t attrValue)
296 {
297     switch (attrKeyId) {
298         case K_ID: {
299             // this string in component itself.
300             ACE_FREE(viewId_);
301             viewId_ = MallocStringOf(attrValue);
302             if (viewId_ == nullptr) {
303                 HILOG_ERROR(HILOG_MODULE_ACE, "failed to set `id` attribute.");
304                 return false;
305             }
306             view.SetViewId(viewId_);
307             break;
308         }
309         case K_SHOW: {
310             view.SetVisible(BoolOf(attrValue));
311             break;
312         }
313         case K_REF: {
314             uint16_t length = 0;
315             char *refName = MallocStringOf(attrValue, &length);
316             if (refName == nullptr) {
317                 HILOG_ERROR(HILOG_MODULE_ACE, "failed to set `ref` attribute.");
318                 return false;
319             }
320             if (length != 0) {
321                 jerry_value_t refs = jerryx_get_property_str(viewModel_, ATTR_REFS);
322                 if (jerry_value_is_undefined(refs)) {
323                     jerry_release_value(refs);
324                     refs = jerry_create_object();
325                     jerryx_set_property_str(viewModel_, ATTR_REFS, refs);
326                 }
327                 jerryx_set_property_str(refs, refName, nativeElement_);
328                 jerry_release_value(refs);
329             }
330             ace_free(refName);
331             refName = nullptr;
332             break;
333         }
334         default: {
335             // this is not error case, just no one get matched
336             return false;
337         }
338     }
339 
340     return true;
341 }
342 
ApplyStyles(const jerry_value_t options,Component & currentComponent) const343 void Component::ApplyStyles(const jerry_value_t options, Component &currentComponent) const
344 {
345     if (jerry_value_is_undefined(options)) {
346         return;
347     }
348     styleManager_->ApplyComponentStyles(options, currentComponent);
349 }
350 
GetDimensionFromStyle(Dimension & dimension,const AppStyleItem & styleItem) const351 void Component::GetDimensionFromStyle(Dimension &dimension, const AppStyleItem &styleItem) const
352 {
353     if (styleItem.GetValueType() == STYLE_PROP_VALUE_TYPE_PERCENT) {
354         // percent format
355         dimension.value.percentage = styleItem.GetPercentValue();
356         dimension.type = DimensionType::TYPE_PERCENT;
357         return;
358     }
359     // number or string format
360     // use INT32_MIN as the impossible default value
361     int32_t pixelValue = GetStylePixelValue(&styleItem, INT32_MIN);
362     if (pixelValue == INT32_MIN) {
363         // get pixel failed, reset to unknown type
364         dimension.type = DimensionType::TYPE_UNKNOWN;
365         return;
366     }
367     dimension.value.pixel = (int16_t)(pixelValue);
368     dimension.type = DimensionType::TYPE_PIXEL;
369 }
370 
CalculateDimensionPixel(Dimension & dimension,int16_t base) const371 void Component::CalculateDimensionPixel(Dimension &dimension, int16_t base) const
372 {
373     const uint8_t hundred = 100;
374     if (dimension.type == DimensionType::TYPE_PERCENT) {
375         dimension.value.pixel = (int16_t)((dimension.value.percentage * base) / hundred);
376         dimension.type = DimensionType::TYPE_PIXEL;
377     }
378 }
379 
GetDimension(uint16_t keyNameId) const380 const Dimension &Component::GetDimension(uint16_t keyNameId) const
381 {
382     const static Dimension unknownDimension = {0, DimensionType::TYPE_UNKNOWN};
383     switch (keyNameId) {
384         case K_WIDTH:
385             return width_;
386         case K_HEIGHT:
387             return height_;
388         case K_TOP:
389             return top_;
390         case K_LEFT:
391             return left_;
392         case K_MARGIN_TOP:
393             return marginTop_;
394         case K_MARGIN_BOTTOM:
395             return marginBottom_;
396         case K_MARGIN_RIGHT:
397             return marginRight_;
398         case K_MARGIN_LEFT:
399             return marginLeft_;
400         default: {
401             return unknownDimension;
402         }
403     }
404 }
405 
AlignDimensions(const ConstrainedParameter & param)406 void Component::AlignDimensions(const ConstrainedParameter &param)
407 {
408     // width
409     CalculateDimensionPixel(width_, param.maxWidth);
410     CalculateDimensionPixel(height_, param.maxHeight);
411     // top & left
412     CalculateDimensionPixel(top_, param.maxHeight);
413     CalculateDimensionPixel(left_, param.maxWidth);
414     // margin
415     CalculateDimensionPixel(marginTop_, param.maxHeight);
416     CalculateDimensionPixel(marginLeft_, param.maxHeight);
417     CalculateDimensionPixel(marginRight_, param.maxHeight);
418     CalculateDimensionPixel(marginBottom_, param.maxHeight);
419     // notify
420     OnDimensionsAligned();
421 }
422 
EnableTransmitSwipe()423 void Component::EnableTransmitSwipe()
424 {
425     if (onTouchListener_ != nullptr) {
426         onTouchListener_->SetStopPropagation(false);
427     }
428 }
429 
GetConstrainedParam(ConstrainedParameter & param) const430 void Component::GetConstrainedParam(ConstrainedParameter &param) const
431 {
432     param.maxWidth = width_.value.pixel;
433     param.maxHeight = height_.value.pixel;
434 }
435 
ApplyAlignedMargin(UIView & uiView) const436 void Component::ApplyAlignedMargin(UIView &uiView) const
437 {
438     if (marginTop_.type == DimensionType::TYPE_PIXEL) {
439         uiView.SetStyle(STYLE_MARGIN_TOP, marginTop_.value.pixel);
440     }
441     if (marginBottom_.type == DimensionType::TYPE_PIXEL) {
442         uiView.SetStyle(STYLE_MARGIN_BOTTOM, marginBottom_.value.pixel);
443     }
444     if (marginLeft_.type == DimensionType::TYPE_PIXEL) {
445         uiView.SetStyle(STYLE_MARGIN_LEFT, marginLeft_.value.pixel);
446     }
447     if (marginRight_.type == DimensionType::TYPE_PIXEL) {
448         uiView.SetStyle(STYLE_MARGIN_RIGHT, marginRight_.value.pixel);
449     }
450 }
451 
IsLayoutRelatedAttrs(uint16_t attrKeyId) const452 bool Component::IsLayoutRelatedAttrs(uint16_t attrKeyId) const
453 {
454     return (attrKeyId == K_HEIGHT || attrKeyId == K_WIDTH || attrKeyId == K_MARGIN || attrKeyId == K_MARGIN_BOTTOM ||
455             attrKeyId == K_MARGIN_LEFT || attrKeyId == K_MARGIN_RIGHT || attrKeyId == K_MARGIN_TOP ||
456             attrKeyId == K_PADDING || attrKeyId == K_PADDING_BOTTOM || attrKeyId == K_PADDING_LEFT ||
457             attrKeyId == K_PADDING_RIGHT || attrKeyId == K_PADDING_TOP || attrKeyId == K_BORDER_BOTTOM_WIDTH ||
458             attrKeyId == K_BORDER_LEFT_WIDTH || attrKeyId == K_BORDER_RIGHT_WIDTH || attrKeyId == K_BORDER_TOP_WIDTH ||
459             attrKeyId == K_BORDER_WIDTH || attrKeyId == K_BORDER_RADIUS || attrKeyId == K_LEFT || attrKeyId == K_TOP ||
460             attrKeyId == K_SHOW || attrKeyId == K_DISPLAY);
461 }
462 
ApplyAlignedPosition(UIView & uiView) const463 void Component::ApplyAlignedPosition(UIView &uiView) const
464 {
465     if (top_.type == DimensionType::TYPE_PIXEL) {
466         uiView.SetY(top_.value.pixel);
467     }
468     if (left_.type == DimensionType::TYPE_PIXEL) {
469         uiView.SetX(left_.value.pixel);
470     }
471 }
472 
AdapteBoxRectArea(UIView & uiView) const473 void Component::AdapteBoxRectArea(UIView &uiView) const
474 {
475     // set view height and width
476     uint8_t borderNum = 2;
477     int16_t height = (height_.type == DimensionType::TYPE_PIXEL) ? height_.value.pixel : -1;
478     int16_t width = (width_.type == DimensionType::TYPE_PIXEL) ? width_.value.pixel : -1;
479     if (height >= 0) {
480         // as uiView->GetStyle(STYLE_PADDING_TOP) and uiView->GetStyle(STYLE_PADDING_BOTTOM) is defined
481         // as uint16_t, so do not need to judge whether less than 0
482         if (uiView.GetStyle(STYLE_BORDER_WIDTH) < 0) {
483             HILOG_WARN(HILOG_MODULE_ACE, "border and padding size should not less than 0");
484         }
485         int16_t contentHeight = height - (uiView.GetStyle(STYLE_BORDER_WIDTH) * borderNum) -
486                                 uiView.GetStyle(STYLE_PADDING_TOP) - uiView.GetStyle(STYLE_PADDING_BOTTOM);
487         if (contentHeight <= 0) {
488             HILOG_WARN(HILOG_MODULE_ACE,
489                        "component height can not include padding and border width, padding and border will be set 0");
490             uiView.SetStyle(STYLE_BORDER_WIDTH, 0);
491             uiView.SetStyle(STYLE_PADDING_TOP, 0);
492             uiView.SetStyle(STYLE_PADDING_BOTTOM, 0);
493             uiView.SetHeight(height);
494         } else {
495             uiView.SetHeight(contentHeight);
496         }
497     }
498     if (width >= 0) {
499         if (uiView.GetStyle(STYLE_BORDER_WIDTH) < 0) {
500             HILOG_WARN(HILOG_MODULE_ACE, "border and padding size should not less than 0");
501         }
502         int16_t contentWidth = width - (uiView.GetStyle(STYLE_BORDER_WIDTH) * borderNum) -
503                                uiView.GetStyle(STYLE_PADDING_LEFT) - uiView.GetStyle(STYLE_PADDING_RIGHT);
504         if (contentWidth <= 0) {
505             HILOG_WARN(HILOG_MODULE_ACE,
506                        "component width can not include padding and border width, padding and border will be set 0");
507             uiView.SetStyle(STYLE_BORDER_WIDTH, 0);
508             uiView.SetStyle(STYLE_PADDING_LEFT, 0);
509             uiView.SetStyle(STYLE_PADDING_RIGHT, 0);
510             uiView.SetWidth(width);
511         } else {
512             uiView.SetWidth(contentWidth);
513         }
514     }
515 }
516 
AdaptBoxSizing(uint16_t attrKeyId) const517 bool Component::AdaptBoxSizing(uint16_t attrKeyId) const
518 {
519     UIView *uiView = GetComponentRootView();
520     if (uiView == nullptr) {
521         return false;
522     }
523     bool isNeedAlignedPosition = ((attrKeyId == K_UNKNOWN) ? true : IsLayoutRelatedAttrs(attrKeyId));
524     if (isNeedAlignedPosition) {
525         // apply aligned top and left
526         ApplyAlignedPosition(*uiView);
527     }
528     // apply aligned magin
529     ApplyAlignedMargin(*uiView);
530     // adjust the box sizing
531     AdapteBoxRectArea(*uiView);
532     return true;
533 }
534 
ApplyStyle(const AppStyleItem * style)535 bool Component::ApplyStyle(const AppStyleItem *style)
536 {
537     UIView *uiView = GetComponentRootView();
538     if (uiView == nullptr) {
539         return false;
540     }
541 
542     // Try private styles first
543     bool applyResult = ApplyPrivateStyle(style);
544     if (applyResult) {
545         // one private style get matched, no need to try private style ones
546         return true;
547     }
548     return ApplyCommonStyle(*uiView, style);
549 }
550 
551 /*
552  * support common style items:
553  *  [left|top]: number                       # flex layout not work
554  * 'width': number,
555  * 'height': number,
556  * 'margin': number,                         # flex layout work
557  * 'border-width': number,
558  * 'border-color':number,
559  * 'border-radius': number,
560  * 'background-color': number,
561  * 'opacity': number,
562  * 'visibility': bool,
563  *
564  * not suport common style item:
565  * border-[left|top|right|bottom]-width,
566  * border-[left|top|right|bottom]-color,
567  * border-[top|bottom]-[left|right]-radius,
568  * border-style,
569  * padding:number,
570  * right|bottom
571  */
ApplyCommonStyle(UIView & view,const AppStyleItem * style)572 bool Component::ApplyCommonStyle(UIView &view, const AppStyleItem *style)
573 {
574     uint16_t styleNameId = GetStylePropNameId(style);
575     if (!KeyParser::IsKeyValid(styleNameId)) {
576         return false;
577     }
578 
579     // we do not support pseudo class for all styles, child must handle itself
580     if (style->IsPseudoClassItem()) {
581         return false;
582     }
583 
584     switch (styleNameId) {
585         case K_HEIGHT: {
586             GetDimensionFromStyle(height_, *style);
587             break;
588         }
589         case K_WIDTH: {
590             GetDimensionFromStyle(width_, *style);
591             break;
592         }
593         case K_DISPLAY: {
594             SetVisible(view, style);
595             break;
596         }
597         case K_MARGIN: {
598             GetDimensionFromStyle(marginBottom_, *style);
599             GetDimensionFromStyle(marginLeft_, *style);
600             GetDimensionFromStyle(marginRight_, *style);
601             GetDimensionFromStyle(marginTop_, *style);
602             break;
603         }
604         case K_MARGIN_BOTTOM: {
605             GetDimensionFromStyle(marginBottom_, *style);
606             break;
607         }
608         case K_MARGIN_LEFT: {
609             GetDimensionFromStyle(marginLeft_, *style);
610             break;
611         }
612         case K_MARGIN_RIGHT: {
613             GetDimensionFromStyle(marginRight_, *style);
614             break;
615         }
616         case K_MARGIN_TOP: {
617             GetDimensionFromStyle(marginTop_, *style);
618             break;
619         }
620         case K_PADDING:
621             SetPadding(view, *style);
622             break;
623         case K_PADDING_BOTTOM:
624             SetBottomPadding(view, *style);
625             break;
626         case K_PADDING_LEFT:
627             SetLeftPadding(view, *style);
628             break;
629         case K_PADDING_RIGHT:
630             SetRightPadding(view, *style);
631             break;
632         case K_PADDING_TOP: {
633             SetTopPadding(view, *style);
634             break;
635         }
636         case K_BORDER_BOTTOM_WIDTH:
637         case K_BORDER_LEFT_WIDTH:
638         case K_BORDER_RIGHT_WIDTH:
639         case K_BORDER_TOP_WIDTH:
640         case K_BORDER_WIDTH: {
641             SetBorderWidth(view, *style);
642             break;
643         }
644         case K_BORDER_BOTTOM_COLOR:
645         case K_BORDER_LEFT_COLOR:
646         case K_BORDER_RIGHT_COLOR:
647         case K_BORDER_TOP_COLOR:
648         case K_BORDER_COLOR: {
649             SetBorderColor(view, *style);
650             break;
651         }
652         case K_BORDER_RADIUS: {
653             SetBorderRadius(view, *style);
654             break;
655         }
656         case K_BACKGROUND_COLOR: {
657             SetBackgroundColor(view, *style);
658             break;
659         }
660         case K_LEFT: {
661             GetDimensionFromStyle(left_, *style);
662             break;
663         }
664         case K_TOP: {
665             GetDimensionFromStyle(top_, *style);
666             break;
667         }
668         case K_ANIMATION_DURATION: {
669             SetAnimationStyle(view, style, K_ANIMATION_DURATION);
670             break;
671         }
672         case K_ANIMATION_TIMING_FUNCTION: {
673             SetAnimationStyle(view, style, K_ANIMATION_TIMING_FUNCTION);
674             break;
675         }
676         case K_ANIMATION_FILL_MODE: {
677             SetAnimationStyle(view, style, K_ANIMATION_FILL_MODE);
678             break;
679         }
680         case K_ANIMATION_DELAY: {
681             SetAnimationStyle(view, style, K_ANIMATION_DELAY);
682             break;
683         }
684         case K_ANIMATION_ITERATION_COUNT: {
685             SetAnimationStyle(view, style, K_ANIMATION_ITERATION_COUNT);
686             break;
687         }
688         case K_ANIMATION_NAME: {
689             SetAnimationKeyFrames(view, style);
690             break;
691         }
692         case K_OPACITY: {
693             SetOpacity(view, *style);
694             break;
695         }
696         default: {
697             return false;
698         }
699     }
700     return true;
701 }
702 
Invalidate()703 void Component::Invalidate()
704 {
705     UIView *view = GetComponentRootView();
706     if (view == nullptr) {
707         return;
708     }
709     view->Invalidate();
710 }
711 
ParseOptions()712 void Component::ParseOptions()
713 {
714     if (JSUndefined::Is(options_)) {
715         HILOG_WARN(HILOG_MODULE_ACE, "options is null");
716         return;
717     }
718 
719     if (!JSObject::Is(options_)) {
720         HILOG_WARN(HILOG_MODULE_ACE, "options is not an object type.");
721         return;
722     }
723 
724     START_TRACING_WITH_COMPONENT_NAME(RENDER_APPLY_STYLE, componentName_);
725     ApplyStyles(options_, *this);
726     STOP_TRACING();
727 
728     START_TRACING(RENDER_PARSE_ATTR);
729     ParseAttrs();
730     STOP_TRACING();
731     START_TRACING(RENDER_PARSE_EVENT);
732     ParseEvents();
733     STOP_TRACING();
734 }
735 
SetAnimationKeyFrames(const UIView & view,const AppStyleItem * styleItem)736 void Component::SetAnimationKeyFrames(const UIView &view, const AppStyleItem *styleItem)
737 {
738     if (trans_ == nullptr) {
739         trans_ = new TransitionParams();
740         if (trans_ == nullptr) {
741             HILOG_ERROR(HILOG_MODULE_ACE, "create TransitionParams object error");
742             return;
743         }
744     }
745 
746     const char * const value = GetStyleStrValue(styleItem);
747     if (value == nullptr) {
748         HILOG_ERROR(HILOG_MODULE_ACE, "animation name is not string value");
749         return;
750     }
751 
752     const AppStyleSheet *styleSheet = GetStyleManager()->GetStyleSheet();
753     if (styleSheet == nullptr) {
754         HILOG_ERROR(HILOG_MODULE_ACE, "styleSheet must set when you set animation attribute");
755         return;
756     }
757     AppStyle *style = styleSheet->GetStyleFromKeyFramesSelectors(value);
758 
759     if (style) {
760         const AppStyleItem *item = style->GetFirst();
761         if (item == nullptr) {
762             HILOG_ERROR(HILOG_MODULE_ACE, "keyFrame style is not set!");
763             return;
764         }
765         SetAnimationKeyFrames(item);
766     }
767 }
768 
SetAnimationKeyFrames(const AppStyleItem * item)769 void Component::SetAnimationKeyFrames(const AppStyleItem *item)
770 {
771     if (item == nullptr) {
772         HILOG_ERROR(HILOG_MODULE_ACE, "keyFrame style is not set!");
773         return;
774     }
775 
776     const int8_t animatorFrom = 1;
777     const int8_t animatorTo = 2;
778 
779     isAnimationKeyFramesSet_ = false;
780     while (item) {
781         const char * const itemValue = item->GetStrValue();
782 
783         if ((itemValue == nullptr) || (strlen(itemValue) == 0)) {
784             return;
785         }
786         size_t valLength = strlen(itemValue);
787         if (valLength >= UINT8_MAX) {
788             item = item->GetNext();
789             continue;
790         }
791         char *animationValue = reinterpret_cast<char *>(ace_malloc(sizeof(char) * (valLength + 1)));
792         if (animationValue == nullptr) {
793             HILOG_ERROR(HILOG_MODULE_ACE, "malloc animationValue memory heap failed.");
794             return;
795         }
796         if (memcpy_s(animationValue, valLength, itemValue, valLength) != 0) {
797             ace_free(animationValue);
798             animationValue = nullptr;
799             return;
800         }
801         animationValue[valLength] = '\0';
802         int32_t valueTo;
803         int32_t valueFrom;
804         int16_t keyId = item->GetPropNameId();
805         if (keyId == K_OPACITY) {
806             valueTo = GetAnimatorValue(animationValue, animatorTo, true);
807             valueFrom = GetAnimatorValue(animationValue, animatorFrom, true);
808         } else {
809             valueTo = GetAnimatorValue(animationValue, animatorTo);
810             valueFrom = GetAnimatorValue(animationValue, animatorFrom);
811         }
812         ace_free(animationValue);
813         animationValue = nullptr;
814         SetAnimationKeyFrames(keyId, valueFrom, valueTo);
815         item = item->GetNext();
816     }
817 }
818 
SetAnimationKeyFrames(int16_t keyId,int32_t valueFrom,int32_t valueTo)819 void Component::SetAnimationKeyFrames(int16_t keyId, int32_t valueFrom, int32_t valueTo)
820 {
821     switch (keyId) {
822         case K_ROTATE:
823             trans_->transformType = const_cast<char *>(TRANSITION_ROTATE);
824             trans_->transform_from = valueFrom;
825             trans_->transform_to = valueTo;
826             isAnimationKeyFramesSet_ = true;
827             break;
828         case K_TRANSLATE_X:
829             trans_->transformType = const_cast<char *>(TRANSITION_TRANSFORM_X);
830             trans_->transform_from = valueFrom;
831             trans_->transform_to = valueTo;
832             isAnimationKeyFramesSet_ = true;
833             break;
834         case K_TRANSLATE_Y:
835             trans_->transformType = const_cast<char *>(TRANSITION_TRANSFORM_Y);
836             trans_->transform_from = valueFrom;
837             trans_->transform_to = valueTo;
838             isAnimationKeyFramesSet_ = true;
839             break;
840         case K_HEIGHT:
841             trans_->height_from = valueFrom;
842             trans_->height_to = valueTo;
843             isAnimationKeyFramesSet_ = true;
844             break;
845         case K_WIDTH:
846             trans_->width_from = valueFrom;
847             trans_->width_to = valueTo;
848             isAnimationKeyFramesSet_ = true;
849             break;
850         case K_BACKGROUND_COLOR:
851             trans_->background_color_from = valueFrom;
852             trans_->background_color_to = valueTo;
853             isAnimationKeyFramesSet_ = true;
854             break;
855         case K_OPACITY:
856             trans_->opacity_from = valueFrom;
857             trans_->opacity_to = valueTo;
858             isAnimationKeyFramesSet_ = true;
859             break;
860         default:
861             break;
862     }
863 }
864 
SetAnimationStyle(const UIView & view,const AppStyleItem * styleItem,const int16_t keyId)865 void Component::SetAnimationStyle(const UIView &view, const AppStyleItem *styleItem, const int16_t keyId)
866 {
867     // special for "animation-iteration-count" which value could be a number or string "infinite"
868     if ((styleItem == nullptr) || (!const_cast<AppStyleItem *>(styleItem)->UpdateNumValToStr())) {
869         HILOG_ERROR(HILOG_MODULE_ACE, "SetAnimationStyle fail");
870         return;
871     }
872     if (trans_ == nullptr) {
873         trans_ = new TransitionParams();
874         if (trans_ == nullptr) {
875             HILOG_ERROR(HILOG_MODULE_ACE, "create TransitionParams object error");
876             return;
877         }
878     }
879 
880     const char * const strValue = GetStyleStrValue(styleItem);
881     const size_t strLen = GetStyleStrValueLen(styleItem);
882     if (strValue == nullptr) {
883         HILOG_ERROR(HILOG_MODULE_ACE, "animation style item is null");
884         return;
885     }
886     switch (keyId) {
887         case K_ANIMATION_DURATION: {
888             if (!IsStyleValueTypeString(styleItem)) {
889                 HILOG_ERROR(HILOG_MODULE_ACE, "style animation during value is invalid!");
890                 return;
891             }
892             trans_->during = ParseToMilliseconds(strValue);
893             break;
894         }
895         case K_ANIMATION_TIMING_FUNCTION: {
896             uint16_t animationTimingKeyId = KeyParser::ParseKeyId(strValue, strLen);
897             switch (animationTimingKeyId) {
898                 case K_EASE_IN:
899                     trans_->easing = EasingType::EASE_IN;
900                     break;
901                 case K_EASE_OUT:
902                     trans_->easing = EasingType::EASE_OUT;
903                     break;
904                 case K_EASE_IN_OUT:
905                     trans_->easing = EasingType::EASE_IN_OUT;
906                     break;
907                 default:
908                     trans_->easing = EasingType::LINEAR;
909                     break;
910             }
911             break;
912         }
913         case K_ANIMATION_FILL_MODE: {
914             uint16_t animationFillKeyId = KeyParser::ParseKeyId(strValue, strLen);
915             switch (animationFillKeyId) {
916                 case K_FORWARDS:
917                     trans_->fill = OptionsFill::FORWARDS;
918                     break;
919                 default:
920                     trans_->fill = OptionsFill::FNONE;
921                     break;
922             }
923             break;
924         }
925         case K_ANIMATION_DELAY: {
926             if (!IsStyleValueTypeString(styleItem)) {
927                 HILOG_ERROR(HILOG_MODULE_ACE, "style animation delay value is invalid!");
928                 return;
929             }
930             trans_->delay = ParseToMilliseconds(strValue);
931             break;
932         }
933         case K_ANIMATION_ITERATION_COUNT: {
934             if (!IsStyleValueTypeString(styleItem)) {
935                 HILOG_ERROR(HILOG_MODULE_ACE, "style iteration count value is invalid!");
936                 return;
937             }
938             trans_->iterations = TransitionImpl::GetNumIterations(strValue);
939             break;
940         }
941         default:
942             break;
943     }
944 }
945 
AddAnimationToList(const TransitionImpl * transitionImpl) const946 void Component::AddAnimationToList(const TransitionImpl *transitionImpl) const
947 {
948     AnimationsNode *animation = new AnimationsNode();
949     if (animation == nullptr) {
950         HILOG_ERROR(HILOG_MODULE_ACE, "create animation node error in startAnimation");
951         return;
952     }
953     animation->transitionImpl = const_cast<TransitionImpl *>(transitionImpl);
954     animation->next = g_animationListHead;
955     g_animationListHead = animation;
956 }
957 
RecordAnimation()958 void Component::RecordAnimation()
959 {
960     if (trans_ == nullptr) {
961         return;
962     }
963 
964     if (trans_->during > 0 && isAnimationKeyFramesSet_) {
965         UIView *uiView = GetComponentRootView();
966         if (uiView) {
967             curTransitionImpl_ = new TransitionImpl(*trans_, uiView);
968             if (curTransitionImpl_ == nullptr) {
969                 HILOG_ERROR(HILOG_MODULE_ACE, "create transitionImpl error");
970                 isAnimationKeyFramesSet_ = false;
971                 return;
972             }
973             curTransitionImpl_->Init();
974             AddAnimationToList(curTransitionImpl_);
975             isAnimationKeyFramesSet_ = false;
976             // special for "if" situation, if g_isAnimatorStarted is started means the page has started all the
977             // animators, and the current component is created by "if" situation, so the animator can start immediately
978             if (g_isAnimatorStarted) {
979                 curTransitionImpl_->Start();
980             }
981         }
982     }
983 }
984 
StartAnimation()985 void Component::StartAnimation()
986 {
987     if (trans_ == nullptr) {
988         return;
989     }
990 
991     if (trans_->during > 0 && isAnimationKeyFramesSet_) {
992         UIView *uiView = GetComponentRootView();
993         if (uiView) {
994             if (curTransitionImpl_ != nullptr) {
995                 curTransitionImpl_->Stop();
996             }
997             curTransitionImpl_ = new TransitionImpl(*trans_, uiView);
998             if (curTransitionImpl_ == nullptr) {
999                 HILOG_ERROR(HILOG_MODULE_ACE, "create transitionImpl error!");
1000                 isAnimationKeyFramesSet_ = false;
1001                 return;
1002             }
1003             curTransitionImpl_->Init();
1004             AddAnimationToList(curTransitionImpl_);
1005             curTransitionImpl_->Start();
1006             isAnimationKeyFramesSet_ = false;
1007         }
1008     }
1009 }
1010 
ReleaseTransitionParam()1011 void Component::ReleaseTransitionParam()
1012 {
1013     if (trans_) {
1014         delete trans_;
1015         trans_ = nullptr;
1016     }
1017 }
1018 
GetAnimatorValue(char * animatorValue,const int8_t index,bool isOpacity) const1019 int32_t Component::GetAnimatorValue(char *animatorValue, const int8_t index, bool isOpacity) const
1020 {
1021     if ((animatorValue == nullptr) || (strlen(animatorValue) == 0) || (strlen(animatorValue) >= UINT8_MAX)) {
1022         return 0;
1023     }
1024     const int8_t animatorfrom = 1;
1025     const int8_t animatorTo = 2;
1026     if ((index != animatorfrom) && (index != animatorTo)) {
1027         return 0;
1028     }
1029 
1030     char *next = nullptr;
1031     // try to get from part
1032     char *value = strtok_s(animatorValue, ANIMATION_VALUE_SEP, &next);
1033     if (index == animatorTo) {
1034         // get to part then if needed
1035         if (value != nullptr) {
1036             value = strtok_s(nullptr, ANIMATION_VALUE_SEP, &next);
1037         }
1038     }
1039     if (value == nullptr) {
1040         HILOG_ERROR(HILOG_MODULE_ACE, "GetAnimatorValue strtok_s failed.");
1041         return 0;
1042     }
1043 
1044     int32_t convertedValue =
1045         isOpacity ? (strtod(value, nullptr) * ALPHA_MAX) : static_cast<int32_t>(strtol(value, nullptr, DEC));
1046     if (TransitionImpl::IsEndWith(value, "rad")) {
1047         uint8_t degConversionRate = 57;
1048         convertedValue = convertedValue * degConversionRate;
1049     }
1050     return convertedValue;
1051 }
1052 
AddWatcherItem(const jerry_value_t attrKey,const jerry_value_t attrValue,bool isLazyLoading)1053 jerry_value_t Component::AddWatcherItem(const jerry_value_t attrKey, const jerry_value_t attrValue, bool isLazyLoading)
1054 {
1055     (void)(isLazyLoading); // for lazy cases, the process is same currently
1056     jerry_value_t options = jerry_create_object();
1057     JerrySetNamedProperty(options, ARG_WATCH_EL, nativeElement_);
1058     JerrySetNamedProperty(options, ARG_WATCH_ATTR, attrKey);
1059     jerry_value_t watcher = CallJSWatcher(attrValue, WatcherCallbackFunc, options);
1060     jerry_release_value(options);
1061     if (IS_UNDEFINED(watcher) || jerry_value_is_error(watcher)) {
1062         HILOG_ERROR(HILOG_MODULE_ACE, "Failed to create Watcher instance.");
1063         jerry_release_value(watcher); // release error case, note: release undefined is harmless
1064         return UNDEFINED;
1065     }
1066     // watcher is valide, insert it to the list
1067     InsertWatcherCommon(watchersHead_, watcher);
1068 
1069     // return the lastValue and need to be released out of this function
1070     return jerryx_get_property_str(watcher, "_lastValue");
1071 }
1072 
ParseAttrs()1073 void Component::ParseAttrs()
1074 {
1075     jerry_value_t attrs = jerryx_get_property_str(options_, ATTR_ATTRS);
1076     if (jerry_value_is_undefined(attrs)) {
1077         return;
1078     }
1079 
1080     jerry_value_t attrKeys = jerry_get_object_keys(attrs);
1081     if (jerry_value_is_undefined(attrKeys)) {
1082         HILOG_ERROR(HILOG_MODULE_ACE, "None attributes to parse.");
1083         jerry_release_value(attrs);
1084         return;
1085     }
1086 
1087     uint16_t length = jerry_get_array_length(attrKeys);
1088     for (uint32_t index = 0; index < length; ++index) {
1089         jerry_value_t attrKey = jerry_get_property_by_index(attrKeys, index);
1090         jerry_value_t attrValue = jerry_get_property(attrs, attrKey);
1091         jerry_value_t newAttrValue = attrValue;
1092         // calculate key ID
1093         uint16_t attrKeyId = ParseKeyIdFromJSString(attrKey);
1094         if (jerry_value_is_function(attrValue)) {
1095             START_TRACING_WITH_COMPONENT_NAME(SET_ATTR_PARSE_EXPRESSION, componentName_);
1096             if (freeze_) {
1097                 newAttrValue = JSFunction::Call(attrValue, viewModel_, nullptr, 0);
1098             } else {
1099 #if (FEATURE_LAZY_LOADING_MODULE == 1)
1100                 newAttrValue = CallJSFunction(attrValue, viewModel_, nullptr, 0);
1101                 JsAppContext *context = JsAppContext::GetInstance();
1102                 LazyLoadManager *lazyLoadManager = const_cast<LazyLoadManager *>(context->GetLazyLoadManager());
1103                 lazyLoadManager->AddLazyLoadWatcher(nativeElement_, attrKey, attrValue, attrKeyId);
1104 #else
1105                 newAttrValue = AddWatcherItem(attrKey, attrValue);
1106 #endif
1107             }
1108             STOP_TRACING();
1109         }
1110 
1111         if (attrKeyId != K_UNKNOWN) {
1112             START_TRACING_WITH_EXTRA_INFO(SET_ATTR_SET_TO_NATIVE, componentName_, attrKeyId);
1113             SetAttribute(attrKeyId, newAttrValue);
1114             STOP_TRACING();
1115         }
1116         if (newAttrValue != attrValue) {
1117             // for watcher case, the attrValue is getter, and the newAttrValue is the real value
1118             jerry_release_value(newAttrValue);
1119         }
1120         ReleaseJerryValue(attrKey, attrValue, VA_ARG_END_FLAG);
1121     }
1122     jerry_release_value(attrKeys);
1123     jerry_release_value(attrs);
1124 }
1125 
SetClickEventListener(UIView & view,const jerry_value_t eventFunc,bool isStopPropagation)1126 void Component::SetClickEventListener(UIView &view, const jerry_value_t eventFunc, bool isStopPropagation)
1127 {
1128     onClickListener_ = new ViewOnClickListener(viewModel_, eventFunc, isStopPropagation);
1129     if (onClickListener_ == nullptr) {
1130         HILOG_ERROR(HILOG_MODULE_ACE, "click listener create failed");
1131         return;
1132     }
1133 
1134     view.SetOnClickListener(onClickListener_);
1135     view.SetTouchable(true);
1136 }
1137 
1138 #ifdef JS_EXTRA_EVENT_SUPPORT
SetTouchCancelEventListener(UIView & view,jerry_value_t eventFunc,uint16_t eventTypeId)1139 void Component::SetTouchCancelEventListener(UIView &view, jerry_value_t eventFunc, uint16_t eventTypeId)
1140 {
1141     onTouchCancelListener_ = new ViewOnTouchCancelListener(eventFunc, eventTypeId);
1142     if (onTouchCancelListener_ == nullptr) {
1143         HILOG_ERROR(HILOG_MODULE_ACE, "touch cancel event listener create failed");
1144         return;
1145     }
1146 
1147     view.SetOnTouchListener(onTouchCancelListener_);
1148     view.SetTouchable(true);
1149     view.SetDraggable(true);
1150 }
1151 
SetKeyBoardEventListener(jerry_value_t eventFunc,uint16_t eventTypeId)1152 void Component::SetKeyBoardEventListener(jerry_value_t eventFunc, uint16_t eventTypeId)
1153 {
1154     RootView *rootView = RootView::GetInstance();
1155     if (rootView == nullptr) {
1156         HILOG_ERROR(HILOG_MODULE_ACE, "get rootView is nullptr");
1157         return;
1158     }
1159     keyBoardEventListener_ = new KeyBoardEventListener(eventFunc, eventTypeId);
1160     if (keyBoardEventListener_ == nullptr) {
1161         HILOG_ERROR(HILOG_MODULE_ACE, "on key borard event listener create failed");
1162         return;
1163     }
1164     rootView->SetOnKeyActListener(keyBoardEventListener_);
1165 }
1166 #endif
1167 
SetLongPressEventListener(UIView & view,const jerry_value_t eventFunc,bool isStopPropagation)1168 void Component::SetLongPressEventListener(UIView &view, const jerry_value_t eventFunc, bool isStopPropagation)
1169 {
1170     onLongPressListener_ = new ViewOnLongPressListener(viewModel_, eventFunc, isStopPropagation);
1171     if (onLongPressListener_ == nullptr) {
1172         HILOG_ERROR(HILOG_MODULE_ACE, "long press listener create failed");
1173         return;
1174     }
1175 
1176     view.SetOnLongPressListener(onLongPressListener_);
1177     view.SetTouchable(true);
1178 }
1179 
SetSwipeEventListener(UIView & view,jerry_value_t eventFunc,bool isStopPropagation)1180 void Component::SetSwipeEventListener(UIView &view, jerry_value_t eventFunc, bool isStopPropagation)
1181 {
1182     if (onTouchListener_ == nullptr) {
1183         onTouchListener_ = new ViewOnTouchListener(viewModel_, isStopPropagation);
1184     }
1185     if (onTouchListener_ == nullptr) {
1186         HILOG_ERROR(HILOG_MODULE_ACE, "DragEnd listener create failed");
1187         return;
1188     }
1189 
1190     view.SetOnDragListener(onTouchListener_);
1191     view.SetDraggable(true);
1192     view.SetTouchable(true);
1193 
1194     onTouchListener_->SetBindSwipeFuncName(eventFunc);
1195 }
1196 
SetTouchStartEventListener(UIView & view,jerry_value_t eventFunc,bool isStopPropagation)1197 void Component::SetTouchStartEventListener(UIView &view, jerry_value_t eventFunc, bool isStopPropagation)
1198 {
1199     if (onTouchListener_ == nullptr) {
1200         onTouchListener_ = new ViewOnTouchListener(viewModel_, isStopPropagation);
1201     }
1202     if (onTouchListener_ == nullptr) {
1203         HILOG_ERROR(HILOG_MODULE_ACE, "DragStart listener create failed");
1204         return;
1205     }
1206 
1207     view.SetOnDragListener(onTouchListener_);
1208 
1209     view.SetDraggable(true);
1210     view.SetTouchable(true);
1211 
1212     onTouchListener_->SetBindTouchStartFuncName(eventFunc);
1213 }
1214 
SetTouchMoveEventListener(UIView & view,jerry_value_t eventFunc,bool isStopPropagation)1215 void Component::SetTouchMoveEventListener(UIView &view, jerry_value_t eventFunc, bool isStopPropagation)
1216 {
1217     if (onTouchListener_ == nullptr) {
1218         onTouchListener_ = new ViewOnTouchListener(viewModel_, isStopPropagation);
1219     }
1220     if (onTouchListener_ == nullptr) {
1221         HILOG_ERROR(HILOG_MODULE_ACE, "Drag listener create failed");
1222         return;
1223     }
1224 
1225     view.SetOnDragListener(onTouchListener_);
1226     view.SetDraggable(true);
1227     view.SetTouchable(true);
1228 
1229     onTouchListener_->SetBindTouchMoveFuncName(eventFunc);
1230 }
1231 
SetTouchEndEventListener(UIView & view,jerry_value_t eventFunc,bool isStopPropagation)1232 void Component::SetTouchEndEventListener(UIView &view, jerry_value_t eventFunc, bool isStopPropagation)
1233 {
1234     if (onTouchListener_ == nullptr) {
1235         onTouchListener_ = new ViewOnTouchListener(viewModel_, isStopPropagation);
1236     }
1237     if (onTouchListener_ == nullptr) {
1238         HILOG_ERROR(HILOG_MODULE_ACE, "DragEnd listener create failed");
1239         return;
1240     }
1241 
1242     view.SetOnDragListener(onTouchListener_);
1243     view.SetDraggable(true);
1244     view.SetTouchable(true);
1245 
1246     onTouchListener_->SetBindTouchEndFuncName(eventFunc);
1247 }
1248 
1249 // default implementation
RegisterEventListener(uint16_t eventTypeId,jerry_value_t funcValue,bool isStopPropagation)1250 bool Component::RegisterEventListener(uint16_t eventTypeId, jerry_value_t funcValue, bool isStopPropagation)
1251 {
1252     if (!KeyParser::IsKeyValid(eventTypeId) || IS_UNDEFINED(funcValue)) {
1253         HILOG_ERROR(HILOG_MODULE_ACE, "register event listener failed cause by invalid attribute name or value.");
1254         return false;
1255     }
1256 
1257     UIView *uiView = GetComponentRootView();
1258     if (uiView == nullptr) {
1259         HILOG_ERROR(HILOG_MODULE_ACE, "register event listener failed cause by empty view.");
1260         return false;
1261     }
1262 
1263     bool registerResult = RegisterPrivateEventListener(eventTypeId, funcValue, isStopPropagation);
1264     if (registerResult) {
1265         return true;
1266     }
1267 
1268     return RegisterCommonEventListener(*uiView, eventTypeId, funcValue, isStopPropagation);
1269 }
1270 
RegisterCommonEventListener(UIView & view,const uint16_t eventTypeId,const jerry_value_t funcValue,bool isStopPropagation)1271 bool Component::RegisterCommonEventListener(UIView &view,
1272                                             const uint16_t eventTypeId,
1273                                             const jerry_value_t funcValue,
1274                                             bool isStopPropagation)
1275 {
1276     switch (eventTypeId) {
1277         case K_CLICK: {
1278             SetClickEventListener(view, funcValue, isStopPropagation);
1279             break;
1280         }
1281         case K_LONGPRESS: {
1282             SetLongPressEventListener(view, funcValue, isStopPropagation);
1283             break;
1284         }
1285         case K_SWIPE: {
1286             SetSwipeEventListener(view, funcValue, isStopPropagation);
1287             break;
1288         }
1289         case K_TOUCHSTART: {
1290             SetTouchStartEventListener(view, funcValue, isStopPropagation);
1291             break;
1292         }
1293         case K_TOUCHMOVE: {
1294             SetTouchMoveEventListener(view, funcValue, isStopPropagation);
1295             break;
1296         }
1297         case K_TOUCHEND: {
1298             SetTouchEndEventListener(view, funcValue, isStopPropagation);
1299             break;
1300         }
1301 
1302 #ifdef JS_EXTRA_EVENT_SUPPORT
1303         case K_KEY: {
1304             SetKeyBoardEventListener(funcValue, eventTypeId);
1305             break;
1306         }
1307         case K_TOUCHCANCEL: {
1308             SetTouchCancelEventListener(view, funcValue, eventTypeId);
1309             break;
1310         }
1311 #endif
1312         default: {
1313             return false;
1314         }
1315     }
1316     return true;
1317 }
1318 
ReleaseCommonEventListeners()1319 void Component::ReleaseCommonEventListeners()
1320 {
1321     ACE_DELETE(onClickListener_);
1322     ACE_DELETE(onLongPressListener_);
1323 #ifdef JS_EXTRA_EVENT_SUPPORT
1324     ACE_DELETE(keyBoardEventListener_);
1325     ACE_DELETE(onTouchCancelListener_);
1326 #endif
1327     ACE_DELETE(onTouchListener_);
1328 }
1329 
AppendDescriptorOrElements(Component * parent,const JSValue descriptorOrElements)1330 void Component::AppendDescriptorOrElements(Component *parent, const JSValue descriptorOrElements)
1331 {
1332     if (!JSUndefined::Is(descriptorOrElements)) {
1333         uint16_t size = JSArray::Length(descriptorOrElements);
1334         for (uint16_t idx = 0; idx < size; ++idx) {
1335             JSValue descriptorOrElement = JSArray::Get(descriptorOrElements, idx);
1336             AppendDescriptorOrElement(parent, descriptorOrElement);
1337             JSRelease(descriptorOrElement);
1338         }
1339     }
1340 }
1341 
InvalidateIfNeeded(uint16_t attrKeyId,bool invalidateSelf) const1342 void Component::InvalidateIfNeeded(uint16_t attrKeyId, bool invalidateSelf) const
1343 {
1344     UIView *uiView = GetComponentRootView();
1345     if ((uiView == nullptr) || !KeyParser::IsKeyValid(attrKeyId)) {
1346         return;
1347     }
1348 
1349     if (IsLayoutRelatedAttrs(attrKeyId)) {
1350         if (invalidateSelf) {
1351             uiView->Invalidate();
1352             return;
1353         }
1354         UIView *parent = uiView->GetParent();
1355         if (parent != nullptr) {
1356             parent->LayoutChildren(true);
1357         }
1358     }
1359 }
1360 
ParseEvents()1361 void Component::ParseEvents()
1362 {
1363     /*
1364      New JS bundle:
1365      _c('div', {
1366          catchBubbleEvents: {
1367              longpress: _vm.handleLongPress
1368          },
1369          onBubbleEvents: {
1370              swipe: _vm.handleSwipe
1371          }
1372      });
1373 
1374      The events bound to 'catchBubbleEvents' field should be stoped propagation,
1375      but the events bound to 'onBubbleEvents' field should not.
1376 
1377      Old JS bundle:
1378      _('div', {
1379          on: {
1380              click: _vm.handleClick
1381          },
1382      });
1383      The old framework does not support the event bubble mechanism.
1384      Therefore, the events bound to 'on' field are processed as bound to 'onBubbleEvents' field.
1385     */
1386     BindEvents("on", true);
1387     BindEvents("catchBubbleEvents", true);
1388     BindEvents("onBubbleEvents", false);
1389 }
1390 
BindEvents(const char * type,bool isStopPropagation)1391 void Component::BindEvents(const char *type, bool isStopPropagation)
1392 {
1393     JSValue events = JSObject::Get(options_, type);
1394     if (JSUndefined::Is(events)) {
1395         JSRelease(events);
1396         return;
1397     }
1398     JSValue keys = JSObject::Keys(events);
1399     if (JSUndefined::Is(keys)) {
1400         JSRelease(keys);
1401         JSRelease(events);
1402         return;
1403     }
1404     uint16_t length = JSArray::Length(keys);
1405     if (length == 0) {
1406         JSRelease(keys);
1407         JSRelease(events);
1408         return;
1409     }
1410     for (uint16_t idx = 0; idx < length; ++idx) {
1411         JSValue key = JSArray::Get(keys, idx);
1412         JSValue func = JSObject::Get(events, key);
1413 
1414         uint16_t keyLength = 0;
1415         char *keyName = MallocStringOf(key, &keyLength);
1416         if (keyLength != 0) {
1417             uint16_t keyId = KeyParser::ParseKeyId(keyName, keyLength);
1418             if (!RegisterEventListener(keyId, func, isStopPropagation)) {
1419                 HILOG_ERROR(HILOG_MODULE_ACE, "Register event listener error.");
1420             }
1421         }
1422         ACE_FREE(keyName);
1423         JSRelease(func);
1424         JSRelease(key);
1425     }
1426     JSRelease(keys);
1427     JSRelease(events);
1428 }
1429 
SetVisible(UIView & view,const AppStyleItem * styleItem) const1430 void Component::SetVisible(UIView &view, const AppStyleItem *styleItem) const
1431 {
1432     if (!IsStyleValueTypeString(styleItem)) {
1433         HILOG_ERROR(HILOG_MODULE_ACE, "Visible style value is invalid!");
1434         return;
1435     }
1436     const char * const strValue = GetStyleStrValue(styleItem);
1437     if (strValue == nullptr) {
1438         return;
1439     }
1440 
1441     uint16_t valueId = KeyParser::ParseKeyId(strValue, GetStyleStrValueLen(styleItem));
1442     view.SetVisible(valueId != K_NONE);
1443 }
1444 
SetBackgroundColor(UIView & view,const AppStyleItem & styleItem) const1445 void Component::SetBackgroundColor(UIView &view, const AppStyleItem &styleItem) const
1446 {
1447     uint32_t color = 0;
1448     uint8_t alpha = OPA_OPAQUE;
1449 
1450     if (GetStyleColorValue(&styleItem, color, alpha)) {
1451         ColorType backgroundRGBColor = GetRGBColor(color);
1452         view.SetStyle(STYLE_BACKGROUND_COLOR, backgroundRGBColor.full);
1453         view.SetStyle(STYLE_BACKGROUND_OPA, alpha);
1454     }
1455 }
1456 
SetOpacity(UIView & view,const AppStyleItem & styleItem) const1457 void Component::SetOpacity(UIView &view, const AppStyleItem &styleItem) const
1458 {
1459     if (styleItem.GetValueType() != STYLE_PROP_VALUE_TYPE_FLOATING) {
1460         return;
1461     }
1462     double opacity = styleItem.GetFloatingValue();
1463     const double opacityMin = 0.0;
1464     const double opacityMax = 1.0;
1465     if (opacity < opacityMin) {
1466         opacity = opacityMin;
1467     } else if (opacity > opacityMax) {
1468         opacity = opacityMax;
1469     }
1470     view.SetOpaScale(static_cast<uint8_t>(opacity * OPA_OPAQUE));
1471 }
1472 
SetMargin(UIView & view) const1473 void Component::SetMargin(UIView &view) const
1474 {
1475     SetLeftMargin(view);
1476     SetTopMargin(view);
1477     SetRightMargin(view);
1478     SetBottomMargin(view);
1479 }
1480 
SetLeftMargin(UIView & view) const1481 void Component::SetLeftMargin(UIView &view) const
1482 {
1483     if (marginLeft_.type == DimensionType::TYPE_PIXEL) {
1484         view.SetStyle(STYLE_MARGIN_LEFT, marginLeft_.value.pixel);
1485     }
1486 }
1487 
SetTopMargin(UIView & view) const1488 void Component::SetTopMargin(UIView &view) const
1489 {
1490     if (marginTop_.type == DimensionType::TYPE_PIXEL) {
1491         view.SetStyle(STYLE_MARGIN_TOP, marginTop_.value.pixel);
1492     }
1493 }
1494 
SetRightMargin(UIView & view) const1495 void Component::SetRightMargin(UIView &view) const
1496 {
1497     if (marginRight_.type == DimensionType::TYPE_PIXEL) {
1498         view.SetStyle(STYLE_MARGIN_RIGHT, marginRight_.value.pixel);
1499     }
1500 }
1501 
SetBottomMargin(UIView & view) const1502 void Component::SetBottomMargin(UIView &view) const
1503 {
1504     if (marginBottom_.type == DimensionType::TYPE_PIXEL) {
1505         view.SetStyle(STYLE_MARGIN_BOTTOM, marginBottom_.value.pixel);
1506     }
1507 }
1508 
SetPadding(UIView & view,const AppStyleItem & styleItem) const1509 void Component::SetPadding(UIView &view, const AppStyleItem &styleItem) const
1510 {
1511     SetLeftPadding(view, styleItem);
1512     SetTopPadding(view, styleItem);
1513     SetRightPadding(view, styleItem);
1514     SetBottomPadding(view, styleItem);
1515 }
1516 
SetLeftPadding(UIView & view,const AppStyleItem & styleItem) const1517 void Component::SetLeftPadding(UIView &view, const AppStyleItem &styleItem) const
1518 {
1519     int32_t paddingLeft = GetStylePixelValue(&styleItem);
1520     if (paddingLeft >= 0) {
1521         view.SetStyle(STYLE_PADDING_LEFT, paddingLeft);
1522     }
1523 }
1524 
SetTopPadding(UIView & view,const AppStyleItem & styleItem) const1525 void Component::SetTopPadding(UIView &view, const AppStyleItem &styleItem) const
1526 {
1527     int32_t paddingTop = GetStylePixelValue(&styleItem);
1528     if (paddingTop >= 0) {
1529         view.SetStyle(STYLE_PADDING_TOP, paddingTop);
1530     }
1531 }
1532 
SetRightPadding(UIView & view,const AppStyleItem & styleItem) const1533 void Component::SetRightPadding(UIView &view, const AppStyleItem &styleItem) const
1534 {
1535     int32_t paddingRight = GetStylePixelValue(&styleItem);
1536     if (paddingRight >= 0) {
1537         view.SetStyle(STYLE_PADDING_RIGHT, paddingRight);
1538     }
1539 }
1540 
SetBottomPadding(UIView & view,const AppStyleItem & styleItem) const1541 void Component::SetBottomPadding(UIView &view, const AppStyleItem &styleItem) const
1542 {
1543     int32_t paddingBottom = GetStylePixelValue(&styleItem);
1544     if (paddingBottom >= 0) {
1545         view.SetStyle(STYLE_PADDING_BOTTOM, paddingBottom);
1546     }
1547 }
1548 
SetBorderColor(UIView & view,const AppStyleItem & styleItem) const1549 void Component::SetBorderColor(UIView &view, const AppStyleItem &styleItem) const
1550 {
1551     uint32_t color = 0;
1552     uint8_t alpha = OPA_OPAQUE;
1553     if (GetStyleColorValue(&styleItem, color, alpha)) {
1554         view.SetStyle(STYLE_BORDER_COLOR, GetRGBColor(color).full);
1555         view.SetStyle(STYLE_BORDER_OPA, alpha);
1556     }
1557 }
1558 
SetBorderRadius(UIView & view,const AppStyleItem & styleItem) const1559 void Component::SetBorderRadius(UIView &view, const AppStyleItem &styleItem) const
1560 {
1561     view.SetStyle(STYLE_BORDER_RADIUS, GetStylePixelValue(&styleItem));
1562 }
1563 
SetBorderWidth(UIView & view,const AppStyleItem & styleItem) const1564 void Component::SetBorderWidth(UIView &view, const AppStyleItem &styleItem) const
1565 {
1566     view.SetStyle(STYLE_BORDER_WIDTH, GetStylePixelValue(&styleItem));
1567 }
1568 
SetListForWatcher(jerry_value_t getter,jerry_value_t children)1569 jerry_value_t Component::SetListForWatcher(jerry_value_t getter, jerry_value_t children)
1570 {
1571     jerry_value_t options = jerry_create_object();
1572     JerrySetNamedProperty(options, ARG_WATCH_EL, nativeElement_);
1573 
1574     jerry_value_t watcher = CallJSWatcher(getter, ListForWatcherCallbackFunc, options);
1575     if (IS_UNDEFINED(watcher) || jerry_value_is_error(watcher)) {
1576         HILOG_ERROR(HILOG_MODULE_ACE, "Failed to create ListForWatcher instance.");
1577     } else {
1578         InsertWatcherCommon(watchersHead_, watcher);
1579     }
1580     jerry_release_value(options);
1581     return UNDEFINED;
1582 }
1583 
HandleListForDireactive()1584 void Component::HandleListForDireactive()
1585 {
1586     uint16_t childrenLength = jerry_get_array_length(descriptors_);
1587     for (uint16_t index = 0; index < childrenLength; index++) {
1588         jerry_value_t child = jerry_get_property_by_index(descriptors_, index);
1589         jerry_value_t getterName = jerry_create_string(reinterpret_cast<const jerry_char_t *>(DESCRIPTOR_ATTR_GETTER));
1590         // add watcher to the array which the getter function returned
1591         if (JerryHasProperty(child, getterName)) {
1592             jerry_value_t getter = jerry_get_property(child, getterName);
1593             SetListForWatcher(getter, descriptors_);
1594             jerry_release_value(getter);
1595         }
1596         ReleaseJerryValue(getterName, child, VA_ARG_END_FLAG);
1597     }
1598 }
1599 
AppendChildren(Component * parent)1600 void Component::AppendChildren(Component *parent)
1601 {
1602     if (JSUndefined::Is(descriptors_)) {
1603         return;
1604     }
1605 
1606     children_ = JSArray::Create(0);
1607     uint16_t size = JSArray::Length(descriptors_);
1608     for (uint16_t index = 0; index < size; ++index) {
1609         JSValue descriptorOrElement = JSArray::Get(descriptors_, index);
1610         if (!JSUndefined::Is(descriptorOrElement)) {
1611             bool isDescriptor = AppendDescriptorOrElement(parent, descriptorOrElement);
1612             if (isDescriptor) {
1613                 CreateDirectiveWatcher(descriptorOrElement);
1614             }
1615         }
1616         JSRelease(descriptorOrElement);
1617     }
1618 }
1619 
AppendDescriptorOrElement(Component * parent,const jerry_value_t descriptorOrElement)1620 bool Component::AppendDescriptorOrElement(Component *parent, const jerry_value_t descriptorOrElement)
1621 {
1622     if (DescriptorUtils::IsIfDescriptor(descriptorOrElement)) {
1623         AppendIfDescriptor(parent, descriptorOrElement);
1624         return true;
1625     }
1626 
1627     if (DescriptorUtils::IsForDescriptor(descriptorOrElement)) {
1628         AppendForDescriptor(parent, descriptorOrElement);
1629         return true;
1630     }
1631     AppendElement(parent, descriptorOrElement);
1632     return false;
1633 }
1634 
AppendIfDescriptor(Component * parent,const jerry_value_t descriptor)1635 void Component::AppendIfDescriptor(Component *parent, const jerry_value_t descriptor)
1636 {
1637     bool isShown = DescriptorUtils::IsIfDescriptorShown(descriptor);
1638     if (isShown) {
1639         JSValue decriptorOrElement = DescriptorUtils::GetDescriptorRendered(descriptor);
1640         if (!JSUndefined::Is(decriptorOrElement)) {
1641             AppendDescriptorOrElement(parent, decriptorOrElement);
1642             JSRelease(decriptorOrElement);
1643         } else {
1644             // Don't release decriptorOrElement
1645             // because decriptorOrElement is the result of jerry_create_object but jerry_get_property
1646             decriptorOrElement = DescriptorUtils::RenderIfDescriptor(descriptor);
1647             AppendDescriptorOrElement(parent, decriptorOrElement);
1648 
1649             // does decriptorOrElement need to be release if decriptorOrElement is descriptor
1650         }
1651     } else {
1652         DescriptorUtils::DelIfDescriptorRendered(descriptor);
1653     }
1654 }
AppendForDescriptor(Component * parent,const jerry_value_t descriptor)1655 void Component::AppendForDescriptor(Component *parent, const jerry_value_t descriptor)
1656 {
1657     JSValue descriptorOrelements = DescriptorUtils::GetDescriptorRendered(descriptor);
1658     if (!JSUndefined::Is(descriptorOrelements)) {
1659         AppendDescriptorOrElements(parent, descriptorOrelements);
1660         JSRelease(descriptorOrelements);
1661     } else {
1662         // Don't release decriptorOrElements
1663         // because decriptorOrElements is the result of jerry_create_object but jerry_get_property
1664         descriptorOrelements = DescriptorUtils::RenderForDescriptor(descriptor);
1665         AppendDescriptorOrElements(parent, descriptorOrelements);
1666     }
1667 }
AppendElement(Component * parent,const jerry_value_t element)1668 void Component::AppendElement(Component *parent, const jerry_value_t element)
1669 {
1670     if (parent == nullptr) {
1671         return;
1672     }
1673     Component *component = nullptr;
1674     if (!JSObject::GetNativePointer(element, reinterpret_cast<void **>(&component))) {
1675         // if get binding component native pointer failed from a child element, just release that element
1676         HILOG_ERROR(HILOG_MODULE_ACE, "fatal error, no component is binded to the child element, not allowed.");
1677         // try to release this element and its children, it means we drop them all
1678         DescriptorUtils::ReleaseDescriptorOrElement(element);
1679         return;
1680     }
1681     JSArray::Push(children_, element);
1682     parent->AddChild(component);
1683 }
1684 
1685 /*
1686  * NOTE: add one child will not attach the native view immediately, but
1687  * when removing one child, the child native view will be detached immediately
1688  */
AddChild(Component * childNode)1689 void Component::AddChild(Component *childNode)
1690 {
1691     if (childNode == nullptr) {
1692         return;
1693     }
1694 
1695     if (childHead_ == nullptr) {
1696         childNode->SetParent(this);
1697         childNode->SetNextSibling(nullptr);
1698         childHead_ = childNode;
1699         return;
1700     }
1701 
1702     // find the tail
1703     Component *temp = childHead_;
1704     while ((temp != nullptr) && (temp->GetNextSibling() != nullptr)) {
1705         if (temp == childNode) {
1706             // already added in the list, drop
1707             return;
1708         }
1709         temp = const_cast<Component *>(temp->GetNextSibling());
1710     }
1711     childNode->SetParent(this);
1712     temp->SetNextSibling(childNode);
1713     childNode->SetNextSibling(nullptr);
1714 }
1715 
RemoveChild(Component * childNode)1716 void Component::RemoveChild(Component *childNode)
1717 {
1718     if ((childNode == nullptr) || (childHead_ == nullptr)) {
1719         return;
1720     }
1721 
1722     UIView *childNativeView = childNode->GetComponentRootView();
1723     UIViewGroup *parentView = reinterpret_cast<UIViewGroup *>(GetComponentRootView());
1724     if (childNativeView == nullptr || parentView == nullptr) {
1725         return;
1726     }
1727 
1728     if (childNode == childHead_) {
1729         // it is the head
1730         Component *next = const_cast<Component *>(childHead_->GetNextSibling());
1731         childNode->SetNextSibling(nullptr);
1732         childNode->SetParent(nullptr);
1733         childHead_ = next;
1734         parentView->Remove(childNativeView);
1735         return;
1736     }
1737 
1738     // find the target node's pre one
1739     Component *temp = childHead_;
1740     while (temp != nullptr) {
1741         if (temp->GetNextSibling() == childNode) {
1742             // found it
1743             break;
1744         }
1745         temp = const_cast<Component *>(temp->GetNextSibling());
1746     }
1747     if (temp == nullptr) {
1748         // not found
1749         return;
1750     }
1751 
1752     temp->SetNextSibling(childNode->GetNextSibling());
1753     childNode->SetNextSibling(nullptr);
1754     childNode->SetParent(nullptr);
1755     parentView->Remove(childNativeView);
1756 }
1757 
RemoveAllChildren()1758 void Component::RemoveAllChildren()
1759 {
1760     while (childHead_ != nullptr) {
1761         RemoveChild(childHead_);
1762     }
1763 }
1764 
CreateDirectiveWatcher(jerry_value_t descriptor)1765 void Component::CreateDirectiveWatcher(jerry_value_t descriptor)
1766 {
1767     JSValue watcher = DescriptorUtils::CreateDescriptorWatcher(nativeElement_, descriptor);
1768     if (!JSUndefined::Is(watcher)) {
1769         InsertWatcherCommon(watchersHead_, watcher);
1770     }
1771 }
1772 
IsAttached() const1773 bool Component::IsAttached() const
1774 {
1775     UIView *nativeView = GetComponentRootView();
1776     if (nativeView == nullptr) {
1777         return false;
1778     }
1779     return (nativeView->GetParent() != nullptr);
1780 }
1781 
BuildViewTree(Component * currComponent,Component * parent,const ConstrainedParameter & parentParameter)1782 void Component::BuildViewTree(Component *currComponent, Component *parent, const ConstrainedParameter &parentParameter)
1783 {
1784     if (currComponent == nullptr) {
1785         return;
1786     }
1787 
1788     // align self dimension
1789     currComponent->AlignDimensions(parentParameter);
1790     // refresh rect (border box sizing -> content box sizing)
1791     currComponent->AdaptBoxSizing();
1792     // attach to parent, and avoid attaching repeatly
1793     if (parent != nullptr && !currComponent->IsAttached()) {
1794         parent->AttachView(currComponent);
1795         // notify view has been attached to tree, it means the parent's size is already calculated out
1796         currComponent->OnViewAttached();
1797     }
1798 
1799     Component *child = const_cast<Component *>(currComponent->GetChildHead());
1800     if (child == nullptr) {
1801         return;
1802     }
1803     // the child only can layout in the content area of parent
1804     ConstrainedParameter alignParameter;
1805     currComponent->GetConstrainedParam(alignParameter);
1806     while (child != nullptr) {
1807         BuildViewTree(child, currComponent, alignParameter);
1808         child = const_cast<Component *>(child->GetNextSibling());
1809     }
1810     // consider how to avoid layout repeatly, for example: div - div -- div
1811     currComponent->LayoutChildren();
1812 }
1813 
HandleChildrenChange(jerry_value_t descriptor)1814 void Component::HandleChildrenChange(jerry_value_t descriptor)
1815 {
1816     RemoveAllChildren();
1817     if (!JSUndefined::Is(children_)) {
1818         JSRelease(children_);
1819         children_ = JSArray::Create(0);
1820     }
1821 
1822     uint16_t size = JSArray::Length(descriptors_);
1823     for (uint16_t idx = 0; idx < size; ++idx) {
1824         JSValue descriptorOrElement = JSArray::Get(descriptors_, idx);
1825         if (IS_UNDEFINED(descriptorOrElement)) {
1826             continue;
1827         }
1828         if (descriptorOrElement == descriptor) {
1829             UpdateDescriptor(this, descriptorOrElement);
1830         } else {
1831             ReappendDescriptorOrElement(this, descriptorOrElement);
1832         }
1833         JSRelease(descriptorOrElement);
1834     }
1835 
1836     Component *parent = const_cast<Component *>(GetParent());
1837     ConstrainedParameter parentParam;
1838     Component *target = (parent == nullptr) ? this : parent;
1839     target->GetConstrainedParam(parentParam);
1840     BuildViewTree(this, nullptr, parentParam);
1841     target->LayoutChildren();
1842     target->Invalidate();
1843 }
1844 
UpdateDescriptor(Component * parent,const jerry_value_t descriptor)1845 void Component::UpdateDescriptor(Component *parent, const jerry_value_t descriptor)
1846 {
1847     if (DescriptorUtils::IsIfDescriptor(descriptor)) {
1848         AppendIfDescriptor(parent, descriptor);
1849     } else if (DescriptorUtils::IsForDescriptor(descriptor)) {
1850         // Release descriptor last rendered
1851         DescriptorUtils::DelForDescriptorRendered(descriptor);
1852 
1853         // Re-render descriptor
1854         JSValue descriptorOrElements = DescriptorUtils::RenderForDescriptor(descriptor);
1855         AppendDescriptorOrElements(parent, descriptorOrElements);
1856     } else {
1857         // never
1858     }
1859 }
1860 
ReappendDescriptorOrElement(Component * parent,const jerry_value_t descriptor)1861 void Component::ReappendDescriptorOrElement(Component *parent, const jerry_value_t descriptor)
1862 {
1863     if (DescriptorUtils::IsIfDescriptor(descriptor)) {
1864         JSValue descriptorOrElement = DescriptorUtils::GetDescriptorRendered(descriptor);
1865         if (!JSUndefined::Is(descriptorOrElement)) {
1866             AppendDescriptorOrElement(parent, descriptor);
1867         }
1868         JSRelease(descriptorOrElement);
1869     } else if (DescriptorUtils::IsForDescriptor(descriptor)) {
1870         JSValue descriptorOrElements = DescriptorUtils::GetDescriptorRendered(descriptor);
1871         if (!JSUndefined::Is(descriptorOrElements)) {
1872             AppendDescriptorOrElements(parent, descriptorOrElements);
1873         }
1874         JSRelease(descriptorOrElements);
1875     } else {
1876         AppendElement(parent, descriptor);
1877     }
1878 }
1879 
GetStylePixelValue(const AppStyleItem * style,int32_t defaultValue) const1880 int32_t Component::GetStylePixelValue(const AppStyleItem *style, int32_t defaultValue) const
1881 {
1882     if (style->GetValueType() == STYLE_PROP_VALUE_TYPE_NUMBER) {
1883         return style->GetNumValue();
1884     }
1885     if (style->GetValueType() == STYLE_PROP_VALUE_TYPE_STRING) {
1886         if (style->GetStrValue() == nullptr) {
1887             HILOG_WARN(HILOG_MODULE_ACE, "Get Style PixelValue failed, return default value!");
1888             return defaultValue;
1889         }
1890         return strtol(style->GetStrValue(), nullptr, DEC);
1891     }
1892     return defaultValue;
1893 }
1894 
GetStyleDegValue(const AppStyleItem * style,int16_t defaultValue) const1895 int16_t Component::GetStyleDegValue(const AppStyleItem *style, int16_t defaultValue) const
1896 {
1897     if (style->GetValueType() == STYLE_PROP_VALUE_TYPE_NUMBER) {
1898         return style->GetNumValue();
1899     }
1900     if (style->GetValueType() == STYLE_PROP_VALUE_TYPE_STRING) {
1901         if (style->GetStrValue() == nullptr) {
1902             HILOG_WARN(HILOG_MODULE_ACE, "Get Style DegValue failed, return default value!");
1903             return defaultValue;
1904         }
1905         return strtol(style->GetStrValue(), nullptr, DEC);
1906     }
1907     return defaultValue;
1908 }
1909 
GetStyleColorValue(const AppStyleItem * style,uint32_t & color,uint8_t & alpha) const1910 bool Component::GetStyleColorValue(const AppStyleItem *style, uint32_t &color, uint8_t &alpha) const
1911 {
1912     if (style->GetValueType() == STYLE_PROP_VALUE_TYPE_NUMBER) {
1913         color = style->GetNumValue();
1914         alpha = OPA_OPAQUE;
1915         return true;
1916     }
1917     if (style->GetValueType() == STYLE_PROP_VALUE_TYPE_STRING) {
1918         return ParseColor(style->GetStrValue(), color, alpha);
1919     }
1920     HILOG_ERROR(HILOG_MODULE_ACE, "invalid color format!");
1921     return false;
1922 }
1923 
HandleBackgroundImg(const AppStyleItem & styleItem,char * & pressedImage,char * & normalImage) const1924 bool Component::HandleBackgroundImg(const AppStyleItem &styleItem, char *&pressedImage, char *&normalImage) const
1925 {
1926     bool result = false;
1927     if (styleItem.GetValueType() == STYLE_PROP_VALUE_TYPE_STRING) {
1928         const char * const url = styleItem.GetStrValue();
1929         char *filePath = CreatePathStrFromUrl(url);
1930         if (filePath != nullptr) {
1931             char *imagePath = JsAppContext::GetInstance()->GetResourcePath(filePath);
1932             if (imagePath == nullptr) {
1933                 ace_free(filePath);
1934                 filePath = nullptr;
1935                 return result;
1936             }
1937 #if (OHOS_ACELITE_PRODUCT_WATCH == 1)
1938             // convert .png/jpeg/bmp to .bin subfix
1939             CureImagePath(imagePath);
1940 #endif // OHOS_ACELITE_PRODUCT_WATCH
1941             if ((styleItem.GetPseudoClassType() == PSEUDO_CLASS_ACTIVE) ||
1942                 (styleItem.GetPseudoClassType() == PSEUDO_CLASS_CHECKED)) {
1943                 // in case we don't free the buffer after using
1944                 ACE_FREE(pressedImage);
1945                 pressedImage = imagePath;
1946             } else {
1947                 // in case we don't free the buffer after using
1948                 ACE_FREE(normalImage);
1949                 normalImage = imagePath;
1950             }
1951             ace_free(filePath);
1952             filePath = nullptr;
1953             result = true;
1954         }
1955     }
1956     return result;
1957 }
1958 
1959 #if (FEATURE_ROTATION_API == 1)
HandleRotationRequest(const jerry_value_t func,const jerry_value_t dom,const jerry_value_t args[],const jerry_length_t size)1960 jerry_value_t Component::HandleRotationRequest(const jerry_value_t func,
1961                                                const jerry_value_t dom,
1962                                                const jerry_value_t args[],
1963                                                const jerry_length_t size)
1964 {
1965     UNUSED(func);
1966     UIView *bindedView = ComponentUtils::GetViewFromBindingObject(dom);
1967     if (bindedView == nullptr) {
1968         return UNDEFINED;
1969     }
1970 
1971     // default action is to request the focus even user do not pass the argument
1972     bool focusRequest = true;
1973     if (args != nullptr && size > 0) {
1974         if (!JerryGetBoolProperty(args[0], ATTR_NAME_FOCUS, focusRequest)) {
1975             HILOG_ERROR(HILOG_MODULE_ACE, "not bool argument passed, will clear the focus!");
1976             focusRequest = false;
1977         }
1978     }
1979     if (focusRequest) {
1980         bindedView->RequestFocus();
1981     } else {
1982         bindedView->ClearFocus();
1983     }
1984 
1985     return UNDEFINED;
1986 }
1987 #endif // FEATURE_ROTATION_API
1988 } // namespace ACELite
1989 } // namespace OHOS
1990