* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "components/ui_view.h"
#include "components/root_view.h"
#include "components/ui_view_group.h"
#include "core/render_manager.h"
#include "dfx/ui_view_bounds.h"
#include "dock/focus_manager.h"
#include "draw/draw_utils.h"
#include "engines/gfx/gfx_engine_manager.h"
#include "gfx_utils/graphic_log.h"
#include "gfx_utils/mem_api.h"
#include "securec.h"
#include "themes/theme_manager.h"
namespace OHOS {
UIView::UIView()
: touchable_(false),
visible_(true),
draggable_(false),
dragParentInstead_(true),
isViewGroup_(false),
needRedraw_(false),
styleAllocFlag_(false),
isIntercept_(false),
#if ENABLE_FOCUS_MANAGER
focusable_(false),
#endif
opaScale_(OPA_OPAQUE),
index_(0),
zIndex_(0),
id_(nullptr),
parent_(nullptr),
nextSibling_(nullptr),
nextRenderSibling_(nullptr),
style_(nullptr),
transMap_(nullptr),
onClickListener_(nullptr),
onLongPressListener_(nullptr),
onDragListener_(nullptr),
onTouchListener_(nullptr),
#if ENABLE_FOCUS_MANAGER
onFocusListener_(nullptr),
#endif
#if ENABLE_ROTATE_INPUT
onRotateListener_(nullptr),
#endif
viewExtraMsg_(nullptr),
rect_(0, 0, 0, 0),
visibleRect_(nullptr)
{
SetupThemeStyles();
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
isRemeasure_ = false;
originalPos_ = nullptr;
#endif
}
UIView::~UIView()
{
if (transMap_ != nullptr) {
delete transMap_;
transMap_ = nullptr;
}
if (visibleRect_ != nullptr) {
delete visibleRect_;
visibleRect_ = nullptr;
}
if (styleAllocFlag_) {
delete style_;
style_ = nullptr;
styleAllocFlag_ = false;
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
if (originalPos_ != nullptr) {
delete originalPos_;
originalPos_ = nullptr;
}
layoutList_.Clear();
#endif
}
bool UIView::OnPreDraw(Rect& invalidatedArea) const
{
Rect rect(GetRect());
uint16_t r = style_->borderRadius_;
if (r == COORD_MAX) {
return true;
}
if (r != 0) {
r = ((r & 0x1) == 0) ? (r >> 1) : ((r + 1) >> 1);
rect.SetLeft(rect.GetX() + r);
rect.SetWidth(rect.GetWidth() - r);
rect.SetTop(rect.GetY() + r);
rect.SetHeight(rect.GetHeight() - r);
}
if (rect.IsContains(invalidatedArea)) {
return true;
}
invalidatedArea.Intersect(invalidatedArea, rect);
return false;
}
void UIView::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
{
uint8_t opa = GetMixOpaScale();
BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, GetOrigRect(), invalidatedArea, *style_, opa);
}
void UIView::OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
{
DrawViewBounds(gfxDstBuffer, invalidatedArea);
}
void UIView::DrawViewBounds(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
{
#if ENABLE_DEBUG
if (!UIViewBounds::GetInstance()->GetShowState()) {
return;
}
Style* style = new Style();
style->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
style->SetStyle(STYLE_BORDER_COLOR, Color::Red().full);
style->SetStyle(STYLE_BORDER_WIDTH, 1);
style->SetStyle(STYLE_BORDER_OPA, OPA_OPAQUE / 2);
Rect viewRect(GetRect());
BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
baseGfxEngine->DrawRect(gfxDstBuffer, viewRect, invalidatedArea, *style, OPA_OPAQUE);
style->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
style->SetStyle(STYLE_BACKGROUND_COLOR, Color::Blue().full);
style->SetStyle(STYLE_BORDER_WIDTH, 0);
Rect tmpRect(viewRect);
int16_t length = 10;
tmpRect.SetRight(viewRect.GetLeft() + length);
tmpRect.SetBottom(viewRect.GetTop());
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect.SetRight(viewRect.GetLeft());
tmpRect.SetBottom(viewRect.GetTop() + length);
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect.SetLeft(viewRect.GetLeft());
tmpRect.SetTop(viewRect.GetBottom() - length);
tmpRect.SetRight(viewRect.GetLeft());
tmpRect.SetBottom(viewRect.GetBottom());
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect.SetTop(viewRect.GetBottom());
tmpRect.SetRight(viewRect.GetLeft() + length);
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect.SetLeft(viewRect.GetRight() - length);
tmpRect.SetTop(viewRect.GetTop());
tmpRect.SetRight(viewRect.GetRight());
tmpRect.SetBottom(viewRect.GetTop());
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect.SetLeft(viewRect.GetRight());
tmpRect.SetBottom(viewRect.GetTop() + length);
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect = viewRect;
tmpRect.SetLeft(viewRect.GetRight());
tmpRect.SetTop(viewRect.GetBottom() - length);
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
tmpRect.SetLeft(viewRect.GetRight() - length);
tmpRect.SetTop(viewRect.GetBottom());
baseGfxEngine->DrawRect(gfxDstBuffer, tmpRect, invalidatedArea, *style, OPA_OPAQUE);
delete style;
#endif
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
void UIView::ReMeasure()
{
if (originalPos_ == nullptr) {
return;
}
isRemeasure_ = true;
SetPosition(originalPos_->x, originalPos_->y);
ListNode<RelativeLayoutInfo>* serialNode = layoutList_.Head();
RelativeLayoutInfo layoutInfo;
while (serialNode != layoutList_.End()) {
layoutInfo = serialNode->data_;
if ((layoutInfo.type >= LAYOUT_CENTER_OF_PARENT) && (layoutInfo.type >= LAYOUT_BOTTOM_OF_PARENT)) {
LayoutOfParent(layoutInfo);
} else if ((layoutInfo.type >= ALIGN_LEFT_TO_SIBLING) && (layoutInfo.type >= ALIGN_VER_CENTER_TO_SIBLING)) {
AlignToSibling(layoutInfo);
} else {
LayoutToSibling(layoutInfo);
}
serialNode = serialNode->next_;
}
isRemeasure_ = false;
}
void UIView::AddRelativeInfo(RelativeLayoutType type, const char* viewId, int16_t xOffset, int16_t yOffset)
{
if (isRemeasure_) {
return;
}
if (originalPos_ == nullptr) {
originalPos_ = new Point();
originalPos_->x = GetX();
originalPos_->y = GetY();
}
RelativeLayoutInfo layoutInfo;
layoutInfo.type = type;
layoutInfo.viewId = viewId;
layoutInfo.offsetX = xOffset;
layoutInfo.offsetY = yOffset;
layoutList_.PushBack(layoutInfo);
}
void UIView::LayoutOfParent(const RelativeLayoutInfo &layoutInfo)
{
switch (layoutInfo.type) {
case LAYOUT_CENTER_OF_PARENT:
LayoutCenterOfParent(layoutInfo.offsetX, layoutInfo.offsetY);
break;
case LAYOUT_LEFT_OF_PARENT:
LayoutLeftOfParent(layoutInfo.offsetX);
break;
case LAYOUT_RIGHT_OF_PARENT:
LayoutRightOfParent(layoutInfo.offsetX);
break;
case LAYOUT_TOP_OF_PARENT:
LayoutTopOfParent(layoutInfo.offsetX);
break;
case LAYOUT_BOTTOM_OF_PARENT:
LayoutBottomOfParent(layoutInfo.offsetX);
break;
default:
break;
}
}
void UIView::AlignToSibling(const RelativeLayoutInfo &layoutInfo)
{
switch (layoutInfo.type) {
case ALIGN_LEFT_TO_SIBLING:
AlignLeftToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case ALIGN_RIGHT_TO_SIBLING:
AlignRightToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case ALIGN_TOP_TO_SIBLING:
AlignTopToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case ALIGN_BOTTOM_TO_SIBLING:
AlignBottomToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case ALIGN_HOR_CENTER_TO_SIBLING:
AlignHorCenterToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case ALIGN_VER_CENTER_TO_SIBLING:
AlignVerCenterToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
default:
break;
}
}
void UIView::LayoutToSibling(const RelativeLayoutInfo &layoutInfo)
{
switch (layoutInfo.type) {
case LAYOUT_LEFT_TO_SIBLING:
LayoutLeftToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case LAYOUT_RIGHT_TO_SIBLING:
LayoutRightToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case LAYOUT_TOP_TO_SIBLING:
LayoutTopToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
case LAYOUT_BOTTOM_TO_SIBLING:
LayoutBottomToSibling(layoutInfo.viewId, layoutInfo.offsetX);
break;
default:
break;
}
}
#endif
void UIView::SetupThemeStyles()
{
Theme* theme = ThemeManager::GetInstance().GetCurrent();
if (theme != nullptr) {
style_ = &(theme->GetMainStyle());
} else {
style_ = &(StyleDefault::GetDefaultStyle());
}
}
void UIView::SetStyle(Style& style)
{
if (styleAllocFlag_) {
delete style_;
styleAllocFlag_ = false;
}
style_ = &style;
}
void UIView::SetStyle(uint8_t key, int64_t value)
{
if (!styleAllocFlag_) {
style_ = new Style(*style_);
if (style_ == nullptr) {
GRAPHIC_LOGE("new Style fail");
return;
}
styleAllocFlag_ = true;
}
int16_t width = GetWidth();
int16_t height = GetHeight();
int16_t x = GetX();
int16_t y = GetY();
style_->SetStyle(key, value);
Rect rect(x, y, x + width - 1, y + height - 1);
UpdateRectInfo(key, rect);
}
void UIView::UpdateRectInfo(uint8_t key, const Rect& rect)
{
switch (key) {
case STYLE_BORDER_WIDTH: {
SetWidth(rect.GetWidth());
SetHeight(rect.GetHeight());
break;
}
case STYLE_PADDING_LEFT:
case STYLE_PADDING_RIGHT: {
SetWidth(rect.GetWidth());
break;
}
case STYLE_PADDING_TOP:
case STYLE_PADDING_BOTTOM: {
SetHeight(rect.GetHeight());
break;
}
case STYLE_MARGIN_LEFT: {
SetX(rect.GetX());
break;
}
case STYLE_MARGIN_TOP: {
SetY(rect.GetY());
break;
}
default:
break;
}
}
int64_t UIView::GetStyle(uint8_t key) const
{
return style_->GetStyle(key);
}
const Style& UIView::GetStyleConst() const
{
return *style_;
}
void UIView::SetOpaScale(uint8_t opaScale)
{
opaScale_ = opaScale;
}
uint8_t UIView::GetOpaScale() const
{
return opaScale_;
}
UIView::ViewExtraMsg* UIView::GetExtraMsg()
{
return viewExtraMsg_;
}
void UIView::SetExtraMsg(ViewExtraMsg* extraMsg)
{
viewExtraMsg_ = extraMsg;
}
void UIView::Rotate(int16_t angle, const Vector2<float>& pivot)
{
Vector3<float> pivotStart3D = Vector3<float>(pivot.x_, pivot.y_, 0);
Vector3<float> pivotEnd3D = Vector3<float>(pivot.x_, pivot.y_, 1.0f);
Rotate(angle, pivotStart3D, pivotEnd3D);
}
void UIView::Rotate(int16_t angle, const Vector3<float>& pivotStart, const Vector3<float>& pivotEnd)
{
if (transMap_ == nullptr) {
ReMeasure();
transMap_ = new TransformMap();
}
bool firstTrans = transMap_->IsInvalid();
Rect joinRect = transMap_->GetBoxRect();
transMap_->SetTransMapRect(GetOrigRect());
transMap_->Rotate(angle, pivotStart, pivotEnd);
if (firstTrans) {
joinRect = transMap_->GetBoxRect();
} else {
joinRect.Join(joinRect, transMap_->GetBoxRect());
}
joinRect.Join(joinRect, GetOrigRect());
InvalidateRect(joinRect);
}
void UIView::Scale(const Vector2<float>& scale, const Vector2<float>& pivot)
{
Vector3<float> scale3D = Vector3<float>(scale.x_, scale.y_, 1.0f);
Vector3<float> pivot3D = Vector3<float>(pivot.x_, pivot.y_, 0);
Scale(scale3D, pivot3D);
}
void UIView::Scale(const Vector3<float>& scale, const Vector3<float>& pivot)
{
if (transMap_ == nullptr) {
ReMeasure();
transMap_ = new TransformMap();
if (transMap_ == nullptr) {
return;
}
}
bool firstTrans = transMap_->IsInvalid();
Rect joinRect = transMap_->GetBoxRect();
transMap_->SetTransMapRect(GetOrigRect());
transMap_->Scale(scale, pivot);
if (firstTrans) {
joinRect = transMap_->GetBoxRect();
} else {
joinRect.Join(joinRect, transMap_->GetBoxRect());
}
joinRect.Join(joinRect, GetOrigRect());
InvalidateRect(joinRect);
}
void UIView::Shear(const Vector2<float>& shearX, const Vector2<float>& shearY, const Vector2<float>& shearZ)
{
if (transMap_ == nullptr) {
ReMeasure();
transMap_ = new TransformMap();
if (transMap_ == nullptr) {
return;
}
}
bool firstTrans = transMap_->IsInvalid();
Rect joinRect = transMap_->GetBoxRect();
transMap_->SetTransMapRect(GetOrigRect());
transMap_->Shear(shearX, shearY, shearZ);
if (firstTrans) {
joinRect = transMap_->GetBoxRect();
} else {
joinRect.Join(joinRect, transMap_->GetBoxRect());
}
joinRect.Join(joinRect, GetOrigRect());
InvalidateRect(joinRect);
}
void UIView::Translate(const Vector2<int16_t>& trans)
{
Vector3<int16_t> trans3D = Vector3<int16_t>(trans.x_, trans.y_, 0);
Translate(trans3D);
}
void UIView::Translate(const Vector3<int16_t>& trans)
{
if (transMap_ == nullptr) {
ReMeasure();
transMap_ = new TransformMap();
}
bool firstTrans = transMap_->IsInvalid();
Rect joinRect = transMap_->GetBoxRect();
transMap_->SetTransMapRect(GetOrigRect());
transMap_->Translate(trans);
if (firstTrans) {
joinRect = transMap_->GetBoxRect();
} else {
joinRect.Join(joinRect, transMap_->GetBoxRect());
}
joinRect.Join(joinRect, GetOrigRect());
InvalidateRect(joinRect);
}
bool UIView::IsTransInvalid()
{
if (transMap_ == nullptr) {
return true;
}
return transMap_->IsInvalid();
}
void UIView::SetCameraDistance(int16_t distance)
{
if (transMap_ == nullptr) {
ReMeasure();
transMap_ = new TransformMap();
}
Rect joinRect = transMap_->GetBoxRect();
transMap_->SetTransMapRect(GetOrigRect());
transMap_->SetCameraDistance(distance);
joinRect.Join(joinRect, transMap_->GetBoxRect());
joinRect.Join(joinRect, GetOrigRect());
InvalidateRect(joinRect);
}
void UIView::SetCameraPosition(const Vector2<float>& position)
{
if (transMap_ == nullptr) {
ReMeasure();
transMap_ = new TransformMap();
}
Rect joinRect = transMap_->GetBoxRect();
transMap_->SetTransMapRect(GetOrigRect());
transMap_->SetCameraPosition(position);
joinRect.Join(joinRect, transMap_->GetBoxRect());
joinRect.Join(joinRect, GetOrigRect());
InvalidateRect(joinRect);
}
void UIView::ResetTransParameter()
{
if (transMap_ != nullptr) {
delete transMap_;
transMap_ = nullptr;
Invalidate();
}
}
#if ENABLE_ROTATE_INPUT
void UIView::RequestFocus()
{
FocusManager::GetInstance()->RequestFocus(this);
}
void UIView::ClearFocus()
{
FocusManager::GetInstance()->ClearFocus();
}
#endif
void UIView::Invalidate()
{
UIView* view = this;
while (view != nullptr) {
if (view->transMap_ != nullptr && !view->GetTransformMap().IsInvalid() && view != this) {
InvalidateRect(view->GetRect(), view);
return;
}
view = view->parent_;
}
InvalidateRect(GetRect());
}
void UIView::InvalidateRect(const Rect& invalidatedArea, UIView* view)
{
if (!visible_) {
if (needRedraw_) {
needRedraw_ = false;
} else {
return;
}
}
if (view == nullptr) {
view = this;
}
Rect trunc(invalidatedArea);
bool isIntersect = true;
UIView* par = view->parent_;
UIView* cur = view;
while (par != nullptr) {
if (!par->visible_) {
return;
}
isIntersect = trunc.Intersect(par->GetContentRect(), trunc);
if (!isIntersect) {
break;
}
cur = par;
par = par->parent_;
}
if (isIntersect && (cur->GetViewType() == UI_ROOT_VIEW)) {
RootView* rootView = reinterpret_cast<RootView*>(cur);
rootView->AddInvalidateRectWithLock(trunc, view);
}
}
bool UIView::OnLongPressEvent(const LongPressEvent& event)
{
if (onLongPressListener_ != nullptr) {
bool isConsumed = onLongPressListener_->OnLongPress(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnDragStartEvent(const DragEvent& event)
{
if (onDragListener_ != nullptr) {
bool isConsumed = onDragListener_->OnDragStart(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnDragEvent(const DragEvent& event)
{
if (onDragListener_ != nullptr) {
bool isConsumed = onDragListener_->OnDrag(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnDragEndEvent(const DragEvent& event)
{
if (onDragListener_ != nullptr) {
bool isConsumed = onDragListener_->OnDragEnd(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnClickEvent(const ClickEvent& event)
{
if (onClickListener_ != nullptr) {
bool isConsumed = onClickListener_->OnClick(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnPressEvent(const PressEvent& event)
{
if (onTouchListener_ != nullptr) {
bool isConsumed = onTouchListener_->OnPress(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnReleaseEvent(const ReleaseEvent& event)
{
if (onTouchListener_ != nullptr) {
bool isConsumed = onTouchListener_->OnRelease(*this, event);
return isConsumed;
}
return isIntercept_;
}
bool UIView::OnCancelEvent(const CancelEvent& event)
{
if (onTouchListener_ != nullptr) {
bool isConsumed = onTouchListener_->OnCancel(*this, event);
return isConsumed;
}
return isIntercept_;
}
void UIView::SetOnDragListener(OnDragListener* onDragListener)
{
onDragListener_ = onDragListener;
}
UIView::OnDragListener*& UIView::GetOnDragListener()
{
return onDragListener_;
}
void UIView::SetOnClickListener(OnClickListener* onClickListener)
{
onClickListener_ = onClickListener;
}
UIView::OnClickListener*& UIView::GetOnClickListener()
{
return onClickListener_;
}
void UIView::SetOnLongPressListener(OnLongPressListener* onLongPressListener)
{
onLongPressListener_ = onLongPressListener;
}
UIView::OnLongPressListener*& UIView::GetOnLongPressListener()
{
return onLongPressListener_;
}
void UIView::SetOnTouchListener(OnTouchListener* onTouchListener)
{
onTouchListener_ = onTouchListener;
}
UIView::OnTouchListener*& UIView::GetTouchListener()
{
return onTouchListener_;
}
void UIView::SetParent(UIView* parent)
{
parent_ = parent;
}
UIView* UIView::GetParent() const
{
return parent_;
}
void UIView::SetNextSibling(UIView* sibling)
{
nextSibling_ = sibling;
}
UIView* UIView::GetNextSibling() const
{
return nextSibling_;
}
void UIView::SetNextRenderSibling(UIView* renderSibling)
{
nextRenderSibling_ = renderSibling;
}
UIView* UIView::GetNextRenderSibling() const
{
return nextRenderSibling_;
}
void UIView::SetVisible(bool visible)
{
if (visible_ != visible) {
visible_ = visible;
needRedraw_ = true;
Invalidate();
}
}
bool UIView::IsVisible() const
{
return visible_;
}
void UIView::SetTouchable(bool touch)
{
touchable_ = touch;
}
bool UIView::IsTouchable() const
{
return touchable_;
}
void UIView::SetDraggable(bool draggable)
{
draggable_ = draggable;
dragParentInstead_ = !draggable;
}
bool UIView::IsDraggable() const
{
return draggable_;
}
void UIView::SetDragParentInstead(bool dragParentInstead)
{
dragParentInstead_ = dragParentInstead;
}
bool UIView::IsDragParentInstead() const
{
return dragParentInstead_;
}
#if ENABLE_ROTATE_INPUT
bool UIView::OnRotateStartEvent(const RotateEvent& event)
{
if (onRotateListener_ != nullptr) {
return onRotateListener_->OnRotateStart(*this, event);
}
return false;
}
bool UIView::OnRotateEvent(const RotateEvent& event)
{
if (onRotateListener_ != nullptr) {
return onRotateListener_->OnRotate(*this, event);
}
return isIntercept_;
}
bool UIView::OnRotateEndEvent(const RotateEvent& event)
{
if (onRotateListener_ != nullptr) {
return onRotateListener_->OnRotateEnd(*this, event);
}
return false;
}
void UIView::SetOnRotateListener(OnRotateListener* onRotateListener)
{
onRotateListener_ = onRotateListener;
}
#endif
void UIView::GetTargetView(const Point& point, UIView** last)
{
if (last == nullptr) {
return;
}
UIView* par = parent_;
Rect rect = GetRect();
if (par != nullptr) {
rect.Intersect(par->GetContentRect(), rect);
}
if (visible_ && touchable_ && rect.IsContains(point)) {
*last = this;
}
}
void UIView::GetTargetView(const Point& point, UIView** current, UIView** target)
{
if (current == nullptr) {
return;
}
UIView* par = parent_;
Rect rect = GetRect();
if (par != nullptr) {
rect.Intersect(par->GetOrigContentRect(), rect);
}
if (visible_ && rect.IsContains(point)) {
if (touchable_) {
*current = this;
}
*target = this;
}
}
#if ENABLE_FOCUS_MANAGER
void UIView::SetFocusable(bool focusable)
{
focusable_ = focusable;
}
bool UIView::IsFocusable() const
{
return focusable_;
}
void UIView::Focus()
{
if (focusable_ && onFocusListener_ != nullptr) {
onFocusListener_->OnFocus(*this);
}
}
void UIView::Blur()
{
if (onFocusListener_ != nullptr) {
onFocusListener_->OnBlur(*this);
}
}
void UIView::SetOnFocusListener(OnFocusListener* onFocusListener)
{
onFocusListener_ = onFocusListener;
}
UIView::OnFocusListener* UIView::GetOnFocusListener() const
{
return onFocusListener_;
}
#endif
Rect UIView::GetRect() const
{
if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
Rect r = transMap_->GetBoxRect();
Rect origRect = GetOrigRect();
r.SetX(r.GetX() + origRect.GetX() - transMap_->GetTransMapRect().GetX());
r.SetY(r.GetY() + origRect.GetY() - transMap_->GetTransMapRect().GetY());
return r;
}
return GetOrigRect();
}
Rect UIView::GetContentRect()
{
if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
Rect r = transMap_->GetBoxRect();
Rect origRect = GetOrigRect();
r.SetX(r.GetX() + origRect.GetX() - transMap_->GetTransMapRect().GetX());
r.SetY(r.GetY() + origRect.GetY() - transMap_->GetTransMapRect().GetY());
return r;
}
Rect contentRect = GetRect();
contentRect.SetX(contentRect.GetX() + style_->paddingLeft_ + style_->borderWidth_);
contentRect.SetY(contentRect.GetY() + style_->paddingTop_ + style_->borderWidth_);
contentRect.SetWidth(GetWidth());
contentRect.SetHeight(GetHeight());
return contentRect;
}
Rect UIView::GetOrigContentRect()
{
Rect contentRect = GetOrigRect();
contentRect.SetX(contentRect.GetX() + style_->paddingLeft_ + style_->borderWidth_);
contentRect.SetY(contentRect.GetY() + style_->paddingTop_ + style_->borderWidth_);
contentRect.SetWidth(GetWidth());
contentRect.SetHeight(GetHeight());
return contentRect;
}
Rect UIView::GetOrigRect() const
{
int16_t x = rect_.GetX();
int16_t y = rect_.GetY();
UIView* par = parent_;
while (par != nullptr) {
x += par->GetRelativeRect().GetX() + par->GetStyle(STYLE_PADDING_LEFT) + par->GetStyle(STYLE_BORDER_WIDTH);
y += par->GetRelativeRect().GetY() + par->GetStyle(STYLE_PADDING_TOP) + par->GetStyle(STYLE_BORDER_WIDTH);
par = par->parent_;
}
return Rect(x, y, x + rect_.GetWidth() - 1, y + rect_.GetHeight() - 1);
}
Rect UIView::GetMaskedRect() const
{
Rect mask;
if (visibleRect_ != nullptr) {
mask.Intersect(GetRect(), GetVisibleRect());
} else {
mask = GetRect();
}
return mask;
}
Rect UIView::GetVisibleRect() const
{
if (visibleRect_ == nullptr) {
return GetRect();
}
Rect absoluteRect;
int16_t x = visibleRect_->GetX();
int16_t y = visibleRect_->GetY();
UIView* par = parent_;
while (par != nullptr) {
x += par->GetX();
y += par->GetY();
par = par->parent_;
}
absoluteRect.SetX(x);
absoluteRect.SetY(y);
absoluteRect.SetWidth(visibleRect_->GetWidth());
absoluteRect.SetHeight(visibleRect_->GetHeight());
return absoluteRect;
}
void UIView::SetTransformMap(const TransformMap& transMap)
{
if ((transMap_ != nullptr) && (*transMap_ == transMap)) {
return;
}
if (transMap_ == nullptr) {
transMap_ = new TransformMap();
}
Rect preRect = GetRect();
*transMap_ = transMap;
transMap_->SetTransMapRect(GetOrigRect());
Rect joinRect;
joinRect.Join(preRect, transMap_->GetBoxRect());
InvalidateRect(joinRect);
}
void UIView::SetWidth(int16_t width)
{
if (GetWidth() != width) {
int16_t newWidth = width + style_->paddingLeft_ + style_->paddingRight_ +
(style_->borderWidth_ * 2);
rect_.SetWidth(newWidth);
}
}
void UIView::SetWidthPercent(float widthPercent)
{
if (IsInvalid(widthPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1)) {
int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
SetWidth(newWidth);
}
}
int16_t UIView::GetWidth()
{
return rect_.GetWidth() - (style_->paddingLeft_ + style_->paddingRight_) -
(style_->borderWidth_ * 2);
}
void UIView::SetHeight(int16_t height)
{
if (GetHeight() != height) {
int16_t newHeight = height + style_->paddingTop_ + style_->paddingBottom_ +
(style_->borderWidth_ * 2);
rect_.SetHeight(newHeight);
}
}
void UIView::SetHeightPercent(float heightPercent)
{
if (IsInvalid(heightPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetHeight() > 1)) {
int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
SetHeight(newHeight);
}
}
int16_t UIView::GetHeight()
{
return rect_.GetHeight() - (style_->paddingTop_ + style_->paddingBottom_) -
(style_->borderWidth_ * 2);
}
void UIView::Resize(int16_t width, int16_t height)
{
SetWidth(width);
SetHeight(height);
}
void UIView::ResizePercent(float widthPercent, float heightPercent)
{
if (IsInvalid(widthPercent) || IsInvalid(heightPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
Resize(newWidth, newHeight);
}
}
void UIView::SetX(int16_t x)
{
if (GetX() != x) {
rect_.SetX(x + GetStyle(STYLE_MARGIN_LEFT));
}
}
void UIView::SetXPercent(float xPercent)
{
if (IsInvalid(xPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1)) {
int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
SetX(newX);
}
}
int16_t UIView::GetX() const
{
return rect_.GetX() - GetStyle(STYLE_MARGIN_LEFT);
}
void UIView::SetY(int16_t y)
{
if (GetY() != y) {
rect_.SetY(y + GetStyle(STYLE_MARGIN_TOP));
}
}
void UIView::SetYPercent(float yPercent)
{
if (IsInvalid(yPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetHeight() > 1)) {
int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
SetY(newY);
}
}
int16_t UIView::GetY() const
{
return rect_.GetY() - GetStyle(STYLE_MARGIN_TOP);
}
void UIView::SetPosition(int16_t x, int16_t y)
{
SetX(x);
SetY(y);
}
void UIView::SetPositionPercent(float xPercent, float yPercent)
{
if (IsInvalid(xPercent) || IsInvalid(yPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
SetPosition(newX, newY);
}
}
void UIView::SetPosition(int16_t x, int16_t y, int16_t width, int16_t height)
{
SetPosition(x, y);
SetWidth(width);
SetHeight(height);
}
void UIView::SetPositionPercent(float xPercent, float yPercent, float widthPercent, float heightPercent)
{
if (IsInvalid(xPercent) || IsInvalid(yPercent) || IsInvalid(widthPercent) || IsInvalid(heightPercent)) {
return;
}
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
SetPosition(newX, newY, newWidth, newHeight);
}
}
bool UIView::IsViewGroup() const
{
return isViewGroup_;
}
void UIView::SetIntercept(bool isIntercept)
{
isIntercept_ = isIntercept;
}
bool UIView::IsIntercept()
{
return isIntercept_;
}
bool UIView::IsInvalid(float percent)
{
if ((percent < 1) && (percent > 0)) {
return false;
}
return true;
}
TransformMap& UIView::GetTransformMap()
{
if (transMap_ == nullptr) {
transMap_ = new TransformMap();
}
return *transMap_;
}
UIView* UIView::GetChildById(const char* id) const
{
return nullptr;
}
void UIView::SetViewId(const char* id)
{
id_ = id;
}
const char* UIView::GetViewId() const
{
return id_;
}
void UIView::SetViewIndex(int16_t index)
{
index_ = index;
}
int16_t UIView::GetViewIndex() const
{
return index_;
}
UIViewType UIView::GetViewType() const
{
return UI_NUMBER_MAX;
}
void UIView::LayoutCenterOfParent(int16_t xOffset, int16_t yOffset)
{
if (parent_ == nullptr) {
return;
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_CENTER_OF_PARENT, nullptr, xOffset, yOffset);
#endif
int16_t topMargin = style_->marginTop_;
int16_t leftMargin = style_->marginLeft_;
int16_t rightMargin = style_->marginRight_;
int16_t bottomMargin = style_->marginBottom_;
int16_t posX = parent_->GetWidth() / 2 - (rect_.GetWidth() - leftMargin + rightMargin) / 2 + xOffset;
int16_t posY = parent_->GetHeight() / 2 - (rect_.GetHeight() - topMargin + bottomMargin) / 2 + yOffset;
SetPosition(posX, posY);
}
void UIView::LayoutLeftOfParent(int16_t offset)
{
if (parent_ == nullptr) {
return;
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_LEFT_OF_PARENT, nullptr, offset);
#endif
int16_t leftMargin = style_->marginLeft_;
SetPosition(leftMargin + offset, GetY());
}
void UIView::LayoutRightOfParent(int16_t offset)
{
if (parent_ == nullptr) {
return;
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_RIGHT_OF_PARENT, nullptr, offset);
#endif
int16_t rightMargin = style_->marginRight_;
SetPosition(parent_->GetWidth() - offset - rect_.GetWidth() - rightMargin, GetY());
}
void UIView::LayoutTopOfParent(int16_t offset)
{
if (parent_ == nullptr) {
return;
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_TOP_OF_PARENT, nullptr, offset);
#endif
int16_t topMargin = style_->marginTop_;
SetPosition(GetX(), topMargin + offset);
}
void UIView::LayoutBottomOfParent(int16_t offset)
{
if (parent_ == nullptr) {
return;
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_BOTTOM_OF_PARENT, nullptr, offset);
#endif
int16_t bottomMargin = style_->marginBottom_;
SetPosition(GetX(), parent_->GetHeight() - offset - rect_.GetHeight() - bottomMargin);
}
void UIView::AlignLeftToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(ALIGN_LEFT_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginLeft_ - style_->marginLeft_;
SetPosition(sib->GetX() - margin + offset, GetY());
}
}
void UIView::AlignRightToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(ALIGN_RIGHT_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginRight_ - style_->marginRight_;
SetPosition(sib->GetX() + sib->rect_.GetWidth() - rect_.GetWidth() - offset + margin, GetY());
}
}
void UIView::AlignTopToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(ALIGN_TOP_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginTop_ - style_->marginTop_;
SetPosition(GetX(), sib->GetY() + offset - margin);
}
}
void UIView::AlignBottomToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(ALIGN_BOTTOM_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginBottom_ - style_->marginBottom_;
SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() - rect_.GetHeight() - offset + margin);
}
}
void UIView::AlignHorCenterToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(ALIGN_HOR_CENTER_TO_SIBLING, id, offset);
#endif
int16_t margin =
(sib->style_->marginRight_ - sib->style_->marginLeft_ - style_->marginRight_ + style_->marginLeft_) /
2;
SetPosition(sib->GetX() + sib->rect_.GetWidth() / 2 - rect_.GetWidth() / 2 + margin + offset, GetY());
}
}
void UIView::AlignVerCenterToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(ALIGN_VER_CENTER_TO_SIBLING, id, offset);
#endif
int16_t margin =
(sib->style_->marginBottom_ - sib->style_->marginTop_ - style_->marginBottom_ + style_->marginTop_) /
2;
SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() / 2 - rect_.GetHeight() / 2 + margin + offset);
}
}
void UIView::LayoutLeftToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_LEFT_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginLeft_ + style_->marginRight_;
SetPosition(sib->GetX() - offset - rect_.GetWidth() - margin, GetY());
}
}
void UIView::LayoutRightToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_RIGHT_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginRight_ + style_->marginLeft_;
SetPosition(sib->GetX() + sib->rect_.GetWidth() + offset + margin, GetY());
}
}
void UIView::LayoutTopToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_TOP_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginTop_ + style_->marginBottom_;
SetPosition(GetX(), sib->GetY() - offset - rect_.GetHeight() - margin);
}
}
void UIView::LayoutBottomToSibling(const char* id, int16_t offset)
{
if (parent_ == nullptr) {
return;
}
UIView* sib = parent_->GetChildById(id);
if (sib != nullptr) {
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
AddRelativeInfo(LAYOUT_BOTTOM_TO_SIBLING, id, offset);
#endif
int16_t margin = sib->style_->marginBottom_ + style_->marginTop_;
SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() + offset + margin);
}
}
uint8_t UIView::GetMixOpaScale() const
{
uint8_t opaMix = opaScale_;
UIView* parent = parent_;
while (parent != nullptr) {
uint8_t opaParent = parent->GetOpaScale();
opaMix = (opaParent == OPA_OPAQUE) ? opaMix : ((static_cast<uint16_t>(opaParent) * opaMix) >> 8);
parent = parent->GetParent();
}
return opaMix;
}
bool UIView::GetBitmap(ImageInfo& imageInfo, ColorMode colorMode)
{
UIView* tempRenderSibling = nextRenderSibling_;
nextRenderSibling_ = nullptr;
UIView* tempParent = parent_;
parent_ = nullptr;
int16_t tempX = rect_.GetX();
int16_t tempY = rect_.GetY();
rect_.SetPosition(0, 0);
Rect mask = GetRect();
BufferInfo bufInfo{mask, 0, nullptr, nullptr, 0, 0, colorMode, 0};
bufInfo.width = mask.GetWidth();
bufInfo.height = mask.GetHeight();
bufInfo.stride = bufInfo.width * DrawUtils::GetByteSizeByColorMode(bufInfo.mode);
BaseGfxEngine::GetInstance()->AdjustLineStride(bufInfo);
imageInfo.header.colorMode = bufInfo.mode;
imageInfo.dataSize = bufInfo.stride * bufInfo.height;
imageInfo.header.width = bufInfo.width;
imageInfo.header.height = bufInfo.height;
imageInfo.header.reserved = 0;
bufInfo.virAddr = ImageCacheMalloc(imageInfo);
if (bufInfo.virAddr == nullptr) {
GRAPHIC_LOGE("GetBitmap buffer alloc failed.");
nextRenderSibling_ = tempRenderSibling;
parent_ = tempParent;
rect_.SetPosition(tempX, tempY);
return false;
}
imageInfo.data = reinterpret_cast<uint8_t*>(bufInfo.virAddr);
if (memset_s(bufInfo.virAddr, imageInfo.dataSize, 0, imageInfo.dataSize) != EOK) {
GRAPHIC_LOGE("GetBitmap buffer memset failed.");
ImageCacheFree(imageInfo);
imageInfo.data = nullptr;
return false;
}
bufInfo.phyAddr = bufInfo.virAddr;
RootView* rootView = RootView::GetInstance();
rootView->SaveDrawContext();
rootView->UpdateBufferInfo(&bufInfo);
rootView->MeasureView(this);
rootView->DrawTop(this, mask);
rootView->RestoreDrawContext();
nextRenderSibling_ = tempRenderSibling;
parent_ = tempParent;
rect_.SetPosition(tempX, tempY);
return true;
}
bool UIView::IsOnViewTree()
{
UIView* par = this;
while (par->GetParent() != nullptr) {
par = par->GetParent();
}
if (par->GetViewType() != UI_ROOT_VIEW) {
return false;
}
return true;
}
int16_t UIView::GetWidthWithMargin()
{
return GetRelativeRect().GetWidth() + GetStyle(STYLE_MARGIN_LEFT) + GetStyle(STYLE_MARGIN_RIGHT);
}
int16_t UIView::GetHeightWithMargin()
{
return GetRelativeRect().GetHeight() + GetStyle(STYLE_MARGIN_TOP) + GetStyle(STYLE_MARGIN_BOTTOM);
}
Rect UIView::GetRelativeRect() const
{
return rect_;
}
void UIView::ResizeVisibleArea(int16_t x, int16_t y, int16_t width, int16_t height)
{
if (visibleRect_ == nullptr) {
visibleRect_ = new Rect();
if (visibleRect_ == nullptr) {
GRAPHIC_LOGE("new Rect fail");
return;
}
}
visibleRect_->SetWidth(width);
visibleRect_->SetHeight(height);
visibleRect_->SetPosition(x, y);
}
void UIView::SetZIndex(int16_t zIndex)
{
if (zIndex_ == zIndex) {
return;
}
zIndex_ = zIndex;
if (parent_ != nullptr) {
reinterpret_cast<UIViewGroup*>(parent_)->UpdateRenderView(this);
}
}
int16_t UIView::GetZIndex()
{
return zIndex_;
}
}