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
16#include "components/ui_view.h"
17
18#include "components/root_view.h"
19#include "components/ui_view_group.h"
20#include "core/render_manager.h"
21#include "dfx/ui_view_bounds.h"
22#include "dock/focus_manager.h"
23#include "draw/draw_utils.h"
24#include "engines/gfx/gfx_engine_manager.h"
25#include "gfx_utils/graphic_log.h"
26#include "gfx_utils/mem_api.h"
27#include "securec.h"
28#include "themes/theme_manager.h"
29
30namespace OHOS {
31UIView::UIView()
32    : touchable_(false),
33      visible_(true),
34      draggable_(false),
35      dragParentInstead_(true),
36      isViewGroup_(false),
37      needRedraw_(false),
38      styleAllocFlag_(false),
39      isIntercept_(false),
40#if ENABLE_FOCUS_MANAGER
41      focusable_(false),
42#endif
43      opaScale_(OPA_OPAQUE),
44      index_(0),
45      zIndex_(0),
46      id_(nullptr),
47      parent_(nullptr),
48      nextSibling_(nullptr),
49      nextRenderSibling_(nullptr),
50      style_(nullptr),
51      transMap_(nullptr),
52      onClickListener_(nullptr),
53      onLongPressListener_(nullptr),
54      onDragListener_(nullptr),
55      onTouchListener_(nullptr),
56#if ENABLE_FOCUS_MANAGER
57      onFocusListener_(nullptr),
58#endif
59#if ENABLE_ROTATE_INPUT
60      onRotateListener_(nullptr),
61#endif
62      viewExtraMsg_(nullptr),
63      rect_(0, 0, 0, 0),
64      visibleRect_(nullptr)
65{
66    SetupThemeStyles();
67}
68
69UIView::~UIView()
70{
71    if (transMap_ != nullptr) {
72        delete transMap_;
73        transMap_ = nullptr;
74    }
75    if (visibleRect_ != nullptr) {
76        delete visibleRect_;
77        visibleRect_ = nullptr;
78    }
79    if (styleAllocFlag_) {
80        delete style_;
81        style_ = nullptr;
82        styleAllocFlag_ = false;
83    }
84}
85
86bool UIView::OnPreDraw(Rect& invalidatedArea) const
87{
88    Rect rect(GetRect());
89    uint16_t r = style_->borderRadius_; // radius must be positive
90    if (r == COORD_MAX) {
91        return true;
92    }
93    if (r != 0) {
94        r = ((r & 0x1) == 0) ? (r >> 1) : ((r + 1) >> 1);
95        rect.SetLeft(rect.GetX() + r);
96        rect.SetWidth(rect.GetWidth() - r);
97        rect.SetTop(rect.GetY() + r);
98        rect.SetHeight(rect.GetHeight() - r);
99    }
100    if (rect.IsContains(invalidatedArea)) {
101        return true;
102    }
103    invalidatedArea.Intersect(invalidatedArea, rect);
104    return false;
105}
106
107void UIView::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
108{
109    uint8_t opa = GetMixOpaScale();
110    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, GetOrigRect(), invalidatedArea, *style_, opa);
111}
112
113void UIView::OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
114{
115    DrawViewBounds(gfxDstBuffer, invalidatedArea);
116}
117
118void UIView::DrawViewBounds(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
119{
120#if ENABLE_DEBUG
121    if (!UIViewBounds::GetInstance()->GetShowState()) {
122        return;
123    }
124    Style* style = new Style();
125    style->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
126    style->SetStyle(STYLE_BORDER_COLOR, Color::Red().full);
127    style->SetStyle(STYLE_BORDER_WIDTH, 1);
128    style->SetStyle(STYLE_BORDER_OPA, OPA_OPAQUE / 2); // 2: half opacity
129    Rect viewRect(GetRect());
130    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
131    baseGfxEngine->DrawRect(gfxDstBuffer, viewRect, invalidatedArea, *style, OPA_OPAQUE);
132
133    style->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
134    style->SetStyle(STYLE_BACKGROUND_COLOR, Color::Blue().full);
135    style->SetStyle(STYLE_BORDER_WIDTH, 0);
136    Rect tmpRect(viewRect);
137    int16_t length = 10; // 10: corner length
138
139    // left top corner
140    tmpRect.SetRight(viewRect.GetLeft() + length);
141    tmpRect.SetBottom(viewRect.GetTop());
142    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
143    tmpRect.SetRight(viewRect.GetLeft());
144    tmpRect.SetBottom(viewRect.GetTop() + length);
145    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
146
147    // left bottom corner
148    tmpRect.SetLeft(viewRect.GetLeft());
149    tmpRect.SetTop(viewRect.GetBottom() - length);
150    tmpRect.SetRight(viewRect.GetLeft());
151    tmpRect.SetBottom(viewRect.GetBottom());
152    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
153    tmpRect.SetTop(viewRect.GetBottom());
154    tmpRect.SetRight(viewRect.GetLeft() + length);
155    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
156
157    // right top corner
158    tmpRect.SetLeft(viewRect.GetRight() - length);
159    tmpRect.SetTop(viewRect.GetTop());
160    tmpRect.SetRight(viewRect.GetRight());
161    tmpRect.SetBottom(viewRect.GetTop());
162    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
163    tmpRect.SetLeft(viewRect.GetRight());
164    tmpRect.SetBottom(viewRect.GetTop() + length);
165    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
166
167    // right bottom corner
168    tmpRect = viewRect;
169    tmpRect.SetLeft(viewRect.GetRight());
170    tmpRect.SetTop(viewRect.GetBottom() - length);
171    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
172    tmpRect.SetLeft(viewRect.GetRight() - length);
173    tmpRect.SetTop(viewRect.GetBottom());
174    baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
175    delete style;
176#endif // ENABLE_DEBUG
177}
178
179void UIView::SetupThemeStyles()
180{
181    Theme* theme = ThemeManager::GetInstance().GetCurrent();
182    if (theme != nullptr) {
183        style_ = &(theme->GetMainStyle());
184    } else {
185        style_ = &(StyleDefault::GetDefaultStyle());
186    }
187}
188
189void UIView::SetStyle(Style& style)
190{
191    if (styleAllocFlag_) {
192        delete style_;
193        styleAllocFlag_ = false;
194    }
195    style_ = &style;
196}
197
198void UIView::SetStyle(uint8_t key, int64_t value)
199{
200    if (!styleAllocFlag_) {
201        style_ = new Style(*style_);
202        if (style_ == nullptr) {
203            GRAPHIC_LOGE("new Style fail");
204            return;
205        }
206        styleAllocFlag_ = true;
207    }
208    int16_t width = GetWidth();
209    int16_t height = GetHeight();
210    int16_t x = GetX();
211    int16_t y = GetY();
212    style_->SetStyle(key, value);
213    Rect rect(x, y, x + width - 1, y + height - 1);
214    UpdateRectInfo(key, rect);
215}
216
217void UIView::UpdateRectInfo(uint8_t key, const Rect& rect)
218{
219    switch (key) {
220        case STYLE_BORDER_WIDTH: {
221            SetWidth(rect.GetWidth());
222            SetHeight(rect.GetHeight());
223            break;
224        }
225        case STYLE_PADDING_LEFT:
226        case STYLE_PADDING_RIGHT: {
227            SetWidth(rect.GetWidth());
228            break;
229        }
230        case STYLE_PADDING_TOP:
231        case STYLE_PADDING_BOTTOM: {
232            SetHeight(rect.GetHeight());
233            break;
234        }
235        case STYLE_MARGIN_LEFT: {
236            SetX(rect.GetX());
237            break;
238        }
239        case STYLE_MARGIN_TOP: {
240            SetY(rect.GetY());
241            break;
242        }
243        default:
244            break;
245    }
246}
247
248int64_t UIView::GetStyle(uint8_t key) const
249{
250    return style_->GetStyle(key);
251}
252
253const Style& UIView::GetStyleConst() const
254{
255    return *style_;
256}
257
258void UIView::SetOpaScale(uint8_t opaScale)
259{
260    opaScale_ = opaScale;
261}
262
263uint8_t UIView::GetOpaScale() const
264{
265    return opaScale_;
266}
267
268UIView::ViewExtraMsg* UIView::GetExtraMsg()
269{
270    return viewExtraMsg_;
271}
272
273void UIView::SetExtraMsg(ViewExtraMsg* extraMsg)
274{
275    viewExtraMsg_ = extraMsg;
276}
277
278void UIView::Rotate(int16_t angle, const Vector2<float>& pivot)
279{
280    Vector3<float> pivotStart3D = Vector3<float>(pivot.x_, pivot.y_, 0);
281    Vector3<float> pivotEnd3D = Vector3<float>(pivot.x_, pivot.y_, 1.0f);
282    Rotate(angle, pivotStart3D, pivotEnd3D);
283}
284
285void UIView::Rotate(int16_t angle, const Vector3<float>& pivotStart, const Vector3<float>& pivotEnd)
286{
287    if (transMap_ == nullptr) {
288        ReMeasure();
289        transMap_ = new TransformMap();
290    }
291    bool firstTrans = transMap_->IsInvalid();
292    Rect joinRect = transMap_->GetBoxRect();
293    transMap_->SetTransMapRect(GetOrigRect());
294    transMap_->Rotate(angle, pivotStart, pivotEnd);
295    if (firstTrans) {
296        joinRect = transMap_->GetBoxRect();
297    } else {
298        joinRect.Join(joinRect, transMap_->GetBoxRect());
299    }
300    joinRect.Join(joinRect, GetOrigRect());
301    InvalidateRect(joinRect);
302}
303
304void UIView::Scale(const Vector2<float>& scale, const Vector2<float>& pivot)
305{
306    Vector3<float> scale3D = Vector3<float>(scale.x_, scale.y_, 1.0f);
307    Vector3<float> pivot3D = Vector3<float>(pivot.x_, pivot.y_, 0);
308    Scale(scale3D, pivot3D);
309}
310
311void UIView::Scale(const Vector3<float>& scale, const Vector3<float>& pivot)
312{
313    if (transMap_ == nullptr) {
314        ReMeasure();
315        transMap_ = new TransformMap();
316    }
317    bool firstTrans = transMap_->IsInvalid();
318    Rect joinRect = transMap_->GetBoxRect();
319    transMap_->SetTransMapRect(GetOrigRect());
320    transMap_->Scale(scale, pivot);
321    if (firstTrans) {
322        joinRect = transMap_->GetBoxRect();
323    } else {
324        joinRect.Join(joinRect, transMap_->GetBoxRect());
325    }
326    joinRect.Join(joinRect, GetOrigRect());
327    InvalidateRect(joinRect);
328}
329
330void UIView::Shear(const Vector2<float>& shearX, const Vector2<float>& shearY, const Vector2<float>& shearZ)
331{
332    if (transMap_ == nullptr) {
333        ReMeasure();
334        transMap_ = new TransformMap();
335        if (transMap_ == nullptr) {
336            return;
337        }
338    }
339    bool firstTrans = transMap_->IsInvalid();
340    Rect joinRect = transMap_->GetBoxRect();
341    transMap_->SetTransMapRect(GetOrigRect());
342    transMap_->Shear(shearX, shearY, shearZ);
343    if (firstTrans) {
344        joinRect = transMap_->GetBoxRect();
345    } else {
346        joinRect.Join(joinRect, transMap_->GetBoxRect());
347    }
348    joinRect.Join(joinRect, GetOrigRect());
349    InvalidateRect(joinRect);
350}
351
352void UIView::Translate(const Vector2<int16_t>& trans)
353{
354    Vector3<int16_t> trans3D = Vector3<int16_t>(trans.x_, trans.y_, 0);
355    Translate(trans3D);
356}
357
358void UIView::Translate(const Vector3<int16_t>& trans)
359{
360    if (transMap_ == nullptr) {
361        ReMeasure();
362        transMap_ = new TransformMap();
363    }
364    bool firstTrans = transMap_->IsInvalid();
365    Rect joinRect = transMap_->GetBoxRect();
366    transMap_->SetTransMapRect(GetOrigRect());
367    transMap_->Translate(trans);
368    if (firstTrans) {
369        joinRect = transMap_->GetBoxRect();
370    } else {
371        joinRect.Join(joinRect, transMap_->GetBoxRect());
372    }
373    joinRect.Join(joinRect, GetOrigRect());
374    InvalidateRect(joinRect);
375}
376
377bool UIView::IsTransInvalid()
378{
379    if (transMap_ == nullptr) {
380        return true;
381    }
382    return transMap_->IsInvalid();
383}
384
385void UIView::SetCameraDistance(int16_t distance)
386{
387    if (transMap_ == nullptr) {
388        ReMeasure();
389        transMap_ = new TransformMap();
390    }
391    Rect joinRect = transMap_->GetBoxRect();
392    transMap_->SetTransMapRect(GetOrigRect());
393    transMap_->SetCameraDistance(distance);
394    joinRect.Join(joinRect, transMap_->GetBoxRect());
395    joinRect.Join(joinRect, GetOrigRect());
396    InvalidateRect(joinRect);
397}
398
399void UIView::SetCameraPosition(const Vector2<float>& position)
400{
401    if (transMap_ == nullptr) {
402        ReMeasure();
403        transMap_ = new TransformMap();
404    }
405    Rect joinRect = transMap_->GetBoxRect();
406    transMap_->SetTransMapRect(GetOrigRect());
407    transMap_->SetCameraPosition(position);
408    joinRect.Join(joinRect, transMap_->GetBoxRect());
409    joinRect.Join(joinRect, GetOrigRect());
410    InvalidateRect(joinRect);
411}
412
413void UIView::ResetTransParameter()
414{
415    if (transMap_ != nullptr) {
416        delete transMap_;
417        transMap_ = nullptr;
418        Invalidate();
419    }
420}
421
422#if ENABLE_ROTATE_INPUT
423void UIView::RequestFocus()
424{
425    FocusManager::GetInstance()->RequestFocus(this);
426}
427
428void UIView::ClearFocus()
429{
430    FocusManager::GetInstance()->ClearFocus();
431}
432#endif
433
434void UIView::Invalidate()
435{
436    UIView* view = this;
437    while (view != nullptr) {
438        if (view->transMap_ != nullptr && !view->GetTransformMap().IsInvalid() && view != this) {
439            InvalidateRect(view->GetRect(), view);
440            return;
441        }
442        view = view->parent_;
443    }
444    InvalidateRect(GetRect());
445}
446
447void UIView::InvalidateRect(const Rect& invalidatedArea, UIView* view)
448{
449    if (!visible_) {
450        if (needRedraw_) {
451            needRedraw_ = false;
452        } else {
453            return;
454        }
455    }
456
457    if (view == nullptr) {
458        view = this;
459    }
460    Rect trunc(invalidatedArea);
461    bool isIntersect = true;
462    UIView* par = view->parent_;
463    UIView* cur = view;
464
465    while (par != nullptr) {
466        if (!par->visible_) {
467            return;
468        }
469
470        isIntersect = trunc.Intersect(par->GetContentRect(), trunc);
471        if (!isIntersect) {
472            break;
473        }
474
475        cur = par;
476        par = par->parent_;
477    }
478
479    if (isIntersect && (cur->GetViewType() == UI_ROOT_VIEW)) {
480        RootView* rootView = reinterpret_cast<RootView*>(cur);
481        rootView->AddInvalidateRectWithLock(trunc, view);
482    }
483}
484
485bool UIView::OnLongPressEvent(const LongPressEvent& event)
486{
487    if (onLongPressListener_ != nullptr) {
488        /* To ensure version compatibility, the listeners of both versions are invoked. */
489        bool isConsumed = onLongPressListener_->OnLongPress(*this, event);
490        return isConsumed;
491    }
492    return isIntercept_;
493}
494
495bool UIView::OnDragStartEvent(const DragEvent& event)
496{
497    if (onDragListener_ != nullptr) {
498        /* To ensure version compatibility, the listeners of both versions are invoked. */
499        bool isConsumed = onDragListener_->OnDragStart(*this, event);
500        return isConsumed;
501    }
502    return isIntercept_;
503}
504
505bool UIView::OnDragEvent(const DragEvent& event)
506{
507    if (onDragListener_ != nullptr) {
508        /* To ensure version compatibility, the listeners of both versions are invoked. */
509        bool isConsumed = onDragListener_->OnDrag(*this, event);
510        return isConsumed;
511    }
512    return isIntercept_;
513}
514
515bool UIView::OnDragEndEvent(const DragEvent& event)
516{
517    if (onDragListener_ != nullptr) {
518        /* To ensure version compatibility, the listeners of both versions are invoked. */
519        bool isConsumed = onDragListener_->OnDragEnd(*this, event);
520        return isConsumed;
521    }
522    return isIntercept_;
523}
524
525bool UIView::OnClickEvent(const ClickEvent& event)
526{
527    if (onClickListener_ != nullptr) {
528        /* To ensure version compatibility, the listeners of both versions are invoked. */
529        bool isConsumed = onClickListener_->OnClick(*this, event);
530        return isConsumed;
531    }
532    return isIntercept_;
533}
534
535bool UIView::OnPressEvent(const PressEvent& event)
536{
537    if (onTouchListener_ != nullptr) {
538        /* To ensure version compatibility, the listeners of both versions are invoked. */
539        bool isConsumed = onTouchListener_->OnPress(*this, event);
540        return isConsumed;
541    }
542    return isIntercept_;
543}
544
545bool UIView::OnReleaseEvent(const ReleaseEvent& event)
546{
547    if (onTouchListener_ != nullptr) {
548        /* To ensure version compatibility, the listeners of both versions are invoked. */
549        bool isConsumed = onTouchListener_->OnRelease(*this, event);
550        return isConsumed;
551    }
552    return isIntercept_;
553}
554
555bool UIView::OnCancelEvent(const CancelEvent& event)
556{
557    if (onTouchListener_ != nullptr) {
558        /* To ensure version compatibility, the listeners of both versions are invoked. */
559        bool isConsumed = onTouchListener_->OnCancel(*this, event);
560        return isConsumed;
561    }
562    return isIntercept_;
563}
564
565void UIView::SetOnDragListener(OnDragListener* onDragListener)
566{
567    onDragListener_ = onDragListener;
568}
569
570UIView::OnDragListener*& UIView::GetOnDragListener()
571{
572    return onDragListener_;
573}
574
575void UIView::SetOnClickListener(OnClickListener* onClickListener)
576{
577    onClickListener_ = onClickListener;
578}
579
580UIView::OnClickListener*& UIView::GetOnClickListener()
581{
582    return onClickListener_;
583}
584
585void UIView::SetOnLongPressListener(OnLongPressListener* onLongPressListener)
586{
587    onLongPressListener_ = onLongPressListener;
588}
589
590UIView::OnLongPressListener*& UIView::GetOnLongPressListener()
591{
592    return onLongPressListener_;
593}
594
595void UIView::SetOnTouchListener(OnTouchListener* onTouchListener)
596{
597    onTouchListener_ = onTouchListener;
598}
599
600UIView::OnTouchListener*& UIView::GetTouchListener()
601{
602    return onTouchListener_;
603}
604
605void UIView::SetParent(UIView* parent)
606{
607    parent_ = parent;
608}
609
610UIView* UIView::GetParent() const
611{
612    return parent_;
613}
614
615void UIView::SetNextSibling(UIView* sibling)
616{
617    nextSibling_ = sibling;
618}
619
620UIView* UIView::GetNextSibling() const
621{
622    return nextSibling_;
623}
624
625void UIView::SetNextRenderSibling(UIView* renderSibling)
626{
627    nextRenderSibling_ = renderSibling;
628}
629
630UIView* UIView::GetNextRenderSibling() const
631{
632    return nextRenderSibling_;
633}
634
635void UIView::SetVisible(bool visible)
636{
637    if (visible_ != visible) {
638        visible_ = visible;
639        needRedraw_ = true;
640        Invalidate();
641    }
642}
643
644bool UIView::IsVisible() const
645{
646    return visible_;
647}
648
649void UIView::SetTouchable(bool touch)
650{
651    touchable_ = touch;
652}
653
654bool UIView::IsTouchable() const
655{
656    return touchable_;
657}
658
659void UIView::SetDraggable(bool draggable)
660{
661    draggable_ = draggable;
662    dragParentInstead_ = !draggable;
663}
664
665bool UIView::IsDraggable() const
666{
667    return draggable_;
668}
669
670void UIView::SetDragParentInstead(bool dragParentInstead)
671{
672    dragParentInstead_ = dragParentInstead;
673}
674
675bool UIView::IsDragParentInstead() const
676{
677    return dragParentInstead_;
678}
679
680#if ENABLE_ROTATE_INPUT
681bool UIView::OnRotateStartEvent(const RotateEvent& event)
682{
683    if (onRotateListener_ != nullptr) {
684        return onRotateListener_->OnRotateStart(*this, event);
685    }
686    return false;
687}
688
689bool UIView::OnRotateEvent(const RotateEvent& event)
690{
691    if (onRotateListener_ != nullptr) {
692        return onRotateListener_->OnRotate(*this, event);
693    }
694    return isIntercept_;
695}
696
697bool UIView::OnRotateEndEvent(const RotateEvent& event)
698{
699    if (onRotateListener_ != nullptr) {
700        return onRotateListener_->OnRotateEnd(*this, event);
701    }
702    return false;
703}
704
705void UIView::SetOnRotateListener(OnRotateListener* onRotateListener)
706{
707    onRotateListener_ = onRotateListener;
708}
709
710#endif
711
712void UIView::GetTargetView(const Point& point, UIView** last)
713{
714    if (last == nullptr) {
715        return;
716    }
717    UIView* par = parent_;
718    Rect rect = GetRect();
719
720    if (par != nullptr) {
721        rect.Intersect(par->GetContentRect(), rect);
722    }
723
724    if (visible_ && touchable_ && rect.IsContains(point)) {
725        *last = this;
726    }
727}
728
729void UIView::GetTargetView(const Point& point, UIView** current, UIView** target)
730{
731    if (current == nullptr) {
732        return;
733    }
734    UIView* par = parent_;
735    Rect rect = GetRect();
736
737    if (par != nullptr) {
738        rect.Intersect(par->GetOrigContentRect(), rect);
739    }
740
741    if (visible_ && rect.IsContains(point)) {
742        if (touchable_) {
743            *current = this;
744        }
745        *target = this;
746    }
747}
748
749#if ENABLE_FOCUS_MANAGER
750void UIView::SetFocusable(bool focusable)
751{
752    focusable_ = focusable;
753}
754
755bool UIView::IsFocusable() const
756{
757    return focusable_;
758}
759
760void UIView::Focus()
761{
762    if (focusable_ && onFocusListener_ != nullptr) {
763        onFocusListener_->OnFocus(*this);
764    }
765}
766
767void UIView::Blur()
768{
769    if (onFocusListener_ != nullptr) {
770        onFocusListener_->OnBlur(*this);
771    }
772}
773
774void UIView::SetOnFocusListener(OnFocusListener* onFocusListener)
775{
776    onFocusListener_ = onFocusListener;
777}
778
779UIView::OnFocusListener* UIView::GetOnFocusListener() const
780{
781    return onFocusListener_;
782}
783
784#endif
785
786Rect UIView::GetRect() const
787{
788    if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
789        Rect r = transMap_->GetBoxRect();
790        Rect origRect = GetOrigRect();
791        r.SetX(r.GetX() + origRect.GetX() - transMap_->GetTransMapRect().GetX());
792        r.SetY(r.GetY() + origRect.GetY() - transMap_->GetTransMapRect().GetY());
793        return r;
794    }
795    return GetOrigRect();
796}
797
798Rect UIView::GetContentRect()
799{
800    if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
801        Rect r = transMap_->GetBoxRect();
802        Rect origRect = GetOrigRect();
803        r.SetX(r.GetX() + origRect.GetX() - transMap_->GetTransMapRect().GetX());
804        r.SetY(r.GetY() + origRect.GetY() - transMap_->GetTransMapRect().GetY());
805        return r;
806    }
807
808    Rect contentRect = GetRect();
809    contentRect.SetX(contentRect.GetX() + style_->paddingLeft_ + style_->borderWidth_);
810    contentRect.SetY(contentRect.GetY() + style_->paddingTop_ + style_->borderWidth_);
811    contentRect.SetWidth(GetWidth());
812    contentRect.SetHeight(GetHeight());
813    return contentRect;
814}
815
816Rect UIView::GetOrigContentRect()
817{
818    Rect contentRect = GetOrigRect();
819    contentRect.SetX(contentRect.GetX() + style_->paddingLeft_ + style_->borderWidth_);
820    contentRect.SetY(contentRect.GetY() + style_->paddingTop_ + style_->borderWidth_);
821    contentRect.SetWidth(GetWidth());
822    contentRect.SetHeight(GetHeight());
823    return contentRect;
824}
825
826Rect UIView::GetOrigRect() const
827{
828    int16_t x = rect_.GetX();
829    int16_t y = rect_.GetY();
830    UIView* par = parent_;
831    while (par != nullptr) {
832        x += par->GetRelativeRect().GetX() + par->GetStyle(STYLE_PADDING_LEFT) + par->GetStyle(STYLE_BORDER_WIDTH);
833        y += par->GetRelativeRect().GetY() + par->GetStyle(STYLE_PADDING_TOP) + par->GetStyle(STYLE_BORDER_WIDTH);
834        par = par->parent_;
835    }
836    return Rect(x, y, x + rect_.GetWidth() - 1, y + rect_.GetHeight() - 1);
837}
838
839Rect UIView::GetMaskedRect() const
840{
841    Rect mask;
842    if (visibleRect_ != nullptr) {
843        mask.Intersect(GetRect(), GetVisibleRect());
844    } else {
845        mask = GetRect();
846    }
847    return mask;
848}
849
850Rect UIView::GetVisibleRect() const
851{
852    if (visibleRect_ == nullptr) {
853        return GetRect();
854    }
855    Rect absoluteRect;
856    int16_t x = visibleRect_->GetX();
857    int16_t y = visibleRect_->GetY();
858    UIView* par = parent_;
859    while (par != nullptr) {
860        x += par->GetX();
861        y += par->GetY();
862        par = par->parent_;
863    }
864    absoluteRect.SetX(x);
865    absoluteRect.SetY(y);
866    absoluteRect.SetWidth(visibleRect_->GetWidth());
867    absoluteRect.SetHeight(visibleRect_->GetHeight());
868    return absoluteRect;
869}
870
871void UIView::SetTransformMap(const TransformMap& transMap)
872{
873    if ((transMap_ != nullptr) && (*transMap_ == transMap)) {
874        return;
875    }
876
877    if (transMap_ == nullptr) {
878        transMap_ = new TransformMap();
879    }
880    Rect preRect = GetRect();
881    *transMap_ = transMap;
882    transMap_->SetTransMapRect(GetOrigRect());
883
884    Rect joinRect;
885    joinRect.Join(preRect, transMap_->GetBoxRect());
886    InvalidateRect(joinRect);
887}
888
889void UIView::SetWidth(int16_t width)
890{
891    if (GetWidth() != width) {
892        int16_t newWidth = width + style_->paddingLeft_ + style_->paddingRight_ +
893                           (style_->borderWidth_ * 2); /* 2: left and right border */
894        rect_.SetWidth(newWidth);
895    }
896}
897
898void UIView::SetWidthPercent(float widthPercent)
899{
900    if (IsInvalid(widthPercent)) {
901        return;
902    }
903    if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1)) {
904        int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
905        SetWidth(newWidth);
906    }
907}
908
909int16_t UIView::GetWidth()
910{
911    return rect_.GetWidth() - (style_->paddingLeft_ + style_->paddingRight_) -
912           (style_->borderWidth_ * 2); /* 2: left and right border */
913}
914
915void UIView::SetHeight(int16_t height)
916{
917    if (GetHeight() != height) {
918        int16_t newHeight = height + style_->paddingTop_ + style_->paddingBottom_ +
919                            (style_->borderWidth_ * 2); /* 2: top and bottom border */
920        rect_.SetHeight(newHeight);
921    }
922}
923
924void UIView::SetHeightPercent(float heightPercent)
925{
926    if (IsInvalid(heightPercent)) {
927        return;
928    }
929    if ((GetParent() != nullptr) && (GetParent()->GetHeight() > 1)) {
930        int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
931        SetHeight(newHeight);
932    }
933}
934
935int16_t UIView::GetHeight()
936{
937    return rect_.GetHeight() - (style_->paddingTop_ + style_->paddingBottom_) -
938           (style_->borderWidth_ * 2); /* 2: top and bottom border */
939}
940
941void UIView::Resize(int16_t width, int16_t height)
942{
943    SetWidth(width);
944    SetHeight(height);
945}
946
947void UIView::ResizePercent(float widthPercent, float heightPercent)
948{
949    if (IsInvalid(widthPercent) || IsInvalid(heightPercent)) {
950        return;
951    }
952    if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
953        int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
954        int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
955        Resize(newWidth, newHeight);
956    }
957}
958
959void UIView::SetX(int16_t x)
960{
961    if (GetX() != x) {
962        rect_.SetX(x + GetStyle(STYLE_MARGIN_LEFT));
963    }
964}
965
966void UIView::SetXPercent(float xPercent)
967{
968    if (IsInvalid(xPercent)) {
969        return;
970    }
971    if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1)) {
972        int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
973        SetX(newX);
974    }
975}
976
977int16_t UIView::GetX() const
978{
979    return rect_.GetX() - GetStyle(STYLE_MARGIN_LEFT);
980}
981
982void UIView::SetY(int16_t y)
983{
984    if (GetY() != y) {
985        rect_.SetY(y + GetStyle(STYLE_MARGIN_TOP));
986    }
987}
988
989void UIView::SetYPercent(float yPercent)
990{
991    if (IsInvalid(yPercent)) {
992        return;
993    }
994    if ((GetParent() != nullptr) && (GetParent()->GetHeight() > 1)) {
995        int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
996        SetY(newY);
997    }
998}
999
1000int16_t UIView::GetY() const
1001{
1002    return rect_.GetY() - GetStyle(STYLE_MARGIN_TOP);
1003}
1004
1005void UIView::SetPosition(int16_t x, int16_t y)
1006{
1007    SetX(x);
1008    SetY(y);
1009}
1010
1011void UIView::SetPositionPercent(float xPercent, float yPercent)
1012{
1013    if (IsInvalid(xPercent) || IsInvalid(yPercent)) {
1014        return;
1015    }
1016    if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
1017        int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
1018        int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
1019        SetPosition(newX, newY);
1020    }
1021}
1022
1023void UIView::SetPosition(int16_t x, int16_t y, int16_t width, int16_t height)
1024{
1025    SetPosition(x, y);
1026    SetWidth(width);
1027    SetHeight(height);
1028}
1029
1030void UIView::SetPositionPercent(float xPercent, float yPercent, float widthPercent, float heightPercent)
1031{
1032    if (IsInvalid(xPercent) || IsInvalid(yPercent) || IsInvalid(widthPercent) || IsInvalid(heightPercent)) {
1033        return;
1034    }
1035    if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
1036        int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
1037        int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
1038        int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
1039        int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
1040        SetPosition(newX, newY, newWidth, newHeight);
1041    }
1042}
1043
1044bool UIView::IsViewGroup() const
1045{
1046    return isViewGroup_;
1047}
1048
1049void UIView::SetIntercept(bool isIntercept)
1050{
1051    isIntercept_ = isIntercept;
1052}
1053
1054bool UIView::IsIntercept()
1055{
1056    return isIntercept_;
1057}
1058
1059bool UIView::IsInvalid(float percent)
1060{
1061    if ((percent < 1) && (percent > 0)) {
1062        return false;
1063    }
1064    return true;
1065}
1066
1067TransformMap& UIView::GetTransformMap()
1068{
1069    if (transMap_ == nullptr) {
1070        transMap_ = new TransformMap();
1071    }
1072    return *transMap_;
1073}
1074
1075UIView* UIView::GetChildById(const char* id) const
1076{
1077    return nullptr;
1078}
1079
1080void UIView::SetViewId(const char* id)
1081{
1082    id_ = id;
1083}
1084
1085const char* UIView::GetViewId() const
1086{
1087    return id_;
1088}
1089
1090void UIView::SetViewIndex(int16_t index)
1091{
1092    index_ = index;
1093}
1094
1095int16_t UIView::GetViewIndex() const
1096{
1097    return index_;
1098}
1099
1100UIViewType UIView::GetViewType() const
1101{
1102    return UI_NUMBER_MAX;
1103}
1104
1105void UIView::LayoutCenterOfParent(int16_t xOffset, int16_t yOffset)
1106{
1107    if (parent_ == nullptr) {
1108        return;
1109    }
1110
1111    int16_t topMargin = style_->marginTop_;
1112    int16_t leftMargin = style_->marginLeft_;
1113    int16_t rightMargin = style_->marginRight_;
1114    int16_t bottomMargin = style_->marginBottom_;
1115    // 2: half
1116    int16_t posX = parent_->GetWidth() / 2 - (rect_.GetWidth() - leftMargin + rightMargin) / 2 + xOffset;
1117    // 2: half
1118    int16_t posY = parent_->GetHeight() / 2 - (rect_.GetHeight() - topMargin + bottomMargin) / 2 + yOffset;
1119    SetPosition(posX, posY);
1120}
1121
1122void UIView::LayoutLeftOfParent(int16_t offset)
1123{
1124    if (parent_ == nullptr) {
1125        return;
1126    }
1127
1128    int16_t leftMargin = style_->marginLeft_;
1129    SetPosition(leftMargin + offset, GetY());
1130}
1131
1132void UIView::LayoutRightOfParent(int16_t offset)
1133{
1134    if (parent_ == nullptr) {
1135        return;
1136    }
1137
1138    int16_t rightMargin = style_->marginRight_;
1139    SetPosition(parent_->GetWidth() - offset - rect_.GetWidth() - rightMargin, GetY());
1140}
1141
1142void UIView::LayoutTopOfParent(int16_t offset)
1143{
1144    if (parent_ == nullptr) {
1145        return;
1146    }
1147
1148    int16_t topMargin = style_->marginTop_;
1149    SetPosition(GetX(), topMargin + offset);
1150}
1151
1152void UIView::LayoutBottomOfParent(int16_t offset)
1153{
1154    if (parent_ == nullptr) {
1155        return;
1156    }
1157
1158    int16_t bottomMargin = style_->marginBottom_;
1159    SetPosition(GetX(), parent_->GetHeight() - offset - rect_.GetHeight() - bottomMargin);
1160}
1161
1162void UIView::AlignLeftToSibling(const char* id, int16_t offset)
1163{
1164    if (parent_ == nullptr) {
1165        return;
1166    }
1167    UIView* sib = parent_->GetChildById(id);
1168    if (sib != nullptr) {
1169        int16_t margin = sib->style_->marginLeft_ - style_->marginLeft_;
1170        SetPosition(sib->GetX() - margin + offset, GetY());
1171    }
1172}
1173
1174void UIView::AlignRightToSibling(const char* id, int16_t offset)
1175{
1176    if (parent_ == nullptr) {
1177        return;
1178    }
1179    UIView* sib = parent_->GetChildById(id);
1180    if (sib != nullptr) {
1181        int16_t margin = sib->style_->marginRight_ - style_->marginRight_;
1182        SetPosition(sib->GetX() + sib->rect_.GetWidth() - rect_.GetWidth() - offset + margin, GetY());
1183    }
1184}
1185
1186void UIView::AlignTopToSibling(const char* id, int16_t offset)
1187{
1188    if (parent_ == nullptr) {
1189        return;
1190    }
1191    UIView* sib = parent_->GetChildById(id);
1192    if (sib != nullptr) {
1193        int16_t margin = sib->style_->marginTop_ - style_->marginTop_;
1194        SetPosition(GetX(), sib->GetY() + offset - margin);
1195    }
1196}
1197
1198void UIView::AlignBottomToSibling(const char* id, int16_t offset)
1199{
1200    if (parent_ == nullptr) {
1201        return;
1202    }
1203    UIView* sib = parent_->GetChildById(id);
1204    if (sib != nullptr) {
1205        int16_t margin = sib->style_->marginBottom_ - style_->marginBottom_;
1206        SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() - rect_.GetHeight() - offset + margin);
1207    }
1208}
1209
1210void UIView::AlignHorCenterToSibling(const char* id, int16_t offset)
1211{
1212    if (parent_ == nullptr) {
1213        return;
1214    }
1215    UIView* sib = parent_->GetChildById(id);
1216    if (sib != nullptr) {
1217        int16_t margin =
1218            (sib->style_->marginRight_ - sib->style_->marginLeft_ - style_->marginRight_ + style_->marginLeft_) /
1219            2; // 2 : half
1220        SetPosition(sib->GetX() + sib->rect_.GetWidth() / 2 - rect_.GetWidth() / 2 + margin + offset, GetY());
1221    }
1222}
1223void UIView::AlignVerCenterToSibling(const char* id, int16_t offset)
1224{
1225    if (parent_ == nullptr) {
1226        return;
1227    }
1228    UIView* sib = parent_->GetChildById(id);
1229    if (sib != nullptr) {
1230        int16_t margin =
1231            (sib->style_->marginBottom_ - sib->style_->marginTop_ - style_->marginBottom_ + style_->marginTop_) /
1232            2; // 2 : half
1233        SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() / 2 - rect_.GetHeight() / 2 + margin + offset);
1234    }
1235}
1236
1237void UIView::LayoutLeftToSibling(const char* id, int16_t offset)
1238{
1239    if (parent_ == nullptr) {
1240        return;
1241    }
1242    UIView* sib = parent_->GetChildById(id);
1243    if (sib != nullptr) {
1244        int16_t margin = sib->style_->marginLeft_ + style_->marginRight_;
1245        SetPosition(sib->GetX() - offset - rect_.GetWidth() - margin, GetY());
1246    }
1247}
1248
1249void UIView::LayoutRightToSibling(const char* id, int16_t offset)
1250{
1251    if (parent_ == nullptr) {
1252        return;
1253    }
1254    UIView* sib = parent_->GetChildById(id);
1255    if (sib != nullptr) {
1256        int16_t margin = sib->style_->marginRight_ + style_->marginLeft_;
1257        SetPosition(sib->GetX() + sib->rect_.GetWidth() + offset + margin, GetY());
1258    }
1259}
1260
1261void UIView::LayoutTopToSibling(const char* id, int16_t offset)
1262{
1263    if (parent_ == nullptr) {
1264        return;
1265    }
1266    UIView* sib = parent_->GetChildById(id);
1267    if (sib != nullptr) {
1268        int16_t margin = sib->style_->marginTop_ + style_->marginBottom_;
1269        SetPosition(GetX(), sib->GetY() - offset - rect_.GetHeight() - margin);
1270    }
1271}
1272
1273void UIView::LayoutBottomToSibling(const char* id, int16_t offset)
1274{
1275    if (parent_ == nullptr) {
1276        return;
1277    }
1278    UIView* sib = parent_->GetChildById(id);
1279    if (sib != nullptr) {
1280        int16_t margin = sib->style_->marginBottom_ + style_->marginTop_;
1281        SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() + offset + margin);
1282    }
1283}
1284
1285uint8_t UIView::GetMixOpaScale() const
1286{
1287    uint8_t opaMix = opaScale_;
1288    UIView* parent = parent_;
1289    while (parent != nullptr) {
1290        uint8_t opaParent = parent->GetOpaScale();
1291        // 8: Shift right 8 bits
1292        opaMix = (opaParent == OPA_OPAQUE) ? opaMix : ((static_cast<uint16_t>(opaParent) * opaMix) >> 8);
1293        parent = parent->GetParent();
1294    }
1295    return opaMix;
1296}
1297
1298bool UIView::GetBitmap(ImageInfo& imageInfo, ColorMode colorMode)
1299{
1300    UIView* tempRenderSibling = nextRenderSibling_;
1301    nextRenderSibling_ = nullptr;
1302    UIView* tempParent = parent_;
1303    parent_ = nullptr;
1304    int16_t tempX = rect_.GetX();
1305    int16_t tempY = rect_.GetY();
1306    rect_.SetPosition(0, 0);
1307
1308    Rect mask = GetRect();
1309    BufferInfo bufInfo{mask, 0, nullptr, nullptr, 0, 0, colorMode, 0};
1310    bufInfo.width = mask.GetWidth();
1311    bufInfo.height = mask.GetHeight();
1312    bufInfo.stride = bufInfo.width * DrawUtils::GetByteSizeByColorMode(bufInfo.mode);
1313    BaseGfxEngine::GetInstance()->AdjustLineStride(bufInfo);
1314    imageInfo.header.colorMode = bufInfo.mode;
1315    imageInfo.dataSize = bufInfo.stride * bufInfo.height;
1316    imageInfo.header.width = bufInfo.width;
1317    imageInfo.header.height = bufInfo.height;
1318    imageInfo.header.reserved = 0;
1319
1320    bufInfo.virAddr = ImageCacheMalloc(imageInfo);
1321    if (bufInfo.virAddr == nullptr) {
1322        GRAPHIC_LOGE("GetBitmap buffer alloc failed.");
1323        nextRenderSibling_ = tempRenderSibling;
1324        parent_ = tempParent;
1325        rect_.SetPosition(tempX, tempY);
1326        return false;
1327    }
1328    imageInfo.data = reinterpret_cast<uint8_t*>(bufInfo.virAddr);
1329    if (memset_s(bufInfo.virAddr, imageInfo.dataSize, 0, imageInfo.dataSize) != EOK) {
1330        GRAPHIC_LOGE("GetBitmap buffer memset failed.");
1331        ImageCacheFree(imageInfo);
1332        imageInfo.data = nullptr;
1333        return false;
1334    }
1335    bufInfo.phyAddr = bufInfo.virAddr;
1336    RootView* rootView = RootView::GetInstance();
1337    rootView->SaveDrawContext();
1338    rootView->UpdateBufferInfo(&bufInfo);
1339    rootView->MeasureView(this);
1340    rootView->DrawTop(this, mask);
1341    rootView->RestoreDrawContext();
1342
1343    nextRenderSibling_ = tempRenderSibling;
1344    parent_ = tempParent;
1345    rect_.SetPosition(tempX, tempY);
1346    return true;
1347}
1348
1349bool UIView::IsOnViewTree()
1350{
1351    UIView* par = this;
1352    while (par->GetParent() != nullptr) {
1353        par = par->GetParent();
1354    }
1355    if (par->GetViewType() != UI_ROOT_VIEW) {
1356        return false;
1357    }
1358    return true;
1359}
1360
1361int16_t UIView::GetWidthWithMargin()
1362{
1363    return GetRelativeRect().GetWidth() + GetStyle(STYLE_MARGIN_LEFT) + GetStyle(STYLE_MARGIN_RIGHT);
1364}
1365
1366int16_t UIView::GetHeightWithMargin()
1367{
1368    return GetRelativeRect().GetHeight() + GetStyle(STYLE_MARGIN_TOP) + GetStyle(STYLE_MARGIN_BOTTOM);
1369}
1370
1371Rect UIView::GetRelativeRect() const
1372{
1373    return rect_;
1374}
1375
1376void UIView::ResizeVisibleArea(int16_t x, int16_t y, int16_t width, int16_t height)
1377{
1378    if (visibleRect_ == nullptr) {
1379        visibleRect_ = new Rect();
1380        if (visibleRect_ == nullptr) {
1381            GRAPHIC_LOGE("new Rect fail");
1382            return;
1383        }
1384    }
1385    visibleRect_->SetWidth(width);
1386    visibleRect_->SetHeight(height);
1387    visibleRect_->SetPosition(x, y);
1388}
1389
1390void UIView::SetZIndex(int16_t zIndex)
1391{
1392    if (zIndex_ == zIndex) {
1393        return;
1394    }
1395
1396    zIndex_ = zIndex;
1397    if (parent_ != nullptr) {
1398        reinterpret_cast<UIViewGroup*>(parent_)->UpdateRenderView(this);
1399    }
1400}
1401
1402int16_t UIView::GetZIndex()
1403{
1404    return zIndex_;
1405}
1406} // namespace OHOS
1407