* Copyright (c) 2021-2022 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.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_DOM_DOM_NODE_H
#define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_DOM_DOM_NODE_H
#include <string>
#include <unordered_map>
#include "base/geometry/transform_util.h"
#include "base/json/json_util.h"
#include "base/memory/ace_type.h"
#include "base/utils/macros.h"
#include "compatible/components/list/list_component.h"
#include "core/animation/animation_util.h"
#include "core/animation/keyframe_animation.h"
#include "core/animation/property_animation.h"
#include "core/components/box/box_component.h"
#include "core/components/common/properties/shadow.h"
#include "core/components/declaration/common/declaration_creator_manager.h"
#include "core/components/declaration/common/common_background_style.h"
#include "core/components/display/display_component.h"
#include "core/components/flex/flex_component.h"
#include "core/components/flex/flex_item_component.h"
#include "core/components/focusable/focusable_component.h"
#include "core/components/gesture_listener/gesture_listener_component.h"
#include "core/components/mouse_listener/mouse_listener_component.h"
#include "core/components/page_transition/page_transition_component.h"
#include "core/components/positioned/positioned_component.h"
#include "core/components/shared_transition/shared_transition_component.h"
#include "core/components/stack/stack_component.h"
#include "core/components/theme/theme_utils.h"
#include "core/components/touch_listener/touch_listener_component.h"
#include "core/components/transform/transform_component.h"
#include "core/components/transition/transition_component.h"
#include "core/components/tween/tween_component.h"
#include "core/pipeline/pipeline_context.h"
#include "frameworks/bridge/common/dom/dom_type.h"
#include "frameworks/bridge/common/utils/transform_convertor.h"
#include "frameworks/core/animation/animatable_data.h"
#ifndef WEARABLE_PRODUCT
#include "core/components/multimodal/multimodal_component.h"
#endif
namespace OHOS::Ace::Framework {
inline constexpr int32_t DEFAULT_ITEM_INDEX = -1;
class ACE_FORCE_EXPORT DOMNode : public virtual AceType {
DECLARE_ACE_TYPE(DOMNode, AceType);
public:
DOMNode(NodeId nodeId, const std::string& nodeName);
~DOMNode() override;
void SetAnimationStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes);
bool ParseAnimationStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes);
void SetSharedTransitionStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes);
bool ParseTransitionPropertyStyle(const std::string& transitionProperty);
bool ParseTransitionNameStyle(const std::string& transitionName);
void CreateDeclaration(const std::string& tag);
void TweenOptionSetKeyframes(TweenOption& tweenOption);
void SetCustomAnimationStyleUpdate(bool enable);
void AddNode(const RefPtr<DOMNode>& node, int32_t slot = DEFAULT_ITEM_INDEX);
void RemoveNode(const RefPtr<DOMNode>& node);
virtual void Mount(int32_t slot);
void GenerateComponentNode();
virtual void OnPageLoadFinish() {}
virtual void SetShowAttr(const std::string& showValue);
virtual const RefPtr<ScrollComponent>& GetScrollComponent() const
{
return scrollComponent_;
}
void MarkNeedUpdate();
void SetTweenComponent(const RefPtr<TweenComponent>& tweenComponent)
{
tweenComponent_ = tweenComponent;
if (!displayComponent_) {
displayComponent_ = AceType::MakeRefPtr<DisplayComponent>(rootComponent_->GetChild());
}
if (!transformComponent_) {
transformComponent_ = AceType::MakeRefPtr<TransformComponent>();
}
}
RefPtr<TweenComponent> GetTweenComponent() const
{
return tweenComponent_;
}
const std::list<RefPtr<DOMNode>>& GetChildList() const
{
return children_;
}
const RefPtr<Declaration>& GetDeclaration() const
{
return declaration_;
}
const RefPtr<ComposedComponent>& GetRootComponent() const
{
return rootComponent_;
}
const RefPtr<BoxComponent>& GetBoxComponent() const
{
return boxComponent_;
}
const RefPtr<DisplayComponent>& GetDisplayComponent() const
{
return displayComponent_;
}
const RefPtr<TouchListenerComponent>& GetTouchListenerComponent() const
{
return touchEventComponent_;
}
const RefPtr<MouseListenerComponent>& GetMouseListenerComponent() const
{
return mouseEventComponent_;
}
const RefPtr<GestureListenerComponent>& GetGestureListenerComponent() const
{
return gestureEventComponent_;
}
const RefPtr<FocusableComponent>& GetFocusableComponent() const
{
return focusableEventComponent_;
}
const RefPtr<TransformComponent>& GetTransformComponent() const
{
return transformComponent_;
}
void SetShareId(const std::string& shareId)
{
shareId_ = shareId;
if (declaration_) {
declaration_->SetShareId(shareId);
}
}
const std::string& GetShareId() const
{
return shareId_;
}
const RefPtr<PageTransitionComponent>& BuildTransitionComponent();
void SetOnClick(const EventMarker& eventMarker)
{
ACE_DCHECK(gestureEventComponent_);
gestureEventComponent_->SetOnClickId(eventMarker);
}
void SetOnDoubleClick(const EventMarker& eventMarker)
{
ACE_DCHECK(gestureEventComponent_);
gestureEventComponent_->SetOnDoubleClickId(eventMarker);
}
void SetOnDragStart(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnFreeDragStartId(eventMarker);
}
void SetOnDrag(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnFreeDragUpdateId(eventMarker);
}
void SetOnDragEnd(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnFreeDragEndId(eventMarker);
}
void SetOnLongPress(const EventMarker& eventMarker)
{
ACE_DCHECK(gestureEventComponent_);
gestureEventComponent_->SetOnLongPressId(eventMarker);
}
void SetOnPinchStart(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnPinchStartId(eventMarker);
}
void SetOnPinchUpdate(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnPinchUpdateId(eventMarker);
}
void SetOnPinchEnd(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnPinchEndId(eventMarker);
}
void SetOnPinchCancel(const EventMarker& eventMarker)
{
gestureEventComponent_->SetOnPinchCancelId(eventMarker);
}
void SetIsRootNode(bool isRootNode)
{
isRootNode_ = isRootNode;
}
bool IsRootNode() const
{
return isRootNode_;
}
void SetIsTransition(bool isTransition)
{
isTransition_ = isTransition;
}
bool GetIsTransition() const
{
return isTransition_;
}
void SetOnFocusClick(const EventMarker& eventMarker);
bool IsNodeDisabled() const;
void SetIsEnter(bool isEnter)
{
isEnter_ = isEnter;
}
bool GetIsEnter() const
{
return isEnter_;
}
NodeId GetNodeId() const
{
return nodeId_;
}
std::string GetNodeIdForEvent() const;
const std::string& GetTag() const
{
return tag_;
}
void SetProxyNode(bool isProxy)
{
isProxy_ = isProxy;
}
bool IsProxy() const
{
return isProxy_;
}
bool IsShow() const
{
double opacity = 1.0;
if (declaration_) {
auto& opacityStyle =
static_cast<CommonOpacityStyle&>(declaration_->GetStyle(StyleTag::COMMON_OPACITY_STYLE));
if (opacityStyle.IsValid()) {
opacity = opacityStyle.opacity;
}
}
return visible_ == VisibleType::VISIBLE && !NearZero(opacity);
}
Color GetBackGroundColor() const
{
Color color = Color::TRANSPARENT;
if (declaration_ && isTransitionColor_) {
auto& style =
static_cast<CommonBackgroundStyle&>(declaration_->GetStyle(StyleTag::COMMON_BACKGROUND_STYLE));
if (style.IsValid()) {
color = style.backgroundColor;
}
}
return color;
}
double GetOpacity() const
{
double opacity = 1.0;
if (declaration_) {
auto& style = static_cast<CommonOpacityStyle&>(declaration_->GetStyle(StyleTag::COMMON_OPACITY_STYLE));
if (style.IsValid()) {
opacity = style.opacity;
}
}
return opacity;
}
NodeId GetParentId() const
{
return parentId_;
}
RefPtr<DOMNode> GetParentNode() const
{
return parentNode_.Upgrade();
}
bool IsTabbarSubNode() const;
void SetParentNode(const RefPtr<DOMNode>& parentNode)
{
if (!parentNode) {
return;
}
parentNode_ = parentNode;
parentId_ = parentNode->GetNodeId();
parentTag_ = parentNode->GetTag();
if (tag_ == DOM_NODE_TAG_SVG || parentNode->HasSvgTag()) {
hasSvgTag_ = true;
}
}
int32_t GetPageId() const
{
return pageId_;
}
void SetPageId(int32_t pageId)
{
pageId_ = pageId;
}
virtual RefPtr<Component> GetSpecializedComponent() = 0;
void SetPipelineContext(const WeakPtr<PipelineContext>& pipelineContext)
{
pipelineContext_ = pipelineContext;
}
const WeakPtr<PipelineContext>& GetPipelineContext() const
{
return pipelineContext_;
}
virtual void InitializeStyle() {}
void OnActive(bool isActive);
bool HasPseudo() const
{
return (cachedPseudoType_ != STATE_NORMAL);
}
bool HasDisabledPseudo() const
{
return ((cachedPseudoType_ & STATE_DISABLED) > 0);
}
bool HasCheckedPseudo() const
{
return ((cachedPseudoType_ & STATE_CHECKED) > 0);
}
bool HasFocusPseudo() const
{
return ((cachedPseudoType_ & STATE_FOCUS) > 0);
}
bool HasActivePseudo() const
{
return ((cachedPseudoType_ & STATE_ACTIVE) > 0);
}
bool HasSvgTag()
{
return hasSvgTag_;
}
* Parse color from string content and reference for id/attr, including format:
* #rrggbb, #aarrggbb, "@id001", "@attr_sys_color".
*/
Color ParseColor(const std::string& value, uint32_t maskAlpha = COLOR_ALPHA_MASK) const;
* Parse double from string content and reference for id/attr, including format:
* 100.01, "@id001", "@attr_sys_alpha".
*/
double ParseDouble(const std::string& value) const;
* Parse dimension from string content and reference for id/attr, including format:
* 10px, "@id001", "@attr_sys_dimension, expression".
*/
CalcDimension ParseDimension(const std::string& value) const;
* Parse line height from string content and reference for id/attr, including format:
* 1.5, "@id001", "@attr_sys_line_height".
*/
Dimension ParseLineHeight(const std::string& value) const;
* Parse font family list from string content and reference for id/attr, including format:
* sans-serif, "@id001", "@attr_sys_font_family".
*/
std::vector<std::string> ParseFontFamilies(const std::string& value) const;
* Parse dimension list from string content and reference for id/attr, including format:
* 10px, "@id001", "@attr_sys_dimension".
*/
std::vector<Dimension> ParsePreferFontSizes(const std::string& value) const;
* Parse image src from string content and reference for id/attr, including format:
* "@app.media.customized_image", "@sys.media.123".
*/
std::string ParseImageSrc(const std::string& imgSrc) const;
RefPtr<ThemeManager> GetThemeManager() const
{
auto context = pipelineContext_.Upgrade();
if (!context) {
return nullptr;
}
return context->GetThemeManager();
}
template<typename T>
RefPtr<T> GetTheme() const
{
auto context = pipelineContext_.Upgrade();
if (!context) {
return nullptr;
}
auto themeManager = context->GetThemeManager();
if (!themeManager) {
return nullptr;
}
return themeManager->GetTheme<T>();
}
virtual void UpdateStyleWithChildren();
bool IsCustomComponent() const
{
return isCustomComponent_;
}
void SetIsCustomComponent(bool isCustomComponent)
{
isCustomComponent_ = isCustomComponent;
}
bool HasBorderRadiusStyle() const
{
return declaration_ ? declaration_->HasBorderRadiusStyle() : false;
}
bool HasOverflowStyle() const
{
return declaration_ ? declaration_->HasOverflowStyle() : false;
}
bool IsBoxWrap() const
{
return boxWrap_;
}
void SetBoxWrap(bool boxWrap)
{
boxWrap_ = boxWrap;
}
void AdjustParamInLiteMode();
virtual void AdjustSpecialParamInLiteMode() {}
virtual void SetAttr(const std::vector<std::pair<std::string, std::string>>& attrs);
virtual void SetStyle(const std::vector<std::pair<std::string, std::string>>& styles);
virtual void AddEvent(int32_t pageId, const std::vector<std::string>& events);
virtual void CallMethod(const std::string& method, const std::string& args);
virtual void OnRequestFocus(bool shouldFocus);
virtual void OnScrollBy(double dx, double dy, bool isSmooth);
bool SetCurrentStyle(const std::pair<std::string, std::string>& style);
bool IsRightToLeft() const
{
return declaration_ ? declaration_->IsRightToLeft() : false;
}
void SetHeight(const CalcDimension& height)
{
if (declaration_) {
auto& sizeStyle = declaration_->MaybeResetStyle<CommonSizeStyle>(StyleTag::COMMON_SIZE_STYLE);
if (sizeStyle.IsValid()) {
sizeStyle.height = height;
}
}
}
void SetWidth(const CalcDimension& width)
{
if (declaration_) {
auto& sizeStyle = declaration_->MaybeResetStyle<CommonSizeStyle>(StyleTag::COMMON_SIZE_STYLE);
if (sizeStyle.IsValid()) {
sizeStyle.width = width;
}
}
}
virtual Dimension GetHeight() const;
virtual CalcDimension GetCalcHeight() const;
virtual Dimension GetWidth() const;
virtual CalcDimension GetCalcWidth() const;
DisplayType GetDisplay() const
{
DisplayType display = DisplayType::NO_SETTING;
if (declaration_) {
auto& displayStyle =
static_cast<CommonDisplayStyle&>(declaration_->GetStyle(StyleTag::COMMON_DISPLAY_STYLE));
if (displayStyle.IsValid()) {
display = displayStyle.display;
}
}
return display;
}
void SetDisplay(DisplayType type)
{
if (declaration_) {
auto& displayStyle = declaration_->MaybeResetStyle<CommonDisplayStyle>(StyleTag::COMMON_DISPLAY_STYLE);
if (displayStyle.IsValid()) {
displayStyle.display = type;
}
}
}
PositionType GetPosition() const
{
PositionType position = PositionType::PTRELATIVE;
if (declaration_) {
auto& positionStyle =
static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
if (positionStyle.IsValid()) {
position = positionStyle.position;
}
}
return position;
}
std::optional<Color> GetImageFill() const
{
std::optional<Color> imageFill = std::nullopt;
if (declaration_) {
auto& imageStyle = static_cast<CommonImageStyle&>(declaration_->GetStyle(StyleTag::COMMON_IMAGE_STYLE));
if (imageStyle.IsValid()) {
imageFill = imageStyle.imageFill;
}
}
return imageFill;
}
virtual NodeId GetDirtyNodeId() const
{
return nodeId_;
}
protected:
virtual void OnMounted(const RefPtr<DOMNode>& parentNode) {}
virtual void OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot) {}
virtual void OnChildNodeRemoved(const RefPtr<DOMNode>& child) {}
virtual void OnSetStyleFinished() {}
virtual const EventMarker& GetClickId();
virtual const EventMarker& GetDoubleClickId();
const EventMarker& GetDragStartId();
const EventMarker& GetDragId();
const EventMarker& GetDragEndId();
const EventMarker& GetDragEnterId();
const EventMarker& GetDragOverId();
const EventMarker& GetDragLeaveId();
const EventMarker& GetDragDropId();
virtual const EventMarker& GetLongPressId();
const EventMarker& GetPinchStartId();
const EventMarker& GetPinchUpdateId();
const EventMarker& GetPinchEndId();
const EventMarker& GetPinchCancelId();
EventMarker& GetSwipeId(uint32_t action, uint32_t stage);
EventMarker& GetTouchId(uint32_t action, uint32_t stage, uint32_t type);
virtual RefPtr<Component> CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>>& components);
virtual void UpdateSpecializedComponentWithDeclaration() {}
virtual void PrepareSpecializedComponent() {}
virtual void CompositeComponents();
virtual void UpdateBoxSize(const CalcDimension& width, const CalcDimension& height);
virtual void UpdateBoxPadding(const Edge& padding);
virtual void UpdateBoxBorder(const Border& border);
virtual void UpdatePropAnimations(const PropAnimationMap& animations);
virtual void UpdatePositionAnimations(const RefPtr<Component> component);
virtual void ResetInitializedStyle() {}
virtual bool IsLeafNode() const
{
return false;
}
void PrepareScrollComponent();
RefPtr<SingleChild> GetLastCommonParent()
{
if (sharedTransitionComponent_) {
return sharedTransitionComponent_;
}
return boxComponent_;
}
void SetAlignment(const Alignment& align)
{
ACE_DCHECK(boxComponent_);
boxComponent_->SetAlignment(align);
}
void OnChecked(bool isChecked);
virtual bool SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
{
return false;
}
virtual bool SetSpecializedStyle(const std::pair<std::string, std::string>& style)
{
return false;
}
virtual bool AddSpecializedEvent(int32_t pageId, const std::string& event)
{
return false;
}
virtual void CallSpecializedMethod(const std::string& method, const std::string& args) {}
virtual bool IsSubscriptEnable() const
{
if (declaration_) {
declaration_->SetIsSubscriptEnable(false);
}
return false;
}
WeakPtr<DOMNode> parentNode_;
NodeId parentId_ = -1;
bool isRootNode_ = false;
std::string parentTag_;
std::list<RefPtr<DOMNode>> children_;
std::vector<std::pair<std::string, std::string>> attributesCache_;
std::unordered_map<int32_t, std::unordered_map<std::string, std::string>> pseudoClassStyleMap_;
RefPtr<ComposedComponent> rootComponent_;
RefPtr<BoxComponent> boxComponent_;
RefPtr<ScrollComponent> scrollComponent_;
RefPtr<FlexItemComponent> flexItemComponent_;
RefPtr<TransformComponent> transformComponent_;
WeakPtr<PipelineContext> pipelineContext_;
RefPtr<Declaration> declaration_;
bool isCustomComponent_ = false;
bool boxWrap_ = false;
private:
static void SetTransform(const std::string& value, DOMNode& node);
static void AddKeyframe(
double time, const std::string& typeValue, RefPtr<KeyframeAnimation<float>>& transformKeyframes);
static void AddKeyframe(double time, double typeValue, RefPtr<KeyframeAnimation<float>>& transformKeyframes);
std::string GetTransformJsonValue(const std::string& value);
std::string GetTransformType(const std::unique_ptr<JsonValue>& transformJson);
std::string GetTransformTypeValue(const std::unique_ptr<JsonValue>& transformJson);
void CreatePropertyAnimation(const std::string& property);
RefPtr<KeyframeAnimation<float>> SetPropertyFloatAnimationKeyframe(float begin, float end);
RefPtr<KeyframeAnimation<Color>> SetPropertyColorAnimationKeyframe(const Color& begin, const Color& end);
void TransitionOptionSetKeyframes(TweenOption& tweenOption);
void SetDisplayStyle();
void SetDisplayType();
void UpdateFlexItemComponent();
void UpdateUiComponents();
void UpdateBoxComponent();
void UpdateDisplayComponent();
void UpdateTweenComponent();
void UpdateTouchEventComponent();
void UpdateGestureEventComponent();
void UpdateMouseEventComponent();
void UpdateFocusableEventComponents();
void UpdatePositionComponent();
void UpdatePositionProps();
void UpdateTweenPosition(const RefPtr<TweenComponent> tweenComponent);
#ifndef WEARABLE_PRODUCT
void UpdateMultimodalComponent();
#endif
void CachePseudoClassStyle(const std::pair<std::string, std::string>& pseudoClassStyle);
void UpdatePseudoStyle(bool isBackendChange);
void PrepareTouchEvent(EventMarker& eventMarker, uint32_t type);
void PrepareFocusableEventId();
void PrepareMouseHoverEvent();
void UpdatePseudoStyleByStatus(int32_t status, bool isBackendChange);
void ResetDefaultStyles();
uint32_t CalculatePseudoStatus() const;
void SetAttrInternal(const std::vector<std::pair<std::string, std::string>>& attrs);
void OnFocus(bool isFocus);
void OnHover(bool isHover);
RefPtr<ThemeConstants> GetThemeConstants() const;
template<typename T>
T ParseThemeReference(const std::string& value, std::function<T()>&& noRefFunc,
std::function<T(uint32_t refId)>&& idRefFunc, const T& errorValue) const
{
const auto& parseResult = ThemeUtils::ParseThemeIdReference(value, GetThemeConstants());
if (!parseResult.parseSuccess) {
return noRefFunc();
}
auto themeConstants = GetThemeConstants();
if (!themeConstants) {
return errorValue;
}
if (parseResult.isIdRef) {
return idRefFunc(parseResult.id);
}
auto themeStyle = themeConstants->GetThemeStyle();
if (!themeStyle) {
return errorValue;
}
return themeStyle->GetAttr<T>(parseResult.refAttr, errorValue);
}
bool isTransition_ = false;
bool isEnter_ = false;
bool isProxy_ = false;
bool animationStyleUpdated_ = false;
bool customAnimationStyleUpdated_ = false;
bool hasSvgTag_ = false;
VisibleType visible_ = VisibleType::VISIBLE;
int32_t pageId_ = -1;
NodeId nodeId_ = -1;
std::string tag_;
RefPtr<DisplayComponent> displayComponent_;
RefPtr<TouchListenerComponent> touchEventComponent_;
RefPtr<GestureListenerComponent> gestureEventComponent_;
RefPtr<FocusableComponent> focusableEventComponent_;
RefPtr<MouseListenerComponent> mouseEventComponent_;
RefPtr<PositionedComponent> positionComponent_;
RefPtr<SharedTransitionComponent> sharedTransitionComponent_;
RefPtr<TweenComponent> tweenComponent_;
RefPtr<TransitionComponent> propTransitionComponent_;
RefPtr<PageTransitionComponent> transitionComponent_;
PropAnimationMap propAnimations_;
AnimationUtil animationUtil_;
RefPtr<KeyframeAnimation<float>> propertyWidthAnimation_;
RefPtr<KeyframeAnimation<float>> propertyHeightAnimation_;
RefPtr<KeyframeAnimation<Color>> propertyColorAnimation_;
std::string animationName_;
bool isActive_ = false;
bool isFocus_ = false;
uint32_t cachedPseudoType_ = STATE_NORMAL;
TweenOption propTransitionOption_;
std::string transitionPropertyName_ = "all";
std::string transitionTimeFunction_ = "ease";
int32_t transitionDuration_ = 0;
int32_t transitionDelay_ = 0;
bool isTransitionNameUpdateFirst_ = true;
bool isTransitionDurationUpdateFirst_ = true;
bool transitionStyleUpdated_ = false;
bool isTransitionColor_ = false;
std::string shareId_;
#ifndef WEARABLE_PRODUCT
RefPtr<MultimodalComponent> multimodalComponent_;
#endif
};
}
#endif