From 7b6b9810f997c40014aa40cdfd6a434eb5ca45df Mon Sep 17 00:00:00 2001 From: zcdqs Date: Sat, 24 Sep 2022 10:47:33 +0800 Subject: [PATCH] ng inspector for xts Signed-off-by: zcdqs Change-Id: Ibc121bd5bf4787243cf24c930356b65d99cb9953 --- frameworks/base/geometry/ng/rect_t.h | 21 ++ frameworks/base/utils/string_utils.h | 6 +- .../engine/jsi/jsi_view_register.cpp | 55 +++-- frameworks/core/animation/curves.cpp | 20 ++ frameworks/core/animation/curves.h | 2 + .../core/components/swiper/render_swiper.cpp | 26 +- frameworks/core/components_ng/base/BUILD.gn | 1 + .../core/components_ng/base/frame_node.cpp | 6 + .../core/components_ng/base/frame_node.h | 2 + .../core/components_ng/base/inspector.cpp | 230 ++++++++++++++++++ .../core/components_ng/base/inspector.h | 32 +++ .../components_ng/layout/layout_property.cpp | 8 + .../components_ng/layout/layout_property.h | 2 + .../pattern/swiper/swiper_layout_property.h | 14 ++ .../pattern/swiper/swiper_paint_property.h | 20 ++ .../components_ng/property/flex_property.h | 10 + .../property/magic_layout_property.h | 7 + .../components_ng/property/measure_property.h | 36 +++ .../property/position_property.h | 5 + .../core/components_ng/property/property.h | 12 +- .../components_ng/render/paint_property.h | 2 + .../core/pipeline_ng/pipeline_context.cpp | 1 + .../core/pipeline_ng/pipeline_context.h | 5 + 23 files changed, 477 insertions(+), 46 deletions(-) create mode 100644 frameworks/core/components_ng/base/inspector.cpp create mode 100644 frameworks/core/components_ng/base/inspector.h diff --git a/frameworks/base/geometry/ng/rect_t.h b/frameworks/base/geometry/ng/rect_t.h index f24a3dd4543..fab677ab09e 100644 --- a/frameworks/base/geometry/ng/rect_t.h +++ b/frameworks/base/geometry/ng/rect_t.h @@ -337,6 +337,27 @@ public: return output; } + std::string ToBounds() const + { + static const int32_t precision = 2; + std::stringstream ss; + ss << "[" << std::fixed << std::setprecision(precision) << x_ << ", " << y_ << "]["; + if (NearEqual(width_, Infinity())) { + ss << "INFINITE"; + } else { + ss << (x_ + width_); + } + ss << ","; + if (NearEqual(height_, Infinity())) { + ss << "INFINITE"; + } else { + ss << (y_ + height_); + } + ss << "]"; + std::string output = ss.str(); + return output; + } + OffsetT Center() const { return OffsetT(width_ / 2.0 + x_, height_ / 2.0 + y_); diff --git a/frameworks/base/utils/string_utils.h b/frameworks/base/utils/string_utils.h index c49ebdf0ad4..5cae7a920c3 100644 --- a/frameworks/base/utils/string_utils.h +++ b/frameworks/base/utils/string_utils.h @@ -327,7 +327,11 @@ inline std::string DoubleToString(double value, int32_t precision = 2) { std::ostringstream result; result.precision(precision); - result << std::fixed << value; + if (NearEqual(value, Infinity())) { + result << "Infinity"; + } else { + result << std::fixed << value; + } return result.str(); } diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp index 44e7e0b77c1..6c00768489f 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp @@ -162,6 +162,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/scroll_bar/js_scroll_bar.h" #include "frameworks/bridge/declarative_frontend/sharedata/js_share_data.h" #include "frameworks/core/common/container.h" +#include "frameworks/core/components_ng/base/inspector.h" #include "frameworks/core/components_v2/inspector/inspector.h" #if defined(PREVIEW) #include "frameworks/bridge/declarative_frontend/jsview/js_previewer_mock.h" @@ -501,6 +502,11 @@ panda::Local JsGetInspectorTree(panda::JsiRuntimeCallInfo* ru LOGW("container is null"); return panda::JSValueRef::Undefined(vm); } + + if (container->IsUseNewPipeline()) { + auto nodeInfos = NG::Inspector::GetInspectorTree(); + return panda::StringRef::NewFromUtf8(vm, nodeInfos.c_str()); + } auto pipelineContext = AceType::DynamicCast(container->GetPipelineContext()); if (pipelineContext == nullptr) { LOGE("pipeline is null"); @@ -513,7 +519,7 @@ panda::Local JsGetInspectorTree(panda::JsiRuntimeCallInfo* ru panda::Local JsGetInspectorByKey(panda::JsiRuntimeCallInfo* runtimeCallInfo) { EcmaVM* vm = runtimeCallInfo->GetVM(); - int32_t argc = runtimeCallInfo->GetArgsNumber(); + auto argc = runtimeCallInfo->GetArgsNumber(); if (vm == nullptr) { LOGE("The EcmaVM is null"); return panda::JSValueRef::Undefined(vm); @@ -528,13 +534,16 @@ panda::Local JsGetInspectorByKey(panda::JsiRuntimeCallInfo* r LOGW("container is null"); return panda::JSValueRef::Undefined(vm); } + std::string key = firstArg->ToString(vm)->ToString(); + if (container->IsUseNewPipeline()) { + auto resultStr = NG::Inspector::GetInspectorNodeByKey(key); + return panda::StringRef::NewFromUtf8(vm, resultStr.c_str()); + } auto pipelineContext = AceType::DynamicCast(container->GetPipelineContext()); if (pipelineContext == nullptr) { LOGE("pipelineContext==nullptr"); return panda::JSValueRef::Undefined(vm); } - - std::string key = firstArg->ToString(vm)->ToString(); auto resultStr = V2::Inspector::GetInspectorNodeByKey(pipelineContext, key); return panda::StringRef::NewFromUtf8(vm, resultStr.c_str()); } @@ -542,7 +551,7 @@ panda::Local JsGetInspectorByKey(panda::JsiRuntimeCallInfo* r panda::Local JsSendEventByKey(panda::JsiRuntimeCallInfo* runtimeCallInfo) { EcmaVM* vm = runtimeCallInfo->GetVM(); - int32_t argc = runtimeCallInfo->GetArgsNumber(); + auto argc = runtimeCallInfo->GetArgsNumber(); if (vm == nullptr) { LOGE("The EcmaVM is null"); return panda::JSValueRef::Undefined(vm); @@ -557,15 +566,19 @@ panda::Local JsSendEventByKey(panda::JsiRuntimeCallInfo* runt LOGW("container is null"); return panda::JSValueRef::Undefined(vm); } + + std::string key = firstArg->ToString(vm)->ToString(); + auto action = runtimeCallInfo->GetCallArgRef(1)->Int32Value(vm); + auto params = runtimeCallInfo->GetCallArgRef(2)->ToString(vm)->ToString(); + if (container->IsUseNewPipeline()) { + auto result = NG::Inspector::SendEventByKey(key, action, params); + return panda::BooleanRef::New(vm, result); + } auto pipelineContext = AceType::DynamicCast(container->GetPipelineContext()); if (pipelineContext == nullptr) { LOGE("pipelineContext==nullptr"); return panda::JSValueRef::Undefined(vm); } - - std::string key = firstArg->ToString(vm)->ToString(); - auto action = runtimeCallInfo->GetCallArgRef(1)->Int32Value(vm); - auto params = runtimeCallInfo->GetCallArgRef(2)->ToString(vm)->ToString(); auto result = V2::Inspector::SendEventByKey(pipelineContext, key, action, params); return panda::BooleanRef::New(vm, result); } @@ -594,7 +607,7 @@ static TouchEvent GetTouchPointFromJS(const JsiObject& value) panda::Local JsSendTouchEvent(panda::JsiRuntimeCallInfo* runtimeCallInfo) { EcmaVM* vm = runtimeCallInfo->GetVM(); - int32_t argc = runtimeCallInfo->GetArgsNumber(); + auto argc = runtimeCallInfo->GetArgsNumber(); if (vm == nullptr) { LOGE("The EcmaVM is null"); return panda::JSValueRef::Undefined(vm); @@ -622,17 +635,18 @@ panda::Local JsSendTouchEvent(panda::JsiRuntimeCallInfo* runt return panda::BooleanRef::New(vm, result); } -static V2::JsKeyEvent GetKeyEventFromJS(const JsiObject& value) +static KeyEvent GetKeyEventFromJS(const JsiObject& value) { - V2::JsKeyEvent keyEvent; auto type = value->GetProperty("type"); - keyEvent.action = static_cast(type->ToNumber()); + auto action = static_cast(type->ToNumber()); auto jsKeyCode = value->GetProperty("keyCode"); - keyEvent.code = static_cast(jsKeyCode->ToNumber()); + auto code = static_cast(jsKeyCode->ToNumber()); + + KeyEvent keyEvent(code, action); auto jsKeySource = value->GetProperty("keySource"); - keyEvent.sourceDevice = jsKeySource->ToNumber(); + keyEvent.sourceType = static_cast(jsKeySource->ToNumber()); auto jsDeviceId = value->GetProperty("deviceId"); keyEvent.deviceId = jsDeviceId->ToNumber(); @@ -641,7 +655,8 @@ static V2::JsKeyEvent GetKeyEventFromJS(const JsiObject& value) keyEvent.metaKey = jsMetaKey->ToNumber(); auto jsTimestamp = value->GetProperty("timestamp"); - keyEvent.timeStamp = jsTimestamp->ToNumber(); + auto timeStamp = jsTimestamp->ToNumber(); + keyEvent.SetTimeStamp(timeStamp); return keyEvent; } @@ -649,7 +664,7 @@ static V2::JsKeyEvent GetKeyEventFromJS(const JsiObject& value) panda::Local JsSendKeyEvent(panda::JsiRuntimeCallInfo* runtimeCallInfo) { EcmaVM* vm = runtimeCallInfo->GetVM(); - int32_t argc = runtimeCallInfo->GetArgsNumber(); + auto argc = runtimeCallInfo->GetArgsNumber(); if (vm == nullptr) { LOGE("The EcmaVM is null"); return panda::JSValueRef::Undefined(vm); @@ -665,13 +680,15 @@ panda::Local JsSendKeyEvent(panda::JsiRuntimeCallInfo* runtim LOGW("container is null"); return panda::JSValueRef::Undefined(vm); } - auto pipelineContext = AceType::DynamicCast(container->GetPipelineContext()); + auto pipelineContext = container->GetPipelineContext(); if (pipelineContext == nullptr) { LOGE("pipelineContext==nullptr"); return panda::JSValueRef::Undefined(vm); } JsiObject obj(firstArg); - auto result = V2::Inspector::SendKeyEvent(pipelineContext, GetKeyEventFromJS(obj)); + KeyEvent keyEvent = GetKeyEventFromJS(obj); + auto result = pipelineContext->GetTaskExecutor()->PostTask( + [pipelineContext, keyEvent]() { pipelineContext->OnKeyEvent(keyEvent); }, TaskExecutor::TaskType::UI); return panda::BooleanRef::New(vm, result); } @@ -701,7 +718,7 @@ static MouseEvent GetMouseEventFromJS(const JsiObject& value) panda::Local JsSendMouseEvent(panda::JsiRuntimeCallInfo* runtimeCallInfo) { EcmaVM* vm = runtimeCallInfo->GetVM(); - int32_t argc = runtimeCallInfo->GetArgsNumber(); + auto argc = runtimeCallInfo->GetArgsNumber(); if (vm == nullptr) { LOGE("The EcmaVM is null"); return panda::JSValueRef::Undefined(vm); diff --git a/frameworks/core/animation/curves.cpp b/frameworks/core/animation/curves.cpp index 3accea4a8fe..44f40347739 100644 --- a/frameworks/core/animation/curves.cpp +++ b/frameworks/core/animation/curves.cpp @@ -15,6 +15,8 @@ #include "core/animation/curves.h" +#include + namespace OHOS::Ace { const RefPtr Curves::DECELE = AceType::MakeRefPtr(); @@ -36,4 +38,22 @@ const RefPtr Curves::ANTICIPATE = AceType::MakeRefPtr Curves::MAGNETIC = AceType::MakeRefPtr(0.8f, 0.0f, 1.0f, 0.6f); const RefPtr Curves::ELASTICS = AceType::MakeRefPtr(2.0f); +const std::string Curves::DEFAULT_CURVE_NAME = "Curves.Ease"; + +std::string Curves::ToString(const RefPtr& curve) +{ + static const std::map, std::string> curveNames = { { Curves::EASE, Curves::DEFAULT_CURVE_NAME }, + { Curves::EASE_IN, "Curves.EaseIn" }, { Curves::EASE_OUT, "Curves.EaseOut" }, + { Curves::EASE_IN_OUT, "Curves.EaseInOut" }, { Curves::FAST_OUT_SLOW_IN, "Curves.FastOutSlowIn" }, + { Curves::LINEAR_OUT_SLOW_IN, "Curves.LinearOutSlowIn" }, + { Curves::FAST_OUT_LINEAR_IN, "Curves.FastOutLinearIn" }, { Curves::FRICTION, "Curves.Friction" }, + { Curves::EXTREME_DECELERATION, "Curves.ExtremeDeceleration" }, { Curves::SHARP, "Curves.Sharp" }, + { Curves::SMOOTH, "Curves.Smooth" }, { Curves::LINEAR, "Curves.Linear" } }; + auto iter = curveNames.find(curve); + if (iter != curveNames.end()) { + return iter->second; + } + return Curves::DEFAULT_CURVE_NAME; +} + } // namespace OHOS::Ace diff --git a/frameworks/core/animation/curves.h b/frameworks/core/animation/curves.h index c62d8aa323f..8421c2dd473 100644 --- a/frameworks/core/animation/curves.h +++ b/frameworks/core/animation/curves.h @@ -44,6 +44,8 @@ public: static const RefPtr ANTICIPATE; static const RefPtr MAGNETIC; static const RefPtr ELASTICS; + static const std::string DEFAULT_CURVE_NAME; + static std::string ToString(const RefPtr& curve); }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/swiper/render_swiper.cpp b/frameworks/core/components/swiper/render_swiper.cpp index b0589328ae4..a5249229eb3 100644 --- a/frameworks/core/components/swiper/render_swiper.cpp +++ b/frameworks/core/components/swiper/render_swiper.cpp @@ -224,31 +224,7 @@ void RenderSwiper::Update(const RefPtr& component) curve_ = swiper->GetCurve(); if (curve_) { - if (curve_ == Curves::EASE) { - curveRender_ = "Curves.Ease"; - } else if (curve_ == Curves::EASE_IN) { - curveRender_ = "Curves.EaseIn"; - } else if (curve_ == Curves::EASE_OUT) { - curveRender_ = "Curves.EaseOut"; - } else if (curve_ == Curves::EASE_IN_OUT) { - curveRender_ = "Curves.EaseInOut"; - } else if (curve_ == Curves::FAST_OUT_SLOW_IN) { - curveRender_ = "Curves.FastOutSlowIn"; - } else if (curve_ == Curves::LINEAR_OUT_SLOW_IN) { - curveRender_ = "Curves.LinearOutSlowIn"; - } else if (curve_ == Curves::FAST_OUT_LINEAR_IN) { - curveRender_ = "Curves.FastOutLinearIn"; - } else if (curve_ == Curves::FRICTION) { - curveRender_ = "Curves.Friction"; - } else if (curve_ == Curves::EXTREME_DECELERATION) { - curveRender_ = "Curves.ExtremeDeceleration"; - } else if (curve_ == Curves::SHARP) { - curveRender_ = "Curves.Sharp"; - } else if (curve_ == Curves::SMOOTH) { - curveRender_ = "Curves.Smooth"; - } else if (curve_ == Curves::LINEAR) { - curveRender_ = "Curves.Linear"; - } + curveRender_ = Curves::ToString(curve_); } // Get item count of swiper diff --git a/frameworks/core/components_ng/base/BUILD.gn b/frameworks/core/components_ng/base/BUILD.gn index 1a7c36c0bd3..346971a8b7e 100644 --- a/frameworks/core/components_ng/base/BUILD.gn +++ b/frameworks/core/components_ng/base/BUILD.gn @@ -18,6 +18,7 @@ build_component_ng("base_ng") { sources = [ "frame_node.cpp", "geometry_node.cpp", + "inspector.cpp", "ui_node.cpp", "view_abstract.cpp", "view_stack_processor.cpp", diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index 2e861252db3..b336b2e0359 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -133,6 +133,12 @@ void FrameNode::DumpInfo() : "NA")); } +void FrameNode::ToJsonValue(std::unique_ptr& json) const +{ + ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty); + ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty); +} + void FrameNode::OnAttachToMainTree() { UINode::OnAttachToMainTree(); diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index b942fe286e7..cae6e0cc243 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -223,6 +223,8 @@ public: ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(InspectorId, std::string); void OnInspectorIdUpdate(const std::string& /*unused*/) {} + virtual void ToJsonValue(std::unique_ptr& json) const; + RefPtr GetAncestorNodeOfFrame() const; bool IsResponseRegion() const; diff --git a/frameworks/core/components_ng/base/inspector.cpp b/frameworks/core/components_ng/base/inspector.cpp new file mode 100644 index 00000000000..f6629e6075b --- /dev/null +++ b/frameworks/core/components_ng/base/inspector.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (c) 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. + */ + +#include "core/components_ng/base/inspector.h" + +#include "base/utils/utils.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { +namespace { +const char INSPECTOR_TYPE[] = "$type"; +const char INSPECTOR_ID[] = "$ID"; +const char INSPECTOR_RECT[] = "$rect"; +const char INSPECTOR_ATTRS[] = "$attrs"; +const char INSPECTOR_ROOT[] = "root"; +const char INSPECTOR_WIDTH[] = "width"; +const char INSPECTOR_HEIGHT[] = "height"; +const char INSPECTOR_RESOLUTION[] = "$resolution"; +const char INSPECTOR_CHILDREN[] = "$children"; + +const uint32_t LONG_PRESS_DELAY = 1000; + +RefPtr GetInspectorByKey(const RefPtr& root, const std::string& key) +{ + std::queue> elements; + elements.push(root); + RefPtr inspectorElement; + while (!elements.empty()) { + auto current = elements.front(); + elements.pop(); + inspectorElement = AceType::DynamicCast(current); + if (inspectorElement != nullptr && inspectorElement->HasInspectorId()) { + if (key == inspectorElement->GetInspectorIdValue()) { + return inspectorElement; + } + } + const auto& children = current->GetChildren(); + for (const auto& child : children) { + elements.push(child); + } + } + return nullptr; +} + +void DumpElementTree( + int32_t depth, const RefPtr& element, std::map>>& depthElementMap) +{ + if (element->GetChildren().empty()) { + return; + } + const auto& children = element->GetChildren(); + depthElementMap[depth].insert(depthElementMap[depth].end(), children.begin(), children.end()); + for (const auto& depthElement : children) { + DumpElementTree(depth + 1, depthElement, depthElementMap); + } +} + +TouchEvent GetUpPoint(const TouchEvent& downPoint) +{ + return { + .x = downPoint.x, .y = downPoint.y, .type = TouchType::UP, .time = std::chrono::high_resolution_clock::now() + }; +} +} // namespace + +std::string Inspector::GetInspectorNodeByKey(const std::string& key) +{ + auto context = NG::PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(context, ""); + auto rootNode = context->GetRootElement(); + CHECK_NULL_RETURN(rootNode, ""); + + auto inspectorElement = GetInspectorByKey(rootNode, key); + if (inspectorElement == nullptr) { + LOGE("no inspector with key:%{public}s is found", key.c_str()); + return ""; + } + + auto jsonNode = JsonUtil::Create(true); + jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str()); + jsonNode->Put(INSPECTOR_ID, inspectorElement->GetId()); + jsonNode->Put(INSPECTOR_RECT, inspectorElement->GetGeometryNode()->GetFrameRect().ToBounds().c_str()); + auto jsonAttrs = JsonUtil::Create(true); + inspectorElement->ToJsonValue(jsonAttrs); + jsonNode->Put(INSPECTOR_ATTRS, jsonAttrs); + return jsonNode->ToString(); +} + +std::string Inspector::GetInspectorTree() +{ + auto jsonRoot = JsonUtil::Create(true); + jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT); + + auto context = NG::PipelineContext::GetCurrentContext(); + if (!context) { + return jsonRoot->ToString(); + } + auto scale = context->GetViewScale(); + auto rootHeight = context->GetRootHeight(); + auto rootWidth = context->GetRootWidth(); + jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str()); + jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str()); + jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str()); + + auto root = context->GetRootElement(); + if (root == nullptr) { + return jsonRoot->ToString(); + } + + std::map>> depthElementMap; + depthElementMap[0].emplace_back(root); + DumpElementTree(1, root, depthElementMap); + + int32_t height = 0; + std::unordered_map, std::string>>> elementJSONInfoMap; + for (int depth = static_cast(depthElementMap.size()); depth > 0; depth--) { + const auto& depthElements = depthElementMap[depth]; + for (const auto& element : depthElements) { + auto inspectorElement = AceType::DynamicCast(element); + if (inspectorElement == nullptr) { + continue; + } + + auto jsonNode = JsonUtil::Create(false); + jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str()); + jsonNode->Put(INSPECTOR_ID, inspectorElement->GetId()); + jsonNode->Put(INSPECTOR_RECT, inspectorElement->GetGeometryNode()->GetFrameRect().ToBounds().c_str()); + auto jsonObject = JsonUtil::Create(false); + inspectorElement->ToJsonValue(jsonObject); + jsonNode->Put(INSPECTOR_ATTRS, jsonObject); + if (!element->GetChildren().empty()) { + if (height > 0) { + auto jsonNodeArray = JsonUtil::CreateArray(false); + auto childNodeJSONVec = elementJSONInfoMap[height - 1]; + for (auto& iter : childNodeJSONVec) { + auto parent = iter.first->GetParent(); + if (parent->GetId() == element->GetId()) { + auto childJSONValue = JsonUtil::ParseJsonString(iter.second); + jsonNodeArray->Put(childJSONValue); + } + } + if (jsonNodeArray->GetArraySize()) { + jsonNode->Put(INSPECTOR_CHILDREN, jsonNodeArray); + } + } + } + elementJSONInfoMap[height].emplace_back(element, jsonNode->ToString()); + } + if (elementJSONInfoMap.find(height) != elementJSONInfoMap.end()) { + height++; + } + } + + auto jsonChildren = JsonUtil::CreateArray(false); + auto firstDepthNodeVec = elementJSONInfoMap[elementJSONInfoMap.size() - 1]; + for (const auto& nodeJSONInfo : firstDepthNodeVec) { + auto nodeJSONValue = JsonUtil::ParseJsonString(nodeJSONInfo.second); + jsonChildren->Put(nodeJSONValue); + } + jsonRoot->Put(INSPECTOR_CHILDREN, jsonChildren); + return jsonRoot->ToString(); +} + +bool Inspector::SendEventByKey(const std::string& key, int action, const std::string& params) +{ + auto context = NG::PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(context, false); + auto rootNode = context->GetRootElement(); + CHECK_NULL_RETURN(rootNode, false); + + auto inspectorElement = GetInspectorByKey(rootNode, key); + if (inspectorElement == nullptr) { + LOGE("no inspector with key:%{public}s is found", key.c_str()); + return false; + } + + auto rect = inspectorElement->GetGeometryNode()->GetFrameRect(); + context->GetTaskExecutor()->PostTask( + [weak = AceType::WeakClaim(AceType::RawPtr(context)), rect, action, params]() { + auto context = weak.Upgrade(); + if (!context) { + return; + } + + TouchEvent point { .x = (rect.Left() + rect.Width() / 2), + .y = (rect.Top() + rect.Height() / 2), + .type = TouchType::DOWN, + .time = std::chrono::high_resolution_clock::now() }; + context->OnTouchEvent(point); + + switch (action) { + case static_cast(AceAction::ACTION_CLICK): { + context->OnTouchEvent(GetUpPoint(point)); + break; + } + case static_cast(AceAction::ACTION_LONG_CLICK): { + CancelableCallback inspectorTimer; + auto&& callback = [weak, point]() { + auto refPtr = weak.Upgrade(); + if (refPtr) { + refPtr->OnTouchEvent(GetUpPoint(point)); + } + }; + inspectorTimer.Reset(callback); + auto taskExecutor = + SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI); + taskExecutor.PostDelayedTask(inspectorTimer, LONG_PRESS_DELAY); + break; + } + default: + break; + } + }, + TaskExecutor::TaskType::UI); + + return true; +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/base/inspector.h b/frameworks/core/components_ng/base/inspector.h new file mode 100644 index 00000000000..e79b4f2f4cc --- /dev/null +++ b/frameworks/core/components_ng/base/inspector.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 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_CORE_COMPONENTS_NG_INSPECTOR_INSPECTOR_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_INSPECTOR_INSPECTOR_H + +#include "base/utils/macros.h" + +#include + +namespace OHOS::Ace::NG { +class ACE_EXPORT Inspector { +public: + static std::string GetInspectorNodeByKey(const std::string& key); + static std::string GetInspectorTree(); + static bool SendEventByKey(const std::string& key, int action, const std::string& params); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_INSPECTOR_INSPECTOR_H diff --git a/frameworks/core/components_ng/layout/layout_property.cpp b/frameworks/core/components_ng/layout/layout_property.cpp index 9d19c0b75d9..431992acb95 100644 --- a/frameworks/core/components_ng/layout/layout_property.cpp +++ b/frameworks/core/components_ng/layout/layout_property.cpp @@ -39,6 +39,14 @@ void LayoutProperty::Reset() CleanDirty(); } +void LayoutProperty::ToJsonValue(std::unique_ptr& json) const +{ + ACE_PROPERTY_TO_JSON_VALUE(calcLayoutConstraint_, MeasureProperty); + ACE_PROPERTY_TO_JSON_VALUE(positionProperty_, PositionProperty); + ACE_PROPERTY_TO_JSON_VALUE(magicItemProperty_, MagicItemProperty); + ACE_PROPERTY_TO_JSON_VALUE(flexItemProperty_, FlexItemProperty); +} + RefPtr LayoutProperty::Clone() const { auto layoutProperty = MakeRefPtr(); diff --git a/frameworks/core/components_ng/layout/layout_property.h b/frameworks/core/components_ng/layout/layout_property.h index 3d4263c20fe..169f97df7ab 100644 --- a/frameworks/core/components_ng/layout/layout_property.h +++ b/frameworks/core/components_ng/layout/layout_property.h @@ -52,6 +52,8 @@ public: virtual void Reset(); + virtual void ToJsonValue(std::unique_ptr& json) const; + const std::optional& GetLayoutConstraint() const { return layoutConstraint_; diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_property.h b/frameworks/core/components_ng/pattern/swiper/swiper_layout_property.h index 670e5b74232..d9055629496 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_property.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_property.h @@ -60,6 +60,20 @@ public: ResetShowIndicator(); } + void ToJsonValue(std::unique_ptr& json) const override + { + LayoutProperty::ToJsonValue(json); + json->Put("index", std::to_string(propIndex_.value_or(0)).c_str()); + json->Put("vertical", propDirection_.value_or(Axis::HORIZONTAL) == Axis::VERTICAL ? "true" : "false"); + json->Put("indicator", propShowIndicator_.value_or(true) ? "true" : "false"); + json->Put("itemSpace", propItemSpace_.value_or(Dimension(0, DimensionUnit::VP)).ToString().c_str()); + json->Put("cachedCount", propCachedCount_.value_or(1)); + json->Put("displayMode", propDisplayMode_.value_or(SwiperDisplayMode::STRETCH) == SwiperDisplayMode::AUTO_LINEAR + ? "SwiperDisplayMode.AutoLinear" + : "SwiperDisplayMode.Stretch"); + json->Put("displayCount", propDisplayCount_.value_or(1)); + } + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Direction, Axis, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(Index, int32_t, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ItemSpace, Dimension, PROPERTY_UPDATE_MEASURE); diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_paint_property.h b/frameworks/core/components_ng/pattern/swiper/swiper_paint_property.h index 24f479f2a55..3e74d83387d 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_paint_property.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_paint_property.h @@ -17,6 +17,7 @@ #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_PAINT_PROPERTY_H #include "core/animation/curve.h" +#include "core/animation/curves.h" #include "core/components/common/layout/constants.h" #include "core/components/common/properties/color.h" #include "core/components_ng/render/paint_property.h" @@ -28,6 +29,9 @@ struct SwiperAnimationStyle { ACE_DEFINE_PROPERTY_GROUP_ITEM(AutoPlayInterval, int32_t); ACE_DEFINE_PROPERTY_GROUP_ITEM(Duration, int32_t); ACE_DEFINE_PROPERTY_GROUP_ITEM(Curve, RefPtr); + + static const int32_t DEFAULT_INTERVAL = 3000; + static const int32_t DEFAULT_DURATION = 400; }; class SwiperPaintProperty : public PaintProperty { @@ -61,6 +65,22 @@ public: ResetFadeColor(); } + void ToJsonValue(std::unique_ptr& json) const override + { + PaintProperty::ToJsonValue(json); + + json->Put("autoPlay", GetAutoPlay().value_or(false) ? "true" : "false"); + json->Put( + "interval", std::to_string(GetAutoPlayInterval().value_or(SwiperAnimationStyle::DEFAULT_INTERVAL)).c_str()); + json->Put("loop", GetLoop().value_or(true) ? "true" : "false"); + json->Put("duration", std::to_string(GetDuration().value_or(SwiperAnimationStyle::DEFAULT_DURATION)).c_str()); + json->Put("disableSwipe", GetDisableSwipe().value_or(false) ? "true" : "false"); + static const char* EDGE_EFFECT[] = { "EdgeEffect.Spring", "EdgeEffect.Fade", "EdgeEffect.None" }; + json->Put("effectMode", EDGE_EFFECT[static_cast(GetEdgeEffect().value_or(EdgeEffect::SPRING))]); + json->Put("curve", + GetCurve().has_value() ? Curves::ToString(GetCurve().value()).c_str() : Curves::DEFAULT_CURVE_NAME.c_str()); + } + ACE_DEFINE_PROPERTY_GROUP(SwiperAnimationStyle, SwiperAnimationStyle); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(SwiperAnimationStyle, AutoPlay, bool, PROPERTY_UPDATE_RENDER); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(SwiperAnimationStyle, AutoPlayInterval, int32_t, PROPERTY_UPDATE_RENDER); diff --git a/frameworks/core/components_ng/property/flex_property.h b/frameworks/core/components_ng/property/flex_property.h index f2efc3aa851..4226da23a5f 100644 --- a/frameworks/core/components_ng/property/flex_property.h +++ b/frameworks/core/components_ng/property/flex_property.h @@ -29,6 +29,16 @@ struct FlexItemProperty { ACE_DEFINE_PROPERTY_GROUP_ITEM(AlignSelf, FlexAlign); ACE_DEFINE_PROPERTY_GROUP_ITEM(FlexBasis, CalcLength); ACE_DEFINE_PROPERTY_GROUP_ITEM(DisplayIndex, int32_t); + + void ToJsonValue(std::unique_ptr& json) const + { + static const char* ITEM_ALIGN[] = { "ItemAlign.Auto", "ItemAlign.Start", "ItemAlign.Center", "ItemAlign.End", + "ItemAlign.Stretch", "ItemAlign.Baseline" }; + json->Put("flexBasis", propFlexBasis.has_value() ? propFlexBasis.value().ToString().c_str() : "auto"); + json->Put("flexGrow", propFlexGrow.value_or(0.0)); + json->Put("flexShrink", propFlexShrink.value_or(1)); + json->Put("alignSelf", ITEM_ALIGN[static_cast(propAlignSelf.value_or(FlexAlign::AUTO))]); + } }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/property/magic_layout_property.h b/frameworks/core/components_ng/property/magic_layout_property.h index e2b9256b46a..fcd9a99527f 100644 --- a/frameworks/core/components_ng/property/magic_layout_property.h +++ b/frameworks/core/components_ng/property/magic_layout_property.h @@ -27,6 +27,13 @@ struct MagicItemProperty { ACE_DEFINE_PROPERTY_GROUP_ITEM(LayoutWeight, float); ACE_DEFINE_PROPERTY_GROUP_ITEM(AspectRatio, float); ACE_DEFINE_PROPERTY_GROUP_ITEM(DisplayPriority, int32_t); + + void ToJsonValue(std::unique_ptr& json) const + { + json->Put("layoutWeight", propLayoutWeight.value_or(0)); + json->Put("aspectRatio", propAspectRatio.value_or(0.0)); + json->Put("displayPriority", propDisplayPriority.value_or(1)); + } }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/property/measure_property.h b/frameworks/core/components_ng/property/measure_property.h index 43204825dfd..cb314fec91f 100644 --- a/frameworks/core/components_ng/property/measure_property.h +++ b/frameworks/core/components_ng/property/measure_property.h @@ -182,6 +182,42 @@ struct MeasureProperty { str.append("selfIdealSize: [").append(selfIdealSize.has_value() ? selfIdealSize->ToString() : "NA").append("]"); return str; } + + void ToJsonValue(std::unique_ptr& json) const + { + std::string width = + selfIdealSize.has_value() + ? (selfIdealSize.value().Width().has_value() ? selfIdealSize.value().Width().value().ToString() : "-") + : "-"; + std::string height = + selfIdealSize.has_value() + ? (selfIdealSize.value().Height().has_value() ? selfIdealSize.value().Height().value().ToString() : "-") + : "-"; + json->Put("width", width.c_str()); + json->Put("height", height.c_str()); + + auto jsonSize = JsonUtil::Create(true); + jsonSize->Put("width", width.c_str()); + jsonSize->Put("height", height.c_str()); + json->Put("size", jsonSize); + + auto jsonConstraintSize = JsonUtil::Create(true); + jsonConstraintSize->Put("minWidth", + minSize.value_or(CalcSize()).Width().value_or(CalcLength(0, DimensionUnit::VP)).ToString().c_str()); + jsonConstraintSize->Put("minHeight", + minSize.value_or(CalcSize()).Height().value_or(CalcLength(0, DimensionUnit::VP)).ToString().c_str()); + jsonConstraintSize->Put("maxWidth", maxSize.value_or(CalcSize()) + .Width() + .value_or(CalcLength(Infinity(), DimensionUnit::VP)) + .ToString() + .c_str()); + jsonConstraintSize->Put("maxHeight", maxSize.value_or(CalcSize()) + .Height() + .value_or(CalcLength(Infinity(), DimensionUnit::VP)) + .ToString() + .c_str()); + json->Put("constraintSize", jsonConstraintSize->ToString().c_str()); + } }; template diff --git a/frameworks/core/components_ng/property/position_property.h b/frameworks/core/components_ng/property/position_property.h index 53c23147717..0d08d5ad0b5 100644 --- a/frameworks/core/components_ng/property/position_property.h +++ b/frameworks/core/components_ng/property/position_property.h @@ -22,6 +22,11 @@ namespace OHOS::Ace::NG { struct PositionProperty { ACE_DEFINE_PROPERTY_GROUP_ITEM(Alignment, Alignment); + + void ToJsonValue(std::unique_ptr& json) const + { + json->Put("align", propAlignment.value_or(Alignment::CENTER).GetAlignmentStr(TextDirection::LTR).c_str()); + } }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/property/property.h b/frameworks/core/components_ng/property/property.h index 71af31dd14e..4eeac9adeb0 100644 --- a/frameworks/core/components_ng/property/property.h +++ b/frameworks/core/components_ng/property/property.h @@ -168,7 +168,7 @@ public: \ #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \ public: \ - const std::optional& Get##name() \ + const std::optional& Get##name() const \ { \ return prop##name##_; \ } \ @@ -272,6 +272,16 @@ public: \ return NearEqual(prop##name.value(), value); \ } +#define ACE_PROPERTY_TO_JSON_VALUE(target, type) \ + do { \ + if (target) { \ + (target)->ToJsonValue(json); \ + } else { \ + type p; \ + p.ToJsonValue(json); \ + } \ + } while (false) + class ACE_EXPORT Property : public virtual AceType { DECLARE_ACE_TYPE(Property, AceType); diff --git a/frameworks/core/components_ng/render/paint_property.h b/frameworks/core/components_ng/render/paint_property.h index 468eaf4f19f..4fe3ded310a 100644 --- a/frameworks/core/components_ng/render/paint_property.h +++ b/frameworks/core/components_ng/render/paint_property.h @@ -39,6 +39,8 @@ public: virtual void Reset() {} + virtual void ToJsonValue(std::unique_ptr& json) const {} + protected: void UpdatePaintProperty(const PaintProperty* renderProperty) {} diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index c9725936862..76757233dbd 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -409,6 +409,7 @@ bool PipelineContext::OnDumpInfo(const std::vector& params) const } else if (params[0] == "-multimodal") { #endif } else if (params[0] == "-accessibility" || params[0] == "-inspector") { + rootNode_->DumpTree(0); } else if (params[0] == "-rotation" && params.size() >= 2) { } else if (params[0] == "-animationscale" && params.size() >= 2) { } else if (params[0] == "-velocityscale" && params.size() >= 2) { diff --git a/frameworks/core/pipeline_ng/pipeline_context.h b/frameworks/core/pipeline_ng/pipeline_context.h index 6cb87246680..ad17bcfe6a6 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.h +++ b/frameworks/core/pipeline_ng/pipeline_context.h @@ -49,6 +49,11 @@ public: void SetupRootElement() override; + const RefPtr& GetRootElement() const + { + return rootNode_; + } + void AddKeyFrame(float fraction, const RefPtr& curve, const std::function& propertyCallback) override {} -- Gitee