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