From 533b75b25f3ed1db96120bc4b30f9cdcfe280d59 Mon Sep 17 00:00:00 2001 From: yu-shihao4 Date: Mon, 29 Aug 2022 16:43:55 +0800 Subject: [PATCH 01/35] =?UTF-8?q?=E3=80=90web=E3=80=91=E6=B8=85=E7=90=86gn?= =?UTF-8?q?=E5=86=97=E4=BD=99=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yu-shihao4 --- frameworks/core/components/web/BUILD.gn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frameworks/core/components/web/BUILD.gn b/frameworks/core/components/web/BUILD.gn index 53ff0137b89..f20b2621ae3 100644 --- a/frameworks/core/components/web/BUILD.gn +++ b/frameworks/core/components/web/BUILD.gn @@ -20,6 +20,9 @@ if (is_standard_system) { "$ability_runtime_path/interfaces/kits/native/appkit/app", "//commonlibrary/c_utils/base/include", "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/graphic/graphic_2d/utils/buffer_handle/export", + "//foundation/multimedia/image_standard/interfaces/innerkits/include", ] } } From d18fdb8faf583824136e907c8a799b241a125fef Mon Sep 17 00:00:00 2001 From: yu-shihao4 Date: Mon, 29 Aug 2022 19:13:32 +0800 Subject: [PATCH 02/35] =?UTF-8?q?gn=E5=86=97=E4=BD=99=20text=5Foveray?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yu-shihao4 --- frameworks/core/components/text_overlay/BUILD.gn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frameworks/core/components/text_overlay/BUILD.gn b/frameworks/core/components/text_overlay/BUILD.gn index bfc2e6df6ee..c26b0ffc377 100755 --- a/frameworks/core/components/text_overlay/BUILD.gn +++ b/frameworks/core/components/text_overlay/BUILD.gn @@ -20,6 +20,9 @@ config("ohos_text_overlay_web_config") { "$ability_runtime_path/interfaces/kits/native/appkit/app", "//utils/native/base/include", "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/graphic/graphic_2d/utils/buffer_handle/export", + "//foundation/multimedia/image_standard/interfaces/innerkits/include", ] } From e023baa77bfc130759d91ddea29e432d3d5f5b0f Mon Sep 17 00:00:00 2001 From: zhoutianer Date: Sun, 28 Aug 2022 17:58:08 +0800 Subject: [PATCH 03/35] fix keyboard auto-hiding in list Signed-off-by: zhoutianer Change-Id: Iad6f6087e7753efb7482a6de5196545c2ffe2e9b modified: frameworks/core/components/scroll/scroll_element.cpp modified: frameworks/core/components_v2/list/render_list.cpp modified: frameworks/core/components_v2/list/render_list.h Change-Id: I700468fb777a917023a60cc6fcf943ee50428fa4 --- .../core/components/scroll/scroll_element.cpp | 4 ++-- .../core/components_v2/list/render_list.cpp | 20 +++++++++++++++++++ .../core/components_v2/list/render_list.h | 3 +++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/frameworks/core/components/scroll/scroll_element.cpp b/frameworks/core/components/scroll/scroll_element.cpp index e245afc6ea9..f00e420c484 100644 --- a/frameworks/core/components/scroll/scroll_element.cpp +++ b/frameworks/core/components/scroll/scroll_element.cpp @@ -38,8 +38,8 @@ void ScrollElement::OnMount() { auto context = context_.Upgrade(); if (context && context->GetTextFieldManager() && context->GetLastPage()) { - auto textFeildManager = context->GetTextFieldManager(); - textFeildManager->SetScrollElement(context->GetLastPage()->GetPageId(), WeakClaim(this)); + auto textFieldManager = context->GetTextFieldManager(); + textFieldManager->SetScrollElement(context->GetLastPage()->GetPageId(), WeakClaim(this)); } } diff --git a/frameworks/core/components_v2/list/render_list.cpp b/frameworks/core/components_v2/list/render_list.cpp index 0d44f6885b7..db46c3cd8d8 100644 --- a/frameworks/core/components_v2/list/render_list.cpp +++ b/frameworks/core/components_v2/list/render_list.cpp @@ -21,6 +21,7 @@ #include "base/utils/string_utils.h" #include "base/utils/utils.h" #include "core/animation/bilateral_spring_node.h" +#include "core/common/text_field_manager.h" #include "core/components/scroll/render_scroll.h" #include "core/components/scroll/render_single_child_scroll.h" #include "core/components/scroll/scroll_spring_effect.h" @@ -1243,6 +1244,7 @@ double RenderList::ApplyLayoutParam() startMainPos_ = (1.0 - VIEW_PORT_SCALE) / 2 * maxMainSize; endMainPos_ = startMainPos_ + (maxMainSize * VIEW_PORT_SCALE); fixedMainSizeByLayoutParam_ = NearEqual(maxMainSize, GetMainSize(GetLayoutParam().GetMinSize())); + SizeChangeOffset(maxMainSize); } fixedCrossSize_ = !NearEqual(GetCrossSize(maxLayoutSize), Size::INFINITE_SIZE); @@ -3031,4 +3033,22 @@ void RenderList::AddChildItem(RefPtr child) AddChild(renderNode); } +void RenderList::SizeChangeOffset(double newWindowHeight) +{ + auto context = context_.Upgrade(); + if (!context) { + return; + } + auto textFieldManager = AceType::DynamicCast(context->GetTextFieldManager()); + // only need to offset vertical lists + if (textFieldManager && vertical_) { + auto position = textFieldManager->GetClickPosition().GetY(); + double offset = newWindowHeight - position; + if (LessOrEqual(offset, 0.0)) { + // negative offset to scroll down + currentOffset_ += offset; + } + } +} + } // namespace OHOS::Ace::V2 diff --git a/frameworks/core/components_v2/list/render_list.h b/frameworks/core/components_v2/list/render_list.h index eb8bf561947..3317a78a4f8 100644 --- a/frameworks/core/components_v2/list/render_list.h +++ b/frameworks/core/components_v2/list/render_list.h @@ -479,6 +479,9 @@ private: void ApplyRestoreInfo(); void InitScrollable(Axis axis); + // when window size change, add offset to keep clicked textfield in display area + void SizeChangeOffset(double newWindowHeight); + bool hasDragItem_ = false; std::map listEventFlags_; From 0d95cd7db304bf470158faaf459d9d9717e1794f Mon Sep 17 00:00:00 2001 From: Guido Grassel Date: Tue, 23 Aug 2022 09:37:55 +0200 Subject: [PATCH 04/35] rerender optimisation, new event viewPropertyHasChanged(varNane, effectedElmtIds) Signed-off-by: Guido Grassel Change-Id: I45b30e871f53c75c3ac99d4656d5f18e6eff3edf --- .../declarative_frontend/engine/stateMgmt.js | 80 ++++++++++++------- .../src/lib/common/i_property_subscriber.ts | 6 ++ .../src/lib/common/local_storage.ts | 2 +- .../pu_observed_property_abstract.ts | 47 +++++------ .../src/lib/partial_update/pu_view.ts | 43 ++++++---- 5 files changed, 108 insertions(+), 70 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/engine/stateMgmt.js b/frameworks/bridge/declarative_frontend/engine/stateMgmt.js index 0ed65e4a93c..9fb1e625781 100644 --- a/frameworks/bridge/declarative_frontend/engine/stateMgmt.js +++ b/frameworks/bridge/declarative_frontend/engine/stateMgmt.js @@ -2264,20 +2264,39 @@ class View extends NativeViewFullUpdate { class ObservedPropertyAbstractPU extends ObservedPropertyAbstract { constructor(subscribingView, viewName) { super(subscribingView, viewName); - this.markDependentElementsIsPending = false; this.dependentElementIds_ = new Set(); } notifyHasChanged(newValue) { - super.notifyHasChanged(newValue); - // for properties owned by a View" - // markDependentElementsDirty needs to be executed - this.markDependentElementsIsPending = true; + + var registry = SubscriberManager.Get(); + this.subscribers_.forEach((subscribedId) => { + var subscriber = registry.get(subscribedId); + if (subscriber) { + if ('hasChanged' in subscriber) { + subscriber.hasChanged(newValue); + } + if ('viewPropertyHasChanged' in subscriber) { + subscriber.viewPropertyHasChanged(this.info_, this.dependentElementIds_); + } + else if ('propertyHasChanged' in subscriber) { + subscriber.propertyHasChanged(this.info_); + } + } + else { + console.error(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged: unknown subscriber ID '${subscribedId}' error!`); + } + }); } notifyPropertyRead() { super.notifyPropertyRead(); this.recordDependentUpdate(); } - // FIXME unification: method needed, what callses to create here? + markDependentElementsDirty(view) { + // TODO ace-ets2bundle, framework, compilated apps need to update together + // this function will be removed after a short transiition periode + console.error(`markDependentElementsDirty no longer supported. + Please update your ace-ets2bundle and recompile your application!`); + } /** * factory function for concrete 'object' or 'simple' ObservedProperty object * depending if value is Class object @@ -2305,19 +2324,6 @@ class ObservedPropertyAbstractPU extends ObservedPropertyAbstract { this.dependentElementIds_.add(elmtId); } - markDependentElementsDirty(view) { - if (!this.markDependentElementsIsPending) { - return; - } - if (this.dependentElementIds_.size > 0) { - - this.dependentElementIds_.forEach(elmtId => { - view.markElemenDirtyById(elmtId); - - }); - } - this.markDependentElementsIsPending = false; - } purgeDependencyOnElmtId(rmElmtId) { this.dependentElementIds_.delete(rmElmtId); @@ -2851,7 +2857,8 @@ class ViewPU extends NativeViewPartialUpdate { constructor(parent, localStorage) { super(); this.watchedProps = new Map(); - // elmtIds of components/elements with this custom component that need partial update + // Set of dependent elmtIds that need partial update + // during next re-render this.dirtDescendantElementIds_ = new Set(); // registry of update functions // the key is the elementId of the Component/Element that's the result of this function @@ -2907,18 +2914,26 @@ class ViewPU extends NativeViewPartialUpdate { this.initialRender(); } // implements IMultiPropertiesChangeSubscriber - propertyHasChanged(info) { - if (info) { + viewPropertyHasChanged(varName, dependentElmtIds) { + + this.syncInstanceId(); + let cb = this.watchedProps.get(varName); + if (cb) { - this.syncInstanceId(); - this.markNeedUpdate(); - let cb = this.watchedProps.get(info); - if (cb) { - - cb.call(this, info); + cb.call(this, varName); + } + if (dependentElmtIds.size) { + if (!this.dirtDescendantElementIds_.size) { + // mark Composedelement dirty when first elmtIds are added + // do not need to do this every time + this.markNeedUpdate(); } - this.restoreInstanceId(); - } // if info avail. + + const union = new Set([...this.dirtDescendantElementIds_, ...dependentElmtIds]); + this.dirtDescendantElementIds_ = union; + + } + this.restoreInstanceId(); } /** * Function to be called from the constructor of the sub component @@ -2971,7 +2986,10 @@ class ViewPU extends NativeViewPartialUpdate { * @param elmtId */ markElemenDirtyById(elmtId) { - this.dirtDescendantElementIds_.add(elmtId); // add to set of dirty element ids if not already included + // TODO ace-ets2bundle, framework, compilated apps need to update together + // this function will be removed after a short transiition periode + console.error(`markElemenDirtyById no longer supported. + Please update your ace-ets2bundle and recompile your application!`); } /** * For each recorded dirty Element in this custom component diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/i_property_subscriber.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/i_property_subscriber.ts index 241c4b050ba..43cf1d92656 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/i_property_subscriber.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/i_property_subscriber.ts @@ -47,3 +47,9 @@ interface IMultiPropertiesReadSubscriber extends IPropertySubscriber { // Note: a Property's PropertyInfo can be undefined. propertyRead(info?: PropertyInfo): void; } + +interface IViewPropertiesChangeSubscriber extends IPropertySubscriber { + // ViewPU get informed when View variable has changed + // informs the elmtIds that need update upon variable change + viewPropertyHasChanged(varName: PropertyInfo, dependentElmtIds: Set): void ; +} diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/local_storage.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/local_storage.ts index 602e93ef43e..c223fbb6004 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/local_storage.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/local_storage.ts @@ -48,7 +48,7 @@ class LocalStorage extends NativeLocalStorage { * @param initializingProperties */ public initializeProps(initializingProperties: Object = {}) { - console.log(`${this.constructor.name} initializing with Object: ${JSON.stringify(initializingProperties)} .`) + console.debug(`${this.constructor.name} initializing with Object keys: [${Object.keys(initializingProperties)}].`) this.storage_.clear(); Object.keys(initializingProperties).filter((propName) => initializingProperties[propName] != undefined).forEach((propName) => this.addNewPropertyInternal(propName, initializingProperties[propName]) diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts index 2a9d72eacac..7c1866e88fb 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_observed_property_abstract.ts @@ -15,7 +15,6 @@ abstract class ObservedPropertyAbstractPU extends ObservedPropertyAbstract { - private markDependentElementsIsPending: boolean = false; private dependentElementIds_: Set = new Set(); constructor(subscribingView: IPropertySubscriber, viewName: PropertyInfo) { @@ -23,11 +22,23 @@ abstract class ObservedPropertyAbstractPU extends ObservedPropertyAbstract } protected notifyHasChanged(newValue: T) { - super.notifyHasChanged(newValue); - - // for properties owned by a View" - // markDependentElementsDirty needs to be executed - this.markDependentElementsIsPending = true; + console.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged, notifying.`); + var registry: IPropertySubscriberLookup = SubscriberManager.Get(); + this.subscribers_.forEach((subscribedId) => { + var subscriber: IPropertySubscriber = registry!.get(subscribedId) + if (subscriber) { + if ('hasChanged' in subscriber) { + (subscriber as ISinglePropertyChangeSubscriber).hasChanged(newValue); + } + if ('viewPropertyHasChanged' in subscriber) { + (subscriber as ViewPU).viewPropertyHasChanged(this.info_, this.dependentElementIds_); + } else if ('propertyHasChanged' in subscriber) { + (subscriber as IMultiPropertiesChangeSubscriber).propertyHasChanged(this.info_); + } + } else { + console.error(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']: notifyHasChanged: unknown subscriber ID '${subscribedId}' error!`); + } + }); } protected notifyPropertyRead() { @@ -35,9 +46,12 @@ abstract class ObservedPropertyAbstractPU extends ObservedPropertyAbstract this.recordDependentUpdate(); } - - - // FIXME unification: method needed, what callses to create here? + public markDependentElementsDirty(view: ViewPU) { + // TODO ace-ets2bundle, framework, compilated apps need to update together + // this function will be removed after a short transiition periode + console.error(`markDependentElementsDirty no longer supported. + Please update your ace-ets2bundle and recompile your application!`); + } /** * factory function for concrete 'object' or 'simple' ObservedProperty object @@ -70,20 +84,7 @@ abstract class ObservedPropertyAbstractPU extends ObservedPropertyAbstract this.dependentElementIds_.add(elmtId); } - public markDependentElementsDirty(view: ViewPU) { - if (!this.markDependentElementsIsPending) { - return; - } - if (this.dependentElementIds_.size > 0) { - console.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']:markDependentElementsDirty`); - this.dependentElementIds_.forEach(elmtId => { - view.markElemenDirtyById(elmtId) - console.debug(` - elmtId ${elmtId}.`); - }); - } - this.markDependentElementsIsPending = false; - } - + public purgeDependencyOnElmtId(rmElmtId: number): void { console.debug(`ObservedPropertyAbstract[${this.id__()}, '${this.info() || "unknown"}']:purgeDependencyOnElmtId ${rmElmtId}`); this.dependentElementIds_.delete(rmElmtId); diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_view.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_view.ts index 0e0cb484cd6..2280b01ca30 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_view.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_view.ts @@ -24,8 +24,8 @@ type UpdateFunc = (elmtId: number, isFirstRender: boolean) => void; // Nativeview // implemented in C++ for release // and in utest/view_native_mock.ts for testing -abstract class ViewPU extends NativeViewPartialUpdate implements - IMultiPropertiesChangeSubscriber { +abstract class ViewPU extends NativeViewPartialUpdate + implements IViewPropertiesChangeSubscriber { private id_: number; @@ -35,7 +35,8 @@ abstract class ViewPU extends NativeViewPartialUpdate implements // @Provide'd variables by this class and its ancestors protected providedVars_: ProvidedVarsMapPU; - // elmtIds of components/elements with this custom component that need partial update + // Set of dependent elmtIds that need partial update + // during next re-render protected dirtDescendantElementIds_: Set = new Set(); @@ -129,19 +130,28 @@ abstract class ViewPU extends NativeViewPartialUpdate implements } // implements IMultiPropertiesChangeSubscriber - propertyHasChanged(info?: PropertyInfo): void { - if (info) { - console.debug(`${this.constructor.name}: propertyHasChanged ['${info || "unknowm"}']. View needs update`); - this.syncInstanceId(); - this.markNeedUpdate(); + viewPropertyHasChanged(varName: PropertyInfo, dependentElmtIds: Set): void { + console.debug(`${this.constructor.name}: viewPropertyHasChanged property '${varName}'. View needs ${dependentElmtIds.size ? 'update' : 'no update'}.`); + this.syncInstanceId(); - let cb = this.watchedProps.get(info) - if (cb) { - console.debug(`${this.constructor.name}: propertyHasChanged ['${info || "unknowm"}']. calling @Watch function`); - cb.call(this, info); + let cb = this.watchedProps.get(varName) + if (cb) { + console.debug(` .. calling @Watch function`); + cb.call(this, varName); + } + + if (dependentElmtIds.size) { + if (!this.dirtDescendantElementIds_.size) { + // mark Composedelement dirty when first elmtIds are added + // do not need to do this every time + this.markNeedUpdate(); } - this.restoreInstanceId(); - } // if info avail. + console.debug(`${this.constructor.name}: viewPropertyHasChanged property '${varName}': elmtIds affected by value change [${Array.from(dependentElmtIds).toString()}].`) + const union: Set = new Set([...this.dirtDescendantElementIds_, ...dependentElmtIds]); + this.dirtDescendantElementIds_ = union; + console.debug(`${this.constructor.name}: viewPropertyHasChanged property '${varName}': all elmtIds need update [${Array.from(this.dirtDescendantElementIds_).toString()}].`) + } + this.restoreInstanceId(); } /** @@ -202,7 +212,10 @@ abstract class ViewPU extends NativeViewPartialUpdate implements * @param elmtId */ public markElemenDirtyById(elmtId: number): void { - this.dirtDescendantElementIds_.add(elmtId) // add to set of dirty element ids if not already included + // TODO ace-ets2bundle, framework, compilated apps need to update together + // this function will be removed after a short transiition periode + console.error(`markElemenDirtyById no longer supported. + Please update your ace-ets2bundle and recompile your application!`); } /** From 5ad051f196f7b27a4e555fb10b6e8b3fa4c3d989 Mon Sep 17 00:00:00 2001 From: yan-shuifeng Date: Wed, 31 Aug 2022 22:21:53 +0800 Subject: [PATCH 05/35] fix the problem of LazyReload without LazyForEach case Signed-off-by: yan-shuifeng Change-Id: Ib76c9dbb87e53ad5ed7f921e589ceceb4b322e5f --- .../core/components_ng/base/frame_node.cpp | 9 ++++++--- .../core/components_ng/base/frame_node.h | 12 +++++++----- .../components_ng/layout/layout_wrapper.h | 11 +++++++++++ .../pattern/custom/custom_node_pattern.cpp | 12 +++++++----- .../pattern/custom/custom_node_pattern.h | 9 ++++----- .../pattern/list/list_layout_algorithm.cpp | 19 ++++++++++++------- .../swiper/swiper_layout_algorithm.cpp | 10 ++++++++-- 7 files changed, 55 insertions(+), 27 deletions(-) diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index 6c3b6d6757f..4c15c86c4f1 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -141,8 +141,10 @@ void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr& CHECK_NULL_VOID(dirty); if (dirty->IsActive()) { pattern_->OnActive(); + isActive_ = true; } else { pattern_->OnInActive(); + isActive_ = false; } auto layoutAlgorithmWrapper = DynamicCast(dirty->GetLayoutAlgorithm()); CHECK_NULL_VOID(layoutAlgorithmWrapper); @@ -151,7 +153,7 @@ void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr& if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) { MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER); } - if (needSyncRenderTree_) { + if (needSyncRenderTree_ || dirty->IsForceSyncRenderTree()) { RebuildRenderContextTree(dirty->GetChildrenInRenderArea()); needSyncRenderTree_ = false; } @@ -289,9 +291,10 @@ RefPtr FrameNode::CreateLayoutWrapper(bool forceMeasure, bool for auto flag = layoutProperty_->GetPropertyChangeFlag(); auto layoutWrapper = MakeRefPtr(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone()); do { - if (CheckMeasureFlag(flag) || CheckRequestNewChildNodeFlag(flag) || forceMeasure) { + // when inactive node need to reactive in render tree, need to measure again. + if (CheckMeasureFlag(flag) || CheckRequestNewChildNodeFlag(flag) || forceMeasure || !isActive_) { layoutWrapper->SetLayoutAlgorithm(MakeRefPtr(pattern_->CreateLayoutAlgorithm())); - bool forceChildMeasure = CheckMeasureFlag(flag) || forceMeasure; + bool forceChildMeasure = CheckMeasureFlag(flag) || forceMeasure || !isActive_; UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false); break; } diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index c6a67d35235..76c61637fda 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -149,6 +149,11 @@ public: bool IsAtomicNode() const override; + void MarkNeedSyncRenderTree() override + { + needSyncRenderTree_ = true; + } + private: RefPtr GetAncestorNodeOfFrame() const; @@ -166,11 +171,6 @@ private: RefPtr CreatePaintWrapper(); - void MarkNeedSyncRenderTree() override - { - needSyncRenderTree_ = true; - } - void RebuildRenderContextTree(const std::list>& children); bool IsMeasureBoundary(); @@ -199,6 +199,8 @@ private: bool isMeasureBoundary_ = false; bool hasPendingRequest_ = false; + bool isActive_ = false; + friend class RosenRenderContext; friend class RenderContext; friend class Pattern; diff --git a/frameworks/core/components_ng/layout/layout_wrapper.h b/frameworks/core/components_ng/layout/layout_wrapper.h index 1f505e3259d..046ad7ba624 100644 --- a/frameworks/core/components_ng/layout/layout_wrapper.h +++ b/frameworks/core/components_ng/layout/layout_wrapper.h @@ -160,6 +160,16 @@ public: void MountToHostOnMainThread(); void SwapDirtyLayoutWrapperOnMainThread(); + bool IsForceSyncRenderTree() const + { + return needForceSyncRenderTree_; + } + + void SetForceSyncRenderTree() + { + needForceSyncRenderTree_ = true; + } + private: // Used to save a persist wrapper created by child, ifElse, ForEach, the map stores [index, Wrapper]. // The Wrapper Created by LazyForEach stores in the LayoutWrapperBuilder object. @@ -174,6 +184,7 @@ private: int32_t currentChildCount_ = 0; bool isContraintNoChanged_ = false; bool isActive_ = false; + bool needForceSyncRenderTree_ = false; ACE_DISALLOW_COPY_AND_MOVE(LayoutWrapper); }; diff --git a/frameworks/core/components_ng/pattern/custom/custom_node_pattern.cpp b/frameworks/core/components_ng/pattern/custom/custom_node_pattern.cpp index 9613b823ffa..87647a6d78b 100644 --- a/frameworks/core/components_ng/pattern/custom/custom_node_pattern.cpp +++ b/frameworks/core/components_ng/pattern/custom/custom_node_pattern.cpp @@ -15,6 +15,8 @@ #include "core/components_ng/pattern/custom/custom_node_pattern.h" +#include "base/utils/utils.h" + namespace OHOS::Ace::NG { bool CustomNodePattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) @@ -24,11 +26,11 @@ bool CustomNodePattern::OnDirtyLayoutWrapperSwap(const RefPtr& di CHECK_NULL_RETURN(host, false); auto customNodeLayoutAlgorithm = DynamicCast(dirty->GetLayoutAlgorithm()->GetLayoutAlgorithm()); - if (customNodeLayoutAlgorithm) { - auto uiNode = customNodeLayoutAlgorithm->MoveBuildItem(); - if (uiNode) { - uiNode->MountToParent(host); - } + CHECK_NULL_RETURN(customNodeLayoutAlgorithm, false); + auto uiNode = customNodeLayoutAlgorithm->MoveBuildItem(); + if (uiNode) { + uiNode->MountToParent(host); + renderFunction_ = nullptr; } return false; } diff --git a/frameworks/core/components_ng/pattern/custom/custom_node_pattern.h b/frameworks/core/components_ng/pattern/custom/custom_node_pattern.h index a2e1bf4d710..966f396a06d 100644 --- a/frameworks/core/components_ng/pattern/custom/custom_node_pattern.h +++ b/frameworks/core/components_ng/pattern/custom/custom_node_pattern.h @@ -18,6 +18,7 @@ #include "base/utils/noncopyable.h" #include "core/components_ng/base/frame_node.h" +#include "core/components_ng/layout/box_layout_algorithm.h" #include "core/components_ng/pattern/custom/custom_node_layout_algorithm.h" #include "core/components_ng/pattern/pattern.h" @@ -32,11 +33,10 @@ public: RefPtr CreateLayoutAlgorithm() override { - if (isBuildDone_) { - return MakeRefPtr(nullptr); + if (renderFunction_) { + return MakeRefPtr(renderFunction_); } - isBuildDone_ = true; - return MakeRefPtr(renderFunction_); + return MakeRefPtr(); } void SetRenderFunction(const RenderFunction& renderFunction) @@ -48,7 +48,6 @@ public: private: RenderFunction renderFunction_; - bool isBuildDone_ = false; ACE_DISALLOW_COPY_AND_MOVE(CustomNodePattern); }; diff --git a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp index 7fbc7db719e..051faa75357 100644 --- a/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/list/list_layout_algorithm.cpp @@ -23,6 +23,7 @@ #include "base/log/ace_trace.h" #include "base/utils/utils.h" #include "core/components/common/layout/layout_param.h" +#include "core/components_ng/base/frame_node.h" #include "core/components_ng/pattern/list/list_layout_property.h" #include "core/components_ng/property/layout_constraint.h" #include "core/components_ng/property/measure_property.h" @@ -89,8 +90,8 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) spaceWidth_ = ConvertToPx(space, listLayoutProperty->GetLayoutConstraint()->scaleProperty, mainSize).value_or(0); if (listLayoutProperty->GetDivider().has_value()) { auto divider = listLayoutProperty->GetDivider().value(); - std::optional dividerSpace = ConvertToPx(divider.strokeWidth, - listLayoutProperty->GetLayoutConstraint()->scaleProperty, mainSize); + std::optional dividerSpace = + ConvertToPx(divider.strokeWidth, listLayoutProperty->GetLayoutConstraint()->scaleProperty, mainSize); if (dividerSpace.has_value()) { spaceWidth_ = std::max(spaceWidth_, dividerSpace.value()); } @@ -130,6 +131,12 @@ void ListLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) LOGD("new start index is %{public}d, new end index is %{public}d, offset is %{public}f", startIndex_.value(), endIndex_.value(), currentOffset_); + + // TODO: need to find better way to sync render tree. + // if index changed, need mark frame node to force sync render tree. + if ((preStartIndex_ != startIndex_.value()) || (preEndIndex_ != endIndex_.value())) { + layoutWrapper->SetForceSyncRenderTree(); + } } void ListLayoutAlgorithm::LayoutForward( @@ -302,7 +309,7 @@ void ListLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); // layout items. - for (auto index = startIndex_.value(); index <= endIndex_.value(); ++index) { + for (auto index = startIndex_.value_or(preStartIndex_); index <= endIndex_.value_or(preEndIndex_); ++index) { auto offset = paddingOffset; auto wrapper = layoutWrapper->GetOrCreateChildByIndex(index); if (!wrapper) { @@ -326,11 +333,9 @@ void ListLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) float childCrossSize = GetCrossAxisSize(wrapper->GetGeometryNode()->GetFrameSize(), axis); float laneCrossOffset = CalculateLaneCrossOffset(crossSize, childCrossSize); if (axis == Axis::VERTICAL) { - offset = offset + OffsetF(0, itemPosition_[index].first - currentOffset_) - + OffsetF(laneCrossOffset, 0); + offset = offset + OffsetF(0, itemPosition_[index].first - currentOffset_) + OffsetF(laneCrossOffset, 0); } else { - offset = offset + OffsetF(itemPosition_[index].first - currentOffset_, 0) - + OffsetF(0, laneCrossOffset); + offset = offset + OffsetF(itemPosition_[index].first - currentOffset_, 0) + OffsetF(0, laneCrossOffset); } } wrapper->GetGeometryNode()->SetFrameOffset(offset); diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp index 629178d4f68..4e37e2b776b 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/swiper/swiper_layout_algorithm.cpp @@ -20,6 +20,7 @@ #include "base/geometry/ng/size_t.h" #include "base/log/ace_trace.h" #include "base/utils/utils.h" +#include "core/components_ng/base/frame_node.h" #include "core/components_ng/layout/layout_algorithm.h" #include "core/components_ng/pattern/swiper/swiper_layout_property.h" #include "core/components_ng/property/layout_constraint.h" @@ -45,8 +46,7 @@ void SwiperLayoutAlgorithm::InitItemRange() } } - if (targetIndex_.has_value() && - (targetIndex_.value() < startIndex_ || targetIndex_.value() > endIndex_)) { + if (targetIndex_.has_value() && (targetIndex_.value() < startIndex_ || targetIndex_.value() > endIndex_)) { itemRange_.insert(targetIndex_.value()); } @@ -99,6 +99,12 @@ void SwiperLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) wrapper->Measure(layoutConstraint); } + // TODO: need to find better way to sync render tree. + // if index changed, need mark frame node to force sync render tree. + if (!inActiveItems_.empty()) { + layoutWrapper->SetForceSyncRenderTree(); + } + // Mark inactive in wrapper. for (const auto& index : inActiveItems_) { layoutWrapper->RemoveChildInRenderTree(index); From b75b4391b65a1cf7c287fd74f4ee1d3b0ba27941 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 30 Aug 2022 16:57:08 +0800 Subject: [PATCH 06/35] fix inspector bug Signed-off-by: peter Change-Id: I984c18cba359dd201225a55015e075a03929e80a --- .../jsview/js_data_panel.cpp | 2 +- .../view_stack_processor.cpp | 16 +++++++++++++ .../inspector/grid_composed_element.cpp | 24 +++++++++++++------ .../inspector/inspector_composed_element.cpp | 2 +- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_data_panel.cpp b/frameworks/bridge/declarative_frontend/jsview/js_data_panel.cpp index 43af2aeffa1..0f24190f905 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_data_panel.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_data_panel.cpp @@ -69,7 +69,7 @@ void JSDataPanel::Create(const JSCallbackInfo& info) auto item = values->GetArrayItem(i); if (!item || !item->IsNumber()) { LOGE("JSDataPanel::Create value is not number"); - return; + continue; } auto value = item->GetDouble(); if (LessOrEqual(value, 0.0)) { diff --git a/frameworks/bridge/declarative_frontend/view_stack_processor.cpp b/frameworks/bridge/declarative_frontend/view_stack_processor.cpp index 2230f0defc7..869bce66343 100644 --- a/frameworks/bridge/declarative_frontend/view_stack_processor.cpp +++ b/frameworks/bridge/declarative_frontend/view_stack_processor.cpp @@ -192,6 +192,15 @@ RefPtr ViewStackProcessor::GetStepperScrollComponent() RefPtr ViewStackProcessor::GetBoxComponent() { +#if defined(PREVIEW) + if (componentsStack_.empty()) { + RefPtr boxComponent = AceType::MakeRefPtr(); + std::unordered_map> wrappingComponentsMap; + wrappingComponentsMap.emplace("box", boxComponent); + componentsStack_.push(wrappingComponentsMap); + return boxComponent; + } +#endif auto& wrappingComponentsMap = componentsStack_.top(); if (wrappingComponentsMap.find("box") != wrappingComponentsMap.end()) { auto boxComponent = AceType::DynamicCast(wrappingComponentsMap["box"]); @@ -437,6 +446,13 @@ void ViewStackProcessor::Push(const RefPtr& component, bool isCustomV bool ViewStackProcessor::ShouldPopImmediately() { +// Pop the non-pop mock component immediately on the preview +#if defined(PREVIEW) + auto inspectorTag = GetMainComponent()->GetInspectorTag(); + if (inspectorTag == "XComponentComponent" || inspectorTag == "WebComponent") { + return true; + } +#endif auto type = AceType::TypeName(GetMainComponent()); auto componentGroup = AceType::DynamicCast(GetMainComponent()); auto multiComposedComponent = AceType::DynamicCast(GetMainComponent()); diff --git a/frameworks/core/components_v2/inspector/grid_composed_element.cpp b/frameworks/core/components_v2/inspector/grid_composed_element.cpp index 5590d6bbc72..83ead1442aa 100644 --- a/frameworks/core/components_v2/inspector/grid_composed_element.cpp +++ b/frameworks/core/components_v2/inspector/grid_composed_element.cpp @@ -18,7 +18,7 @@ #include "base/log/dump_log.h" #include "core/components/common/layout/constants.h" #include "core/components/grid_layout/render_grid_layout.h" -#include "core/components_v2/grid/grid_element.h" +#include "core/components_v2/grid/render_grid_scroll.h" #include "core/components_v2/inspector/utils.h" namespace OHOS::Ace::V2 { @@ -100,27 +100,37 @@ std::string GridComposedElement::GetRowsTemplate() const std::string GridComposedElement::GetColumnsGap() const { - auto node = GetInspectorNode(GridLayoutElement::TypeId()); - if (!node) { + auto gridLayoutNode = GetInspectorNode(GridLayoutElement::TypeId()); + auto gridNode = GetInspectorNode(V2::GridElement::TypeId()); + if (!gridNode && !gridLayoutNode) { return "0"; } - auto renderGrip = AceType::DynamicCast(node); + auto renderGrip = AceType::DynamicCast(gridLayoutNode); + auto renderScroll = AceType::DynamicCast(gridNode); if (renderGrip) { return renderGrip->GetColumns().ToString().c_str(); } + if (renderScroll) { + return renderScroll->GetColumns().ToString().c_str(); + } return "0"; } std::string GridComposedElement::GetRowsGap() const { - auto node = GetInspectorNode(GridLayoutElement::TypeId()); - if (!node) { + auto gridLayoutNode = GetInspectorNode(GridLayoutElement::TypeId()); + auto gridNode = GetInspectorNode(V2::GridElement::TypeId()); + if (!gridNode && !gridLayoutNode) { return "0"; } - auto renderGrip = AceType::DynamicCast(node); + auto renderGrip = AceType::DynamicCast(gridLayoutNode); + auto renderScroll = AceType::DynamicCast(gridNode); if (renderGrip) { return renderGrip->GetRows().ToString().c_str(); } + if (renderScroll) { + return renderScroll->GetRows().ToString().c_str(); + } return "0"; } diff --git a/frameworks/core/components_v2/inspector/inspector_composed_element.cpp b/frameworks/core/components_v2/inspector/inspector_composed_element.cpp index 69d9d9fa49a..79e031ae15b 100644 --- a/frameworks/core/components_v2/inspector/inspector_composed_element.cpp +++ b/frameworks/core/components_v2/inspector/inspector_composed_element.cpp @@ -405,7 +405,7 @@ RefPtr InspectorComposedElement::GetAccessibilityNode() const LOGW("get AccessibilityManager failed"); return nullptr; } - return accessibilityManager->GetAccessibilityNodeById(std::stoi(id_)); + return accessibilityManager->GetAccessibilityNodeById(StringUtils::StringToInt(id_)); } RefPtr InspectorComposedElement::GetRenderBox() const From 4380d175eb752719cd8df69e8b9ad6ec3b4e96ca Mon Sep 17 00:00:00 2001 From: lushi Date: Thu, 1 Sep 2022 09:54:32 +0800 Subject: [PATCH 07/35] unittest coverage Signed-off-by: lushi Change-Id: I20586919da8bc6c5efcd820c484c6825cbb7f91b --- BUILD.gn | 7 +++++++ ace_config.gni | 3 +++ frameworks/core/pipeline/test/unittest/context/BUILD.gn | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/BUILD.gn b/BUILD.gn index 9ca289e2b14..01b18c5fe75 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -104,3 +104,10 @@ config("ace_test_config") { cflags_cc += [ "-fvisibility-inlines-hidden" ] ldflags = [ "-Wl,-gc-sections" ] } + +config("ace_test_coverage_config") { + if (ace_engine_feature_enable_coverage) { + cflags = [ "--coverage" ] + ldflags = [ "--coverage" ] + } +} diff --git a/ace_config.gni b/ace_config.gni index 7d0abff9f34..172013edcd1 100644 --- a/ace_config.gni +++ b/ace_config.gni @@ -40,6 +40,9 @@ declare_args() { # Enable metal in iOS or MacOS shell_enable_metal = false + + # Enable test coverage + ace_engine_feature_enable_coverage = false } use_external_v8_snapshot = false diff --git a/frameworks/core/pipeline/test/unittest/context/BUILD.gn b/frameworks/core/pipeline/test/unittest/context/BUILD.gn index 6409c75e9b3..05933ac7afa 100644 --- a/frameworks/core/pipeline/test/unittest/context/BUILD.gn +++ b/frameworks/core/pipeline/test/unittest/context/BUILD.gn @@ -235,6 +235,7 @@ ohos_unittest("PipelineContextTest") { "$ace_root/frameworks/base/resource:ace_resource", "$ace_root/frameworks/core/components/theme:build_theme_code", "$cjson_root:cjson_static", + "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", ] @@ -245,7 +246,10 @@ ohos_unittest("PipelineContextTest") { "resmgr:resourcemanager", ] } else { - configs += [ "//third_party/curl:curl_config" ] + configs += [ + "$ace_root:ace_test_coverage_config", + "//third_party/curl:curl_config", + ] deps += [ "//third_party/curl:curl" ] external_deps = [ "eventhandler:libeventhandler", From a7adf5e44fcb30b3d18eb749f936ba37a5cf29c1 Mon Sep 17 00:00:00 2001 From: leiguangyu Date: Sat, 27 Aug 2022 10:29:08 +0800 Subject: [PATCH 08/35] jdwp for onesdk Change-Id: I07b16e58c53312c36d39420c1661f1f9657b0634 Signed-off-by: leiguangyu --- frameworks/core/common/register/define.h | 1 + frameworks/core/common/register/hdc_jdwp.cpp | 79 +++++++++++++++++++- frameworks/core/common/register/hdc_jdwp.h | 3 + 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/frameworks/core/common/register/define.h b/frameworks/core/common/register/define.h index abb3e46b35f..ab03080af9c 100644 --- a/frameworks/core/common/register/define.h +++ b/frameworks/core/common/register/define.h @@ -16,6 +16,7 @@ #ifndef HDC_TEST #define HDC_TEST +#include #include #include #include diff --git a/frameworks/core/common/register/hdc_jdwp.cpp b/frameworks/core/common/register/hdc_jdwp.cpp index 7dad2f9350e..0b82e3a67ee 100644 --- a/frameworks/core/common/register/hdc_jdwp.cpp +++ b/frameworks/core/common/register/hdc_jdwp.cpp @@ -39,6 +39,10 @@ void HdcJdwpSimulator::FreeContext() uv_close((uv_handle_t *)&ctxPoint_->newFd, nullptr); } } + if (ctxPoint_ != nullptr && ctxPoint_->cfd > -1) { + close(ctxPoint_->cfd); + ctxPoint_->cfd = -1; + } } HdcJdwpSimulator::~HdcJdwpSimulator() @@ -101,6 +105,15 @@ RetErrCode HdcJdwpSimulator::SendToStream(uv_stream_t *handleStream, const uint8 return ret; } +void HdcJdwpSimulator::SendToJpid(int fd, const uint8_t *buf, const int bufLen) +{ + LOGI("SendToJpid: %{public}s, %{public}d", buf, bufLen); + ssize_t rc = write(fd, buf, bufLen); + if (rc < 0) { + LOGE("SendToJpid failed errno:%{public}d", errno); + } +} + void HdcJdwpSimulator::ConnectJdwp(uv_connect_t *connection, int status) { uint32_t pid_curr = static_cast(getpid()); @@ -137,6 +150,44 @@ void HdcJdwpSimulator::ConnectJdwp(uv_connect_t *connection, int status) #endif // JS_JDWP_CONNECT } +void HdcJdwpSimulator::ConnectJpid(void *param) +{ + uint32_t pid_curr = static_cast(getpid()); + HdcJdwpSimulator *thisClass = static_cast(param); +#ifdef JS_JDWP_CONNECT + string pkgName = thisClass->pkgName_; + uint32_t pkgSize = pkgName.size() + sizeof(JsMsgHeader); + uint8_t* info = new (std::nothrow) uint8_t[pkgSize](); + if (!info) { + LOGE("ConnectJpid new info fail."); + return; + } + if (memset_s(info, pkgSize, 0, pkgSize) != EOK) { + delete[] info; + info = nullptr; + return; + } + JsMsgHeader *jsMsg = reinterpret_cast(info); + jsMsg->pid = pid_curr; + jsMsg->msgLen = pkgSize; + LOGI("ConnectJpid send pid:%{public}d, pkgName:%{public}s, msglen:%{public}d", + jsMsg->pid, pkgName.c_str(), jsMsg->msgLen); + bool retFail = false; + if (memcpy_s(info + sizeof(JsMsgHeader), pkgName.size(), &pkgName[0], pkgName.size()) != EOK) { + LOGE("ConnectJpid memcpy_s fail :%{public}s.", pkgName.c_str()); + retFail = true; + } + if (!retFail) { + LOGI("ConnectJpid send JS msg:%{public}s", info); + SendToJpid(thisClass->ctxPoint_->cfd, (uint8_t*)info, pkgSize); + } + if (info) { + delete[] info; + info = nullptr; + } +#endif +} + void *HdcJdwpSimulator::MallocContext() { HCtxJdwpSimulator ctx = nullptr; @@ -146,21 +197,41 @@ void *HdcJdwpSimulator::MallocContext() ctx->thisClass = this; ctx->pipe.data = ctx; ctx->hasNewFd = false; + ctx->cfd = -1; return ctx; } bool HdcJdwpSimulator::Connect() { - string jdwpCtrlName = "\0jdwp-control"; + const char jdwp[] = { '\0', 'o', 'h', 'j', 'p', 'i', 'd', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 }; if (!ctxPoint_) { LOGE("MallocContext failed"); delete connect_; connect_ = nullptr; return false; } - connect_->data = ctxPoint_; - uv_pipe_init(loop_, (uv_pipe_t *)&ctxPoint_->pipe, 1); - uv_pipe_connect(connect_, &ctxPoint_->pipe, jdwpCtrlName.c_str(), ConnectJdwp); + struct sockaddr_un caddr; + if (memset_s(&caddr, sizeof(caddr), 0, sizeof(caddr)) != EOK) { + LOGE("memset_s failed"); + return false; + } + caddr.sun_family = AF_UNIX; + for (size_t i = 0; i < sizeof(jdwp); i++) { + caddr.sun_path[i] = jdwp[i]; + } + int cfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (cfd < 0) { + LOGE("socket failed errno:%{public}d", errno); + return false; + } + int rc = connect(cfd, reinterpret_cast(&caddr), sizeof(caddr)); + if (rc != 0) { + LOGE("connect failed errno:%{public}d", errno); + close(cfd); + return false; + } + ctxPoint_->cfd = cfd; + ConnectJpid(this); return true; } } // namespace OHOS::Ace diff --git a/frameworks/core/common/register/hdc_jdwp.h b/frameworks/core/common/register/hdc_jdwp.h index e90e3ca603f..18b24f993cb 100644 --- a/frameworks/core/common/register/hdc_jdwp.h +++ b/frameworks/core/common/register/hdc_jdwp.h @@ -32,6 +32,7 @@ public: protected: struct ContextJdwpSimulator { + int cfd; uv_pipe_t pipe; uv_tcp_t newFd; bool hasNewFd; @@ -46,6 +47,7 @@ private: }; void *MallocContext(); static void ConnectJdwp(uv_connect_t *connection, int status); + static void ConnectJpid(void *param); static void FinishWriteCallback(uv_write_t *req, int status); #ifndef JS_JDWP_CONNECT static void ReceiveNewFd(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf); @@ -53,6 +55,7 @@ private: #endif // JS_JDWP_CONNECT static RetErrCode SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, const void *finishCallback); + static void SendToJpid(int fd, const uint8_t *buf, const int bufLen); bool exit_ = false; HCtxJdwpSimulator ctxPoint_; string pkgName_; From 2a5a09b23a866d24776e0b7966eb34981c07b324 Mon Sep 17 00:00:00 2001 From: xuzhidan Date: Thu, 1 Sep 2022 11:35:22 +0800 Subject: [PATCH 09/35] Cancel default padding of the bindMenu custom mode. Signed-off-by: xuzhidan Change-Id: Ica7fe5d17b8680e0b487ee99f36034951922506c --- .../declarative_frontend/jsview/js_view_abstract.cpp | 1 + frameworks/core/components/menu/menu_component.h | 7 +++++++ .../components/select_popup/select_popup_component.cpp | 2 +- .../core/components/select_popup/select_popup_component.h | 6 ++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index b08c48781bf..816d077b51b 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -1922,6 +1922,7 @@ void JSViewAbstract::JsBindMenu(const JSCallbackInfo& info) if (!menuComponent) { return; } + menuComponent->SetIsCustomMenu(true); ExecMenuBuilder(builderFunc, menuComponent); auto showDialog = menuComponent->GetTargetCallback(); showDialog("BindMenu", info.GetGlobalLocation()); diff --git a/frameworks/core/components/menu/menu_component.h b/frameworks/core/components/menu/menu_component.h index ef7d4a73e4d..44768fd4e1e 100644 --- a/frameworks/core/components/menu/menu_component.h +++ b/frameworks/core/components/menu/menu_component.h @@ -159,6 +159,13 @@ public: return isContextMenu_; } + void SetIsCustomMenu(bool isCustomMenu) + { + if (popup_) { + popup_->SetIsCustomMenu(isCustomMenu); + } + } + private: RefPtr popup_ = AceType::MakeRefPtr(); std::function targetCallback_; diff --git a/frameworks/core/components/select_popup/select_popup_component.cpp b/frameworks/core/components/select_popup/select_popup_component.cpp index 18b06b51e33..d46fc6c77b7 100644 --- a/frameworks/core/components/select_popup/select_popup_component.cpp +++ b/frameworks/core/components/select_popup/select_popup_component.cpp @@ -324,7 +324,7 @@ bool SelectPopupComponent::Initialize(const RefPtr& manage back->SetBorderRadius(Radius(theme_->GetPopupRRectSize())); back->AddShadow(ShadowConfig::DefaultShadowM); box->SetBackDecoration(back); - box->SetPadding(Edge(IN_OUT_BOX_INTERVAL)); + box->SetPadding(isCustomMenu_ ? Edge() : Edge(IN_OUT_BOX_INTERVAL)); } box->SetChild(innerBox); diff --git a/frameworks/core/components/select_popup/select_popup_component.h b/frameworks/core/components/select_popup/select_popup_component.h index f4cea2014f0..d843e3ae7b3 100644 --- a/frameworks/core/components/select_popup/select_popup_component.h +++ b/frameworks/core/components/select_popup/select_popup_component.h @@ -287,6 +287,11 @@ public: return dialogShowed_; } + void SetIsCustomMenu(bool isCustomMenu) + { + isCustomMenu_ = isCustomMenu; + } + private: RefPtr InitializeInnerBox(const RefPtr& scroll); void HandleOptionClick(std::size_t index); @@ -299,6 +304,7 @@ private: Offset selectRightBottom_; bool isMenu_ = false; bool isContextMenu_ = false; + bool isCustomMenu_ = false; std::vector> options_; std::string title_; RefPtr theme_; From 21ca66fc49bbb0385eab4f7017cafabedb28c13b Mon Sep 17 00:00:00 2001 From: zhengqiyi Date: Thu, 1 Sep 2022 12:31:46 +0800 Subject: [PATCH 10/35] solve divider crash problem in list component Signed-off-by: zhengqiyi --- frameworks/core/components_ng/pattern/list/list_pattern.h | 5 +++-- frameworks/core/components_ng/render/divider_painter.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.h b/frameworks/core/components_ng/pattern/list/list_pattern.h index 27ef55a2163..4d92855e672 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.h +++ b/frameworks/core/components_ng/pattern/list/list_pattern.h @@ -34,8 +34,9 @@ public: RefPtr CreateNodePaintMethod() override { auto listLayoutProperty = GetHost()->GetLayoutProperty(); - auto divider = listLayoutProperty->GetDivider().value(); - auto axis = listLayoutProperty->GetListDirection().value_or(Axis::VERTICAL); + V2::ItemDivider itemDivider; + auto divider = listLayoutProperty->GetDivider().value_or(itemDivider); + auto axis = listLayoutProperty->GetListDirection().value_or(Axis::HORIZONTAL); auto vertical = axis == Axis::VERTICAL ? true : false; return MakeRefPtr(divider, startIndex_, endIndex_, vertical, std::move(itemPosition_)); diff --git a/frameworks/core/components_ng/render/divider_painter.cpp b/frameworks/core/components_ng/render/divider_painter.cpp index 58dec20944c..40e7a28444d 100644 --- a/frameworks/core/components_ng/render/divider_painter.cpp +++ b/frameworks/core/components_ng/render/divider_painter.cpp @@ -40,9 +40,9 @@ void DividerPainter::DrawListLines(RSCanvas& canvas, const int32_t startIndex, c { for (int32_t lineIndex = startIndex; lineIndex < endIndex; lineIndex++) { if (vertical_) { - DrawLine(canvas, OffsetF(itemPosition.at(lineIndex).first, 0)); + DrawLine(canvas, OffsetF(itemPosition.at(lineIndex).second, 0)); } else { - DrawLine(canvas, OffsetF(0, itemPosition.at(lineIndex).first)); + DrawLine(canvas, OffsetF(0, itemPosition.at(lineIndex).second)); } } } From 869b8ed9d57f9db47ac09ff810d8d053e4301542 Mon Sep 17 00:00:00 2001 From: buzhuyu Date: Thu, 1 Sep 2022 14:30:48 +0800 Subject: [PATCH 11/35] remove debugger and modify build/gn description:remove debugger and modify build/gn issue:https://gitee.com/openharmony/arkcompiler_toolchain/issues/I5NLUF Signed-off-by: buzhuyu --- adapter/ohos/build/BUILD.gn | 5 - .../js_frontend/engine/jsi/debugger/BUILD.gn | 74 ----- .../engine/jsi/debugger/hilog_wrapper.h | 50 ---- .../engine/jsi/debugger/inspector.cpp | 268 ------------------ .../engine/jsi/debugger/inspector.h | 66 ----- .../engine/jsi/debugger/library_loader.cpp | 91 ------ .../engine/jsi/debugger/library_loader.h | 28 -- .../engine/jsi/debugger/ws_server.cpp | 123 -------- .../engine/jsi/debugger/ws_server.h | 66 ----- 9 files changed, 771 deletions(-) delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/BUILD.gn delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/hilog_wrapper.h delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.cpp delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.h delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.cpp delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.h delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.cpp delete mode 100644 frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.h diff --git a/adapter/ohos/build/BUILD.gn b/adapter/ohos/build/BUILD.gn index 42c25eef853..f15a0bf6fa7 100644 --- a/adapter/ohos/build/BUILD.gn +++ b/adapter/ohos/build/BUILD.gn @@ -46,11 +46,6 @@ group("ace_packages") { "$ace_root/build:libace_engine_pa_qjs", ] - # ark debugger - deps += [ - "$ace_root/frameworks/bridge/js_frontend/engine/jsi/debugger:ark_debugger", - ] - # pid register deps += [ "$ace_root/frameworks/core/common/register:hdc_register" ] diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/BUILD.gn b/frameworks/bridge/js_frontend/engine/jsi/debugger/BUILD.gn deleted file mode 100644 index 301fe5c0d9b..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/BUILD.gn +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 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. - -import("//build/ohos.gni") -import("//foundation/arkui/ace_engine/ace_config.gni") - -config("ark_debugger_config") { - cflags_cc = [ - "-fexceptions", - "-fno-complete-member-pointers", - "-Wno-implicit-fallthrough", - "-fvisibility=default", - "-frtti", - ] -} - -ohos_shared_library("ark_debugger") { - deps = [] - defines = [ - "BOOST_ERROR_CODE_HEADER_ONLY", - "BOOST_CLANG", - ] - - if (is_mingw || is_mac) { - cflags = [ "-std=c++17" ] - if (is_mingw) { - platform = "windows" - defines += [ "WINDOWS_PLATFORM" ] - ldflags = [ - "-lwsock32", - "-lws2_32", - ] - } else { - platform = "mac" - defines += [ - "MAC_PLATFORM", - "UNIX_PLATFORM", - ] - } - deps = [ - "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_$platform", - ] - } else { - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - defines += [ "UNIX_PLATFORM" ] - } - - include_dirs = [ - ".", - "//third_party/boost", - "//third_party/boost/boost", - ] - - sources = [ - "inspector.cpp", - "library_loader.cpp", - "ws_server.cpp", - ] - - configs = [ ":ark_debugger_config" ] - - subsystem_name = "arkui" - part_name = ace_engine_part -} diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/hilog_wrapper.h b/frameworks/bridge/js_frontend/engine/jsi/debugger/hilog_wrapper.h deleted file mode 100644 index 9c57100dbe7..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/hilog_wrapper.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 ARKCOMPILER_TOOLCHAIN_HILOG_WRAPPER_H -#define ARKCOMPILER_TOOLCHAIN_HILOG_WRAPPER_H - -#include "hilog/log.h" - -namespace OHOS::Ace::Framework { -#ifdef LOGF -#undef LOGF -#endif -#ifdef LOGE -#undef LOGE -#endif -#ifdef LOGW -#undef LOGW -#endif -#ifdef LOGI -#undef LOGI -#endif -#ifdef LOGD -#undef LOGD -#endif - -static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { - LOG_CORE, - 0xD003F00, - "ArkCompiler" -}; - -#define LOGF(fmt, ...) OHOS::HiviewDFX::HiLog::Fatal(LABEL, fmt, ##__VA_ARGS__) -#define LOGE(fmt, ...) OHOS::HiviewDFX::HiLog::Error(LABEL, fmt, ##__VA_ARGS__) -#define LOGW(fmt, ...) OHOS::HiviewDFX::HiLog::Warn(LABEL, fmt, ##__VA_ARGS__) -#define LOGI(fmt, ...) OHOS::HiviewDFX::HiLog::Info(LABEL, fmt, ##__VA_ARGS__) -#define LOGD(fmt, ...) OHOS::HiviewDFX::HiLog::Debug(LABEL, fmt, ##__VA_ARGS__) -} // namespace OHOS::Ace::Framework -#endif // ARKCOMPILER_TOOLCHAIN_HILOG_WRAPPER_H diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.cpp b/frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.cpp deleted file mode 100644 index 650921eeaf0..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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. - */ - -#include "inspector.h" - -#include -#include -#include -#include - -#include "hilog_wrapper.h" -#include "library_loader.h" - -namespace OHOS::Ace::Framework { -namespace { -enum DispatchStatus : int32_t { - UNKNOWN = 0, - DISPATCHING, - DISPATCHED -}; - -using InitializeDebugger = void(*)(void*, const std::function&); -using UninitializeDebugger = void(*)(void*); -using WaitForDebugger = void(*)(void*); -using OnMessage = void(*)(void*, std::string&&); -using ProcessMessage = void(*)(void*); -using GetDispatchStatus = int32_t(*)(void*); - -OnMessage g_onMessage = nullptr; -InitializeDebugger g_initializeDebugger = nullptr; -UninitializeDebugger g_uninitializeDebugger = nullptr; -WaitForDebugger g_waitForDebugger = nullptr; -ProcessMessage g_processMessage = nullptr; -GetDispatchStatus g_getDispatchStatus = nullptr; - -std::atomic g_hasArkFuncsInited = false; -std::unordered_map g_inspectors; -std::shared_mutex g_mutex; - -thread_local void* g_handle = nullptr; -thread_local void* g_vm = nullptr; - -#if defined(WINDOWS_PLATFORM) -constexpr char ARK_DEBUGGER_SHARED_LIB[] = "libark_ecma_debugger.dll"; -#elif defined(MAC_PLATFORM) -constexpr char ARK_DEBUGGER_SHARED_LIB[] = "libark_ecma_debugger.dylib"; -#else -constexpr char ARK_DEBUGGER_SHARED_LIB[] = "libark_ecma_debugger.so"; -#endif - -void* HandleClient(void* const server) -{ - LOGI("HandleClient"); - if (server == nullptr) { - LOGE("HandleClient server nullptr"); - return nullptr; - } - static_cast(server)->RunServer(); - return nullptr; -} - -bool LoadArkDebuggerLibrary() -{ - if (g_handle != nullptr) { - LOGE("Already opened"); - return false; - } - g_handle = Load(ARK_DEBUGGER_SHARED_LIB); - if (g_handle == nullptr) { - return false; - } - return true; -} - -void* GetArkDynFunction(const char* symbol) -{ - return ResolveSymbol(g_handle, symbol); -} - -void SendReply(const void* vm, const std::string& message) -{ - std::shared_lock lock(g_mutex); - auto iter = g_inspectors.find(vm); - if (iter != g_inspectors.end() && iter->second != nullptr && - iter->second->websocketServer_ != nullptr) { - iter->second->websocketServer_->SendReply(message); - } -} - -void ResetServiceLocked() -{ - auto iter = g_inspectors.find(g_vm); - if (iter != g_inspectors.end() && iter->second != nullptr && - iter->second->websocketServer_ != nullptr) { - iter->second->websocketServer_->StopServer(); - delete iter->second; - iter->second = nullptr; - g_inspectors.erase(iter); - } - if (g_handle != nullptr) { - CloseHandle(g_handle); - g_handle = nullptr; - } -} - -bool InitializeInspector(void* vm, const std::string& componentName, int32_t instanceId, - const DebuggerPostTask& debuggerPostTask) -{ - std::unique_lock lock(g_mutex); - auto iter = g_inspectors.find(vm); - if (iter != g_inspectors.end()) { - LOGE("Already have the same vm in the map"); - return false; - } - - Inspector *newInspector = new Inspector(); - if (!g_inspectors.emplace(vm, newInspector).second) { - delete newInspector; - return false; - } - - newInspector->tid_ = pthread_self(); - newInspector->vm_ = vm; - newInspector->debuggerPostTask_ = debuggerPostTask; - newInspector->websocketServer_ = std::make_unique(componentName, - std::bind(&Inspector::OnMessage, newInspector, std::placeholders::_1), instanceId); - - pthread_t tid; - if (pthread_create(&tid, nullptr, &HandleClient, static_cast( - newInspector->websocketServer_.get())) != 0) { - LOGE("Create inspector thread failed"); - return false; - } - - return true; -} - -bool InitializeArkFunctions() -{ - // no need to initialize again in case of multi-instance - if (g_hasArkFuncsInited) { - return true; - } - - std::unique_lock lock(g_mutex); - if (g_hasArkFuncsInited) { - return true; - } - g_initializeDebugger = reinterpret_cast( - GetArkDynFunction("InitializeDebugger")); - if (g_initializeDebugger == nullptr) { - ResetServiceLocked(); - return false; - } - g_uninitializeDebugger = reinterpret_cast( - GetArkDynFunction("UninitializeDebugger")); - if (g_uninitializeDebugger == nullptr) { - ResetServiceLocked(); - return false; - } - g_waitForDebugger = reinterpret_cast( - GetArkDynFunction("WaitForDebugger")); - if (g_waitForDebugger == nullptr) { - ResetServiceLocked(); - return false; - } - g_onMessage = reinterpret_cast( - GetArkDynFunction("OnMessage")); - if (g_onMessage == nullptr) { - ResetServiceLocked(); - return false; - } - g_getDispatchStatus = reinterpret_cast( - GetArkDynFunction("GetDispatchStatus")); - if (g_getDispatchStatus == nullptr) { - ResetServiceLocked(); - return false; - } - g_processMessage = reinterpret_cast( - GetArkDynFunction("ProcessMessage")); - if (g_processMessage == nullptr) { - ResetServiceLocked(); - return false; - } - - g_hasArkFuncsInited = true; - return true; -} -} // namespace - -void Inspector::OnMessage(std::string&& msg) -{ - g_onMessage(vm_, std::move(msg)); - - // message will be processed soon if the debugger thread is in running or waiting status - if (g_getDispatchStatus(vm_) != DispatchStatus::UNKNOWN) { - return; - } - std::this_thread::sleep_for(std::chrono::microseconds(DELAY_CHECK_DISPATCH_STATUS)); - if (g_getDispatchStatus(vm_) != DispatchStatus::UNKNOWN) { - return; - } - - // the debugger thread maybe in idle status, so try to post a task to wake it up - if (debuggerPostTask_ != nullptr) { - debuggerPostTask_([tid = tid_, vm = vm_] { - if (tid != pthread_self()) { - LOGE("Task not in debugger thread"); - return; - } - g_processMessage(vm); - }); - } else { - LOGW("No debuggerPostTask provided"); - } -} - -bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId, - const DebuggerPostTask& debuggerPostTask) -{ - g_vm = vm; - if (!LoadArkDebuggerLibrary()) { - return false; - } - if (!InitializeArkFunctions()) { - LOGE("Initialize ark functions failed"); - return false; - } - - g_initializeDebugger(vm, std::bind(&SendReply, vm, std::placeholders::_2)); - - if (!InitializeInspector(vm, componentName, instanceId, debuggerPostTask)) { - LOGE("Initialize inspector failed"); - return false; - } - - if (isDebugMode) { - g_waitForDebugger(vm); - } - return true; -} - -void StopDebug(const std::string& componentName) -{ - LOGI("StopDebug: %{private}s", componentName.c_str()); - std::unique_lock lock(g_mutex); - auto iter = g_inspectors.find(g_vm); - if (iter == g_inspectors.end() || iter->second == nullptr) { - return; - } - - g_uninitializeDebugger(g_vm); - ResetServiceLocked(); - LOGI("StopDebug end"); -} -} // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.h b/frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.h deleted file mode 100644 index 3a689b7450c..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/inspector.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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_JS_FRONTEND_ENGINE_ARK_DEBUGGER_INSPECTOR_H -#define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_INSPECTOR_H - -#include "ws_server.h" - -#include - -#include - -namespace panda::ecmascript { -class EcmaVM; -} // namespace panda::ecmascript - -namespace OHOS::Ace::Framework { -using EcmaVM = panda::ecmascript::EcmaVM; -using DebuggerPostTask = std::function&&)>; - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif /* End of #ifdef __cplusplus */ - -bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId, - const DebuggerPostTask& debuggerPostTask); - -void StopDebug(const std::string& componentName); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* End of #ifdef __cplusplus */ - -class Inspector { -public: - Inspector() = default; - ~Inspector() = default; - - void OnMessage(std::string&& msg); - - static constexpr int32_t DELAY_CHECK_DISPATCH_STATUS = 100; - - pthread_t tid_ = 0; - void* vm_ = nullptr; - std::unique_ptr websocketServer_; - DebuggerPostTask debuggerPostTask_; -}; -} // namespace OHOS::Ace::Framework - -#endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_INSPECTOR_H \ No newline at end of file diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.cpp b/frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.cpp deleted file mode 100644 index d807a852eee..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 "library_loader.h" - -#include "hilog_wrapper.h" - -#if defined(UNIX_PLATFORM) -#include -#elif defined(WINDOWS_PLATFORM) -#include -#else -#error "Unsupported platform" -#endif - -#include - -namespace OHOS::Ace::Framework { -#ifdef WINDOWS_PLATFORM -void* Load(std::string_view libraryName) -{ - HMODULE module = LoadLibrary(libraryName.data()); - void* handle = reinterpret_cast(module); - if (handle != nullptr) { - return handle; - } - - LOGE("Failed to open %{public}s, reason:%{public}sn", libraryName.data(), - std::to_string(GetLastError()).c_str()); - return nullptr; -} - -void* ResolveSymbol(void* handle, std::string_view symbol) -{ - HMODULE module = reinterpret_cast(handle); - void* addr = reinterpret_cast(GetProcAddress(module, symbol.data())); - if (addr != nullptr) { - return addr; - } - LOGE("Failed to get symbol:%{public}s, reason:%{public}s", symbol.data(), - std::to_string(GetLastError()).c_str()); - return nullptr; -} - -void CloseHandle(void* handle) -{ - if (handle != nullptr) { - FreeLibrary(reinterpret_cast(handle)); - } -} -#else // UNIX_PLATFORM -void* Load(std::string_view libraryName) -{ - void* handle = dlopen(libraryName.data(), RTLD_LAZY); - if (handle != nullptr) { - return handle; - } - LOGE("Failed to open %{public}s, reason:%{public}sn", libraryName.data(), dlerror()); - return nullptr; -} - -void* ResolveSymbol(void* handle, std::string_view symbol) -{ - void* addr = dlsym(handle, symbol.data()); - if (addr != nullptr) { - return addr; - } - LOGE("Failed to get symbol:%{public}s, reason:%{public}sn", symbol.data(), dlerror()); - return nullptr; -} - -void CloseHandle(void* handle) -{ - if (handle != nullptr) { - dlclose(handle); - } -} -#endif -} \ No newline at end of file diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.h b/frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.h deleted file mode 100644 index a198ac79601..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/library_loader.h +++ /dev/null @@ -1,28 +0,0 @@ - -/** - * 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_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_LIBRARY_LOADER_H -#define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_LIBRARY_LOADER_H - -#include - -namespace OHOS::Ace::Framework { -void* Load(std::string_view filename); -void* ResolveSymbol(void* handle, std::string_view name); -void CloseHandle(void* handle); -} // namespace OHOS::Ace::Framework - -#endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_LIBRARY_LOADER_H diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.cpp b/frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.cpp deleted file mode 100644 index 8644cd4832d..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 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 "ws_server.h" - -#include -#include -#include - -#include "hilog_wrapper.h" - -namespace OHOS::Ace::Framework { - -void WsServer::RunServer() -{ - terminateExecution_ = false; - try { - tid_ = pthread_self(); -#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) - constexpr int32_t DEFAULT_INSEPTOR_PORT = 9230; - CommProtocol::endpoint endPoint(CommProtocol::v4(), DEFAULT_INSEPTOR_PORT); -#else - int appPid = getpid(); - std::string pidStr = std::to_string(appPid); - std::string instanceIdStr(""); - /** - * The old version of IDE is not compatible with the new images due to the connect server. - * The First instance will use "pid" instead of "pid + instanceId" to avoid this. - * If old version of IDE does not get the instanceId by connect server, it can still connect the debug server. - */ - if (instanceId_ != 0) { - instanceIdStr = std::to_string(instanceId_); - } - std::string sockName = '\0' + pidStr + instanceIdStr + componentName_; - LOGI("WsServer RunServer: %{public}d%{public}d%{public}s", appPid, instanceId_, componentName_.c_str()); - CommProtocol::endpoint endPoint(sockName); -#endif - ioContext_ = std::make_unique(); - CommProtocol::socket socket(*ioContext_); - CommProtocol::acceptor acceptor(*ioContext_, endPoint); - auto& connectFlag = connectState_; - acceptor.async_accept(socket, [&connectFlag](const boost::system::error_code& error) { - if (!error) { - connectFlag = true; - } - }); - ioContext_->run(); - if (terminateExecution_ || !connectState_) { - return; - } - webSocket_ = std::unique_ptr>( - std::make_unique>(std::move(socket))); - webSocket_->accept(); - while (!terminateExecution_) { - beast::flat_buffer buffer; - boost::system::error_code error; - webSocket_->read(buffer, error); - if (error) { - webSocket_.reset(); - return; - } - std::string message = boost::beast::buffers_to_string(buffer.data()); - LOGI("WsServer OnMessage: %{public}s", message.c_str()); - wsOnMessage_(std::move(message)); - } - } catch (const beast::system_error& se) { - if (se.code() != websocket::error::closed) { - webSocket_.reset(); - LOGE("Error system_error, %{public}s", se.what()); - } - } catch (const std::exception& e) { - LOGE("Error exception, %{public}s", e.what()); - } -} - -void WsServer::StopServer() -{ - LOGI("WsServer StopServer"); - terminateExecution_ = true; - if (!connectState_) { - ioContext_->stop(); - } else if (webSocket_ != nullptr) { - boost::system::error_code error; - webSocket_->close(websocket::close_code::normal, error); - } - pthread_join(tid_, nullptr); -} - -void WsServer::SendReply(const std::string& message) const -{ - if (webSocket_ == nullptr) { - LOGE("WsServer SendReply websocket has been closed unexpectedly"); - return; - } - LOGI("WsServer SendReply: %{public}s", message.c_str()); - try { - boost::beast::multi_buffer buffer; - boost::beast::ostream(buffer) << message; - - webSocket_->text(webSocket_->got_text()); - webSocket_->write(buffer.data()); - } catch (const beast::system_error& se) { - if (se.code() != websocket::error::closed) { - LOGE("SendReply Error system_error"); - } - } catch (const std::exception& e) { - LOGE("SendReply Error exception"); - } -} - -} // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.h b/frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.h deleted file mode 100644 index 1e5e5321f27..00000000000 --- a/frameworks/bridge/js_frontend/engine/jsi/debugger/ws_server.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 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. - */ - -#ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_WS_SERVER_H -#define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_WS_SERVER_H - -#include -#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) -#include -#else -#include -#endif -#include -#include -#include -#include -#include - -#include - -namespace OHOS::Ace::Framework { - -namespace beast = boost::beast; -namespace websocket = beast::websocket; -#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) -using CommProtocol = boost::asio::ip::tcp; -#else -using CommProtocol = boost::asio::local::stream_protocol; -#endif - -class WsServer { -public: - WsServer(const std::string& component, const std::function& onMessage, int32_t instanceId) - : instanceId_(instanceId), componentName_(component), wsOnMessage_(onMessage) - {} - ~WsServer() = default; - void RunServer(); - void StopServer(); - void SendReply(const std::string& message) const; - -private: - std::atomic connectState_ {false}; - std::atomic terminateExecution_ { false }; - [[maybe_unused]] int32_t instanceId_ {0}; - pthread_t tid_ {0}; - std::string componentName_ {}; - std::function wsOnMessage_ {}; - std::unique_ptr> webSocket_ { nullptr }; - std::unique_ptr ioContext_ { nullptr }; -}; - -} // namespace OHOS::Ace::Framework - -#endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_ARK_DEBUGGER_WS_SERVER_H From e295b32754fd12b1dfc4f99b7bbea2f296549ec4 Mon Sep 17 00:00:00 2001 From: changjiaxing Date: Wed, 31 Aug 2022 16:51:55 +0800 Subject: [PATCH 12/35] =?UTF-8?q?Merge=20abc=E9=80=82=E9=85=8Darkui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5OEOD Signed-off-by: changjiaxing Change-Id: I561acfd89c0949472dfc60998a6d29147edeb44b --- .../engine/jsi/jsi_declarative_engine.cpp | 18 ++++++++++++++++-- .../engine/jsi/jsi_declarative_engine.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp index a99243bc5ef..ef6911fe8a3 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp @@ -963,10 +963,8 @@ void JsiDeclarativeEngine::LoadJs(const std::string& url, const RefPtrGetRunningPage()); engineInstance_->SetRunningPage(page); } - auto runtime = engineInstance_->GetJsRuntime(); auto delegate = engineInstance_->GetDelegate(); - // get source map std::string jsSourceMap; if (delegate->GetAssetContent(url + ".map", jsSourceMap)) { @@ -983,6 +981,9 @@ void JsiDeclarativeEngine::LoadJs(const std::string& url, const RefPtrGetJsRuntime(); + auto vm = const_cast(std::static_pointer_cast(runtime)->GetEcmaVm()); + if (!JSNApi::IsBundle(vm)) { + if (!runtime->ExecuteJsBin(urlName)) { + LOGE("ExecuteJsBin %{private}s failed.", urlName.c_str()); + } + return true; + } + return false; +} + // Load the app.js file of the FA model in NG structure. bool JsiDeclarativeEngine::LoadFaAppSource() { diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h index 12706a068b5..ec002d8fdc4 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h @@ -215,6 +215,7 @@ public: // Load and initialize a JS bundle into the JS Framework void LoadJs(const std::string& url, const RefPtr& page, bool isMainPage) override; + bool LoadJsWithModule(const std::string& urlName); // Load the app.js file of the FA model in NG structure.. bool LoadFaAppSource() override; From a3715916679db888a2ee9f6d8869726dc4307b57 Mon Sep 17 00:00:00 2001 From: zhengqiyi Date: Thu, 1 Sep 2022 15:12:25 +0800 Subject: [PATCH 13/35] solve divider crash problem in list component Signed-off-by: zhengqiyi --- frameworks/core/components_ng/pattern/list/list_pattern.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.cpp b/frameworks/core/components_ng/pattern/list/list_pattern.cpp index 58d455e4111..24f14ccc8eb 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.cpp +++ b/frameworks/core/components_ng/pattern/list/list_pattern.cpp @@ -72,7 +72,10 @@ bool ListPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, b endIndex_ = listLayoutAlgorithm->GetEndIndex(); isInitialized_ = listLayoutAlgorithm->GetIsInitialized(); itemPosition_ = listLayoutAlgorithm->GetItemPosition(); - return true; + if (listLayoutAlgorithm->GetDivider().has_value()) { + return true; + } + return false; } void ListPattern::UpdateCurrentOffset(float offset) From 8059de1f5dd9ea03d89e61bb79779b02f669b20f Mon Sep 17 00:00:00 2001 From: yujiadong Date: Wed, 31 Aug 2022 21:28:41 +0800 Subject: [PATCH 14/35] =?UTF-8?q?[UI=E7=BB=84=E4=BB=B6=E9=87=8D=E6=9E=84]S?= =?UTF-8?q?wiper=E6=96=B0=E5=A2=9E=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yujiadong Change-Id: I80aefb78c76ad2b00b02f270ba791e75193b452e --- .../pattern/swiper/swiper_paint_property.h | 1 - .../core/components_ng/test/property/BUILD.gn | 5 +- .../test/property/swiper/BUILD.gn | 47 +++ .../swiper/swiper_property_test_ng.cpp | 350 ++++++++++++++++++ 4 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 frameworks/core/components_ng/test/property/swiper/BUILD.gn create mode 100644 frameworks/core/components_ng/test/property/swiper/swiper_property_test_ng.cpp 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 6175b939e47..fd319f0ec1f 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_paint_property.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_paint_property.h @@ -16,7 +16,6 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_PAINT_PROPERTY_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWIPER_SWIPER_PAINT_PROPERTY_H -#include "src/core/SkPaintPriv.h" #include "core/animation/curve.h" #include "core/components/common/layout/constants.h" #include "core/components/common/properties/color.h" diff --git a/frameworks/core/components_ng/test/property/BUILD.gn b/frameworks/core/components_ng/test/property/BUILD.gn index 29ad6ea2af7..a7d3f06bf88 100644 --- a/frameworks/core/components_ng/test/property/BUILD.gn +++ b/frameworks/core/components_ng/test/property/BUILD.gn @@ -13,5 +13,8 @@ group("property_unittest") { testonly = true - deps = [ "list:list_property_test" ] + deps = [ + "list:list_property_test", + "swiper:swiper_property_test_ng", + ] } diff --git a/frameworks/core/components_ng/test/property/swiper/BUILD.gn b/frameworks/core/components_ng/test/property/swiper/BUILD.gn new file mode 100644 index 00000000000..7e39c80ac47 --- /dev/null +++ b/frameworks/core/components_ng/test/property/swiper/BUILD.gn @@ -0,0 +1,47 @@ +# 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. + +import("//build/test.gni") +import("//foundation/arkui/ace_engine/ace_config.gni") +import( + "//foundation/arkui/ace_engine/frameworks/core/components_ng/components.gni") + +ohos_unittest("swiper_property_test_ng") { + module_out_path = "$test_output_path/swiper" + + sources = [ "swiper_property_test_ng.cpp" ] + + deps = [ + "$ace_root/build:ace_ohos_unittest_base", + "$ace_root/frameworks/core/components_ng/base:ace_core_components_base_ng_ohos", + "//third_party/googletest:gmock_main", + ] + + configs = [ + ":config_swiper_test", + "$ace_root:ace_config", + ] + configs += [ + "$ace_root:ace_test_coverage_config", + "//third_party/curl:curl_config", + ] +} + +config("config_swiper_test") { + visibility = [ ":*" ] + include_dirs = [ + "//commonlibrary/c_utils/base/include", + "$ace_root", + "$ace_root/frameworks", + ] +} diff --git a/frameworks/core/components_ng/test/property/swiper/swiper_property_test_ng.cpp b/frameworks/core/components_ng/test/property/swiper/swiper_property_test_ng.cpp new file mode 100644 index 00000000000..d6aa4d69569 --- /dev/null +++ b/frameworks/core/components_ng/test/property/swiper/swiper_property_test_ng.cpp @@ -0,0 +1,350 @@ +/* + * 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 +#include "gtest/gtest.h" + +#include "base/geometry/dimension.h" +#include "base/geometry/ng/size_t.h" +#include "base/memory/ace_type.h" +#include "base/memory/referenced.h" +#include "core/animation/cubic_curve.h" +#include "core/animation/curve.h" +#include "core/animation/curves.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/swiper/swiper_layout_property.h" +#include "core/components_ng/pattern/swiper/swiper_paint_property.h" +#include "core/components_ng/pattern/swiper/swiper_view.h" +#include "core/components_v2/inspector/inspector_constants.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS::Ace::NG { +namespace { +constexpr int32_t INDEX_DEFAULT = 1; +constexpr int32_t SWIPER_LAYOUT_PROPERTY_INDEX_1 = -1; +constexpr int32_t SWIPER_LAYOUT_PROPERTY_INDEX_2 = 0; +constexpr int32_t SWIPER_LAYOUT_PROPERTY_INDEX_3 = 1; +const std::vector SWIPER_LAYOUT_PROPERTY_INDEX = { SWIPER_LAYOUT_PROPERTY_INDEX_1, + SWIPER_LAYOUT_PROPERTY_INDEX_2, + SWIPER_LAYOUT_PROPERTY_INDEX_3 }; + +const bool SWIPER_PAINT_PROPERTY_AUTOPLAY = false; +constexpr int32_t SWIPER_PAINT_PROPERTY_INTERVAL_DEFAULT = 3000; +constexpr int32_t SWIPER_PAINT_PROPERTY_INTERVAL_1 = 5000; +constexpr int32_t SWIPER_PAINT_PROPERTY_INTERVAL_2 = -100; +const std::vector SWIPER_PAINT_PROPERTY_INTERVAL = { SWIPER_PAINT_PROPERTY_INTERVAL_1, + SWIPER_PAINT_PROPERTY_INTERVAL_2 }; +const bool SWIPER_LAYOUT_PROPERTY_SHOW_INDICATOR = false; +const bool SWIPER_PAINT_PROPERTY_LOOP = false; +const SwiperDisplayMode SWIPER_LAYOUT_PROPERTY_DISPLAY_MODE = SwiperDisplayMode::AUTO_LINEAR; +const std::vector SWIPER_PAINT_PROPERTY_EDGE_EFFECT = { EdgeEffect::FADE, + EdgeEffect::NONE, + EdgeEffect::SPRING }; + +const RefPtr LINEAR = AceType::MakeRefPtr(); +const RefPtr SINE = AceType::MakeRefPtr(); +const RefPtr EASE = AceType::MakeRefPtr(0.25f, 0.1f, 0.25f, 1.0f); +const RefPtr SMOOTH = AceType::MakeRefPtr(0.4f, 0.0f, 0.4f, 1.0f); +const RefPtr ELASTICS = AceType::MakeRefPtr(2.0f); +const std::vector> SWIPER_PAINT_PROPERTY_CURVE = { LINEAR, SINE, EASE, SMOOTH, ELASTICS }; + +const std::vector SWIPER_PAINT_PROPERTY_DURATION = { 100, 2000, 400 }; +constexpr Dimension SWIPER_PAINT_PROPERTY_ITEM_SPACE_1 = Dimension(0); +constexpr Dimension SWIPER_PAINT_PROPERTY_ITEM_SPACE_2 = Dimension(1); +constexpr Dimension SWIPER_PAINT_PROPERTY_ITEM_SPACE_3 = Dimension(10); +const std::vector SWIPER_PAINT_PROPERTY_ITEM_SPACE = { SWIPER_PAINT_PROPERTY_ITEM_SPACE_1, + SWIPER_PAINT_PROPERTY_ITEM_SPACE_2, + SWIPER_PAINT_PROPERTY_ITEM_SPACE_3 }; + +const std::vector SWIPER_PAINT_PROPERTY_CACHED_COUNT = { -2, 1, 5, 10 }; +const std::vector SWIPER_PAINT_PROPERTY_DISPLAY_COUNT = { -2, 0, 2, 10 }; +const bool SWIPER_LAYOUT_PROPERTY_SHOW_DISABLE_SWIPE = true; + +const std::vector SWIPER_PAINT_PROPERTY_DIRECTION = { Axis::HORIZONTAL, + Axis::FREE, + Axis::NONE, + Axis::VERTICAL }; +} // namespace + +class SwiperPropertyTestNg : public testing::Test { +public: + static void SetUpTestCase() {}; + static void TearDownTestCase() {}; +}; + +/** + * @tc.name: SwiperLayoutPropertyTest001 + * @tc.desc: Set one index value into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest001, TestSize.Level1) +{ + SwiperView::Create(); + SwiperView::SetIndex(INDEX_DEFAULT); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_FALSE(frameNode == nullptr); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetIndex().value_or(0), INDEX_DEFAULT); +} + +/** + * @tc.name: SwiperLayoutPropertyTest002 + * @tc.desc: set a lot of index values into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest002, TestSize.Level1) +{ + for (int32_t i = 0; i < SWIPER_LAYOUT_PROPERTY_INDEX.size(); ++i) { + SwiperView::Create(); + SwiperView::SetIndex(SWIPER_LAYOUT_PROPERTY_INDEX[i]); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetIndex().value_or(0), SWIPER_LAYOUT_PROPERTY_INDEX[i]); + } +} + +/** + * @tc.name: SwiperPaintPropertyTest003 + * @tc.desc: set autoPlay value into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest003, TestSize.Level1) +{ + SwiperView::Create(); + SwiperView::SetAutoPlay(SWIPER_PAINT_PROPERTY_AUTOPLAY); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetAutoPlay().value_or(false), SWIPER_PAINT_PROPERTY_AUTOPLAY); +} + +/** + * @tc.name: SwiperPaintPropertyTest004 + * @tc.desc: set a lot of intertval values into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest004, TestSize.Level1) +{ + for (const auto& interval : SWIPER_PAINT_PROPERTY_INTERVAL) { + SwiperView::Create(); + SwiperView::SetAutoPlayInterval(interval); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetAutoPlayInterval().value_or(SWIPER_PAINT_PROPERTY_INTERVAL_DEFAULT), + interval); + } +} + +/** + * @tc.name: SwiperLayoutPropertyTest005 + * @tc.desc: set showIndicator value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest005, TestSize.Level1) +{ + SwiperView::Create(); + SwiperView::SetShowIndicator(SWIPER_LAYOUT_PROPERTY_SHOW_INDICATOR); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetShowIndicator().value_or(false), SWIPER_LAYOUT_PROPERTY_SHOW_INDICATOR); +} + +/** + * @tc.name: SwiperPaintPropertyTest006 + * @tc.desc: set loop value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest006, TestSize.Level1) +{ + SwiperView::Create(); + SwiperView::SetLoop(SWIPER_PAINT_PROPERTY_LOOP); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetLoop().value_or(false), SWIPER_PAINT_PROPERTY_LOOP); +} + +/** + * @tc.name: SwiperLayoutPropertyTest007 + * @tc.desc: set one displayMode value into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest007, TestSize.Level1) +{ + SwiperView::Create(); + SwiperView::SetDisplayMode(SWIPER_LAYOUT_PROPERTY_DISPLAY_MODE); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_FALSE(frameNode == nullptr); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetDisplayMode().value_or(SwiperDisplayMode::STRETCH), + SWIPER_LAYOUT_PROPERTY_DISPLAY_MODE); +} + +/** + * @tc.name: SwiperPaintPropertyTest008 + * @tc.desc: set one effectMode value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest008, TestSize.Level1) +{ + for (const auto& effectMode : SWIPER_PAINT_PROPERTY_EDGE_EFFECT) { + SwiperView::Create(); + SwiperView::SetEdgeEffect(effectMode); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_FALSE(frameNode == nullptr); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetEdgeEffect().value_or(EdgeEffect::FADE), effectMode); + } +} + +/** + * @tc.name: SwiperPaintPropertyTest009 + * @tc.desc: set curve value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest009, TestSize.Level1) +{ + for (int32_t i = 0; i < static_cast(SWIPER_PAINT_PROPERTY_CURVE.size()); ++i) { + SwiperView::Create(); + SwiperView::SetCurve(SWIPER_PAINT_PROPERTY_CURVE[i]); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetCurve().value_or(Curves::EASE), SWIPER_PAINT_PROPERTY_CURVE[i]); + } +} + +/** + * @tc.name: SwiperPaintPropertyTest0010 + * @tc.desc: set duration value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest0010, TestSize.Level1) +{ + for (const auto& duration : SWIPER_PAINT_PROPERTY_DURATION) { + SwiperView::Create(); + SwiperView::SetDuration(duration); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetDuration().value_or(Curves::EASE), duration); + } +} + +/** + * @tc.name: SwiperLayoutPropertyTest0011 + * @tc.desc: set a lot of itemSpace values into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest0011, TestSize.Level1) +{ + for (const auto& itemSpace : SWIPER_PAINT_PROPERTY_ITEM_SPACE) { + SwiperView::Create(); + SwiperView::SetItemSpace(itemSpace); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetItemSpace().value_or(Dimension(0)).Value(), + static_cast(itemSpace.Value())); + } +} + +/** + * @tc.name: SwiperLayoutPropertyTest0012 + * @tc.desc: set a lot of cachedCount values into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest0012, TestSize.Level1) +{ + for (int32_t i = 0; i < SWIPER_PAINT_PROPERTY_CACHED_COUNT.size(); ++i) { + SwiperView::Create(); + SwiperView::SetCachedCount(SWIPER_PAINT_PROPERTY_CACHED_COUNT[i]); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetCachedCount().value_or(1), SWIPER_PAINT_PROPERTY_CACHED_COUNT[i]); + } +} + +/** + * @tc.name: SwiperLayoutPropertyTest0013 + * @tc.desc: set a lot of displayCount values into SwiperLayoutProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperLayoutPropertyTest0013, TestSize.Level1) +{ + for (int32_t i = 0; i < SWIPER_PAINT_PROPERTY_DISPLAY_COUNT.size(); ++i) { + SwiperView::Create(); + SwiperView::SetDisplayCount(SWIPER_PAINT_PROPERTY_DISPLAY_COUNT[i]); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetDisplayCount().value_or(1), SWIPER_PAINT_PROPERTY_DISPLAY_COUNT[i]); + } +} + +/** + * @tc.name: SwiperPaintPropertyTest0014 + * @tc.desc: set disableSwipe value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest0014, TestSize.Level1) +{ + SwiperView::Create(); + SwiperView::SetDisableSwipe(SWIPER_LAYOUT_PROPERTY_SHOW_DISABLE_SWIPE); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_EQ(frameNode == nullptr, false); + auto swiperPaintProperty = frameNode->GetPaintProperty(); + EXPECT_FALSE(swiperPaintProperty == nullptr); + EXPECT_EQ(swiperPaintProperty->GetDisableSwipe().value_or(false), SWIPER_LAYOUT_PROPERTY_SHOW_DISABLE_SWIPE); +} + +/** + * @tc.name: SwiperLayoutPropertyTest0015 + * @tc.desc: set one direction value into SwiperPaintProperty and get it. + * @tc.type: FUNC + */ +HWTEST_F(SwiperPropertyTestNg, SwiperPaintPropertyTest0015, TestSize.Level1) +{ + for (const auto& direction : SWIPER_PAINT_PROPERTY_DIRECTION) { + SwiperView::Create(); + SwiperView::SetDirection(direction); + auto frameNode = AceType::DynamicCast(ViewStackProcessor::GetInstance()->Finish()); + EXPECT_FALSE(frameNode == nullptr); + auto swiperLayoutProperty = frameNode->GetLayoutProperty(); + EXPECT_FALSE(swiperLayoutProperty == nullptr); + EXPECT_EQ(swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL), direction); + } +} +} // namespace OHOS::Ace::NG From 524e586e26834e992da3d1acb40f68d0b69975b8 Mon Sep 17 00:00:00 2001 From: zhengqiyi Date: Thu, 1 Sep 2022 15:45:44 +0800 Subject: [PATCH 15/35] solve divider crash problem in list component Signed-off-by: zhengqiyi --- .../core/components_ng/pattern/list/list_pattern.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frameworks/core/components_ng/pattern/list/list_pattern.cpp b/frameworks/core/components_ng/pattern/list/list_pattern.cpp index 24f14ccc8eb..33cceca59f5 100644 --- a/frameworks/core/components_ng/pattern/list/list_pattern.cpp +++ b/frameworks/core/components_ng/pattern/list/list_pattern.cpp @@ -72,7 +72,12 @@ bool ListPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, b endIndex_ = listLayoutAlgorithm->GetEndIndex(); isInitialized_ = listLayoutAlgorithm->GetIsInitialized(); itemPosition_ = listLayoutAlgorithm->GetItemPosition(); - if (listLayoutAlgorithm->GetDivider().has_value()) { + auto host = GetHost(); + if (host == nullptr) { + return false; + } + auto listLayoutProperty = host->GetLayoutProperty(); + if (listLayoutProperty && listLayoutProperty->GetDivider().has_value()) { return true; } return false; From 9da1c1b09b40e7a3b749872d9e98fe3d402a619d Mon Sep 17 00:00:00 2001 From: chenqinxin Date: Sat, 13 Aug 2022 11:20:19 +0800 Subject: [PATCH 16/35] update RSNodeTree when children change Signed-off-by: chenqinxin Change-Id: I7d8a2be2dd5107883dc8f32da5403e6bf4d0610e --- .../pipeline/base/rosen_render_context.cpp | 21 +++++++++++++++++-- .../core/pipeline/base/rosen_render_context.h | 3 +++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/frameworks/core/pipeline/base/rosen_render_context.cpp b/frameworks/core/pipeline/base/rosen_render_context.cpp index 3906d06f35a..25857c60a62 100644 --- a/frameworks/core/pipeline/base/rosen_render_context.cpp +++ b/frameworks/core/pipeline/base/rosen_render_context.cpp @@ -54,6 +54,7 @@ void RosenRenderContext::Repaint(const RefPtr& node) InitContext(rsNode, node->GetRectWithShadow(), offset); } node->RenderWithContext(*this, offset); + UpdateChildren(rsNode); StopRecordingIfNeeded(); } @@ -78,7 +79,7 @@ void RosenRenderContext::PaintChild(const RefPtr& child, const Offse auto childRSNode = child->GetRSNode(); if (childRSNode && childRSNode != rsNode_) { - rsNode_->AddChild(childRSNode, -1); + childNodes_.emplace_back(childRSNode); std::string name = AceType::TypeName(child); if (name != "RosenRenderForm" && name != "RosenRenderPlugin") { if (child->NeedRender()) { @@ -174,7 +175,7 @@ void RosenRenderContext::InitContext( if (rsNode_ == nullptr) { return; } - rsNode_->ClearChildren(); + childNodes_.clear(); if (auto rsCanvasNode = rsNode_->ReinterpretCastTo()) { rosenCanvas_ = rsCanvasNode->BeginRecording(rsCanvasNode->GetPaintWidth(), rsCanvasNode->GetPaintHeight()); } @@ -221,4 +222,20 @@ void RosenRenderContext::Restore() } } +void RosenRenderContext::UpdateChildren(const std::shared_ptr& rsNode) +{ + std::vector childNodeIds; + for (auto& child : childNodes_) { + if (auto childNode = child.lock()) { + childNodeIds.emplace_back(childNode->GetId()); + } + } + if (childNodeIds != rsNode->GetChildIds()) { + rsNode->ClearChildren(); + rsNode->SetChildIds(childNodeIds); + for (auto& child : childNodes_) { + rsNode->AddChild(child.lock(), -1); + } + } +} } // namespace OHOS::Ace diff --git a/frameworks/core/pipeline/base/rosen_render_context.h b/frameworks/core/pipeline/base/rosen_render_context.h index 2ff4a7067de..75c1481e40f 100644 --- a/frameworks/core/pipeline/base/rosen_render_context.h +++ b/frameworks/core/pipeline/base/rosen_render_context.h @@ -58,11 +58,14 @@ public: sk_sp FinishRecordingAsImage(); private: + void UpdateChildren(const std::shared_ptr& rsNode); + std::shared_ptr rsNode_ = nullptr; SkPictureRecorder* recorder_ = nullptr; SkCanvas* recordingCanvas_ = nullptr; SkCanvas* rosenCanvas_ = nullptr; Rect estimatedRect_; + std::vector> childNodes_; }; } // namespace OHOS::Ace From b5c434410104b546ac934a0891cfb62c8cf32dea Mon Sep 17 00:00:00 2001 From: xiexiyun Date: Thu, 1 Sep 2022 19:51:14 +0800 Subject: [PATCH 17/35] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dgridrow=E6=8D=A2?= =?UTF-8?q?=E8=A1=8C=E5=B8=A6=E6=9C=89offset=E6=97=B6=E5=B0=91=E5=81=8F?= =?UTF-8?q?=E7=A7=BB=E4=B8=80=E4=B8=AAgutterX=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiexiyun Change-Id: I20a0b3a9b5a35167985b031d0a9248b11ba2ceb5 --- frameworks/core/components_v2/grid_layout/render_grid_row.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/core/components_v2/grid_layout/render_grid_row.cpp b/frameworks/core/components_v2/grid_layout/render_grid_row.cpp index 48e1613c044..ec39dbd6724 100644 --- a/frameworks/core/components_v2/grid_layout/render_grid_row.cpp +++ b/frameworks/core/components_v2/grid_layout/render_grid_row.cpp @@ -189,7 +189,7 @@ void RenderGridRow::PerformLayout() lastLength -= childSpanPlusOffsetWidth + gutterInDouble.first; } else if (component->GetDirection() == V2::GridRowDirection::Row) { if (newLineOffset.newLineCount > 0) { - position.SetX(offset > 0 ? offset * columnUnitWidth + (offset - 1) * gutterInDouble.first : 0); + position.SetX(offset > 0 ? offset * columnUnitWidth + offset * gutterInDouble.first : 0); } else { offset += GetRelativeOffset(gridColChild, sizeType); position.SetX(offset * (columnUnitWidth + gutterInDouble.first)); From 2b07f17f37bb3903b10a542bb5bd2d19abc4f3e1 Mon Sep 17 00:00:00 2001 From: Sunbees Date: Sun, 28 Aug 2022 22:33:57 +0800 Subject: [PATCH 18/35] xcomponent_ng Signed-off-by: Sunbees --- .../engine/jsi/jsi_declarative_engine.cpp | 75 ++++ .../jsview/js_xcomponent.cpp | 67 +++- .../core/components_ng/base/frame_node.cpp | 9 +- .../core/components_ng/pattern/BUILD.gn | 3 + .../core/components_ng/pattern/pattern.h | 11 +- .../pattern/xcomponent/xcomponent_event_hub.h | 90 +++++ .../xcomponent_layout_algorithm.cpp | 30 ++ .../xcomponent/xcomponent_layout_algorithm.h | 43 +++ .../pattern/xcomponent/xcomponent_pattern.cpp | 362 ++++++++++++++++++ .../pattern/xcomponent/xcomponent_pattern.h | 148 +++++++ .../pattern/xcomponent/xcomponent_view.cpp | 58 +++ .../pattern/xcomponent/xcomponent_view.h | 37 ++ frameworks/core/components_ng/render/BUILD.gn | 3 + .../render/adapter/flutter_render_context.cpp | 2 +- .../render/adapter/flutter_render_context.h | 2 +- .../render/adapter/flutter_render_surface.h | 34 ++ .../render/adapter/rosen_render_context.cpp | 16 +- .../render/adapter/rosen_render_context.h | 2 +- .../render/adapter/rosen_render_surface.cpp | 109 ++++++ .../render/adapter/rosen_render_surface.h | 59 +++ .../components_ng/render/render_context.h | 2 +- .../components_ng/render/render_surface.h | 69 ++++ .../render/render_surface_creator.cpp | 38 ++ 23 files changed, 1243 insertions(+), 26 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_event_hub.h create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.cpp create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.h create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.cpp create mode 100644 frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.h create mode 100644 frameworks/core/components_ng/render/adapter/flutter_render_surface.h create mode 100644 frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp create mode 100644 frameworks/core/components_ng/render/adapter/rosen_render_surface.h create mode 100644 frameworks/core/components_ng/render/render_surface.h create mode 100644 frameworks/core/components_ng/render/render_surface_creator.cpp diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp index f0cbf5fe6ea..4eccb5626c4 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.cpp @@ -47,6 +47,8 @@ #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h" #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h" #include "frameworks/bridge/js_frontend/engine/jsi/jsi_base_utils.h" +#include "frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h" +#include "core/components_v2/inspector/inspector_constants.h" #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) extern const char _binary_jsMockSystemPlugin_abc_start[]; @@ -1102,6 +1104,79 @@ void JsiDeclarativeEngine::FireExternalEvent( const std::string& componentId, const uint32_t nodeId, const bool isDestroy) { CHECK_RUN_ON(JS); + if (Container::IsCurrentUseNewPipeline()) { + InitXComponent(componentId); + auto xcFrameNode = NG::FrameNode::GetFrameNode(V2::XCOMPONENT_ETS_TAG, static_cast(nodeId)); + if (!xcFrameNode) { + LOGE("FireExternalEvent xcFrameNode is null."); + return; + } + auto xcPattern = DynamicCast(xcFrameNode->GetPattern()); + + void* nativeWindow = nullptr; + + nativeWindow = xcPattern->GetNativeWindow(); + + if (!nativeWindow) { + LOGE("FireExternalEvent nativeWindow invalid"); + return; + } + nativeXComponentImpl_->SetSurface(nativeWindow); + nativeXComponentImpl_->SetXComponentId(componentId); + + auto* arkNativeEngine = static_cast(nativeEngine_); + if (arkNativeEngine == nullptr) { + LOGE("FireExternalEvent arkNativeEngine is nullptr"); + return; + } + + std::string arguments; + auto arkObjectRef = arkNativeEngine->LoadModuleByName(xcPattern->GetLibraryName(), true, arguments, + OH_NATIVE_XCOMPONENT_OBJ, reinterpret_cast(nativeXComponent_)); + + auto runtime = engineInstance_->GetJsRuntime(); + shared_ptr pandaRuntime = std::static_pointer_cast(runtime); + if (arkObjectRef.IsEmpty() || pandaRuntime->HasPendingException()) { + LOGE("LoadModuleByName failed."); + return; + } + + renderContext_ = runtime->NewObject(); + auto renderContext = std::static_pointer_cast(renderContext_); + LocalScope scope(pandaRuntime->GetEcmaVm()); + Local objXComp = arkObjectRef->ToObject(pandaRuntime->GetEcmaVm()); + if (objXComp.IsEmpty() || pandaRuntime->HasPendingException()) { + LOGE("Get local object failed."); + return; + } + renderContext->SetValue(pandaRuntime, objXComp); + + auto objContext = JsiObject(objXComp); + JSRef obj = JSRef::Make(objContext); + OHOS::Ace::Framework::XComponentClient::GetInstance().AddJsValToJsValMap(componentId, obj); + + auto task = [weak = WeakClaim(this), weakPattern = AceType::WeakClaim(AceType::RawPtr(xcPattern))]() { + auto pattern = weakPattern.Upgrade(); + if (!pattern) { + return; + } + auto bridge = weak.Upgrade(); + if (bridge) { +#ifdef XCOMPONENT_SUPPORTED + pattern->NativeXComponentInit( + bridge->nativeXComponent_, AceType::WeakClaim(AceType::RawPtr(bridge->nativeXComponentImpl_))); +#endif + } + }; + + auto delegate = engineInstance_->GetDelegate(); + if (!delegate) { + LOGE("Delegate is null"); + return; + } + delegate->PostSyncTaskToPage(task); + return; + } if (isDestroy) { XComponentClient::GetInstance().DeleteFromXcomponentsMapById(componentId); XComponentClient::GetInstance().DeleteControllerFromJSXComponentControllersMap(componentId); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_xcomponent.cpp b/frameworks/bridge/declarative_frontend/jsview/js_xcomponent.cpp index 6b84dec9bd7..18a2ba33a7e 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_xcomponent.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_xcomponent.cpp @@ -20,6 +20,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_view_common_def.h" #include "frameworks/bridge/declarative_frontend/jsview/js_xcomponent_controller.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_view.h" namespace OHOS::Ace::Framework { void JSXComponent::JSBind(BindingTarget globalObj) @@ -40,18 +41,40 @@ void JSXComponent::Create(const JSCallbackInfo& info) } auto paramObject = JSRef::Cast(info[0]); auto id = paramObject->GetProperty("id"); - - auto type = paramObject->GetProperty("type"); - auto libraryname = paramObject->GetProperty("libraryname"); - auto xcomponentComponent = AceType::MakeRefPtr("xcomponent"); - if (!id->IsString()) { LOGI("xcomponent create error, id is invalid"); return; } + + auto type = paramObject->GetProperty("type"); + auto libraryname = paramObject->GetProperty("libraryname"); + auto controllerObj = paramObject->GetProperty("controller"); + RefPtr xcomponentController = nullptr; + if (controllerObj->IsObject()) { + auto* jsXComponentController = JSRef::Cast(controllerObj)->Unwrap(); + if (jsXComponentController) { + XComponentClient::GetInstance().AddControllerToJSXComponentControllersMap( + id->ToString(), jsXComponentController); + xcomponentController = jsXComponentController->GetController(); + } + } + if (Container::IsCurrentUseNewPipeline()) { + NG::XComponentView::Create(id->ToString(), type->ToString(), libraryname->ToString(), xcomponentController); + auto surfaceDestroyCallback = [xcId = id->ToString()]() { + XComponentClient::GetInstance().DeleteFromNativeXcomponentsMapById(xcId); + XComponentClient::GetInstance().DeleteControllerFromJSXComponentControllersMap(xcId); + }; + NG::XComponentView::SetOnSurfaceDestroyEvent(std::move(surfaceDestroyCallback)); + return; + } + + auto xcomponentComponent = AceType::MakeRefPtr("xcomponent"); xcomponentComponent->SetId(id->ToString()); xcomponentComponent->SetXComponentType(type->ToString()); xcomponentComponent->SetLibraryName(libraryname->ToString()); + if (xcomponentController) { + xcomponentComponent->SetXComponentController(xcomponentController); + } XComponentClient::GetInstance().AddXComponentToXcomponentsMap(xcomponentComponent->GetId(), xcomponentComponent); auto deleteCallback = [xcId = id->ToString()]() { @@ -59,22 +82,23 @@ void JSXComponent::Create(const JSCallbackInfo& info) XComponentClient::GetInstance().DeleteControllerFromJSXComponentControllersMap(xcId); }; xcomponentComponent->RegisterDeleteCallback(deleteCallback); - - auto controllerObj = paramObject->GetProperty("controller"); - if (controllerObj->IsObject()) { - auto jsXComponentController = JSRef::Cast(controllerObj)->Unwrap(); - if (jsXComponentController) { - xcomponentComponent->SetXComponentController(jsXComponentController->GetController()); - XComponentClient::GetInstance().AddControllerToJSXComponentControllersMap(xcomponentComponent->GetId(), - jsXComponentController); - } - } - ViewStackProcessor::GetInstance()->Push(xcomponentComponent); } void JSXComponent::JsOnLoad(const JSCallbackInfo& args) { + if (Container::IsCurrentUseNewPipeline()) { + auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); + auto onLoad = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)]( + const std::string& xcomponentId) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("XComponent.onLoad"); + std::vector keys = { "load", xcomponentId }; + func->ExecuteNew(keys, ""); + }; + NG::XComponentView::SetOnLoad(std::move(onLoad)); + return; + } auto stack = ViewStackProcessor::GetInstance(); auto xcomponentComponent = AceType::DynamicCast(stack->GetMainComponent()); if (!xcomponentComponent) { @@ -89,6 +113,17 @@ void JSXComponent::JsOnLoad(const JSCallbackInfo& args) void JSXComponent::JsOnDestroy(const JSCallbackInfo& args) { + if (Container::IsCurrentUseNewPipeline()) { + auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); + auto onDestroy = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)]() { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("XComponent.onDestroy"); + std::vector keys = {"destroy"}; + func->Execute(keys, ""); + }; + NG::XComponentView::SetOnDestroy(std::move(onDestroy)); + return; + } auto stack = ViewStackProcessor::GetInstance(); auto xcomponentComponent = AceType::DynamicCast(stack->GetMainComponent()); if (!xcomponentComponent) { diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index 24d3e8b4038..6ff54d04790 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -37,7 +37,7 @@ namespace OHOS::Ace::NG { FrameNode::FrameNode(const std::string& tag, int32_t nodeId, const RefPtr& pattern, bool isRoot) : UINode(tag, nodeId, isRoot), pattern_(pattern) { - renderContext_->InitContext(IsRootNode()); + renderContext_->InitContext(IsRootNode(), pattern_->SurfaceNodeName()); paintProperty_ = pattern->CreatePaintProperty(); layoutProperty_ = pattern->CreateLayoutProperty(); eventHub_ = pattern->CreateEventHub(); @@ -154,10 +154,15 @@ void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr& RebuildRenderContextTree(dirty->GetChildrenInRenderArea()); needSyncRenderTree_ = false; } - if (geometryNode_->GetFrame().GetRect() != dirty->GetGeometryNode()->GetFrame().GetRect()) { + bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize(); + bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset(); + bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize(); + bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset(); + if (frameSizeChange || frameOffsetChange) { renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode())); } SetGeometryNode(dirty->MoveGeometryNode()); + pattern_->OnLayoutChange(frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange); } void FrameNode::SetGeometryNode(RefPtr&& node) diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 5229c07eba2..2bc609edfc1 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -49,5 +49,8 @@ build_component_ng("pattern_ng") { "text/text_pattern.cpp", "text/text_styles.cpp", "text/text_view.cpp", + "xcomponent/xcomponent_layout_algorithm.cpp", + "xcomponent/xcomponent_pattern.cpp", + "xcomponent/xcomponent_view.cpp", ] } diff --git a/frameworks/core/components_ng/pattern/pattern.h b/frameworks/core/components_ng/pattern/pattern.h index 57b688df0e3..c716cbc4464 100644 --- a/frameworks/core/components_ng/pattern/pattern.h +++ b/frameworks/core/components_ng/pattern/pattern.h @@ -44,10 +44,15 @@ public: return true; } + virtual std::optional SurfaceNodeName() const + { + return std::nullopt; + } + void DetachFromFrameNode() { - frameNode_.Reset(); OnDetachFromFrameNode(); + frameNode_.Reset(); } void AttachToFrameNode(const WeakPtr& frameNode) @@ -59,6 +64,10 @@ public: OnAttachToFrameNode(); } + virtual void OnLayoutChange( + bool frameSizeChange, bool frameOffsetChange, bool contentSizeChange, bool contentOffsetChange) + {} + virtual RefPtr CreatePaintProperty() { return MakeRefPtr(); diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_event_hub.h b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_event_hub.h new file mode 100644 index 00000000000..e8b3d38f715 --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_event_hub.h @@ -0,0 +1,90 @@ +/* + * 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_PATTERNS_XCOMPONENT_XCOMPONENT_EVENT_HUB_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_XCOMPONENT_XCOMPONENT_EVENT_HUB_H + +#include "base/memory/ace_type.h" +#include "core/components_ng/event/event_hub.h" +#include "core/components_ng/event/gesture_event_hub.h" + +namespace OHOS::Ace::NG { +using LoadEvent = std::function; +using DestroyEvent = std::function; +using ExternalEvent = std::function; + +class XComponentEventHub : public EventHub { + DECLARE_ACE_TYPE(XComponentEventHub, EventHub) + +public: + XComponentEventHub() = default; + ~XComponentEventHub() override = default; + + void SetOnLoad(LoadEvent&& loadEvent) + { + loadEvent_ = std::move(loadEvent); + } + + void FireLoadEvent(const std::string& xcomponentId) const + { + if (loadEvent_) { + loadEvent_(xcomponentId); + } + } + + void SetOnDestroy(DestroyEvent&& destroyEvent) + { + destroyEvent_ = std::move(destroyEvent); + } + + void FireDestroyEvent() const + { + if (destroyEvent_) { + destroyEvent_(); + } + } + + void SetOnSurfaceInitEvent(ExternalEvent&& surfaceInitEvent) + { + surfaceInitEvent_ = std::move(surfaceInitEvent); + } + + void FireSurfaceInitEvent(const std::string& componentId, const uint32_t nodeId) const + { + if (surfaceInitEvent_) { + surfaceInitEvent_(componentId, nodeId, false); + } + } + + void SetOnSurfaceDestroyEvent(DestroyEvent&& surfaceDestroyEvent) + { + surfaceDestroyEvent_ = std::move(surfaceDestroyEvent); + } + + void FireSurfaceDestroyEvent() const + { + if (surfaceDestroyEvent_) { + surfaceDestroyEvent_(); + } + } + +private: + LoadEvent loadEvent_; + DestroyEvent destroyEvent_; + ExternalEvent surfaceInitEvent_; + DestroyEvent surfaceDestroyEvent_; +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_XCOMPONENT_XCOMPONENT_EVENT_HUB_H diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.cpp new file mode 100644 index 00000000000..1f0306f3c2c --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.cpp @@ -0,0 +1,30 @@ +/* + * 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/pattern/xcomponent/xcomponent_layout_algorithm.h" +#include "base/utils/utils.h" + +namespace OHOS::Ace::NG { +XComponentLayoutAlgorithm::XComponentLayoutAlgorithm() = default; + +std::optional XComponentLayoutAlgorithm::MeasureContent( + const LayoutConstraintF& contentConstraint, LayoutWrapper* /* layoutWrapper */) +{ + if (contentConstraint.selfIdealSize.IsValid()) { + return contentConstraint.selfIdealSize.ConvertToSizeT(); + } + return contentConstraint.maxSize; +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.h b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.h new file mode 100644 index 00000000000..69d8fa55ba1 --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.h @@ -0,0 +1,43 @@ +/* + * 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_PATTERN_XCOMPONENT_XCOMPONENT_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_XCOMPONENT_XCOMPONENT_LAYOUT_ALGORITHM_H + +#include + +#include "core/components_ng/layout/box_layout_algorithm.h" +#include "core/components_ng/layout/layout_wrapper.h" + +namespace OHOS::Ace::NG { +class PipelineContext; + +class ACE_EXPORT XComponentLayoutAlgorithm : public BoxLayoutAlgorithm { + DECLARE_ACE_TYPE(XComponentLayoutAlgorithm, BoxLayoutAlgorithm); + +public: + XComponentLayoutAlgorithm(); + + ~XComponentLayoutAlgorithm() override = default; + + std::optional MeasureContent( + const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override; + +private: + ACE_DISALLOW_COPY_AND_MOVE(XComponentLayoutAlgorithm); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_XCOMPONENT_XCOMPONENT_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp new file mode 100644 index 00000000000..367fd8b4349 --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp @@ -0,0 +1,362 @@ +/* + * 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/pattern/xcomponent/xcomponent_pattern.h" + +#include "base/geometry/ng/size_t.h" +#include "base/utils/utils.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_event_hub.h" +#include "core/event/touch_event.h" +#include "core/pipeline/pipeline_context.h" +#include "frameworks/bridge/declarative_frontend/declarative_frontend.h" + + +namespace OHOS::Ace::NG { +XComponentPattern::XComponentPattern(const std::string& id, const std::string& type, const std::string& libraryname, + const RefPtr& xcomponentController) + : id_(id), type_(type), libraryname_(libraryname), xcomponentController_(xcomponentController) +{} + +void XComponentPattern::OnAttachToFrameNode() +{ + auto host = GetHost(); + renderSurface_->SetRenderContext(host->GetRenderContext()); + renderSurface_->InitSurface(); + InitEvent(); + SetMethodCall(); + auto renderContext = host->GetRenderContext(); + renderContext->UpdateBackgroundColor(Color::BLACK); +} + +void XComponentPattern::OnDetachFromFrameNode() +{ + if (!hasXComponentInit_) { + return; + } + NativeXComponentDestroy(); + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto eventHub = host->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->FireSurfaceDestroyEvent(); + // TODO: cannot execute properly for the jsi engine has destroyed + eventHub->FireDestroyEvent(); +} + +void XComponentPattern::SetMethodCall() +{ + CHECK_NULL_VOID(xcomponentController_); + auto pipelineContext = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipelineContext); + auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(), TaskExecutor::TaskType::UI); + xcomponentController_->SetConfigSurfaceImpl( + [weak = WeakClaim(this), uiTaskExecutor](uint32_t surfaceWidth, uint32_t surfaceHeight) { + uiTaskExecutor.PostSyncTask([weak, surfaceWidth, surfaceHeight]() { + auto pattern = weak.Upgrade(); + if (pattern) { + pattern->ConfigSurface(surfaceWidth, surfaceHeight); + } + }); + }); + + xcomponentController_->surfaceId_ = renderSurface_->GetUniqueId(); +} + +void XComponentPattern::ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight) +{ + renderSurface_->ConfigSurface(surfaceWidth, surfaceHeight); +} + +void XComponentPattern::OnLayoutChange( + bool /* frameSizeChange */, bool frameOffsetChange, bool contentSizeChange, bool contentOffsetChange) +{ + if (!hasXComponentInit_) { + hasXComponentInit_ = true; + return; + } + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto geometryNode = host->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + if (frameOffsetChange || contentOffsetChange) { + auto position = geometryNode->GetContentOffset() + geometryNode->GetFrameOffset(); + NativeXComponentOffset(position.GetX(), position.GetY()); + } + if (contentSizeChange) { + auto drawSize = geometryNode->GetContentSize(); + XComponentSizeChange(drawSize.Width(), drawSize.Height()); + } +} + +bool XComponentPattern::OnDirtyLayoutWrapperSwap( + const RefPtr& dirty, bool skipMeasure, bool /* skipLayout */) +{ + if (skipMeasure || dirty->SkipMeasureContent()) { + return false; + } + auto geometryNode = dirty->GetGeometryNode(); + CHECK_NULL_RETURN(geometryNode, false); + + if (!hasXComponentInit_) { + auto position = geometryNode->GetContentOffset() + geometryNode->GetFrameOffset(); + auto drawSize = geometryNode->GetContentSize(); + NativeXComponentOffset(position.GetX(), position.GetY()); + XComponentSizeInit(drawSize.Width(), drawSize.Height()); + } + return true; +} + +void XComponentPattern::OnPaint() +{ + auto host = GetHost(); + auto renderContext = host->GetRenderContext(); + renderContext->UpdateBackgroundColor(Color::BLACK); +} + +void XComponentPattern::NativeXComponentChange(float width, float height) +{ + auto pipelineContext = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipelineContext); + pipelineContext->GetTaskExecutor()->PostTask( + [weakNXCompImpl = nativeXComponentImpl_, nXComp = nativeXComponent_, width, height] { + auto nXCompImpl = weakNXCompImpl.Upgrade(); + if (nXComp && nXCompImpl) { + nXCompImpl->SetXComponentWidth(static_cast(width)); + nXCompImpl->SetXComponentHeight(static_cast(height)); + auto* surface = const_cast(nXCompImpl->GetSurface()); + const auto* callback = nXCompImpl->GetCallback(); + if (callback && callback->OnSurfaceChanged != nullptr) { + callback->OnSurfaceChanged(nXComp, surface); + } + } else { + LOGE("Native XComponent nullptr"); + } + }, + TaskExecutor::TaskType::JS); +} + +void XComponentPattern::NativeXComponentDestroy() +{ + // TODO: need to use pipelineContext to ensure the following run on JS thread + auto nXCompImpl = nativeXComponentImpl_.Upgrade(); + if (nativeXComponent_ != nullptr && nXCompImpl) { + auto* surface = const_cast(nXCompImpl->GetSurface()); + const auto* callback = nXCompImpl->GetCallback(); + if (callback != nullptr && callback->OnSurfaceDestroyed != nullptr) { + callback->OnSurfaceDestroyed(nativeXComponent_, surface); + } + } else { + LOGE("Native XComponent nullptr"); + } +} + +void XComponentPattern::NativeXComponentOffset(double x, double y) +{ + auto pipelineContext = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipelineContext); + float scale = pipelineContext->GetViewScale(); + pipelineContext->GetTaskExecutor()->PostTask( + [weakNXCompImpl = nativeXComponentImpl_, x, y, scale] { + auto nXCompImpl = weakNXCompImpl.Upgrade(); + if (nXCompImpl) { + nXCompImpl->SetXComponentOffsetX(x * scale); + nXCompImpl->SetXComponentOffsetY(y * scale); + } + }, + TaskExecutor::TaskType::JS); +} + +void XComponentPattern::NativeXComponentDispatchTouchEvent(const OH_NativeXComponent_TouchEvent& touchEvent) +{ + auto pipelineContext = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipelineContext); + pipelineContext->GetTaskExecutor()->PostTask( + [weakNXCompImpl = nativeXComponentImpl_, nXComp = nativeXComponent_, touchEvent] { + auto nXCompImpl = weakNXCompImpl.Upgrade(); + if (nXComp != nullptr && nXCompImpl) { + nXCompImpl->SetTouchEvent(touchEvent); + auto* surface = const_cast(nXCompImpl->GetSurface()); + const auto* callback = nXCompImpl->GetCallback(); + if (callback != nullptr && callback->DispatchTouchEvent != nullptr) { + callback->DispatchTouchEvent(nXComp, surface); + } + } else { + LOGE("Native XComponent nullptr"); + } + }, + TaskExecutor::TaskType::JS); +} + +void XComponentPattern::XComponentSizeInit(float textureWidth, float textureHeight) +{ + auto host = GetHost(); + auto context = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(context); + + if (renderSurface_->IsSurfaceValid()) { + float viewScale = context->GetViewScale(); + renderSurface_->CreateNativeWindow(); + renderSurface_->AdjustNativeWindowSize( + static_cast(textureWidth * viewScale), static_cast(textureHeight * viewScale)); + } + + auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::JS); + platformTaskExecutor.PostTask([weak = WeakClaim(this)] { + auto pattern = weak.Upgrade(); + if (pattern) { + auto xcId = pattern->GetId(); + auto host = pattern->GetHost(); + auto eventHub = host->GetEventHub(); + eventHub->FireSurfaceInitEvent(xcId, host->GetId()); + eventHub->FireLoadEvent(xcId); + } + }); +} + +void XComponentPattern::XComponentSizeChange(float textureWidth, float textureHeight) +{ + auto context = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(context); + auto viewScale = context->GetViewScale(); + renderSurface_->AdjustNativeWindowSize( + static_cast(textureWidth * viewScale), static_cast(textureHeight * viewScale)); + NativeXComponentChange(textureWidth, textureHeight); +} + +void XComponentPattern::InitEvent() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto eventHub = host->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnSurfaceInitEvent(CreateExternalEvent()); + auto gestureHub = eventHub->GetOrCreateGestureEventHub(); + CHECK_NULL_VOID(gestureHub); + InitTouchEvent(gestureHub); +} + +void XComponentPattern::InitTouchEvent(const RefPtr& gestureHub) +{ + if (touchEvent_) { + return; + } + + auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo info) { + auto pattern = weak.Upgrade(); + if (pattern) { + pattern->HandleTouchEvent(info); + } + }; + + touchEvent_ = MakeRefPtr(std::move(touchTask)); + gestureHub->AddTouchEvent(touchEvent_); +} + +void XComponentPattern::HandleTouchEvent(const TouchEventInfo& info) +{ + auto touchInfoList = info.GetTouches(); + if (touchInfoList.empty()) { + return; + } + const auto& locationInfo = touchInfoList.front(); + const auto& screenOffset = locationInfo.GetGlobalLocation(); + const auto& localOffset = locationInfo.GetLocalLocation(); + touchEventPoint_.id = locationInfo.GetFingerId(); + touchEventPoint_.screenX = static_cast(screenOffset.GetX()); + touchEventPoint_.screenY = static_cast(screenOffset.GetY()); + touchEventPoint_.x = static_cast(localOffset.GetX()); + touchEventPoint_.y = static_cast(localOffset.GetY()); + touchEventPoint_.size = locationInfo.GetSize(); + touchEventPoint_.force = locationInfo.GetForce(); + touchEventPoint_.deviceId = locationInfo.GetTouchDeviceId(); + const auto timeStamp = info.GetTimeStamp().time_since_epoch().count(); + touchEventPoint_.timeStamp = timeStamp; + auto touchType = touchInfoList.front().GetTouchType(); + touchEventPoint_.type = ConvertNativeXComponentTouchEvent(touchType); + + SetTouchPoint(touchInfoList, timeStamp, touchType); + + NativeXComponentDispatchTouchEvent(touchEventPoint_); +} + +OH_NativeXComponent_TouchEventType XComponentPattern::ConvertNativeXComponentTouchEvent(const TouchType& touchType) +{ + switch (touchType) { + case TouchType::DOWN: + return OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_DOWN; + case TouchType::UP: + return OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP; + case TouchType::MOVE: + return OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_MOVE; + case TouchType::CANCEL: + return OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_CANCEL; + default: + return OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UNKNOWN; + } +} + +void XComponentPattern::SetTouchPoint( + const std::list& touchInfoList, const int64_t timeStamp, const TouchType& touchType) +{ + touchEventPoint_.numPoints = + touchInfoList.size() <= OH_MAX_TOUCH_POINTS_NUMBER ? touchInfoList.size() : OH_MAX_TOUCH_POINTS_NUMBER; + uint32_t index = 0; + for (auto iterator = touchInfoList.begin(); iterator != touchInfoList.end() && index < OH_MAX_TOUCH_POINTS_NUMBER; + iterator++) { + OH_NativeXComponent_TouchPoint ohTouchPoint; + const auto& pointTouchInfo = *iterator; + const auto& pointScreenOffset = pointTouchInfo.GetGlobalLocation(); + const auto& pointLocalOffset = pointTouchInfo.GetLocalLocation(); + ohTouchPoint.id = pointTouchInfo.GetFingerId(); + ohTouchPoint.screenX = static_cast(pointScreenOffset.GetX()); + ohTouchPoint.screenY = static_cast(pointScreenOffset.GetY()); + ohTouchPoint.x = static_cast(pointLocalOffset.GetX()); + ohTouchPoint.y = static_cast(pointLocalOffset.GetY()); + ohTouchPoint.type = ConvertNativeXComponentTouchEvent(touchType); + ohTouchPoint.size = pointTouchInfo.GetSize(); + ohTouchPoint.force = pointTouchInfo.GetForce(); + ohTouchPoint.timeStamp = timeStamp; + ohTouchPoint.isPressed = (touchType == TouchType::DOWN); + touchEventPoint_.touchPoints[index++] = ohTouchPoint; + } + while (index < OH_MAX_TOUCH_POINTS_NUMBER) { + OH_NativeXComponent_TouchPoint ohTouchPoint; + ohTouchPoint.id = 0; + ohTouchPoint.screenX = 0; + ohTouchPoint.screenY = 0; + ohTouchPoint.x = 0; + ohTouchPoint.y = 0; + ohTouchPoint.type = OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UNKNOWN; + ohTouchPoint.size = 0; + ohTouchPoint.force = 0; + ohTouchPoint.timeStamp = 0; + ohTouchPoint.isPressed = false; + touchEventPoint_.touchPoints[index++] = ohTouchPoint; + } +} + +ExternalEvent XComponentPattern::CreateExternalEvent() +{ + return + [weak = AceType::WeakClaim(this)](const std::string& componentId, const uint32_t nodeId, const bool isDestroy) { + auto context = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(context); + auto frontEnd = AceType::DynamicCast(context->GetFrontend()); + CHECK_NULL_VOID(frontEnd); + auto jsEngine = frontEnd->GetJsEngine(); + jsEngine->FireExternalEvent(componentId, nodeId, isDestroy); + }; +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h new file mode 100644 index 00000000000..6b23e87f615 --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h @@ -0,0 +1,148 @@ +/* + * 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_PATTERNS_XCOMPONENT_XCOMPONENT_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_XCOMPONENT_XCOMPONENT_PATTERN_H + +#include +#include + +#include "base/geometry/dimension.h" +#include "base/geometry/size.h" +#include "base/memory/referenced.h" +#include "base/utils/utils.h" +#include "core/components/xcomponent/resource/native_texture.h" +#include "core/components/xcomponent/xcomponent_component.h" +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_event_hub.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_layout_algorithm.h" +#include "core/components_ng/property/property.h" +#include "core/components_ng/render/render_surface.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { +class XComponentPattern : public Pattern { + DECLARE_ACE_TYPE(XComponentPattern, Pattern); + +public: + XComponentPattern() = default; + XComponentPattern(const std::string& id, const std::string& type, const std::string& libraryname, + const RefPtr& xcomponentController); + ~XComponentPattern() override = default; + + std::optional SurfaceNodeName() const override + { + return id_ + "Surface"; + } + + RefPtr CreateEventHub() override + { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override + { + return MakeRefPtr(); + } + + void NativeXComponentInit(OH_NativeXComponent* nativeXComponent, WeakPtr nativeXComponentImpl) + { + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto pipelineContext = host->GetContext(); + CHECK_NULL_VOID(pipelineContext); + auto geometryNode = host->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + nativeXComponent_ = nativeXComponent; + nativeXComponentImpl_ = std::move(nativeXComponentImpl); + auto width = geometryNode->GetContentSize().Width(); + auto height = geometryNode->GetContentSize().Height(); + + pipelineContext->GetTaskExecutor()->PostTask( + [weakNXCompImpl = nativeXComponentImpl_, nXComp = nativeXComponent_, width, height] { + auto nXCompImpl = weakNXCompImpl.Upgrade(); + if (nXComp && nXCompImpl) { + nXCompImpl->SetXComponentWidth(static_cast(width)); + nXCompImpl->SetXComponentHeight(static_cast(height)); + auto* surface = const_cast(nXCompImpl->GetSurface()); + const auto* callback = nXCompImpl->GetCallback(); + if (callback && callback->OnSurfaceCreated != nullptr) { + callback->OnSurfaceCreated(nXComp, surface); + } + } else { + LOGE("Native XComponent nullptr"); + } + }, + TaskExecutor::TaskType::JS); + } + void OnPaint(); + void NativeXComponentOffset(double x, double y); + void NativeXComponentChange(float width, float height); + void NativeXComponentDestroy(); + void NativeXComponentDispatchTouchEvent(const OH_NativeXComponent_TouchEvent& touchEvent); + + void XComponentSizeInit(float textureWidth, float textureHeight); + void XComponentSizeChange(float textureWidth, float textureHeight); + + void* GetNativeWindow() + { + return renderSurface_->GetNativeWindow(); + } + + const std::string& GetId() const + { + return id_; + } + + const std::string& GetLibraryName() const + { + return libraryname_; + } + +private: + void OnAttachToFrameNode() override; + void OnDetachFromFrameNode() override; + void OnLayoutChange( + bool frameSizeChange, bool frameOffsetChange, bool contentSizeChange, bool contentOffsetChange) override; + bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; + void InitEvent(); + void InitTouchEvent(const RefPtr& gestureHub); + void HandleTouchEvent(const TouchEventInfo& info); + ExternalEvent CreateExternalEvent(); + void CreateSurface(); + void SetMethodCall(); + void ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight); + void SetTouchPoint( + const std::list& touchInfoList, int64_t timeStamp, const TouchType& touchType); + static OH_NativeXComponent_TouchEventType ConvertNativeXComponentTouchEvent(const TouchType& touchType); + + std::string id_; + std::string type_; + std::string libraryname_; + RefPtr xcomponentController_; + + RefPtr renderSurface_ = RenderSurface::Create(); + + OH_NativeXComponent* nativeXComponent_ = nullptr; + WeakPtr nativeXComponentImpl_; + + bool hasXComponentInit_ = false; + + RefPtr touchEvent_; + OH_NativeXComponent_TouchEvent touchEventPoint_; +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_XCOMPONENT_XCOMPONENT_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.cpp b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.cpp new file mode 100644 index 00000000000..162ab416741 --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.cpp @@ -0,0 +1,58 @@ +/* + * 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/pattern/xcomponent/xcomponent_view.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_event_hub.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_pattern.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { +void XComponentView::Create(const std::string& id, const std::string& type, const std::string& libraryname, + const RefPtr& xcomponentController) +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode( + V2::XCOMPONENT_ETS_TAG, nodeId, [id, type, libraryname, xcomponentController]() { + return AceType::MakeRefPtr(id, type, libraryname, xcomponentController); + }); + stack->Push(frameNode); +} +void XComponentView::SetOnLoad(LoadEvent&& onLoad) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnLoad(std::move(onLoad)); +} +void XComponentView::SetOnDestroy(DestroyEvent&& onDestroy) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnDestroy(std::move(onDestroy)); +} +void XComponentView::SetOnSurfaceDestroyEvent(DestroyEvent&& onSurfaceDestroyEvent) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnSurfaceDestroyEvent(std::move(onSurfaceDestroyEvent)); +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.h b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.h new file mode 100644 index 00000000000..3800878d46f --- /dev/null +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_view.h @@ -0,0 +1,37 @@ +/* + * 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_PATTERNS_XCOMPONENT_XCOMPONENT_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_XCOMPONENT_XCOMPONENT_VIEW_H + +#include + +#include "base/geometry/dimension.h" +#include "base/utils/macros.h" +#include "core/components/xcomponent/xcomponent_component.h" +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_event_hub.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT XComponentView { +public: + static void Create(const std::string& id, const std::string& type, const std::string& libraryname, + const RefPtr& xcomponentController); + static void SetOnLoad(LoadEvent&& onLoad); + static void SetOnDestroy(DestroyEvent&& onDestroy); + static void SetOnSurfaceDestroyEvent(DestroyEvent&& onSurfaceDestroyEvent); +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_XCOMPONENT_XCOMPONENT_VIEW_H diff --git a/frameworks/core/components_ng/render/BUILD.gn b/frameworks/core/components_ng/render/BUILD.gn index f1444a803bc..08db1f90a0a 100644 --- a/frameworks/core/components_ng/render/BUILD.gn +++ b/frameworks/core/components_ng/render/BUILD.gn @@ -27,6 +27,7 @@ build_component_ng("render_ng") { "image_painter.cpp", "paint_wrapper.cpp", "render_context_creator.cpp", + "render_surface_creator.cpp", ] if (enable_ng_build) { @@ -34,12 +35,14 @@ build_component_ng("render_ng") { "adapter/flutter_canvas_image.cpp", "adapter/flutter_node.cpp", "adapter/flutter_render_context.cpp", + "adapter/flutter_render_surface.cpp", "adapter/flutter_window.cpp", ] } rosen_sources = [ "adapter/rosen_render_context.cpp", + "adapter/rosen_render_surface.cpp", "adapter/rosen_window.cpp", ] } diff --git a/frameworks/core/components_ng/render/adapter/flutter_render_context.cpp b/frameworks/core/components_ng/render/adapter/flutter_render_context.cpp index bc6f1977f58..8add9f13ab1 100644 --- a/frameworks/core/components_ng/render/adapter/flutter_render_context.cpp +++ b/frameworks/core/components_ng/render/adapter/flutter_render_context.cpp @@ -61,7 +61,7 @@ void FlutterRenderContext::StopRecordingIfNeeded() } } -void FlutterRenderContext::InitContext(bool isRoot) +void FlutterRenderContext::InitContext(bool isRoot, const std::optional& surfaceName) { LOGD("InitContext root:%d", isRoot); flutterNode_ = std::make_shared(isRoot); diff --git a/frameworks/core/components_ng/render/adapter/flutter_render_context.h b/frameworks/core/components_ng/render/adapter/flutter_render_context.h index 7623cfd3c50..51abb5ec345 100644 --- a/frameworks/core/components_ng/render/adapter/flutter_render_context.h +++ b/frameworks/core/components_ng/render/adapter/flutter_render_context.h @@ -32,7 +32,7 @@ public: FlutterRenderContext() = default; ~FlutterRenderContext() override; - void InitContext(bool isRoot) override; + void InitContext(bool isRoot, const std::optional& surfaceName) override; void SyncGeometryProperties(GeometryNode* geometryNode) override; diff --git a/frameworks/core/components_ng/render/adapter/flutter_render_surface.h b/frameworks/core/components_ng/render/adapter/flutter_render_surface.h new file mode 100644 index 00000000000..48c22ea547f --- /dev/null +++ b/frameworks/core/components_ng/render/adapter/flutter_render_surface.h @@ -0,0 +1,34 @@ +/* + * 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_PAINTS_ADAPTER_FLUTTER_RENDER_SURFACE_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_FLUTTER_RENDER_SURFACE_H + +#include "base/utils/noncopyable.h" +#include "core/components_ng/render/render_surface.h" + +namespace OHOS::Ace::NG { +class FlutterRenderSurface : public RenderSurface { + DECLARE_ACE_TYPE(FlutterRenderSurface, NG::RenderSurface) +public: + FlutterRenderSurface() = default; + ~FlutterRenderSurface() override = default; + +private: + ACE_DISALLOW_COPY_AND_MOVE(FlutterRenderSurface); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_FLUTTER_RENDER_SURFACE_H diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp b/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp index 316a180f904..329f605d208 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp @@ -26,6 +26,7 @@ #include "core/components_ng/render/adapter/skia_canvas.h" #include "core/components_ng/render/canvas.h" #include "core/components_ng/render/drawing.h" +#include "render_service_client/core/ui/rs_surface_node.h" namespace OHOS::Ace::NG { RosenRenderContext::~RosenRenderContext() @@ -66,10 +67,13 @@ void RosenRenderContext::StopRecordingIfNeeded() } } -void RosenRenderContext::InitContext(bool isRoot) +void RosenRenderContext::InitContext(bool isRoot, const std::optional& surfaceName) { if (!rsNode_) { - if (isRoot) { + if (surfaceName.has_value()) { + struct Rosen::RSSurfaceNodeConfig surfaceNodeConfig = { .SurfaceNodeName = surfaceName.value() }; + rsNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, false); + } else if (isRoot) { LOGI("create RSRootNode"); rsNode_ = Rosen::RSRootNode::Create(); } else { @@ -87,7 +91,13 @@ void RosenRenderContext::SyncGeometryProperties(GeometryNode* geometryNode) return; } const auto& frameRect = geometryNode->GetFrame().GetRect(); - rsNode_->SetBounds(frameRect.GetX(), frameRect.GetY(), frameRect.Width(), frameRect.Height()); + if (rsNode_->GetType() == Rosen::RSUINodeType::SURFACE_NODE) { + const auto& contentRect = geometryNode->GetContent()->GetRect(); + rsNode_->SetBounds(frameRect.GetX() + contentRect.GetX(), frameRect.GetY() + contentRect.GetY(), + contentRect.Width(), contentRect.Height()); + } else { + rsNode_->SetBounds(frameRect.GetX(), frameRect.GetY(), frameRect.Width(), frameRect.Height()); + } rsNode_->SetFrame(frameRect.GetX(), frameRect.GetY(), frameRect.Width(), frameRect.Height()); } diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_context.h b/frameworks/core/components_ng/render/adapter/rosen_render_context.h index 5586be99ebe..6420567ea91 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_context.h +++ b/frameworks/core/components_ng/render/adapter/rosen_render_context.h @@ -35,7 +35,7 @@ public: RosenRenderContext() = default; ~RosenRenderContext() override; - void InitContext(bool isRoot) override; + void InitContext(bool isRoot, const std::optional& surfaceName) override; void SyncGeometryProperties(GeometryNode* geometryNode) override; diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp b/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp new file mode 100644 index 00000000000..d087bc7e121 --- /dev/null +++ b/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp @@ -0,0 +1,109 @@ +/* + * 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/render/adapter/rosen_render_surface.h" + +#include "foundation/graphic/graphic_2d/interfaces/inner_api/surface/surface_utils.h" +#include "render_service_client/core/ui/rs_surface_node.h" +#include "base/memory/referenced.h" +#include "core/components_ng/render/adapter/rosen_render_context.h" + +namespace OHOS::Ace::NG { +namespace { +const char * const SURFACE_STRIDE_ALIGNMENT = "8"; +constexpr int32_t SURFACE_QUEUE_SIZE = 5; +} // namespace +RosenRenderSurface::~RosenRenderSurface() +{ + if (producerSurface_) { + auto* surfaceUtils = SurfaceUtils::GetInstance(); + auto ret = surfaceUtils->Remove(producerSurface_->GetUniqueId()); + if (ret != SurfaceError::SURFACE_ERROR_OK) { + LOGE("remove surface error: %{public}d", ret); + } + } +} + +void RosenRenderSurface::InitSurface() +{ + CreateSurface(); + + CHECK_NULL_VOID(producerSurface_); + + auto* surfaceUtils = SurfaceUtils::GetInstance(); + auto ret = surfaceUtils->Add(producerSurface_->GetUniqueId(), producerSurface_); + if (ret != SurfaceError::SURFACE_ERROR_OK) { + LOGE("xcomponent add surface error: %{public}d", ret); + } + + producerSurface_->SetQueueSize(SURFACE_QUEUE_SIZE); + producerSurface_->SetUserData("SURFACE_STRIDE_ALIGNMENT", SURFACE_STRIDE_ALIGNMENT); + producerSurface_->SetUserData("SURFACE_FORMAT", std::to_string(PIXEL_FMT_RGBA_8888)); +} + +void* RosenRenderSurface::GetNativeWindow() +{ + return nativeWindow_; +} + +void RosenRenderSurface::CreateSurface() +{ + auto renderContext = renderContext_.Upgrade(); + CHECK_NULL_VOID(renderContext); + + auto rosenRenderContext = AceType::DynamicCast(renderContext); + auto surfaceNode = + OHOS::Rosen::RSBaseNode::ReinterpretCast(rosenRenderContext->GetRSNode()); + if (surfaceNode) { + producerSurface_ = surfaceNode->GetSurface(); + } +} + +void RosenRenderSurface::SetRenderContext(const RefPtr& renderContext) +{ + renderContext_ = WeakClaim(RawPtr(renderContext)); +} + +void RosenRenderSurface::ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight) +{ + if (producerSurface_) { + producerSurface_->SetUserData("SURFACE_WIDTH", std::to_string(surfaceWidth)); + producerSurface_->SetUserData("SURFACE_HEIGHT", std::to_string(surfaceHeight)); + } +} + +bool RosenRenderSurface::IsSurfaceValid() const +{ + return producerSurface_ != nullptr; +} + +void RosenRenderSurface::CreateNativeWindow() +{ + nativeWindow_ = CreateNativeWindowFromSurface(&producerSurface_); +} + +void RosenRenderSurface::AdjustNativeWindowSize(uint32_t width, uint32_t height) +{ + if (nativeWindow_) { + NativeWindowHandleOpt(nativeWindow_, SET_BUFFER_GEOMETRY, width, height); + } else { + LOGE("nativeWindow is null"); + } +} + +std::string RosenRenderSurface::GetUniqueId() const +{ + return std::to_string(producerSurface_->GetUniqueId()); +} +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_surface.h b/frameworks/core/components_ng/render/adapter/rosen_render_surface.h new file mode 100644 index 00000000000..d90de6ffebc --- /dev/null +++ b/frameworks/core/components_ng/render/adapter/rosen_render_surface.h @@ -0,0 +1,59 @@ +/* + * 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_PAINTS_ADAPTER_ROSEN_RENDER_SURFACE_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_ROSEN_RENDER_SURFACE_H + +#include "base/memory/referenced.h" +#include "base/utils/noncopyable.h" +#include "core/components_ng/render/render_surface.h" +#include "foundation/graphic/graphic_2d/interfaces/inner_api/surface/window.h" +#include "foundation/graphic/graphic_2d/interfaces/inner_api/surface/surface.h" + +namespace OHOS::Ace::NG { +class RosenRenderSurface : public RenderSurface { + DECLARE_ACE_TYPE(RosenRenderSurface, NG::RenderSurface) +public: + RosenRenderSurface() = default; + ~RosenRenderSurface() override; + + void InitSurface() override; + + void* GetNativeWindow() override; + + void CreateSurface() override; + + void SetRenderContext(const RefPtr& renderContext) override; + + void ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight) override; + + bool IsSurfaceValid() const override; + + void CreateNativeWindow() override; + + void AdjustNativeWindowSize(uint32_t width, uint32_t height) override; + + std::string GetUniqueId() const override; + +private: + OHOS::sptr producerSurface_ = nullptr; + struct NativeWindow *nativeWindow_ = nullptr; + WeakPtr renderContext_ = nullptr; + + ACE_DISALLOW_COPY_AND_MOVE(RosenRenderSurface); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_ROSEN_RENDER_SURFACE_H diff --git a/frameworks/core/components_ng/render/render_context.h b/frameworks/core/components_ng/render/render_context.h index e21327b9d1d..53c9e208685 100644 --- a/frameworks/core/components_ng/render/render_context.h +++ b/frameworks/core/components_ng/render/render_context.h @@ -58,7 +58,7 @@ public: virtual void SyncGeometryProperties(GeometryNode* geometryNode) {} - virtual void InitContext(bool isRoot) {} + virtual void InitContext(bool isRoot, const std::optional& surfaceName) {} virtual void StartRecording() {} virtual void StopRecordingIfNeeded() {} diff --git a/frameworks/core/components_ng/render/render_surface.h b/frameworks/core/components_ng/render/render_surface.h new file mode 100644 index 00000000000..3cc9f416088 --- /dev/null +++ b/frameworks/core/components_ng/render/render_surface.h @@ -0,0 +1,69 @@ +/* + * 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_PAINTS_RENDER_SURFACE_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_RENDER_SURFACE_H + +#include + +#include "base/memory/ace_type.h" +#include "base/utils/noncopyable.h" +#include "core/components_ng/render/render_context.h" + +namespace OHOS::Ace::NG { +// RenderSurface is used for SurfaceNode +class RenderSurface : public virtual AceType { + DECLARE_ACE_TYPE(NG::RenderSurface, AceType) + +public: + ~RenderSurface() override = default; + + static RefPtr Create(); + + virtual void InitSurface() {} + + virtual void* GetNativeWindow() + { + return nullptr; + } + + virtual void CreateSurface() {} + + virtual void SetRenderContext(const RefPtr& renderContext) {}; + + virtual void ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight) {}; + + virtual bool IsSurfaceValid() const + { + return false; + } + + virtual void CreateNativeWindow() {}; + + virtual void AdjustNativeWindowSize(uint32_t width, uint32_t height) {} + + virtual std::string GetUniqueId() const + { + return ""; + } + +protected: + RenderSurface() = default; + + ACE_DISALLOW_COPY_AND_MOVE(RenderSurface); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_RENDER_SURFACE_H diff --git a/frameworks/core/components_ng/render/render_surface_creator.cpp b/frameworks/core/components_ng/render/render_surface_creator.cpp new file mode 100644 index 00000000000..e61077550f5 --- /dev/null +++ b/frameworks/core/components_ng/render/render_surface_creator.cpp @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifdef ENABLE_ROSEN_BACKEND +#include "core/components_ng/render/adapter/rosen_render_surface.h" +#endif +#ifdef NG_BUILD +#include "core/components_ng/render/adapter/flutter_render_surface.h" +#endif +#include "core/components_ng/render/render_surface.h" + +namespace OHOS::Ace::NG { +RefPtr RenderSurface::Create() +{ + if (SystemProperties::GetRosenBackendEnabled()) { +#ifdef ENABLE_ROSEN_BACKEND + return MakeRefPtr(); +#endif + } +#ifdef NG_BUILD + return MakeRefPtr(); +#else + return nullptr; +#endif +} +} // namespace OHOS::Ace::NG From ac8062a7262d340ff79682f257a41dd2ce475428 Mon Sep 17 00:00:00 2001 From: xuzhidan Date: Fri, 2 Sep 2022 11:04:09 +0800 Subject: [PATCH 19/35] Fix the problem that date and time picker dialog does not have title. Signed-off-by: xuzhidan Change-Id: I79f6063874a74f01e77e84864220a47b5db7f1a7 --- frameworks/core/components/picker/picker_base_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/core/components/picker/picker_base_component.cpp b/frameworks/core/components/picker/picker_base_component.cpp index 9a62c0a52a2..de82b2dc857 100644 --- a/frameworks/core/components/picker/picker_base_component.cpp +++ b/frameworks/core/components/picker/picker_base_component.cpp @@ -419,7 +419,7 @@ void PickerBaseComponent::InitializeTitle(std::list>& outChild LOGE("theme is null."); return; } - if (isDialog_ && hasTitle_) { + if ((isDialog_ || isCreateDialogComponent_) && hasTitle_) { auto triangle = AceType::MakeRefPtr(); triangle->SetPadding(8.0_vp); // all padding triangle->SetWidth(25.0_vp); // left padding + it width + right padding = 8dp + 9dp + 8dp From 397f6267bef1648d7c0fcb35698a96f86bd47086 Mon Sep 17 00:00:00 2001 From: liwenzhen Date: Wed, 31 Aug 2022 09:37:16 +0800 Subject: [PATCH 20/35] add rating ng Signed-off-by: liwenzhen Change-Id: I12c0bee2c467dc818218688e6371202a3976eba1 --- .../declarative_frontend/jsview/js_rating.cpp | 41 ++- .../core/components_ng/pattern/BUILD.gn | 4 + .../rating/rating_layout_algorithm.cpp | 76 +++++ .../pattern/rating/rating_layout_algorithm.h | 60 ++++ .../pattern/rating/rating_layout_property.h | 64 +++++ .../pattern/rating/rating_paint_method.cpp | 95 +++++++ .../pattern/rating/rating_paint_method.h | 50 ++++ .../pattern/rating/rating_pattern.cpp | 268 ++++++++++++++++++ .../pattern/rating/rating_pattern.h | 107 +++++++ .../pattern/rating/rating_property_group.h | 38 +++ .../pattern/rating/rating_render_property.h | 58 ++++ .../pattern/rating/rating_view.cpp | 69 +++++ .../pattern/rating/rating_view.h | 37 +++ 13 files changed, 959 insertions(+), 8 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.cpp create mode 100644 frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.h create mode 100644 frameworks/core/components_ng/pattern/rating/rating_layout_property.h create mode 100644 frameworks/core/components_ng/pattern/rating/rating_paint_method.cpp create mode 100644 frameworks/core/components_ng/pattern/rating/rating_paint_method.h create mode 100644 frameworks/core/components_ng/pattern/rating/rating_pattern.cpp create mode 100644 frameworks/core/components_ng/pattern/rating/rating_pattern.h create mode 100644 frameworks/core/components_ng/pattern/rating/rating_property_group.h create mode 100644 frameworks/core/components_ng/pattern/rating/rating_render_property.h create mode 100644 frameworks/core/components_ng/pattern/rating/rating_view.cpp create mode 100644 frameworks/core/components_ng/pattern/rating/rating_view.h diff --git a/frameworks/bridge/declarative_frontend/jsview/js_rating.cpp b/frameworks/bridge/declarative_frontend/jsview/js_rating.cpp index e42b7fe1afe..5f8805d4b3f 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_rating.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_rating.cpp @@ -19,6 +19,7 @@ #include "core/components/box/box_component.h" #include "core/components/rating/rating_component.h" #include "core/components/rating/rating_theme.h" +#include "core/components_ng/pattern/rating/rating_view.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" namespace OHOS::Ace::Framework { @@ -42,6 +43,14 @@ void JSRating::Create(const JSCallbackInfo& info) if (getIndicator->IsBoolean()) { indicator = getIndicator->ToBoolean(); } + + if (Container::IsCurrentUseNewPipeline()) { + NG::RatingView::Create(); + NG::RatingView::SetRatingScore(rating); + NG::RatingView::SetIndicator(indicator); + return; + } + auto component = AceType::MakeRefPtr(); component->SetMouseAnimationType(HoverAnimationType::NONE); component->SetRatingScore(rating); @@ -86,7 +95,6 @@ void JSRating::JSBind(BindingTarget globalObj) JSClass::StaticMethod("stepSize", &JSRating::SetStepSize, opt); JSClass::StaticMethod("starStyle", &JSRating::SetStarStyle, opt); JSClass::StaticMethod("onChange", &JSRating::SetOnChange); - JSClass::StaticMethod("onAppear", &JSInteractableView::JsOnAppear); JSClass::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear); JSClass::StaticMethod("onTouch", &JSInteractableView::JsOnTouch); @@ -110,6 +118,11 @@ void JSRating::SetStars(const JSCallbackInfo& info) return; } + if (Container::IsCurrentUseNewPipeline()) { + NG::RatingView::SetStars(info[0]->ToNumber()); + return; + } + auto stack = ViewStackProcessor::GetInstance(); auto component = AceType::DynamicCast(stack->GetMainComponent()); if (!component) { @@ -131,6 +144,11 @@ void JSRating::SetStepSize(const JSCallbackInfo& info) return; } + if (Container::IsCurrentUseNewPipeline()) { + NG::RatingView::SetStepSize(info[0]->ToNumber()); + return; + } + auto stack = ViewStackProcessor::GetInstance(); auto component = AceType::DynamicCast(stack->GetMainComponent()); if (!component) { @@ -147,13 +165,6 @@ void JSRating::SetStarStyle(const JSCallbackInfo& info) return; } - auto stack = ViewStackProcessor::GetInstance(); - auto component = AceType::DynamicCast(stack->GetMainComponent()); - if (!component) { - LOGE("ratingComponent is null"); - return; - } - auto paramObject = JSRef::Cast(info[0]); auto getBackgroundUri = paramObject->GetProperty("backgroundUri"); auto getForegroundUri = paramObject->GetProperty("foregroundUri"); @@ -177,6 +188,20 @@ void JSRating::SetStarStyle(const JSCallbackInfo& info) secondaryUri = getSecondaryUri->ToString(); } + if (Container::IsCurrentUseNewPipeline()) { + NG::RatingView::SetForegroundSrc(foregroundUri); + NG::RatingView::SetSecondarySrc(secondaryUri); + NG::RatingView::SetBackgroundSrc(backgroundUri); + return; + } + + auto stack = ViewStackProcessor::GetInstance(); + auto component = AceType::DynamicCast(stack->GetMainComponent()); + if (!component) { + LOGE("ratingComponent is null"); + return; + } + component->SetBackgroundSrc(backgroundUri); component->SetForegroundSrc(foregroundUri); component->SetSecondarySrc(secondaryUri); diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index e5f86e868e3..703cef3ae1d 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -37,6 +37,10 @@ build_component_ng("pattern_ng") { "list/list_pattern.cpp", "list/list_view.cpp", "overlay/overlay_manager.cpp", + "rating/rating_layout_algorithm.cpp", + "rating/rating_paint_method.cpp", + "rating/rating_pattern.cpp", + "rating/rating_view.cpp", "scroll/scroll_layout_algorithm.cpp", "scroll/scroll_pattern.cpp", "scroll/scroll_view.cpp", diff --git a/frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.cpp new file mode 100644 index 00000000000..fc890a5138f --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.cpp @@ -0,0 +1,76 @@ +/* + * 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/pattern/rating/rating_layout_algorithm.h" + +#include "base/geometry/dimension.h" +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/pattern/rating/rating_layout_property.h" +#include "core/components_ng/pattern/rating/rating_pattern.h" +#include "core/pipeline_ng/ui_task_scheduler.h" + +namespace OHOS::Ace::NG { +std::optional RatingLayoutAlgorithm::MeasureContent( + const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) +{ + // case 1: rating component is set with valid size, return contentConstraint.selfIdealSize as component size + if (contentConstraint.selfIdealSize.IsValid() && contentConstraint.selfIdealSize.IsNonNegative()) { + return contentConstraint.selfIdealSize.ConvertToSizeT(); + } + + // case 2: Using the theme's height and width by default if rating component is not set size. + auto pipelineContext = PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(pipelineContext, std::nullopt); + auto themeManager = pipelineContext->GetThemeManager(); + CHECK_NULL_RETURN(themeManager, std::nullopt); + auto ratingTheme = themeManager->GetTheme(); + CHECK_NULL_RETURN(ratingTheme, std::nullopt); + + SizeF componentSize; + auto ratingLayoutProperty = DynamicCast(layoutWrapper->GetLayoutProperty()); + // case 2.1: Rating use the mini size specified in the theme, when it is used as indicator. + bool indicator = ratingLayoutProperty->GetIndicator().value_or(false); + if (!indicator) { + componentSize.SetHeight(static_cast(ratingTheme->GetRatingHeight().ConvertToPx())); + componentSize.SetWidth(static_cast(ratingTheme->GetRatingWidth().ConvertToPx())); + } else { + componentSize.SetHeight(static_cast(ratingTheme->GetRatingMiniHeight().ConvertToPx())); + componentSize.SetWidth(static_cast(ratingTheme->GetRatingMiniWidth().ConvertToPx())); + } + return contentConstraint.Constrain(componentSize); +} + +void RatingLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) +{ + BoxLayoutAlgorithm::Layout(layoutWrapper); + // if layout size has not decided yet, resize target can not be calculated + if (!layoutWrapper->GetGeometryNode()->GetContent()) { + return; + } + const auto& ratingSize = layoutWrapper->GetGeometryNode()->GetContentSize(); + auto ratingLayoutProperty = DynamicCast(layoutWrapper->GetLayoutProperty()); + + // step1: calculate single star size. + float singleWidth = + ratingSize.Width() / static_cast(ratingLayoutProperty->GetStars().value_or( + RatingPattern::GetStarNumFromTheme().value_or(DEFAULT_RATING_STAR_NUM))); + SizeF singleStarSize(singleWidth, ratingSize.Height()); + + // step2: make 3 images canvas and set its dst size as single star size. + foregroundLoadingCtx_->MakeCanvasImage(singleStarSize, true, ImageFit::FILL); + secondaryLoadingCtx_->MakeCanvasImage(singleStarSize, true, ImageFit::FILL); + backgroundLoadingCtx_->MakeCanvasImage(singleStarSize, true, ImageFit::FILL); +} + +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.h b/frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.h new file mode 100644 index 00000000000..a10dd80807e --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_layout_algorithm.h @@ -0,0 +1,60 @@ +/* + * 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_PATTERN_RATING_RATING_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_LAYOUT_ALGORITHM_H + +#include "base/geometry/ng/size_t.h" +#include "core/components_ng/image_provider/image_loading_context.h" +#include "core/components_ng/layout/box_layout_algorithm.h" +#include "core/components_ng/layout/layout_wrapper.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT RatingLayoutAlgorithm : public BoxLayoutAlgorithm { + DECLARE_ACE_TYPE(RatingLayoutAlgorithm, BoxLayoutAlgorithm); + +public: + RatingLayoutAlgorithm(); + RatingLayoutAlgorithm(const RefPtr& foregroundLoadingCtx, + const RefPtr& secondaryLoadingCtx, const RefPtr& backgroundLoadingCtx) + : foregroundLoadingCtx_(foregroundLoadingCtx), secondaryLoadingCtx_(secondaryLoadingCtx), + backgroundLoadingCtx_(backgroundLoadingCtx) + {} + + ~RatingLayoutAlgorithm() override = default; + + void OnReset() override + { + foregroundLoadingCtx_ = nullptr; + secondaryLoadingCtx_ = nullptr; + backgroundLoadingCtx_ = nullptr; + } + + std::optional MeasureContent( + const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override; + + void Layout(LayoutWrapper* layoutWrapper) override; + +private: + RefPtr foregroundLoadingCtx_; + RefPtr secondaryLoadingCtx_; + RefPtr backgroundLoadingCtx_; + + ACE_DISALLOW_COPY_AND_MOVE(RatingLayoutAlgorithm); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/rating/rating_layout_property.h b/frameworks/core/components_ng/pattern/rating/rating_layout_property.h new file mode 100644 index 00000000000..8a9dee3aa1b --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_layout_property.h @@ -0,0 +1,64 @@ +/* + * 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_PATTERN_RATING_RATING_LAYOUT_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_LAYOUT_PROPERTY_H + +#include "base/geometry/dimension.h" +#include "core/components_ng/layout/layout_property.h" +#include "core/components_ng/pattern/rating/rating_property_group.h" +#include "core/components_ng/property/property.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT RatingLayoutProperty : public LayoutProperty { + DECLARE_ACE_TYPE(RatingLayoutProperty, LayoutProperty); + +public: + RatingLayoutProperty() = default; + + ~RatingLayoutProperty() override = default; + + RefPtr Clone() const override + { + auto value = MakeRefPtr(); + value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); + value->propRatingPropertyGroup_ = CloneRatingPropertyGroup(); + return value; + } + + void Reset() override + { + LayoutProperty::Reset(); + ResetRatingPropertyGroup(); + } + + ACE_DEFINE_PROPERTY_GROUP(RatingPropertyGroup, RatingPropertyGroup); + + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(RatingPropertyGroup, Indicator, bool, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(RatingPropertyGroup, Stars, int32_t, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP( + RatingPropertyGroup, ForegroundImageSourceInfo, ImageSourceInfo, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP( + RatingPropertyGroup, SecondaryImageSourceInfo, ImageSourceInfo, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP( + RatingPropertyGroup, BackgroundImageSourceInfo, ImageSourceInfo, PROPERTY_UPDATE_MEASURE); + +private: + ACE_DISALLOW_COPY_AND_MOVE(RatingLayoutProperty); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_LAYOUT_PROPERTY_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_paint_method.cpp b/frameworks/core/components_ng/pattern/rating/rating_paint_method.cpp new file mode 100644 index 00000000000..90302552a8a --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_paint_method.cpp @@ -0,0 +1,95 @@ +/* + * 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/pattern/rating/rating_paint_method.h" + +#include "draw/canvas.h" + +#include "base/geometry/ng/offset_t.h" +#include "core/components/rating/rating_theme.h" +#include "core/components_ng/pattern/rating/rating_render_property.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { +CanvasDrawFunction RatingPaintMethod::GetContentDrawFunction(PaintWrapper* paintWrapper) +{ + CHECK_NULL_RETURN(foregroundImageCanvas_, nullptr); + CHECK_NULL_RETURN(secondaryImageCanvas_, nullptr); + CHECK_NULL_RETURN(backgroundImageCanvas_, nullptr); + auto offset = paintWrapper->GetContentOffset(); + + ImagePainter foregroundImagePainter(foregroundImageCanvas_); + ImagePainter secondaryImagePainter(secondaryImageCanvas_); + ImagePainter backgroundPainter(backgroundImageCanvas_); + + auto pipelineContext = PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(pipelineContext, nullptr); + auto themeManager = pipelineContext->GetThemeManager(); + CHECK_NULL_RETURN(themeManager, nullptr); + auto ratingTheme = themeManager->GetTheme(); + CHECK_NULL_RETURN(ratingTheme, nullptr); + + auto ratingRenderProperty = DynamicCast(paintWrapper->GetPaintProperty()); + double ratingScore = ratingRenderProperty->GetRatingScore().value_or(ratingTheme->GetRatingScore()); + double stepSize = ratingRenderProperty->GetStepSize().value_or(ratingTheme->GetStepSize()); + + return [foregroundImagePainter, secondaryImagePainter, backgroundPainter, ratingScore, stepSize, starNum = starNum_, + offset, ImagePaintConfig = singleStarImagePaintConfig_](RSCanvas& canvas) { + // step1: get drewScore based on the stepSize, and it is cannot be greater than starNum. + double drawScore = fmin(Round(ratingScore / stepSize) * stepSize, static_cast(starNum)); + // step2: calculate 3 images repeat times. + int32_t foregroundImageRepeatNum = ceil(drawScore); + double secondaryImageRepeatNum = foregroundImageRepeatNum - drawScore; + int32_t backgroundImageRepeatNum = starNum - foregroundImageRepeatNum; + // step3: draw the foreground images. + canvas.Save(); + auto offsetTemp = offset; + float singleStarWidth = ImagePaintConfig.dstRect_.Width(); + float singleStarHeight = ImagePaintConfig.dstRect_.Height(); + // step3.1: calculate the clip area in order to display the secondary image. + auto clipRect1 = OHOS::Rosen::Drawing::RectF(offset.GetX(), offsetTemp.GetY(), + static_cast(offset.GetX() + singleStarWidth * drawScore), offset.GetY() + singleStarHeight); + canvas.ClipRect(clipRect1, OHOS::Rosen::Drawing::ClipOp::INTERSECT); + for (int32_t i = 0; i < foregroundImageRepeatNum; i++) { + foregroundImagePainter.DrawImage(canvas, offsetTemp, ImagePaintConfig); + offsetTemp.SetX(static_cast(offsetTemp.GetX() + singleStarWidth)); + } + canvas.Restore(); + + // step4: if drawScore is a decimal, it needs to draw the secondary image. + if (secondaryImageRepeatNum != 0) { + canvas.Save(); + auto clipRect2 = OHOS::Rosen::Drawing::RectF( + static_cast(offset.GetX() + singleStarWidth * drawScore), offsetTemp.GetY(), + static_cast(offset.GetX() + singleStarWidth * static_cast(foregroundImageRepeatNum)), + offset.GetY() + singleStarHeight); + // step4.1: calculate the clip area which already occupied by the foreground image. + canvas.ClipRect(clipRect2, OHOS::Rosen::Drawing::ClipOp::INTERSECT); + offsetTemp.SetX(static_cast(offsetTemp.GetX() - singleStarWidth)); + secondaryImagePainter.DrawImage(canvas, offsetTemp, ImagePaintConfig); + offsetTemp.SetX(offsetTemp.GetX() + ImagePaintConfig.dstRect_.Width()); + canvas.Restore(); + } + + // step5: draw background image. + for (int32_t i = 0; i < backgroundImageRepeatNum; i++) { + backgroundPainter.DrawImage(canvas, offsetTemp, ImagePaintConfig); + if (i < backgroundImageRepeatNum - 1) { + offsetTemp.SetX(offsetTemp.GetX() + ImagePaintConfig.dstRect_.Width()); + } + } + }; +} + +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_paint_method.h b/frameworks/core/components_ng/pattern/rating/rating_paint_method.h new file mode 100644 index 00000000000..ff70b0b5e82 --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_paint_method.h @@ -0,0 +1,50 @@ +/* + * 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_PATTERN_RATING_RATING_PAINT_METHOD_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_PAINT_METHOD_H + +#include "core/components_ng/render/image_painter.h" +#include "core/components_ng/render/node_paint_method.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT RatingPaintMethod : public NodePaintMethod { + DECLARE_ACE_TYPE(RatingPaintMethod, NodePaintMethod) +public: + RatingPaintMethod(const RefPtr& foregroundImageCanvas, const RefPtr& secondaryImageCanvas, + const RefPtr& backgroundImageCanvas, const ImagePaintConfig& singleStarImagePaintConfig, + int32_t starNum) + : foregroundImageCanvas_(foregroundImageCanvas), secondaryImageCanvas_(secondaryImageCanvas), + backgroundImageCanvas_(backgroundImageCanvas), singleStarImagePaintConfig_(singleStarImagePaintConfig), + starNum_(starNum) + {} + ~RatingPaintMethod() override = default; + + CanvasDrawFunction GetContentDrawFunction(PaintWrapper* paintWrapper) override; + +private: + RefPtr foregroundImageCanvas_; + RefPtr secondaryImageCanvas_; + RefPtr backgroundImageCanvas_; + + ImagePaintConfig singleStarImagePaintConfig_; + int32_t starNum_ = 0; + + ACE_DISALLOW_COPY_AND_MOVE(RatingPaintMethod); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_PAINT_METHOD_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_pattern.cpp b/frameworks/core/components_ng/pattern/rating/rating_pattern.cpp new file mode 100644 index 00000000000..a61b8326152 --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_pattern.cpp @@ -0,0 +1,268 @@ +/* + * 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/pattern/rating/rating_pattern.h" + +#include + +#include "core/components_ng/pattern/rating/rating_paint_method.h" +#include "core/image/image_source_info.h" + +namespace OHOS::Ace::NG { +constexpr int32_t RATING_IMAGE_SUCCESS_CODE = 0b111; +constexpr int32_t DEFAULT_RATING_STAR_NUM = 5; + +void RatingPattern::CheckImageInfoHasChangedOrNot( + int32_t imageFlag, const ImageSourceInfo& sourceInfo, const std::string& lifeCycleTag) +{ + auto ratingLayoutProperty = GetLayoutProperty(); + CHECK_NULL_VOID(ratingLayoutProperty); + switch (imageFlag) { + case 0b001: + if (ratingLayoutProperty->GetForegroundImageSourceInfo() != sourceInfo) { + LOGW("Foreground image sourceInfo does not match, ignore current %{private}s callback. " + "current: %{private}s vs callback's: %{private}s", + lifeCycleTag.c_str(), ratingLayoutProperty->GetForegroundImageSourceInfo()->ToString().c_str(), + sourceInfo.ToString().c_str()); + return; + } + if (lifeCycleTag == "ImageDataFailed") { + LOGE("Rating load foreground image failed"); + } + break; + case 0b010: + if (ratingLayoutProperty->GetSecondaryImageSourceInfo() != sourceInfo) { + LOGW("Secondary image sourceInfo does not match, ignore current %{private}s callback. " + "current: %{private}s vs callback's: %{private}s", + lifeCycleTag.c_str(), ratingLayoutProperty->GetSecondaryImageSourceInfo()->ToString().c_str(), + sourceInfo.ToString().c_str()); + return; + } + if (lifeCycleTag == "ImageDataFailed") { + LOGE("Rating load secondary image failed"); + } + break; + case 0b100: + if (ratingLayoutProperty->GetBackgroundImageSourceInfo() != sourceInfo) { + LOGW("Background image sourceInfo does not match, ignore current %{private}s callback. " + "current: %{private}s vs callback's: %{private}s", + lifeCycleTag.c_str(), ratingLayoutProperty->GetBackgroundImageSourceInfo()->ToString().c_str(), + sourceInfo.ToString().c_str()); + return; + } + if (lifeCycleTag == "ImageDataFailed") { + LOGE("Rating load background image failed"); + } + break; + default: + break; + } +} + +LoadSuccessNotifyTask RatingPattern::CreateLoadSuccessCallback(int32_t imageFlag) +{ + auto task = [weak = WeakClaim(this), imageFlag](const ImageSourceInfo& sourceInfo) { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + // check image info has changed or not + pattern->CheckImageInfoHasChangedOrNot(imageFlag, sourceInfo, "ImageDataSuccess"); + pattern->OnImageLoadSuccess(imageFlag); + }; + return task; +} + +DataReadyNotifyTask RatingPattern::CreateDataReadyCallback(int32_t imageFlag) +{ + auto task = [weak = WeakClaim(this), imageFlag](const ImageSourceInfo& sourceInfo) { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + // check image info has changed or not + pattern->CheckImageInfoHasChangedOrNot(imageFlag, sourceInfo, "ImageDataReady"); + pattern->OnImageDataReady(imageFlag); + }; + return task; +} + +LoadFailNotifyTask RatingPattern::CreateLoadFailCallback(int32_t imageFlag) +{ + auto task = [weak = WeakClaim(this), imageFlag](const ImageSourceInfo& sourceInfo) { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + // check image info has changed or not + pattern->CheckImageInfoHasChangedOrNot(imageFlag, sourceInfo, "ImageDataFailed"); + }; + return task; +} + +void RatingPattern::OnImageLoadSuccess(int32_t imageFlag) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + if (imageFlag == 0b001) { + foregroundImageCanvas_ = foregroundImageLoadingCtx_->GetCanvasImage(); + singleStarRect_ = foregroundImageLoadingCtx_->GetSrcRect(); + singleStarDstRect_ = foregroundImageLoadingCtx_->GetDstRect(); + imageSuccessStateCode_ = imageFlag | imageSuccessStateCode_; + } + if (imageFlag == 0b010) { + secondaryImageCanvas_ = secondaryImageLoadingCtx_->GetCanvasImage(); + imageSuccessStateCode_ = imageFlag | imageSuccessStateCode_; + } + + if (imageFlag == 0b100) { + backgroundImageCanvas_ = backgroundImageLoadingCtx_->GetCanvasImage(); + imageSuccessStateCode_ = imageFlag | imageSuccessStateCode_; + } + // only when foreground, secondary and background image are all loaded successfully, mark dirty to update rendering. + if (imageSuccessStateCode_ == RATING_IMAGE_SUCCESS_CODE) { + LOGD("Rating foreground, secondary and background image are loaded successfully."); + host->MarkDirtyNode(PROPERTY_UPDATE_RENDER); + } +} + +void RatingPattern::OnImageDataReady(int32_t imageFlag) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + imageReadyStateCode_ = imageReadyStateCode_ | imageFlag; + + // 3 images are ready, invoke to update layout to calculate single star size. + if (imageReadyStateCode_ == RATING_IMAGE_SUCCESS_CODE) { + LOGD("Rating foreground, secondary and background image are ready."); + host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT); + } +} + +RefPtr RatingPattern::CreateNodePaintMethod() +{ + CHECK_NULL_RETURN(foregroundImageCanvas_, nullptr); + CHECK_NULL_RETURN(secondaryImageCanvas_, nullptr); + CHECK_NULL_RETURN(backgroundImageCanvas_, nullptr); + auto starNum = GetLayoutProperty()->GetStars().value_or( + GetStarNumFromTheme().value_or(DEFAULT_RATING_STAR_NUM)); + ImagePaintConfig singleStarImagePaintConfig(singleStarRect_, singleStarDstRect_); + return MakeRefPtr( + foregroundImageCanvas_, secondaryImageCanvas_, backgroundImageCanvas_, singleStarImagePaintConfig, starNum); +} + +bool RatingPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) +{ + if (skipMeasure || dirty->SkipMeasureContent()) { + return false; + } + if (!foregroundImageCanvas_ || !secondaryImageCanvas_ || !backgroundImageCanvas_) { + return false; + } + return true; +} + +ImageSourceInfo RatingPattern::GetImageSourceInfoFromTheme(int32_t imageFlag) +{ + auto pipelineContext = PipelineContext::GetCurrentContext(); + ImageSourceInfo imageSourceInfo; + CHECK_NULL_RETURN(pipelineContext, imageSourceInfo); + auto themeManager = pipelineContext->GetThemeManager(); + CHECK_NULL_RETURN(themeManager, imageSourceInfo); + auto ratingTheme = themeManager->GetTheme(); + CHECK_NULL_RETURN(ratingTheme, imageSourceInfo); + switch (imageFlag) { + case 0b001: + imageSourceInfo.SetResourceId(ratingTheme->GetForegroundResourceId()); + break; + case 0b010: + imageSourceInfo.SetResourceId(ratingTheme->GetSecondaryResourceId()); + break; + case 0b100: + imageSourceInfo.SetResourceId(ratingTheme->GetBackgroundResourceId()); + break; + default: + break; + } + imageSourceInfo.UpdateSrcType(); + return imageSourceInfo; +} + +void RatingPattern::ConstrainsRatingScore() +{ + auto ratingLayoutProperty = GetLayoutProperty(); + auto ratingRenderProperty = GetPaintProperty(); + + // constrains ratingScore and StarNum. + // check if starNum is not positive, assign the value defined in theme. + if (ratingLayoutProperty->HasStars() && ratingLayoutProperty->GetStars().value() <= 0) { + ratingLayoutProperty->UpdateStars(GetStarNumFromTheme().value_or(DEFAULT_RATING_STAR_NUM)); + } + + // if ratingScore > StarsNum, constrain ratingScore value with StarNums. + if (ratingRenderProperty->HasRatingScore() && ratingLayoutProperty->HasStars()) { + if (GreatOrEqual(ratingRenderProperty->GetRatingScore().value(), ratingLayoutProperty->GetStars().value())) { + ratingRenderProperty->UpdateRatingScore(ratingLayoutProperty->GetStars().value()); + } + } + + // if ratingScore < 0, assign the value defined in theme. + if (ratingRenderProperty->HasRatingScore()) { + if (LessOrEqual(ratingRenderProperty->GetRatingScore().value(), 0.0)) { + ratingRenderProperty->UpdateRatingScore(GetRatingScoreFromTheme().value_or(0.0)); + } + } +} + +void RatingPattern::OnModifyDone() +{ + // Reset image state code. + imageReadyStateCode_ = 0; + imageSuccessStateCode_ = 0; + // Constrains ratingScore and starNum in case of the illegal input. + ConstrainsRatingScore(); + + auto ratingLayoutProperty = GetLayoutProperty(); + CHECK_NULL_VOID(ratingLayoutProperty); + + ImageSourceInfo foregroundImageSourceInfo = + ratingLayoutProperty->GetForegroundImageSourceInfo().value_or(GetImageSourceInfoFromTheme(0b001)); + // Recreate ImageLoadingContext only when image source info has changed. + if (!foregroundImageLoadingCtx_ || + (foregroundImageLoadingCtx_ && (foregroundImageLoadingCtx_->GetSourceInfo() != foregroundImageSourceInfo))) { + // Construct the ImageLoadingContext and register the image life cycle callback. + LoadNotifier loadNotifierForegroundImage( + CreateDataReadyCallback(0b001), CreateLoadSuccessCallback(0b001), CreateLoadFailCallback(0b001)); + foregroundImageLoadingCtx_ = + AceType::MakeRefPtr(foregroundImageSourceInfo, std::move(loadNotifierForegroundImage)); + foregroundImageLoadingCtx_->LoadImageData(); + } + + ImageSourceInfo secondaryImageSourceInfo = + ratingLayoutProperty->GetSecondaryImageSourceInfo().value_or(GetImageSourceInfoFromTheme(0b010)); + if (!secondaryImageLoadingCtx_ || + (secondaryImageLoadingCtx_ && secondaryImageLoadingCtx_->GetSourceInfo() != secondaryImageSourceInfo)) { + LoadNotifier loadNotifierSecondaryImage( + CreateDataReadyCallback(0b010), CreateLoadSuccessCallback(0b010), CreateLoadFailCallback(0b010)); + secondaryImageLoadingCtx_ = + AceType::MakeRefPtr(secondaryImageSourceInfo, std::move(loadNotifierSecondaryImage)); + secondaryImageLoadingCtx_->LoadImageData(); + } + + ImageSourceInfo backgroundImageSourceInfo = + ratingLayoutProperty->GetBackgroundImageSourceInfo().value_or(GetImageSourceInfoFromTheme(0b100)); + if (!backgroundImageLoadingCtx_ || + (backgroundImageLoadingCtx_ && backgroundImageLoadingCtx_->GetSourceInfo() != backgroundImageSourceInfo)) { + LoadNotifier loadNotifierBackgroundImage( + CreateDataReadyCallback(0b100), CreateLoadSuccessCallback(0b100), CreateLoadFailCallback(0b100)); + backgroundImageLoadingCtx_ = + AceType::MakeRefPtr(backgroundImageSourceInfo, std::move(loadNotifierBackgroundImage)); + backgroundImageLoadingCtx_->LoadImageData(); + } +} +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_pattern.h b/frameworks/core/components_ng/pattern/rating/rating_pattern.h new file mode 100644 index 00000000000..f2ecf07be43 --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_pattern.h @@ -0,0 +1,107 @@ +/* + * 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_PATTERNS_RATING_RATING_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_RATING_RATING_PATTERN_H + +#include + +#include "core/components/rating/rating_theme.h" +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/pattern/rating/rating_layout_algorithm.h" +#include "core/components_ng/pattern/rating/rating_layout_property.h" +#include "core/components_ng/pattern/rating/rating_render_property.h" +#include "core/components_ng/render/canvas_image.h" + +namespace OHOS::Ace::NG { + +#define ACE_DEFINE_RATING_GET_PROPERTY_FROM_THEME(name, type) \ + static std::optional Get##name##FromTheme() \ + { \ + do { \ + auto pipelineContext = PipelineContext::GetCurrentContext(); \ + CHECK_NULL_RETURN(pipelineContext, std::nullopt); \ + auto themeManager = pipelineContext->GetThemeManager(); \ + CHECK_NULL_RETURN(themeManager, std::nullopt); \ + auto ratingTheme = themeManager->GetTheme(); \ + CHECK_NULL_RETURN(ratingTheme, std::nullopt); \ + return ratingTheme->Get##name(); \ + } while (false); \ + } + +class RatingPattern : public Pattern { + DECLARE_ACE_TYPE(RatingPattern, Pattern); + +public: + RatingPattern() = default; + ~RatingPattern() override = default; + + RefPtr CreateNodePaintMethod() override; + + RefPtr CreateLayoutProperty() override + { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override + { + return MakeRefPtr( + foregroundImageLoadingCtx_, secondaryImageLoadingCtx_, backgroundImageLoadingCtx_); + } + + RefPtr CreatePaintProperty() override + { + return MakeRefPtr(); + } + + // Called on main thread to check if need rerender of the content. + bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; + + ACE_DEFINE_RATING_GET_PROPERTY_FROM_THEME(RatingScore, double); + ACE_DEFINE_RATING_GET_PROPERTY_FROM_THEME(StepSize, double); + ACE_DEFINE_RATING_GET_PROPERTY_FROM_THEME(StarNum, int32_t); + +private: + void OnModifyDone() override; + + void ConstrainsRatingScore(); + void OnImageDataReady(int32_t imageFlag); + void OnImageLoadSuccess(int32_t imageFlag); + void CheckImageInfoHasChangedOrNot( + int32_t imageFlag, const ImageSourceInfo& sourceInfo, const std::string& lifeCycleTag); + static ImageSourceInfo GetImageSourceInfoFromTheme(int32_t imageFlag); + + DataReadyNotifyTask CreateDataReadyCallback(int32_t imageFlag); + LoadSuccessNotifyTask CreateLoadSuccessCallback(int32_t imageFlag); + LoadFailNotifyTask CreateLoadFailCallback(int32_t imageFlag); + + RefPtr foregroundImageLoadingCtx_; + RefPtr secondaryImageLoadingCtx_; + RefPtr backgroundImageLoadingCtx_; + + RefPtr foregroundImageCanvas_; + RefPtr secondaryImageCanvas_; + RefPtr backgroundImageCanvas_; + RectF singleStarDstRect_; + RectF singleStarRect_; + int32_t imageReadyStateCode_ = 0; + int32_t imageSuccessStateCode_ = 0; + + ACE_DISALLOW_COPY_AND_MOVE(RatingPattern); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_RATING_RATING_PATTERN_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_property_group.h b/frameworks/core/components_ng/pattern/rating/rating_property_group.h new file mode 100644 index 00000000000..7cd68f00a02 --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_property_group.h @@ -0,0 +1,38 @@ +/* + * 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_PATTERN_RATING_RATING_PROPERTY_GROUP_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_PROPERTY_GROUP_H + +#include "base/geometry/ng/size_t.h" +#include "base/resource/internal_resource.h" +#include "core/components_ng/property/property.h" +#include "core/image/image_source_info.h" + +namespace OHOS::Ace::NG { +struct RatingPropertyGroup { + ACE_DEFINE_PROPERTY_GROUP_ITEM(RatingScore, double); + ACE_DEFINE_PROPERTY_GROUP_ITEM(Indicator, bool); + ACE_DEFINE_PROPERTY_GROUP_ITEM(Stars, int32_t); + ACE_DEFINE_PROPERTY_GROUP_ITEM(StepSize, double); + + ACE_DEFINE_PROPERTY_GROUP_ITEM(ForegroundImageSourceInfo, ImageSourceInfo); + ACE_DEFINE_PROPERTY_GROUP_ITEM(SecondaryImageSourceInfo, ImageSourceInfo); + ACE_DEFINE_PROPERTY_GROUP_ITEM(BackgroundImageSourceInfo, ImageSourceInfo); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_PROPERTY_GROUP_H diff --git a/frameworks/core/components_ng/pattern/rating/rating_render_property.h b/frameworks/core/components_ng/pattern/rating/rating_render_property.h new file mode 100644 index 00000000000..0b13522869b --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_render_property.h @@ -0,0 +1,58 @@ +/* + * 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_PATTERN_RATING_RATING_RENDER_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_RENDER_PROPERTY_H + +#include + +#include "core/components_ng/property/property.h" +#include "core/components_ng/render/paint_property.h" + +namespace OHOS::Ace::NG { +// PaintProperty are used to set render properties. +class RatingRenderProperty : public PaintProperty { + DECLARE_ACE_TYPE(RatingRenderProperty, PaintProperty) + +public: + RatingRenderProperty() = default; + ~RatingRenderProperty() override = default; + + RefPtr Clone() const override + { + auto renderProperty = MakeRefPtr(); + renderProperty->UpdatePaintProperty(this); + renderProperty->propRatingScore_ = CloneRatingScore(); + renderProperty->propStepSize_ = CloneStepSize(); + return renderProperty; + } + + void Reset() override + { + propRatingScore_.reset(); + propStepSize_.reset(); + } + + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(RatingScore, double, PROPERTY_UPDATE_RENDER); + + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(StepSize, double, PROPERTY_UPDATE_RENDER); + +private: + ACE_DISALLOW_COPY_AND_MOVE(RatingRenderProperty); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_RATING_RATING_RENDER_PROPERTY_H diff --git a/frameworks/core/components_ng/pattern/rating/rating_view.cpp b/frameworks/core/components_ng/pattern/rating/rating_view.cpp new file mode 100644 index 00000000000..659e99b5985 --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_view.cpp @@ -0,0 +1,69 @@ +/* + * 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/pattern/rating/rating_view.h" + +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/rating/rating_pattern.h" +#include "core/components_ng/pattern/rating/rating_render_property.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { +void RatingView::Create() +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode( + V2::RATING_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); +} + +void RatingView::SetRatingScore(double value) +{ + ACE_UPDATE_PAINT_PROPERTY(RatingRenderProperty, RatingScore, value); +} + +void RatingView::SetIndicator(bool value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(RatingLayoutProperty, Indicator, value); +} + +void RatingView::SetStars(int32_t value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(RatingLayoutProperty, Stars, value); +} + +void RatingView::SetStepSize(double value) +{ + ACE_UPDATE_PAINT_PROPERTY(RatingRenderProperty, StepSize, value); +} + +void RatingView::SetForegroundSrc(const std::string& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(RatingLayoutProperty, ForegroundImageSourceInfo, ImageSourceInfo(value)); +} + +void RatingView::SetSecondarySrc(const std::string& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(RatingLayoutProperty, SecondaryImageSourceInfo, ImageSourceInfo(value)); +} + +void RatingView::SetBackgroundSrc(const std::string& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(RatingLayoutProperty, BackgroundImageSourceInfo, ImageSourceInfo(value)); +} + +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/rating/rating_view.h b/frameworks/core/components_ng/pattern/rating/rating_view.h new file mode 100644 index 00000000000..6439cd518ee --- /dev/null +++ b/frameworks/core/components_ng/pattern/rating/rating_view.h @@ -0,0 +1,37 @@ +/* + * 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_PATTERNS_RATING_RATING_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_RATING_RATING_VIEW_H + +#include + +#include "base/utils/macros.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT RatingView { +public: + static void Create(); + static void SetRatingScore(double value); + static void SetIndicator(bool value); + static void SetStars(int32_t value); + static void SetStepSize(double value); + static void SetForegroundSrc(const std::string& value); + static void SetSecondarySrc(const std::string& value); + static void SetBackgroundSrc(const std::string& value); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_RATING_RATING_VIEW_H From 27135b4548ab064c350590e3376141657c7089c5 Mon Sep 17 00:00:00 2001 From: lvjunmao Date: Sat, 27 Aug 2022 18:15:11 +0800 Subject: [PATCH 21/35] web component add w3c drag feature Signed-off-by: lvjunmao Change-Id: I7a2d4e9b9a6770df3f534ca173ce84329fc557d7 --- .../declarative_frontend/jsview/js_web.cpp | 104 +++++++ .../declarative_frontend/jsview/js_web.h | 5 + frameworks/core/components/web/render_web.cpp | 280 +++++++++++++++++- frameworks/core/components/web/render_web.h | 18 +- .../web/resource/web_client_impl.cpp | 10 + .../components/web/resource/web_client_impl.h | 2 +- .../components/web/resource/web_delegate.cpp | 35 ++- .../components/web/resource/web_delegate.h | 17 +- .../core/components/web/rosen_render_web.cpp | 1 + .../core/components/web/web_component.h | 56 ++++ 10 files changed, 521 insertions(+), 7 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_web.cpp b/frameworks/bridge/declarative_frontend/jsview/js_web.cpp index 18a85e4d2e1..c07b38ad470 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_web.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_web.cpp @@ -23,9 +23,11 @@ #include "core/components/web/web_component.h" #include "core/components/web/web_event.h" #include "frameworks/bridge/declarative_frontend/engine/functions/js_click_function.h" +#include "frameworks/bridge/declarative_frontend/engine/functions/js_drag_function.h" #include "frameworks/bridge/declarative_frontend/engine/functions/js_key_function.h" #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h" #include "frameworks/bridge/declarative_frontend/jsview/js_web_controller.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_utils.h" namespace OHOS::Ace::Framework { @@ -1022,6 +1024,11 @@ void JSWeb::JSBind(BindingTarget globalObj) JSClass::StaticMethod("onContextMenuShow", &JSWeb::OnContextMenuShow); JSClass::StaticMethod("onSearchResultReceive", &JSWeb::OnSearchResultReceive); JSClass::StaticMethod("mediaPlayGestureAccess", &JSWeb::MediaPlayGestureAccess); + JSClass::StaticMethod("onDragStart", &JSWeb::JsOnDragStart); + JSClass::StaticMethod("onDragEnter", &JSWeb::JsOnDragEnter); + JSClass::StaticMethod("onDragMove", &JSWeb::JsOnDragMove); + JSClass::StaticMethod("onDragLeave", &JSWeb::JsOnDragLeave); + JSClass::StaticMethod("onDrop", &JSWeb::JsOnDrop); JSClass::StaticMethod("onScroll", &JSWeb::OnScroll); JSClass::Inherit(); JSClass::Bind(globalObj); @@ -2163,4 +2170,101 @@ void JSWeb::OnSearchResultReceive(const JSCallbackInfo& args) auto webComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); webComponent->SetSearchResultReceiveEventId(eventMarker); } + +void JSWeb::JsOnDragStart(const JSCallbackInfo& info) +{ + RefPtr jsOnDragStartFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); + auto onDragStartId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc)]( + const RefPtr& info, const std::string& extraParams) -> DragItemInfo { + DragItemInfo itemInfo; + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo); + + auto ret = func->Execute(info, extraParams); + if (!ret->IsObject()) { + LOGE("builder param is not an object."); + return itemInfo; + } + auto component = ParseDragItemComponent(ret); + if (component) { + LOGI("use custom builder param."); + itemInfo.customComponent = component; + return itemInfo; + } + + auto builderObj = JSRef::Cast(ret); +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) + auto pixmap = builderObj->GetProperty("pixelMap"); + itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap); +#endif + auto extraInfo = builderObj->GetProperty("extraInfo"); + ParseJsString(extraInfo, itemInfo.extraInfo); + component = ParseDragItemComponent(builderObj->GetProperty("builder")); + itemInfo.customComponent = component; + return itemInfo; + }; + auto webComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (webComponent) { + webComponent->SetOnDragStartId(onDragStartId); + } +} + +void JSWeb::JsOnDragEnter(const JSCallbackInfo& info) +{ + RefPtr jsOnDragEnterFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); + auto onDragEnterId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc)]( + const RefPtr& info, const std::string& extraParams) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("onDragEnter"); + func->Execute(info, extraParams); + }; + auto webComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (webComponent) { + webComponent->SetOnDragEnterId(onDragEnterId); + } +} + +void JSWeb::JsOnDragMove(const JSCallbackInfo& info) +{ + RefPtr jsOnDragMoveFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); + auto onDragMoveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc)]( + const RefPtr& info, const std::string& extraParams) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("onDragMove"); + func->Execute(info, extraParams); + }; + auto webComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (webComponent) { + webComponent->SetOnDragMoveId(onDragMoveId); + } +} + +void JSWeb::JsOnDragLeave(const JSCallbackInfo& info) +{ + RefPtr jsOnDragLeaveFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); + auto onDragLeaveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc)]( + const RefPtr& info, const std::string& extraParams) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("onDragLeave"); + func->Execute(info, extraParams); + }; + auto webComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (webComponent) { + webComponent->SetOnDragLeaveId(onDragLeaveId); + } +} + +void JSWeb::JsOnDrop(const JSCallbackInfo& info) +{ + RefPtr jsOnDropFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); + auto onDropId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc)]( + const RefPtr& info, const std::string& extraParams) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("onDrop"); + func->Execute(info, extraParams); + }; + auto webComponent = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); + if (webComponent) { + webComponent->SetOnDropId(onDropId); + } +} } // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/declarative_frontend/jsview/js_web.h b/frameworks/bridge/declarative_frontend/jsview/js_web.h index 3cab9f90539..7975d9107eb 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_web.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_web.h @@ -80,6 +80,11 @@ public: static void OnSearchResultReceive(const JSCallbackInfo& args); static void MediaPlayGestureAccess(bool isNeedGestureAccess); static void OnKeyEvent(const JSCallbackInfo& args); + static void JsOnDragStart(const JSCallbackInfo& info); + static void JsOnDragEnter(const JSCallbackInfo& info); + static void JsOnDragMove(const JSCallbackInfo& info); + static void JsOnDragLeave(const JSCallbackInfo& info); + static void JsOnDrop(const JSCallbackInfo& info); protected: static void OnCommonDialog(const JSCallbackInfo& args, int dialogEventType); diff --git a/frameworks/core/components/web/render_web.cpp b/frameworks/core/components/web/render_web.cpp index 11d93bd2936..4ea78347dd4 100755 --- a/frameworks/core/components/web/render_web.cpp +++ b/frameworks/core/components/web/render_web.cpp @@ -21,6 +21,7 @@ #include "base/log/log.h" #include "core/common/manager_interface.h" +#include "core/components/positioned/positioned_component.h" #include "core/components/web/resource/web_resource.h" #include "core/event/ace_events.h" #include "core/event/ace_event_helper.h" @@ -98,6 +99,11 @@ void RenderWeb::Update(const RefPtr& component) delegate_->UpdateInitialScale(web->GetInitialScale()); } delegate_->SetRenderWeb(AceType::WeakClaim(this)); + onDragStart_ = web->GetOnDragStartId(); + onDragEnter_ = web->GetOnDragEnterId(); + onDragMove_ = web->GetOnDragMoveId(); + onDragLeave_ = web->GetOnDragLeaveId(); + onDrop_ = web->GetOnDropId(); } MarkNeedLayout(); } @@ -286,6 +292,10 @@ void RenderWeb::HandleTouchUp(const TouchEventInfo& info, bool fromOverlay) void RenderWeb::HandleTouchMove(const TouchEventInfo& info, bool fromOverlay) { + if (isDragging_) { + return; + } + if (!delegate_) { LOGE("Touch move delegate_ is nullptr"); return; @@ -383,6 +393,12 @@ void RenderWeb::SetUpdateHandlePosition( void RenderWeb::OnTouchTestHit(const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) { + if (dragDropGesture_) { + dragDropGesture_->SetCoordinateOffset(coordinateOffset); + result.emplace_back(dragDropGesture_); + MarkIsNotSiblingAddRecognizerToResult(true); + } + if (doubleClickRecognizer_ && touchRestrict.sourceType == SourceType::MOUSE) { doubleClickRecognizer_->SetCoordinateOffset(coordinateOffset); result.emplace_back(doubleClickRecognizer_); @@ -475,7 +491,7 @@ bool RenderWeb::RunQuickMenu( WebOverlayType overlayType = GetTouchHandleOverlayType(insertTouchHandle, beginTouchHandle, endTouchHandle); - + if (textOverlay_ || overlayType == INVALID_OVERLAY) { PopTextOverlay(); } @@ -747,5 +763,267 @@ void RenderWeb::OnTouchSelectionChanged( } } } + +DragItemInfo RenderWeb::GenerateDragItemInfo(const RefPtr& context, const GestureEvent& info) +{ + DragItemInfo itemInfo; + if (delegate_) { + itemInfo.pixelMap = delegate_->GetDragPixelMap(); + } + + if (itemInfo.pixelMap) { + LOGI("get w3c drag info"); + isW3cDragEvent_ = true; + return itemInfo; + } + + if (onDragStart_) { + LOGI("user has set onDragStart"); + isW3cDragEvent_ = false; + RefPtr event = AceType::MakeRefPtr(); + event->SetX(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX))); + event->SetY(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX))); + selectedItemSize_ = GetLayoutSize(); + auto extraParams = JsonUtil::Create(true); + return onDragStart_(event, extraParams->ToString()); + } + + return itemInfo; +} + +void RenderWeb::OnDragWindowStartEvent(RefPtr pipelineContext, const GestureEvent& info, + const DragItemInfo& dragItemInfo) +{ + LOGI("create drag window"); + auto rect = pipelineContext->GetCurrentWindowRect(); + int32_t globalX = static_cast(info.GetGlobalPoint().GetX()); + int32_t globalY = static_cast(info.GetGlobalPoint().GetY()); + dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW", globalX + rect.Left(), globalY + rect.Top(), + dragItemInfo.pixelMap->GetWidth(), dragItemInfo.pixelMap->GetHeight()); + dragWindow_->SetOffset(rect.Left(), rect.Top()); + dragWindow_->DrawPixelMap(dragItemInfo.pixelMap); + if (isW3cDragEvent_ && delegate_) { + LOGI("w3c drag start"); + auto viewScale = pipelineContext->GetViewScale(); + int32_t localX = static_cast(globalX - GetCoordinatePoint().GetX()); + int32_t localY = static_cast(globalY - GetCoordinatePoint().GetY()); + delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_ENTER); + } +} + +void RenderWeb::PanOnActionStart(const GestureEvent& info) +{ + LOGI("web drag action start"); + auto pipelineContext = context_.Upgrade(); + if (!pipelineContext) { + LOGE("Context is null."); + return; + } + + isDragging_ = true; + GestureEvent newInfo = info; + newInfo.SetGlobalPoint(startPoint_); + auto dragItemInfo = GenerateDragItemInfo(pipelineContext, newInfo); +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) + if (dragItemInfo.pixelMap) { + auto initRenderNode = AceType::Claim(this); + isDragDropNode_ = true; + pipelineContext->SetInitRenderNode(initRenderNode); + AddDataToClipboard(pipelineContext, dragItemInfo.extraInfo, "", ""); + if (!dragWindow_) { + OnDragWindowStartEvent(pipelineContext, info, dragItemInfo); + } + return; + } +#endif + if (!dragItemInfo.customComponent) { + LOGW("the drag custom component is null"); + isDragging_ = false; + return; + } + + hasDragItem_ = true; + auto positionedComponent = AceType::MakeRefPtr(dragItemInfo.customComponent); + positionedComponent->SetTop(Dimension(GetGlobalOffset().GetY())); + positionedComponent->SetLeft(Dimension(GetGlobalOffset().GetX())); + SetLocalPoint(info.GetGlobalPoint() - GetGlobalOffset()); + auto updatePosition = [renderBox = AceType::Claim(this)]( + const std::function& func) { + if (!renderBox) { + return; + } + renderBox->SetUpdateBuilderFuncId(func); + }; + positionedComponent->SetUpdatePositionFuncId(updatePosition); + auto stackElement = pipelineContext->GetLastStack(); + stackElement->PushComponent(positionedComponent); +} + +void RenderWeb::OnDragWindowMoveEvent(RefPtr pipelineContext, const GestureEvent& info) +{ + int32_t globalX = static_cast(info.GetGlobalPoint().GetX()); + int32_t globalY = static_cast(info.GetGlobalPoint().GetY()); + LOGD("drag window position update, x = %{public}d, y = %{public}d", globalX, globalY); + dragWindow_->MoveTo(globalX, globalY); + if (isW3cDragEvent_ && delegate_) { + LOGD("w3c drag update"); + auto viewScale = pipelineContext->GetViewScale(); + int32_t localX = static_cast(globalX - GetCoordinatePoint().GetX()); + int32_t localY = static_cast(globalY - GetCoordinatePoint().GetY()); + delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_OVER); + } +} + +void RenderWeb::PanOnActionUpdate(const GestureEvent& info) +{ + LOGD("web drag action update"); + auto pipelineContext = context_.Upgrade(); + if (!pipelineContext) { + LOGE("Context is null."); + return; + } + +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) + if (isDragDropNode_ && dragWindow_) { + OnDragWindowMoveEvent(pipelineContext, info); + return; + } +#endif + + RefPtr event = AceType::MakeRefPtr(); + event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX))); + event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX))); + + Offset offset = info.GetGlobalPoint() - GetLocalPoint(); + if (GetUpdateBuilderFuncId()) { + GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY())); + } + + auto extraParams = JsonUtil::Create(true); + auto targetDragDropNode = FindDragDropNode(pipelineContext, info); + auto preDragDropNode = GetPreDragDropNode(); + if (preDragDropNode == targetDragDropNode) { + if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) { + (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString()); + } + return; + } + if (preDragDropNode && preDragDropNode->GetOnDragLeave()) { + (preDragDropNode->GetOnDragLeave())(event, extraParams->ToString()); + } + if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) { + (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString()); + } + SetPreDragDropNode(targetDragDropNode); +} + +void RenderWeb::OnDragWindowDropEvent(RefPtr pipelineContext, const GestureEvent& info) +{ + if (GetOnDrop()) { + RefPtr event = AceType::MakeRefPtr(); + RefPtr pasteData = AceType::MakeRefPtr(); + event->SetPasteData(pasteData); + event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX))); + event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX))); + + auto extraParams = JsonUtil::Create(true); + (GetOnDrop())(event, extraParams->ToString()); + pipelineContext->SetInitRenderNode(nullptr); + } + + if (isW3cDragEvent_ && delegate_) { + LOGI("w3c drag end"); + auto viewScale = pipelineContext->GetViewScale(); + int32_t localX = static_cast(info.GetGlobalPoint().GetX() - GetCoordinatePoint().GetX()); + int32_t localY = static_cast(info.GetGlobalPoint().GetY() - GetCoordinatePoint().GetY()); + delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_DROP); + delegate_->HandleDragEvent(localX * viewScale, localY * viewScale, DragAction::DRAG_END); + } +} + +void RenderWeb::PanOnActionEnd(const GestureEvent& info) +{ + LOGI("web drag action end"); + isDragging_ = false; + auto pipelineContext = context_.Upgrade(); + if (!pipelineContext) { + LOGE("Context is null."); + return; + } +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) + if (isDragDropNode_) { + isDragDropNode_ = false; + RestoreCilpboardData(pipelineContext); + OnDragWindowDropEvent(pipelineContext, info); + } + + if (dragWindow_) { + dragWindow_->Destroy(); + dragWindow_ = nullptr; + return; + } +#endif + + RefPtr event = AceType::MakeRefPtr(); + RefPtr pasteData = AceType::MakeRefPtr(); + event->SetPasteData(pasteData); + event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX))); + event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX))); + + Offset offset = info.GetGlobalPoint() - GetLocalPoint(); + if (GetUpdateBuilderFuncId()) { + GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY())); + } + if (hasDragItem_) { + auto stackElement = pipelineContext->GetLastStack(); + stackElement->PopComponent(); + } + hasDragItem_ = false; + + ACE_DCHECK(GetPreDragDropNode() == FindTargetRenderNode(pipelineContext, info)); + auto targetDragDropNode = GetPreDragDropNode(); + if (!targetDragDropNode) { + return; + } + if (targetDragDropNode->GetOnDrop()) { + auto extraParams = JsonUtil::Create(true); + (targetDragDropNode->GetOnDrop())(event, extraParams->ToString()); + } + SetPreDragDropNode(nullptr); +} + +void RenderWeb::PanOnActionCancel() +{ + LOGI("drag cancel"); + isDragging_ = false; + auto pipelineContext = context_.Upgrade(); + if (!pipelineContext) { + LOGE("Context is null."); + return; + } + +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) + if (isDragDropNode_) { + RestoreCilpboardData(pipelineContext); + isDragDropNode_ = false; + if (isW3cDragEvent_ && delegate_) { + LOGI("w3c drag cancel"); + delegate_->HandleDragEvent(0, 0, DragAction::DRAG_CANCEL); + } + } + + if (dragWindow_) { + dragWindow_->Destroy(); + dragWindow_ = nullptr; + } +#endif + + if (hasDragItem_) { + auto stackElement = pipelineContext->GetLastStack(); + stackElement->PopComponent(); + hasDragItem_ = false; + } + SetPreDragDropNode(nullptr); +} #endif } // namespace OHOS::Ace diff --git a/frameworks/core/components/web/render_web.h b/frameworks/core/components/web/render_web.h index 1c1a2177f21..60236d65d6e 100755 --- a/frameworks/core/components/web/render_web.h +++ b/frameworks/core/components/web/render_web.h @@ -47,8 +47,8 @@ enum WebOverlayType { #endif } -class RenderWeb : public RenderNode { - DECLARE_ACE_TYPE(RenderWeb, RenderNode); +class RenderWeb : public RenderNode, public DragDropEvent { + DECLARE_ACE_TYPE(RenderWeb, RenderNode, DragDropEvent); public: static RefPtr Create(); @@ -73,7 +73,7 @@ public: void HandleTouchMove(const TouchEventInfo& info, bool fromOverlay); void HandleTouchCancel(const TouchEventInfo& info); void HandleDoubleClick(const ClickInfo& info); - + // Related to text overlay void SetUpdateHandlePosition( const std::function& updateHandlePosition); @@ -104,6 +104,12 @@ public: bool IsAxisScrollable(AxisDirection direction) override; WeakPtr CheckAxisNode() override; + void PanOnActionStart(const GestureEvent& info) override; + void PanOnActionUpdate(const GestureEvent& info) override; + void PanOnActionEnd(const GestureEvent& info) override; + void PanOnActionCancel() override; + DragItemInfo GenerateDragItemInfo(const RefPtr& context, const GestureEvent& info) override; + protected: RefPtr delegate_; RefPtr web_; @@ -131,6 +137,10 @@ private: Offset NormalizeTouchHandleOffset(float x, float y); void RegisterTextOverlayCallback( int32_t flags, std::shared_ptr callback); + void OnDragWindowStartEvent(RefPtr pipelineContext, const GestureEvent& info, + const DragItemInfo& dragItemInfo); + void OnDragWindowMoveEvent(RefPtr pipelineContext, const GestureEvent& info); + void OnDragWindowDropEvent(RefPtr pipelineContext, const GestureEvent& info); RefPtr touchRecognizer_ = nullptr; RefPtr doubleClickRecognizer_ = nullptr; @@ -143,6 +153,8 @@ private: bool showTextOveralyMenu_ = false; bool showStartTouchHandle_ = false; bool showEndTouchHandle_ = false; + bool isDragging_ = false; + bool isW3cDragEvent_ = false; #endif Offset position_; diff --git a/frameworks/core/components/web/resource/web_client_impl.cpp b/frameworks/core/components/web/resource/web_client_impl.cpp index 98a19439295..acfd35f91d2 100755 --- a/frameworks/core/components/web/resource/web_client_impl.cpp +++ b/frameworks/core/components/web/resource/web_client_impl.cpp @@ -500,4 +500,14 @@ void WebClientImpl::OnTouchSelectionChanged( delegate->OnTouchSelectionChanged( insertHandle, startSelectionHandle, endSelectionHandle); } + +bool WebClientImpl::OnDragAndDropData(const void* data, size_t len, const NWeb::ImageOptions& opt) +{ + ContainerScope scope(instanceId_); + auto delegate = webDelegate_.Upgrade(); + if (!delegate) { + return false; + } + return delegate->OnDragAndDropData(data, len, opt.width, opt.height); +} } // namespace OHOS::Ace diff --git a/frameworks/core/components/web/resource/web_client_impl.h b/frameworks/core/components/web/resource/web_client_impl.h index 5d0adfc43f0..f6ca3dca8bd 100755 --- a/frameworks/core/components/web/resource/web_client_impl.h +++ b/frameworks/core/components/web/resource/web_client_impl.h @@ -123,7 +123,7 @@ public: std::shared_ptr insertHandle, std::shared_ptr startSelectionHandle, std::shared_ptr endSelectionHandle) override; - + bool OnDragAndDropData(const void* data, size_t len, const NWeb::ImageOptions& opt) override; void SetWebDelegate(const WeakPtr& delegate) { webDelegate_ = delegate; diff --git a/frameworks/core/components/web/resource/web_delegate.cpp b/frameworks/core/components/web/resource/web_delegate.cpp index 3231b49ed0c..ab81ef45724 100755 --- a/frameworks/core/components/web/resource/web_delegate.cpp +++ b/frameworks/core/components/web/resource/web_delegate.cpp @@ -90,7 +90,7 @@ void WebMessagePortOhos::Close() return; } delegate->ClosePort(handle_); - + } void WebMessagePortOhos::PostMessage(std::string& data) @@ -2643,6 +2643,28 @@ void WebDelegate::OnSearchResultReceive(int activeMatchOrdinal, int numberOfMatc } } +bool WebDelegate::OnDragAndDropData(const void* data, size_t len, int width, int height) +{ + LOGI("store pixel map, len = %{public}zu, width = %{public}d, height = %{public}d", len, width, height); + pixelMap_ = PixelMap::ConvertSkImageToPixmap(static_cast(data), len, width, height); + if (pixelMap_ == nullptr) { + LOGE("convert drag image to pixel map failed"); + return false; + } + isRefreshPixelMap_ = true; + return true; +} + +RefPtr WebDelegate::GetDragPixelMap() +{ + if (isRefreshPixelMap_) { + isRefreshPixelMap_ = false; + return pixelMap_; + } + + return nullptr; +} + #ifdef OHOS_STANDARD_SYSTEM void WebDelegate::HandleTouchDown(const int32_t& id, const double& x, const double& y) { @@ -2747,6 +2769,17 @@ void WebDelegate::OnTouchSelectionChanged( insertHandle, startSelectionHandle, endSelectionHandle); } } + +void WebDelegate::HandleDragEvent(int32_t x, int32_t y, const DragAction& dragAction) +{ + if (nweb_) { + OHOS::NWeb::DragEvent dragEvent; + dragEvent.x = x; + dragEvent.y = y; + dragEvent.action = static_cast(dragAction); + nweb_->SendDragEvent(dragEvent); + } +} #endif std::string WebDelegate::GetUrlStringParam(const std::string& param, const std::string& name) const diff --git a/frameworks/core/components/web/resource/web_delegate.h b/frameworks/core/components/web/resource/web_delegate.h index 5ac617796e2..cccd6ebafb5 100755 --- a/frameworks/core/components/web/resource/web_delegate.h +++ b/frameworks/core/components/web/resource/web_delegate.h @@ -23,6 +23,7 @@ #include #endif +#include "base/image/pixel_map.h" #include "core/components/common/layout/constants.h" #include "core/components/web/resource/web_client_impl.h" #include "core/components/web/resource/web_resource.h" @@ -189,6 +190,16 @@ private: std::shared_ptr request_; }; +enum class DragAction { + DRAG_START = 0, + DRAG_ENTER, + DRAG_LEAVE, + DRAG_OVER, + DRAG_DROP, + DRAG_END, + DRAG_CANCEL, +}; + class RenderWeb; class WebDelegate : public WebResource { DECLARE_ACE_TYPE(WebDelegate, WebResource); @@ -274,6 +285,8 @@ public: std::shared_ptr insertHandle, std::shared_ptr startSelectionHandle, std::shared_ptr endSelectionHandle); + void HandleDragEvent(int32_t x, int32_t y, const DragAction& dragAction); + RefPtr GetDragPixelMap(); #endif void OnErrorReceive(std::shared_ptr request, std::shared_ptr error); @@ -307,6 +320,7 @@ public: void OnScroll(double xOffset, double yOffset); bool LoadDataWithRichText(); void OnSearchResultReceive(int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting); + bool OnDragAndDropData(const void* data, size_t len, int width, int height); private: void InitWebEvent(); @@ -412,7 +426,8 @@ private: std::string bundlePath_; std::string bundleDataPath_; - + RefPtr pixelMap_ = nullptr; + bool isRefreshPixelMap_ = false; #endif }; diff --git a/frameworks/core/components/web/rosen_render_web.cpp b/frameworks/core/components/web/rosen_render_web.cpp index 27d3f928629..f21a2745477 100644 --- a/frameworks/core/components/web/rosen_render_web.cpp +++ b/frameworks/core/components/web/rosen_render_web.cpp @@ -61,6 +61,7 @@ void RosenRenderWeb::OnAttachContext() return; } if (delegate_) { + CreateDragDropRecognizer(context_); auto surface = GetSurface(); delegate_->InitOHOSWeb(context_, surface); } diff --git a/frameworks/core/components/web/web_component.h b/frameworks/core/components/web/web_component.h index 6701e716589..2b51d4a3bfe 100644 --- a/frameworks/core/components/web/web_component.h +++ b/frameworks/core/components/web/web_component.h @@ -20,6 +20,7 @@ #include "base/geometry/size.h" #include "base/utils/utils.h" +#include "core/components/box/drag_drop_event.h" #include "core/components/declaration/common/declaration.h" #include "core/components/declaration/web/web_client.h" #include "core/components/declaration/web/web_declaration.h" @@ -1342,6 +1343,56 @@ public: return isNeedGestureAccess_; } + const OnDragFunc& GetOnDragStartId() const + { + return onDragStartId_; + } + + void SetOnDragStartId(const OnDragFunc& onDragStartId) + { + onDragStartId_ = onDragStartId; + } + + const OnDropFunc& GetOnDragEnterId() const + { + return onDragEnterId_; + } + + void SetOnDragEnterId(const OnDropFunc& onDragEnterId) + { + onDragEnterId_ = onDragEnterId; + } + + const OnDropFunc& GetOnDragMoveId() const + { + return onDragMoveId_; + } + + void SetOnDragMoveId(const OnDropFunc& onDragMoveId) + { + onDragMoveId_ = onDragMoveId; + } + + const OnDropFunc& GetOnDragLeaveId() const + { + return onDragLeaveId_; + } + + void SetOnDragLeaveId(const OnDropFunc& onDragLeaveId) + { + onDragLeaveId_ = onDragLeaveId; + } + + const OnDropFunc& GetOnDropId() const + { + return onDropId_; + } + + void SetOnDropId(const OnDropFunc& onDropId) + { + onDropId_ = onDropId; + } + private: RefPtr declaration_; CreatedCallback createdCallback_ = nullptr; @@ -1386,6 +1437,11 @@ private: int32_t backgroundColor_; bool isBackgroundColor_ = false; bool isNeedGestureAccess_ = true; + OnDragFunc onDragStartId_; + OnDropFunc onDragEnterId_; + OnDropFunc onDragMoveId_; + OnDropFunc onDragLeaveId_; + OnDropFunc onDropId_; }; } // namespace OHOS::Ace From c0a666df37f50ae011886888dc9ea320078018c1 Mon Sep 17 00:00:00 2001 From: tomppo Date: Wed, 31 Aug 2022 16:19:44 +0300 Subject: [PATCH 22/35] Fix conflict on Windows build by renaming conflicting items. Change-Id: Ia74ecabb0efe94a1f7a8b47d9369c6a12ec5b222 Signed-off-by: tomppo Change-Id: I3a8d7408a302701dafe6c3bbdaeb5093b9692adb Signed-off-by: tomppo --- frameworks/bridge/common/dom/dom_document.cpp | 2 +- .../bridge/common/dom/dom_grid_column.cpp | 2 +- frameworks/bridge/common/dom/dom_node.cpp | 10 +++++----- frameworks/bridge/common/dom/dom_node.h | 2 +- .../jsview/js_view_abstract.cpp | 6 +++--- .../view_stack_processor.cpp | 3 ++- frameworks/bridge/js_frontend/js_command.cpp | 2 +- .../core/components/box/render_box_base.cpp | 7 ++++--- .../core/components/common/layout/constants.h | 18 +++++++++--------- .../components/common/layout/position_param.h | 2 +- .../properties/motion_path_evaluator.cpp | 2 +- .../common/properties/motion_path_evaluator.h | 4 ++-- .../components/coverage/coverage_component.h | 4 ++-- .../declaration/common/declaration.cpp | 4 ++-- .../core/components/declaration/common/style.h | 2 +- .../core/components/flex/render_flex.cpp | 14 ++++++++------ .../core/components/flex/render_flex_item.cpp | 2 +- .../side_bar/render_side_bar_container.cpp | 2 +- .../side_bar/side_bar_container_component.cpp | 2 +- .../core/components/stack/render_stack.cpp | 2 +- .../test/unittest/stack/render_stack_test.cpp | 5 +++-- .../test/unittest/stack/stack_test_utils.h | 2 +- .../components/tool_bar/render_tool_bar_item.h | 4 ++-- .../inspector/inspector_composed_element.cpp | 4 ++-- frameworks/core/pipeline/base/component.h | 2 +- frameworks/core/pipeline/base/render_node.cpp | 14 +++++++------- frameworks/core/pipeline/base/render_node.h | 2 +- 27 files changed, 65 insertions(+), 60 deletions(-) diff --git a/frameworks/bridge/common/dom/dom_document.cpp b/frameworks/bridge/common/dom/dom_document.cpp index 150a0efaa61..446a4c3b3f3 100644 --- a/frameworks/bridge/common/dom/dom_document.cpp +++ b/frameworks/bridge/common/dom/dom_document.cpp @@ -347,7 +347,7 @@ void DOMDocument::RemoveNodes(const RefPtr& node, bool scheduleUpdate) } } // Fixed positioned node and navigation bar node need to delete the relative proxy node. - if (node->GetPosition() == PositionType::FIXED && rootStackComponent_) { + if (node->GetPosition() == PositionType::PTFIXED && rootStackComponent_) { rootStackComponent_->RemoveChild(node->GetRootComponent()); auto context = node->GetPipelineContext().Upgrade(); if (context && scheduleUpdate) { diff --git a/frameworks/bridge/common/dom/dom_grid_column.cpp b/frameworks/bridge/common/dom/dom_grid_column.cpp index 85aa31bb375..ce2e22396c2 100644 --- a/frameworks/bridge/common/dom/dom_grid_column.cpp +++ b/frameworks/bridge/common/dom/dom_grid_column.cpp @@ -75,7 +75,7 @@ bool DomGridColumn::SetSpecializedAttr(const std::pair auto& positionStyle = declaration->MaybeResetStyle(StyleTag::COMMON_POSITION_STYLE); if (positionStyle.IsValid()) { - positionStyle.position = PositionType::ABSOLUTE; + positionStyle.position = PositionType::PTABSOLUTE; positionStyle.top = Dimension(0.0, DimensionUnit::PX); positionStyle.left = column.ParseDimension(value); declaration->SetHasLeft(true); diff --git a/frameworks/bridge/common/dom/dom_node.cpp b/frameworks/bridge/common/dom/dom_node.cpp index 87efffd7533..a84dc831d99 100644 --- a/frameworks/bridge/common/dom/dom_node.cpp +++ b/frameworks/bridge/common/dom/dom_node.cpp @@ -778,7 +778,7 @@ void DOMNode::AddNode(const RefPtr& node, int32_t slot) auto pos = children_.begin(); std::advance(pos, slot); children_.insert(pos, node); - if (node->GetPosition() != PositionType::FIXED) { + if (node->GetPosition() != PositionType::PTFIXED) { if (!node->IsProxy() && GetDisplay() == DisplayType::NONE) { node->GenerateComponentNode(); } @@ -792,7 +792,7 @@ void DOMNode::RemoveNode(const RefPtr& node) return; } children_.remove_if([node](const RefPtr& child) { return node->GetNodeId() == child->GetNodeId(); }); - if (node->GetPosition() != PositionType::FIXED) { + if (node->GetPosition() != PositionType::PTFIXED) { OnChildNodeRemoved(node); } } @@ -1300,7 +1300,7 @@ void DOMNode::CompositeComponents() Component::MergeRSNode(components, mainComponent); } // Only fixed position has position component - if (positionComponent_ && GetPosition() == PositionType::FIXED) { + if (positionComponent_ && GetPosition() == PositionType::PTFIXED) { components.emplace(components.begin(), positionComponent_); Component::MergeRSNode(positionComponent_); } @@ -2057,7 +2057,7 @@ void DOMNode::UpdateFocusableEventComponents() void DOMNode::UpdatePositionProps() { - if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() == PositionType::FIXED) { + if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() == PositionType::PTFIXED) { return; } @@ -2138,7 +2138,7 @@ void DOMNode::UpdateTweenPosition(const RefPtr tweenComponent) void DOMNode::UpdatePositionComponent() { - if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() != PositionType::FIXED) { + if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() != PositionType::PTFIXED) { return; } if (!positionComponent_) { diff --git a/frameworks/bridge/common/dom/dom_node.h b/frameworks/bridge/common/dom/dom_node.h index 815fb70ab18..3e90e414e70 100644 --- a/frameworks/bridge/common/dom/dom_node.h +++ b/frameworks/bridge/common/dom/dom_node.h @@ -614,7 +614,7 @@ public: PositionType GetPosition() const { - PositionType position = PositionType::RELATIVE; + PositionType position = PositionType::PTRELATIVE; if (declaration_) { auto& positionStyle = static_cast(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE)); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 958eb435630..a415f019d0f 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -1276,7 +1276,7 @@ void JSViewAbstract::JsPosition(const JSCallbackInfo& info) auto flexItemComponent = ViewStackProcessor::GetInstance()->GetFlexItemComponent(); flexItemComponent->SetLeft(x); flexItemComponent->SetTop(y); - flexItemComponent->SetPositionType(PositionType::ABSOLUTE); + flexItemComponent->SetPositionType(PositionType::PTABSOLUTE); } } @@ -1299,7 +1299,7 @@ void JSViewAbstract::JsOffset(const JSCallbackInfo& info) auto flexItemComponent = ViewStackProcessor::GetInstance()->GetFlexItemComponent(); flexItemComponent->SetLeft(x); flexItemComponent->SetTop(y); - flexItemComponent->SetPositionType(PositionType::OFFSET); + flexItemComponent->SetPositionType(PositionType::PTOFFSET); } } @@ -5124,7 +5124,7 @@ void JSViewAbstract::JsHitTestBehavior(const JSCallbackInfo& info) return; } - HitTestMode hitTestMode = HitTestMode::DEFAULT; + HitTestMode hitTestMode = HitTestMode::HTMDEFAULT; if (info[0]->IsNumber()) { hitTestMode = static_cast(info[0]->ToNumber()); } diff --git a/frameworks/bridge/declarative_frontend/view_stack_processor.cpp b/frameworks/bridge/declarative_frontend/view_stack_processor.cpp index 2230f0defc7..7563387848d 100644 --- a/frameworks/bridge/declarative_frontend/view_stack_processor.cpp +++ b/frameworks/bridge/declarative_frontend/view_stack_processor.cpp @@ -706,7 +706,8 @@ std::pair, RefPtr> ViewStackProcessor::WrapComponen } for (auto&& component : components) { - component->SetTouchable(mainComponent->IsTouchable() && mainComponent->GetHitTestMode() != HitTestMode::NONE); + component->SetTouchable(mainComponent->IsTouchable() && + mainComponent->GetHitTestMode() != HitTestMode::HTMNONE); } for (auto&& component : components) { diff --git a/frameworks/bridge/js_frontend/js_command.cpp b/frameworks/bridge/js_frontend/js_command.cpp index b6e9ce75b10..b5bd0f5b2bf 100644 --- a/frameworks/bridge/js_frontend/js_command.cpp +++ b/frameworks/bridge/js_frontend/js_command.cpp @@ -309,7 +309,7 @@ void JsCommandDomElementCreator::MountDomNode( useProxyNode = true; isIgnored = true; } - } else if (node->GetPosition() == PositionType::FIXED) { + } else if (node->GetPosition() == PositionType::PTFIXED) { const auto& rootStack = domDocument->GetRootStackComponent(); if (rootStack) { rootStack->AppendChild(node->GetRootComponent()); diff --git a/frameworks/core/components/box/render_box_base.cpp b/frameworks/core/components/box/render_box_base.cpp index a10e0a90380..a00d6f7a1a3 100644 --- a/frameworks/core/components/box/render_box_base.cpp +++ b/frameworks/core/components/box/render_box_base.cpp @@ -364,7 +364,7 @@ void RenderBoxBase::CalculateGridLayoutSize() if (IsHeadRenderNode()) { auto context = context_.Upgrade(); positionParam_.type = - (context && context->GetIsDeclarative()) ? PositionType::SEMI_RELATIVE : PositionType::ABSOLUTE; + (context && context->GetIsDeclarative()) ? PositionType::PTSEMI_RELATIVE : PositionType::PTABSOLUTE; std::pair& edge = (GetTextDirection() == TextDirection::RTL) ? positionParam_.right : positionParam_.left; edge.first = offset; @@ -374,7 +374,8 @@ void RenderBoxBase::CalculateGridLayoutSize() if (headRenderNode) { auto context = headRenderNode->GetContext().Upgrade(); headRenderNode->SetPositionType( - (context && context->GetIsDeclarative()) ? PositionType::SEMI_RELATIVE : PositionType::ABSOLUTE); + (context && context->GetIsDeclarative()) ? PositionType::PTSEMI_RELATIVE : + PositionType::PTABSOLUTE); headRenderNode->GetTextDirection() == TextDirection::RTL ? headRenderNode->SetRight(offset) : headRenderNode->SetLeft(offset); } @@ -383,7 +384,7 @@ void RenderBoxBase::CalculateGridLayoutSize() #ifndef ENABLE_ROSEN_BACKEND auto context = context_.Upgrade(); positionParam_.type = - (context && context->GetIsDeclarative()) ? PositionType::SEMI_RELATIVE : PositionType::ABSOLUTE; + (context && context->GetIsDeclarative()) ? PositionType::PTSEMI_RELATIVE : PositionType::PTABSOLUTE; std::pair& edge = (GetTextDirection() == TextDirection::RTL) ? positionParam_.right : positionParam_.left; edge.first = offset; diff --git a/frameworks/core/components/common/layout/constants.h b/frameworks/core/components/common/layout/constants.h index 061a5758c13..a98ae2ad279 100644 --- a/frameworks/core/components/common/layout/constants.h +++ b/frameworks/core/components/common/layout/constants.h @@ -171,11 +171,11 @@ enum class MainSwiperSize { }; enum class PositionType { - RELATIVE = 0, - FIXED, - ABSOLUTE, - OFFSET, // percentage layout based on RELATIVE - SEMI_RELATIVE, // absolute offset based on RELATIVE + PTRELATIVE = 0, + PTFIXED, + PTABSOLUTE, + PTOFFSET, // percentage layout based on RELATIVE + PTSEMI_RELATIVE, // absolute offset based on RELATIVE }; enum class TextAlign { @@ -496,25 +496,25 @@ enum class HitTestMode { * Both self and children respond to the hit test for touch events, * but block hit test of the other nodes which is masked by this node. */ - DEFAULT = 0, + HTMDEFAULT = 0, /** * Self respond to the hit test for touch events, * but block hit test of children and other nodes which is masked by this node. */ - BLOCK, + HTMBLOCK, /** * Self and child respond to the hit test for touch events, * and allow hit test of other nodes which is masked by this node. */ - TRANSPARENT, + HTMTRANSPARENT, /** * Self not respond to the hit test for touch events, * but children respond to the hit test for touch events. */ - NONE + HTMNONE }; enum class CopyOptions { diff --git a/frameworks/core/components/common/layout/position_param.h b/frameworks/core/components/common/layout/position_param.h index 41e241f6ac3..b9147bb27fc 100644 --- a/frameworks/core/components/common/layout/position_param.h +++ b/frameworks/core/components/common/layout/position_param.h @@ -28,7 +28,7 @@ struct PositionParam { std::pair top = { AnimatableDimension(0.0, DimensionUnit::PX), false }; std::pair bottom = { AnimatableDimension(0.0, DimensionUnit::PX), false }; std::pair anchor = {0.0_px, 0.0_px}; - PositionType type = PositionType::RELATIVE; + PositionType type = PositionType::PTRELATIVE; }; enum class AlignDirection { diff --git a/frameworks/core/components/common/properties/motion_path_evaluator.cpp b/frameworks/core/components/common/properties/motion_path_evaluator.cpp index 36abe245fa0..172e1c6a43b 100644 --- a/frameworks/core/components/common/properties/motion_path_evaluator.cpp +++ b/frameworks/core/components/common/properties/motion_path_evaluator.cpp @@ -68,7 +68,7 @@ MotionPathPosition MotionPathEvaluator::Evaluate(float fraction) auto progress = motionPathOption_.GetBegin() * (1.0f - fraction) + motionPathOption_.GetEnd() * fraction; MotionPathPosition position; if (FlutterSvgPainter::GetMotionPathPosition(motionPathOption_.GetPath(), progress, position)) { - if (positionType_ == PositionType::OFFSET) { + if (positionType_ == PositionType::PTOFFSET) { position.offset += startPoint_; } return position; diff --git a/frameworks/core/components/common/properties/motion_path_evaluator.h b/frameworks/core/components/common/properties/motion_path_evaluator.h index a3670270682..c637a994e2f 100644 --- a/frameworks/core/components/common/properties/motion_path_evaluator.h +++ b/frameworks/core/components/common/properties/motion_path_evaluator.h @@ -42,7 +42,7 @@ class MotionPathEvaluator final : public AceType { public: explicit MotionPathEvaluator(const MotionPathOption& option = MotionPathOption(), const Offset& start = Offset(0.0, 0.0), const Offset& end = Offset(0.0, 0.0), - PositionType type = PositionType::RELATIVE); + PositionType type = PositionType::PTRELATIVE); ~MotionPathEvaluator() override = default; MotionPathPosition Evaluate(float fraction); @@ -96,7 +96,7 @@ private: MotionPathOption motionPathOption_; Offset startPoint_ { 0.0, 0.0 }; Offset endPoint_ { 0.0, 0.0 }; - PositionType positionType_ = PositionType::RELATIVE; + PositionType positionType_ = PositionType::PTRELATIVE; }; // MotionPathEvaluator adapter for dimension diff --git a/frameworks/core/components/coverage/coverage_component.h b/frameworks/core/components/coverage/coverage_component.h index 399142c050d..12c20666507 100644 --- a/frameworks/core/components/coverage/coverage_component.h +++ b/frameworks/core/components/coverage/coverage_component.h @@ -56,14 +56,14 @@ public: { textComponent_->SetHasLeft(true); textComponent_->SetLeft(x); - textComponent_->SetPositionType(PositionType::RELATIVE); + textComponent_->SetPositionType(PositionType::PTRELATIVE); } void SetY(const Dimension& y) { textComponent_->SetHasTop(true); textComponent_->SetTop(y); - textComponent_->SetPositionType(PositionType::RELATIVE); + textComponent_->SetPositionType(PositionType::PTRELATIVE); } const Dimension& GetX() const diff --git a/frameworks/core/components/declaration/common/declaration.cpp b/frameworks/core/components/declaration/common/declaration.cpp index 533a9202aba..bac78d914d1 100644 --- a/frameworks/core/components/declaration/common/declaration.cpp +++ b/frameworks/core/components/declaration/common/declaration.cpp @@ -1393,8 +1393,8 @@ void Declaration::SetCurrentStyle(const std::pair& sty if (positionStyle.IsValid() && !value.empty()) { positionStyle.position = value == DOM_POSITION_FIXED - ? PositionType::FIXED - : value == DOM_POSITION_ABSOLUTE ? PositionType::ABSOLUTE : PositionType::RELATIVE; + ? PositionType::PTFIXED + : value == DOM_POSITION_ABSOLUTE ? PositionType::PTABSOLUTE : PositionType::PTRELATIVE; declaration.hasPositionStyle_ = true; } } }, diff --git a/frameworks/core/components/declaration/common/style.h b/frameworks/core/components/declaration/common/style.h index 8f5eeca2238..8293b3eec79 100644 --- a/frameworks/core/components/declaration/common/style.h +++ b/frameworks/core/components/declaration/common/style.h @@ -115,7 +115,7 @@ struct CommonFlexStyle : Style { }; struct CommonPositionStyle : Style { - PositionType position { PositionType::RELATIVE }; + PositionType position { PositionType::PTRELATIVE }; Dimension left; Dimension top; Dimension right; diff --git a/frameworks/core/components/flex/render_flex.cpp b/frameworks/core/components/flex/render_flex.cpp index 51f101f08b5..cde14da282c 100644 --- a/frameworks/core/components/flex/render_flex.cpp +++ b/frameworks/core/components/flex/render_flex.cpp @@ -45,7 +45,9 @@ double GetMainAxisValue(const Size& size, FlexDirection direction) inline bool IsNonRelativePosition(PositionType pos) { - return ((pos != PositionType::RELATIVE) && (pos != PositionType::SEMI_RELATIVE) && (pos != PositionType::OFFSET)); + return ((pos != PositionType::PTRELATIVE) && + (pos != PositionType::PTSEMI_RELATIVE) && + (pos != PositionType::PTOFFSET)); } } // namespace @@ -749,13 +751,13 @@ void RenderFlex::PlaceChildren(double frontSpace, double betweenSpace, const Bas } Offset offset; if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { - if (item->GetPositionType() == PositionType::SEMI_RELATIVE) { + if (item->GetPositionType() == PositionType::PTSEMI_RELATIVE) { childMainPos = 0.0; } offset = Offset(childMainPos, childCrossPos); } else { offset = - Offset((item->GetPositionType() == PositionType::SEMI_RELATIVE) ? 0.0 : childCrossPos, childMainPos); + Offset((item->GetPositionType() == PositionType::PTSEMI_RELATIVE) ? 0.0 : childCrossPos, childMainPos); } if (!IsStartTopLeft(direction_, GetTextDirection())) { @@ -989,7 +991,7 @@ void RenderFlex::ResizeByItem(const RefPtr& item, double &allocatedS crossSize_ = std::max(crossSize_, GetCrossSize(item)); // Semi relative and variable allocatedSize is used for grid container. - if ((item->GetPositionType() == PositionType::SEMI_RELATIVE) && + if ((item->GetPositionType() == PositionType::PTSEMI_RELATIVE) && (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE)) { allocatedSize_ = std::max(allocatedSize_, mainSize); allocatedSize = mainSize; @@ -1039,7 +1041,7 @@ double RenderFlex::GetMainSize(const RefPtr& item) const } if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { size = item->GetLayoutSize().Width(); - if (item->GetPositionType() == PositionType::SEMI_RELATIVE) { + if (item->GetPositionType() == PositionType::PTSEMI_RELATIVE) { Offset absoluteOffset = PositionLayoutUtils::GetAbsoluteOffset(Claim(const_cast(this)), item); size += absoluteOffset.GetX(); } @@ -1059,7 +1061,7 @@ double RenderFlex::GetCrossSize(const RefPtr& item) const size = item->GetLayoutSize().Height(); } else { size = item->GetLayoutSize().Width(); - if (item->GetPositionType() == PositionType::SEMI_RELATIVE) { + if (item->GetPositionType() == PositionType::PTSEMI_RELATIVE) { Offset absoluteOffset = PositionLayoutUtils::GetAbsoluteOffset(Claim(const_cast(this)), item); size += absoluteOffset.GetX(); } diff --git a/frameworks/core/components/flex/render_flex_item.cpp b/frameworks/core/components/flex/render_flex_item.cpp index 9b1bf02da37..3aa4439843f 100644 --- a/frameworks/core/components/flex/render_flex_item.cpp +++ b/frameworks/core/components/flex/render_flex_item.cpp @@ -72,7 +72,7 @@ void RenderFlexItem::PerformLayout() } auto offset = gridColumnInfo_->GetOffset(); if (offset != UNDEFINED_DIMENSION) { - positionParam_.type = PositionType::SEMI_RELATIVE; + positionParam_.type = PositionType::PTSEMI_RELATIVE; std::pair& edge = (GetTextDirection() == TextDirection::RTL) ? positionParam_.right : positionParam_.left; edge.first = offset; diff --git a/frameworks/core/components/side_bar/render_side_bar_container.cpp b/frameworks/core/components/side_bar/render_side_bar_container.cpp index 20e2ae10d2f..b730891bf07 100644 --- a/frameworks/core/components/side_bar/render_side_bar_container.cpp +++ b/frameworks/core/components/side_bar/render_side_bar_container.cpp @@ -381,7 +381,7 @@ void RenderSideBarContainer::PlaceChildren() for (const auto& item : GetChildren()) { auto positionedItem = AceType::DynamicCast(item); if (!positionedItem) { - if (item->GetPositionType() == PositionType::ABSOLUTE) { + if (item->GetPositionType() == PositionType::PTABSOLUTE) { auto itemOffset = PositionLayoutUtils::GetAbsoluteOffset(Claim(this), item); item->SetAbsolutePosition(itemOffset); continue; diff --git a/frameworks/core/components/side_bar/side_bar_container_component.cpp b/frameworks/core/components/side_bar/side_bar_container_component.cpp index 85c162791e9..2985fcbae25 100644 --- a/frameworks/core/components/side_bar/side_bar_container_component.cpp +++ b/frameworks/core/components/side_bar/side_bar_container_component.cpp @@ -99,7 +99,7 @@ void SideBarContainerComponent::Build() RefPtr displayBtn = AceType::MakeRefPtr(btnbox); displayBtn->SetLeft(Dimension(declaration_->GetLeft(), DimensionUnit::VP)); displayBtn->SetTop(Dimension(declaration_->GetTop(), DimensionUnit::VP)); - displayBtn->SetPositionType(PositionType::ABSOLUTE); + displayBtn->SetPositionType(PositionType::PTABSOLUTE); if (!GetShowControlButton()) { displayBtn->SetVisible(VisibleType::GONE); } else { diff --git a/frameworks/core/components/stack/render_stack.cpp b/frameworks/core/components/stack/render_stack.cpp index 4ecc9ffbd78..562480cda49 100644 --- a/frameworks/core/components/stack/render_stack.cpp +++ b/frameworks/core/components/stack/render_stack.cpp @@ -86,7 +86,7 @@ void RenderStack::PerformLayout() for (const auto& item : GetChildren()) { auto positionedItem = AceType::DynamicCast(item); if (!positionedItem) { - if (item->GetPositionType() == PositionType::ABSOLUTE) { + if (item->GetPositionType() == PositionType::PTABSOLUTE) { auto itemOffset = PositionLayoutUtils::GetAbsoluteOffset(Claim(this), item); item->SetAbsolutePosition(itemOffset); continue; diff --git a/frameworks/core/components/test/unittest/stack/render_stack_test.cpp b/frameworks/core/components/test/unittest/stack/render_stack_test.cpp index 44365482baf..de90f32a65b 100644 --- a/frameworks/core/components/test/unittest/stack/render_stack_test.cpp +++ b/frameworks/core/components/test/unittest/stack/render_stack_test.cpp @@ -481,12 +481,13 @@ HWTEST_F(RenderStackTest, RenderStackLayout010, TestSize.Level1) HWTEST_F(RenderStackTest, RenderStackHitTest001, TestSize.Level1) { /** - * @tc.steps: step1. construct the node tree, stack is set HitTestMode::BLOCK. + * @tc.steps: step1. construct the node tree, stack is set HitTestMode::HTMBLOCK. */ auto mockContext = MockRenderCommon::GetMockContext(); RefPtr root = FlexTestUtils::CreateRenderRoot(); RefPtr stack = - StackTestUtils::CreateRenderStack(Alignment::TOP_LEFT, Overflow::CLIP, StackFit::STRETCH, HitTestMode::BLOCK); + StackTestUtils::CreateRenderStack(Alignment::TOP_LEFT, Overflow::CLIP, + StackFit::STRETCH, HitTestMode::HTMBLOCK); root->AddChild(stack); auto renderButton = FlexTestUtils::CreateRenderButton(BUTTON_WIDTH_DEFAULT, BUTTON_HEIGHT_DEFAULT); renderButton->Attach(mockContext); diff --git a/frameworks/core/components/test/unittest/stack/stack_test_utils.h b/frameworks/core/components/test/unittest/stack/stack_test_utils.h index c54c4b79112..450fefa8a36 100644 --- a/frameworks/core/components/test/unittest/stack/stack_test_utils.h +++ b/frameworks/core/components/test/unittest/stack/stack_test_utils.h @@ -31,7 +31,7 @@ class MockRenderStack : public RenderStack { class StackTestUtils { public: static RefPtr CreateRenderStack(const Alignment& alignment, Overflow overflow, - StackFit stackFit, HitTestMode hitTestMode = HitTestMode::DEFAULT); + StackFit stackFit, HitTestMode hitTestMode = HitTestMode::HTMDEFAULT); static RefPtr CreateRenderPositioned(RefPtr positioned); }; diff --git a/frameworks/core/components/tool_bar/render_tool_bar_item.h b/frameworks/core/components/tool_bar/render_tool_bar_item.h index 555434f0a0e..39422146df4 100644 --- a/frameworks/core/components/tool_bar/render_tool_bar_item.h +++ b/frameworks/core/components/tool_bar/render_tool_bar_item.h @@ -51,7 +51,7 @@ public: void SetFocusEventFlag(bool onFocus) { onFocus_ = onFocus; - if (position_ == PositionType::FIXED) { + if (position_ == PositionType::PTFIXED) { auto context = context_.Upgrade(); if (!context) { LOGE("Pipeline context upgrade fail!"); @@ -116,7 +116,7 @@ private: TargetMenuCallBack targetMenuCallBack_; bool isEndItem_ = false; Dimension menuMinWidth_; - PositionType position_ { PositionType::RELATIVE }; + PositionType position_ { PositionType::PTRELATIVE }; RefPtr eventEffectController_; }; diff --git a/frameworks/core/components_v2/inspector/inspector_composed_element.cpp b/frameworks/core/components_v2/inspector/inspector_composed_element.cpp index 69d9d9fa49a..8237e4e72d5 100644 --- a/frameworks/core/components_v2/inspector/inspector_composed_element.cpp +++ b/frameworks/core/components_v2/inspector/inspector_composed_element.cpp @@ -619,7 +619,7 @@ std::unique_ptr InspectorComposedElement::GetPosition() const auto render = AceType::DynamicCast(node); if (render) { PositionType type = render->GetPositionType(); - if (type == PositionType::ABSOLUTE) { + if (type == PositionType::PTABSOLUTE) { jsonValue->Put("x", render->GetLeft().ToString().c_str()); jsonValue->Put("y", render->GetTop().ToString().c_str()); return jsonValue; @@ -662,7 +662,7 @@ std::unique_ptr InspectorComposedElement::GetOffset() const auto render = AceType::DynamicCast(node); if (render) { PositionType type = render->GetPositionType(); - if (type == PositionType::OFFSET) { + if (type == PositionType::PTOFFSET) { jsonValue->Put("x", render->GetLeft().ToString().c_str()); jsonValue->Put("y", render->GetTop().ToString().c_str()); return jsonValue; diff --git a/frameworks/core/pipeline/base/component.h b/frameworks/core/pipeline/base/component.h index 94ee27402db..d4b821a84f1 100644 --- a/frameworks/core/pipeline/base/component.h +++ b/frameworks/core/pipeline/base/component.h @@ -322,7 +322,7 @@ private: bool useExternalRSNode_ = false; std::string inspectorTag_; int32_t restoreId_ = -1; - HitTestMode hitTestMode_ = HitTestMode::DEFAULT; + HitTestMode hitTestMode_ = HitTestMode::HTMDEFAULT; ElementIdType elmtId_ = ElementRegister::UndefinedElementId; }; diff --git a/frameworks/core/pipeline/base/render_node.cpp b/frameworks/core/pipeline/base/render_node.cpp index d035ea869c7..86ba21c0013 100644 --- a/frameworks/core/pipeline/base/render_node.cpp +++ b/frameworks/core/pipeline/base/render_node.cpp @@ -727,7 +727,7 @@ bool RenderNode::DispatchTouchTestToChildren(const Point& localPoint, const Poin const TouchRestrict& touchRestrict, TouchTestResult& result) { bool dispatchSuccess = false; - if (!IsChildrenTouchEnable() || GetHitTestMode() == HitTestMode::BLOCK) { + if (!IsChildrenTouchEnable() || GetHitTestMode() == HitTestMode::HTMBLOCK) { return dispatchSuccess; } @@ -739,14 +739,14 @@ bool RenderNode::DispatchTouchTestToChildren(const Point& localPoint, const Poin } if (child->TouchTest(globalPoint, localPoint, touchRestrict, result)) { dispatchSuccess = true; - if (child->GetHitTestMode() != HitTestMode::TRANSPARENT) { + if (child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) { break; } } auto interceptTouchEvent = (child->IsTouchable() && (child->InterceptTouchEvent() || IsExclusiveEventForChild()) && - child->GetHitTestMode() != HitTestMode::TRANSPARENT); - if (child->GetHitTestMode() == HitTestMode::BLOCK || interceptTouchEvent) { + child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT); + if (child->GetHitTestMode() == HitTestMode::HTMBLOCK || interceptTouchEvent) { auto localTransformPoint = child->GetTransformPoint(localPoint); bool isInRegion = false; for (const auto& rect : child->GetTouchRectList()) { @@ -756,7 +756,7 @@ bool RenderNode::DispatchTouchTestToChildren(const Point& localPoint, const Poin break; } } - if (isInRegion && child->GetHitTestMode() != HitTestMode::DEFAULT) { + if (isInRegion && child->GetHitTestMode() != HitTestMode::HTMDEFAULT) { break; } } @@ -1192,7 +1192,7 @@ double RenderNode::NormalizePercentToPx(const Dimension& dimension, bool isVerti if (!parent) { referSize = GetLayoutParam().GetMaxSize(); } else { - if (positionParam_.type == PositionType::OFFSET) { + if (positionParam_.type == PositionType::PTOFFSET) { referSize = parent->GetLayoutSize(); } else { referSize = parent->GetLayoutParam().GetMaxSize(); @@ -1335,7 +1335,7 @@ void RenderNode::UpdateAll(const RefPtr& component) if (auto rsNode = GetRSNode()) { auto nativeMotionOption = std::make_shared( NativeCurveHelper::ToNativeMotionPathOption(motionPathOption_, - positionParam_.type == PositionType::OFFSET)); + positionParam_.type == PositionType::PTOFFSET)); rsNode->SetMotionPathOption(nativeMotionOption); } } diff --git a/frameworks/core/pipeline/base/render_node.h b/frameworks/core/pipeline/base/render_node.h index 77ddf657380..49a8870ec36 100644 --- a/frameworks/core/pipeline/base/render_node.h +++ b/frameworks/core/pipeline/base/render_node.h @@ -1356,7 +1356,7 @@ private: std::string restoreInfo_; bool isNotSiblingAddRecognizerToResult_ = true; - HitTestMode hitTestMode_ = HitTestMode::DEFAULT; + HitTestMode hitTestMode_ = HitTestMode::HTMDEFAULT; ACE_DISALLOW_COPY_AND_MOVE(RenderNode); }; From 993f79fcec346df74d0655ec27110af724bd0425 Mon Sep 17 00:00:00 2001 From: yangwt Date: Thu, 1 Sep 2022 11:48:18 +0800 Subject: [PATCH 23/35] =?UTF-8?q?=E3=80=90UI=E7=BB=84=E4=BB=B6=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E3=80=91Text=E7=BB=84=E4=BB=B6=E6=96=B0=E5=A2=9EminFo?= =?UTF-8?q?ntSize=E3=80=81maxFontSize=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangwt Change-Id: I740979f2ce75f19b8a671b132513326b19c7dee7 --- .../declarative_frontend/jsview/js_text.cpp | 8 ++ .../pattern/text/text_layout_algorithm.cpp | 77 +++++++++++++++++-- .../pattern/text/text_layout_algorithm.h | 5 ++ .../pattern/text/text_layout_property.h | 2 + .../pattern/text/text_styles.cpp | 2 + .../components_ng/pattern/text/text_styles.h | 2 + .../components_ng/pattern/text/text_view.cpp | 10 +++ .../components_ng/pattern/text/text_view.h | 2 + .../pattern/text/text_pattern_test_ng.cpp | 18 +++++ 9 files changed, 120 insertions(+), 6 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_text.cpp b/frameworks/bridge/declarative_frontend/jsview/js_text.cpp index f83f8fe8fdd..3318bcee178 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_text.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_text.cpp @@ -319,6 +319,10 @@ void JSText::SetMinFontSize(const JSCallbackInfo& info) if (!ParseJsDimensionFp(info[0], fontSize)) { return; } + if (Container::IsCurrentUseNewPipeline()) { + NG::TextView::SetAdaptMinFontSize(fontSize); + return; + } auto component = GetComponent(); if (!component) { LOGE("component is not valid"); @@ -340,6 +344,10 @@ void JSText::SetMaxFontSize(const JSCallbackInfo& info) if (!ParseJsDimensionFp(info[0], fontSize)) { return; } + if (Container::IsCurrentUseNewPipeline()) { + NG::TextView::SetAdaptMaxFontSize(fontSize); + return; + } auto component = GetComponent(); if (!component) { LOGE("component is not valid"); diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp index 7620c80f52e..b32d5785aa4 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp @@ -44,13 +44,14 @@ std::optional TextLayoutAlgorithm::MeasureContent( auto themeManager = pipeline->GetThemeManager(); TextStyle textStyle = CreateTextStyleUsingTheme(textLayoutProperty->GetFontStyle(), textLayoutProperty->GetTextLineStyle(), themeManager ? themeManager->GetTheme() : nullptr); - if (!CreateParagraph(textStyle, textLayoutProperty->GetContent().value_or(""))) { - return std::nullopt; - } - if (contentConstraint.selfIdealSize.Width()) { - paragraph_->Layout(contentConstraint.selfIdealSize.Width().value()); + if (!textStyle.GetAdaptTextSize()) { + if (CreateParagraphAndLayout(textStyle, textLayoutProperty->GetContent().value_or(""), contentConstraint)) { + return std::nullopt; + } } else { - paragraph_->Layout(contentConstraint.maxSize.Width()); + if (AdaptMinTextSize(textStyle, textLayoutProperty->GetContent().value_or(""), contentConstraint, pipeline)) { + return std::nullopt; + } } auto height = static_cast(paragraph_->GetHeight()); double baselineOffset = 0.0; @@ -95,6 +96,70 @@ bool TextLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::strin return true; } +bool TextLayoutAlgorithm::CreateParagraphAndLayout( + const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint) +{ + if (!CreateParagraph(textStyle, content)) { + return false; + } + CHECK_NULL_RETURN(paragraph_, false); + if (contentConstraint.selfIdealSize.Width()) { + paragraph_->Layout(contentConstraint.selfIdealSize.Width().value()); + } else { + paragraph_->Layout(contentConstraint.maxSize.Width()); + } + return true; +} + +bool TextLayoutAlgorithm::AdaptMinTextSize(TextStyle& textStyle, const std::string& content, + const LayoutConstraintF& contentConstraint, const RefPtr& pipeline) +{ + double maxFontSize = 0.0; + double minFontSize = 0.0; + if (!textStyle.GetAdaptMaxFontSize().NormalizeToPx(pipeline->GetDipScale(), pipeline->GetFontScale(), + pipeline->GetLogicScale(), contentConstraint.maxSize.Height(), maxFontSize)) { + return false; + } + if (!textStyle.GetAdaptMinFontSize().NormalizeToPx(pipeline->GetDipScale(), pipeline->GetFontScale(), + pipeline->GetLogicScale(), contentConstraint.maxSize.Height(), minFontSize)) { + return false; + } + if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) { + CreateParagraphAndLayout(textStyle, content, contentConstraint); + } + constexpr Dimension ADAPT_UNIT = 1.0_fp; + Dimension step = ADAPT_UNIT; + if (GreatNotEqual(textStyle.GetAdaptFontSizeStep().Value(), 0.0)) { + step = textStyle.GetAdaptFontSizeStep(); + } + double stepSize = 0.0; + if (!step.NormalizeToPx(pipeline->GetDipScale(), pipeline->GetFontScale(), pipeline->GetLogicScale(), + contentConstraint.maxSize.Height(), stepSize)) { + return false; + } + while (GreatOrEqual(maxFontSize, minFontSize)) { + textStyle.SetFontSize(Dimension(maxFontSize)); + if (!CreateParagraphAndLayout(textStyle, content, contentConstraint)) { + return false; + } + if (!DidExceedMaxLines(contentConstraint)) { + break; + } + maxFontSize -= stepSize; + } + return true; +} + +bool TextLayoutAlgorithm::DidExceedMaxLines(const LayoutConstraintF& contentConstraint) +{ + CHECK_NULL_RETURN(paragraph_, false); + bool didExceedMaxLines = paragraph_->DidExceedMaxLines(); + didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph_->GetHeight(), contentConstraint.maxSize.Height()); + didExceedMaxLines = + didExceedMaxLines || GreatNotEqual(paragraph_->GetLongestLine(), contentConstraint.maxSize.Width()); + return didExceedMaxLines; +} + TextDirection TextLayoutAlgorithm::GetTextDirection(const std::string& content) { TextDirection textDirection = TextDirection::LTR; diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h index c95826f5646..7ffbba0a03e 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h @@ -52,6 +52,11 @@ public: private: bool CreateParagraph(const TextStyle& textStyle, std::string content); + bool CreateParagraphAndLayout( + const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint); + bool AdaptMinTextSize(TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint, + const RefPtr& pipeline); + bool DidExceedMaxLines(const LayoutConstraintF& contentConstraint); static TextDirection GetTextDirection(const std::string& content); double GetTextWidth() const; diff --git a/frameworks/core/components_ng/pattern/text/text_layout_property.h b/frameworks/core/components_ng/pattern/text/text_layout_property.h index 53859760df3..b0f1efa5f02 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_property.h +++ b/frameworks/core/components_ng/pattern/text/text_layout_property.h @@ -56,6 +56,8 @@ public: ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, TextDecoration, TextDecoration, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, TextDecorationColor, Color, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, TextCase, TextCase, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, AdaptMinFontSize, Dimension, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, AdaptMaxFontSize, Dimension, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_GROUP(TextLineStyle, TextLineStyle); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TextLineStyle, LineHeight, Dimension, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(TextLineStyle, TextBaseline, TextBaseline, PROPERTY_UPDATE_MEASURE); diff --git a/frameworks/core/components_ng/pattern/text/text_styles.cpp b/frameworks/core/components_ng/pattern/text/text_styles.cpp index fa080b17a9a..ff9d49748c2 100644 --- a/frameworks/core/components_ng/pattern/text/text_styles.cpp +++ b/frameworks/core/components_ng/pattern/text/text_styles.cpp @@ -36,6 +36,8 @@ TextStyle CreateTextStyleUsingTheme(const std::unique_ptr& fontStyle, UPDATE_TEXT_STYLE(fontStyle, TextDecoration, SetTextDecoration); UPDATE_TEXT_STYLE(fontStyle, TextDecorationColor, SetTextDecorationColor); UPDATE_TEXT_STYLE(fontStyle, TextCase, SetTextCase); + UPDATE_TEXT_STYLE(fontStyle, AdaptMinFontSize, SetAdaptMinFontSize); + UPDATE_TEXT_STYLE(fontStyle, AdaptMaxFontSize, SetAdaptMaxFontSize); } if (textLineStyle) { UPDATE_TEXT_STYLE(textLineStyle, LineHeight, SetLineHeight); diff --git a/frameworks/core/components_ng/pattern/text/text_styles.h b/frameworks/core/components_ng/pattern/text/text_styles.h index 8311c37c5cc..4c209b31c05 100644 --- a/frameworks/core/components_ng/pattern/text/text_styles.h +++ b/frameworks/core/components_ng/pattern/text/text_styles.h @@ -32,6 +32,8 @@ struct FontStyle { ACE_DEFINE_PROPERTY_GROUP_ITEM(TextDecoration, TextDecoration); ACE_DEFINE_PROPERTY_GROUP_ITEM(TextDecorationColor, Color); ACE_DEFINE_PROPERTY_GROUP_ITEM(TextCase, TextCase); + ACE_DEFINE_PROPERTY_GROUP_ITEM(AdaptMinFontSize, Dimension); + ACE_DEFINE_PROPERTY_GROUP_ITEM(AdaptMaxFontSize, Dimension); }; struct TextLineStyle { diff --git a/frameworks/core/components_ng/pattern/text/text_view.cpp b/frameworks/core/components_ng/pattern/text/text_view.cpp index 8ca2be0dc18..f38aed474b7 100644 --- a/frameworks/core/components_ng/pattern/text/text_view.cpp +++ b/frameworks/core/components_ng/pattern/text/text_view.cpp @@ -103,4 +103,14 @@ void TextView::SetLetterSpacing(const Dimension& value) ACE_UPDATE_LAYOUT_PROPERTY(TextLayoutProperty, LetterSpacing, value); } +void TextView::SetAdaptMinFontSize(const Dimension& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(TextLayoutProperty, AdaptMinFontSize, value); +} + +void TextView::SetAdaptMaxFontSize(const Dimension& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(TextLayoutProperty, AdaptMaxFontSize, value); +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text/text_view.h b/frameworks/core/components_ng/pattern/text/text_view.h index df109e3b9f9..287eea8ddfc 100644 --- a/frameworks/core/components_ng/pattern/text/text_view.h +++ b/frameworks/core/components_ng/pattern/text/text_view.h @@ -41,6 +41,8 @@ public: static void SetBaselineOffset(const Dimension& value); static void SetTextCase(const TextCase& value); static void SetLetterSpacing(const Dimension& value); + static void SetAdaptMinFontSize(const Dimension& value); + static void SetAdaptMaxFontSize(const Dimension& value); }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/test/pattern/text/text_pattern_test_ng.cpp b/frameworks/core/components_ng/test/pattern/text/text_pattern_test_ng.cpp index d159a01b494..1ef6eab2a09 100644 --- a/frameworks/core/components_ng/test/pattern/text/text_pattern_test_ng.cpp +++ b/frameworks/core/components_ng/test/pattern/text/text_pattern_test_ng.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "gtest/gtest.h" #include "base/memory/ace_type.h" @@ -41,6 +43,8 @@ const Ace::TextDecoration TEXT_DECORATION_VALUE = Ace::TextDecoration::INHERIT; const Color TEXT_DECORATION_COLOR_VALUE = Color::FromRGB(255, 100, 100); const Dimension BASELINE_OFFSET_VALUE = Dimension(20.1, DimensionUnit::PX); const Ace::TextCase TEXT_CASE_VALUE = Ace::TextCase::LOWERCASE; +const Dimension ADAPT_MIN_FONT_SIZE_VALUE = Dimension(50, DimensionUnit::PX); +const Dimension ADAPT_MAX_FONT_SIZE_VALUE = Dimension(200, DimensionUnit::PX); } // namespace struct TestProperty { @@ -57,6 +61,8 @@ struct TestProperty { std::optional textDecorationColorValue = std::nullopt; std::optional baselineOffsetValue = std::nullopt; std::optional textCaseValue = std::nullopt; + std::optional adaptMinFontSize = std::nullopt; + std::optional adaptMaxFontSize = std::nullopt; }; class TextPatternTestNg : public testing::Test { @@ -118,6 +124,12 @@ RefPtr TextPatternTestNg::CreateTextParagraph( if (testProperty.textCaseValue.has_value()) { TextView::SetTextCase(testProperty.textCaseValue.value()); } + if (testProperty.adaptMinFontSize.has_value()) { + TextView::SetAdaptMinFontSize(testProperty.adaptMinFontSize.value()); + } + if (testProperty.adaptMaxFontSize.has_value()) { + TextView::SetAdaptMaxFontSize(testProperty.adaptMaxFontSize.value()); + } RefPtr element = ViewStackProcessor::GetInstance()->Finish(); // TextView pop return AceType::DynamicCast(element); @@ -144,6 +156,8 @@ HWTEST_F(TextPatternTestNg, TextFrameNodeCreator001, TestSize.Level1) testProperty.textDecorationColorValue = std::make_optional(TEXT_DECORATION_COLOR_VALUE); testProperty.baselineOffsetValue = std::make_optional(BASELINE_OFFSET_VALUE); testProperty.textCaseValue = std::make_optional(TEXT_CASE_VALUE); + testProperty.adaptMinFontSize = std::make_optional(ADAPT_MIN_FONT_SIZE_VALUE); + testProperty.adaptMaxFontSize = std::make_optional(ADAPT_MAX_FONT_SIZE_VALUE); RefPtr frameNode = CreateTextParagraph(CREATE_VALUE, testProperty); EXPECT_EQ(frameNode == nullptr, false); @@ -170,5 +184,9 @@ HWTEST_F(TextPatternTestNg, TextFrameNodeCreator001, TestSize.Level1) EXPECT_EQ(textStyle.GetTextDecorationColor(), TEXT_DECORATION_COLOR_VALUE); EXPECT_EQ(textStyle.GetBaselineOffset(), BASELINE_OFFSET_VALUE); EXPECT_EQ(textStyle.GetTextCase(), TEXT_CASE_VALUE); + EXPECT_EQ(textStyle.GetAdaptMinFontSize(), ADAPT_MIN_FONT_SIZE_VALUE); + EXPECT_EQ(textStyle.GetAdaptMaxFontSize(), ADAPT_MAX_FONT_SIZE_VALUE); + EXPECT_EQ(textStyle.GetAdaptTextSize(), + testProperty.adaptMinFontSize.has_value() || testProperty.adaptMaxFontSize.has_value()); } } // namespace OHOS::Ace::NG From 72755ae84c8b346ad48ada4be8954564937ef3e9 Mon Sep 17 00:00:00 2001 From: zhoutianer Date: Mon, 29 Aug 2022 16:58:21 +0800 Subject: [PATCH 24/35] fix flutter image blur Signed-off-by: zhoutianer Change-Id: Ia393f4b0df74e8bc740bbf825ac2e8bab5b5f6bb --- .../declarative_frontend/jsview/js_image.cpp | 22 +++++++++++++++++++ .../declarative_frontend/jsview/js_image.h | 1 + .../components/image/flutter_render_image.cpp | 9 ++++++++ .../components/image/flutter_render_image.h | 1 + .../core/components/image/image_component.h | 11 ++++++++++ .../core/components/image/render_image.cpp | 1 + .../core/components/image/render_image.h | 1 + 7 files changed, 46 insertions(+) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_image.cpp b/frameworks/bridge/declarative_frontend/jsview/js_image.cpp index b1d0728f4d7..9487ac8a40c 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_image.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_image.cpp @@ -393,6 +393,27 @@ void JSImage::JsOpacity(const JSCallbackInfo& info) } } +void JSImage::JsBlur(const JSCallbackInfo& info) +{ +// only flutter runs special image blur +#ifdef ENABLE_ROSEN_BACKEND + JSViewAbstract::JsBlur(info); +#else + if (info.Length() < 1) { + LOGE("The argv is wrong, it is supposed to have at least 1 argument"); + return; + } + auto mainComp = ViewStackProcessor::GetInstance()->GetMainComponent(); + auto image = AceType::DynamicCast(mainComp); + if (image) { + double blur = 0.0; + if (ParseJsDouble(info[0], blur)) { + image->SetBlur(blur); + } + } +#endif +} + void JSImage::SetAutoResize(bool autoResize) { SET_PROP_FOR_NG(AutoResize, bool, autoResize); @@ -509,6 +530,7 @@ void JSImage::JSBind(BindingTarget globalObj) JSClass::StaticMethod("copyOption", &JSImage::SetCopyOption); // override method JSClass::StaticMethod("opacity", &JSImage::JsOpacity); + JSClass::StaticMethod("blur", &JSImage::JsBlur); JSClass::StaticMethod("transition", &JSImage::JsTransition); JSClass::Inherit(); JSClass::Bind<>(globalObj); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_image.h b/frameworks/bridge/declarative_frontend/jsview/js_image.h index 0d7fe3f34aa..71bcc4e4d00 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_image.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_image.h @@ -69,6 +69,7 @@ public: static void SetBottomBorderWidth(const Dimension& value); static void SetBorderRadius(const Dimension& value); static void JsOpacity(const JSCallbackInfo& info); + static void JsBlur(const JSCallbackInfo& info); static void JsTransition(const JSCallbackInfo& info); static void JsOnDragStart(const JSCallbackInfo& info); static void JsOnDragEnter(const JSCallbackInfo& info); diff --git a/frameworks/core/components/image/flutter_render_image.cpp b/frameworks/core/components/image/flutter_render_image.cpp index bdf18ccda44..ce405a5c394 100644 --- a/frameworks/core/components/image/flutter_render_image.cpp +++ b/frameworks/core/components/image/flutter_render_image.cpp @@ -20,6 +20,7 @@ #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkShader.h" +#include "third_party/skia/include/effects/SkImageFilters.h" #include "base/utils/utils.h" @@ -549,6 +550,7 @@ void FlutterRenderImage::Paint(RenderContext& context, const Offset& offset) return; } ApplyColorFilter(paint); + ApplyBlur(paint); ApplyInterpolation(paint); sk_sp colorSpace = SkColorSpace::MakeSRGB(); if (image_) { @@ -626,6 +628,13 @@ void FlutterRenderImage::ApplyColorFilter(flutter::Paint& paint) #endif } +void FlutterRenderImage::ApplyBlur(flutter::Paint& paint) +{ + if (GreatNotEqual(blurRadius_, 0.0)) { + paint.paint()->setImageFilter(SkImageFilters::Blur(blurRadius_, blurRadius_, nullptr)); + } +} + void FlutterRenderImage::ApplyInterpolation(flutter::Paint& paint) { auto skFilterQuality = SkFilterQuality::kNone_SkFilterQuality; diff --git a/frameworks/core/components/image/flutter_render_image.h b/frameworks/core/components/image/flutter_render_image.h index 40dbbb88201..32c3d5f3513 100644 --- a/frameworks/core/components/image/flutter_render_image.h +++ b/frameworks/core/components/image/flutter_render_image.h @@ -134,6 +134,7 @@ private: Rect RecalculateSrcRect(const Size& realImageSize); void ApplyColorFilter(flutter::Paint& paint); void ApplyInterpolation(flutter::Paint& paint); + void ApplyBlur(flutter::Paint& paint); void ApplyBorderRadius(const Offset& offset, const ScopedCanvas& canvas, const Rect& paintRect); void AddSvgChild(); void CreateAnimatedPlayer(const RefPtr& provider, SkCodec* codecPtr, bool forceResize); diff --git a/frameworks/core/components/image/image_component.h b/frameworks/core/components/image/image_component.h index 3c174ff8440..554fef636ed 100644 --- a/frameworks/core/components/image/image_component.h +++ b/frameworks/core/components/image/image_component.h @@ -173,6 +173,16 @@ public: focusable_ = focusable; } + float GetBlurRadius() const + { + return blurRadius_; + } + + void SetBlur(float radius) + { + blurRadius_ = radius; + } + private: std::string src_; std::string alt_; @@ -182,6 +192,7 @@ private: std::optional color_; std::optional fillColor_; // used for paint svg path. std::vector colorfilter_; + float blurRadius_ = 0.0f; EventMarker loadSuccessEvent_; EventMarker loadFailEvent_; diff --git a/frameworks/core/components/image/render_image.cpp b/frameworks/core/components/image/render_image.cpp index a4a09e02423..063b94b0252 100644 --- a/frameworks/core/components/image/render_image.cpp +++ b/frameworks/core/components/image/render_image.cpp @@ -69,6 +69,7 @@ void RenderImage::Update(const RefPtr& component) currentDstRect_ = dstRect_; currentDstRectList_ = rectList_; colorfilter_ = image->GetColorFilterMatrix(); + blurRadius_ = image->GetBlurRadius(); width_ = image->GetWidth(); syncMode_ = image->GetSyncMode(); height_ = image->GetHeight(); diff --git a/frameworks/core/components/image/render_image.h b/frameworks/core/components/image/render_image.h index 8704c38db74..032dc1536be 100644 --- a/frameworks/core/components/image/render_image.h +++ b/frameworks/core/components/image/render_image.h @@ -399,6 +399,7 @@ protected: bool syncMode_ = false; Border border_; std::vector colorfilter_; + float blurRadius_; private: void UpdateOverlay(); void HandleOnCopy(); From 3c6ec7b47873d9abf30754c00f5d3f8cede37dd2 Mon Sep 17 00:00:00 2001 From: Sunfei Date: Fri, 2 Sep 2022 10:26:46 +0800 Subject: [PATCH 25/35] fix cross-platform build issue Signed-off-by: Sunfei Change-Id: Id447a37447a4eba393a03d08d51355ff2a60bd8e --- .../js_frontend/engine/common/js_engine.h | 3 ++- frameworks/bridge/js_frontend/js_ace_page.h | 2 +- frameworks/core/components/components.gni | 26 ++++++++++++++----- .../core/components/text_overlay/BUILD.gn | 8 ++---- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/frameworks/bridge/js_frontend/engine/common/js_engine.h b/frameworks/bridge/js_frontend/engine/common/js_engine.h index cfab911d51d..dadcc31eed9 100644 --- a/frameworks/bridge/js_frontend/engine/common/js_engine.h +++ b/frameworks/bridge/js_frontend/engine/common/js_engine.h @@ -22,12 +22,13 @@ #include "core/common/frontend.h" #include "core/common/js_message_dispatcher.h" #include "frameworks/bridge/js_frontend/frontend_delegate.h" -#include "frameworks/bridge/js_frontend/js_ace_page.h" class NativeEngine; class NativeReference; namespace OHOS::Ace::Framework { + +class JsAcePage; using PixelMapNapiEntry = void* (*)(void*, void*); struct JsModule { const std::string moduleName; diff --git a/frameworks/bridge/js_frontend/js_ace_page.h b/frameworks/bridge/js_frontend/js_ace_page.h index b492ab3084f..af855383631 100644 --- a/frameworks/bridge/js_frontend/js_ace_page.h +++ b/frameworks/bridge/js_frontend/js_ace_page.h @@ -31,7 +31,6 @@ #endif #include "core/components/page/page_target.h" #include "core/components/page_transition/page_transition_component.h" -#include "frameworks/bridge/common/dom/dom_document.h" #include "frameworks/bridge/common/utils/source_map.h" #include "frameworks/bridge/common/utils/utils.h" #include "frameworks/bridge/js_frontend/engine/common/base_animation_bridge.h" @@ -48,6 +47,7 @@ class UINode; namespace OHOS::Ace::Framework { #ifndef NG_BUILD +class DOMDocument; using JsPageRadioGroups = std::unordered_map>; #endif diff --git a/frameworks/core/components/components.gni b/frameworks/core/components/components.gni index 2cbb0144acb..dc675407e9c 100644 --- a/frameworks/core/components/components.gni +++ b/frameworks/core/components/components.gni @@ -103,12 +103,6 @@ template("build_component") { defines += invoker.component_defines } - if (defined(config.enable_rosen_backend) && config.enable_rosen_backend && - defined(invoker.rosen_sources)) { - sources += invoker.rosen_sources - configs += [ "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:render_service_client_config" ] - } - if (defined(config.enable_standard_input) && config.enable_standard_input) { if (defined(invoker.standard_input_sources)) { @@ -122,6 +116,26 @@ template("build_component") { } } } + + if (defined(config.web_components_support) && + config.web_components_support && is_standard_system) { + if (defined(invoker.standard_web_configs)) { + configs += invoker.standard_web_configs + } + if (defined(invoker.standard_web_deps)) { + if (defined(external_deps)) { + external_deps += invoker.standard_web_deps + } else { + external_deps = invoker.standard_web_deps + } + } + } + + if (defined(config.enable_rosen_backend) && config.enable_rosen_backend && + defined(invoker.rosen_sources)) { + sources += invoker.rosen_sources + configs += [ "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:render_service_client_config" ] + } part_name = ace_engine_part } } diff --git a/frameworks/core/components/text_overlay/BUILD.gn b/frameworks/core/components/text_overlay/BUILD.gn index 2022c2e6369..e18afc0ddaf 100755 --- a/frameworks/core/components/text_overlay/BUILD.gn +++ b/frameworks/core/components/text_overlay/BUILD.gn @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//foundation/arkui/ace_engine/adapter/ohos/build/config.gni") import( "//foundation/arkui/ace_engine/frameworks/core/components/components.gni") @@ -48,9 +47,6 @@ build_component("text_overlay_for_web") { rosen_sources = [ "rosen_render_text_overlay.cpp" ] - if (defined(web_components_support) && web_components_support && - is_standard_system) { - configs = [ ":ohos_text_overlay_web_config" ] - external_deps = [ "webview:libnweb" ] - } + standard_web_configs = [ ":ohos_text_overlay_web_config" ] + standard_web_deps = [ "webview:libnweb" ] } From ef598f7cf1abd0e9e7aafba4f67ecc89a2ce6bac Mon Sep 17 00:00:00 2001 From: laosan_ted Date: Fri, 2 Sep 2022 10:19:16 +0800 Subject: [PATCH 26/35] webview support virtual keyboard block input text Signed-off-by: laosan_ted --- frameworks/core/components/web/render_web.cpp | 96 ++++++++++++++++++- frameworks/core/components/web/render_web.h | 25 ++++- .../core/components/web/rosen_render_web.cpp | 1 + .../core/components/web/web_element.cpp | 4 +- frameworks/core/pipeline/pipeline_context.cpp | 15 +++ frameworks/core/pipeline/pipeline_context.h | 15 ++- 6 files changed, 150 insertions(+), 6 deletions(-) diff --git a/frameworks/core/components/web/render_web.cpp b/frameworks/core/components/web/render_web.cpp index 11d93bd2936..592806a9b26 100755 --- a/frameworks/core/components/web/render_web.cpp +++ b/frameworks/core/components/web/render_web.cpp @@ -31,6 +31,9 @@ constexpr int32_t DOUBLE_CLICK_FINGERS = 1; constexpr int32_t DOUBLE_CLICK_COUNTS = 2; constexpr int32_t SINGLE_CLICK_NUM = 1; constexpr int32_t DOUBLE_CLICK_NUM = 2; +constexpr int32_t DEFAULT_POINT_X = 0; +constexpr int32_t DEFAULT_POINT_Y = 50; +constexpr int32_t DEFAULT_NUMS_ONE = 1; RenderWeb::RenderWeb() : RenderNode(true) { @@ -49,6 +52,7 @@ void RenderWeb::OnAttachContext() if (delegate_) { // web component is displayed in full screen by default. drawSize_ = Size(pipelineContext->GetRootWidth(), pipelineContext->GetRootHeight()); + drawSizeCache_ = drawSize_; position_ = Offset(0, 0); #ifdef OHOS_STANDARD_SYSTEM delegate_->InitOHOSWeb(context_); @@ -58,6 +62,26 @@ void RenderWeb::OnAttachContext() } } +void RenderWeb::RegistVirtualKeyBoardListener() +{ + if (!needUpdateWeb_) { + return; + } + auto pipelineContext = context_.Upgrade(); + if (!pipelineContext) { + return; + } + pipelineContext->SetVirtualKeyBoardCallback( + [weak = AceType::WeakClaim(this)](int32_t width, int32_t height, double keyboard) { + auto renderWeb = weak.Upgrade(); + if (renderWeb) { + return renderWeb->ProcessVirtualKeyBoard(width, height, keyboard); + } + return false; + }); + needUpdateWeb_ = false; +} + void RenderWeb::Update(const RefPtr& component) { const RefPtr web = AceType::DynamicCast(component); @@ -68,7 +92,7 @@ void RenderWeb::Update(const RefPtr& component) onMouse_ = web->GetOnMouseEventCallback(); onKeyEvent_ = web->GetOnKeyEventCallback(); - + RegistVirtualKeyBoardListener(); web_ = web; if (delegate_) { delegate_->SetComponent(web); @@ -102,6 +126,58 @@ void RenderWeb::Update(const RefPtr& component) MarkNeedLayout(); } +bool RenderWeb::ProcessVirtualKeyBoard(int32_t width, int32_t height, double keyboard) +{ + double offsetFix = (height - globlePointPosition_.GetY()) > 100.0 ? + keyboard - (height - globlePointPosition_.GetY()) / 2.0 : keyboard; + LOGI("Web ProcessVirtualKeyBoard width=%{public}d height=%{public}d keyboard=%{public}f offsetFix=%{public}f", + width, height, keyboard, offsetFix); + if (globlePointPosition_.GetY() <= (height - keyboard) || offsetFix <= 0.0) { + offsetFix = 0.0; + } + if (delegate_) { + if (!isFocus_) { + if (isVirtualKeyBoardShow_ == VkState::VK_SHOW) { + drawSize_.SetSize(drawSizeCache_); + delegate_->Resize(drawSize_.Width(), drawSize_.Height()); + SyncGeometryProperties(); + SetRootView(width, height, 0); + isVirtualKeyBoardShow_ = VkState::VK_HIDE; + } + return false; + } + if (NearZero(keyboard)) { + drawSize_.SetSize(drawSizeCache_); + delegate_->Resize(drawSize_.Width(), drawSize_.Height()); + SyncGeometryProperties(); + SetRootView(width, height, 0); + isVirtualKeyBoardShow_ = VkState::VK_HIDE; + } else if (isVirtualKeyBoardShow_ != VkState::VK_SHOW) { + drawSizeCache_.SetSize(drawSize_); + if (drawSize_.Height() <= (height - keyboard - GetCoordinatePoint().GetY() + offsetFix)) { + SetRootView(width, height, -offsetFix); + isVirtualKeyBoardShow_ = VkState::VK_SHOW; + return true; + } + drawSize_.SetHeight(height - keyboard - GetCoordinatePoint().GetY() + offsetFix); + delegate_->Resize(drawSize_.Width(), drawSize_.Height()); + SyncGeometryProperties(); + SetRootView(width, height, (NearZero(offsetFix)) ? DEFAULT_NUMS_ONE : -offsetFix); + isVirtualKeyBoardShow_ = VkState::VK_SHOW; + } + } + return true; +} + +void RenderWeb::SetRootView(int32_t width, int32_t height, int32_t offset) +{ + auto pipelineContext = context_.Upgrade(); + if (!pipelineContext) { + return; + } + pipelineContext->SetRootRect(width, height, offset); +} + void RenderWeb::OnMouseEvent(const MouseEvent& event) { if (!delegate_) { @@ -116,6 +192,17 @@ void RenderWeb::OnMouseEvent(const MouseEvent& event) auto localLocation = event.GetOffset() - Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY()); delegate_->OnMouseEvent(localLocation.GetX(), localLocation.GetY(), event.button, event.action, SINGLE_CLICK_NUM); + + // clear the recording position, for not move content when virtual keyboard popup when web get focused. + if (GetCoordinatePoint().GetY() > 0) { + webPoint_ = Offset(DEFAULT_POINT_X, DEFAULT_POINT_Y) + + Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY()); + } + auto context = GetContext().Upgrade(); + if (context && context->GetTextFieldManager()) { + context->GetTextFieldManager()->SetClickPosition(Offset()); + globlePointPosition_ = localLocation + webPoint_; + } } bool RenderWeb::HandleMouseEvent(const MouseEvent& event) @@ -242,6 +329,7 @@ void RenderWeb::HandleTouchDown(const TouchEventInfo& info, bool fromOverlay) LOGE("Touch down delegate_ is nullptr"); return; } + Offset touchOffset = Offset(0, 0); std::list touchInfos; if (!ParseTouchInfo(info, touchInfos, TouchType::DOWN)) { LOGE("Touch down error"); @@ -252,12 +340,18 @@ void RenderWeb::HandleTouchDown(const TouchEventInfo& info, bool fromOverlay) touchPoint.x -= GetGlobalOffset().GetX(); touchPoint.y -= GetGlobalOffset().GetY(); } + touchOffset = Offset(touchPoint.x, touchPoint.y); delegate_->HandleTouchDown(touchPoint.id, touchPoint.x, touchPoint.y); } // clear the recording position, for not move content when virtual keyboard popup when web get focused. + if (GetCoordinatePoint().GetY() > 0) { + webPoint_ = Offset(DEFAULT_POINT_X, DEFAULT_POINT_Y) + + Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY()); + } auto context = GetContext().Upgrade(); if (context && context->GetTextFieldManager()) { context->GetTextFieldManager()->SetClickPosition(Offset()); + globlePointPosition_ = touchOffset + webPoint_; } } diff --git a/frameworks/core/components/web/render_web.h b/frameworks/core/components/web/render_web.h index 1c1a2177f21..41468f62ae5 100755 --- a/frameworks/core/components/web/render_web.h +++ b/frameworks/core/components/web/render_web.h @@ -56,6 +56,12 @@ public: RenderWeb(); ~RenderWeb() override = default; + enum class VkState { + VK_NONE, + VK_SHOW, + VK_HIDE + }; + void Update(const RefPtr& component) override; void PerformLayout() override; void OnAttachContext() override; @@ -103,11 +109,21 @@ public: void HandleAxisEvent(const AxisEvent& event) override; bool IsAxisScrollable(AxisDirection direction) override; WeakPtr CheckAxisNode() override; + + void SetWebIsFocus(bool isFocus) + { + isFocus_ = isFocus; + } + bool GetWebIsFocus() const + { + return isFocus_; + } protected: RefPtr delegate_; RefPtr web_; Size drawSize_; + Size drawSizeCache_; bool isUrlLoaded_ = false; private: @@ -144,8 +160,15 @@ private: bool showStartTouchHandle_ = false; bool showEndTouchHandle_ = false; #endif - + void RegistVirtualKeyBoardListener(); + bool ProcessVirtualKeyBoard(int32_t width, int32_t height, double keyboard); + void SetRootView(int32_t width, int32_t height, int32_t offset); Offset position_; + Offset webPoint_; + Offset globlePointPosition_; + bool needUpdateWeb_ = true; + bool isFocus_ = false; + VkState isVirtualKeyBoardShow_ { VkState::VK_NONE }; }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/web/rosen_render_web.cpp b/frameworks/core/components/web/rosen_render_web.cpp index 27d3f928629..9a0bd37890d 100644 --- a/frameworks/core/components/web/rosen_render_web.cpp +++ b/frameworks/core/components/web/rosen_render_web.cpp @@ -77,6 +77,7 @@ void RosenRenderWeb::Paint(RenderContext& context, const Offset& offset) drawSize_ = Size(1.0, 1.0); } else { drawSize_ = Size(GetLayoutParam().GetMaxSize().Width(), GetLayoutParam().GetMaxSize().Height()); + drawSizeCache_ = drawSize_; } if (drawSize_.Width() == Size::INFINITE_SIZE || drawSize_.Height() == Size::INFINITE_SIZE || drawSize_.Width() == 0 || drawSize_.Height() == 0) { diff --git a/frameworks/core/components/web/web_element.cpp b/frameworks/core/components/web/web_element.cpp index 7ff788eb3f3..a66d9660ef3 100755 --- a/frameworks/core/components/web/web_element.cpp +++ b/frameworks/core/components/web/web_element.cpp @@ -58,12 +58,13 @@ void WebElement::OnFocus() return; } renderWeb->GetDelegate()->OnFocus(); + renderWeb->SetWebIsFocus(true); FocusNode::OnFocus(); } void WebElement::OnBlur() { - LOGI("web element onblur"); + LOGI("web element onBlur"); auto renderWeb = AceType::DynamicCast(renderNode_); if (!renderWeb) { return; @@ -73,6 +74,7 @@ void WebElement::OnBlur() return; } renderWeb->GetDelegate()->OnBlur(); + renderWeb->SetWebIsFocus(false); renderWeb->OnQuickMenuDismissed(); FocusNode::OnBlur(); } diff --git a/frameworks/core/pipeline/pipeline_context.cpp b/frameworks/core/pipeline/pipeline_context.cpp index 4b20d91e4ff..17392f1bb51 100644 --- a/frameworks/core/pipeline/pipeline_context.cpp +++ b/frameworks/core/pipeline/pipeline_context.cpp @@ -2036,6 +2036,9 @@ void PipelineContext::OnVirtualKeyboardAreaChange(Rect keyboardArea) if (textFieldManager_) { positionY = textFieldManager_->GetClickPosition().GetY(); } + if (NotifyVirtualKeyBoard(width_, height_, keyboardHeight)) { + return; + } double offsetFix = (height_ - positionY) > 100.0 ? keyboardHeight - (height_ - positionY) / 2.0 : keyboardHeight; LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f", positionY, (height_ - keyboardHeight), offsetFix); @@ -2159,6 +2162,17 @@ void PipelineContext::NotifyWebPaint() const } } +bool PipelineContext::NotifyVirtualKeyBoard(int32_t width, int32_t height, double keyboard) const +{ + CHECK_RUN_ON(UI); + for (auto& iterVirtualKeyBoardCallback : virtualKeyBoardCallback_) { + if (iterVirtualKeyBoardCallback && iterVirtualKeyBoardCallback(width, height, keyboard)) { + return true; + } + } + return false; +} + void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type) { CHECK_RUN_ON(UI); @@ -2517,6 +2531,7 @@ void PipelineContext::Destroy() window_->Destroy(); touchPluginPipelineContext_.clear(); webPaintCallback_.clear(); + virtualKeyBoardCallback_.clear(); rectCallbackList_.clear(); LOGI("PipelineContext::Destroy end."); } diff --git a/frameworks/core/pipeline/pipeline_context.h b/frameworks/core/pipeline/pipeline_context.h index 9a5d3b74d1b..ca5776188ae 100644 --- a/frameworks/core/pipeline/pipeline_context.h +++ b/frameworks/core/pipeline/pipeline_context.h @@ -307,6 +307,13 @@ public: } void NotifyWebPaint() const; + using virtualKeyBoardCallback = std::function; + void SetVirtualKeyBoardCallback(virtualKeyBoardCallback&& listener) + { + virtualKeyBoardCallback_.push_back(std::move(listener)); + } + bool NotifyVirtualKeyBoard(int32_t width, int32_t height, double keyboard) const; + float GetViewScale() const { return viewScale_; @@ -1072,13 +1079,14 @@ public: rectCallbackList_.emplace_back(RectCallback(getRectCallback, touchCallback, mouseCallback)); } -protected: - bool OnDumpInfo(const std::vector& params) const override; - void FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount) override; void SetRootRect(double width, double height, double offset = 0.0) override { SetRootSizeWithWidthHeight(width, height, offset); } + +protected: + bool OnDumpInfo(const std::vector& params) const override; + void FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount) override; void FlushPipelineWithoutAnimation() override; void FlushMessages() override; void FlushAnimation(uint64_t nanoTimestamp) override; @@ -1195,6 +1203,7 @@ private: EventTrigger eventTrigger_; std::list webPaintCallback_; + std::list virtualKeyBoardCallback_; WeakPtr requestedRenderNode_; // Make page update tasks pending here to avoid block receiving vsync. std::queue> pageUpdateTasks_; From f8370b22d08ecd62abe920078954919be9fc0083 Mon Sep 17 00:00:00 2001 From: chenxuankai1 Date: Sat, 3 Sep 2022 16:27:57 +0800 Subject: [PATCH 27/35] fix bug of divider covering sticky item Signed-off-by: chenxuankai1 Change-Id: Idec5ce12290df04a702024e8ee6d9589330b3ebc --- .../components_v2/list/rosen_render_list.cpp | 35 +++++++++++++------ .../components_v2/list/rosen_render_list.h | 4 +++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/frameworks/core/components_v2/list/rosen_render_list.cpp b/frameworks/core/components_v2/list/rosen_render_list.cpp index 3010f97a332..c21579bd1ff 100644 --- a/frameworks/core/components_v2/list/rosen_render_list.cpp +++ b/frameworks/core/components_v2/list/rosen_render_list.cpp @@ -34,6 +34,24 @@ void RosenRenderList::Update(const RefPtr& component) rsNode->SetClipToFrame(true); } +void RosenRenderList::DrawDividerOnNode(const std::shared_ptr& rsNode, const SkPaint& paint, bool isVertical, + double startCrossAxis, double mainAxis, double endCrossAxis) +{ + rsNode->DrawOnNode(Rosen::RSModifierType::CONTENT_STYLE, + [isVertical = vertical_, startX = startCrossAxis, startY = mainAxis, endX = endCrossAxis, endY = mainAxis, + paint](const std::shared_ptr& canvas) mutable { + if (!canvas) { + LOGE("sk canvas is nullptr when try paint divider for list"); + return; + } + if (!isVertical) { + std::swap(startX, startY); + std::swap(endX, endY); + } + canvas->drawLine(startX, startY, endX, endY, paint); + }); +} + void RosenRenderList::Paint(RenderContext& context, const Offset& offset) { const auto& layoutSize = GetLayoutSize(); @@ -57,6 +75,11 @@ void RosenRenderList::Paint(RenderContext& context, const Offset& offset) LOGE("canvas is null"); return; } + // if we call [SetPaintOrder(true)], all draw commands that are directly generated by [RosenRenderList] will be + // executed at last, which means the paint action of [divider] and [scrollBar_] is at the last(after + // [currentStickyItem_] being painted). Because [currentStickyItem_] is painted by [context.PiantChild] so that it has its + // own seperate recording. In order to accomplish the effect that [divider] is covered by [currentStickyItem_], we + // should draw it before [currentStickyItem_] being painted. rsNode->SetPaintOrder(true); const auto& divider = component_->GetItemDivider(); if (divider && divider->color.GetAlpha() > 0x00 && GreatNotEqual(divider->strokeWidth.Value(), 0.0)) { @@ -93,20 +116,12 @@ void RosenRenderList::Paint(RenderContext& context, const Offset& offset) continue; } mainAxis -= halfSpaceWidth; - if (vertical_) { - canvas->drawLine(startCrossAxis, mainAxis, endCrossAxis, mainAxis, paint); - } else { - canvas->drawLine(mainAxis, startCrossAxis, mainAxis, endCrossAxis, paint); - } + DrawDividerOnNode(rsNode, paint, vertical_, startCrossAxis, mainAxis, endCrossAxis); } if (selectedItem_) { double mainAxis = targetMainAxis_ - halfSpaceWidth; - if (vertical_) { - canvas->drawLine(startCrossAxis, mainAxis, endCrossAxis, mainAxis, paint); - } else { - canvas->drawLine(mainAxis, startCrossAxis, mainAxis, endCrossAxis, paint); - } + DrawDividerOnNode(rsNode, paint, vertical_, startCrossAxis, mainAxis, endCrossAxis); } } diff --git a/frameworks/core/components_v2/list/rosen_render_list.h b/frameworks/core/components_v2/list/rosen_render_list.h index 619f5f04e42..4cc16179b7f 100644 --- a/frameworks/core/components_v2/list/rosen_render_list.h +++ b/frameworks/core/components_v2/list/rosen_render_list.h @@ -16,6 +16,8 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_LIST_ROSEN_RENDER_LIST_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_V2_LIST_ROSEN_RENDER_LIST_H +#include "include/core/SkPaint.h" + #include "base/utils/noncopyable.h" #include "core/components_v2/list/render_list.h" @@ -34,6 +36,8 @@ public: private: void PaintSelectedZone(RenderContext& context); void PaintItemZone(RenderContext& context, const RefPtr& item); + void DrawDividerOnNode(const std::shared_ptr& rsNode, const SkPaint& paint, bool isVertical, + double startCrossAxis, double mainAxis, double endCrossAxis); RefPtr prevStickyItem_; ACE_DISALLOW_COPY_AND_MOVE(RosenRenderList); }; From 28589f1dbbd10592afbfd155cf5a77dc3435a71f Mon Sep 17 00:00:00 2001 From: yeyinglong Date: Fri, 2 Sep 2022 16:28:21 +0800 Subject: [PATCH 28/35] =?UTF-8?q?=E4=BF=AE=E5=A4=8DList/ListItemGroup?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yeyinglong Change-Id: I6bdc2e6c9c6245fa23e6d2d58b0a9770e18861c2 --- .../list/flutter_render_list.cpp | 14 +++++- .../list/flutter_render_list_item_group.cpp | 7 +++ .../core/components_v2/list/render_list.cpp | 22 ++++----- .../list/render_list_item_group.cpp | 47 +++++++++++-------- .../list/render_list_item_group.h | 10 ++-- .../components_v2/list/rosen_render_list.cpp | 9 +++- .../list/rosen_render_list_item_group.cpp | 7 +++ 7 files changed, 77 insertions(+), 39 deletions(-) diff --git a/frameworks/core/components_v2/list/flutter_render_list.cpp b/frameworks/core/components_v2/list/flutter_render_list.cpp index 02a3cb56c45..0ea9ea2c63c 100644 --- a/frameworks/core/components_v2/list/flutter_render_list.cpp +++ b/frameworks/core/components_v2/list/flutter_render_list.cpp @@ -17,6 +17,7 @@ #include "base/utils/utils.h" #include "core/components/common/painter/flutter_scroll_bar_painter.h" +#include "core/components_v2/list/render_list_item_group.h" #include "core/pipeline/base/scoped_canvas_state.h" namespace OHOS::Ace::V2 { @@ -72,24 +73,35 @@ void FlutterRenderList::Paint(RenderContext& context, const Offset& offset) paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(strokeWidth); bool isFirstIndex = (startIndex_ == 0); + double lastMainAxis = INFINITY; for (const auto& child : items_) { if (child == selectedItem_) { continue; } + double mainAxis = GetMainAxis(child->GetPosition()); if (isFirstIndex) { + lastMainAxis = mainAxis; isFirstIndex = false; continue; } - double mainAxis = GetMainAxis(child->GetPosition()); + auto itemGroup = AceType::DynamicCast(child); + if (itemGroup) { + mainAxis = GetMainAxis(itemGroup->GetRenderNode()->GetPosition()); + } if (GreatOrEqual(mainAxis - topOffset, mainSize)) { break; } if (LessOrEqual(mainAxis - bottomOffset, 0.0)) { continue; } + if (NearEqual(lastMainAxis, mainAxis)) { + continue; + } + lastMainAxis = mainAxis; + mainAxis -= halfSpaceWidth; if (vertical_) { skCanvas->drawLine(startCrossAxis, mainAxis, endCrossAxis, mainAxis, paint); diff --git a/frameworks/core/components_v2/list/flutter_render_list_item_group.cpp b/frameworks/core/components_v2/list/flutter_render_list_item_group.cpp index d343fa3c133..9d4d1f43b77 100644 --- a/frameworks/core/components_v2/list/flutter_render_list_item_group.cpp +++ b/frameworks/core/components_v2/list/flutter_render_list_item_group.cpp @@ -48,6 +48,7 @@ void FlutterRenderListItemGroup::PaintDivider(RenderContext& context) paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(strokeWidth); bool isFirstItem = (GetStartIndex() == 0); + double lastMainAxis = INFINITY; for (const auto& child : GetItems()) { double mainAxis = GetMainAxis(child->GetPosition()); @@ -55,12 +56,18 @@ void FlutterRenderListItemGroup::PaintDivider(RenderContext& context) break; } if (isFirstItem) { + lastMainAxis = mainAxis; isFirstItem = false; continue; } if (LessOrEqual(mainAxis - bottomOffset, 0.0)) { continue; } + if (NearEqual(mainAxis, lastMainAxis)) { + continue; + } + lastMainAxis = mainAxis; + mainAxis -= halfSpaceWidth; mainAxis += mainOffset; if (IsVertical()) { diff --git a/frameworks/core/components_v2/list/render_list.cpp b/frameworks/core/components_v2/list/render_list.cpp index 18c0a386b12..bd5941ce19b 100644 --- a/frameworks/core/components_v2/list/render_list.cpp +++ b/frameworks/core/components_v2/list/render_list.cpp @@ -488,9 +488,7 @@ void RenderList::RequestNewItemsAtEndForLaneList(double& curMainPos, double main } if (itemGroup) { double size = GetMainSize(itemGroup->GetLayoutSize()); - if (GreatNotEqual(size, 0.0)) { - curMainPos += size + spaceWidth_; - } + curMainPos += size + spaceWidth_; } if (breakWhenRequestNewItem) { break; @@ -572,10 +570,8 @@ void RenderList::RequestNewItemsAtStartForLaneList() } if (itemGroup) { double size = GetMainSize(itemGroup->GetLayoutSize()); - if (GreatNotEqual(size, 0.0)) { - currentOffset_ -= size + spaceWidth_; - startIndexOffset_ -= size + spaceWidth_; - } + currentOffset_ -= size + spaceWidth_; + startIndexOffset_ -= size + spaceWidth_; } if (breakWhenRequestNewItem) { break; @@ -646,7 +642,9 @@ void RenderList::PerformLayout() curMainPos += GetMainSize(selectedItem_->GetLayoutSize()) + spaceWidth_; } - curMainPos -= spaceWidth_; + if (startIndex_ + items_.size() >= TotalCount()) { + curMainPos -= spaceWidth_; + } // Check if reach the end of list reachEnd_ = LessOrEqual(curMainPos, mainSize); @@ -1310,8 +1308,8 @@ double RenderList::LayoutOrRecycleCurrentItemsForLaneList(double mainSize) double curMainPos = currentOffset_; size_t curIndex = startIndex_ - 1; std::vector> itemsInOneRow; - int32_t lackItemCount = 0; for (auto it = items_.begin(); it != items_.end();) { + int32_t lackItemCount = 0; // 1. layout children in a row double mainSize = 0.0; itemsInOneRow.clear(); @@ -1341,7 +1339,7 @@ double RenderList::LayoutOrRecycleCurrentItemsForLaneList(double mainSize) } // reach end of [items_] if (it == items_.end()) { - lackItemCount = lanes_ - i; + lackItemCount = lanes_ - i - 1; break; } } @@ -2995,8 +2993,8 @@ void RenderList::LayoutChild(RefPtr child, double referencePos, bool if (listItemGroup) { renderNode = listItemGroup->GetRenderNode(); ListItemLayoutParam param = { - .startCacheCount = cachedCount_ > 0 ? cachedCount_ - startCachedCount_ : 0, - .endCacheCount = cachedCount_ > 0 ? cachedCount_ - endCachedCount_ : 0, + .startCacheCount = (cachedCount_ > 0 && !isLaneList_) ? cachedCount_ - startCachedCount_ : 0, + .endCacheCount = (cachedCount_ > 0 && !isLaneList_) ? cachedCount_ - endCachedCount_ : 0, .startMainPos = (cachedCount_ == 0 || isLaneList_) ? startMainPos_ : 0, .endMainPos = (cachedCount_ == 0 || isLaneList_) ? endMainPos_ : mainSize_, .listMainSize = mainSize_, diff --git a/frameworks/core/components_v2/list/render_list_item_group.cpp b/frameworks/core/components_v2/list/render_list_item_group.cpp index 9a5fa0becfc..176d29cdd13 100644 --- a/frameworks/core/components_v2/list/render_list_item_group.cpp +++ b/frameworks/core/components_v2/list/render_list_item_group.cpp @@ -120,10 +120,10 @@ void RenderListItemGroup::Update(const RefPtr& component) void RenderListItemGroup::RecycleStartCacheItems() { double curMainPosForRecycle = startIndexOffset_; - int32_t curIndex = startIndex_; + size_t curIndex = startIndex_; for (auto it = items_.begin(); it != items_.end() && currStartCacheCount_ > startCacheCount_; curIndex += lanes_) { double rowSize = 0; - for (int32_t i = 0; i < lanes_ && it != items_.end(); i++) { + for (size_t i = 0; i < lanes_ && it != items_.end(); i++) { const auto& child = *(it); double childSize = GetMainSize(child->GetLayoutSize()); rowSize = std::max(childSize, rowSize); @@ -141,7 +141,7 @@ void RenderListItemGroup::RecycleStartCacheItems() double RenderListItemGroup::LayoutALine(std::list>::iterator& it) { double rowSize = 0; - for (int32_t i = 0; i < lanes_; i++) { + for (size_t i = 0; i < lanes_; i++) { RefPtr child; if (it == items_.end()) { if (i == 0) { @@ -171,7 +171,7 @@ double RenderListItemGroup::LayoutOrRecycleCurrentItems() for (auto it = items_.begin(); it != items_.end(); curIndex += lanes_) { if (GreatNotEqual(curMainPos, endMainPos_) && currEndCacheCount_ >= endCacheCount_) { - for (int32_t i = 0; i < lanes_ && it != items_.end(); i++) { + for (size_t i = 0; i < lanes_ && it != items_.end(); i++) { // Recycle list items out of view port RecycleListItem(curIndex + i); it = items_.erase(it); @@ -199,7 +199,7 @@ void RenderListItemGroup::RequestNewItemsAtEnd(double& curMainPos) break; } double rowSize = 0; - int32_t idx = 0; + size_t idx = 0; for (; idx < lanes_; idx++) { auto child = RequestListItem(newIndex + idx, false); if (!child) { @@ -232,8 +232,15 @@ void RenderListItemGroup::RequestNewItemsAtStart() break; } double rowSize = 0; - int32_t idx = 0; - for (; idx < lanes_ && startIndex_ - idx > 0; idx++) { + size_t count = lanes_; + if (startIndex_ >= TotalCount()) { + count = startIndex_ % lanes_; + if (count == 0) { + count = lanes_; + } + } + size_t idx = 0; + for (; idx < count && startIndex_ - idx > 0; idx++) { auto child = RequestListItem(startIndex_ - idx - 1, true); if (!child) { break; @@ -282,7 +289,7 @@ void RenderListItemGroup::SetItemsPostion() if (header_) { double crossOffset = CalculateCrossOffset(crossSize, GetCrossSize(header_->GetLayoutSize())); double headerSize = GetMainSize(header_->GetLayoutSize()); - if (stickHeader_ && Negative(forwardReferencePos_)) { + if (stickyHeader_ && Negative(forwardReferencePos_)) { double headerPos = backwardReferencePos_ - headerSize; if (footer_) { headerPos -= GetMainSize(footer_->GetLayoutSize()); @@ -297,7 +304,7 @@ void RenderListItemGroup::SetItemsPostion() double laneCrossSize = GetCrossSize(GetLayoutSize()) / lanes_; for (auto it = items_.begin(); it != items_.end();) { double rowSize = 0; - for (int32_t i = 0; i < lanes_ && it != items_.end(); i++) { + for (size_t i = 0; i < lanes_ && it != items_.end(); i++) { auto child = *(it++); double childSize = GetMainSize(child->GetLayoutSize()); rowSize = std::max(childSize, rowSize); @@ -313,7 +320,7 @@ void RenderListItemGroup::SetItemsPostion() endIndexOffset_ = layoutPos; if (footer_) { double crossOffset = CalculateCrossOffset(crossSize, GetCrossSize(footer_->GetLayoutSize())); - if (stickFooter_ && GreatNotEqual(backwardReferencePos_, listMainSize_)) { + if (stickyFooter_ && GreatNotEqual(backwardReferencePos_, listMainSize_)) { double footerSize = GetMainSize(footer_->GetLayoutSize()); double footerPos = forwardReferencePos_; if (header_) { @@ -335,16 +342,16 @@ void RenderListItemGroup::PerformLayout() RequestNewItemsAtStart(); bool reachEnd = (startIndex_ + items_.size() >= TotalCount()); - if ((stickHeader_ || startIndex_ == 0) && !header_) { + if ((stickyHeader_ || startIndex_ == 0) && !header_) { RequestListItemHeader(); - } else if (!stickHeader_ && startIndex_ > 0 && header_) { + } else if (!stickyHeader_ && startIndex_ > 0 && header_) { RemoveChild(header_); header_ = nullptr; } - if ((stickFooter_ || reachEnd) && !footer_) { + if ((stickyFooter_ || reachEnd) && !footer_) { RequestListItemFooter(); - } else if (!stickFooter_ && !reachEnd && footer_) { + } else if (!stickyFooter_ && !reachEnd && footer_) { RemoveChild(footer_); footer_ = nullptr; } @@ -396,12 +403,12 @@ void RenderListItemGroup::SetItemGroupLayoutParam(const ListItemLayoutParam &par listMainSize_ = param.listMainSize; vertical_ = param.isVertical; align_ = param.align; - stickHeader_ = static_cast(param.sticky & StickyStyle::HEADER); - stickFooter_ = static_cast(param.sticky & StickyStyle::FOOTER); - lanes_ = param.lanes; + stickyHeader_ = static_cast(param.sticky & StickyStyle::HEADER); + stickyFooter_ = static_cast(param.sticky & StickyStyle::FOOTER); + lanes_ = static_cast(param.lanes); if (!isInitialized_) { isInitialized_ = true; - startIndex_ = param.forwardLayout ? 0 : static_cast(TotalCount()); + startIndex_ = param.forwardLayout ? 0 : TotalCount(); startIndexOffset_ = param.referencePos; forwardReferencePos_ = param.referencePos; backwardReferencePos_ = param.referencePos; @@ -422,7 +429,7 @@ void RenderListItemGroup::SetChainOffset(double offset) return; } - if (header_ && stickHeader_) { + if (header_ && stickyHeader_) { double layoutPos = forwardLayout_ ? (startIndexOffset_ - forwardReferencePos_) : spaceWidth_; double crossOffset = GetCrossAxis(header_->GetPosition()); double headerSize = GetMainSize(header_->GetLayoutSize()); @@ -438,7 +445,7 @@ void RenderListItemGroup::SetChainOffset(double offset) header_->SetPosition(offset); } } - if (footer_ && stickFooter_) { + if (footer_ && stickyFooter_) { double crossOffset = GetCrossAxis(footer_->GetPosition()); if (GreatNotEqual(backwardReferencePos_ + offset, listMainSize_)) { double footerSize = GetMainSize(footer_->GetLayoutSize()); diff --git a/frameworks/core/components_v2/list/render_list_item_group.h b/frameworks/core/components_v2/list/render_list_item_group.h index fd1b5197bef..af4a995043a 100644 --- a/frameworks/core/components_v2/list/render_list_item_group.h +++ b/frameworks/core/components_v2/list/render_list_item_group.h @@ -102,7 +102,7 @@ public: return vertical_; } - int32_t GetStartIndex() const + size_t GetStartIndex() const { return startIndex_; } @@ -164,8 +164,8 @@ private: // param for frontend Dimension listSpace_; - bool stickHeader_ = false; - bool stickFooter_ = false; + bool stickyHeader_ = false; + bool stickyFooter_ = false; WeakPtr renderBox_; // layout param @@ -177,9 +177,9 @@ private: double listMainSize_ = 0.0; size_t startCacheCount_ = 0; size_t endCacheCount_ = 0; - int32_t lanes_ = 1; + size_t lanes_ = 1; bool vertical_ = true; - ListItemAlign align_; + ListItemAlign align_ = V2::ListItemAlign::START; // layout status bool isInitialized_ = false; diff --git a/frameworks/core/components_v2/list/rosen_render_list.cpp b/frameworks/core/components_v2/list/rosen_render_list.cpp index 3010f97a332..95d1613f445 100644 --- a/frameworks/core/components_v2/list/rosen_render_list.cpp +++ b/frameworks/core/components_v2/list/rosen_render_list.cpp @@ -74,24 +74,31 @@ void RosenRenderList::Paint(RenderContext& context, const Offset& offset) paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(strokeWidth); bool isFirstIndex = (startIndex_ == 0); + double lastMainAxis = INFINITY; for (const auto& child : items_) { if (child == selectedItem_) { continue; } + double mainAxis = GetMainAxis(child->GetPosition()); if (isFirstIndex) { + lastMainAxis = mainAxis; isFirstIndex = false; continue; } - double mainAxis = GetMainAxis(child->GetPosition()); if (GreatOrEqual(mainAxis - topOffset, mainSize)) { break; } if (LessOrEqual(mainAxis - bottomOffset, 0.0)) { continue; } + if (NearEqual(lastMainAxis, mainAxis)) { + continue; + } + lastMainAxis = mainAxis; + mainAxis -= halfSpaceWidth; if (vertical_) { canvas->drawLine(startCrossAxis, mainAxis, endCrossAxis, mainAxis, paint); diff --git a/frameworks/core/components_v2/list/rosen_render_list_item_group.cpp b/frameworks/core/components_v2/list/rosen_render_list_item_group.cpp index a19d35acece..eb90b54f2cc 100644 --- a/frameworks/core/components_v2/list/rosen_render_list_item_group.cpp +++ b/frameworks/core/components_v2/list/rosen_render_list_item_group.cpp @@ -50,6 +50,7 @@ void RosenRenderListItemGroup::PaintDivider(RenderContext& context) paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(strokeWidth); bool isFirstItem = (GetStartIndex() == 0); + double lastMainAxis = INFINITY; for (const auto& child : GetItems()) { double mainAxis = GetMainAxis(child->GetPosition()); @@ -57,12 +58,18 @@ void RosenRenderListItemGroup::PaintDivider(RenderContext& context) break; } if (isFirstItem) { + lastMainAxis = mainAxis; isFirstItem = false; continue; } if (LessOrEqual(mainAxis - bottomOffset, 0.0)) { continue; } + if (NearEqual(mainAxis, lastMainAxis)) { + continue; + } + lastMainAxis = mainAxis; + mainAxis -= halfSpaceWidth; if (IsVertical()) { canvas->drawLine(startCrossAxis, mainAxis, endCrossAxis, mainAxis, paint); From ae7f9298e185f295e65f1519066ae5815fd62f95 Mon Sep 17 00:00:00 2001 From: cheng-feiwang Date: Sat, 3 Sep 2022 12:30:51 +0800 Subject: [PATCH 29/35] [ng]image support interpolation,objectRepeat,sourceSize,onError,onComplete Signed-off-by: cheng-feiwang Change-Id: Ie0a6a51d445a30536aef2cbcee06ad04d914eceb --- .../declarative_frontend/jsview/js_image.cpp | 27 ++++++++ .../core/components/image/image_event.h | 2 + .../adapter/flutter_image_provider.cpp | 6 +- .../image_provider/image_loading_context.cpp | 31 +++++++-- .../image_provider/image_loading_context.h | 6 +- .../image_provider/image_object.cpp | 6 +- .../image_provider/image_object.h | 4 +- .../image_provider/image_provider.h | 2 +- .../image_provider/image_state_manager.cpp | 1 + .../pattern/image/image_event_hub.h | 66 +++++++++++++++++++ .../pattern/image/image_layout_algorithm.cpp | 3 +- .../pattern/image/image_layout_property.h | 14 +++- .../pattern/image/image_paint_method.h | 12 +++- .../pattern/image/image_pattern.cpp | 30 ++++++++- .../pattern/image/image_pattern.h | 6 ++ .../pattern/image/image_render_property.h | 21 ++++-- .../pattern/image/image_view.cpp | 28 ++++++++ .../components_ng/pattern/image/image_view.h | 7 ++ .../render/adapter/skia_canvas_image.cpp | 2 +- .../components_ng/render/image_painter.cpp | 62 ++++++++++++++++- .../core/components_ng/render/image_painter.h | 6 +- 21 files changed, 310 insertions(+), 32 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/image/image_event_hub.h diff --git a/frameworks/bridge/declarative_frontend/jsview/js_image.cpp b/frameworks/bridge/declarative_frontend/jsview/js_image.cpp index b1d0728f4d7..8d6fb53ecaa 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_image.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_image.cpp @@ -242,6 +242,18 @@ void JSImage::OnComplete(const JSCallbackInfo& args) if (args[0]->IsFunction()) { auto jsLoadSuccFunc = AceType::MakeRefPtr>( JSRef::Cast(args[0]), LoadImageSuccEventToJSValue); + + if (Container::IsCurrentUseNewPipeline()) { + auto onComplete = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadSuccFunc)]( + const LoadImageSuccessEvent& info) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("Image.onComplete"); + func->Execute(info); + }; + NG::ImageView::SetOnComplete(std::move(onComplete)); + return; + } + auto image = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); image->SetLoadSuccessEvent(EventMarker( [execCtx = args.GetExecutionContext(), func = std::move(jsLoadSuccFunc)](const BaseEventInfo* info) { @@ -261,6 +273,15 @@ void JSImage::OnError(const JSCallbackInfo& args) if (args[0]->IsFunction()) { auto jsLoadFailFunc = AceType::MakeRefPtr>( JSRef::Cast(args[0]), LoadImageFailEventToJSValue); + if (Container::IsCurrentUseNewPipeline()) { + auto onError = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadFailFunc)](const LoadImageFailEvent& info) { + JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); + ACE_SCORING_EVENT("Image.onError"); + func->Execute(info); + }; + NG::ImageView::SetOnError(std::move(onError)); + return; + } auto image = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); image->SetLoadFailEvent(EventMarker( [execCtx = args.GetExecutionContext(), func = std::move(jsLoadFailFunc)](const BaseEventInfo* info) { @@ -334,6 +355,11 @@ void JSImage::JsBorderRadius(const JSCallbackInfo& info) void JSImage::SetSourceSize(const JSCallbackInfo& info) { + if (Container::IsCurrentUseNewPipeline()) { + std::pair sourceSize = JSViewAbstract::ParseSize(info); + NG::ImageView::SetImageSourceSize(sourceSize); + return; + } auto image = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); image->SetImageSourceSize(JSViewAbstract::ParseSize(info)); } @@ -369,6 +395,7 @@ void JSImage::SetImageInterpolation(int32_t imageInterpolation) void JSImage::SetImageRepeat(int32_t imageRepeat) { + SET_PROP_FOR_NG(ImageRepeat, ImageRepeat, imageRepeat); auto image = AceType::DynamicCast(ViewStackProcessor::GetInstance()->GetMainComponent()); image->SetImageRepeat(static_cast(imageRepeat)); } diff --git a/frameworks/core/components/image/image_event.h b/frameworks/core/components/image/image_event.h index 2b1769e03cf..799e48086f1 100644 --- a/frameworks/core/components/image/image_event.h +++ b/frameworks/core/components/image/image_event.h @@ -16,6 +16,8 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_IMAGE_IMAGE_EVENT_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_IMAGE_IMAGE_EVENT_H +#include "core/event/ace_events.h" + namespace OHOS::Ace { class ACE_EXPORT LoadImageSuccessEvent : public BaseEventInfo { diff --git a/frameworks/core/components_ng/image_provider/adapter/flutter_image_provider.cpp b/frameworks/core/components_ng/image_provider/adapter/flutter_image_provider.cpp index c7e1fffad1d..afd55412a97 100644 --- a/frameworks/core/components_ng/image_provider/adapter/flutter_image_provider.cpp +++ b/frameworks/core/components_ng/image_provider/adapter/flutter_image_provider.cpp @@ -152,9 +152,9 @@ RefPtr ImageEncodedInfo::CreateImageEncodedInfo(const RefPtr& imageObjWp, const LoadCallbacks& loadCallbacks, - const SizeF& resizeTarget, const RefPtr& renderTaskHolder) + const SizeF& resizeTarget, const RefPtr& renderTaskHolder, bool forceResize) { - auto canvasImageMakingTask = [objWp = imageObjWp, loadCallbacks, resizeTarget, renderTaskHolder] { + auto canvasImageMakingTask = [objWp = imageObjWp, loadCallbacks, resizeTarget, renderTaskHolder, forceResize] { auto obj = objWp.Upgrade(); CHECK_NULL_VOID(obj); CHECK_NULL_VOID(renderTaskHolder); @@ -203,7 +203,7 @@ void ImageProvider::MakeCanvasImage(const WeakPtr& imageObjWp, cons return; } // upload to gpu for render - auto image = ResizeSkImage(rawImage, obj->GetSourceInfo().GetSrc(), resizeTarget, false); + auto image = ResizeSkImage(rawImage, obj->GetSourceInfo().GetSrc(), resizeTarget, forceResize); flutter::SkiaGPUObject skiaGpuObjSkImage({ image, flutterRenderTaskHolder->unrefQueue }); #ifdef NG_BUILD auto canvasImage = CanvasImage::Create(); diff --git a/frameworks/core/components_ng/image_provider/image_loading_context.cpp b/frameworks/core/components_ng/image_provider/image_loading_context.cpp index be57a3046e4..68e2b4b9494 100644 --- a/frameworks/core/components_ng/image_provider/image_loading_context.cpp +++ b/frameworks/core/components_ng/image_provider/image_loading_context.cpp @@ -114,7 +114,8 @@ EnterStateTask ImageLoadingContext::CreateOnMakeCanvasImageTask() auto resizeTarget = imageLoadingContext->GetImageSize(); if (imageLoadingContext->needResize_) { resizeTarget = ImageLoadingContext::CalculateResizeTarget(imageLoadingContext->srcRect_.GetSize(), - imageLoadingContext->dstRect_.GetSize(), imageLoadingContext->GetImageSize()); + imageLoadingContext->dstRect_.GetSize(), + imageLoadingContext->GetSourceSize().value_or(imageLoadingContext->GetImageSize())); } // step3: do second [ApplyImageFit] to calculate real srcRect used for paint based on resized image size @@ -122,7 +123,8 @@ EnterStateTask ImageLoadingContext::CreateOnMakeCanvasImageTask() imageLoadingContext->srcRect_, imageLoadingContext->dstRect_); // step4: [MakeCanvasImage] according to [resizeTarget] - imageLoadingContext->imageObj_->MakeCanvasImage(imageLoadingContext->loadCallbacks_, resizeTarget); + imageLoadingContext->imageObj_->MakeCanvasImage(imageLoadingContext->loadCallbacks_, resizeTarget, + imageLoadingContext->GetSourceSize().has_value()); }; return task; } @@ -229,17 +231,19 @@ void ImageLoadingContext::LoadImageData() stateManager_->HandleCommand(ImageLoadingCommand::LOAD_DATA); } -void ImageLoadingContext::MakeCanvasImage(const SizeF& dstSize, bool needResize, ImageFit imageFit) +void ImageLoadingContext::MakeCanvasImage(const SizeF& dstSize, bool needResize, ImageFit imageFit, + const std::optional>& sourceSize) { // Because calling of this interface does not guarantee the excution of [MakeCanvasImage], so in order to avoid // updating params before they are not actually used, caputure the params in a function. This funtion will only run // when it actually do [MakeCanvasImage], i.e. doing the update in [OnMakeCanvasImageTask] - updateParamsCallback_ = [wp = WeakClaim(this), dstSize, needResize, imageFit]() { + updateParamsCallback_ = [wp = WeakClaim(this), dstSize, needResize, imageFit, sourceSize]() { auto loadingCtx = wp.Upgrade(); CHECK_NULL_VOID(loadingCtx); loadingCtx->dstSize_ = dstSize; loadingCtx->imageFit_ = imageFit; loadingCtx->needResize_ = needResize; + loadingCtx->SetSourceSize(sourceSize); }; // send command to [StateManager] and waiting the callback from it to determine next step stateManager_->HandleCommand(ImageLoadingCommand::MAKE_CANVAS_IMAGE); @@ -280,4 +284,21 @@ bool ImageLoadingContext::GetNeedResize() const return needResize_; } -} // namespace OHOS::Ace::NG \ No newline at end of file +void ImageLoadingContext::SetSourceSize(const std::optional>& sourceSize) +{ + if (sourceSize.has_value()) { + sourceSizePtr_ = std::make_unique>(sourceSize.value()); + } +} + +std::optional ImageLoadingContext::GetSourceSize() const +{ + if (sourceSizePtr_ == nullptr) { + return std::nullopt; + } + return std::optional(SizeF( + static_cast(sourceSizePtr_->first.ConvertToPx()), + static_cast(sourceSizePtr_->second.ConvertToPx()))); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/image_provider/image_loading_context.h b/frameworks/core/components_ng/image_provider/image_loading_context.h index 2445c55995b..5cb5af1b09f 100644 --- a/frameworks/core/components_ng/image_provider/image_loading_context.h +++ b/frameworks/core/components_ng/image_provider/image_loading_context.h @@ -41,7 +41,8 @@ public: /* interfaces to drive image loading */ void LoadImageData(); - void MakeCanvasImage(const SizeF& dstSize, bool needResize, ImageFit imageFit = ImageFit::COVER); + void MakeCanvasImage(const SizeF& dstSize, bool needResize, ImageFit imageFit = ImageFit::COVER, + const std::optional>& sourceSize = std::nullopt); /* interfaces to get properties */ SizeF GetImageSize() const; @@ -52,10 +53,12 @@ public: const ImageSourceInfo& GetSourceInfo() const; const SizeF& GetDstSize() const; bool GetNeedResize() const; + std::optional GetSourceSize() const; /* interfaces to set properties */ void SetImageFit(ImageFit imageFit); void SetNeedResize(bool needResize); + void SetSourceSize(const std::optional>& sourceSize = std::nullopt); private: #define DEFINE_SET_NOTIFY_TASK(loadResult, loadResultNotifierName) \ @@ -102,6 +105,7 @@ private: SizeF dstSize_; bool needResize_ = true; ImageFit imageFit_ = ImageFit::COVER; + std::unique_ptr> sourceSizePtr_ = nullptr; std::function updateParamsCallback_ = nullptr; }; diff --git a/frameworks/core/components_ng/image_provider/image_object.cpp b/frameworks/core/components_ng/image_provider/image_object.cpp index 9a6180a8eaf..f26364de664 100644 --- a/frameworks/core/components_ng/image_provider/image_object.cpp +++ b/frameworks/core/components_ng/image_provider/image_object.cpp @@ -70,11 +70,11 @@ void ImageObject::ClearData() data_ = nullptr; } -void StaticImageObject::MakeCanvasImage(const LoadCallbacks& loadCallbacks, const SizeF& resizeTarget) +void StaticImageObject::MakeCanvasImage(const LoadCallbacks& loadCallbacks, const SizeF& resizeTarget, bool forceResize) { auto renderTaskHolder = ImageProvider::CreateRenderTaskHolder(); CHECK_NULL_VOID(renderTaskHolder); - ImageProvider::MakeCanvasImage(WeakClaim(this), loadCallbacks, resizeTarget, renderTaskHolder); + ImageProvider::MakeCanvasImage(WeakClaim(this), loadCallbacks, resizeTarget, renderTaskHolder, forceResize); } -} // namespace OHOS::Ace::NG \ No newline at end of file +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/image_provider/image_object.h b/frameworks/core/components_ng/image_provider/image_object.h index 83607b9132f..5d428a8422a 100644 --- a/frameworks/core/components_ng/image_provider/image_object.h +++ b/frameworks/core/components_ng/image_provider/image_object.h @@ -47,7 +47,7 @@ public: void SetData(const RefPtr& data); void ClearData(); - virtual void MakeCanvasImage(const LoadCallbacks& loadCallbacks, const SizeF& resizeTarget) = 0; + virtual void MakeCanvasImage(const LoadCallbacks& loadCallbacks, const SizeF& resizeTarget, bool forceResize) = 0; protected: ImageSourceInfo sourceInfo_; @@ -67,7 +67,7 @@ public: {} ~StaticImageObject() override = default; - void MakeCanvasImage(const LoadCallbacks& loadCallbacks, const SizeF& resizeTarget) override; + void MakeCanvasImage(const LoadCallbacks& loadCallbacks, const SizeF& resizeTarget, bool forceResize) override; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/image_provider/image_provider.h b/frameworks/core/components_ng/image_provider/image_provider.h index f4ad72d32bb..5d471059f6c 100644 --- a/frameworks/core/components_ng/image_provider/image_provider.h +++ b/frameworks/core/components_ng/image_provider/image_provider.h @@ -107,7 +107,7 @@ public: static RefPtr CreateRenderTaskHolder(); static void CreateImageObject(const ImageSourceInfo& sourceInfo, const LoadCallbacks& loadCallbacks); static void MakeCanvasImage(const WeakPtr& imageObjWp, const LoadCallbacks& loadCallbacks, - const SizeF& resizeTarget, const RefPtr& renderTaskHolder); + const SizeF& resizeTarget, const RefPtr& renderTaskHolder, bool forceResize = false); static void UploadImageToGPUForRender(const RefPtr& canvasImage, std::function)>&& callback, const RefPtr& renderTaskHolder); diff --git a/frameworks/core/components_ng/image_provider/image_state_manager.cpp b/frameworks/core/components_ng/image_provider/image_state_manager.cpp index 522864ae6d7..a00d3427bc7 100644 --- a/frameworks/core/components_ng/image_provider/image_state_manager.cpp +++ b/frameworks/core/components_ng/image_provider/image_state_manager.cpp @@ -74,6 +74,7 @@ void ImageStateManager::HandleCommandByUnloadedState(ImageLoadingCommand command void ImageStateManager::HandleCommandByDataLoadingState(ImageLoadingCommand command) { switch (command) { + CASE_OF_STATE_TRANSITION(MAKE_CANVAS_IMAGE_FAIL, LOAD_FAIL, LoadFail); CASE_OF_STATE_TRANSITION(LOAD_DATA_SUCCESS, DATA_READY, DataReady); CASE_OF_STATE_TRANSITION(LOAD_DATA_FAIL, LOAD_FAIL, LoadFail); DEFAULT_CASE_OF_STATE_TRANSITION(); diff --git a/frameworks/core/components_ng/pattern/image/image_event_hub.h b/frameworks/core/components_ng/pattern/image/image_event_hub.h new file mode 100644 index 00000000000..f12300eb48a --- /dev/null +++ b/frameworks/core/components_ng/pattern/image/image_event_hub.h @@ -0,0 +1,66 @@ +/* + * 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_PATTERNS_IMAGE_IMAGE_EVENT_HUB_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_IMAGE_IMAGE_EVENT_HUB_H + +#include "base/memory/ace_type.h" +#include "core/components/image/image_event.h" +#include "core/components_ng/event/event_hub.h" + +namespace OHOS::Ace::NG { + +using CompleteEvent = std::function; +using ErrorEvent = std::function; + +class ImageEventHub : public EventHub { + DECLARE_ACE_TYPE(ImageEventHub, EventHub) + +public: + ImageEventHub() = default; + ~ImageEventHub() override = default; + + void SetOnError(ErrorEvent&& errorEvent) + { + errorEvent_ = std::move(errorEvent); + } + + void FireErrorEvent(const LoadImageFailEvent& info) const + { + if (errorEvent_) { + errorEvent_(info); + } + } + + void SetOnComplete(CompleteEvent&& completeEvent) + { + completeEvent_ = std::move(completeEvent); + } + + void FireCompleteEvent(const LoadImageSuccessEvent& info) const + { + if (completeEvent_) { + completeEvent_(info); + } + } + +private: + ErrorEvent errorEvent_; + CompleteEvent completeEvent_; +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_IMAGE_IMAGE_EVENT_HUB_H diff --git a/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp index 028d23a5798..98d1fad0e09 100644 --- a/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp @@ -79,6 +79,7 @@ void ImageLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) const auto& dstSize = layoutWrapper->GetGeometryNode()->GetContentSize(); bool incomingNeedResize = imageLayoutProperty->GetAutoResize().value_or(true); ImageFit incomingImageFit = imageLayoutProperty->GetImageFit().value_or(ImageFit::COVER); + const std::optional>& sourceSize = imageLayoutProperty->GetSourceSize(); bool needMakeCanvasImage = incomingNeedResize != loadingCtx_->GetNeedResize() || dstSize != loadingCtx_->GetDstSize() || incomingImageFit != loadingCtx_->GetImageFit(); // do [MakeCanvasImage] only when: @@ -86,7 +87,7 @@ void ImageLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) // 2. component size (aka [dstSize] here) changes. // 3. [ImageFit] changes if (needMakeCanvasImage) { - loadingCtx_->MakeCanvasImage(dstSize, incomingNeedResize, incomingImageFit); + loadingCtx_->MakeCanvasImage(dstSize, incomingNeedResize, incomingImageFit, sourceSize); } } diff --git a/frameworks/core/components_ng/pattern/image/image_layout_property.h b/frameworks/core/components_ng/pattern/image/image_layout_property.h index 37f61106e4a..95e3be5ee21 100644 --- a/frameworks/core/components_ng/pattern/image/image_layout_property.h +++ b/frameworks/core/components_ng/pattern/image/image_layout_property.h @@ -22,6 +22,12 @@ namespace OHOS::Ace::NG { class ImagePattern; +using DimensionPair = std::pair; +struct ImageSizeStyle { + ACE_DEFINE_PROPERTY_GROUP_ITEM(AutoResize, bool); + ACE_DEFINE_PROPERTY_GROUP_ITEM(SourceSize, DimensionPair); +}; + class ACE_EXPORT ImageLayoutProperty : public LayoutProperty { DECLARE_ACE_TYPE(ImageLayoutProperty, LayoutProperty); @@ -36,7 +42,7 @@ public: value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); value->propImageSourceInfo_ = CloneImageSourceInfo(); value->propImageFit_ = CloneImageFit(); - value->propAutoResize_ = CloneAutoResize(); + value->propImageSizeStyle_ = CloneImageSizeStyle(); return value; } @@ -45,12 +51,14 @@ public: LayoutProperty::Reset(); ResetImageSourceInfo(); ResetImageFit(); - ResetAutoResize(); + ResetImageSizeStyle(); } ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ImageFit, ImageFit, PROPERTY_UPDATE_LAYOUT); ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ImageSourceInfo, ImageSourceInfo, PROPERTY_UPDATE_MEASURE); - ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(AutoResize, bool, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_GROUP(ImageSizeStyle, ImageSizeStyle); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImageSizeStyle, AutoResize, bool, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImageSizeStyle, SourceSize, DimensionPair, PROPERTY_UPDATE_LAYOUT); private: ACE_DISALLOW_COPY_AND_MOVE(ImageLayoutProperty); diff --git a/frameworks/core/components_ng/pattern/image/image_paint_method.h b/frameworks/core/components_ng/pattern/image/image_paint_method.h index d2a5e5cfb70..55b790e4523 100644 --- a/frameworks/core/components_ng/pattern/image/image_paint_method.h +++ b/frameworks/core/components_ng/pattern/image/image_paint_method.h @@ -36,11 +36,17 @@ public: CanvasDrawFunction GetContentDrawFunction(PaintWrapper* paintWrapper) override { CHECK_NULL_RETURN(canvasImage_, nullptr); - auto offset = paintWrapper->GetContentOffset(); + auto contentSize = paintWrapper->GetContentSize(); ImagePainter imagePainter(canvasImage_); - return [imagePainter, offset, ImagePaintConfig = imagePaintConfig_]( - RSCanvas& canvas) { imagePainter.DrawImage(canvas, offset, ImagePaintConfig); }; + return [imagePainter, offset, ImagePaintConfig = imagePaintConfig_, contentSize](RSCanvas& canvas) { + if (ImagePaintConfig.imageRepeat_ == ImageRepeat::NOREPEAT) { + imagePainter.DrawImage(canvas, offset, ImagePaintConfig); + return; + } + imagePainter.DrawImageWithRepeat(canvas, ImagePaintConfig, + RectF(offset.GetX(), offset.GetY(), contentSize.Width(), contentSize.Height())); + }; } private: diff --git a/frameworks/core/components_ng/pattern/image/image_pattern.cpp b/frameworks/core/components_ng/pattern/image/image_pattern.cpp index c588ccd5ce5..bd33d31fa08 100644 --- a/frameworks/core/components_ng/pattern/image/image_pattern.cpp +++ b/frameworks/core/components_ng/pattern/image/image_pattern.cpp @@ -85,6 +85,15 @@ void ImagePattern::OnImageLoadSuccess() { auto host = GetHost(); CHECK_NULL_VOID(host); + const auto& geometryNode = host->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto imageEventHub = GetEventHub(); + CHECK_NULL_VOID(imageEventHub); + LoadImageSuccessEvent loadImageSuccessEvent_( + loadingCtx_->GetImageSize().Width(), loadingCtx_->GetImageSize().Height(), + geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height(), 1); + imageEventHub->FireCompleteEvent(std::move(loadImageSuccessEvent_)); + lastCanvasImage_ = loadingCtx_->GetCanvasImage(); lastSrcRect_ = loadingCtx_->GetSrcRect(); lastDstRect_ = loadingCtx_->GetDstRect(); @@ -107,6 +116,14 @@ void ImagePattern::OnImageDataReady() auto host = GetHost(); CHECK_NULL_VOID(host); const auto& geometryNode = host->GetGeometryNode(); + CHECK_NULL_VOID(geometryNode); + auto imageEventHub = GetEventHub(); + CHECK_NULL_VOID(imageEventHub); + LoadImageSuccessEvent loadImageSuccessEvent_( + loadingCtx_->GetImageSize().Width(), loadingCtx_->GetImageSize().Height(), + geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height(), 0); + imageEventHub->FireCompleteEvent(std::move(loadImageSuccessEvent_)); + if (!geometryNode->GetContent()) { host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); return; @@ -116,7 +133,15 @@ void ImagePattern::OnImageDataReady() void ImagePattern::OnImageLoadFail() { - // TODO: fire load fail event + auto host = GetHost(); + CHECK_NULL_VOID(host); + const auto& geometryNode = host->GetGeometryNode(); + auto imageEventHub = GetEventHub(); + CHECK_NULL_VOID(imageEventHub); + LoadImageFailEvent loadImageFailEvent_( + geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height(), ""); + // TODO: remove errorMsg in fail event + imageEventHub->FireErrorEvent(std::move(loadImageFailEvent_)); } RefPtr ImagePattern::CreateNodePaintMethod() @@ -126,6 +151,9 @@ RefPtr ImagePattern::CreateNodePaintMethod() CHECK_NULL_RETURN(imageRenderProperty, nullptr); ImagePaintConfig imagePaintConfig(lastSrcRect_, lastDstRect_); imagePaintConfig.renderMode_ = imageRenderProperty->GetImageRenderMode().value_or(ImageRenderMode::ORIGINAL); + imagePaintConfig.imageInterpolation_ = + imageRenderProperty->GetImageInterpolation().value_or(ImageInterpolation::NONE); + imagePaintConfig.imageRepeat_ = imageRenderProperty->GetImageRepeat().value_or(ImageRepeat::NOREPEAT); return MakeRefPtr(lastCanvasImage_, imagePaintConfig); } diff --git a/frameworks/core/components_ng/pattern/image/image_pattern.h b/frameworks/core/components_ng/pattern/image/image_pattern.h index 7842d0518f2..3331ebab2d9 100644 --- a/frameworks/core/components_ng/pattern/image/image_pattern.h +++ b/frameworks/core/components_ng/pattern/image/image_pattern.h @@ -17,6 +17,7 @@ #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_IMAGE_IMAGE_PATTERN_H #include "base/memory/referenced.h" +#include "core/components_ng/pattern/image/image_event_hub.h" #include "core/components_ng/pattern/image/image_layout_algorithm.h" #include "core/components_ng/pattern/image/image_layout_property.h" #include "core/components_ng/pattern/image/image_render_property.h" @@ -50,6 +51,11 @@ public: return MakeRefPtr(loadingCtx_); } + RefPtr CreateEventHub() override + { + return MakeRefPtr(); + } + // Called on main thread to check if need rerender of the content. bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; diff --git a/frameworks/core/components_ng/pattern/image/image_render_property.h b/frameworks/core/components_ng/pattern/image/image_render_property.h index bf520bdb896..6e7a788466e 100644 --- a/frameworks/core/components_ng/pattern/image/image_render_property.h +++ b/frameworks/core/components_ng/pattern/image/image_render_property.h @@ -18,8 +18,16 @@ #include "core/components/common/layout/constants.h" #include "core/components_ng/render/paint_property.h" +#include "core/image/image_source_info.h" namespace OHOS::Ace::NG { + +struct ImagePaintStyle { + ACE_DEFINE_PROPERTY_GROUP_ITEM(ImageRenderMode, ImageRenderMode); + ACE_DEFINE_PROPERTY_GROUP_ITEM(ImageInterpolation, ImageInterpolation); + ACE_DEFINE_PROPERTY_GROUP_ITEM(ImageRepeat, ImageRepeat); +}; + // PaintProperty are used to set render properties. class ImageRenderProperty : public PaintProperty { DECLARE_ACE_TYPE(ImageRenderProperty, PaintProperty) @@ -32,19 +40,20 @@ public: { auto renderProperty = MakeRefPtr(); renderProperty->UpdatePaintProperty(this); - renderProperty->propImageRenderMode_ = CloneImageRenderMode(); - renderProperty->propImageInterpolation_ = CloneImageInterpolation(); + renderProperty->propImagePaintStyle_ = CloneImagePaintStyle(); return renderProperty; } void Reset() override { - propImageRenderMode_.reset(); - propImageInterpolation_.reset(); + ResetImagePaintStyle(); } - ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ImageRenderMode, ImageRenderMode, PROPERTY_UPDATE_RENDER); - ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ImageInterpolation, ImageInterpolation, PROPERTY_UPDATE_RENDER); + ACE_DEFINE_PROPERTY_GROUP(ImagePaintStyle, ImagePaintStyle); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImagePaintStyle, ImageRenderMode, ImageRenderMode, PROPERTY_UPDATE_RENDER); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP( + ImagePaintStyle, ImageInterpolation, ImageInterpolation, PROPERTY_UPDATE_RENDER); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(ImagePaintStyle, ImageRepeat, ImageRepeat, PROPERTY_UPDATE_RENDER); }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/image/image_view.cpp b/frameworks/core/components_ng/pattern/image/image_view.cpp index c3db8fa2f9f..a77ec49cf9b 100644 --- a/frameworks/core/components_ng/pattern/image/image_view.cpp +++ b/frameworks/core/components_ng/pattern/image/image_view.cpp @@ -53,4 +53,32 @@ void ImageView::SetImageInterpolation(ImageInterpolation imageInterpolation) ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageInterpolation, imageInterpolation); } +void ImageView::SetImageRepeat(ImageRepeat imageRepeat) +{ + ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageRepeat, imageRepeat); +} + +void ImageView::SetImageSourceSize(const std::pair& sourceSize) +{ + ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, SourceSize, sourceSize); +} + +void ImageView::SetOnError(ErrorEvent&& onError) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnError(std::move(onError)); +} + +void ImageView::SetOnComplete(CompleteEvent&& onComplete) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnComplete(std::move(onComplete)); +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/image/image_view.h b/frameworks/core/components_ng/pattern/image/image_view.h index 83ec0f5f21a..d9ecb674f5e 100644 --- a/frameworks/core/components_ng/pattern/image/image_view.h +++ b/frameworks/core/components_ng/pattern/image/image_view.h @@ -18,10 +18,13 @@ #include +#include "base/geometry/dimension.h" #include "base/utils/macros.h" #include "core/components/common/layout/constants.h" +#include "core/components_ng/pattern/image/image_event_hub.h" namespace OHOS::Ace::NG { + class ACE_EXPORT ImageView { public: static void Create(const std::string& src); @@ -29,6 +32,10 @@ public: static void SetAutoResize(bool autoResize); static void SetImageRenderMode(ImageRenderMode imageRenderMode); static void SetImageInterpolation(ImageInterpolation imageInterpolation); + static void SetImageRepeat(ImageRepeat imageRepeat); + static void SetImageSourceSize(const std::pair& sourceSize); + static void SetOnError(ErrorEvent&& onError); + static void SetOnComplete(CompleteEvent&& onComplete); }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/adapter/skia_canvas_image.cpp b/frameworks/core/components_ng/render/adapter/skia_canvas_image.cpp index de027f4be4b..0eb4969da78 100644 --- a/frameworks/core/components_ng/render/adapter/skia_canvas_image.cpp +++ b/frameworks/core/components_ng/render/adapter/skia_canvas_image.cpp @@ -65,4 +65,4 @@ void SkiaCanvasImage::DrawToRSCanvas(RSCanvas& canvas, const RSRect& srcRect, co canvas.DrawImageRect(rsImage, srcRect, dstRect, options); } -} // namespace OHOS::Ace::NG \ No newline at end of file +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/image_painter.cpp b/frameworks/core/components_ng/render/image_painter.cpp index e2625baebe9..3c698df88b0 100644 --- a/frameworks/core/components_ng/render/image_painter.cpp +++ b/frameworks/core/components_ng/render/image_painter.cpp @@ -96,19 +96,79 @@ void ImagePainter::DrawImage(RSCanvas& canvas, const OffsetF& offset, const Imag CHECK_NULL_VOID(canvasImage_); RSBrush brush; RSFilter filter; + filter.SetFilterQuality(RSFilter::FilterQuality(imagePaintConfig.imageInterpolation_)); if (ImageRenderMode::TEMPLATE == imagePaintConfig.renderMode_) { RSColorMatrix grayMatrix; grayMatrix.SetArray(GRAY_COLOR_MATRIX); filter.SetColorFilter(RSColorFilter::CreateMatrixColorFilter(grayMatrix)); - brush.SetFilter(filter); } canvas.Save(); canvas.Translate(offset.GetX(), offset.GetY()); + brush.SetFilter(filter); canvas.AttachBrush(brush); canvasImage_->DrawToRSCanvas(canvas, ToRSRect(imagePaintConfig.srcRect_), ToRSRect(imagePaintConfig.dstRect_)); canvas.Restore(); } +void ImagePainter::DrawImageWithRepeat( + RSCanvas& canvas, const ImagePaintConfig& imagePaintConfig, const RectF& contentRect) const +{ + if (imagePaintConfig.imageRepeat_ == ImageRepeat::NOREPEAT) { + return; + } + auto offset = contentRect.GetOffset(); + float contentWidth = contentRect.Width(); + float contentHeight = contentRect.Height(); + float singleImageWidth = imagePaintConfig.dstRect_.Width(); + float singleImageHeight = imagePaintConfig.dstRect_.Height(); + bool imageRepeatX = + imagePaintConfig.imageRepeat_ == ImageRepeat::REPEAT || imagePaintConfig.imageRepeat_ == ImageRepeat::REPEATX; + bool imageRepeatY = + imagePaintConfig.imageRepeat_ == ImageRepeat::REPEAT || imagePaintConfig.imageRepeat_ == ImageRepeat::REPEATY; + std::vector dirRepeatNum = { + static_cast(ceil(imagePaintConfig.dstRect_.GetY() / singleImageHeight)), + static_cast((ceil((contentHeight - imagePaintConfig.dstRect_.GetY()) / singleImageHeight))) - 1, + static_cast(ceil(imagePaintConfig.dstRect_.GetX() / singleImageWidth)), + imageRepeatX ? static_cast(ceil((contentWidth - imagePaintConfig.dstRect_.GetX()) / singleImageWidth)) + : 1 }; + + canvas.Save(); + auto clipRect = RSRect(offset.GetX(), offset.GetY(), + static_cast(offset.GetX() + contentWidth), + static_cast(offset.GetY() + contentHeight)); + canvas.ClipRect(clipRect, OHOS::Rosen::Drawing::ClipOp::INTERSECT); + uint32_t up = 0; + uint32_t down = 1; + uint32_t left = 2; + uint32_t right = 3; + auto DrawRepeatYTask = [this, &canvas, &imagePaintConfig, &dirRepeatNum, &singleImageHeight, &imageRepeatY]( + OffsetF offsetTempY, uint32_t dir) { + float downNum = (dir == 0) ? -1 : 1; + for (size_t j = 0; j < dirRepeatNum[dir] && imageRepeatY; j++) { + offsetTempY.SetY(static_cast(offsetTempY.GetY() + singleImageHeight * downNum)); + DrawImage(canvas, offsetTempY, imagePaintConfig); + } + }; + auto offsetTempX = offset; + // right + for (size_t i = 0; i < dirRepeatNum[right]; i++) { + DrawImage(canvas, offsetTempX, imagePaintConfig); + DrawRepeatYTask(offsetTempX, up); + DrawRepeatYTask(offsetTempX, down); + offsetTempX.SetX(static_cast(offsetTempX.GetX() + singleImageWidth)); + } + // left + offsetTempX = offset; + for (size_t i = 0; i < dirRepeatNum[left] && imageRepeatX; i++) { + offsetTempX.SetX(static_cast(offsetTempX.GetX() - singleImageWidth)); + DrawImage(canvas, offsetTempX, imagePaintConfig); + DrawRepeatYTask(offsetTempX, up); + DrawRepeatYTask(offsetTempX, down); + } + canvas.Restore(); + // TODO: repeat refactory +} + void ImagePainter::ApplyImageFit( ImageFit imageFit, const SizeF& rawPicSize, const SizeF& dstSize, RectF& srcRect, RectF& dstRect) { diff --git a/frameworks/core/components_ng/render/image_painter.h b/frameworks/core/components_ng/render/image_painter.h index e76282be431..1fe44474224 100644 --- a/frameworks/core/components_ng/render/image_painter.h +++ b/frameworks/core/components_ng/render/image_painter.h @@ -30,15 +30,19 @@ struct ImagePaintConfig { RectF srcRect_; RectF dstRect_; ImageRenderMode renderMode_ = ImageRenderMode::ORIGINAL; + ImageInterpolation imageInterpolation_ = ImageInterpolation::NONE; + ImageRepeat imageRepeat_ = ImageRepeat::NOREPEAT; }; class ImagePainter { public: - ImagePainter(const RefPtr& canvasImage) : canvasImage_(canvasImage) {} + explicit ImagePainter(const RefPtr& canvasImage) : canvasImage_(canvasImage) {} ~ImagePainter() = default; void DrawImage(RSCanvas& canvas, const OffsetF& offset, const ImagePaintConfig& imagePaintConfig) const; + void DrawImageWithRepeat(RSCanvas& canvas, const ImagePaintConfig& ImagePaintConfig, const RectF& rect) const; + static void ApplyImageFit( ImageFit imageFit, const SizeF& rawPicSize, const SizeF& dstSize, RectF& srcRect, RectF& dstRect); From 5492e3c87fd05ebc9173e1c2954cce31b9de6316 Mon Sep 17 00:00:00 2001 From: luzehui Date: Thu, 25 Aug 2022 11:06:42 +0800 Subject: [PATCH 30/35] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Flex=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E4=B8=AD=E7=9A=84LyaoutInWeight=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: luzehui Change-Id: I9f5eb7b4cbd62e02e07517488ce7fd69c723e21f --- frameworks/base/geometry/ng/size_t.h | 5 + .../jsview/js_flex_impl.cpp | 54 +- .../jsview/js_view_abstract.cpp | 7 +- .../core/components_ng/base/view_abstract.cpp | 4 + .../core/components_ng/base/view_abstract.h | 3 + .../layout/box_layout_algorithm.cpp | 1 + .../components_ng/layout/layout_property.h | 32 ++ .../core/components_ng/pattern/BUILD.gn | 2 + .../pattern/flex/flex_layout_algorithm.cpp | 517 ++++++++++++++++++ .../pattern/flex/flex_layout_algorithm.h | 107 ++++ .../pattern/flex/flex_layout_pattern.h | 36 ++ .../pattern/flex/flex_layout_property.h | 67 +++ .../pattern/flex/flex_layout_styles.h | 20 + .../components_ng/pattern/flex/flex_view.cpp | 36 ++ .../components_ng/pattern/flex/flex_view.h | 21 + 15 files changed, 908 insertions(+), 4 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp create mode 100644 frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h create mode 100644 frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h create mode 100644 frameworks/core/components_ng/pattern/flex/flex_layout_property.h create mode 100644 frameworks/core/components_ng/pattern/flex/flex_layout_styles.h create mode 100644 frameworks/core/components_ng/pattern/flex/flex_view.cpp create mode 100644 frameworks/core/components_ng/pattern/flex/flex_view.h diff --git a/frameworks/base/geometry/ng/size_t.h b/frameworks/base/geometry/ng/size_t.h index dd06b080f7d..cb970b7f7e7 100644 --- a/frameworks/base/geometry/ng/size_t.h +++ b/frameworks/base/geometry/ng/size_t.h @@ -215,6 +215,11 @@ public: } } + bool IsValid() const + { + return width_ > 0.0 && height_ > 0.0; + } + SizeT operator*(double value) const { return SizeT(width_ * value, height_ * value); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_flex_impl.cpp b/frameworks/bridge/declarative_frontend/jsview/js_flex_impl.cpp index f193122ac5f..ec95d9e9685 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_flex_impl.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_flex_impl.cpp @@ -17,6 +17,7 @@ #include "core/components/flex/flex_component_v2.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" +#include "core/components_ng/pattern/flex/flex_view.h" namespace OHOS::Ace::Framework { namespace { @@ -45,6 +46,10 @@ void JSFlexImpl::Create(const JSCallbackInfo& info) std::list> children; if (info.Length() < 1) { LOGI("No input args, use default row setting"); + if (Container::IsCurrentUseNewPipeline()) { + NG::FlexView::Create(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH); + return; + } RefPtr row = AceType::MakeRefPtr(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH, children); row->SetInspectorTag("FlexComponentV2"); @@ -54,6 +59,10 @@ void JSFlexImpl::Create(const JSCallbackInfo& info) } if (!info[0]->IsObject()) { LOGW("arg is not a object, use default row setting"); + if (Container::IsCurrentUseNewPipeline()) { + NG::FlexView::Create(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH); + return; + } RefPtr row = AceType::MakeRefPtr(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH, children); row->SetInspectorTag("FlexComponentV2"); @@ -74,6 +83,9 @@ void JSFlexImpl::Create(const JSCallbackInfo& info) } else { mainComponent = CreateFlexComponent(info); } + if (!mainComponent) { + return; + } ViewStackProcessor::GetInstance()->ClaimElementId(mainComponent); ViewStackProcessor::GetInstance()->Push(mainComponent); } @@ -82,11 +94,19 @@ RefPtr JSFlexImpl::CreateFlexComponent(const JSCallbackInfo& info { std::list> children; if (info.Length() < 1) { + if (Container::IsCurrentUseNewPipeline()) { + NG::FlexView::Create(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH); + return nullptr; + } RefPtr row = AceType::MakeRefPtr(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH, children); return row; } if (!info[0]->IsObject()) { + if (Container::IsCurrentUseNewPipeline()) { + NG::FlexView::Create(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH); + return nullptr; + } RefPtr row = AceType::MakeRefPtr(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH, children); return row; @@ -95,24 +115,46 @@ RefPtr JSFlexImpl::CreateFlexComponent(const JSCallbackInfo& info JSRef directionVal = obj->GetProperty("direction"); JSRef justifyVal = obj->GetProperty("justifyContent"); JSRef alignItemVal = obj->GetProperty("alignItems"); + if (Container::IsCurrentUseNewPipeline()) { + NG::FlexView::Create(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH); + if (directionVal->IsNumber()) { + auto direction = directionVal->ToNumber(); + if (direction >= 0 && direction <= DIRECTION_MAX_VALUE) { + NG::FlexView::Direction(static_cast(direction)); + } + } + if (justifyVal->IsNumber()) { + auto mainAlign = justifyVal->ToNumber(); + if (mainAlign >= 0 && mainAlign <= MAIN_ALIGN_MAX_VALUE) { + NG::FlexView::MainAxisAlign(static_cast(mainAlign)); + } + } + if (alignItemVal->IsNumber()) { + auto crossAlign = alignItemVal->ToNumber(); + if (crossAlign >= 0 && crossAlign <= CROSS_ALIGN_MAX_VALUE) { + NG::FlexView::CrossAxisAlign(static_cast(crossAlign)); + } + } + return nullptr; + } auto flex = AceType::MakeRefPtr(FlexDirection::ROW, FlexAlign::FLEX_START, FlexAlign::STRETCH, children); if (directionVal->IsNumber()) { auto direction = directionVal->ToNumber(); if (direction >= 0 && direction <= DIRECTION_MAX_VALUE) { - flex->SetDirection((FlexDirection)direction); + flex->SetDirection(static_cast(direction)); } } if (justifyVal->IsNumber()) { auto mainAlign = justifyVal->ToNumber(); if (mainAlign >= 0 && mainAlign <= MAIN_ALIGN_MAX_VALUE) { - flex->SetMainAxisAlign((FlexAlign)mainAlign); + flex->SetMainAxisAlign(static_cast(mainAlign)); } } if (alignItemVal->IsNumber()) { auto crossAlign = alignItemVal->ToNumber(); if (crossAlign >= 0 && crossAlign <= CROSS_ALIGN_MAX_VALUE) { - flex->SetCrossAxisAlign((FlexAlign)crossAlign); + flex->SetCrossAxisAlign(static_cast(crossAlign)); } } return flex; @@ -179,6 +221,9 @@ void JSFlexImpl::JsFlexWidth(const JSCallbackInfo& info) void JSFlexImpl::JsFlexWidth(const JSRef& jsValue) { JSViewAbstract::JsWidth(jsValue); + if (Container::IsCurrentUseNewPipeline()) { + return; + } auto box = ViewStackProcessor::GetInstance()->GetBoxComponent(); auto widthVal = box->GetWidth(); auto mainComponent = ViewStackProcessor::GetInstance()->GetMainComponent(); @@ -210,6 +255,9 @@ void JSFlexImpl::JsFlexHeight(const JSCallbackInfo& info) void JSFlexImpl::JsFlexHeight(const JSRef& jsValue) { JSViewAbstract::JsHeight(jsValue); + if (Container::IsCurrentUseNewPipeline()) { + return; + } auto box = ViewStackProcessor::GetInstance()->GetBoxComponent(); auto heightVal = box->GetHeight(); auto mainComponent = ViewStackProcessor::GetInstance()->GetMainComponent(); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 564c9c50cf8..e150abb4fe7 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -1615,8 +1615,13 @@ void JSViewAbstract::JsAlignSelf(const JSCallbackInfo& info) if (!CheckJSCallbackInfo("JsAlignSelf", info, checkList)) { return; } - auto flexItem = ViewStackProcessor::GetInstance()->GetFlexItemComponent(); auto alignVal = info[0]->ToNumber(); + if (Container::IsCurrentUseNewPipeline()) { + NG::ViewAbstract::SetAlignSelf(alignVal); + return; + } + auto flexItem = ViewStackProcessor::GetInstance()->GetFlexItemComponent(); +// auto alignVal = info[0]->ToNumber(); if (alignVal >= 0 && alignVal <= MAX_ALIGN_VALUE) { flexItem->SetAlignSelf((FlexAlign)alignVal); diff --git a/frameworks/core/components_ng/base/view_abstract.cpp b/frameworks/core/components_ng/base/view_abstract.cpp index 0c349ec7fc6..5cee38247c5 100644 --- a/frameworks/core/components_ng/base/view_abstract.cpp +++ b/frameworks/core/components_ng/base/view_abstract.cpp @@ -85,6 +85,10 @@ void ViewAbstract::SetLayoutWeight(int32_t value) ACE_UPDATE_LAYOUT_PROPERTY(LayoutProperty, LayoutWeight, static_cast(value)); } +void ViewAbstract::SetAlignSelf(int32_t value) { + ACE_UPDATE_LAYOUT_PROPERTY(LayoutProperty, AlignSelf, static_cast(value)); +} + void ViewAbstract::SetPadding(const CalcLength& value) { PaddingProperty padding; diff --git a/frameworks/core/components_ng/base/view_abstract.h b/frameworks/core/components_ng/base/view_abstract.h index e82844b4c1a..cf56c46917b 100644 --- a/frameworks/core/components_ng/base/view_abstract.h +++ b/frameworks/core/components_ng/base/view_abstract.h @@ -51,6 +51,9 @@ public: static void SetOnClick(GestureEventFunc&& clickEventFunc); static void SetOnTouch(TouchEventFunc&& touchEventFunc); + // flex properties + static void SetAlignSelf(int32_t value); + static void Pop(); }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/layout/box_layout_algorithm.cpp b/frameworks/core/components_ng/layout/box_layout_algorithm.cpp index b47ed95c8d0..efed9b4125a 100644 --- a/frameworks/core/components_ng/layout/box_layout_algorithm.cpp +++ b/frameworks/core/components_ng/layout/box_layout_algorithm.cpp @@ -84,6 +84,7 @@ void BoxLayoutAlgorithm::PerformMeasureSelf(LayoutWrapper* layoutWrapper) frameSize.UpdateIllegalSizeWithCheck(SizeF { 0.0f, 0.0f }); } while (false); + frameSize.Constrain(minSize, maxSize); layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize.ConvertToSizeT()); } diff --git a/frameworks/core/components_ng/layout/layout_property.h b/frameworks/core/components_ng/layout/layout_property.h index 60fc7453e6c..eb75b5cb8a1 100644 --- a/frameworks/core/components_ng/layout/layout_property.h +++ b/frameworks/core/components_ng/layout/layout_property.h @@ -26,6 +26,7 @@ #include "base/utils/noncopyable.h" #include "base/utils/utils.h" #include "core/components_ng/property/border_property.h" +#include "core/components_ng/property/flex_property.h" #include "core/components_ng/property/geometry_property.h" #include "core/components_ng/property/layout_constraint.h" #include "core/components_ng/property/magic_layout_property.h" @@ -81,6 +82,9 @@ public: return calcLayoutConstraint_; } + const std::unique_ptr& GetFlexItemProperty() const { + return flexItemProperty_; + } MeasureType GetMeasureType(MeasureType defaultType = MeasureType::MATCH_CONTENT) const { return measureType_.value_or(defaultType); @@ -180,6 +184,33 @@ public: } } + void UpdateFlexGrow(const int32_t flexGrow, bool updateFlag = false) { + if (!flexItemProperty_) { + flexItemProperty_ = std::make_unique(); + } + if (flexItemProperty_->UpdateFlexGrow(flexGrow)) { + propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE; + } + } + + void UpdateFlexShrink(const int32_t flexShrink, bool updateFlag = false) { + if (!flexItemProperty_) { + flexItemProperty_ = std::make_unique(); + } + if (flexItemProperty_->UpdateFlexShrink(flexShrink)) { + propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE; + } + } + + void UpdateAlignSelf(const FlexAlign& flexAlign, bool updateFlag = false) { + if (!flexItemProperty_) { + flexItemProperty_ = std::make_unique(); + } + if (flexItemProperty_->UpdateAlignSelf(flexAlign)) { + propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE; + } + } + void UpdateContentConstraint(); LayoutConstraintF CreateChildConstraint() const; @@ -209,6 +240,7 @@ private: std::unique_ptr borderWidth_; std::unique_ptr magicItemProperty_; std::unique_ptr positionProperty_; + std::unique_ptr flexItemProperty_; std::optional measureType_; ACE_DISALLOW_COPY_AND_MOVE(LayoutProperty); diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 93de5f6630c..8938405403e 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -32,6 +32,8 @@ build_component_ng("pattern_ng") { "linear_layout/linear_layout_algorithm.cpp", "linear_layout/linear_layout_utils.cpp", "linear_layout/row_view.cpp", + "flex/flex_layout_algorithm.cpp", + "flex/flex_view.cpp", "list/list_item_view.cpp", "list/list_layout_algorithm.cpp", "list/list_paint_method.cpp", diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp new file mode 100644 index 00000000000..a199e36b231 --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp @@ -0,0 +1,517 @@ +// +// Created by 陆泽辉 on 2022/8/8. +// + +#include "flex_layout_algorithm.h" +#include "base/utils/utils.h" +#include "core/components_ng/pattern/flex/flex_layout_property.h" +#include "core/components_ng/property/measure_utils.h" + +namespace OHOS::Ace::NG { + + +float FlexLayoutAlgorithm::GetMainSize(const SizeF& size, FlexDirection direction) const { + if (direction == FlexDirection::ROW || direction == FlexDirection::ROW_REVERSE) { + return size.Width(); + } + return size.Height(); +} + +float FlexLayoutAlgorithm::GetMainSize(const RefPtr& layoutWrapper) const { + float size = 0.0; + if (!layoutWrapper) { + return size; + } + if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { + size = layoutWrapper->GetGeometryNode()->GetFrameSize().Width(); + } else { + size = layoutWrapper->GetGeometryNode()->GetFrameSize().Height(); + } + return size; +} + +float FlexLayoutAlgorithm::GetCrossSize(const SizeF& size, FlexDirection direction) const { + if (direction == FlexDirection::ROW || direction == FlexDirection::ROW_REVERSE) { + return size.Height(); + } + return size.Width(); +} + +float FlexLayoutAlgorithm::GetCrossSize(const RefPtr& layoutWrapper) const { + float size = 0.0; + if (!layoutWrapper) { + return size; + } + if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { + size = layoutWrapper->GetGeometryNode()->GetFrameSize().Height(); + } else { + size = layoutWrapper->GetGeometryNode()->GetFrameSize().Width(); + } + return size; +} + +void FlexLayoutAlgorithm::CheckSizeValidity(const RefPtr& layoutWrapper) { +// if (item->IsIgnored() || IsNonRelativePosition(item->GetPositionType())) { +// return; +// } + if (!layoutWrapper->GetGeometryNode()->GetFrameSize().IsValid()) { + return; + } + ++validSizeCount_; +} + +void FlexLayoutAlgorithm::CheckBaselineProperties(const RefPtr& layoutWrapper, BaselineProperties& baselineProperties) { +} + +void FlexLayoutAlgorithm::InitFlexProperties(LayoutWrapper* layoutWrapper) { + mainSize_ = 0.0; + crossSize_ = 0.0; + allocatedSize_ = 0.0; + layoutMode_ = FlexLayoutMode::FLEX_WEIGHT_MODE; + totalFlexWeight_ = 0.0; + maxDisplayPriority_ = 0; + layoutWrapper_ = layoutWrapper; + direction_ = AceType::DynamicCast(layoutWrapper->GetLayoutProperty())->GetFlexDirection().value_or(FlexDirection::ROW); + mainAxisAlign_ = AceType::DynamicCast(layoutWrapper->GetLayoutProperty())->GetMainAxisAlignValue(FlexAlign::FLEX_START); + crossAxisAlign_ = AceType::DynamicCast(layoutWrapper->GetLayoutProperty())->GetCrossAxisAlignValue(FlexAlign::FLEX_START); + TravelChildrenFlexProps(layoutWrapper); +} + +void FlexLayoutAlgorithm::TravelChildrenFlexProps(LayoutWrapper* layoutWrapper) { + std::list> children = layoutWrapper->GetAllChildrenWithBuild(); + for (const auto& child: children) { + /** + * FIXME: no handle absolute child. + */ +// if (IsNonRelativePosition(child->GetPositionType())) { +// absoluteNodes_.insert(child); +// continue; +// } + relativeNodes_.emplace_back(child); + const auto& childLayoutProperty = child->GetLayoutProperty(); + const auto& childMagicItemProperty = childLayoutProperty->GetMagicItemProperty(); + MagicLayoutNode node; + node.layoutWrapper = child; + int32_t childDisplayPriority = 1; + float childLayoutWeight = -1.0; + if (childMagicItemProperty) { + childDisplayPriority = childMagicItemProperty->GetDisplayPriority().value_or(1); + childLayoutWeight = childMagicItemProperty->GetLayoutWeight().value_or(-1); + } + if (!magicNodes_.count(childDisplayPriority)) { + magicNodes_.insert(std::map>::value_type(childDisplayPriority, {node})); + if (childLayoutWeight > 0) { + magicNodeWeights_.insert(std::map::value_type(childDisplayPriority, childLayoutWeight)); + totalFlexWeight_ += childLayoutWeight; + } + } else { + magicNodes_[childDisplayPriority].emplace_back(node); + if (childLayoutWeight > 0) { + magicNodeWeights_[childDisplayPriority] += childLayoutWeight; + totalFlexWeight_ += childLayoutWeight; + } + } + maxDisplayPriority_ = std::max(childDisplayPriority, maxDisplayPriority_); + } + layoutMode_ = LessOrEqual(totalFlexWeight_, 0.0) ? FlexLayoutMode::FLEX_ITEM_MODE : FlexLayoutMode::FLEX_WEIGHT_MODE; + /** + * FIXME: no handle absolute node. + */ +// if (relativeNodes_.empty() && !absoluteNodes_.empty()) { +// layoutMode_ = FlexLayoutMode::FLEX_ITEM_MODE; +// } +} + +void FlexLayoutAlgorithm::ResizeByItem(const RefPtr& childLayoutWrapper, float& allocatedSize) { + float mainSize = GetMainSize(childLayoutWrapper); + if (NearEqual(mainSize, Size::INFINITE_SIZE)) { + mainSize = 0.0; + infinityLayoutNodes_.insert(childLayoutWrapper); + } + /** + * FIXME: no handle absolute node; + */ +// if (IsNonRelativePosition(item->GetPositionType())) { +// return; +// } + /** + * SEMI_Relative 指的是x轴基于父容器,y轴基于自身; + */ + crossSize_ = std::max(crossSize_, GetCrossSize(childLayoutWrapper)); + allocatedSize_ += mainSize; + allocatedSize_ += space_; + allocatedSize += mainSize; + allocatedSize += space_; +} + +void FlexLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) { + LOGD("FlexLayoutAlgorithm::Measure"); + auto children = layoutWrapper->GetAllChildrenWithBuild(); + if (children.empty()) { + LOGD("FlexLayoutAlgorithm::Measure, children is empty"); + layoutWrapper->GetGeometryNode()->SetFrameSize(realSize_); + return; + } + InitFlexProperties(layoutWrapper); + LOGD("FlexLayoutAlgorithm::Measure, layoutMode = %{public}d", layoutMode_); + if (layoutMode_ == FlexLayoutMode::FLEX_WEIGHT_MODE) { + MeasureInWeightMode(layoutWrapper); + } else if (maxDisplayPriority_ > 1) { + MeasureInIndexMode(layoutWrapper); + } else { + MeasureInItemMode(layoutWrapper); + } + +} + +float FlexLayoutAlgorithm::GetStretchCrossLimit() const { + SizeF maxLayoutConstraint = layoutWrapper_->GetLayoutProperty()->GetLayoutConstraint()->maxSize; + float crossAxisLimit = 0.0; + if (!stretchToParent_) { + crossAxisLimit = crossSize_; + } else if (!isCrossInfinite_ || !useViewPort_) { + crossAxisLimit = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? maxLayoutConstraint.Height() : maxLayoutConstraint.Width(); + } else { + /** + * FIXME: no handle viewport size; + */ +// crossAxisLimit = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? viewPort_.Height() : viewPort_.Width(); + } + return crossAxisLimit; +} + +LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraint(float mainFlexExtent, const LayoutConstraintF& constraint, bool isStretch, bool supportZero) const { + LayoutConstraintF layoutConstraint; + LOGD("FlexLayoutAlgorithm::MakeLayoutConstraint, mainFlexExtent = %{public}f, isStretch = %{public}s, supportZero = %{public}s", mainFlexExtent, isStretch ? "true" : "false", supportZero ? "true" : "false"); + if (LessNotEqual(mainFlexExtent, 0.0)) { + layoutConstraint.UpdateMaxSizeWithCheck(layoutWrapper_->GetLayoutProperty()->GetLayoutConstraint()->maxSize); + } else if (GreatNotEqual(mainFlexExtent, 0.0)) { + layoutConstraint = MakeLayoutConstraintWithLimit(mainFlexExtent, mainFlexExtent, isStretch); + } else { + if (supportZero) { + layoutConstraint = MakeLayoutConstraintWithLimit(mainFlexExtent, mainFlexExtent, isStretch); + } else { + layoutConstraint.UpdateMaxSizeWithCheck(layoutWrapper_->GetLayoutProperty()->GetLayoutConstraint()->maxSize); + } + } + layoutConstraint.UpdateMaxSizeWithCheck(layoutConstraint.maxSize); + layoutConstraint.UpdateMinSizeWithCheck(layoutConstraint.minSize); + return layoutConstraint; +} + +LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraintWithLimit(float minMainLimit, float maxMainLimit, bool isStretch) const { + LayoutConstraintF layoutConstraint; + auto parentLayoutConstraint = layoutWrapper_->GetLayoutProperty()->GetLayoutConstraint(); + float minCrossLimit = 0.0; + float maxCrossLimit = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? parentLayoutConstraint->maxSize.Height() : parentLayoutConstraint->maxSize.Width(); + if (isStretch) { + minCrossLimit = GetStretchCrossLimit(); + maxCrossLimit = minCrossLimit; + } + if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { + layoutConstraint.UpdateMinSizeWithCheck(SizeF(minMainLimit, minCrossLimit)); + layoutConstraint.UpdateMaxSizeWithCheck(SizeF(maxMainLimit, maxCrossLimit)); + } else { + layoutConstraint.UpdateMinSizeWithCheck(SizeF(minCrossLimit, minMainLimit)); + layoutConstraint.UpdateMaxSizeWithCheck(SizeF(maxCrossLimit, minMainLimit)); + } + return layoutConstraint; +} + +void FlexLayoutAlgorithm::MeasureInWeightMode(LayoutWrapper* layoutWrapper) { + LOGD("FlexLayoutAlgorithm::MeasureInWeightMode"); + const auto& layoutConstraint = layoutWrapper->GetLayoutProperty()->GetLayoutConstraint(); + float maxMainSize = GetMainSize(layoutConstraint->maxSize, direction_); + LOGD("FlexLayoutAlgorithm::MeasureInWeightMode, maxMainSize = %{public}f", maxMainSize); + if (NearEqual(maxMainSize, Size::INFINITE_SIZE)) { + LOGW("not supported infinite size"); + return; + } + if (!relativeNodes_.empty()) { + maxMainSize -= space_ * static_cast((relativeNodes_.size() - 1)); + } + BaselineProperties baselineProperties; + auto childConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint().value(); + float allocatedSize = allocatedSize_; + for (const auto& child : relativeNodes_) { + const auto& magicItemProperty = child->GetLayoutProperty()->GetMagicItemProperty(); + float childLayoutWeight = -1.0; + if (magicItemProperty) { + childLayoutWeight = magicItemProperty->GetLayoutWeight().value_or(-1); + } + if (LessOrEqual(childLayoutWeight, 0.0)) { + child->Measure(childConstraint); + ResizeByItem(child, allocatedSize); + CheckSizeValidity(child); + CheckBaselineProperties(child, baselineProperties); + } + } + maxMainSize -= allocatedSize_; + // if remain size less than zero, adjust it to zero +// if (!useOldLayoutVersion_ && LessNotEqual(maxMainSize, 0.0)) { +// maxMainSize = 0.0; +// } + + auto spacePerWeight = maxMainSize / totalFlexWeight_; + bool isExceed = false; + auto iter = magicNodes_.rbegin(); + while (iter != magicNodes_.rend()) { + auto& layoutList = (*iter).second; + for (auto& node : layoutList) { + auto childLayoutWrapper = node.layoutWrapper; + const auto& childLayoutProperty = childLayoutWrapper->GetLayoutProperty(); + const auto& magicItemProperty = childLayoutProperty->GetMagicItemProperty(); + if (!magicItemProperty) { + continue; + } + float childLayoutWeight = magicItemProperty->GetLayoutWeightValue(); + if (LessOrEqual(childLayoutWeight, 0.0)) { + continue; + } + float childFlexSize = spacePerWeight * childLayoutWeight; +// isExceed = isExceed || GetMainSize() > childFlexSize; + childConstraint = MakeLayoutConstraint(childFlexSize, childConstraint, false, false); + isExceed = isExceed || GetMainSize(childConstraint.minSize, direction_) > childFlexSize; + node.layoutConstraint = childConstraint; + } + if (!isExceed) { + iter++; + } else if (magicNodes_.size() <= 1) { + break; + } else { + totalFlexWeight_ -= magicNodeWeights_[magicNodes_.begin()->first]; + spacePerWeight = maxMainSize / totalFlexWeight_; + isExceed = false; + magicNodes_.erase(magicNodes_.begin()); + iter = magicNodes_.rbegin(); + } + } + + MeasureMagicNodes(layoutWrapper, baselineProperties); + if (crossAxisAlign_ == FlexAlign::STRETCH) { + RelayoutForStretchMagicNode(); + } + /** + * FIXME: no handle absolute children and hidden nodes; + */ +// LayoutAbsoluteChildren(); +// LayoutHiddenNodes(); + + SizeF idealSize = {-1, -1}; + const auto& parentIdealSize = layoutConstraint->parentIdealSize; +// const auto& minSize = layoutConstraint->minSize; + const auto& maxSize = layoutConstraint->maxSize; + auto measureType = layoutWrapper->GetLayoutProperty()->GetMeasureType(); + if (layoutConstraint->selfIdealSize.has_value()) { + const auto& selfIdealSize = layoutConstraint->selfIdealSize.value(); + idealSize.UpdateSizeWithCheck(selfIdealSize); + } else if (measureType == MeasureType::MATCH_PARENT && parentIdealSize.has_value()) { + idealSize.UpdateIllegalSizeWithCheck(*parentIdealSize); + } + realSize_ = idealSize; + idealSize.UpdateIllegalSizeWithCheck(maxSize); + layoutWrapper->GetGeometryNode()->SetFrameSize(realSize_); + mainSize_ = GetMainSize(realSize_, direction_); + crossSize_ = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? realSize_.Height() : realSize_.Width(); +} + +void FlexLayoutAlgorithm::MeasureInIndexMode(LayoutWrapper* layoutWrapper) { +} + +void FlexLayoutAlgorithm::MeasureInItemMode(LayoutWrapper* layoutWrapper) { +} + +void FlexLayoutAlgorithm::MeasureMagicNodes(LayoutWrapper* layoutWrapper, BaselineProperties& baselineProperties) { + float allocatedSize = allocatedSize_; + LOGD("FlexLayoutAlgorithm::MeasureMagicNodes"); + for (const auto& magicNode : magicNodes_) { + auto childList = magicNode.second; + for (const auto& child : childList) { + const auto& childLayoutWrapper = child.layoutWrapper; + const auto& magicItemProperty = childLayoutWrapper->GetLayoutProperty()->GetMagicItemProperty(); + if (!magicItemProperty) { + continue; + } + float childLayoutWeight = magicItemProperty->GetLayoutWeightValue(); + if (LessOrEqual(childLayoutWeight, 0.0)) { + continue; + } + const auto& layoutConstraint = child.layoutConstraint; + childLayoutWrapper->Measure(layoutConstraint); + ResizeByItem(childLayoutWrapper, allocatedSize); + CheckSizeValidity(childLayoutWrapper); + CheckBaselineProperties(childLayoutWrapper, baselineProperties); + } + } +} + +void FlexLayoutAlgorithm::RelayoutForStretchMagicNode() { + auto childLayoutConstraint = layoutWrapper_->GetLayoutProperty()->CreateChildConstraint().value(); + for (const auto& magicNodeMap : magicNodes_) { + auto nodeList = magicNodeMap.second; + for (const auto& node : nodeList) { + auto childLayoutWrapper = node.layoutWrapper; + childLayoutConstraint = MakeLayoutConstraint(GetMainSize(childLayoutWrapper), childLayoutConstraint, true); + childLayoutWrapper->Measure(childLayoutConstraint); + crossSize_ = std::max(crossSize_, GetCrossSize(childLayoutWrapper)); + } + } +} + +void FlexLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) { + LOGD("FlexLayoutAlgorithm::Layout"); + auto children = layoutWrapper->GetAllChildrenWithBuild(); + if (children.empty()) { + LOGD("FlexLayoutAlgorithm::Layout, children is empty"); + return; + } + BaselineProperties baselineProperties; + float remainSpace = (mainSize_ - allocatedSize_) > 0.0 ? (mainSize_ - allocatedSize_) : 0.0; + float frontSpace = 0.0; + float betweenSpace = 0.0; + CalculateSpace(remainSpace, frontSpace, betweenSpace); + PlaceChildren(layoutWrapper, frontSpace, betweenSpace, baselineProperties); +} + +void FlexLayoutAlgorithm::CalculateSpace(float remainSpace, float& frontSpace, float& betweenSpace) const { + if (NearZero(remainSpace) && mainAxisAlign_ != FlexAlign::SPACE_CUSTOMIZATION) { + return; + } + switch (mainAxisAlign_) { + case FlexAlign::FLEX_START: + frontSpace = 0.0; + betweenSpace = 0.0; + break; + case FlexAlign::FLEX_END: + frontSpace = remainSpace; + betweenSpace = 0.0; + break; + case FlexAlign::CENTER: + frontSpace = remainSpace / 2; + betweenSpace = 0.0; + break; + case FlexAlign::SPACE_BETWEEN: + frontSpace = 0.0; + betweenSpace = validSizeCount_ > 1 ? remainSpace / static_cast(validSizeCount_ - 1) : 0; + break; + case FlexAlign::SPACE_AROUND: + betweenSpace = validSizeCount_ > 0 ? remainSpace / static_cast(validSizeCount_) : 0; + frontSpace = betweenSpace / 2.0; + break; + case FlexAlign::SPACE_EVENLY: + betweenSpace = validSizeCount_ > 0 ? remainSpace / static_cast(validSizeCount_ + 1) : 0; + frontSpace = betweenSpace; + break; + case FlexAlign::SPACE_CUSTOMIZATION: + betweenSpace = space_; + frontSpace = 0.0; + break; + default: + break; + } +} + +void FlexLayoutAlgorithm::PlaceChildren(LayoutWrapper* layoutWrapper, float frontSpace, float betweenSpace, const BaselineProperties& baselineProperties) { + float childMainPos = IsStartTopLeft(direction_, TextDirection::LTR) ? frontSpace : mainSize_ - frontSpace; + float childCrossPos = 0.0; + auto children = layoutWrapper->GetAllChildrenWithBuild(); + for (const auto& child : children) { +// if (child->IsIgnored()) { +// continue; +// } +// auto flexItem = AceType::DynamicCast(item); +// if (flexItem && flexItem->IsHidden() && !flexItem->GetLayoutSize().IsValid()) { +// continue; +// } +// if (IsNonRelativePosition(item->GetPositionType())) { +// Offset absoluteOffset = PositionLayoutUtils::GetAbsoluteOffset(Claim(this), item); +// item->SetAbsolutePosition(absoluteOffset); +// continue; +// } + auto alignItem = GetSelfAlign(child); + auto textDirection = AdjustTextDirectionByDir(); + switch (alignItem) { + case FlexAlign::FLEX_START: + case FlexAlign::FLEX_END: + childCrossPos = (IsStartTopLeft(FlipAxis(direction_), textDirection) == (alignItem == FlexAlign::FLEX_START)) ? 0 : (crossSize_ - GetCrossSize(child)); + break; + case FlexAlign::CENTER: + childCrossPos = (crossSize_ / 2) - (GetCrossSize(child) / 2); + break; + case FlexAlign::STRETCH: + childCrossPos = IsStartTopLeft(FlipAxis(direction_), textDirection) ? 0 : (crossSize_ - GetCrossSize(child)); + break; + case FlexAlign::BASELINE: + default: + break; + } + + OffsetF offset; + if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { +// if (item->GetPositionType() == PositionType::SEMI_RELATIVE) { +// childMainPos = 0.0; +// } + offset = OffsetF(childMainPos, childCrossPos); + } else { +// offset = Offset((item->GetPositionType() == PositionType::SEMI_RELATIVE) ? 0.0 : childCrossPos, childMainPos); + offset = OffsetF(childCrossPos, childMainPos); + } + + if (!IsStartTopLeft(direction_, TextDirection::LTR)) { + if (direction_ != FlexDirection::COLUMN_REVERSE) { + offset.SetX(offset.GetX() - GetMainSize(child)); + } else { + offset.SetY(offset.GetY() - GetMainSize(child)); + } + child->GetGeometryNode()->SetFrameOffset(offset); + childMainPos -= GetMainSize(child) + betweenSpace; + } else { + child->GetGeometryNode()->SetFrameOffset(offset); + childMainPos += GetMainSize(child) + betweenSpace; + } + } +} + +bool FlexLayoutAlgorithm::IsStartTopLeft(FlexDirection direction, TextDirection textDirection) const { + switch (direction) { + case FlexDirection::ROW: + return textDirection == TextDirection::LTR; + case FlexDirection::ROW_REVERSE: + return textDirection == TextDirection::RTL; + case FlexDirection::COLUMN: + return true; + case FlexDirection::COLUMN_REVERSE: + return false; + default: + return true; + } +} + +FlexAlign FlexLayoutAlgorithm::GetSelfAlign(const RefPtr& layoutWrapper) const { + const auto& flexItemProperty = layoutWrapper->GetLayoutProperty()->GetFlexItemProperty(); + const auto& magicItemProperty = layoutWrapper->GetLayoutProperty()->GetMagicItemProperty(); + if (!magicItemProperty) { + } + if (!flexItemProperty) { + return crossAxisAlign_; + } + auto alignSelf = flexItemProperty->GetAlignSelf().value_or(crossAxisAlign_); + return alignSelf; + +} + +TextDirection FlexLayoutAlgorithm::AdjustTextDirectionByDir() const { + auto textDir = TextDirection::RTL; + if (direction_ == FlexDirection::ROW_REVERSE) { + textDir = textDir == TextDirection::RTL ? TextDirection::LTR : TextDirection::RTL; + } + return textDir; +} + +FlexDirection FlexLayoutAlgorithm::FlipAxis(FlexDirection direction) const { + if (direction == FlexDirection::ROW || direction == FlexDirection::ROW_REVERSE) { + return FlexDirection::COLUMN; + } + return FlexDirection::ROW; +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h new file mode 100644 index 00000000000..54f23901afb --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h @@ -0,0 +1,107 @@ +// +// Created by 陆泽辉 on 2022/8/8. +// + +#ifndef ARKUI_ACE_ENGINE_FLEX_LAYOUT_ALGORITHM_H +#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_ALGORITHM_H + +#include "core/components_ng/layout/layout_algorithm.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/layout/layout_wrapper.h" +#include "core/components_ng/pattern/flex/flex_layout_styles.h" + +namespace OHOS::Ace::NG { + +//struct FlexMeasureProperty { +// SizeF realSize; +// float crossSize = 0.0; +// float allocatedSize = 0.0; +// FlexDirection direction; +// std::list> relativeNodes; +// std::list> weightNodes; +// std::set> infinityLayoutNodes; +// std::map>> magicNodes; +// std::map magicNodeWeights; +// float totalFlexWeight = 0; +// int32_t maxDisplayPriority = 0; +// FlexLayoutMode layoutMode = FlexLayoutMode::FLEX_ITEM_MODE; +// float space = 0.0; +// +//}; + +struct MagicLayoutNode { + LayoutConstraintF layoutConstraint; + RefPtr layoutWrapper; +}; + + +struct BaselineProperties { + float maxBaselineDistance = 0.0; + float maxDistanceAboveBaseline = 0.0; + float maxDistanceBelowBaseline = 0.0; +}; + +class ACE_EXPORT FlexLayoutAlgorithm : public LayoutAlgorithm { + DECLARE_ACE_TYPE(FlexLayoutAlgorithm, LayoutAlgorithm); + +public: + FlexLayoutAlgorithm() = default; + ~FlexLayoutAlgorithm() override = default; + + void Measure(LayoutWrapper* layoutWrapper) override; + + void Layout(LayoutWrapper* layoutWrapper) override; + +private: + void InitFlexProperties(LayoutWrapper* layoutWrapper); + void TravelChildrenFlexProps(LayoutWrapper* layoutWrapper); + void MeasureInWeightMode(LayoutWrapper* layoutWrapper); + void MeasureInIndexMode(LayoutWrapper* layoutWrapper); + void MeasureInItemMode(LayoutWrapper* layoutWrapper); + void MeasureMagicNodes(LayoutWrapper* layoutWrapper, BaselineProperties& baselineProperties); + void ResizeByItem(const RefPtr& layoutWrapper, float& allocatedSize); + float GetMainSize(const RefPtr& layoutWrapper) const; + float GetMainSize(const SizeF& size, FlexDirection direction) const; + float GetCrossSize(const RefPtr& layoutWrapper) const; + float GetCrossSize(const SizeF& size, FlexDirection direction) const; + void RelayoutForStretchMagicNode(); + void CheckSizeValidity(const RefPtr& layoutWrapper); + void CheckBaselineProperties(const RefPtr& layoutWrapper, BaselineProperties& baselineProperties); + void CalculateSpace(float remainSpace, float& frontSpace, float& betweenSpace) const; + void PlaceChildren(LayoutWrapper* layoutWrapper, float frontSpace, float betweenSpace, const BaselineProperties& baselineProperties); + bool IsStartTopLeft(FlexDirection direction, TextDirection textDirection) const; + FlexAlign GetSelfAlign(const RefPtr& layoutWrapper) const; + TextDirection AdjustTextDirectionByDir() const; + FlexDirection FlipAxis(FlexDirection direction) const; + LayoutConstraintF MakeLayoutConstraint(float mainFlexExtent, const LayoutConstraintF& constraint, bool isStretch, bool supportZero = false) const; + LayoutConstraintF MakeLayoutConstraintWithLimit(float minMainLimit, float maxMainLimit, bool isStretch) const; + float GetStretchCrossLimit() const; + + SizeF realSize_; + float mainSize_ = 0.0; + float crossSize_ = 0.0; + float allocatedSize_ = 0.0; + float space_ = 0.0; + bool isCrossInfinite_ = false; + bool useViewPort_ = false; + bool stretchToParent_ = false; + float totalFlexWeight_ = 0.0; + int32_t maxDisplayPriority_ = 0; + int32_t validSizeCount_ = 0; + FlexAlign crossAxisAlign_ = FlexAlign::FLEX_START; + FlexAlign mainAxisAlign_ = FlexAlign::FLEX_START; + + RefPtr layoutWrapper_; + std::list> relativeNodes_; + std::list> weightNodes_; + std::set> infinityLayoutNodes_; + std::map> magicNodes_; + std::map magicNodeWeights_; + FlexLayoutMode layoutMode_ = FlexLayoutMode::FLEX_ITEM_MODE; + FlexDirection direction_ = FlexDirection::ROW; + friend class LinearLayoutUtils; + ACE_DISALLOW_COPY_AND_MOVE(FlexLayoutAlgorithm); +}; +} // namespace OHOS::Ace::NG + +#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h b/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h new file mode 100644 index 00000000000..fe13de675f6 --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h @@ -0,0 +1,36 @@ +// +// Created by 陆泽辉 on 2022/8/8. +// + +#ifndef ARKUI_ACE_ENGINE_FLEX_LAYOUT_PATTERN_H +#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_PATTERN_H + +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/pattern/flex/flex_layout_algorithm.h" +#include "core/components_ng/pattern/flex/flex_layout_property.h" + +namespace OHOS::Ace::NG { +class FlexLayoutPattern : public Pattern { + +public: + explicit FlexLayoutPattern() = default; + ~FlexLayoutPattern() override = default; + + RefPtr CreateLayoutProperty() override { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override { + return MakeRefPtr(); + } + + bool IsAtomicNode() const override { + return false; + } + +private: + ACE_DISALLOW_COPY_AND_MOVE(FlexLayoutPattern); +}; +} // namespace OHOS::Ace::NG + +#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_property.h b/frameworks/core/components_ng/pattern/flex/flex_layout_property.h new file mode 100644 index 00000000000..e48c1ca326c --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_property.h @@ -0,0 +1,67 @@ +// +// Created by 陆泽辉 on 2022/8/8. +// + +#ifndef ARKUI_ACE_ENGINE_FLEX_LAYOUT_PROPERTY_H +#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_PROPERTY_H + +#include "base/utils/macros.h" +#include "core/components_ng/layout/layout_property.h" +#include "core/components_ng/pattern/flex/flex_layout_styles.h" +#include "core/components_ng/property/property.h" + + +namespace OHOS::Ace::NG { +class ACE_EXPORT FlexLayoutProperty : public LayoutProperty { + DECLARE_ACE_TYPE(FlexLayoutProperty, LayoutProperty); + +public: + explicit FlexLayoutProperty() = default; + + ~FlexLayoutProperty() override = default; + + RefPtr Clone() const override { + auto value = MakeRefPtr(); + value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); + value->propFlexLayoutAttribute_ = CloneFlexLayoutAttribute(); + return value; + } + + void Reset() override { + LayoutProperty::Reset(); + ResetFlexLayoutAttribute(); + } + + ACE_DEFINE_PROPERTY_GROUP(FlexLayoutAttribute, FlexLayoutAttribute); + + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, FlexDirection, FlexDirection, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, MainAxisAlign, FlexAlign, PROPERTY_UPDATE_MEASURE); + ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, CrossAxisAlign, FlexAlign, PROPERTY_UPDATE_MEASURE); + +// FlexDirection GetFlexDirection() const { +// if (!propFlexLayoutAttribute_) { +// return FlexDirection::ROW; +// } +// return propFlexLayoutAttribute_->GetFlexDirection().value_or(FlexDirection::ROW); +// } + +// FlexAlign GetMainAxisAlign() const { +// if (!propFlexLayoutAttribute_) { +// return FlexAlign::FLEX_START; +// } +// return propFlexLayoutAttribute_->GetMainAxisAlign().value_or(FlexAlign::FLEX_START); +// } + +// FlexAlign GetCrossAxisAlign() const { +// if (!propFlexLayoutAttribute_) { +// return FlexAlign::FLEX_START; +// } +// return propFlexLayoutAttribute_->GetCrossAxisAlign().value_or(FlexAlign::FLEX_START); +// } +private: + ACE_DISALLOW_COPY_AND_MOVE(FlexLayoutProperty); +}; + +} // namespace OHOS::Ace::NG + +#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_PROPERTY_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h b/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h new file mode 100644 index 00000000000..a0f37859268 --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h @@ -0,0 +1,20 @@ +// +// Created by 陆泽辉 on 2022/8/8. +// + +#ifndef ARKUI_ACE_ENGINE_FLEX_LAYOUT_STYLES_H +#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_STYLES_H + +#include "base/geometry/dimension.h" +#include "core/components/common/layout/constants.h" +#include "core/components_ng/property/property.h" + +namespace OHOS::Ace::NG { +struct FlexLayoutAttribute { + ACE_DEFINE_PROPERTY_GROUP_ITEM(FlexDirection, FlexDirection); + ACE_DEFINE_PROPERTY_GROUP_ITEM(MainAxisAlign, FlexAlign); + ACE_DEFINE_PROPERTY_GROUP_ITEM(CrossAxisAlign, FlexAlign); +}; +} // namespace OHOS::Ace::NG + +#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_STYLES_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_view.cpp b/frameworks/core/components_ng/pattern/flex/flex_view.cpp new file mode 100644 index 00000000000..2053d70b077 --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_view.cpp @@ -0,0 +1,36 @@ +// +// Created by 陆泽辉 on 2022/8/4. +// + +#include "core/components_ng/pattern/flex/flex_view.h" +#include "base/log/log_wrapper.h" +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/flex/flex_layout_pattern.h" +#include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { +void FlexView::Create(FlexDirection direction, FlexAlign mainAxisAlign, FlexAlign crossAxisAlign) { + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode(V2::FLEX_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); + + ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, FlexDirection, direction); + ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAxisAlign, mainAxisAlign); + ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAxisAlign, crossAxisAlign); +} + +void FlexView::Direction(const FlexDirection& value) { + ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, FlexDirection, value); +} + +void FlexView::MainAxisAlign(const FlexAlign& value) { + ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, MainAxisAlign, value); +} + +void FlexView::CrossAxisAlign(const FlexAlign& value) { + ACE_UPDATE_LAYOUT_PROPERTY(FlexLayoutProperty, CrossAxisAlign, value); +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/flex/flex_view.h b/frameworks/core/components_ng/pattern/flex/flex_view.h new file mode 100644 index 00000000000..0dd17707175 --- /dev/null +++ b/frameworks/core/components_ng/pattern/flex/flex_view.h @@ -0,0 +1,21 @@ +// +// Created by 陆泽辉 on 2022/8/4. +// + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LINEAR_LAYOUT_FLEX_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LINEAR_LAYOUT_FLEX_VIEW_H + +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT FlexView { +public: + static void Create(FlexDirection direction, FlexAlign mainAxisAlign, FlexAlign crossAxisAlign); + static void Direction(const FlexDirection& value); + static void MainAxisAlign(const FlexAlign& value); + static void CrossAxisAlign(const FlexAlign& value); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LINEAR_LAYOUT_FLEX_VIEW_H From 147815a2b2568297542e8bc76f6685477fd8fdd2 Mon Sep 17 00:00:00 2001 From: luzehui Date: Sun, 4 Sep 2022 12:54:54 +0800 Subject: [PATCH 31/35] Modify FlexLayout in weightMode Signed-off-by: luzehui Change-Id: Ia70b26d3e0b729654b77d06b89affb9a5c8568f9 --- frameworks/base/geometry/ng/size_t.h | 15 +- .../jsview/js_view_abstract.cpp | 1 - .../layout/box_layout_algorithm.cpp | 2 +- .../components_ng/layout/layout_property.h | 3 +- .../pattern/flex/flex_layout_algorithm.cpp | 297 ++++++++++-------- .../pattern/flex/flex_layout_algorithm.h | 40 ++- .../pattern/flex/flex_layout_pattern.h | 34 +- .../pattern/flex/flex_layout_property.h | 51 ++- .../pattern/flex/flex_layout_styles.h | 24 +- .../components_ng/pattern/flex/flex_view.cpp | 18 +- .../components_ng/pattern/flex/flex_view.h | 17 +- interfaces/napi/kits/router/js_router.cpp | 98 ++++++ 12 files changed, 383 insertions(+), 217 deletions(-) diff --git a/frameworks/base/geometry/ng/size_t.h b/frameworks/base/geometry/ng/size_t.h index cb970b7f7e7..3957c98f050 100644 --- a/frameworks/base/geometry/ng/size_t.h +++ b/frameworks/base/geometry/ng/size_t.h @@ -202,24 +202,19 @@ public: void Constrain(const SizeT& minSize, const SizeT& maxSize) { if (NonNegative(minSize.width_)) { - width_ = width_ > minSize.width_ ? width_ : minSize.width_; + width_ = width_ > minSize.Width() ? width_ : minSize.Width(); } if (NonNegative(minSize.height_)) { - height_ = height_ > minSize.height_ ? height_ : minSize.height_; + height_ = height_ > minSize.Height() ? height_ : minSize.Height(); } if (NonNegative(maxSize.width_)) { - width_ = width_ < maxSize.width_ ? width_ : maxSize.width_; + width_ = width_ < maxSize.Width() ? width_ : maxSize.Width(); } if (NonNegative(maxSize.height_)) { - height_ = height_ < maxSize.height_ ? height_ : maxSize.height_; + height_ = height_ < maxSize.Height() ? height_ : maxSize.Height(); } } - bool IsValid() const - { - return width_ > 0.0 && height_ > 0.0; - } - SizeT operator*(double value) const { return SizeT(width_ * value, height_ * value); @@ -560,7 +555,7 @@ public: width_ = width_.value_or(0) < maxSize.Width() ? width_ : maxSize.Width(); } if (NonNegative(maxSize.Height())) { - height_ = height_.value_or(0) < maxSize.height_ ? Height() : maxSize.Height(); + height_ = height_.value_or(0) < maxSize.Height() ? Height() : maxSize.Height(); } } diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index e150abb4fe7..59d87cd55d1 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -1621,7 +1621,6 @@ void JSViewAbstract::JsAlignSelf(const JSCallbackInfo& info) return; } auto flexItem = ViewStackProcessor::GetInstance()->GetFlexItemComponent(); -// auto alignVal = info[0]->ToNumber(); if (alignVal >= 0 && alignVal <= MAX_ALIGN_VALUE) { flexItem->SetAlignSelf((FlexAlign)alignVal); diff --git a/frameworks/core/components_ng/layout/box_layout_algorithm.cpp b/frameworks/core/components_ng/layout/box_layout_algorithm.cpp index efed9b4125a..a5e54f3e295 100644 --- a/frameworks/core/components_ng/layout/box_layout_algorithm.cpp +++ b/frameworks/core/components_ng/layout/box_layout_algorithm.cpp @@ -60,6 +60,7 @@ void BoxLayoutAlgorithm::PerformMeasureSelf(LayoutWrapper* layoutWrapper) if (measureType == MeasureType::MATCH_PARENT) { frameSize.UpdateIllegalSizeWithCheck(layoutConstraint->parentIdealSize); if (frameSize.IsValid()) { + frameSize.Constrain(minSize, maxSize); break; } } @@ -84,7 +85,6 @@ void BoxLayoutAlgorithm::PerformMeasureSelf(LayoutWrapper* layoutWrapper) frameSize.UpdateIllegalSizeWithCheck(SizeF { 0.0f, 0.0f }); } while (false); - frameSize.Constrain(minSize, maxSize); layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize.ConvertToSizeT()); } diff --git a/frameworks/core/components_ng/layout/layout_property.h b/frameworks/core/components_ng/layout/layout_property.h index eb75b5cb8a1..403a51e61b6 100644 --- a/frameworks/core/components_ng/layout/layout_property.h +++ b/frameworks/core/components_ng/layout/layout_property.h @@ -82,7 +82,8 @@ public: return calcLayoutConstraint_; } - const std::unique_ptr& GetFlexItemProperty() const { + const std::unique_ptr& GetFlexItemProperty() const + { return flexItemProperty_; } MeasureType GetMeasureType(MeasureType defaultType = MeasureType::MATCH_CONTENT) const diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp index a199e36b231..7d178c05605 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp @@ -1,6 +1,17 @@ -// -// Created by 陆泽辉 on 2022/8/8. -// +/* + * 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 "flex_layout_algorithm.h" #include "base/utils/utils.h" @@ -10,15 +21,17 @@ namespace OHOS::Ace::NG { -float FlexLayoutAlgorithm::GetMainSize(const SizeF& size, FlexDirection direction) const { +float FlexLayoutAlgorithm::GetMainSize(const SizeF& size, FlexDirection direction) const +{ if (direction == FlexDirection::ROW || direction == FlexDirection::ROW_REVERSE) { return size.Width(); } return size.Height(); } -float FlexLayoutAlgorithm::GetMainSize(const RefPtr& layoutWrapper) const { - float size = 0.0; +float FlexLayoutAlgorithm::GetMainSize(const RefPtr& layoutWrapper) const +{ + float size = 0.0f; if (!layoutWrapper) { return size; } @@ -30,15 +43,17 @@ float FlexLayoutAlgorithm::GetMainSize(const RefPtr& layoutWrappe return size; } -float FlexLayoutAlgorithm::GetCrossSize(const SizeF& size, FlexDirection direction) const { +float FlexLayoutAlgorithm::GetCrossSize(const SizeF& size, FlexDirection direction) const +{ if (direction == FlexDirection::ROW || direction == FlexDirection::ROW_REVERSE) { return size.Height(); } return size.Width(); } -float FlexLayoutAlgorithm::GetCrossSize(const RefPtr& layoutWrapper) const { - float size = 0.0; +float FlexLayoutAlgorithm::GetCrossSize(const RefPtr& layoutWrapper) const +{ + float size = 0.0f; if (!layoutWrapper) { return size; } @@ -50,20 +65,33 @@ float FlexLayoutAlgorithm::GetCrossSize(const RefPtr& layoutWrapp return size; } -void FlexLayoutAlgorithm::CheckSizeValidity(const RefPtr& layoutWrapper) { -// if (item->IsIgnored() || IsNonRelativePosition(item->GetPositionType())) { -// return; -// } - if (!layoutWrapper->GetGeometryNode()->GetFrameSize().IsValid()) { +OptionalSizeF FlexLayoutAlgorithm::GetCalcSize(float mainSize, float crossSize) +{ + OptionalSizeF size; + if (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) { + size.SetWidth(mainSize); + size.SetHeight(crossSize); + } else { + size.SetHeight(mainSize); + size.SetWidth(crossSize); + } + return size; +} + +void FlexLayoutAlgorithm::CheckSizeValidity(const RefPtr& layoutWrapper) +{ + if (!layoutWrapper->GetGeometryNode()->GetFrameSize().IsPositive()) { return; } ++validSizeCount_; } -void FlexLayoutAlgorithm::CheckBaselineProperties(const RefPtr& layoutWrapper, BaselineProperties& baselineProperties) { +void FlexLayoutAlgorithm::CheckBaselineProperties(const RefPtr& layoutWrapper, BaselineProperties& baselineProperties) +{ } -void FlexLayoutAlgorithm::InitFlexProperties(LayoutWrapper* layoutWrapper) { +void FlexLayoutAlgorithm::InitFlexProperties(LayoutWrapper* layoutWrapper) +{ mainSize_ = 0.0; crossSize_ = 0.0; allocatedSize_ = 0.0; @@ -77,23 +105,16 @@ void FlexLayoutAlgorithm::InitFlexProperties(LayoutWrapper* layoutWrapper) { TravelChildrenFlexProps(layoutWrapper); } -void FlexLayoutAlgorithm::TravelChildrenFlexProps(LayoutWrapper* layoutWrapper) { - std::list> children = layoutWrapper->GetAllChildrenWithBuild(); +void FlexLayoutAlgorithm::TravelChildrenFlexProps(LayoutWrapper* layoutWrapper) +{ + const auto& children = layoutWrapper->GetAllChildrenWithBuild(); for (const auto& child: children) { - /** - * FIXME: no handle absolute child. - */ -// if (IsNonRelativePosition(child->GetPositionType())) { -// absoluteNodes_.insert(child); -// continue; -// } - relativeNodes_.emplace_back(child); const auto& childLayoutProperty = child->GetLayoutProperty(); const auto& childMagicItemProperty = childLayoutProperty->GetMagicItemProperty(); MagicLayoutNode node; node.layoutWrapper = child; int32_t childDisplayPriority = 1; - float childLayoutWeight = -1.0; + float childLayoutWeight = -1.0f; if (childMagicItemProperty) { childDisplayPriority = childMagicItemProperty->GetDisplayPriority().value_or(1); childLayoutWeight = childMagicItemProperty->GetLayoutWeight().value_or(-1); @@ -114,29 +135,15 @@ void FlexLayoutAlgorithm::TravelChildrenFlexProps(LayoutWrapper* layoutWrapper) maxDisplayPriority_ = std::max(childDisplayPriority, maxDisplayPriority_); } layoutMode_ = LessOrEqual(totalFlexWeight_, 0.0) ? FlexLayoutMode::FLEX_ITEM_MODE : FlexLayoutMode::FLEX_WEIGHT_MODE; - /** - * FIXME: no handle absolute node. - */ -// if (relativeNodes_.empty() && !absoluteNodes_.empty()) { -// layoutMode_ = FlexLayoutMode::FLEX_ITEM_MODE; -// } } -void FlexLayoutAlgorithm::ResizeByItem(const RefPtr& childLayoutWrapper, float& allocatedSize) { +void FlexLayoutAlgorithm::ResizeByItem(const RefPtr& childLayoutWrapper, float& allocatedSize) +{ float mainSize = GetMainSize(childLayoutWrapper); if (NearEqual(mainSize, Size::INFINITE_SIZE)) { mainSize = 0.0; infinityLayoutNodes_.insert(childLayoutWrapper); } - /** - * FIXME: no handle absolute node; - */ -// if (IsNonRelativePosition(item->GetPositionType())) { -// return; -// } - /** - * SEMI_Relative 指的是x轴基于父容器,y轴基于自身; - */ crossSize_ = std::max(crossSize_, GetCrossSize(childLayoutWrapper)); allocatedSize_ += mainSize; allocatedSize_ += space_; @@ -144,12 +151,12 @@ void FlexLayoutAlgorithm::ResizeByItem(const RefPtr& childLayoutW allocatedSize += space_; } -void FlexLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) { - LOGD("FlexLayoutAlgorithm::Measure"); +void FlexLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) +{ auto children = layoutWrapper->GetAllChildrenWithBuild(); if (children.empty()) { LOGD("FlexLayoutAlgorithm::Measure, children is empty"); - layoutWrapper->GetGeometryNode()->SetFrameSize(realSize_); + layoutWrapper->GetGeometryNode()->SetFrameSize(realSize_.ConvertToSizeT()); return; } InitFlexProperties(layoutWrapper); @@ -164,23 +171,19 @@ void FlexLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) { } -float FlexLayoutAlgorithm::GetStretchCrossLimit() const { - SizeF maxLayoutConstraint = layoutWrapper_->GetLayoutProperty()->GetLayoutConstraint()->maxSize; - float crossAxisLimit = 0.0; - if (!stretchToParent_) { - crossAxisLimit = crossSize_; - } else if (!isCrossInfinite_ || !useViewPort_) { - crossAxisLimit = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? maxLayoutConstraint.Height() : maxLayoutConstraint.Width(); +float FlexLayoutAlgorithm::GetStretchCrossLimit() const +{ + float crossAxisLimit = 0.0f; + if (GreatNotEqual(selfIdealCrossSize_, -1.0f)) { + crossAxisLimit = selfIdealCrossSize_; } else { - /** - * FIXME: no handle viewport size; - */ -// crossAxisLimit = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? viewPort_.Height() : viewPort_.Width(); + crossAxisLimit = crossSize_; } return crossAxisLimit; } -LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraint(float mainFlexExtent, const LayoutConstraintF& constraint, bool isStretch, bool supportZero) const { +LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraint(float mainFlexExtent, const LayoutConstraintF& constraint, bool isStretch, bool supportZero) const +{ LayoutConstraintF layoutConstraint; LOGD("FlexLayoutAlgorithm::MakeLayoutConstraint, mainFlexExtent = %{public}f, isStretch = %{public}s, supportZero = %{public}s", mainFlexExtent, isStretch ? "true" : "false", supportZero ? "true" : "false"); if (LessNotEqual(mainFlexExtent, 0.0)) { @@ -199,10 +202,11 @@ LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraint(float mainFlexExtent return layoutConstraint; } -LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraintWithLimit(float minMainLimit, float maxMainLimit, bool isStretch) const { +LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraintWithLimit(float minMainLimit, float maxMainLimit, bool isStretch) const +{ LayoutConstraintF layoutConstraint; auto parentLayoutConstraint = layoutWrapper_->GetLayoutProperty()->GetLayoutConstraint(); - float minCrossLimit = 0.0; + float minCrossLimit = 0.0f; float maxCrossLimit = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? parentLayoutConstraint->maxSize.Height() : parentLayoutConstraint->maxSize.Width(); if (isStretch) { minCrossLimit = GetStretchCrossLimit(); @@ -218,58 +222,91 @@ LayoutConstraintF FlexLayoutAlgorithm::MakeLayoutConstraintWithLimit(float minMa return layoutConstraint; } -void FlexLayoutAlgorithm::MeasureInWeightMode(LayoutWrapper* layoutWrapper) { +void FlexLayoutAlgorithm::MeasureInWeightMode(LayoutWrapper* layoutWrapper) +{ LOGD("FlexLayoutAlgorithm::MeasureInWeightMode"); const auto& layoutConstraint = layoutWrapper->GetLayoutProperty()->GetLayoutConstraint(); - float maxMainSize = GetMainSize(layoutConstraint->maxSize, direction_); + const auto& parentIdealSize = layoutConstraint->parentIdealSize; + auto measureType = layoutWrapper->GetLayoutProperty()->GetMeasureType(); + OptionalSizeF realSize; + /** + * check selfIdealSize and matchParent. + */ + do { + realSize.UpdateSizeWithCheck(layoutConstraint->selfIdealSize); + if (realSize.IsValid()) { + break; + } + + if (measureType == MeasureType::MATCH_PARENT) { + realSize.UpdateIllegalSizeWithCheck(parentIdealSize); + } + } while(false); + /** + * get the user defined main axis size and cross axis size. + */ + SizeF maxSize; + maxSize.UpdateSizeWithCheck(layoutConstraint->maxSize); + maxSize.UpdateSizeWhenSmaller(realSize.ConvertToSizeT()); + float maxMainSize = GetMainSize(maxSize, direction_); LOGD("FlexLayoutAlgorithm::MeasureInWeightMode, maxMainSize = %{public}f", maxMainSize); if (NearEqual(maxMainSize, Size::INFINITE_SIZE)) { LOGW("not supported infinite size"); return; } - if (!relativeNodes_.empty()) { - maxMainSize -= space_ * static_cast((relativeNodes_.size() - 1)); - } + selfIdealCrossSize_ = GetCrossSize(realSize.ConvertToSizeT(), direction_); + LOGD("selfIdealCrossSize_ = %{public}f", selfIdealCrossSize_); BaselineProperties baselineProperties; - auto childConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint().value(); + auto childConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint(); float allocatedSize = allocatedSize_; - for (const auto& child : relativeNodes_) { - const auto& magicItemProperty = child->GetLayoutProperty()->GetMagicItemProperty(); - float childLayoutWeight = -1.0; - if (magicItemProperty) { - childLayoutWeight = magicItemProperty->GetLayoutWeight().value_or(-1); - } - if (LessOrEqual(childLayoutWeight, 0.0)) { - child->Measure(childConstraint); - ResizeByItem(child, allocatedSize); - CheckSizeValidity(child); - CheckBaselineProperties(child, baselineProperties); - } - } - maxMainSize -= allocatedSize_; - // if remain size less than zero, adjust it to zero -// if (!useOldLayoutVersion_ && LessNotEqual(maxMainSize, 0.0)) { -// maxMainSize = 0.0; -// } - - auto spacePerWeight = maxMainSize / totalFlexWeight_; - bool isExceed = false; + /** + * measure relative nodes; + */ auto iter = magicNodes_.rbegin(); while (iter != magicNodes_.rend()) { auto& layoutList = (*iter).second; for (auto& node : layoutList) { auto childLayoutWrapper = node.layoutWrapper; + float childLayoutWeight = 0.0f; + const auto& magicItemProperty = childLayoutWrapper->GetLayoutProperty()->GetMagicItemProperty(); + if (magicItemProperty) { + childLayoutWeight = magicItemProperty->GetLayoutWeightValue(); + } + if (LessOrEqual(childLayoutWeight, 0.0)) { + childLayoutWrapper->Measure(childConstraint); + ResizeByItem(childLayoutWrapper, allocatedSize); + CheckSizeValidity(childLayoutWrapper); + CheckBaselineProperties(childLayoutWrapper, baselineProperties); + } + } + iter++; + } + + maxMainSize -= allocatedSize_; + if (LessOrEqual(maxMainSize, 0)) { + return; + } + + /** + * measure magic nodes + */ + auto spacePerWeight = maxMainSize / totalFlexWeight_; + bool isExceed = false; + iter = magicNodes_.rbegin(); + while (iter != magicNodes_.rend()) { + auto& layoutList = (*iter).second; + for (auto& node : layoutList) { + auto childLayoutWrapper = node.layoutWrapper; + float childLayoutWeight = 0.0f; const auto& childLayoutProperty = childLayoutWrapper->GetLayoutProperty(); const auto& magicItemProperty = childLayoutProperty->GetMagicItemProperty(); - if (!magicItemProperty) { - continue; + if (magicItemProperty) { + childLayoutWeight = magicItemProperty->GetLayoutWeightValue(); } - float childLayoutWeight = magicItemProperty->GetLayoutWeightValue(); - if (LessOrEqual(childLayoutWeight, 0.0)) { + if (LessOrEqual(childLayoutWeight, 0)) { continue; } float childFlexSize = spacePerWeight * childLayoutWeight; -// isExceed = isExceed || GetMainSize() > childFlexSize; childConstraint = MakeLayoutConstraint(childFlexSize, childConstraint, false, false); isExceed = isExceed || GetMainSize(childConstraint.minSize, direction_) > childFlexSize; node.layoutConstraint = childConstraint; @@ -291,37 +328,22 @@ void FlexLayoutAlgorithm::MeasureInWeightMode(LayoutWrapper* layoutWrapper) { if (crossAxisAlign_ == FlexAlign::STRETCH) { RelayoutForStretchMagicNode(); } - /** - * FIXME: no handle absolute children and hidden nodes; - */ -// LayoutAbsoluteChildren(); -// LayoutHiddenNodes(); - SizeF idealSize = {-1, -1}; - const auto& parentIdealSize = layoutConstraint->parentIdealSize; -// const auto& minSize = layoutConstraint->minSize; - const auto& maxSize = layoutConstraint->maxSize; - auto measureType = layoutWrapper->GetLayoutProperty()->GetMeasureType(); - if (layoutConstraint->selfIdealSize.has_value()) { - const auto& selfIdealSize = layoutConstraint->selfIdealSize.value(); - idealSize.UpdateSizeWithCheck(selfIdealSize); - } else if (measureType == MeasureType::MATCH_PARENT && parentIdealSize.has_value()) { - idealSize.UpdateIllegalSizeWithCheck(*parentIdealSize); - } - realSize_ = idealSize; - idealSize.UpdateIllegalSizeWithCheck(maxSize); - layoutWrapper->GetGeometryNode()->SetFrameSize(realSize_); - mainSize_ = GetMainSize(realSize_, direction_); - crossSize_ = (direction_ == FlexDirection::ROW || direction_ == FlexDirection::ROW_REVERSE) ? realSize_.Height() : realSize_.Width(); + realSize.UpdateIllegalSizeWithCheck(GetCalcSize(maxMainSize, crossSize_)); + LOGD("realSize = %{public}s", realSize.ToString().c_str()); + layoutWrapper->GetGeometryNode()->SetFrameSize(realSize.ConvertToSizeT()); } -void FlexLayoutAlgorithm::MeasureInIndexMode(LayoutWrapper* layoutWrapper) { +void FlexLayoutAlgorithm::MeasureInIndexMode(LayoutWrapper* layoutWrapper) +{ } -void FlexLayoutAlgorithm::MeasureInItemMode(LayoutWrapper* layoutWrapper) { +void FlexLayoutAlgorithm::MeasureInItemMode(LayoutWrapper* layoutWrapper) +{ } -void FlexLayoutAlgorithm::MeasureMagicNodes(LayoutWrapper* layoutWrapper, BaselineProperties& baselineProperties) { +void FlexLayoutAlgorithm::MeasureMagicNodes(LayoutWrapper* layoutWrapper, BaselineProperties& baselineProperties) +{ float allocatedSize = allocatedSize_; LOGD("FlexLayoutAlgorithm::MeasureMagicNodes"); for (const auto& magicNode : magicNodes_) { @@ -345,8 +367,9 @@ void FlexLayoutAlgorithm::MeasureMagicNodes(LayoutWrapper* layoutWrapper, Baseli } } -void FlexLayoutAlgorithm::RelayoutForStretchMagicNode() { - auto childLayoutConstraint = layoutWrapper_->GetLayoutProperty()->CreateChildConstraint().value(); +void FlexLayoutAlgorithm::RelayoutForStretchMagicNode() +{ + auto childLayoutConstraint = layoutWrapper_->GetLayoutProperty()->CreateChildConstraint(); for (const auto& magicNodeMap : magicNodes_) { auto nodeList = magicNodeMap.second; for (const auto& node : nodeList) { @@ -358,7 +381,8 @@ void FlexLayoutAlgorithm::RelayoutForStretchMagicNode() { } } -void FlexLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) { +void FlexLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) +{ LOGD("FlexLayoutAlgorithm::Layout"); auto children = layoutWrapper->GetAllChildrenWithBuild(); if (children.empty()) { @@ -367,13 +391,14 @@ void FlexLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) { } BaselineProperties baselineProperties; float remainSpace = (mainSize_ - allocatedSize_) > 0.0 ? (mainSize_ - allocatedSize_) : 0.0; - float frontSpace = 0.0; - float betweenSpace = 0.0; + float frontSpace = 0.0f; + float betweenSpace = 0.0f; CalculateSpace(remainSpace, frontSpace, betweenSpace); PlaceChildren(layoutWrapper, frontSpace, betweenSpace, baselineProperties); } -void FlexLayoutAlgorithm::CalculateSpace(float remainSpace, float& frontSpace, float& betweenSpace) const { +void FlexLayoutAlgorithm::CalculateSpace(float remainSpace, float& frontSpace, float& betweenSpace) const +{ if (NearZero(remainSpace) && mainAxisAlign_ != FlexAlign::SPACE_CUSTOMIZATION) { return; } @@ -396,7 +421,7 @@ void FlexLayoutAlgorithm::CalculateSpace(float remainSpace, float& frontSpace, f break; case FlexAlign::SPACE_AROUND: betweenSpace = validSizeCount_ > 0 ? remainSpace / static_cast(validSizeCount_) : 0; - frontSpace = betweenSpace / 2.0; + frontSpace = betweenSpace / 2; break; case FlexAlign::SPACE_EVENLY: betweenSpace = validSizeCount_ > 0 ? remainSpace / static_cast(validSizeCount_ + 1) : 0; @@ -411,22 +436,14 @@ void FlexLayoutAlgorithm::CalculateSpace(float remainSpace, float& frontSpace, f } } -void FlexLayoutAlgorithm::PlaceChildren(LayoutWrapper* layoutWrapper, float frontSpace, float betweenSpace, const BaselineProperties& baselineProperties) { +void FlexLayoutAlgorithm::PlaceChildren(LayoutWrapper* layoutWrapper, float frontSpace, float betweenSpace, const BaselineProperties& baselineProperties) +{ float childMainPos = IsStartTopLeft(direction_, TextDirection::LTR) ? frontSpace : mainSize_ - frontSpace; - float childCrossPos = 0.0; + float childCrossPos = 0.0f; auto children = layoutWrapper->GetAllChildrenWithBuild(); for (const auto& child : children) { // if (child->IsIgnored()) { // continue; -// } -// auto flexItem = AceType::DynamicCast(item); -// if (flexItem && flexItem->IsHidden() && !flexItem->GetLayoutSize().IsValid()) { -// continue; -// } -// if (IsNonRelativePosition(item->GetPositionType())) { -// Offset absoluteOffset = PositionLayoutUtils::GetAbsoluteOffset(Claim(this), item); -// item->SetAbsolutePosition(absoluteOffset); -// continue; // } auto alignItem = GetSelfAlign(child); auto textDirection = AdjustTextDirectionByDir(); @@ -472,7 +489,8 @@ void FlexLayoutAlgorithm::PlaceChildren(LayoutWrapper* layoutWrapper, float fron } } -bool FlexLayoutAlgorithm::IsStartTopLeft(FlexDirection direction, TextDirection textDirection) const { +bool FlexLayoutAlgorithm::IsStartTopLeft(FlexDirection direction, TextDirection textDirection) const +{ switch (direction) { case FlexDirection::ROW: return textDirection == TextDirection::LTR; @@ -487,7 +505,8 @@ bool FlexLayoutAlgorithm::IsStartTopLeft(FlexDirection direction, TextDirection } } -FlexAlign FlexLayoutAlgorithm::GetSelfAlign(const RefPtr& layoutWrapper) const { +FlexAlign FlexLayoutAlgorithm::GetSelfAlign(const RefPtr& layoutWrapper) const +{ const auto& flexItemProperty = layoutWrapper->GetLayoutProperty()->GetFlexItemProperty(); const auto& magicItemProperty = layoutWrapper->GetLayoutProperty()->GetMagicItemProperty(); if (!magicItemProperty) { @@ -500,7 +519,8 @@ FlexAlign FlexLayoutAlgorithm::GetSelfAlign(const RefPtr& layoutW } -TextDirection FlexLayoutAlgorithm::AdjustTextDirectionByDir() const { +TextDirection FlexLayoutAlgorithm::AdjustTextDirectionByDir() const +{ auto textDir = TextDirection::RTL; if (direction_ == FlexDirection::ROW_REVERSE) { textDir = textDir == TextDirection::RTL ? TextDirection::LTR : TextDirection::RTL; @@ -508,7 +528,8 @@ TextDirection FlexLayoutAlgorithm::AdjustTextDirectionByDir() const { return textDir; } -FlexDirection FlexLayoutAlgorithm::FlipAxis(FlexDirection direction) const { +FlexDirection FlexLayoutAlgorithm::FlipAxis(FlexDirection direction) const +{ if (direction == FlexDirection::ROW || direction == FlexDirection::ROW_REVERSE) { return FlexDirection::COLUMN; } diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h index 54f23901afb..310dcf797f5 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h @@ -1,9 +1,20 @@ -// -// Created by 陆泽辉 on 2022/8/8. -// +/* + * 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 ARKUI_ACE_ENGINE_FLEX_LAYOUT_ALGORITHM_H -#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_ALGORITHM_H +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_ALGORITHM_H #include "core/components_ng/layout/layout_algorithm.h" #include "core/components/common/layout/constants.h" @@ -76,23 +87,23 @@ private: LayoutConstraintF MakeLayoutConstraint(float mainFlexExtent, const LayoutConstraintF& constraint, bool isStretch, bool supportZero = false) const; LayoutConstraintF MakeLayoutConstraintWithLimit(float minMainLimit, float maxMainLimit, bool isStretch) const; float GetStretchCrossLimit() const; + OptionalSizeF GetCalcSize(float mainSize, float crossSize); - SizeF realSize_; - float mainSize_ = 0.0; - float crossSize_ = 0.0; - float allocatedSize_ = 0.0; - float space_ = 0.0; + OptionalSizeF realSize_; + float mainSize_ = 0.0f; + float crossSize_ = 0.0f; + float selfIdealCrossSize_ = -1.0f; + float allocatedSize_ = 0.0f; + float space_ = 0.0f; bool isCrossInfinite_ = false; - bool useViewPort_ = false; bool stretchToParent_ = false; - float totalFlexWeight_ = 0.0; + float totalFlexWeight_ = 0.0f; int32_t maxDisplayPriority_ = 0; int32_t validSizeCount_ = 0; FlexAlign crossAxisAlign_ = FlexAlign::FLEX_START; FlexAlign mainAxisAlign_ = FlexAlign::FLEX_START; RefPtr layoutWrapper_; - std::list> relativeNodes_; std::list> weightNodes_; std::set> infinityLayoutNodes_; std::map> magicNodes_; @@ -100,8 +111,9 @@ private: FlexLayoutMode layoutMode_ = FlexLayoutMode::FLEX_ITEM_MODE; FlexDirection direction_ = FlexDirection::ROW; friend class LinearLayoutUtils; + ACE_DISALLOW_COPY_AND_MOVE(FlexLayoutAlgorithm); }; } // namespace OHOS::Ace::NG -#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_ALGORITHM_H +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h b/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h index fe13de675f6..11828a37ce3 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_pattern.h @@ -1,9 +1,20 @@ -// -// Created by 陆泽辉 on 2022/8/8. -// +/* + * 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 ARKUI_ACE_ENGINE_FLEX_LAYOUT_PATTERN_H -#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_PATTERN_H +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_PATTERN_H #include "core/components_ng/pattern/pattern.h" #include "core/components_ng/pattern/flex/flex_layout_algorithm.h" @@ -13,18 +24,21 @@ namespace OHOS::Ace::NG { class FlexLayoutPattern : public Pattern { public: - explicit FlexLayoutPattern() = default; + FlexLayoutPattern() = default; ~FlexLayoutPattern() override = default; - RefPtr CreateLayoutProperty() override { + RefPtr CreateLayoutProperty() override + { return MakeRefPtr(); } - RefPtr CreateLayoutAlgorithm() override { + RefPtr CreateLayoutAlgorithm() override + { return MakeRefPtr(); } - bool IsAtomicNode() const override { + bool IsAtomicNode() const override + { return false; } @@ -33,4 +47,4 @@ private: }; } // namespace OHOS::Ace::NG -#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_PATTERN_H +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_property.h b/frameworks/core/components_ng/pattern/flex/flex_layout_property.h index e48c1ca326c..8540418d25b 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_property.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_property.h @@ -1,9 +1,20 @@ -// -// Created by 陆泽辉 on 2022/8/8. -// +/* + * 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 ARKUI_ACE_ENGINE_FLEX_LAYOUT_PROPERTY_H -#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_PROPERTY_H +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_PROPERTY_H #include "base/utils/macros.h" #include "core/components_ng/layout/layout_property.h" @@ -16,18 +27,20 @@ class ACE_EXPORT FlexLayoutProperty : public LayoutProperty { DECLARE_ACE_TYPE(FlexLayoutProperty, LayoutProperty); public: - explicit FlexLayoutProperty() = default; + FlexLayoutProperty() = default; ~FlexLayoutProperty() override = default; - RefPtr Clone() const override { + RefPtr Clone() const override + { auto value = MakeRefPtr(); value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); value->propFlexLayoutAttribute_ = CloneFlexLayoutAttribute(); return value; } - void Reset() override { + void Reset() override + { LayoutProperty::Reset(); ResetFlexLayoutAttribute(); } @@ -38,30 +51,10 @@ public: ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, MainAxisAlign, FlexAlign, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, CrossAxisAlign, FlexAlign, PROPERTY_UPDATE_MEASURE); -// FlexDirection GetFlexDirection() const { -// if (!propFlexLayoutAttribute_) { -// return FlexDirection::ROW; -// } -// return propFlexLayoutAttribute_->GetFlexDirection().value_or(FlexDirection::ROW); -// } - -// FlexAlign GetMainAxisAlign() const { -// if (!propFlexLayoutAttribute_) { -// return FlexAlign::FLEX_START; -// } -// return propFlexLayoutAttribute_->GetMainAxisAlign().value_or(FlexAlign::FLEX_START); -// } - -// FlexAlign GetCrossAxisAlign() const { -// if (!propFlexLayoutAttribute_) { -// return FlexAlign::FLEX_START; -// } -// return propFlexLayoutAttribute_->GetCrossAxisAlign().value_or(FlexAlign::FLEX_START); -// } private: ACE_DISALLOW_COPY_AND_MOVE(FlexLayoutProperty); }; } // namespace OHOS::Ace::NG -#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_PROPERTY_H +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_PROPERTY_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h b/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h index a0f37859268..74a68315369 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_styles.h @@ -1,9 +1,19 @@ -// -// Created by 陆泽辉 on 2022/8/8. -// - -#ifndef ARKUI_ACE_ENGINE_FLEX_LAYOUT_STYLES_H -#define ARKUI_ACE_ENGINE_FLEX_LAYOUT_STYLES_H +/* + * 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_PATTERN_FLEX_FLEX_LAYOUT_STYLES_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_STYLES_H #include "base/geometry/dimension.h" #include "core/components/common/layout/constants.h" @@ -17,4 +27,4 @@ struct FlexLayoutAttribute { }; } // namespace OHOS::Ace::NG -#endif // ARKUI_ACE_ENGINE_FLEX_LAYOUT_STYLES_H +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_FLEX_FLEX_LAYOUT_STYLES_H diff --git a/frameworks/core/components_ng/pattern/flex/flex_view.cpp b/frameworks/core/components_ng/pattern/flex/flex_view.cpp index 2053d70b077..b5dedbb518e 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_view.cpp +++ b/frameworks/core/components_ng/pattern/flex/flex_view.cpp @@ -1,6 +1,18 @@ -// -// Created by 陆泽辉 on 2022/8/4. -// +/* + * 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/pattern/flex/flex_view.h" #include "base/log/log_wrapper.h" diff --git a/frameworks/core/components_ng/pattern/flex/flex_view.h b/frameworks/core/components_ng/pattern/flex/flex_view.h index 0dd17707175..5bb4c770a4d 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_view.h +++ b/frameworks/core/components_ng/pattern/flex/flex_view.h @@ -1,6 +1,17 @@ -// -// Created by 陆泽辉 on 2022/8/4. -// +/* + * 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_PATTERNS_LINEAR_LAYOUT_FLEX_VIEW_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LINEAR_LAYOUT_FLEX_VIEW_H diff --git a/interfaces/napi/kits/router/js_router.cpp b/interfaces/napi/kits/router/js_router.cpp index 76da47a7716..94dc2d84cbc 100644 --- a/interfaces/napi/kits/router/js_router.cpp +++ b/interfaces/napi/kits/router/js_router.cpp @@ -493,6 +493,102 @@ static napi_value JSRouterGetParams(napi_env env, napi_callback_info info) return result; } +static napi_value JSTestSyncFunc(napi_env env, napi_callback_info info) { + size_t argc = 2; + napi_value args[2] = { nullptr }; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + + napi_valuetype valuetype1; + napi_typeof(env, args[1], &valuetype1); + + NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected"); + + double value0; + double value1; + napi_get_value_double(env, args[0], &value0); + napi_get_value_double(env, args[1], &value1); + + napi_value sum; + napi_create_double(env, value0 + value1, &sum); + return sum; +} + +struct AsyncCallbackInfo { + napi_env env = nullptr; + napi_async_work work = nullptr; + napi_deferred deferred = nullptr; + napi_ref callbackRef = nullptr; + double value0; + double value1; + double sum; +}; + +static napi_value JSTestAsyncFunc(napi_env env, napi_callback_info info) { + size_t argc = 3; + napi_value args[3] = { 0 }; + napi_value thisArg = nullptr; + void* data = nullptr; + napi_get_cb_info(env, info, &argc, args, &thisArg, &data); + + auto asyncContext = new AsyncCallbackInfo(); + asyncContext->env = env; + + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + + napi_valuetype valuetype1; + napi_typeof(env, args[1], &valuetype1); + + NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected"); + napi_get_value_double(env, args[0], &asyncContext->value0); + napi_get_value_double(env, args[1], &asyncContext->value1); + + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "JSTestAsyncFunc", NAPI_AUTO_LENGTH, &resourceName); + + napi_value result = nullptr; + if (argc == 3) { + napi_valuetype valuetype2; + napi_typeof(env, args[2], &valuetype2); + NAPI_ASSERT(env, valuetype2 == napi_function, "Wrong argument type. Numbers expected"); + napi_create_reference(env, args[2], 1, &asyncContext->callbackRef); + } else { + napi_create_promise(env, &asyncContext->deferred, &result); + } + napi_create_async_work(env, nullptr, resourceName, [](napi_env env, void* data) { + /** + * 非js线程,用于处理异步计算; + */ + AsyncCallbackInfo* asyncContext = (AsyncCallbackInfo*)data; + double value0 = asyncContext->value0; + double value1 = asyncContext->value1; + asyncContext->sum = value0 + value1; + }, [](napi_env env, napi_status status, void* data) { + /** + * js线程,用于返回异步计算结果; + */ + AsyncCallbackInfo* asyncContext = (AsyncCallbackInfo*)data; + napi_value argv = nullptr; + napi_create_double(env, asyncContext->sum, &argv); + if (asyncContext->callbackRef) { + napi_value callback = nullptr; + napi_value callbackResult = nullptr; + napi_get_reference_value(env, asyncContext->callbackRef, &callback); + napi_call_function(env, nullptr, callback, 1, &argv, &callbackResult); + napi_delete_reference(env, asyncContext->callbackRef); + delete asyncContext; + } else if (asyncContext->deferred) { + napi_resolve_deferred(env, asyncContext->deferred, argv); + } + napi_delete_async_work(env, asyncContext->work); + }, (void*)asyncContext, &asyncContext->work); + napi_queue_async_work(env, asyncContext->work); + return result; +} + static napi_value RouterExport(napi_env env, napi_value exports) { napi_value routerMode = nullptr; @@ -513,6 +609,8 @@ static napi_value RouterExport(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("enableAlertBeforeBackPage", JSRouterEnableAlertBeforeBackPage), DECLARE_NAPI_FUNCTION("disableAlertBeforeBackPage", JSRouterDisableAlertBeforeBackPage), DECLARE_NAPI_FUNCTION("getParams", JSRouterGetParams), + DECLARE_NAPI_FUNCTION("testSyncFunc", JSTestSyncFunc), + DECLARE_NAPI_FUNCTION("testAsyncFunc", JSTestAsyncFunc), DECLARE_NAPI_PROPERTY("RouterMode", routerMode), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(routerDesc) / sizeof(routerDesc[0]), routerDesc)); From 8b6c4dc8c17b3fbc83df35f43520e095649b71f3 Mon Sep 17 00:00:00 2001 From: luzehui Date: Sun, 4 Sep 2022 12:59:09 +0800 Subject: [PATCH 32/35] Modify FlexLayout in weightMode Signed-off-by: luzehui Change-Id: I203f512185d3d2dd00bb7f3da4db1b7fcd8d20fe --- interfaces/napi/kits/router/js_router.cpp | 98 ----------------------- 1 file changed, 98 deletions(-) diff --git a/interfaces/napi/kits/router/js_router.cpp b/interfaces/napi/kits/router/js_router.cpp index 94dc2d84cbc..76da47a7716 100644 --- a/interfaces/napi/kits/router/js_router.cpp +++ b/interfaces/napi/kits/router/js_router.cpp @@ -493,102 +493,6 @@ static napi_value JSRouterGetParams(napi_env env, napi_callback_info info) return result; } -static napi_value JSTestSyncFunc(napi_env env, napi_callback_info info) { - size_t argc = 2; - napi_value args[2] = { nullptr }; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - napi_valuetype valuetype0; - napi_typeof(env, args[0], &valuetype0); - - napi_valuetype valuetype1; - napi_typeof(env, args[1], &valuetype1); - - NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected"); - - double value0; - double value1; - napi_get_value_double(env, args[0], &value0); - napi_get_value_double(env, args[1], &value1); - - napi_value sum; - napi_create_double(env, value0 + value1, &sum); - return sum; -} - -struct AsyncCallbackInfo { - napi_env env = nullptr; - napi_async_work work = nullptr; - napi_deferred deferred = nullptr; - napi_ref callbackRef = nullptr; - double value0; - double value1; - double sum; -}; - -static napi_value JSTestAsyncFunc(napi_env env, napi_callback_info info) { - size_t argc = 3; - napi_value args[3] = { 0 }; - napi_value thisArg = nullptr; - void* data = nullptr; - napi_get_cb_info(env, info, &argc, args, &thisArg, &data); - - auto asyncContext = new AsyncCallbackInfo(); - asyncContext->env = env; - - napi_valuetype valuetype0; - napi_typeof(env, args[0], &valuetype0); - - napi_valuetype valuetype1; - napi_typeof(env, args[1], &valuetype1); - - NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected"); - napi_get_value_double(env, args[0], &asyncContext->value0); - napi_get_value_double(env, args[1], &asyncContext->value1); - - napi_value resourceName = nullptr; - napi_create_string_utf8(env, "JSTestAsyncFunc", NAPI_AUTO_LENGTH, &resourceName); - - napi_value result = nullptr; - if (argc == 3) { - napi_valuetype valuetype2; - napi_typeof(env, args[2], &valuetype2); - NAPI_ASSERT(env, valuetype2 == napi_function, "Wrong argument type. Numbers expected"); - napi_create_reference(env, args[2], 1, &asyncContext->callbackRef); - } else { - napi_create_promise(env, &asyncContext->deferred, &result); - } - napi_create_async_work(env, nullptr, resourceName, [](napi_env env, void* data) { - /** - * 非js线程,用于处理异步计算; - */ - AsyncCallbackInfo* asyncContext = (AsyncCallbackInfo*)data; - double value0 = asyncContext->value0; - double value1 = asyncContext->value1; - asyncContext->sum = value0 + value1; - }, [](napi_env env, napi_status status, void* data) { - /** - * js线程,用于返回异步计算结果; - */ - AsyncCallbackInfo* asyncContext = (AsyncCallbackInfo*)data; - napi_value argv = nullptr; - napi_create_double(env, asyncContext->sum, &argv); - if (asyncContext->callbackRef) { - napi_value callback = nullptr; - napi_value callbackResult = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef, &callback); - napi_call_function(env, nullptr, callback, 1, &argv, &callbackResult); - napi_delete_reference(env, asyncContext->callbackRef); - delete asyncContext; - } else if (asyncContext->deferred) { - napi_resolve_deferred(env, asyncContext->deferred, argv); - } - napi_delete_async_work(env, asyncContext->work); - }, (void*)asyncContext, &asyncContext->work); - napi_queue_async_work(env, asyncContext->work); - return result; -} - static napi_value RouterExport(napi_env env, napi_value exports) { napi_value routerMode = nullptr; @@ -609,8 +513,6 @@ static napi_value RouterExport(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("enableAlertBeforeBackPage", JSRouterEnableAlertBeforeBackPage), DECLARE_NAPI_FUNCTION("disableAlertBeforeBackPage", JSRouterDisableAlertBeforeBackPage), DECLARE_NAPI_FUNCTION("getParams", JSRouterGetParams), - DECLARE_NAPI_FUNCTION("testSyncFunc", JSTestSyncFunc), - DECLARE_NAPI_FUNCTION("testAsyncFunc", JSTestAsyncFunc), DECLARE_NAPI_PROPERTY("RouterMode", routerMode), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(routerDesc) / sizeof(routerDesc[0]), routerDesc)); From d49b3bf15e6283976e26e4deb22db42c02b6dc1c Mon Sep 17 00:00:00 2001 From: luzehui Date: Sun, 4 Sep 2022 14:12:39 +0800 Subject: [PATCH 33/35] Modify FlexLayout in weightMode Signed-off-by: luzehui Change-Id: I87d42809ae2a39489266b3676ddf07faca130540 --- .../core/components_ng/pattern/flex/flex_layout_algorithm.h | 6 +++--- .../components_ng/pattern/text/text_layout_algorithm.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h index 310dcf797f5..4a89e653f93 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h @@ -47,9 +47,9 @@ struct MagicLayoutNode { struct BaselineProperties { - float maxBaselineDistance = 0.0; - float maxDistanceAboveBaseline = 0.0; - float maxDistanceBelowBaseline = 0.0; + float maxBaselineDistance = 0.0f; + float maxDistanceAboveBaseline = 0.0f; + float maxDistanceBelowBaseline = 0.0f; }; class ACE_EXPORT FlexLayoutAlgorithm : public LayoutAlgorithm { diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp index b32d5785aa4..7c5c8e9ee07 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp @@ -45,11 +45,11 @@ std::optional TextLayoutAlgorithm::MeasureContent( TextStyle textStyle = CreateTextStyleUsingTheme(textLayoutProperty->GetFontStyle(), textLayoutProperty->GetTextLineStyle(), themeManager ? themeManager->GetTheme() : nullptr); if (!textStyle.GetAdaptTextSize()) { - if (CreateParagraphAndLayout(textStyle, textLayoutProperty->GetContent().value_or(""), contentConstraint)) { + if (!CreateParagraphAndLayout(textStyle, textLayoutProperty->GetContent().value_or(""), contentConstraint)) { return std::nullopt; } } else { - if (AdaptMinTextSize(textStyle, textLayoutProperty->GetContent().value_or(""), contentConstraint, pipeline)) { + if (!AdaptMinTextSize(textStyle, textLayoutProperty->GetContent().value_or(""), contentConstraint, pipeline)) { return std::nullopt; } } From 96841f5fdc905367ee3b183668245a28770b0fbd Mon Sep 17 00:00:00 2001 From: luzehui Date: Sun, 4 Sep 2022 15:49:16 +0800 Subject: [PATCH 34/35] Modify FlexLayout in weightMode Signed-off-by: luzehui Change-Id: I3b5f023dcbd244a297967a1c23dd15db820141d0 --- frameworks/core/components_ng/pattern/BUILD.gn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 8938405403e..7a83b8dead8 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -25,6 +25,8 @@ build_component_ng("pattern_ng") { "divider/divider_layout_algorithm.cpp", "divider/divider_pattern.cpp", "divider/divider_view.cpp", + "flex/flex_layout_algorithm.cpp", + "flex/flex_view.cpp", "image/image_layout_algorithm.cpp", "image/image_pattern.cpp", "image/image_view.cpp", @@ -32,8 +34,6 @@ build_component_ng("pattern_ng") { "linear_layout/linear_layout_algorithm.cpp", "linear_layout/linear_layout_utils.cpp", "linear_layout/row_view.cpp", - "flex/flex_layout_algorithm.cpp", - "flex/flex_view.cpp", "list/list_item_view.cpp", "list/list_layout_algorithm.cpp", "list/list_paint_method.cpp", From c2c9fabde8321c77e1e329aa7a9a09810df84b6d Mon Sep 17 00:00:00 2001 From: chenxuankai1 Date: Sun, 4 Sep 2022 18:41:29 +0800 Subject: [PATCH 35/35] [ng] grid with only columns/rows template and grid item without any prop Signed-off-by: chenxuankai1 Change-Id: I873b07009b2f943b594effdc804703bad5c571e6 --- .../declarative_frontend/jsview/js_grid.cpp | 45 +- .../jsview/js_grid_item.cpp | 5 + .../core/components_ng/pattern/BUILD.gn | 4 + .../pattern/grid/grid_item_pattern.h | 42 ++ .../pattern/grid/grid_item_view.cpp | 33 ++ .../pattern/grid/grid_item_view.h | 28 ++ .../pattern/grid/grid_layout_algorithm.cpp | 397 ++++++++++++++++++ .../pattern/grid/grid_layout_algorithm.h | 100 +++++ .../pattern/grid/grid_layout_property.h | 68 +++ .../pattern/grid/grid_pattern.cpp | 95 +++++ .../components_ng/pattern/grid/grid_pattern.h | 74 ++++ .../components_ng/pattern/grid/grid_view.cpp | 45 ++ .../components_ng/pattern/grid/grid_view.h | 33 ++ 13 files changed, 963 insertions(+), 6 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/grid/grid_item_pattern.h create mode 100644 frameworks/core/components_ng/pattern/grid/grid_item_view.cpp create mode 100644 frameworks/core/components_ng/pattern/grid/grid_item_view.h create mode 100644 frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.cpp create mode 100644 frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.h create mode 100644 frameworks/core/components_ng/pattern/grid/grid_layout_property.h create mode 100644 frameworks/core/components_ng/pattern/grid/grid_pattern.cpp create mode 100644 frameworks/core/components_ng/pattern/grid/grid_pattern.h create mode 100644 frameworks/core/components_ng/pattern/grid/grid_view.cpp create mode 100644 frameworks/core/components_ng/pattern/grid/grid_view.h diff --git a/frameworks/bridge/declarative_frontend/jsview/js_grid.cpp b/frameworks/bridge/declarative_frontend/jsview/js_grid.cpp index 3a936d4fbff..6486018d844 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_grid.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_grid.cpp @@ -18,6 +18,9 @@ #include "bridge/declarative_frontend/jsview/js_view_common_def.h" #include "core/common/ace_application_info.h" #include "core/common/container.h" +#include "core/components_ng/base/view_abstract.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/grid/grid_view.h" #include "core/components_v2/grid/render_grid_scroll.h" #include "frameworks/bridge/declarative_frontend/engine/functions/js_drag_function.h" #include "frameworks/bridge/declarative_frontend/jsview/js_interactable_view.h" @@ -34,8 +37,20 @@ const std::vector LAYOUT_DIRECTION = { FlexDirection::ROW, FlexDi } // namespace +#define SET_PROP_FOR_NG(propName, propType, propValue) \ + do { \ + if (Container::IsCurrentUseNewPipeline()) { \ + NG::GridView::Set##propName(static_cast(propValue)); \ + return; \ + } \ + } while (0); + void JSGrid::Create(const JSCallbackInfo& info) { + if (Container::IsCurrentUseNewPipeline()) { + NG::GridView::Create(); + return; + } LOGD("Create component: Grid"); std::list> componentChildren; @@ -69,6 +84,10 @@ void JSGrid::Create(const JSCallbackInfo& info) void JSGrid::PopGrid(const JSCallbackInfo& info) { + if (Container::IsCurrentUseNewPipeline()) { + NG::ViewStackProcessor::GetInstance()->PopContainer(); + return; + } ViewStackProcessor::GetInstance()->PopGrid(); } @@ -89,6 +108,7 @@ void JSGrid::UseProxy(const JSCallbackInfo& args) void JSGrid::SetColumnsTemplate(const std::string& value) { + SET_PROP_FOR_NG(ColumnsTemplate, std::string, value); auto component = ViewStackProcessor::GetInstance()->GetMainComponent(); auto grid = AceType::DynamicCast(component); if (grid) { @@ -98,6 +118,7 @@ void JSGrid::SetColumnsTemplate(const std::string& value) void JSGrid::SetRowsTemplate(const std::string& value) { + SET_PROP_FOR_NG(RowsTemplate, std::string, value); auto component = ViewStackProcessor::GetInstance()->GetMainComponent(); auto grid = AceType::DynamicCast(component); if (grid) { @@ -145,6 +166,19 @@ void JSGrid::JsGridHeight(const JSCallbackInfo& info) LOGE("The arg is wrong, it is supposed to have at least 1 argument"); return; } + if (Container::IsCurrentUseNewPipeline()) { + Dimension value; + if (!ParseJsDimensionVp(info[0], value)) { + LOGE("parse height fail for grid, please check."); + return; + } + + if (LessNotEqual(value.Value(), 0.0)) { + value.SetValue(0.0); + } + NG::ViewAbstract::SetHeight(NG::CalcLength(value)); + return; + } JSViewAbstract::JsHeight(info); Dimension height; if (!ParseJsDimensionVp(info[0], height)) { @@ -157,7 +191,6 @@ void JSGrid::JsGridHeight(const JSCallbackInfo& info) } } - void JSGrid::JsOnScrollIndex(const JSCallbackInfo& info) { if (info[0]->IsFunction()) { @@ -367,7 +400,7 @@ void JSGrid::JsOnGridDragEnter(const JSCallbackInfo& info) RefPtr jsOnDragEnterFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); auto onItemDragEnterId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc)]( - const ItemDragInfo& dragInfo) { + const ItemDragInfo& dragInfo) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Grid.onItemDragEnter"); func->ItemDragEnterExecute(dragInfo); @@ -389,7 +422,7 @@ void JSGrid::JsOnGridDragMove(const JSCallbackInfo& info) RefPtr jsOnDragMoveFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); auto onItemDragMoveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc)]( - const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex) { + const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Grid.onItemDragMove"); func->ItemDragMoveExecute(dragInfo, itemIndex, insertIndex); @@ -411,7 +444,7 @@ void JSGrid::JsOnGridDragLeave(const JSCallbackInfo& info) RefPtr jsOnDragLeaveFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); auto onItemDragLeaveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc)]( - const ItemDragInfo& dragInfo, int32_t itemIndex) { + const ItemDragInfo& dragInfo, int32_t itemIndex) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Grid.onItemDragLeave"); func->ItemDragLeaveExecute(dragInfo, itemIndex); @@ -433,7 +466,7 @@ void JSGrid::JsOnGridDragStart(const JSCallbackInfo& info) RefPtr jsOnDragFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); auto onItemDragStartId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragFunc)]( - const ItemDragInfo& dragInfo, int32_t itemIndex) -> RefPtr { + const ItemDragInfo& dragInfo, int32_t itemIndex) -> RefPtr { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, nullptr); auto ret = func->ItemDragStartExecute(dragInfo, itemIndex); if (!ret->IsObject()) { @@ -482,7 +515,7 @@ void JSGrid::JsOnGridDrop(const JSCallbackInfo& info) RefPtr jsOnDropFunc = AceType::MakeRefPtr(JSRef::Cast(info[0])); auto onItemDropId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc)]( - const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex, bool isSuccess) { + const ItemDragInfo& dragInfo, int32_t itemIndex, int32_t insertIndex, bool isSuccess) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Grid.onItemDrop"); func->ItemDropExecute(dragInfo, itemIndex, insertIndex, isSuccess); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_grid_item.cpp b/frameworks/bridge/declarative_frontend/jsview/js_grid_item.cpp index 714488d0919..d4d9dde5983 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_grid_item.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_grid_item.cpp @@ -16,6 +16,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_grid_item.h" #include "core/common/container.h" +#include "core/components_ng/pattern/grid/grid_item_view.h" #include "frameworks/bridge/declarative_frontend/engine/functions/js_mouse_function.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" #include "frameworks/core/pipeline/base/element_register.h" @@ -24,6 +25,10 @@ namespace OHOS::Ace::Framework { void JSGridItem::Create(const JSCallbackInfo& args) { + if (Container::IsCurrentUseNewPipeline()) { + NG::GridItemView::Create(); + return; + } auto container = Container::Current(); if (!container) { LOGE("fail to get container"); diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index 7a83b8dead8..40d8c3747f2 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -27,6 +27,10 @@ build_component_ng("pattern_ng") { "divider/divider_view.cpp", "flex/flex_layout_algorithm.cpp", "flex/flex_view.cpp", + "grid/grid_item_view.cpp", + "grid/grid_layout_algorithm.cpp", + "grid/grid_pattern.cpp", + "grid/grid_view.cpp", "image/image_layout_algorithm.cpp", "image/image_pattern.cpp", "image/image_view.cpp", diff --git a/frameworks/core/components_ng/pattern/grid/grid_item_pattern.h b/frameworks/core/components_ng/pattern/grid/grid_item_pattern.h new file mode 100644 index 00000000000..2bb77465a0d --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_item_pattern.h @@ -0,0 +1,42 @@ +/* + * 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_PATTERNS_GRID_GRID_ITEM_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_ITEM_PATTERN_H + +#include "base/memory/referenced.h" +#include "base/utils/noncopyable.h" +#include "core/components_ng/pattern/pattern.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT GridItemPattern : public Pattern { + DECLARE_ACE_TYPE(GridItemPattern, Pattern); + +public: + GridItemPattern() = default; + ~GridItemPattern() override = default; + + bool IsAtomicNode() const override + { + return false; + } + +private: + ACE_DISALLOW_COPY_AND_MOVE(GridItemPattern); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_ITEM_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/grid/grid_item_view.cpp b/frameworks/core/components_ng/pattern/grid/grid_item_view.cpp new file mode 100644 index 00000000000..5bdf1afa6a3 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_item_view.cpp @@ -0,0 +1,33 @@ +/* + * 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/pattern/grid/grid_item_view.h" + +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/grid/grid_item_pattern.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { + +void GridItemView::Create() +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode( + V2::GRID_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/grid/grid_item_view.h b/frameworks/core/components_ng/pattern/grid/grid_item_view.h new file mode 100644 index 00000000000..0f19c9f31d1 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_item_view.h @@ -0,0 +1,28 @@ +/* + * 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_PATTERNS_GRID_GRID_ITEM_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_ITEM_VIEW_H + +#include "base/utils/macros.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT GridItemView { +public: + static void Create(); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_ITEM_VIEW_H diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.cpp new file mode 100644 index 00000000000..5af37b6cc5f --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.cpp @@ -0,0 +1,397 @@ +/* + * 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/pattern/grid/grid_layout_algorithm.h" + +#include "base/geometry/ng/offset_t.h" +#include "base/utils/utils.h" +#include "core/components_ng/property/layout_constraint.h" +#include "core/components_ng/property/measure_utils.h" + +#ifdef NG_BUILD +#include "ace_shell/shell/common/window_manager.h" +#endif + +namespace OHOS::Ace::NG { + +void GridLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) +{ + auto gridLayoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_VOID(gridLayoutProperty); + + // Step1: Decide size of Grid + Axis axis = gridLayoutInfo_.axis_; + auto idealSize = CreateIdealSize( + gridLayoutProperty->GetLayoutConstraint().value(), axis, gridLayoutProperty->GetMeasureType(), true); + if (GreatOrEqual(GetMainAxisSize(idealSize, axis), Infinity())) { + // TODO: use total height of all children as grid's main size when main size of ideal is infinite + LOGE("size of main axis value is infinity, please check"); + return; + } + layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize); + MinusPaddingToSize(gridLayoutProperty->CreatePaddingAndBorder(), idealSize); + + // Step2: Measure children that can be displayed in viewport of Grid + float mainSize = GetMainAxisSize(idealSize, axis); + float crossSize = GetCrossAxisSize(idealSize, axis); + FillGridViewportAndMeasureChildren(mainSize, crossSize, gridLayoutProperty, layoutWrapper); + StripItemsOutOfViewport(); + layoutWrapper->SetForceSyncRenderTree(); +} + +void GridLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) +{ + auto gridLayoutProperty = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); + CHECK_NULL_VOID(gridLayoutProperty); + auto size = layoutWrapper->GetGeometryNode()->GetFrameSize(); + auto padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder(); + MinusPaddingToSize(padding, size); + auto childFrameOffset = OffsetF(padding.left.value_or(0.0f), padding.top.value_or(0.0f)); + childFrameOffset += gridLayoutProperty->IsVertical() ? OffsetF(0.0f, gridLayoutInfo_.currentOffset_) + : OffsetF(gridLayoutInfo_.currentOffset_, 0.0f); + auto parentOffset = + layoutWrapper->GetGeometryNode()->GetParentGlobalOffset() + layoutWrapper->GetGeometryNode()->GetFrameOffset(); + float crossFrWidth = GetCrossAxisSize(size, gridLayoutInfo_.axis_) / static_cast(crossCount_); + + // For e.g, when a vertical grid has two [GridItem] in first row, [gridMatrix_] is like {[0: {[0: 1fr], [1: 2fr]}]} + // TODO: Support horizontal Grid + float prevLineHeight = 0.0f; + for (const auto& line : gridLayoutInfo_.gridMatrix_) { + auto offset = childFrameOffset + OffsetF(0.0, prevLineHeight); + if (line.second.empty()) { + LOGE("line %{public}d should not be empty, please check.", line.first); + break; + } + float prevItemCrossSize = 0.0f; + for (auto iter = line.second.begin(); iter != line.second.end(); iter++) { + offset += + gridLayoutProperty->IsVertical() ? OffsetF(prevItemCrossSize, 0.0) : OffsetF(0.0, prevItemCrossSize); + auto wrapper = layoutWrapper->GetOrCreateChildByIndex(iter->first); + if (!wrapper) { + LOGE("item wrapper of index: %{public}d is null, please check.", iter->first); + continue; + } + wrapper->GetGeometryNode()->SetFrameOffset(offset); + wrapper->Layout(parentOffset); + prevItemCrossSize = static_cast(iter->second) * crossFrWidth; + } + prevLineHeight += gridLayoutInfo_.lineHeightMap_[line.first]; + } +} + +void GridLayoutAlgorithm::FillGridViewportAndMeasureChildren( + float mainSize, float crossSize, const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper) +{ + float mainLength = gridLayoutInfo_.currentOffset_; + + // Step1: Measure [GridItem] that has been recorded to [gridMatrix_] + MeasureRecordedItems(mainSize, crossSize, gridLayoutProperty, layoutWrapper, mainLength); + + // Step2: When done measure items in record, request new items to fill blank at end + FillBlankAtEnd(mainSize, crossSize, gridLayoutProperty, layoutWrapper, mainLength); + if (gridLayoutInfo_.reachEnd_) { // If it reaches end when [FillBlankAtEnd], modify [currentOffset_] + ModifyCurrentOffsetWhenReachEnd(mainSize); + return; + } + + // Step3: Check if need to fill blank at start (in situation of grid items moving down) + FillBlankAtStart(mainSize, crossSize, gridLayoutProperty, layoutWrapper, mainLength); + if (gridLayoutInfo_.reachStart_) { + gridLayoutInfo_.currentOffset_ = 0.0; + gridLayoutInfo_.prevOffset_ = 0.0; + } +} + +void GridLayoutAlgorithm::FillBlankAtStart(float mainSize, float crossSize, + const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper, float& mainLength) +{ + if (LessOrEqual( + gridLayoutInfo_.currentOffset_, 0.0)) { // If [currentOffset_] is none-positive, it means no blank at start + return; + } + auto blankAtStart = gridLayoutInfo_.currentOffset_; + while (GreatNotEqual(blankAtStart, 0.0)) { + float lineHeight = FillNewLineForward(crossSize, mainSize, gridLayoutProperty, layoutWrapper); + if (GreatNotEqual(lineHeight, 0.0)) { + gridLayoutInfo_.lineHeightMap_[gridLayoutInfo_.startMainLineIndex_] = lineHeight; + blankAtStart -= lineHeight; + continue; + } + gridLayoutInfo_.reachStart_ = true; + break; + } + gridLayoutInfo_.currentOffset_ = blankAtStart; + gridLayoutInfo_.prevOffset_ = gridLayoutInfo_.currentOffset_; +} + +// When a moving up event comes, the [currrentOffset_] may have been reduced too much than the items really need to +// be moved up, so we need to modify [currrentOffset_] accrording to previous position. +void GridLayoutAlgorithm::ModifyCurrentOffsetWhenReachEnd(float mainSize) +{ + // Step1. Calculate total length of all items in viewport. [lengthOfItemsInViewport] must be greater than or equal + // to viewport height + float lengthOfItemsInViewport = 0.0f; + for (auto i = gridLayoutInfo_.startMainLineIndex_; i <= gridLayoutInfo_.endMainLineIndex_; i++) { + lengthOfItemsInViewport += gridLayoutInfo_.lineHeightMap_[i]; + } + + // Step2. Calculate real offset that items can only be moved up by. + float realOffsetToMoveUp = + lengthOfItemsInViewport - mainSize + gridLayoutInfo_.prevOffset_; // Hint: [prevOffset_] is a non-positive value + + // Step3. modify [currentOffset_] + gridLayoutInfo_.currentOffset_ = gridLayoutInfo_.prevOffset_ - realOffsetToMoveUp; + gridLayoutInfo_.prevOffset_ = gridLayoutInfo_.currentOffset_; +} + +void GridLayoutAlgorithm::FillBlankAtEnd(float mainSize, float crossSize, + const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper, float& mainLength) +{ + // When [mainLength] is still less than [mainSize], do [FillNewLineBackward] repeatedly until filling up the lower + // part of the viewport + while (LessNotEqual(mainLength, mainSize)) { + float lineHeight = FillNewLineBackward(crossSize, mainSize, gridLayoutProperty, layoutWrapper); + if (GreatNotEqual(lineHeight, 0.0)) { + mainLength += lineHeight; + continue; + } + gridLayoutInfo_.reachEnd_ = true; + break; + }; +} + +void GridLayoutAlgorithm::MeasureRecordedItems(float mainSize, float crossSize, + const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper, float& mainLength) +{ + currentMainLineIndex_ = gridLayoutInfo_.startMainLineIndex_ - 1; + bool runOutOfRecord = false; + while (LessNotEqual(mainLength, mainSize)) { // Measure grid items row by row + auto gridMatrixIter = gridLayoutInfo_.gridMatrix_.find(++currentMainLineIndex_); + if (gridMatrixIter == gridLayoutInfo_.gridMatrix_.end()) { + runOutOfRecord = true; + break; // If [gridMatrix_] does not contain record of line [currentMainLineIndex_], do [FillNewLineBackward] + } + float lineHeight = -1.0f; + int32_t currentIndex = 0; + // One record is like [0: 1fr] or [1: 2fr] + for (const auto& gridItemRecord : gridMatrixIter->second) { + currentIndex = gridItemRecord.first; + auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); + if (!itemWrapper) { + LOGE("GridItem wrapper of index %{public}u null", currentIndex); + break; + } + itemWrapper->Measure( + MakeMeasureConstraintForGridItem(mainSize, crossSize, gridItemRecord.second, gridLayoutProperty)); + auto itemSize = itemWrapper->GetGeometryNode()->GetFrameSize(); + lineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), lineHeight); + // Record end index. When fill new line, the [endIndex_] will be the first item index to request + gridLayoutInfo_.endIndex_ = gridItemRecord.first; + } + if (lineHeight > 0) { // Means at least one item has been measured + gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = lineHeight; + mainLength += lineHeight; + } + // If a line moves up out of viewport, update [startIndex_], [currentOffset_] and [startMainLineIndex_], and + // delete record in [gridMatrix_] and [lineHeightMap_]. The strip operation of [gridMatrix_] and + // [lineHeightMap_] will take place in [StripItemsOutOfViewport]. + // TODO: inactive items + if (LessOrEqual(mainLength, 0.0)) { + gridLayoutInfo_.currentOffset_ = mainLength; + gridLayoutInfo_.startMainLineIndex_ = currentMainLineIndex_ + 1; + gridLayoutInfo_.startIndex_ = currentIndex + 1; + } + } + // Case 1. if this while-loop breaks due to running out of records, the [currentMainLineIndex_] is larger by 1 than + // real main line index, so reduce 1. + // Case 2. if this while-loop stops due to false result of [LessNotEqual(mainLength, mainSize)], the + // [currentMainLineIndex_] is exactly the real main line index. Update [endMainLineIndex_] when the recorded items + // are done measured. + gridLayoutInfo_.endMainLineIndex_ = runOutOfRecord ? --currentMainLineIndex_ : currentMainLineIndex_; +} + +float GridLayoutAlgorithm::FillNewLineForward( + float crossSize, float mainSize, const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper) +{ + // To make the code more convinient to read, we name a param in situation of vertical, for exacmple: + // 1. [lineHight] means height of a row when the Grid is vertical; + // 2. [lineHight] means width of a column when the Grid is horizontal; + // Other params are also named according to this principle. + float lineHeight = -1.0f; + float measuredItemsWidth = 0.0f; + auto currentIndex = gridLayoutInfo_.startIndex_; + // TODO: need to consider [colunmStart]\[columsEnd] of [GridItem] + // TODO: shoule we use policy of adaptive layout according to size of [GridItem] ? + if (gridLayoutInfo_.startMainLineIndex_ - 1 < 0) { + LOGI("startMainLineIndex: %{public}d is alreay the first line, no forward line to make", + gridLayoutInfo_.startMainLineIndex_); + return -1.0f; + } + gridLayoutInfo_.startMainLineIndex_--; + bool doneCreateNewLine = false; + for (uint32_t i = 0; i < crossCount_; i++) { + if (currentIndex-- < 0) { + break; + } + // Step1. Get wrapper of [GridItem] + auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); + if (!itemWrapper) { + LOGE("GridItem wrapper of index %{public}u null", currentIndex); + break; + } + // Step2. Make constraint and measure child + // TODO: need to consider [colunmStart]\[columsEnd] of [GridItem] + // TODO: need to use [isScrollable_] + itemWrapper->Measure(MakeMeasureConstraintForGridItem(mainSize, crossSize, 1, gridLayoutProperty)); + + // Step3. Measure [GridItem] + auto itemSize = itemWrapper->GetGeometryNode()->GetFrameSize(); + measuredItemsWidth += GetCrossAxisSize(itemSize, gridLayoutInfo_.axis_); + lineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), lineHeight); + // TODO: get [colunmStart]\[columsEnd] of [GridItem] + gridLayoutInfo_.gridMatrix_[gridLayoutInfo_.startMainLineIndex_][currentIndex] = 1; + gridLayoutInfo_.startIndex_ = currentIndex; + doneCreateNewLine = true; + } + // If it fails to create new line when [FillNewLineForward] is called, it means that it reaches start + if (!doneCreateNewLine) { + gridLayoutInfo_.reachStart_ = true; + } + return lineHeight; +} + +float GridLayoutAlgorithm::FillNewLineBackward( + float crossSize, float mainSize, const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper) +{ + // To make the code more convinient to read, we name a param in situation of vertical, for exacmple: + // 1. [lineHight] means height of a row when the Grid is vertical; + // 2. [lineHight] means width of a column when the Grid is horizontal; + // Other params are also named according to this principle. + float lineHeight = -1.0f; + float measuredItemsWidth = 0.0f; + auto currentIndex = gridLayoutInfo_.endIndex_ + 1; + currentMainLineIndex_++; // if it fails to fill a new line backward, do [currentMainLineIndex_--] + // TODO: need to consider [colunmStart]\[columsEnd] of [GridItem] + // TODO: shoule we use policy of adaptive layout according to size of [GridItem] ? + bool doneFillLine = false; + for (uint32_t i = 0; i < crossCount_; i++) { + // Step1. Get wrapper of [GridItem] + auto itemWrapper = layoutWrapper->GetOrCreateChildByIndex(currentIndex); + if (!itemWrapper) { + LOGE("GridItem wrapper of index %{public}u null", currentIndex); + break; + } + // Step2. Make constraint and measure child + // TODO: need to consider [colunmStart]\[columsEnd] of [GridItem] + // TODO: need to use [isScrollable_] + itemWrapper->Measure(MakeMeasureConstraintForGridItem(mainSize, crossSize, 1, gridLayoutProperty)); + + // Step3. Measure [GridItem] + auto itemSize = itemWrapper->GetGeometryNode()->GetFrameSize(); + measuredItemsWidth += GetCrossAxisSize(itemSize, gridLayoutInfo_.axis_); + lineHeight = std::max(GetMainAxisSize(itemSize, gridLayoutInfo_.axis_), lineHeight); + // TODO: get [colunmStart]\[columsEnd] of [GridItem] + gridLayoutInfo_.gridMatrix_[currentMainLineIndex_][currentIndex] = 1; + gridLayoutInfo_.endIndex_ = currentIndex; + currentIndex++; + doneFillLine = true; + } + if (!doneFillLine) { + // If it fails to fill a new line backward, do [currentMainLineIndex_--] + currentMainLineIndex_--; + } else { + gridLayoutInfo_.lineHeightMap_[currentMainLineIndex_] = lineHeight; + gridLayoutInfo_.endMainLineIndex_ = currentMainLineIndex_; + } + return lineHeight; +} +void GridLayoutAlgorithm::StripItemsOutOfViewport() +{ + // Erase records that are out of viewport + // TODO: add cache and inactive item + // 1. Erase records that are on top of viewport + if (gridLayoutInfo_.lineHeightMap_.empty() || gridLayoutInfo_.gridMatrix_.empty()) { + return; + } + int32_t startIndexInMap = gridLayoutInfo_.lineHeightMap_.begin()->first; + for (int32_t i = startIndexInMap; i < gridLayoutInfo_.startMainLineIndex_; i++) { + gridLayoutInfo_.lineHeightMap_.erase(i); + gridLayoutInfo_.gridMatrix_.erase(i); + } + + // 2. Erase records that are under viewport + if (gridLayoutInfo_.lineHeightMap_.empty() || gridLayoutInfo_.gridMatrix_.empty()) { + return; + } + for (int32_t i = gridLayoutInfo_.endMainLineIndex_ + 1; + i < static_cast(gridLayoutInfo_.lineHeightMap_.size()); i++) { + gridLayoutInfo_.lineHeightMap_.erase(i); + gridLayoutInfo_.gridMatrix_.erase(i); + } +} + +LayoutConstraintF GridLayoutAlgorithm::MakeMeasureConstraintForGridItem(float mainSize, float crossSize, + uint32_t itemFractionCount, const RefPtr& gridLayoutProperty) const +{ + float itemMainSize = + gridLayoutProperty->IsConfiguredScrollable() ? Infinity() : mainSize / static_cast(mainCount_); + float fractionWidth = crossSize / static_cast(crossCount_); + float itemCrossSize = fractionWidth * static_cast(itemFractionCount); + SizeF itemIdealSize = + gridLayoutProperty->IsVertical() ? SizeF(itemCrossSize, itemMainSize) : SizeF(itemMainSize, itemCrossSize); + auto itemConstraint = gridLayoutProperty->CreateChildConstraint(); + + // The percent size of GridItem is based on the fraction size, for e.g., if a GridItem has width of "50%" in Grid + // configured with columnsTemplate = "1fr 1fr", rowsTemplate = "1fr 1fr", then tht GridItem width = [width of 1fr] * + // 50% + // [itemFractionCount] is now only in direction of cross axis + // TODO: consider rowStart/rowEnd + float widthPercentBase = + GreatOrEqual(crossCount_, Infinity()) + ? itemConstraint.percentReference.Width() + : itemConstraint.percentReference.Width() / static_cast(crossCount_ * itemFractionCount); + float heightPercentBase = GreatOrEqual(mainCount_, Infinity()) + ? itemConstraint.percentReference.Height() + : itemConstraint.percentReference.Height() / static_cast(mainCount_); + itemConstraint.percentReference = SizeF(widthPercentBase, heightPercentBase); + itemConstraint.maxSize = itemIdealSize; + return itemConstraint; +} + +GridLayoutInfo GridLayoutAlgorithm::GetGridLayoutInfo() +{ + return std::move(gridLayoutInfo_); +} + +// only for debug use +void GridLayoutAlgorithm::PrintGridMatrix(const std::map>& gridMatrix) +{ + for (const auto& record : gridMatrix) { + for (const auto& item : record.second) { + LOGD("grid matrix -- line: %{public}d, item: %{public}d, fr: %{public}d", record.first, item.first, + item.second); + } + } +} + +// only for debug use +void GridLayoutAlgorithm::PrintLineHeightMap(const std::map& lineHeightMap) +{ + for (const auto& record : lineHeightMap) { + LOGD("line height -- line: %{public}d, lineHeight: %{public}f", record.first, record.second); + } +} + +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.h b/frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.h new file mode 100644 index 00000000000..a707c9ae814 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_algorithm.h @@ -0,0 +1,100 @@ +/* + * 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_PATTERN_GRID_GRID_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_LAYOUT_ALGORITHM_H + +#include "core/components_ng/layout/box_layout_algorithm.h" +#include "core/components_ng/layout/layout_wrapper.h" +#include "core/components_ng/pattern/grid/grid_layout_property.h" + +namespace OHOS::Ace::NG { + +// Try not to add more variables in [GridLayoutInfo] because the more state variables, the more problematic and the +// harder it is to maintain +struct GridLayoutInfo { + Axis axis_ = Axis::VERTICAL; + + float currentOffset_ = 0.0f; + float prevOffset_ = 0.0f; + + // index of first and last GridItem in viewport + int32_t startIndex_ = 0; + int32_t endIndex_ = -1; + + // index of first row and last row in viewport (assuming it's a vertical Grid) + int32_t startMainLineIndex_ = 0; + int32_t endMainLineIndex_ = 0; + + bool reachEnd_ = false; + bool reachStart_ = false; + + // in vertical grid, this map is like: [rowIndex: [itemIndex: fractionCount], [itemIndex: fractionCount]] + // for e.g, when a vertical grid has two [GridItem]s in first row, [gridMatrix_] is like [0: [0: 1fr], [1: 2fr]] + std::map> gridMatrix_; + // in vertical grid, this map is like: [rowIndex: rowHeight] + std::map lineHeightMap_; +}; + +class ACE_EXPORT GridLayoutAlgorithm : public LayoutAlgorithm { + DECLARE_ACE_TYPE(GridLayoutAlgorithm, LayoutAlgorithm); + +public: + GridLayoutAlgorithm(GridLayoutInfo gridLayoutInfo, uint32_t crossCount, uint32_t mainCount) + : gridLayoutInfo_(std::move(gridLayoutInfo)), crossCount_(crossCount), mainCount_(mainCount) {}; + ~GridLayoutAlgorithm() override = default; + + void Measure(LayoutWrapper* layoutWrapper) override; + void Layout(LayoutWrapper* layoutWrapper) override; + + GridLayoutInfo GetGridLayoutInfo(); + + static void PrintGridMatrix(const std::map>& gridMatrix); + static void PrintLineHeightMap(const std::map& lineHeightMap); + +private: + void FillGridViewportAndMeasureChildren(float mainSize, float crossSize, + const RefPtr& gridLayoutProperty, LayoutWrapper* layoutWrapper); + void MeasureRecordedItems(float mainSize, float crossSize, const RefPtr& gridLayoutProperty, + LayoutWrapper* layoutWrapper, float& mainLength); + + // fill end of viewport + void FillBlankAtStart(float mainSize, float crossSize, const RefPtr& gridLayoutProperty, + LayoutWrapper* layoutWrapper, float& mainLength); + float FillNewLineForward(float crossSize, float mainSize, const RefPtr& gridLayoutProperty, + LayoutWrapper* layoutWrapper); + + // fill start of viewport + void FillBlankAtEnd(float mainSize, float crossSize, const RefPtr& gridLayoutProperty, + LayoutWrapper* layoutWrapper, float& mainLength); + float FillNewLineBackward(float crossSize, float mainSize, const RefPtr& gridLayoutProperty, + LayoutWrapper* layoutWrapper); + + LayoutConstraintF MakeMeasureConstraintForGridItem(float mainSize, float crossSize, uint32_t itemFractionCount, + const RefPtr& gridLayoutProperty) const; + void StripItemsOutOfViewport(); + void ModifyCurrentOffsetWhenReachEnd(float mainSize); + + GridLayoutInfo gridLayoutInfo_; + + uint32_t crossCount_ = 0; + uint32_t mainCount_ = 0; + int32_t currentMainLineIndex_ = 0; // it equals to row index in vertical grid + + ACE_DISALLOW_COPY_AND_MOVE(GridLayoutAlgorithm); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/grid/grid_layout_property.h b/frameworks/core/components_ng/pattern/grid/grid_layout_property.h new file mode 100644 index 00000000000..29e7ef7c918 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_layout_property.h @@ -0,0 +1,68 @@ +/* + * 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_PATTERN_GRID_GRID_LAYOUT_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_LAYOUT_PROPERTY_H + +#include "core/components_ng/layout/layout_property.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT GridLayoutProperty : public LayoutProperty { + DECLARE_ACE_TYPE(GridLayoutProperty, LayoutProperty); + +public: + GridLayoutProperty() = default; + ~GridLayoutProperty() override = default; + + RefPtr Clone() const override + { + auto value = MakeRefPtr(); + value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); + value->propColumnsTemplate_ = CloneColumnsTemplate(); + value->propColumnsTemplate_ = CloneColumnsTemplate(); + return value; + } + + void Reset() override + { + LayoutProperty::Reset(); + ResetColumnsTemplate(); + ResetRowsTemplate(); + } + bool IsVertical() const + { + bool columnsTemplateValid = propColumnsTemplate_.has_value() && !propColumnsTemplate_.value().empty(); + bool rowsTemplateValid = propRowsTemplate_.has_value() && !propRowsTemplate_.value().empty(); + return columnsTemplateValid || + (!columnsTemplateValid && !rowsTemplateValid); // TODO: take layoutDirection into account + } + bool IsConfiguredScrollable() const + { + bool columnsTemplateSet = !propColumnsTemplate_.value_or("").empty(); + bool rowsTemplateSet = !propRowsTemplate_.value_or("").empty(); + bool verticalScrollable = (columnsTemplateSet && !rowsTemplateSet); + bool horizontalScrollable = (!columnsTemplateSet && rowsTemplateSet); + return verticalScrollable || horizontalScrollable; + } + + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(ColumnsTemplate, std::string, PROPERTY_UPDATE_LAYOUT); + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(RowsTemplate, std::string, PROPERTY_UPDATE_LAYOUT); + +private: + ACE_DISALLOW_COPY_AND_MOVE(GridLayoutProperty); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_GRID_LAYOUT_PROPERTY_H diff --git a/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp b/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp new file mode 100644 index 00000000000..c26c66065e6 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_pattern.cpp @@ -0,0 +1,95 @@ +/* + * 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/pattern/grid/grid_pattern.h" + +namespace OHOS::Ace::NG { + +void GridPattern::OnAttachToFrameNode() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + host->GetRenderContext()->SetClipToFrame(true); +} + +void GridPattern::OnModifyDone() +{ + auto gridLayoutProperty = GetLayoutProperty(); + CHECK_NULL_VOID(gridLayoutProperty); + gridLayoutInfo_.axis_ = gridLayoutProperty->IsVertical() ? Axis::VERTICAL : Axis::HORIZONTAL; + AddScrollEvent(); +} + +void GridPattern::AddScrollEvent() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto hub = host->GetEventHub(); + CHECK_NULL_VOID(hub); + auto gestureHub = hub->GetOrCreateGestureEventHub(); + CHECK_NULL_VOID(gestureHub); + if (scrollableEvent_) { + gestureHub->RemoveScrollableEvent(scrollableEvent_); + } + scrollableEvent_ = MakeRefPtr(gridLayoutInfo_.axis_); + auto scrollCallback = [weak = WeakClaim(this)](double offset, int32_t source) { + auto gridPattern = weak.Upgrade(); + if (!gridPattern) { + LOGE("grid pattern upgrade fail when try handle scroll event."); + return false; + } + return gridPattern->UpdateScrollPosition(static_cast(offset), source); + }; + scrollableEvent_->SetScrollPositionCallback(std::move(scrollCallback)); + gestureHub->AddScrollableEvent(scrollableEvent_); +} + +bool GridPattern::UpdateScrollPosition(float offset, int32_t source) +{ + auto host = GetHost(); + CHECK_NULL_RETURN(host, false); + // When finger moves down, offset is positive. + // When finger moves up, offset is negative. + if (gridLayoutInfo_.reachEnd_) { + if (LessOrEqual(offset, 0)) { + return false; + } + gridLayoutInfo_.reachEnd_ = false; + } + if (gridLayoutInfo_.reachStart_) { + if (GreatOrEqual(offset, 0.0)) { + return false; + } + gridLayoutInfo_.reachStart_ = false; + } + gridLayoutInfo_.currentOffset_ += offset; + host->MarkDirtyNode(PROPERTY_REQUEST_NEW_CHILD_NODE); + return true; +} + +bool GridPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) +{ + if (skipMeasure && skipLayout) { + return false; + } + auto layoutAlgorithmWrapper = DynamicCast(dirty->GetLayoutAlgorithm()); + CHECK_NULL_RETURN(layoutAlgorithmWrapper, false); + auto gridLayoutAlgorithm = DynamicCast(layoutAlgorithmWrapper->GetLayoutAlgorithm()); + CHECK_NULL_RETURN(gridLayoutAlgorithm, false); + gridLayoutInfo_ = gridLayoutAlgorithm->GetGridLayoutInfo(); + return false; +} + +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/grid/grid_pattern.h b/frameworks/core/components_ng/pattern/grid/grid_pattern.h new file mode 100644 index 00000000000..943e7db823f --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_pattern.h @@ -0,0 +1,74 @@ +/* + * 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_PATTERNS_GRID_GRID_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_PATTERN_H + +#include "base/memory/referenced.h" +#include "core/components_ng/pattern/grid/grid_layout_algorithm.h" +#include "core/components_ng/pattern/grid/grid_layout_property.h" +#include "core/components_ng/pattern/pattern.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT GridPattern : public Pattern { + DECLARE_ACE_TYPE(GridPattern, Pattern); + +public: + GridPattern() = default; + ~GridPattern() override = default; + + bool IsAtomicNode() const override + { + return false; + } + + RefPtr CreateLayoutProperty() override + { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override + { + auto gridLayoutProperty = GetLayoutProperty(); + CHECK_NULL_RETURN(gridLayoutProperty, nullptr); + std::vector cols; + StringUtils::StringSplitter(gridLayoutProperty->GetColumnsTemplate().value_or(""), ' ', cols); + std::vector rows; + StringUtils::StringSplitter(gridLayoutProperty->GetRowsTemplate().value_or(""), ' ', rows); + auto crossCount = cols.empty() ? Infinity() : cols.size(); + auto mainCount = rows.empty() ? Infinity() : rows.size(); + if (!gridLayoutProperty->IsVertical()) { + std::swap(crossCount, mainCount); + } + return MakeRefPtr(gridLayoutInfo_, crossCount, mainCount); + } + +private: + void OnAttachToFrameNode() override; + void OnModifyDone() override; + void AddScrollEvent(); + bool UpdateScrollPosition(float offset, int32_t source); + bool OnDirtyLayoutWrapperSwap(const RefPtr& dirty, bool skipMeasure, bool skipLayout) override; + + GridLayoutInfo gridLayoutInfo_; + RefPtr scrollableEvent_; + + ACE_DISALLOW_COPY_AND_MOVE(GridPattern); +}; + +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/grid/grid_view.cpp b/frameworks/core/components_ng/pattern/grid/grid_view.cpp new file mode 100644 index 00000000000..4300c5dd8c0 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_view.cpp @@ -0,0 +1,45 @@ +/* + * 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/pattern/grid/grid_view.h" + +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/grid/grid_layout_property.h" +#include "core/components_ng/pattern/grid/grid_pattern.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { + +void GridView::Create() +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = + FrameNode::GetOrCreateFrameNode(V2::GRID_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); +} + +void GridView::SetColumnsTemplate(const std::string& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(GridLayoutProperty, ColumnsTemplate, value); +} + +void GridView::SetRowsTemplate(const std::string& value) +{ + ACE_UPDATE_LAYOUT_PROPERTY(GridLayoutProperty, RowsTemplate, value); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/grid/grid_view.h b/frameworks/core/components_ng/pattern/grid/grid_view.h new file mode 100644 index 00000000000..e4d75a04cbc --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid/grid_view.h @@ -0,0 +1,33 @@ +/* + * 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_PATTERNS_GRIF_GRID_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRIF_GRID_VIEW_H + +#include + +#include "base/utils/macros.h" +#include "core/components/common/layout/constants.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT GridView { +public: + static void Create(); + static void SetColumnsTemplate(const std::string& value); + static void SetRowsTemplate(const std::string& value); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRIF_GRID_VIEW_H