diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt index d2f656132f..9358e441b2 100644 --- a/weex_core/Source/CMakeLists.txt +++ b/weex_core/Source/CMakeLists.txt @@ -96,7 +96,9 @@ set(COMMON_SRCS ./core/data_render/binary_file.cc ./core/data_render/vnode/vnode.cc ./core/data_render/vnode/vcomponent.cc - ./core/data_render/vnode/vcomponent_lifecycle_listener.cc + ./core/data_render/vnode/android/vcomponent_lifecycle_listener.cc + ./core/data_render/vnode/android/vnode_on_event_listener.cc + ./core/data_render/vnode/android/conversion.cc ./core/data_render/vnode/vnode_exec_env.cc ./core/data_render/vnode/vnode_render_manager.cc ./core/data_render/vnode/vnode_render_context.cc diff --git a/weex_core/Source/core/data_render/vnode/android/conversion.cc b/weex_core/Source/core/data_render/vnode/android/conversion.cc new file mode 100644 index 0000000000..9248dd11c4 --- /dev/null +++ b/weex_core/Source/core/data_render/vnode/android/conversion.cc @@ -0,0 +1,81 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 OS_ANDROID + +#include "core/data_render/vnode/android/conversion.h" +#include "android/utils/params_utils.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/object.h" +#include "core/manager/weex_core_manager.h" +#include "wson/wson.h" +#include "wson/wson_parser.h" + +namespace weex { +namespace core { +namespace data_render { + +json11::Json Conversion::GenJSON(const Value* v) { + switch (v->type) { + case Value::Type::NUMBER: + return v->n; + case Value::Type::STRING: + return v->str->c_str(); + case Value::Type::INT: + return static_cast(v->i); + case Value::Type::BOOL: + return v->b; + case Value::Type::ARRAY: { + Array* array = ValueTo(v); + std::vector json_array; + for (auto it = array->items.begin(); it != array->items.end(); it++) { + json_array.push_back(GenJSON(&*it)); + } + return json_array; + } + case Value::Type::TABLE: { + Table* table = ValueTo(v); + std::map json_table; + for (auto it = table->map.begin(); it != table->map.end(); it++) { + json_table.insert({it->first, GenJSON(&it->second)}); + } + return json_table; + } + case Value::Type::NIL: + return nullptr; + } +} + +VALUE_WITH_TYPE* Conversion::GenValueWithType(const char* event_str) { + VALUE_WITH_TYPE* event = getValueWithTypePtr(); + event->type = ParamsType::BYTEARRAY; + auto buffer = wson_buffer_new(); + wson_push_type_uint8_string( + buffer, reinterpret_cast(event_str), strlen(event_str)); + event->value.byteArray = genWeexByteArray( + static_cast(buffer->data), buffer->position); + buffer->data = nullptr; + wson_buffer_free(buffer); + return event; +} + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif \ No newline at end of file diff --git a/weex_core/Source/core/data_render/vnode/android/conversion.h b/weex_core/Source/core/data_render/vnode/android/conversion.h new file mode 100644 index 0000000000..e3f91200c9 --- /dev/null +++ b/weex_core/Source/core/data_render/vnode/android/conversion.h @@ -0,0 +1,45 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 OS_ANDROID + +#ifndef CORE_DATA_RENDER_VNODE_ANDROID_CONVERSION_H_ +#define CORE_DATA_RENDER_VNODE_ANDROID_CONVERSION_H_ + +#include +#include +#include +#include "include/WeexApiHeader.h" +#include "third_party/json11/json11.hpp" + +namespace weex { +namespace core { +namespace data_render { +class Value; +class Conversion { + public: + static json11::Json GenJSON(const Value* v); + static VALUE_WITH_TYPE* GenValueWithType(const char* event_str); +}; + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // CORE_DATA_RENDER_VNODE_ANDROID_CONVERSION_H_ +#endif diff --git a/weex_core/Source/core/data_render/vnode/android/vcomponent_lifecycle_listener.cc b/weex_core/Source/core/data_render/vnode/android/vcomponent_lifecycle_listener.cc new file mode 100644 index 0000000000..cc707fb4b1 --- /dev/null +++ b/weex_core/Source/core/data_render/vnode/android/vcomponent_lifecycle_listener.cc @@ -0,0 +1,265 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 OS_ANDROID + +#include "core/data_render/vnode/vcomponent_lifecycle_listener.h" +#include "android/utils/params_utils.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/vnode/android/conversion.h" +#include "core/manager/weex_core_manager.h" +#include "wson/wson.h" + +namespace weex { +namespace core { +namespace data_render { + +static const char* kMethodOnComponentEvent = "callJS"; +static const char* kComponentHook = "componentHook"; +static const char* kLifecycle = "lifecycle"; +static const char* kKeyMethod = "method"; +static const char* kKeyArgs = "args"; +static const char* kEventOnCreated = "created"; +static const char* kEventOnUpdated = "updated"; +static const char* kEventOnDestroyed = "destroyed"; +static int kNonParentId = -1; + +void GenWSONValue(wson_buffer* buffer, Value* value); +void GenWSONValue(wson_buffer* buffer, Table* t); +void GenWSONValue(wson_buffer* buffer, int32_t i); +void GenWSONArray(wson_buffer* buffer, Array* array); +void GenWSONTable(wson_buffer* buffer, Table* table); + +void GenWSONValue(wson_buffer* buffer, const std::string& str); +template +void GenWSONValue(wson_buffer* buffer, const std::vector& vector); +template +void GenWSONValue(wson_buffer* buffer, + const std::unordered_map& ref_map); + +void GenWSONValue(wson_buffer* buffer, Value* value) { + switch (value->type) { + case Value::Type::ARRAY: + return GenWSONArray(buffer, ValueTo(value)); + case Value::Type::TABLE: + return GenWSONTable(buffer, ValueTo
(value)); + case Value::Type::INT: + wson_push_type_long(buffer, value->i); + break; + case Value::Type::NUMBER: + wson_push_type_double(buffer, value->n); + break; + case Value::Type::STRING: + wson_push_type_uint8_string( + buffer, reinterpret_cast(value->str->c_str()), + strlen(value->str->c_str())); + break; + case Value::Type::BOOL: + wson_push_type_boolean(buffer, value->b); + break; + default: + wson_push_type_null(buffer); + break; + } +} + +void GenWSONArray(wson_buffer* buffer, Array* array) { + wson_push_type_array(buffer, array->items.size()); + for (auto it = array->items.begin(); it != array->items.end(); it++) { + GenWSONValue(buffer, &*it); + } +} + +void GenWSONTable(wson_buffer* buffer, Table* table) { + wson_push_type_map(buffer, table->map.size()); + for (auto it = table->map.begin(); it != table->map.end(); it++) { + if (it->first.empty()) continue; + // Use utf16 as wson only support utf16 as key in map + auto utf16_key = weex::base::to_utf16(const_cast(it->first.c_str()), + it->first.size()); + wson_push_uint(buffer, utf16_key.size() * sizeof(uint16_t)); + wson_push_bytes(buffer, utf16_key.c_str(), + utf16_key.size() * sizeof(uint16_t)); + GenWSONValue(buffer, &it->second); + } +} + +void GenWSONValue(wson_buffer* buffer, Table* t) { GenWSONTable(buffer, t); } + +void GenWSONValue(wson_buffer* buffer, int32_t i) { + wson_push_type_int(buffer, i); +} + +void GenWSONValue(wson_buffer* buffer, const std::string& str) { + wson_push_type_uint8_string( + buffer, reinterpret_cast(str.c_str()), str.size()); +} + +template +void GenWSONValue(wson_buffer* buffer, const std::vector& vector) { + wson_push_type_array(buffer, vector.size()); + for (auto it = vector.begin(); it != vector.end(); it++) { + GenWSONValue(buffer, *it); + } +} + +template +void GenWSONValue(wson_buffer* buffer, + const std::unordered_map& ref_map) { + wson_push_type_map(buffer, ref_map.size()); + for (auto it = ref_map.begin(); it != ref_map.end(); it++) { + if (it->first.empty()) continue; + // Use utf16 as wson only support utf16 as key in map + auto utf16_key = weex::base::to_utf16(const_cast(it->first.c_str()), + it->first.size()); + wson_push_uint(buffer, utf16_key.size() * sizeof(uint16_t)); + wson_push_bytes(buffer, utf16_key.c_str(), + utf16_key.size() * sizeof(uint16_t)); + GenWSONValue(buffer, it->second); + } +} + +static void UnpackAndGenWSONValue(wson_buffer* buffer) {} + +template +static void UnpackAndGenWSONValue(wson_buffer* buffer, T arg) { + GenWSONValue(buffer, std::forward(arg)); +} + +template +static void UnpackAndGenWSONValue(wson_buffer* buffer, T arg, Args... args) { + GenWSONValue(buffer, std::forward(arg)); + UnpackAndGenWSONValue(buffer, args...); +} + +template +static void GenParamsForCallJS(std::vector& params, + VComponent* component, const char* event, + int32_t id, size_t argc_inside, + Args... args_inside) { + auto page_id = component->exec_state()->context()->page_id(); + // page_id + params.push_back(Conversion::GenValueWithType(page_id.c_str())); + + // args -> { method: 'componentHook', args: [ id, 'lifecycle', + // event, [args_inside ] } + VALUE_WITH_TYPE* args = getValueWithTypePtr(); + args->type = ParamsType::BYTEARRAY; + auto buffer = wson_buffer_new(); + wson_push_type_array(buffer, 1); + wson_push_type_map(buffer, 2); + // key -> method + auto utf16_key_method = + weex::base::to_utf16(const_cast(kKeyMethod), strlen(kKeyMethod)); + wson_push_uint(buffer, utf16_key_method.size() * sizeof(uint16_t)); + wson_push_bytes(buffer, utf16_key_method.c_str(), + utf16_key_method.size() * sizeof(uint16_t)); + // value -> 'componentHook' + wson_push_type_uint8_string(buffer, + reinterpret_cast(kComponentHook), + strlen(kComponentHook)); + // key -> args + auto utf16_key_args = + weex::base::to_utf16(const_cast(kKeyArgs), strlen(kKeyArgs)); + wson_push_uint(buffer, utf16_key_args.size() * sizeof(uint16_t)); + wson_push_bytes(buffer, utf16_key_args.c_str(), + utf16_key_args.size() * sizeof(uint16_t)); + // value -> [ id, 'lifecycle', event, [ args_inside ] ] + { + wson_push_type_array(buffer, 4); + // templateId + wson_push_type_int(buffer, id); + // 'lifecycle' + wson_push_type_uint8_string(buffer, + reinterpret_cast(kLifecycle), + strlen(kLifecycle)); + // lifecycle + wson_push_type_uint8_string(buffer, reinterpret_cast(event), + strlen(event)); + // array -> [ args_inside ] + { + wson_push_type_array(buffer, argc_inside); + for (int i = 0; i < argc_inside; i++) { + UnpackAndGenWSONValue(buffer, args_inside...); + } + } + } + + args->value.byteArray = genWeexByteArray( + static_cast(buffer->data), buffer->position); + buffer->data = nullptr; + wson_buffer_free(buffer); + params.push_back(args); +} + +void VComponentLifecycleListener::OnCreated( + VComponent* component, Table* data, Table* props, + const std::unordered_map& ref_map) { + std::vector params; + // parentId + int parentId = kNonParentId; + if (component->parent() != NULL) { + parentId = component->parent()->component()->id(); + } + // [pageId, args] + // + // args -> { method: 'componentHook', args: [ templateId, 'lifecycle', + // lifecycle, [componentId, parentId, data, props, refList] ] } + GenParamsForCallJS(params, component, kEventOnCreated, + component->template_id(), 5, component->id(), parentId, + data, props, ref_map); + auto page_id = component->exec_state()->context()->page_id(); + WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( + page_id.c_str(), "", kMethodOnComponentEvent, params); + freeParams(params); +} + +void VComponentLifecycleListener::OnUpdated( + VComponent* component, Table* props, + const std::unordered_map& ref_map) { + auto page_id = component->exec_state()->context()->page_id(); + + std::vector params; + // [pageId, args] + // + // args -> { method: 'componentHook', args: [ componentId, 'lifecycle', + // lifecycle, [props, refList] ] } + GenParamsForCallJS(params, component, kEventOnUpdated, component->id(), 2, + props, ref_map); + WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( + page_id.c_str(), "", kMethodOnComponentEvent, params); + freeParams(params); +} + +void VComponentLifecycleListener::OnDestroyed(VComponent* component) { + auto page_id = component->exec_state()->context()->page_id(); + std::vector params; + // [pageId, args] + // + // args -> { method: 'componentHook', args: [ componentId, 'lifecycle', + // lifecycle, [] ] } + GenParamsForCallJS(params, component, kEventOnDestroyed, component->id(), 0); + WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( + page_id.c_str(), "", kMethodOnComponentEvent, params); + freeParams(params); +} +} // namespace data_render +} // namespace core +} // namespace weex + +#endif \ No newline at end of file diff --git a/weex_core/Source/core/data_render/vnode/android/vnode_on_event_listener.cc b/weex_core/Source/core/data_render/vnode/android/vnode_on_event_listener.cc new file mode 100644 index 0000000000..9afa37aa7d --- /dev/null +++ b/weex_core/Source/core/data_render/vnode/android/vnode_on_event_listener.cc @@ -0,0 +1,92 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 OS_ANDROID + +#include "core/data_render/vnode/vnode_on_event_listener.h" +#include "android/utils/params_utils.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/vnode/android/conversion.h" +#include "core/data_render/vnode/vcomponent.h" +#include "core/manager/weex_core_manager.h" +#include "include/WeexApiHeader.h" +#include "third_party/json11/json11.hpp" + +namespace weex { +namespace core { +namespace data_render { +static const char* kMethodCallJS = "callJS"; +static const char* kMethodFireEvent = "fireEvent"; +static const char* kKeyMethod = "method"; +static const char* kKeyArgs = "args"; +static const char* kKeyParams = "params"; + +void VNodeOnEventListener::OnEvent(VNode* node, const std::string& event, + const std::string& json_args, + const VNode::Params& param_list) { + auto page_id = node->component()->exec_state()->context()->page_id(); + std::vector params; + // page_id + params.push_back(Conversion::GenValueWithType(page_id.c_str())); + + // args -> { method: 'fireEvent', args: [ref, event, args ,{params: [...]}] } + VALUE_WITH_TYPE* args = getValueWithTypePtr(); + args->type = ParamsType::JSONSTRING; + std::vector args_object_list; + std::map args_object; + // method: 'FireEvent' + args_object.insert({kKeyMethod, kMethodFireEvent}); + + std::vector args_in_args_object; + // nodeId + args_in_args_object.push_back(node->render_object_ref()); + // event + args_in_args_object.push_back(event); + // args + std::string error; + args_in_args_object.push_back(json11::Json::parse(json_args, error)); + // params + std::map params_object; + std::vector array_in_params_object; + for (auto it = param_list.begin(); it != param_list.end(); it++) { + array_in_params_object.push_back(Conversion::GenJSON(&*it)); + } + params_object.insert({kKeyParams, array_in_params_object}); + args_in_args_object.push_back(params_object); + args_object.insert({kKeyArgs, args_in_args_object}); + args_object_list.push_back(args_object); + + json11::Json final_json(args_object_list); + auto temp = final_json.dump(); + auto final_json_str = temp.c_str(); + auto utf16_key = weex::base::to_utf16(const_cast(final_json_str), + strlen(final_json_str)); + args->value.string = genWeexString( + reinterpret_cast(utf16_key.c_str()), utf16_key.size()); + params.push_back(args); + + WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( + page_id.c_str(), "", kMethodCallJS, params); + freeParams(params); +} + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif \ No newline at end of file diff --git a/weex_core/Source/core/data_render/vnode/vcomponent.cc b/weex_core/Source/core/data_render/vnode/vcomponent.cc index 4736f0ac8b..7e66aada34 100644 --- a/weex_core/Source/core/data_render/vnode/vcomponent.cc +++ b/weex_core/Source/core/data_render/vnode/vcomponent.cc @@ -104,6 +104,8 @@ static void BuildRefsInner( ref_map.insert({node->ref(), refs}); } } + // Record { ref : node } in context + node->component()->exec_state()->context()->AddVNode(node->render_object_ref(), node); if (node->child_list()->size() > 0 && !node->IsVirtualComponent()) { if (node->attributes()->find("[[repeat]]") != node->attributes()->end()) { in_for_loop = true; @@ -115,6 +117,22 @@ static void BuildRefsInner( } } +static void DetachVNodesInContext(VNode *node) { + // Remove { ref : node } in context + if (!node || node->IsVirtualComponent()) return;; + auto context = node->component()->exec_state()->context(); + auto record = context->GetVNode(node->render_object_ref()); + if (record != node) { + context->RemoveVNode(node->render_object_ref()); + } + if (node->child_list()->size() > 0 && !node->IsVirtualComponent()) { + for (auto it = node->child_list()->begin(); it != node->child_list()->end(); + it++) { + DetachVNodesInContext(*it); + } + } +} + void VComponent::BuildRefMap() { ref_map_.clear(); BuildRefsInner(ref_map_, root_vnode(), false); @@ -179,9 +197,6 @@ void VComponent::UpdateData(Value *data) { } } -void VComponent::OnEvent(VNode *node, const std::string event, - std::vector params) {} - // TODO Depth-first traversal void VComponent::TravelVComponentsWithFunc(TravelTreeFunc func, VNode *root) { if (!root) return; @@ -235,6 +250,8 @@ void VComponent::DispatchDestroyed() { listener_->OnDestroyed(this); } TravelVComponentsWithFunc(&VComponent::DispatchDestroyed, root_vnode()); + exec_state_->context()->RemoveComponent(id_); + DetachVNodesInContext(root_vnode()); } void VComponent::SetRootNode(VNode *node) { diff --git a/weex_core/Source/core/data_render/vnode/vcomponent.h b/weex_core/Source/core/data_render/vnode/vcomponent.h index 9e37698697..a07aee57c7 100644 --- a/weex_core/Source/core/data_render/vnode/vcomponent.h +++ b/weex_core/Source/core/data_render/vnode/vcomponent.h @@ -19,7 +19,7 @@ #ifndef CORE_DATA_RENDER_VNODE_VCOMPONENT_H_ #define CORE_DATA_RENDER_VNODE_VCOMPONENT_H_ -#include +#include "core/data_render/object.h" #include #include "core/data_render/vnode/vnode.h" @@ -29,9 +29,10 @@ namespace data_render { class VComponent : public VNode { public: typedef std::unordered_map VNodeRef; - typedef std::vector> VNodeRefs; + typedef std::vector VNodeRefs; class LifecycleListener { public: + ~LifecycleListener() {} virtual void OnCreated( VComponent* component, Table* data, Table* props, const std::unordered_map& ref_map) = 0; @@ -45,7 +46,6 @@ class VComponent : public VNode { ~VComponent(); void UpdateData(); void UpdateData(Value* datas); - void OnEvent(VNode* node, const std::string event, std::vector params); inline bool IsSameNode(VComponent* old_component) { return template_id_ == old_component->template_id_; } diff --git a/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.cc b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.cc deleted file mode 100644 index 50c98501c7..0000000000 --- a/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.cc +++ /dev/null @@ -1,414 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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/data_render/vnode/vcomponent_lifecycle_listener.h" -#include -#include -#include -#include "core/data_render/exec_state.h" -#include "core/manager/weex_core_manager.h" - -namespace weex { -namespace core { -namespace data_render { - -//static const char* kMethodOnComponentEvent = "__onComponentEvent"; - static const char* kMethodOnComponentEvent = "callJS"; -static const char* kComponentHook = "componentHook"; -static const char* kLifecycle = "lifecycle"; -static const char* kKeyMethod = "method"; -static const char* kKeyArgs = "args"; -static const char* kEventOnCreated = "created"; -static const char* kEventOnUpdated = "updated"; -static const char* kEventOnDestroyed = "destroyed"; - -static VALUE_WITH_TYPE* GenValueWithType(const char* event_str) { - VALUE_WITH_TYPE* event = getValueWithTypePtr(); - event->type = ParamsType::BYTEARRAY; - auto buffer = wson_buffer_new(); - wson_push_type_uint8_string( - buffer, reinterpret_cast(event_str), strlen(event_str)); - event->value.byteArray = genWeexByteArray( - static_cast(buffer->data), buffer->position); - buffer->data = nullptr; - wson_buffer_free(buffer); - return event; -} - -inline static VALUE_WITH_TYPE* GenValueWithType(int i) { - VALUE_WITH_TYPE* event = getValueWithTypePtr(); - event->type = ParamsType::INT32; - event->value.int32Value = i; - return event; -} -static void GenWSONArray(wson_buffer* buffer, Array* array); -static void GenWSONTable(wson_buffer* buffer, Table* table); -static void GenWSONValue(wson_buffer* buffer, Value* value) { - switch (value->type) { - case Value::Type::ARRAY: - return GenWSONArray(buffer, ValueTo(value)); - case Value::Type::TABLE: - return GenWSONTable(buffer, ValueTo
(value)); - case Value::Type::INT: - wson_push_type_long(buffer, value->i); - break; - case Value::Type::NUMBER: - wson_push_type_double(buffer, value->n); - break; - case Value::Type::STRING: - wson_push_type_uint8_string( - buffer, reinterpret_cast(value->str->c_str()), - strlen(value->str->c_str())); - break; - case Value::Type::BOOL: - wson_push_type_boolean(buffer, value->b); - break; - default: - wson_push_type_null(buffer); - break; - } -} - -static void GenWSONArray(wson_buffer* buffer, Array* array) { - wson_push_type_array(buffer, array->items.size()); - for (auto it = array->items.begin(); it != array->items.end(); it++) { - GenWSONValue(buffer, &*it); - } -} - -static void GenWSONTable(wson_buffer* buffer, Table* table) { - wson_push_type_map(buffer, table->map.size()); - for (auto it = table->map.begin(); it != table->map.end(); it++) { - if (it->first.empty()) continue; - // Use utf16 as wson only support utf16 as key in map - auto utf16_key = weex::base::to_utf16(const_cast(it->first.c_str()), - it->first.size()); - wson_push_uint(buffer, utf16_key.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key.c_str(), - utf16_key.size() * sizeof(uint16_t)); - GenWSONValue(buffer, &it->second); - } -} -static void GenWSONValue(wson_buffer* buffer, const std::string& str); -template -static void GenWSONValue(wson_buffer* buffer, const std::vector& vector); -template -static void GenWSONValue(wson_buffer* buffer, - const std::unordered_map& ref_map); - -static void GenWSONValue(wson_buffer* buffer, Table* t) { - GenWSONTable(buffer, t); -} - -static void GenWSONValue(wson_buffer* buffer, int32_t i) { - wson_push_type_int(buffer, i); -} - -static void GenWSONValue(wson_buffer* buffer, const std::string& str) { - wson_push_type_uint8_string( - buffer, reinterpret_cast(str.c_str()), str.size()); -} - -template -static void GenWSONValue(wson_buffer* buffer, const std::vector& vector) { - wson_push_type_array(buffer, vector.size()); - for (auto it = vector.begin(); it != vector.end(); it++) { - GenWSONValue(buffer, *it); - } -} - -template -static void GenWSONValue( - wson_buffer* buffer, - const std::unordered_map& ref_map) { - wson_push_type_map(buffer, ref_map.size()); - for (auto it = ref_map.begin(); it != ref_map.end(); it++) { - if (it->first.empty()) continue; - // Use utf16 as wson only support utf16 as key in map - auto utf16_key = weex::base::to_utf16(const_cast(it->first.c_str()), - it->first.size()); - wson_push_uint(buffer, utf16_key.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key.c_str(), - utf16_key.size() * sizeof(uint16_t)); - GenWSONValue(buffer, it->second); - } -} - -//template -//static void GenParamsForCallJS(std::vector& params, VComponent* component, -// const char* event, int32_t id, size_t argc_inside, Args... args_inside) { -// auto page_id = component->exec_state()->context()->page_id(); -// // page_id -// params.push_back(GenValueWithType(page_id.c_str())); -// // args -> { method: 'componentHook', args: [ templateId, 'lifecycle', -// // lifecycle, [componentId, parentId, data, props, refList] ] } -// -// VALUE_WITH_TYPE* args = getValueWithTypePtr(); -// args->type = ParamsType::BYTEARRAY; -// auto buffer = wson_buffer_new(); -// wson_push_type_array(buffer, 1); -// wson_push_type_map(buffer, 2); -// // key -> method -// auto utf16_key_method = -// weex::base::to_utf16(const_cast(kKeyMethod), strlen(kKeyMethod)); -// wson_push_uint(buffer, utf16_key_method.size() * sizeof(uint16_t)); -// wson_push_bytes(buffer, utf16_key_method.c_str(), -// utf16_key_method.size() * sizeof(uint16_t)); -// // value -> 'componentHook' -// wson_push_type_uint8_string(buffer, -// reinterpret_cast(kComponentHook), -// strlen(kComponentHook)); -// // key -> args -// auto utf16_key_args = -// weex::base::to_utf16(const_cast(kKeyArgs), strlen(kKeyArgs)); -// wson_push_uint(buffer, utf16_key_args.size() * sizeof(uint16_t)); -// wson_push_bytes(buffer, utf16_key_args.c_str(), -// utf16_key_args.size() * sizeof(uint16_t)); -// // value -> [ templateId, 'lifecycle', lifecycle, [componentId, parentId, -// // data, props, refList] ] -// { -// wson_push_type_array(buffer, 4); -// // templateId -// wson_push_type_int(buffer, component->template_id()); -// // 'lifecycle' -// wson_push_type_uint8_string(buffer, -// reinterpret_cast(kLifecycle), -// strlen(kLifecycle)); -// // lifecycle -// wson_push_type_uint8_string( -// buffer, reinterpret_cast(event), -// strlen(event)); -// // array -> [componentId, parentId, data, props, refList] -// { -// wson_push_type_array(buffer, argc_inside); -// for (int i = 0; i < argc_inside; i++) { -// (GenWSONValue(std::forward< Args>(args_inside)),0)...); -// } -// } -// } -// -// args->value.byteArray = genWeexByteArray( -// static_cast(buffer->data), buffer->position); -// buffer->data = nullptr; -// wson_buffer_free(buffer); -// params.push_back(args); -//} - - - -void VComponentLifecycleListener::OnCreated( - VComponent* component, Table* data, Table* props, - const std::unordered_map& ref_map) { - auto page_id = component->exec_state()->context()->page_id(); - - std::vector params; - // page_id - params.push_back(GenValueWithType(page_id.c_str())); - // args -> { method: 'componentHook', args: [ templateId, 'lifecycle', - // lifecycle, [componentId, parentId, data, props, refList] ] } - - VALUE_WITH_TYPE* args = getValueWithTypePtr(); - args->type = ParamsType::BYTEARRAY; - auto buffer = wson_buffer_new(); - wson_push_type_array(buffer, 1); - wson_push_type_map(buffer, 2); - // key -> method - auto utf16_key_method = - weex::base::to_utf16(const_cast(kKeyMethod), strlen(kKeyMethod)); - wson_push_uint(buffer, utf16_key_method.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key_method.c_str(), - utf16_key_method.size() * sizeof(uint16_t)); - // value -> 'componentHook' - wson_push_type_uint8_string(buffer, - reinterpret_cast(kComponentHook), - strlen(kComponentHook)); - // key -> args - auto utf16_key_args = - weex::base::to_utf16(const_cast(kKeyArgs), strlen(kKeyArgs)); - wson_push_uint(buffer, utf16_key_args.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key_args.c_str(), - utf16_key_args.size() * sizeof(uint16_t)); - // value -> [ templateId, 'lifecycle', lifecycle, [componentId, parentId, - // data, props, refList] ] - { - wson_push_type_array(buffer, 4); - // templateId - wson_push_type_int(buffer, component->template_id()); - // 'lifecycle' - wson_push_type_uint8_string(buffer, - reinterpret_cast(kLifecycle), - strlen(kLifecycle)); - // lifecycle - wson_push_type_uint8_string( - buffer, reinterpret_cast(kEventOnCreated), - strlen(kEventOnCreated)); - // array -> [componentId, parentId, data, props, refList] - { - wson_push_type_array(buffer, 5); - // componentId - wson_push_type_int(buffer, component->id()); - // parentId - if (component->parent() != NULL) { - wson_push_type_int(buffer, component->parent()->component()->id()); - } else { - wson_push_type_int(buffer, INT32_MAX); - } - // data - GenWSONTable(buffer, data); - // props - GenWSONTable(buffer, props); - // refList - GenWSONValue(buffer, ref_map); - } - } - - args->value.byteArray = genWeexByteArray( - static_cast(buffer->data), buffer->position); - buffer->data = nullptr; - wson_buffer_free(buffer); - params.push_back(args); - - WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( - page_id.c_str(), "", kMethodOnComponentEvent, params); - freeParams(params); -} - -void VComponentLifecycleListener::OnUpdated( - VComponent* component, Table* props, - const std::unordered_map& ref_map) { - auto page_id = component->exec_state()->context()->page_id(); - - std::vector params; - // page_id - params.push_back(GenValueWithType(page_id.c_str())); - // args -> { method: 'componentHook', args: [ componentId, 'lifecycle', - // lifecycle, [props, refList] ] } - - VALUE_WITH_TYPE* args = getValueWithTypePtr(); - args->type = ParamsType::BYTEARRAY; - auto buffer = wson_buffer_new(); - wson_push_type_array(buffer, 1); - wson_push_type_map(buffer, 2); - // key -> method - auto utf16_key_method = - weex::base::to_utf16(const_cast(kKeyMethod), strlen(kKeyMethod)); - wson_push_uint(buffer, utf16_key_method.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key_method.c_str(), - utf16_key_method.size() * sizeof(uint16_t)); - // value -> 'componentHook' - wson_push_type_uint8_string(buffer, - reinterpret_cast(kComponentHook), - strlen(kComponentHook)); - // key -> args - auto utf16_key_args = - weex::base::to_utf16(const_cast(kKeyArgs), strlen(kKeyArgs)); - wson_push_uint(buffer, utf16_key_args.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key_args.c_str(), - utf16_key_args.size() * sizeof(uint16_t)); - // value -> [ componentId, 'lifecycle', lifecycle, [props, refList] ] - { - wson_push_type_array(buffer, 4); - // componentId - wson_push_type_int(buffer, component->id()); - // 'lifecycle' - wson_push_type_uint8_string(buffer, - reinterpret_cast(kLifecycle), - strlen(kLifecycle)); - // lifecycle - wson_push_type_uint8_string( - buffer, reinterpret_cast(kEventOnUpdated), - strlen(kEventOnUpdated)); - // array -> [props, refList] - { - wson_push_type_array(buffer, 2); - // props - GenWSONTable(buffer, props); - // refList - GenWSONValue(buffer, ref_map); - } - } - args->value.byteArray = genWeexByteArray( - static_cast(buffer->data), buffer->position); - buffer->data = nullptr; - wson_buffer_free(buffer); - params.push_back(args); - - WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( - page_id.c_str(), "", kMethodOnComponentEvent, params); - freeParams(params); -} - -void VComponentLifecycleListener::OnDestroyed(VComponent* component) { - auto page_id = component->exec_state()->context()->page_id(); - std::vector params; - // page_id - params.push_back(GenValueWithType(page_id.c_str())); - // args -> { method: 'componentHook', args: [ componentId, 'lifecycle', - // lifecycle, [] ] } - - VALUE_WITH_TYPE* args = getValueWithTypePtr(); - args->type = ParamsType::BYTEARRAY; - auto buffer = wson_buffer_new(); - wson_push_type_array(buffer, 1); - wson_push_type_map(buffer, 2); - // key -> method - auto utf16_key_method = - weex::base::to_utf16(const_cast(kKeyMethod), strlen(kKeyMethod)); - wson_push_uint(buffer, utf16_key_method.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key_method.c_str(), - utf16_key_method.size() * sizeof(uint16_t)); - // value -> 'componentHook' - wson_push_type_uint8_string(buffer, - reinterpret_cast(kComponentHook), - strlen(kComponentHook)); - // key -> args - auto utf16_key_args = - weex::base::to_utf16(const_cast(kKeyArgs), strlen(kKeyArgs)); - wson_push_uint(buffer, utf16_key_args.size() * sizeof(uint16_t)); - wson_push_bytes(buffer, utf16_key_args.c_str(), - utf16_key_args.size() * sizeof(uint16_t)); - // value -> [ componentId, 'lifecycle', lifecycle, [props, refList] ] - { - wson_push_type_array(buffer, 4); - // componentId - wson_push_type_int(buffer, component->id()); - // 'lifecycle' - wson_push_type_uint8_string(buffer, - reinterpret_cast(kLifecycle), - strlen(kLifecycle)); - // lifecycle - wson_push_type_uint8_string( - buffer, reinterpret_cast(kEventOnDestroyed), - strlen(kEventOnDestroyed)); - // array -> [] - { wson_push_type_array(buffer, 0); } - } - args->value.byteArray = genWeexByteArray( - static_cast(buffer->data), buffer->position); - buffer->data = nullptr; - wson_buffer_free(buffer); - params.push_back(args); - - WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( - page_id.c_str(), "", kMethodOnComponentEvent, params); - freeParams(params); -} -} // namespace data_render -} // namespace core -} // namespace weex \ No newline at end of file diff --git a/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h index 9785d486ff..3cd6c71eea 100644 --- a/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h +++ b/weex_core/Source/core/data_render/vnode/vcomponent_lifecycle_listener.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef WEEX_PROJECT_VCOMPONENT_LIFECYCLE_LISTENER_H -#define WEEX_PROJECT_VCOMPONENT_LIFECYCLE_LISTENER_H +#ifndef CORE_DATA_RENDER_VNODE_VCOMPONENT_LIFECYCLE_LISTENER_H_ +#define CORE_DATA_RENDER_VNODE_VCOMPONENT_LIFECYCLE_LISTENER_H_ #include "core/data_render/vnode/vcomponent.h" @@ -38,4 +38,4 @@ class VComponentLifecycleListener : public VComponent::LifecycleListener { } // namespace core } // namespace weex -#endif // WEEX_PROJECT_VCOMPONENT_LIFECYCLE_LISTENER_H +#endif // CORE_DATA_RENDER_VNODE_VCOMPONENT_LIFECYCLE_LISTENER_H_ diff --git a/weex_core/Source/core/data_render/vnode/vnode.cc b/weex_core/Source/core/data_render/vnode/vnode.cc index e61ee45094..33895261cb 100644 --- a/weex_core/Source/core/data_render/vnode/vnode.cc +++ b/weex_core/Source/core/data_render/vnode/vnode.cc @@ -34,6 +34,7 @@ VNode::VNode(const std::string &tag_name, const std::string &node_id, attributes_ = new std::map(); events_ = new std::map(); event_params_map_.reset(new EventParamsMap); + on_event_listener_.reset(); } VNode::~VNode() { @@ -61,9 +62,15 @@ VNode::~VNode() { } } -const VNode::ParamsList &VNode::GetParamsList(const std::string &event) { +void VNode::OnEvent(const std::string &event, const std::string args) { + if (!on_event_listener_) return; + auto it = event_params_map_->find(event); - return it != event_params_map_->end() ? it->second : ParamsList(); + if (it == event_params_map_->end()) return; + auto params_list = it->second; + for (auto it = params_list.begin(); it != params_list.end(); it++) { + on_event_listener_->OnEvent(this, event, args, *it); + } } void VNode::SetStyle(const std::string &key, const std::string &value) { diff --git a/weex_core/Source/core/data_render/vnode/vnode.h b/weex_core/Source/core/data_render/vnode/vnode.h index 305aa1756e..d7ad64a2f2 100644 --- a/weex_core/Source/core/data_render/vnode/vnode.h +++ b/weex_core/Source/core/data_render/vnode/vnode.h @@ -39,6 +39,14 @@ class VNode { typedef std::vector ParamsList; typedef std::unordered_map EventParamsMap; + class OnEventListener { + public: + ~OnEventListener() {} + virtual void OnEvent(VNode *node, const std::string &event, + const std::string &json_args, + const Params ¶ms) = 0; + }; + VNode(const std::string &tag_name, const std::string &node_id, const std::string &ref); @@ -52,6 +60,8 @@ class VNode { const std::vector ¶ms); void AddEvent(const std::string &event, void *func, void *inst); + void AddOnEventListener(); + void AddChild(VNode *child); void RemoveChild(VNode *child); @@ -92,7 +102,11 @@ class VNode { return event_params_map_.get(); } - const ParamsList& GetParamsList(const std::string& event); + void OnEvent(const std::string& event, const std::string args); + + inline void set_on_event_listener(std::unique_ptr listener) { + on_event_listener_ = std::move(listener); + } inline bool HasChildren() { return !child_list_.empty(); } @@ -122,8 +136,11 @@ class VNode { std::vector child_list_; std::map *styles_; std::map *attributes_; + // This events if record event with func from vm std::map *events_; + // This events if record event with value from vm std::unique_ptr event_params_map_; + std::unique_ptr on_event_listener_; void MapInsertOrAssign(std::map *target_map, const std::string &key, const std::string &value); diff --git a/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc b/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc index 2496419b0c..7dbf44f699 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc +++ b/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc @@ -30,6 +30,7 @@ #include "core/data_render/vnode/vcomponent.h" #include "core/data_render/vnode/vnode_render_manager.h" #include "core/data_render/vnode/vcomponent_lifecycle_listener.h" +#include "core/data_render/vnode/vnode_on_event_listener.h" #include namespace weex { @@ -289,7 +290,7 @@ static Value CreateComponent(ExecState* exec_state) { component->set_life_cycle_listener( std::unique_ptr( new VComponentLifecycleListener)); - exec_state->context()->add_component(component->id(), component); + exec_state->context()->AddComponent(component->id(), component); return result; } @@ -557,6 +558,8 @@ static Value AddEvent(ExecState* exec_state) { return Value(); } node->AddEvent(event->str->c_str(), args); + node->set_on_event_listener( + std::unique_ptr(new VNodeOnEventListener)); return Value(); } diff --git a/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h b/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h new file mode 100644 index 0000000000..f11801d921 --- /dev/null +++ b/weex_core/Source/core/data_render/vnode/vnode_on_event_listener.h @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 CORE_DATA_RENDER_VNODE_VNODE_ON_EVENT_LISTENER_H_ +#define CORE_DATA_RENDER_VNODE_VNODE_ON_EVENT_LISTENER_H_ + +#include "core/data_render/vnode/vnode.h" + +namespace weex { +namespace core { +namespace data_render { + +class VNodeOnEventListener : public VNode::OnEventListener { + void OnEvent(VNode *node, const std::string &event, + const std::string &json_args, const VNode::Params ¶ms); +}; + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // CORE_DATA_RENDER_VNODE_VNODE_ON_EVENT_LISTENER_H_ diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc b/weex_core/Source/core/data_render/vnode/vnode_render_context.cc index 2ebccf2c77..158e7eaa77 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_render_context.cc +++ b/weex_core/Source/core/data_render/vnode/vnode_render_context.cc @@ -24,7 +24,12 @@ namespace core { namespace data_render { VNodeRenderContext::VNodeRenderContext() - : page_id_(), root_(nullptr), raw_json_(), script_(), vcomponent_trees_() {} + : page_id_(), + root_(nullptr), + raw_json_(), + script_(), + vcomponent_trees_(), + vnode_trees_() {} VNodeRenderContext::~VNodeRenderContext() {} diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.h b/weex_core/Source/core/data_render/vnode/vnode_render_context.h index 4e64c5d544..622d435764 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_render_context.h +++ b/weex_core/Source/core/data_render/vnode/vnode_render_context.h @@ -47,15 +47,40 @@ class VNodeRenderContext { return style_json_; } - inline void add_component(int ref, VComponent* component) { + inline void AddComponent(int ref, VComponent *component) { vcomponent_trees_.insert({ref, component}); } + inline void RemoveComponent(int ref) { + vcomponent_trees_.erase(ref); + } + inline VComponent* GetComponent(int ref) { auto it = vcomponent_trees_.find(ref); return it != vcomponent_trees_.end() ? it->second : nullptr; } + inline void RemoveVNode(const std::string& ref) { + auto it = vnode_trees_.find(ref); + if (it != vnode_trees_.end()) { + vnode_trees_.erase(it); + } + } + + inline void AddVNode(const std::string& ref, VNode* node) { + auto it = vnode_trees_.find(ref); + if (it != vnode_trees_.end()) { + vnode_trees_[ref] = node; + } else { + vnode_trees_.insert({ref, node}); + } + } + + inline VNode* GetVNode(const std::string &ref) { + auto it = vnode_trees_.find(ref); + return it != vnode_trees_.end() ? it->second : nullptr; + } + private: // node context std::string page_id_; @@ -66,6 +91,7 @@ class VNodeRenderContext { std::string script_; std::map style_json_; std::unordered_map vcomponent_trees_; + std::unordered_map vnode_trees_; }; } // namespace data_render } // namespace core diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc b/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc index 2cf5cd2e68..dabe741ddf 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc +++ b/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc @@ -96,14 +96,19 @@ WeexCore::RenderObject* ParseVNode2RenderObject(VNode* vnode, render_object->AddAttr(it->first, it->second); } - // event,todo + // event std::map *events = vnode->events(); for (auto iter = events->begin(); iter != events->end(); iter++) { render_object->events()->insert(iter->first); } + auto event_params_map = vnode->event_params_map(); + for (auto it = event_params_map->begin(); it != event_params_map->end(); + it++) { + render_object->events()->insert(it->first); + } // child - vector* children = (const_cast(vnode))->child_list(); + vector* children = vnode->child_list(); for (int i = 0; i < children->size(); i++) { ParseVNode2RenderObject((*children)[i], render_object, false, i, pageId); } @@ -361,7 +366,23 @@ void VNodeRenderManager::FireEvent(const std::string &page_id, const std::string if (node == vnode_trees_.end()) { break; } + // TODO merge two way to fire event + { + // First way to fire event from VNode::OnEvent + auto vnode = iter->second->context()->GetVNode(ref); + if (vnode) { + auto hit_test = vnode->event_params_map()->find(event); + if (hit_test != vnode->event_params_map()->end()) { + // If vnode has eat event, return. + vnode->OnEvent(event, args); + return; + } + } + } + + // Second way to fire event from call vm func auto vnode = node->second->FindNode(ref); + if (vnode == nullptr) if (!vnode) { break; } @@ -707,7 +728,6 @@ vector>* CompareMap(const map& oldMap, auto p_vec = new vector>(); for (auto it = newMap.cbegin(); it != newMap.cend(); it++) { auto pos = oldMap.find(it->first); - if (pos == oldMap.end() || pos->second != it->second) { // key not exist, or value not same p_vec->push_back({it->first, it->second}); @@ -716,7 +736,6 @@ vector>* CompareMap(const map& oldMap, for (auto it = oldMap.cbegin(); it != oldMap.cend(); it++) { auto pos = newMap.find(it->first); - if (pos == newMap.end()) { // key not exist, remove //todo check if this is correct p_vec->push_back({it->first, ""}); @@ -724,7 +743,63 @@ vector>* CompareMap(const map& oldMap, } return p_vec; }; - + +void CompareAndApplyEvents1(const std::string& page_id, VNode* old_node, + VNode* new_node) { + std::map old_events = *old_node->events(); + std::map new_events = *new_node->events(); + + for (auto it = old_events.cbegin(); it != old_events.cend(); it++) { + auto pos = new_events.find(it->first); + if (pos == new_events.end()) { + new_events.erase(pos); + } + } + for (auto it = new_events.cbegin(); it != new_events.cend(); it++) { + auto pos = old_events.find(it->first); + if (pos == old_events.end()) { + old_events.erase(pos); + } + } + for (auto it = old_events.cbegin(); it != old_events.cend(); it++) { + RenderManager::GetInstance()->RemoveEvent( + page_id, new_node->render_object_ref(), it->first); + } + for (auto it = new_events.cbegin(); it != new_events.cend(); it++) { + RenderManager::GetInstance()->AddEvent( + page_id, new_node->render_object_ref(), it->first); + } +} + +void CompareAndApplyEvents2(const std::string& page_id, VNode* old_node, + VNode* new_node) { + VNode::EventParamsMap old_events = *old_node->event_params_map(); + VNode::EventParamsMap new_events = *new_node->event_params_map(); + + for (auto it = old_events.cbegin(); it != old_events.cend(); it++) { + auto pos = new_events.find(it->first); + + if (pos == new_events.end()) { + new_events.erase(pos); + } + } + for (auto it = new_events.cbegin(); it != new_events.cend(); it++) { + auto pos = old_events.find(it->first); + + if (pos == old_events.end()) { + old_events.erase(pos); + } + } + for (auto it = old_events.cbegin(); it != old_events.cend(); it++) { + RenderManager::GetInstance()->RemoveEvent( + page_id, new_node->render_object_ref(), it->first); + } + for (auto it = new_events.cbegin(); it != new_events.cend(); it++) { + RenderManager::GetInstance()->AddEvent( + page_id, new_node->render_object_ref(), it->first); + } +} + void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) { if (old_node->IsVirtualComponent()) { static_cast(old_node) @@ -752,8 +827,9 @@ void PatchVNode(const string& page_id, VNode* old_node, VNode* new_node) { p_vec = nullptr; } - // compare event - // todo + // compare and apply event + CompareAndApplyEvents1(page_id, old_node, new_node); + CompareAndApplyEvents2(page_id, old_node, new_node); // compare children if (old_node->HasChildren() && new_node->HasChildren()) {