mirror of
https://github.com/Tencent/Hippy.git
synced 2026-10-26 11:10:06 +08:00
318 lines
8.8 KiB
Dart
318 lines
8.8 KiB
Dart
//
|
|
// Tencent is pleased to support the open source community by making
|
|
// Hippy available.
|
|
//
|
|
// Copyright (C) 2022 THL A29 Limited, a Tencent company.
|
|
// All rights reserved.
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
import '../common.dart';
|
|
import '../engine.dart';
|
|
import '../render.dart';
|
|
import '../style.dart';
|
|
import '../util.dart';
|
|
import '../viewmodel.dart';
|
|
import 'controller.dart';
|
|
import 'div.dart';
|
|
import 'generator.dart';
|
|
import 'registry.dart';
|
|
import 'update.dart';
|
|
|
|
class ControllerManager implements InstanceLifecycleEventListener {
|
|
final RenderContext _context;
|
|
final ControllerRegistry _controllerRegistry;
|
|
|
|
ControllerManager(
|
|
this._context,
|
|
List<ViewControllerGenerator>? generators,
|
|
) : _controllerRegistry = ControllerRegistry() {
|
|
_context.addInstanceLifecycleEventListener(this);
|
|
processControllers(generators);
|
|
}
|
|
|
|
void processControllers(List<ViewControllerGenerator>? generators) {
|
|
if (generators == null || generators.isEmpty) {
|
|
return;
|
|
}
|
|
|
|
for (var controllerFactory in generators) {
|
|
_controllerRegistry.addControllerHolder(
|
|
controllerFactory.name,
|
|
ControllerHolder(
|
|
controllerFactory.generateController,
|
|
controllerFactory.isLazy,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
RenderContext get context => _context;
|
|
|
|
void destroy() {
|
|
_context.removeInstanceLifecycleEventListener(this);
|
|
_controllerRegistry.forEachRenderTree(deleteRoot);
|
|
}
|
|
|
|
void deleteRoot(int id, [RenderTree? renderTree]) {
|
|
final _renderTree = renderTree ?? _controllerRegistry.getRenderTree(id);
|
|
if (_renderTree != null) {
|
|
_renderTree.clear();
|
|
_controllerRegistry.removeRenderTree(_renderTree);
|
|
}
|
|
}
|
|
|
|
void deleteChild(RenderViewModel? parentViewModel, RenderViewModel? childViewModel,
|
|
{int childIndex = -1}) {
|
|
if (parentViewModel is GroupViewModel && childViewModel != null) {
|
|
deleteChildRecursive(parentViewModel, childViewModel, childIndex);
|
|
}
|
|
}
|
|
|
|
void deleteChildRecursive(GroupViewModel? viewParent, RenderViewModel? child, int childIndex) {
|
|
if (viewParent == null || child == null) {
|
|
return;
|
|
}
|
|
var childName = child.name;
|
|
|
|
var childViewController = _controllerRegistry.getViewController(childName);
|
|
if (childViewController != null) {
|
|
childViewController.onViewDestroy(child);
|
|
}
|
|
|
|
if (child is GroupViewModel) {
|
|
for (var i = child.childCount - 1; i >= 0; i--) {
|
|
var nextChild = child.getChildAt(i);
|
|
if (nextChild != null) {
|
|
deleteChildRecursive(child, nextChild, -1);
|
|
}
|
|
}
|
|
}
|
|
|
|
viewParent.removeViewModel(child);
|
|
}
|
|
|
|
VirtualNode? createVirtualNode(
|
|
int id,
|
|
int pid,
|
|
int index,
|
|
String className,
|
|
VoltronMap props,
|
|
) {
|
|
var controller = findController(className);
|
|
if (controller != null) {
|
|
return controller.createVirtualNode(
|
|
id,
|
|
pid,
|
|
index,
|
|
className,
|
|
props,
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
void createViewModel(RenderNode node, VoltronMap? initialProps) {
|
|
var controller = findController(node.name);
|
|
if (controller != null && node.checkRenderViewModel()) {
|
|
ControllerUpdateUtil.updateProps(controller, node, initialProps);
|
|
controller.onAfterUpdateProps(_context, node);
|
|
}
|
|
}
|
|
|
|
bool hasNode(RenderNode node) {
|
|
return findNode(node.rootId, node.id) == node;
|
|
}
|
|
|
|
RenderNode? findNode(int instanceId, int id) {
|
|
if (instanceId < 0) {
|
|
return null;
|
|
}
|
|
return _controllerRegistry.getRenderNode(instanceId, id);
|
|
}
|
|
|
|
RenderTree? findTree(int instanceId) {
|
|
if (instanceId < 0) {
|
|
return null;
|
|
}
|
|
return _controllerRegistry.getRenderTree(instanceId);
|
|
}
|
|
|
|
VoltronViewController? findController(String name, {bool canFindRootNode = false}) {
|
|
if (name == NodeProps.kRootNode && !canFindRootNode) {
|
|
return null;
|
|
}
|
|
var controller = _controllerRegistry.getViewController(name);
|
|
if (controller == null) {
|
|
return _controllerRegistry.getViewController(DivController.kClassName);
|
|
}
|
|
|
|
return controller;
|
|
}
|
|
|
|
void updateWidget(RenderNode? node, VoltronMap? newProps) {
|
|
if (node != null && newProps != null && newProps.size() > 0) {
|
|
final controller = findController(node.name);
|
|
|
|
if (controller != null) {
|
|
ControllerUpdateUtil.updateProps(controller, node, newProps);
|
|
controller.onAfterUpdateProps(_context, node);
|
|
}
|
|
}
|
|
}
|
|
|
|
void addChild(RenderNode parentNode, RenderNode childNode, int index) {
|
|
var childViewModel = childNode.renderViewModel;
|
|
var parentViewModel = parentNode.renderViewModel;
|
|
|
|
if (parentViewModel is GroupViewModel) {
|
|
parentViewModel.addViewModel(childViewModel, index);
|
|
} else {
|
|
Error exception = StateError(
|
|
"${"child null or parent not ViewGroup pid ${parentNode.id}"} parentClass ${parentNode.name} renderNodeClass ${childNode.name}${" id ${childNode.id}"}",
|
|
);
|
|
_context.handleNativeException(exception, true);
|
|
}
|
|
}
|
|
|
|
void move(RenderNode node, RenderNode toNode, int index) {
|
|
var viewModel = node.renderViewModel;
|
|
|
|
var oldParent = viewModel.parent;
|
|
if (oldParent != null && oldParent is GroupViewModel) {
|
|
oldParent.removeViewModel(viewModel);
|
|
}
|
|
var newParent = toNode.renderViewModel;
|
|
if (newParent is GroupViewModel) {
|
|
newParent.addViewModel(viewModel, index);
|
|
}
|
|
|
|
LogUtils.d(
|
|
"ControllerManager",
|
|
"move id: ${node.id} fromId:${oldParent?.id} toId:${newParent.id} ",
|
|
);
|
|
}
|
|
|
|
void updateLayout(RenderNode node) {
|
|
final controller = findController(node.name);
|
|
if (controller != null) {
|
|
controller.updateLayout(_context, node);
|
|
}
|
|
}
|
|
|
|
void updateExtra(RenderNode node, Object updateExtra) {
|
|
final controller = findController(node.name);
|
|
if (controller != null) {
|
|
controller.updateExtra(node.renderViewModel, updateExtra);
|
|
}
|
|
}
|
|
|
|
void updateEvents(RenderNode node, Set<EventHolder> holders) {
|
|
final controller = findController(node.name, canFindRootNode: true);
|
|
if (controller != null) {
|
|
controller.updateEvents(node.renderViewModel, holders);
|
|
}
|
|
}
|
|
|
|
void applyProps(RenderNode node) {
|
|
final controller = findController(node.name);
|
|
if (controller != null) {
|
|
controller.applyProps(context, node);
|
|
}
|
|
}
|
|
|
|
RenderNode? createRenderNode(int id, VoltronMap? props, String name, RenderTree tree, bool lazy) {
|
|
final controller = findController(name);
|
|
if (controller != null) {
|
|
return controller.createRenderNode(id, props, name, tree, this, lazy);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
void dispatchUIFunction(
|
|
int instanceId,
|
|
int id,
|
|
String name,
|
|
String functionName,
|
|
VoltronArray params,
|
|
Promise promise,
|
|
) {
|
|
final node = findNode(instanceId, id);
|
|
final controller = findController(name);
|
|
if (node != null && controller != null) {
|
|
controller.dispatchFunction(
|
|
node.renderViewModel,
|
|
functionName,
|
|
params,
|
|
promise: promise.isCallback() ? promise : null,
|
|
);
|
|
}
|
|
}
|
|
|
|
void batchComplete(RenderNode? node) {
|
|
if (node != null) {
|
|
final controller = findController(node.name);
|
|
controller?.onBatchComplete(node);
|
|
}
|
|
}
|
|
|
|
void manageChildComplete(RenderNode node) {
|
|
final controller = findController(node.name);
|
|
controller?.onManageChildComplete(node);
|
|
}
|
|
|
|
@override
|
|
void onInstanceDestroy(int instanceId) {}
|
|
|
|
@override
|
|
void onInstanceLoad(int instanceId) {
|
|
tryInitRoot(instanceId);
|
|
}
|
|
|
|
bool isControllerLazy(String name) {
|
|
return _controllerRegistry.getControllerHolder(name)?.isLazy ?? false;
|
|
}
|
|
|
|
RenderNode? createRootNode(int instanceId) {
|
|
return tryInitRoot(instanceId);
|
|
}
|
|
|
|
RenderNode? tryInitRoot(int instanceId) {
|
|
var viewModel = _context.getInstance(instanceId);
|
|
if (viewModel != null) {
|
|
var tree = _controllerRegistry.getRenderTree(instanceId);
|
|
if (tree == null) {
|
|
tree = RenderTree(instanceId, viewModel);
|
|
_controllerRegistry.addRenderTree(tree);
|
|
}
|
|
|
|
var node = _controllerRegistry.getRenderNode(instanceId, instanceId);
|
|
if (node == null) {
|
|
node = RootRenderNode(instanceId, NodeProps.kRootNode, tree, this, null);
|
|
tree.init(node);
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
@override
|
|
void onInstancePause(int instanceId) {}
|
|
|
|
@override
|
|
void onInstanceResume(int instanceId) {}
|
|
}
|