1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_v2/grid/grid_element.h"
17
18 #include "base/log/log.h"
19 #include "base/utils/utils.h"
20 #include "core/components/grid_layout/grid_layout_component.h"
21 #include "core/components/grid_layout/grid_layout_item_component.h"
22 #include "core/components/grid_layout/render_grid_layout.h"
23 #include "core/components/proxy/render_item_proxy.h"
24 #include "core/components_v2/grid/render_grid_scroll.h"
25
26 namespace OHOS::Ace::V2 {
27
CreateRenderNode()28 RefPtr<RenderNode> GridElement::CreateRenderNode()
29 {
30 auto render = RenderElement::CreateRenderNode();
31 RefPtr<RenderGridScroll> renderGrid = AceType::DynamicCast<RenderGridScroll>(render);
32 if (renderGrid) {
33 renderGrid->SetBuildChildByIndex([weak = WeakClaim(this)](int32_t index) {
34 auto element = weak.Upgrade();
35 if (!element) {
36 return false;
37 }
38 return element->BuildChildByIndex(index);
39 });
40
41 renderGrid->SetDeleteChildByIndex([weak = WeakClaim(this)](int32_t index) {
42 auto element = weak.Upgrade();
43 if (!element) {
44 return;
45 }
46 element->DeleteChildByIndex(index);
47 });
48
49 renderGrid->SetGetChildSpanByIndex([weak = WeakClaim(this)](int32_t index, bool isHorizontal, int32_t& itemMain,
50 int32_t& itemCross, int32_t& itemMainSpan, int32_t& itemCrossSpan) {
51 auto element = weak.Upgrade();
52 if (!element) {
53 return false;
54 }
55 return element->GetItemSpanByIndex(index, isHorizontal, itemMain, itemCross, itemMainSpan, itemCrossSpan);
56 });
57
58 renderGrid->SetGetItemTotalCount([weak = WeakClaim(this)]() {
59 auto element = weak.Upgrade();
60 if (!element) {
61 return 0;
62 }
63 return static_cast<int32_t>(element->TotalCount());
64 });
65 }
66
67 return render;
68 }
69
PerformBuild()70 void GridElement::PerformBuild()
71 {
72 auto component = AceType::DynamicCast<GridLayoutComponent>(component_);
73 ACE_DCHECK(component); // MUST be GridComponent
74 V2::ElementProxyHost::UpdateChildren(component->GetChildren());
75 RefPtr<RenderGridScroll> render = AceType::DynamicCast<RenderGridScroll>(renderNode_);
76 CHECK_NULL_VOID(render);
77 render->OnDataSourceUpdated(0);
78 }
79
BuildChildByIndex(int32_t index)80 bool GridElement::BuildChildByIndex(int32_t index)
81 {
82 if (index < 0) {
83 return false;
84 }
85 auto element = GetElementByIndex(index);
86 if (!element) {
87 LOGE("GetElementByIndex failed index=[%d]", index);
88 return false;
89 }
90 auto renderNode = element->GetRenderNode();
91 if (!renderNode) {
92 LOGE("GetRenderNode failed");
93 return false;
94 }
95 RefPtr<RenderGridScroll> grid = AceType::DynamicCast<RenderGridScroll>(renderNode_);
96 if (!grid) {
97 return false;
98 }
99 grid->AddChildByIndex(index, renderNode);
100 return true;
101 }
102
GetItemSpanByIndex(int32_t index,bool isHorizontal,int32_t & itemMain,int32_t & itemCross,int32_t & itemMainSpan,int32_t & itemCrossSpan)103 bool GridElement::GetItemSpanByIndex(int32_t index, bool isHorizontal, int32_t& itemMain, int32_t& itemCross,
104 int32_t& itemMainSpan, int32_t& itemCrossSpan)
105 {
106 if (index < 0) {
107 return false;
108 }
109 auto component = GetComponentByIndex(index);
110 auto gridItem = AceType::DynamicCast<GridLayoutItemComponent>(component);
111
112 if (!gridItem) {
113 return false;
114 }
115 if (isHorizontal) {
116 itemMain = gridItem->GetColumnIndex();
117 itemCross = gridItem->GetRowIndex();
118 itemMainSpan = gridItem->GetColumnSpan();
119 itemCrossSpan = gridItem->GetRowSpan();
120 } else {
121 itemMain = gridItem->GetRowIndex();
122 itemCross = gridItem->GetColumnIndex();
123 itemMainSpan = gridItem->GetRowSpan();
124 itemCrossSpan = gridItem->GetColumnSpan();
125 }
126 return true;
127 }
128
DeleteChildByIndex(int32_t index)129 void GridElement::DeleteChildByIndex(int32_t index)
130 {
131 ReleaseElementByIndex(index);
132 }
133
RequestNextFocus(bool vertical,bool reverse,const Rect & rect)134 bool GridElement::RequestNextFocus(bool vertical, bool reverse, const Rect& rect)
135 {
136 RefPtr<RenderGridLayout> grid = AceType::DynamicCast<RenderGridLayout>(renderNode_);
137 if (!grid) {
138 LOGE("Render grid is null.");
139 return false;
140 }
141 LOGI("RequestNextFocus vertical:%{public}d reverse:%{public}d.", vertical, reverse);
142 bool ret = false;
143 while (!ret) {
144 int32_t focusIndex = grid->RequestNextFocus(vertical, reverse);
145 int32_t size = static_cast<int32_t>(GetChildrenList().size());
146 if (focusIndex < 0 || focusIndex >= size) {
147 return false;
148 }
149 auto iter = GetChildrenList().begin();
150 std::advance(iter, focusIndex);
151 auto focusNode = *iter;
152 if (!focusNode) {
153 LOGE("Target focus node is null.");
154 return false;
155 }
156 // If current Node can not obtain focus, move to next.
157 ret = focusNode->RequestFocusImmediately();
158 }
159 return ret;
160 }
161
ApplyRenderChild(const RefPtr<RenderElement> & renderChild)162 void GridElement::ApplyRenderChild(const RefPtr<RenderElement>& renderChild)
163 {
164 if (!renderChild) {
165 LOGE("Element child is null");
166 return;
167 }
168
169 if (!renderNode_) {
170 LOGE("RenderElement don't have a render node");
171 return;
172 }
173 renderNode_->AddChild(renderChild->GetRenderNode());
174 }
175
OnUpdateElement(const RefPtr<Element> & element,const RefPtr<Component> & component)176 RefPtr<Element> GridElement::OnUpdateElement(const RefPtr<Element>& element, const RefPtr<Component>& component)
177 {
178 return UpdateChild(element, component);
179 }
180
OnMakeEmptyComponent()181 RefPtr<Component> GridElement::OnMakeEmptyComponent()
182 {
183 return AceType::MakeRefPtr<GridLayoutItemComponent>();
184 }
185
OnDataSourceUpdated(size_t startIndex)186 void GridElement::OnDataSourceUpdated(size_t startIndex)
187 {
188 auto context = context_.Upgrade();
189 if (context) {
190 context->AddPostFlushListener(AceType::Claim(this));
191 }
192 RefPtr<RenderGridScroll> render = AceType::DynamicCast<RenderGridScroll>(renderNode_);
193 if (!render) {
194 return;
195 }
196 render->OnDataSourceUpdated(static_cast<int32_t>(startIndex));
197 render->SetTotalCount(ElementProxyHost::TotalCount());
198 ElementProxyHost::OnDataSourceUpdated(startIndex);
199 }
200
OnPostFlush()201 void GridElement::OnPostFlush()
202 {
203 ReleaseRedundantComposeIds();
204 }
205
GetReloadedCheckNum()206 size_t GridElement::GetReloadedCheckNum()
207 {
208 RefPtr<RenderGridScroll> render = AceType::DynamicCast<RenderGridScroll>(renderNode_);
209 if (render) {
210 size_t cachedNum = render->GetCachedSize();
211 if (cachedNum > 0) {
212 return cachedNum;
213 }
214 }
215 return ElementProxyHost::GetReloadedCheckNum();
216 }
217
Dump()218 void GridElement::Dump()
219 {
220 DumpProxy();
221 }
222
223 } // namespace OHOS::Ace::V2
224