• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_COMPONENT_H
17 #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_COMPONENT_H
18 
19 #include <functional>
20 #include <set>
21 #include <string>
22 
23 #include "base/memory/ace_type.h"
24 #include "bridge/declarative_frontend/jsview/js_lazy_foreach_actuator.h"
25 #include "bridge/declarative_frontend/jsview/js_view.h"
26 #include "core/components_v2/foreach/lazy_foreach_component.h"
27 
28 namespace OHOS::Ace::Framework {
29 
30 class DefaultDataChangeListener : public V2::DataChangeListener {
31 public:
DefaultDataChangeListener(JSView * parentView)32     explicit DefaultDataChangeListener(JSView* parentView) : parentView_(parentView) {}
33     ~DefaultDataChangeListener() override = default;
34 
OnDataReloaded()35     void OnDataReloaded() override
36     {
37         if (parentView_ != nullptr) {
38             parentView_->MarkNeedUpdate();
39         }
40     }
OnDataAdded(size_t index)41     void OnDataAdded(size_t index) override
42     {
43         if (parentView_ != nullptr) {
44             parentView_->MarkNeedUpdate();
45         }
46     }
OnDataDeleted(size_t index)47     void OnDataDeleted(size_t index) override
48     {
49         if (parentView_ != nullptr) {
50             parentView_->MarkNeedUpdate();
51         }
52     }
OnDataChanged(size_t index)53     void OnDataChanged(size_t index) override
54     {
55         if (parentView_ != nullptr) {
56             parentView_->MarkNeedUpdate();
57         }
58     }
OnDataMoved(size_t from,size_t to)59     void OnDataMoved(size_t from, size_t to) override
60     {
61         if (parentView_ != nullptr) {
62             parentView_->MarkNeedUpdate();
63         }
64     }
65 
66 private:
67     JSView* parentView_ = nullptr;
68 
69     ACE_DISALLOW_COPY_AND_MOVE(DefaultDataChangeListener);
70 };
71 
72 class JSLazyForEachComponent : public V2::LazyForEachComponent, public JSLazyForEachActuator {
73     DECLARE_ACE_TYPE(JSLazyForEachComponent, V2::LazyForEachComponent, JSLazyForEachActuator);
74 
75 public:
JSLazyForEachComponent(const std::string & id)76     explicit JSLazyForEachComponent(const std::string& id) : V2::LazyForEachComponent(id) {}
77     ~JSLazyForEachComponent() override = default;
78 
OnGetTotalCount()79     size_t OnGetTotalCount() override
80     {
81         return static_cast<size_t>(GetTotalIndexCount());
82     }
83 
ExpandChildrenOnInitial()84     void ExpandChildrenOnInitial()
85     {
86         auto totalIndex = GetTotalIndexCount();
87         auto* stack = ViewStackProcessor::GetInstance();
88         JSRef<JSVal> params[2];
89         for (auto index = 0; index < totalIndex; index++) {
90             params[0] = CallJSFunction(getDataFunc_, dataSourceObj_, index);
91             params[1] = JSRef<JSVal>::Make(ToJSValue(index));
92             std::string key = keyGenFunc_(params[0], index);
93             auto multiComposed = AceType::MakeRefPtr<MultiComposedComponent>(key, "LazyForEach");
94             stack->Push(multiComposed);
95             stack->PushKey(key);
96             itemGenFunc_->Call(JSRef<JSObject>(), 2, params);
97             stack->PopContainer();
98             stack->PopKey();
99         }
100     }
101 
OnGetChildByIndex(size_t index)102     RefPtr<Component> OnGetChildByIndex(size_t index) override
103     {
104         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext_, nullptr);
105         if (getDataFunc_.IsEmpty()) {
106             return nullptr;
107         }
108 
109         JSRef<JSVal> params[2];
110         params[0] = CallJSFunction(getDataFunc_, dataSourceObj_, index);
111         params[1] = JSRef<JSVal>::Make(ToJSValue(index));
112         std::string key = keyGenFunc_(params[0], index);
113 
114         ScopedViewStackProcessor scopedViewStackProcessor;
115         auto* viewStack = ViewStackProcessor::GetInstance();
116         auto multiComposed = AceType::MakeRefPtr<MultiComposedComponent>(key, "LazyForEach");
117         viewStack->Push(multiComposed);
118         if (parentView_) {
119             parentView_->MarkLazyForEachProcess(key);
120         }
121         viewStack->PushKey(key);
122         itemGenFunc_->Call(JSRef<JSObject>(), 2, params);
123         viewStack->PopContainer();
124         viewStack->PopKey();
125         if (parentView_) {
126             parentView_->ResetLazyForEachProcess();
127         }
128         auto component = viewStack->Finish();
129         ACE_DCHECK(multiComposed == component);
130 
131         while (multiComposed) {
132             const auto& children = multiComposed->GetChildren();
133             if (children.empty()) {
134                 return AceType::MakeRefPtr<ComposedComponent>(key, "LazyForEachItem");
135             }
136 
137             component = children.front();
138             multiComposed = AceType::DynamicCast<MultiComposedComponent>(component);
139         }
140 
141         return AceType::MakeRefPtr<ComposedComponent>(key, "LazyForEachItem", component);
142     }
143 
ReleaseChildGroupByComposedId(const std::string & composedId)144     void ReleaseChildGroupByComposedId(const std::string& composedId) override
145     {
146         JSLazyForEachActuator::ReleaseChildGroupByComposedId(composedId);
147     }
148 
RegisterDataChangeListener(const RefPtr<V2::DataChangeListener> & listener)149     void RegisterDataChangeListener(const RefPtr<V2::DataChangeListener>& listener) override
150     {
151         JSLazyForEachActuator::RegisterListener(listener);
152     }
153 
UnregisterDataChangeListener(const RefPtr<V2::DataChangeListener> & listener)154     void UnregisterDataChangeListener(const RefPtr<V2::DataChangeListener>& listener) override
155     {
156         JSLazyForEachActuator::UnregisterListener(listener);
157     }
158 
159 private:
ExpandChildren()160     std::list<RefPtr<Component>>& ExpandChildren() override
161     {
162         // Register data change listener while expanding the lazy foreach component
163         if (!Expanded()) {
164             defaultListener_ = Referenced::MakeRefPtr<DefaultDataChangeListener>(parentView_);
165             RegisterDataChangeListener(defaultListener_);
166         }
167         return LazyForEachComponent::ExpandChildren();
168     }
169 
170     ACE_DISALLOW_COPY_AND_MOVE(JSLazyForEachComponent);
171 };
172 
173 } // namespace OHOS::Ace::Framework
174 
175 #endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_COMPONENT_H
176