diff --git a/frameworks/bridge/declarative_frontend/jsview/js_grid_container.cpp b/frameworks/bridge/declarative_frontend/jsview/js_grid_container.cpp index b8a440095d7d8ae27aa4c0e6da8663a2f80100d7..5b670a61bae13de156e0a2d4b497716ed8e2f6c2 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_grid_container.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_grid_container.cpp @@ -18,6 +18,7 @@ #include "base/log/ace_trace.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" #include "frameworks/core/components/common/layout/grid_system_manager.h" +#include "frameworks/core/components_ng/pattern/grid_container/grid_container_view.h" namespace OHOS::Ace::Framework { @@ -25,11 +26,7 @@ thread_local std::vector> JSGridContainer::gridContain void JSGridContainer::Create(const JSCallbackInfo& info) { - JSColumn::SetInspectorTag("GridContainer"); - JSColumn::Create(info); - JSColumn::ClearInspectorTag(); GridContainerInfo::Builder gridContainerInfoBuilder; - if (info.Length() > 0 && info[0]->IsObject()) { JSRef obj = JSRef::Cast(info[0]); @@ -58,8 +55,17 @@ void JSGridContainer::Create(const JSCallbackInfo& info) gridContainerInfoBuilder.SetMarginRight(dim); } } - auto gridContainerInfo = gridContainerInfoBuilder.Build(); + + if (Container::IsCurrentUseNewPipeline()) { + NG::GridContainerView::Create(gridContainerInfo); + return; + } + + JSColumn::SetInspectorTag("GridContainer"); + JSColumn::Create(info); + JSColumn::ClearInspectorTag(); + gridContainerStack_.emplace_back(gridContainerInfo); ViewStackProcessor::GetInstance()->GetBoxComponent()->SetGridLayoutInfo(gridContainerInfo); @@ -72,7 +78,9 @@ void JSGridContainer::Create(const JSCallbackInfo& info) void JSGridContainer::Pop() { - gridContainerStack_.pop_back(); + if (!Container::IsCurrentUseNewPipeline()) { + gridContainerStack_.pop_back(); + } JSColumn::Pop(); } diff --git a/frameworks/bridge/declarative_frontend/jsview/js_grid_container.h b/frameworks/bridge/declarative_frontend/jsview/js_grid_container.h index 4a9e4dc469034dcf2026e1260520d482f8ca2475..4a89d3b0600f95014ba352f4ab7ee49fddffaba7 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_grid_container.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_grid_container.h @@ -31,6 +31,12 @@ public: static void Pop(); private: + /* + * GridContainer layout info is stored in box component in non-declarative_fronted bridge instead of + * creating a new component. + * Using thread_local stack is a compromise for compatibility, as child node cannot get info from its ancestors. + * In NG framework, layout info is stored in a frameNode and this stack is obsoleted. + */ static thread_local std::vector> gridContainerStack_; }; diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index bb0c79b4a082e0b834f5542ae3b5c568c9275ff2..833ebff984a7f9b2e3d87399ffd436c4c9a02c4e 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -3682,9 +3682,14 @@ void JSViewAbstract::JsGridSpan(const JSCallbackInfo& info) if (!CheckJSCallbackInfo("JsGridSpan", info, checkList)) { return; } + auto span = info[0]->ToNumber(); + + if (Container::IsCurrentUseNewPipeline()) { + NG::ViewAbstract::SetGrid(span, std::nullopt); + return; + } auto gridContainerInfo = JSGridContainer::GetContainer(); if (gridContainerInfo != nullptr) { - auto span = info[0]->ToNumber(); auto builder = ViewStackProcessor::GetInstance()->GetBoxComponent()->GetGridColumnInfoBuilder(); builder->SetParent(gridContainerInfo); builder->SetColumns(span); @@ -3693,16 +3698,20 @@ void JSViewAbstract::JsGridSpan(const JSCallbackInfo& info) void JSViewAbstract::JsGridOffset(const JSCallbackInfo& info) { - if (info.Length() < 1) { - LOGE("The arg is wrong, it is supposed to have at least 1 arguments"); + std::vector checkList { JSCallbackInfoType::NUMBER }; + if (!CheckJSCallbackInfo("JsGridOffset", info, checkList)) { + return; + } + auto offset = info[0]->ToNumber(); + if (Container::IsCurrentUseNewPipeline()) { + NG::ViewAbstract::SetGrid(std::nullopt, offset); return; } auto gridContainerInfo = JSGridContainer::GetContainer(); - if (info[0]->IsNumber() && gridContainerInfo != nullptr) { + if (gridContainerInfo != nullptr) { auto builder = ViewStackProcessor::GetInstance()->GetBoxComponent()->GetGridColumnInfoBuilder(); builder->SetParent(gridContainerInfo); - int32_t offset = info[0]->ToNumber(); builder->SetOffset(offset); } } @@ -3733,6 +3742,25 @@ void JSViewAbstract::JsUseSizeType(const JSCallbackInfo& info) if (!CheckJSCallbackInfo("JsUseSizeType", info, checkList)) { return; } + JSRef sizeObj = JSRef::Cast(info[0]); + // keys order must be strictly refer to GridSizeType + const char* keys[] = { "", "xs", "sm", "md", "lg" }; + + if (Container::IsCurrentUseNewPipeline()) { + for (uint32_t i = 1; i < sizeof(keys) / sizeof(const char*); i++) { + JSRef val = sizeObj->GetProperty(keys[i]); + if (val->IsNull() || val->IsEmpty()) { + continue; + } + uint32_t span = 0; + int32_t offset = 0; + if (ParseSpanAndOffset(val, span, offset)) { + NG::ViewAbstract::SetGrid(span, offset, static_cast(i)); + } + } + return; + } + auto gridContainerInfo = JSGridContainer::GetContainer(); if (gridContainerInfo == nullptr) { LOGE("No valid grid container."); @@ -3740,10 +3768,6 @@ void JSViewAbstract::JsUseSizeType(const JSCallbackInfo& info) } auto builder = ViewStackProcessor::GetInstance()->GetBoxComponent()->GetGridColumnInfoBuilder(); builder->SetParent(gridContainerInfo); - - JSRef sizeObj = JSRef::Cast(info[0]); - // keys order must be strictly refer to GridSizeType - const char* keys[] = { "", "xs", "sm", "md", "lg" }; for (uint32_t i = 1; i < sizeof(keys) / sizeof(const char*); i++) { JSRef val = sizeObj->GetProperty(keys[i]); if (val->IsNull() || val->IsEmpty()) { diff --git a/frameworks/core/components/common/layout/grid_column_info.h b/frameworks/core/components/common/layout/grid_column_info.h index e416d0e585a65f3e8fe63e2385437da1e83dc793..c02a5479786925ff1502c64c6533b4ea4dff245a 100644 --- a/frameworks/core/components/common/layout/grid_column_info.h +++ b/frameworks/core/components/common/layout/grid_column_info.h @@ -66,6 +66,8 @@ public: SetMdSizeColumn(column, offset); } else if (type == GridSizeType::LG) { SetLgSizeColumn(column, offset); + } else if (type == GridSizeType::UNDEFINED) { + SetColumns(column); } } diff --git a/frameworks/core/components/common/layout/grid_container_info.cpp b/frameworks/core/components/common/layout/grid_container_info.cpp index e5e257d5bef8e4d3a7e2f16c96e10d57e093d133..7e5864ea2630a1397c8d771596730d6060cf5d05 100644 --- a/frameworks/core/components/common/layout/grid_container_info.cpp +++ b/frameworks/core/components/common/layout/grid_container_info.cpp @@ -27,9 +27,8 @@ const T& GetValue(const T& current, const T& system, const T& defaultValue) { if (current == defaultValue) { return system; - } else { - return current; } + return current; } void GridContainerInfo::BuildColumnWidth() @@ -66,7 +65,8 @@ void GridContainerInfo::BuildColumnWidth(double width) double gutterWidth = GetValue(gutterWidth_, systemGridInfo.gutter, UNDEFINED_DIMENSION).ConvertToPx(dipScale); double marginLeft = GetValue(marginLeft_, systemGridInfo.margin, UNDEFINED_DIMENSION).ConvertToPx(dipScale); double marginRight = GetValue(marginRight_, systemGridInfo.margin, UNDEFINED_DIMENSION).ConvertToPx(dipScale); - double padding = paddingLeft_.ConvertToPx(dipScale) + paddingRight_.ConvertToPx(dipScale); + double padding = GetValue(paddingLeft_, Dimension(), UNDEFINED_DIMENSION).ConvertToPx(dipScale) + + GetValue(paddingRight_, Dimension(), UNDEFINED_DIMENSION).ConvertToPx(dipScale); columnWidth_ = (width - marginLeft - marginRight - padding - (columns - 1) * gutterWidth) / columns; LOGD("width = %{public}f, columns: %{public}d columnWidth: %{public}f gutterWidth: %{public}f marginLeft: " diff --git a/frameworks/core/components/common/layout/grid_container_info.h b/frameworks/core/components/common/layout/grid_container_info.h index d72fb8093c15ac549f903e3ae10a8c4ea52ef9e8..63141e5c04a56ff75284dddea1f2faf85bd4da01 100644 --- a/frameworks/core/components/common/layout/grid_container_info.h +++ b/frameworks/core/components/common/layout/grid_container_info.h @@ -16,6 +16,8 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_LAYOUT_GRID_CONTAINER_INFO_H #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_LAYOUT_GRID_CONTAINER_INFO_H +#include + #include "base/geometry/dimension.h" #include "core/components/common/layout/grid_layout_info.h" @@ -90,6 +92,11 @@ public: private: RefPtr containerInfo_; }; + + GridContainerInfo(const GridContainerInfo& info) + { + *this = info; + } ~GridContainerInfo() override = default; double GetColumnWidth() const @@ -112,6 +119,38 @@ public: */ void ACE_EXPORT BuildColumnWidth(); void BuildColumnWidth(double width); + bool operator==(const GridContainerInfo& info) const + { + if (&info == this) { + return true; + } + + return ((templateType_ == info.templateType_) && (currentSizeType_ == info.currentSizeType_) && + (sizeType_ == info.sizeType_) && (columns_ == info.columns_) && (gutterWidth_ == info.gutterWidth_) && + (marginLeft_ == info.marginLeft_) && (marginRight_ == info.marginRight_) && + (paddingLeft_ == info.paddingLeft_) && (paddingRight_ == info.paddingRight_) && + (containerWidth_ == info.containerWidth_) && (columnWidth_ == info.columnWidth_) && + (columnType_ == info.columnType_)); + } + + GridContainerInfo& operator=(const GridContainerInfo& info) + { + if (&info != this) { + templateType_ = info.templateType_; + currentSizeType_ = info.currentSizeType_; + sizeType_ = info.sizeType_; + columns_ = info.columns_; + gutterWidth_ = info.gutterWidth_; + marginLeft_ = info.marginLeft_; + marginRight_ = info.marginRight_; + paddingLeft_ = info.paddingLeft_; + paddingRight_ = info.paddingRight_; + containerWidth_ = info.containerWidth_; + columnWidth_ = info.columnWidth_; + columnType_ = info.columnType_; + } + return *this; + } private: GridContainerInfo() = default; diff --git a/frameworks/core/components_ng/base/view_abstract.cpp b/frameworks/core/components_ng/base/view_abstract.cpp index 910ecb0841952721701e621ff2dfad8467dbd834..3ae00780730c9d2e1757163d51a8d8fe844ed0bb 100644 --- a/frameworks/core/components_ng/base/view_abstract.cpp +++ b/frameworks/core/components_ng/base/view_abstract.cpp @@ -496,6 +496,16 @@ void ViewAbstract::SetInspectorId(const std::string& inspectorId) frameNode->UpdateInspectorId(inspectorId); } +void ViewAbstract::SetGrid(std::optional span, std::optional offset, GridSizeType type) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto layoutProperty = frameNode->GetLayoutProperty(); + CHECK_NULL_VOID(layoutProperty); + // frame node is mounted to parent when pop from stack later, no grid-container is added here + layoutProperty->UpdateGridProperty(span, offset, type); +} + void ViewAbstract::Pop() { ViewStackProcessor::GetInstance()->Pop(); diff --git a/frameworks/core/components_ng/base/view_abstract.h b/frameworks/core/components_ng/base/view_abstract.h index c743870327edcdd734438fb60e88497297498493..c5cf6a6923c85e134162e7c107ca376901318e96 100644 --- a/frameworks/core/components_ng/base/view_abstract.h +++ b/frameworks/core/components_ng/base/view_abstract.h @@ -79,6 +79,8 @@ public: static void SetAlign(Alignment alignment); static void SetAlignRules(const std::map& alignRules); static void SetVisibility(VisibleType visible); + static void SetGrid( + std::optional span, std::optional offset, GridSizeType type = GridSizeType::UNDEFINED); // position static void SetPosition(const OffsetT& value); diff --git a/frameworks/core/components_ng/layout/layout_property.cpp b/frameworks/core/components_ng/layout/layout_property.cpp index 0c7f1534bf668d6f343e33ea70206aa4ac1b8c03..8bd063793bdf7aac985eb23207cf83071ca5360e 100644 --- a/frameworks/core/components_ng/layout/layout_property.cpp +++ b/frameworks/core/components_ng/layout/layout_property.cpp @@ -24,9 +24,11 @@ #include "core/components_ng/property/calc_length.h" #include "core/components_ng/property/layout_constraint.h" #include "core/components_ng/property/measure_utils.h" +#include "core/components_v2/inspector/inspector_constants.h" #include "core/pipeline_ng/pipeline_context.h" namespace OHOS::Ace::NG { + void LayoutProperty::Reset() { layoutConstraint_.reset(); @@ -63,6 +65,9 @@ void LayoutProperty::Clone(RefPtr layoutProperty) const void LayoutProperty::UpdateLayoutProperty(const LayoutProperty* layoutProperty) { layoutConstraint_ = layoutProperty->layoutConstraint_; + if (layoutProperty->gridProperty_) { + gridProperty_ = std::make_unique(*layoutProperty->gridProperty_); + } if (layoutProperty->calcLayoutConstraint_) { calcLayoutConstraint_ = std::make_unique(*layoutProperty->calcLayoutConstraint_); } @@ -179,6 +184,25 @@ void LayoutProperty::CheckAspectRatio() // TODO: after measure done, need to check AspectRatio again. } +void LayoutProperty::UpdateGridConstraint(const RefPtr& host) +{ + const auto& gridProperty = GetGridProperty(); + CHECK_NULL_VOID(gridProperty); + bool gridflag = false; + auto parent = host->GetParent(); + while (parent) { + if (parent->GetTag() == V2::GRIDCONTAINER_ETS_TAG) { + auto containerLayout = AceType::DynamicCast(parent)->GetLayoutProperty(); + gridflag = gridProperty->UpdateContainer(containerLayout, host); + break; + } + parent = parent->GetParent(); + } + if (gridflag) { + UpdateUserDefinedIdealSize(CalcSize(CalcLength(gridProperty->GetWidth()), std::nullopt)); + } +} + void LayoutProperty::CheckSelfIdealSize() { if (measureType_ == MeasureType::MATCH_PARENT) { diff --git a/frameworks/core/components_ng/layout/layout_property.h b/frameworks/core/components_ng/layout/layout_property.h index 71cb73ffde757e164e1ac09dbdb2930e13221515..af9aedf368cbf4fa114d534f58bd28399595bc01 100644 --- a/frameworks/core/components_ng/layout/layout_property.h +++ b/frameworks/core/components_ng/layout/layout_property.h @@ -29,6 +29,7 @@ #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/grid_property.h" #include "core/components_ng/property/layout_constraint.h" #include "core/components_ng/property/magic_layout_property.h" #include "core/components_ng/property/measure_property.h" @@ -98,6 +99,12 @@ public: { return flexItemProperty_; } + + const std::unique_ptr& GetGridProperty() const + { + return gridProperty_; + } + MeasureType GetMeasureType(MeasureType defaultType = MeasureType::MATCH_CONTENT) const { return measureType_.value_or(defaultType); @@ -272,6 +279,22 @@ public: } } + void UpdateGridProperty( + std::optional span, std::optional offset, GridSizeType type = GridSizeType::UNDEFINED) + { + if (!gridProperty_) { + gridProperty_ = std::make_unique(); + } + + bool isSpanUpdated = (span.has_value() && gridProperty_->UpdateSpan(span.value(), type)); + bool isOffsetUpdated = (offset.has_value() && gridProperty_->UpdateOffset(offset.value(), type)); + if (isSpanUpdated || isOffsetUpdated) { + propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE; + } + } + + void UpdateGridConstraint(const RefPtr& host); + void UpdateContentConstraint(); LayoutConstraintF CreateChildConstraint() const; @@ -315,6 +338,7 @@ private: std::unique_ptr magicItemProperty_; std::unique_ptr positionProperty_; std::unique_ptr flexItemProperty_; + std::unique_ptr gridProperty_; std::optional measureType_; WeakPtr host_; diff --git a/frameworks/core/components_ng/layout/layout_wrapper.cpp b/frameworks/core/components_ng/layout/layout_wrapper.cpp index 4d36b77bce67b1668453beb4343794a678a80291..0db40d5ca73967ce9f9bd906b13e1a57cf774d10 100644 --- a/frameworks/core/components_ng/layout/layout_wrapper.cpp +++ b/frameworks/core/components_ng/layout/layout_wrapper.cpp @@ -119,11 +119,13 @@ void LayoutWrapper::Measure(const std::optional& parentConstr if (parentConstraint) { geometryNode_->SetParentLayoutConstraint(parentConstraint.value()); + layoutProperty_->UpdateGridConstraint(GetHostNode()); layoutProperty_->UpdateLayoutConstraint(parentConstraint.value()); } else { LayoutConstraintF layoutConstraint; layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth()); layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight()); + layoutProperty_->UpdateGridConstraint(GetHostNode()); layoutProperty_->UpdateLayoutConstraint(layoutConstraint); } layoutProperty_->UpdateContentConstraint(); @@ -189,6 +191,17 @@ void LayoutWrapper::Layout() } layoutProperty_->UpdateContentConstraint(); } + + // TODO: delete following to use constraint offset + { + const auto& gridProp = layoutProperty_->GetGridProperty(); + if (gridProp) { + OffsetF gridOffset = geometryNode_->GetFrameOffset(); + gridOffset.SetX(gridProp->GetOffset().Value()); + LOGD("On grid layout Done: %{public}s, Offset: %{public}f", GetHostTag().c_str(), gridOffset.GetX()); + geometryNode_->SetMarginFrameOffset(gridOffset); + } + } layoutAlgorithm_->Layout(this); LOGD("On Layout Done: %{public}s, Offset: %{public}s", GetHostTag().c_str(), geometryNode_->GetFrameOffset().ToString().c_str()); diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index c53265fe86db2ccf6d1808966060ff1806c95ecc..255958d95d393ca51a9c8a1b536907455788b46c 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -69,6 +69,8 @@ build_component_ng("pattern_ng") { "grid/grid_scroll/grid_scroll_layout_algorithm.cpp", "grid/grid_utils.cpp", "grid/grid_view.cpp", + "grid_container/grid_container_layout_property.cpp", + "grid_container/grid_container_view.cpp", "image/image_layout_algorithm.cpp", "image/image_model_ng.cpp", "image/image_pattern.cpp", diff --git a/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_algorithm.h b/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_algorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..5445b5a477224bcdb1863317a27fb521f02ca227 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_algorithm.h @@ -0,0 +1,51 @@ + +/* + * 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_CONTAINER_GRID_CONTAINER_LAYOUT_ALGORITHM_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_CONTAINER_GRID_CONTAINER_LAYOUT_ALGORITHM_H + +#include "grid_container_layout_property.h" + +#include "core/components_ng/pattern/linear_layout/linear_layout_algorithm.h" +#include "core/components_ng/property/measure_utils.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT GridContainerLayoutAlgorithm : public LinearLayoutAlgorithm { + DECLARE_ACE_TYPE(GridContainerLayoutAlgorithm, LinearLayoutAlgorithm); + +public: + GridContainerLayoutAlgorithm() = default; + ~GridContainerLayoutAlgorithm() override = default; + + void Measure(LayoutWrapper* layoutWrapper) override + { + const auto& layoutProperty = layoutWrapper->GetLayoutProperty(); + float width = CreateIdealSize( + layoutProperty->GetLayoutConstraint().value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT, true) + .Width(); + const auto& gridContainerLayoutProperty = DynamicCast(layoutProperty); + gridContainerLayoutProperty->BuildWidth(width); + + auto curLayoutProp = layoutWrapper->GetHostNode()->GetLayoutProperty(); + curLayoutProp->BuildWidth(width); + + LinearLayoutAlgorithm::Measure(layoutWrapper); + } +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_CONTAINER_GRID_CONTAINER_LAYOUT_ALGORITHM_H diff --git a/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_property.cpp b/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_property.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36d95b031042807f47f1a7c5724ac2e8ffb0f92c --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_property.cpp @@ -0,0 +1,52 @@ +/* + * 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 "grid_container_layout_property.h" + +#include "base/log/log_wrapper.h" + +namespace OHOS::Ace::NG { + +void GridContainerLayoutProperty::RegistGridChild(const RefPtr& child) +{ + childrenFramenode_.emplace_back(child); +} + +void GridContainerLayoutProperty::OnContainerInfoUpdate(const GridContainerInfo& info) +{ + LOGD("GridContainer layout info update."); + for (auto p = childrenFramenode_.begin(); p != childrenFramenode_.end(); ++p) { + RefPtr child; + do { + child = p->Upgrade(); + if (child) { + LOGD("MarkDirtyNode, %{public}s", child->GetTag().c_str()); + child->MarkDirtyNode(PROPERTY_UPDATE_MEASURE | PROPERTY_UPDATE_LAYOUT); + } + p = childrenFramenode_.erase(p); + } while (p != childrenFramenode_.end()); + } +} + +void GridContainerLayoutProperty::BuildWidth(float width) +{ + if (NearEqual(width, Infinity())) { + propContainerInfo_->BuildColumnWidth(); + } else { + propContainerInfo_->BuildColumnWidth(width); + } +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_property.h b/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_property.h new file mode 100644 index 0000000000000000000000000000000000000000..31f6446a1a7af982dcea3b8dcedc936ea4723495 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid_container/grid_container_layout_property.h @@ -0,0 +1,72 @@ +/* + * 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_CONTAINER_LAYOUT_PROPERTY_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_CONTAINER_LAYOUT_PROPERTY_H + +#include +#include + +#include "../linear_layout/linear_layout_property.h" + +#include "core/components_ng/base/frame_node.h" +#include "frameworks/core/components/common/layout/grid_container_info.h" + +namespace OHOS::Ace::NG { + +class ACE_EXPORT GridContainerLayoutProperty : public LinearLayoutProperty { + DECLARE_ACE_TYPE(GridContainerLayoutProperty, LinearLayoutProperty); + +public: + GridContainerLayoutProperty() : LinearLayoutProperty(true) {} + + ~GridContainerLayoutProperty() override = default; + + bool operator==(const GridContainerLayoutProperty& other) const + { + return (propContainerInfo_ == other.propContainerInfo_); + } + + RefPtr Clone() const override + { + auto value = MakeRefPtr(); + LinearLayoutProperty::Clone(value); + value->propContainerInfo_ = propContainerInfo_; + value->childrenFramenode_ = childrenFramenode_; + value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); + return value; + } + + void Reset() override + { + childrenFramenode_.clear(); + ResetContainerInfo(); + LinearLayoutProperty::Reset(); + } + + void UpdateChild(RefPtr& child, const GridContainerInfo& info); + void RegistGridChild(const RefPtr& child); + void BuildWidth(float width); + + ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_AND_USING_CALLBACK(ContainerInfo, GridContainerInfo, PROPERTY_UPDATE_NORMAL); + +private: + void OnContainerInfoUpdate(const GridContainerInfo& info); + + std::vector> childrenFramenode_; + ACE_DISALLOW_COPY_AND_MOVE(GridContainerLayoutProperty); +}; +} // namespace OHOS::Ace::NG +#endif \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/grid_container/grid_container_pattern.h b/frameworks/core/components_ng/pattern/grid_container/grid_container_pattern.h new file mode 100644 index 0000000000000000000000000000000000000000..be7df17d0ceb299fb1f95a6187edbc55ebaf4c46 --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid_container/grid_container_pattern.h @@ -0,0 +1,44 @@ +/* + * 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_CONTAINER_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_CONTAINER_PATTERN_H + +#include "../linear_layout/linear_layout_pattern.h" +#include "grid_container_layout_algorithm.h" +#include "grid_container_layout_property.h" + +namespace OHOS::Ace::NG { + +class GridContainerLayoutPattern : public LinearLayoutPattern { + DECLARE_ACE_TYPE(GridContainerLayoutPattern, LinearLayoutPattern); + +public: + GridContainerLayoutPattern() : LinearLayoutPattern(true) {} + ~GridContainerLayoutPattern() override = default; + + RefPtr CreateLayoutProperty() override + { + return MakeRefPtr(); + } + + RefPtr CreateLayoutAlgorithm() override + { + return MakeRefPtr(); + } +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_GRID_CONTAINER_PATTERN_H diff --git a/frameworks/core/components_ng/pattern/grid_container/grid_container_view.cpp b/frameworks/core/components_ng/pattern/grid_container/grid_container_view.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d24872cfe98a15fc3a13c8107cf216c1401b12f --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid_container/grid_container_view.cpp @@ -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. + */ + +#include "grid_container_view.h" + +#include "grid_container_pattern.h" + +#include "base/memory/referenced.h" +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_v2/inspector/inspector_constants.h" + +namespace OHOS::Ace::NG { + +void GridContainerView::Create(const RefPtr& containerInfo) +{ + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode( + V2::GRIDCONTAINER_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); + + ACE_UPDATE_LAYOUT_PROPERTY(GridContainerLayoutProperty, ContainerInfo, *containerInfo); + + PaddingProperty padding; + padding.left = CalcLength(containerInfo->GetMarginLeft()); + padding.right = CalcLength(containerInfo->GetMarginRight()); + ACE_UPDATE_LAYOUT_PROPERTY(LayoutProperty, Padding, padding); +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/grid_container/grid_container_view.h b/frameworks/core/components_ng/pattern/grid_container/grid_container_view.h new file mode 100644 index 0000000000000000000000000000000000000000..b321c2549ee91a3258da31818ba3275b262aaffe --- /dev/null +++ b/frameworks/core/components_ng/pattern/grid_container/grid_container_view.h @@ -0,0 +1,29 @@ +/* + * 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_CONTAINER_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_CONTAINER_VIEW_H + +#include "base/utils/macros.h" +#include "frameworks/core/components/common/layout/grid_container_info.h" + +namespace OHOS::Ace::NG { +class ACE_EXPORT GridContainerView { +public: + static void Create(const RefPtr& containerInfo); +}; +} // namespace OHOS::Ace::NG + +#endif \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h b/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h index 50bf8b7664c1de96fee389efd953b7adfdee7bfb..41cd603fd5d407dcef416fb1c4d76fba87b8f4ab 100644 --- a/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h +++ b/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h @@ -33,9 +33,7 @@ public: RefPtr Clone() const override { auto value = MakeRefPtr(isVertical_); - value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); - value->propLinearLayoutAttribute_ = CloneLinearLayoutAttribute(); - value->isVertical_ = isVertical_; + Clone(value); return value; } @@ -64,6 +62,15 @@ public: return isVertical_; } +protected: + void Clone(RefPtr property) const override + { + auto value = DynamicCast(property); + value->LayoutProperty::UpdateLayoutProperty(DynamicCast(this)); + value->propLinearLayoutAttribute_ = CloneLinearLayoutAttribute(); + value->isVertical_ = isVertical_; + } + private: // This will call after ModifyLayoutConstraint. bool isVertical_ = false; diff --git a/frameworks/core/components_ng/property/BUILD.gn b/frameworks/core/components_ng/property/BUILD.gn index 4912ee3f1d0f86b0cf7a036ec30d1639586140c8..599e156e2890b13f3162f0dc7ddfcba489143891 100644 --- a/frameworks/core/components_ng/property/BUILD.gn +++ b/frameworks/core/components_ng/property/BUILD.gn @@ -18,6 +18,7 @@ build_component_ng("property_ng") { sources = [ "calc_length.cpp", "gradient_property.cpp", + "grid_property.cpp", "measure_utils.cpp", "property.cpp", ] diff --git a/frameworks/core/components_ng/property/grid_property.cpp b/frameworks/core/components_ng/property/grid_property.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09dda0f8c57b46513b3bcf94a65864fcee1e21f7 --- /dev/null +++ b/frameworks/core/components_ng/property/grid_property.cpp @@ -0,0 +1,120 @@ +/* + * 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 "grid_property.h" + +#include + +#include "core/components/common/layout/grid_container_info.h" +#include "core/components_ng/pattern/grid_container/grid_container_layout_property.h" + +namespace OHOS::Ace::NG { + +Dimension GridProperty::GetWidth() +{ + // gridInfo_ must exist, because layout algorithm invoke UpdateContainer first + return Dimension(gridInfo_->GetWidth()); +} + +Dimension GridProperty::GetOffset() +{ + // gridInfo_ must exist, because layout algorithm invoke UpdateContainer() first + return gridInfo_->GetOffset(); +} + +bool GridProperty::UpdateContainer(const RefPtr& container, const RefPtr& host) +{ + auto gridContainer = DynamicCast(container); + auto mGridContainer = DynamicCast(container_); + + if ((container_) && (*mGridContainer == *gridContainer)) { + return false; + } + container_ = container; + + GridColumnInfo::Builder builder; + auto containerInfo = MakeRefPtr(gridContainer->GetContainerInfoValue()); + builder.SetParent(containerInfo); + + for (const auto& item : typedPropertySet_) { + builder.SetSizeColumn(item.type_, item.span_); + builder.SetOffset(item.offset_, item.type_); + } + + gridInfo_ = builder.Build(); + gridContainer->RegistGridChild(DynamicCast(host)); + return true; +} + +bool GridProperty::UpdateSpan(uint32_t span, GridSizeType type) +{ + LOGD("Update grid span. (span=%u, type=%i)", span, type); + if (!container_) { + SetSpan(type, span); + return true; + } + + auto container = DynamicCast(container_); + GridSizeType currentType = container->GetContainerInfo()->GetSizeType(); // working type, not UNDEFINED + auto currentProp = GetTypedProperty(type); // working property + + return (currentProp->type_ == type || currentType == type) && SetSpan(type, span); +} + +bool GridProperty::UpdateOffset(int32_t offset, GridSizeType type) +{ + LOGD("Update grid span. (offset=%u, type=%i)", offset, type); + if (!container_) { + SetOffset(type, offset); + return true; + } + auto container = DynamicCast(container_); + GridSizeType currentType = container->GetContainerInfo()->GetSizeType(); // working type, not UNDEFINED + auto currentProp = GetTypedProperty(type); // working property + + return (currentProp->type_ == type || currentType == type) && SetOffset(type, offset); +} + +bool GridProperty::SetSpan(GridSizeType type, uint32_t span) +{ + auto item = std::find_if(typedPropertySet_.begin(), typedPropertySet_.end(), + [type](const GridTypedProperty& p) { return p.type_ == type; }); + if (item == typedPropertySet_.end()) { + typedPropertySet_.emplace_back(type, span, DEFAULT_GRID_OFFSET); + return true; + } + if (item->span_ == span) { + return false; + } + item->span_ = span; + return true; +} + +bool GridProperty::SetOffset(GridSizeType type, int32_t offset) +{ + auto item = std::find_if(typedPropertySet_.begin(), typedPropertySet_.end(), + [type](const GridTypedProperty& p) { return p.type_ == type; }); + if (item == typedPropertySet_.end()) { + typedPropertySet_.emplace_back(type, DEFAULT_GRID_SPAN, offset); + return true; + } + if (item->offset_ == offset) { + return false; + } + item->offset_ = offset; + return true; +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/property/grid_property.h b/frameworks/core/components_ng/property/grid_property.h new file mode 100644 index 0000000000000000000000000000000000000000..7cc03ac57ebfc86f8b30746260439fa13a4eba9a --- /dev/null +++ b/frameworks/core/components_ng/property/grid_property.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_PROPERTIES_GRID_PROPERTIES_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_GRID_PROPERTIES_H + +#include + +#include "property.h" + +#include "base/memory/ace_type.h" +#include "base/utils/utils.h" +#include "core/components/common/layout/grid_column_info.h" +#include "core/components/common/layout/grid_layout_info.h" +#include "core/components_ng/property/calc_length.h" + +namespace OHOS::Ace::NG { + +constexpr uint32_t DEFAULT_GRID_SPAN = 1; +constexpr int32_t DEFAULT_GRID_OFFSET = 0; +struct GridTypedProperty { + GridTypedProperty(GridSizeType type, uint32_t span, int32_t offset) : type_(type), span_(span), offset_(offset) {} + + bool operator==(const GridTypedProperty& other) const + { + if ((type_ != GridSizeType::UNDEFINED) && (other.type_ != GridSizeType::UNDEFINED) && (type_ != other.type_)) { + return false; + } + return ((span_ == other.span_) && (offset_ == other.offset_)); + } + + GridSizeType type_ = GridSizeType::UNDEFINED; + uint32_t span_ = DEFAULT_GRID_SPAN; + int32_t offset_ = DEFAULT_GRID_OFFSET; +}; + +class ACE_EXPORT GridProperty : public AceType { // TODO delete EXPORT + DECLARE_ACE_TYPE(GridPropertySet, AceType); + +public: + GridProperty() : typedPropertySet_ { { GridSizeType::UNDEFINED, DEFAULT_GRID_SPAN, DEFAULT_GRID_OFFSET } } {} + + GridProperty(const GridProperty& other) + { + *this = other; + } + + ~GridProperty() override = default; + + GridProperty(const GridProperty&& other) = delete; + + GridProperty& operator=(const GridProperty&& other) = delete; + + GridProperty& operator=(const GridProperty& other) + { + if (&other != this) { + typedPropertySet_ = other.typedPropertySet_; + } + container_ = other.container_; + gridInfo_ = other.gridInfo_; + return *this; + } + + Dimension GetWidth(); + + Dimension GetOffset(); + + bool UpdateContainer(const RefPtr& container, const RefPtr& host); + + bool UpdateSpan(uint32_t span, GridSizeType type = GridSizeType::UNDEFINED); + + bool UpdateOffset(int32_t offset, GridSizeType type = GridSizeType::UNDEFINED); + + std::optional GetTypedProperty(GridSizeType type) const + { + for (const auto& item : typedPropertySet_) { + if (item.type_ == type) { + return item; + } + } + return std::nullopt; + } + +private: + bool SetSpan(GridSizeType type, uint32_t span); + + bool SetOffset(GridSizeType type, int32_t offset); + + std::vector typedPropertySet_; + RefPtr container_; + RefPtr gridInfo_; +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_GRID_PROPERTIES_H \ No newline at end of file