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