• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 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
16interface NodeInfo {
17    nodeId: number,
18    nodePtr: NodePtr
19}
20
21class NodeAdapter {
22    nativePtr_: NodePtr;
23    nativeRef_: NativeStrongRef;
24    nodeRefs_: Array<FrameNode> = new Array();
25    count_: number = 0;
26    attachedNodeRef_: WeakRef<FrameNode>;
27
28    onAttachToNode?: (target: FrameNode) => void;
29    onDetachFromNode?: () => void;
30    onGetChildId?: (index: number) => number;
31    onCreateChild?: (index: number) => FrameNode;
32    onDisposeChild?: (id: number, node: FrameNode) => void;
33    onUpdateChild?: (id: number, node: FrameNode) => void;
34
35    constructor() {
36        this.nativeRef_ = getUINativeModule().nodeAdapter.createAdapter();
37        this.nativePtr_ = this.nativeRef_.getNativeHandle();
38        getUINativeModule().nodeAdapter.setCallbacks(this.nativePtr_, this,
39            this.onAttachToNodePtr, this.onDetachFromNodePtr,
40            this.onGetChildId !== undefined ? this.onGetChildId : undefined,
41            this.onCreateChild !== undefined ? this.onCreateNewNodePtr : undefined,
42            this.onDisposeChild !== undefined ? this.onDisposeNodePtr : undefined,
43            this.onUpdateChild !== undefined ? this.onUpdateNodePtr : undefined
44        );
45    }
46
47    dispose(): void {
48        let hostNode = this.attachedNodeRef_.deref();
49        if (hostNode !== undefined) {
50            NodeAdapter.detachNodeAdapter(hostNode);
51        }
52        this.nativeRef_.dispose();
53        this.nativePtr_ = null;
54    }
55
56    set totalNodeCount(count: number) {
57        if (count < 0) {
58            return;
59        }
60        getUINativeModule().nodeAdapter.setTotalNodeCount(this.nativePtr_, count);
61        this.count_ = count;
62    }
63
64    get totalNodeCount(): number {
65        return this.count_;
66    }
67
68    reloadAllItems(): void {
69        getUINativeModule().nodeAdapter.notifyItemReloaded(this.nativePtr_);
70    }
71
72    reloadItem(start: number, count: number): void {
73        if (start < 0 || count < 0) {
74            return;
75        }
76        getUINativeModule().nodeAdapter.notifyItemChanged(this.nativePtr_, start, count);
77    }
78
79    removeItem(start: number, count: number): void {
80        if (start < 0 || count < 0) {
81            return;
82        }
83        getUINativeModule().nodeAdapter.notifyItemRemoved(this.nativePtr_, start, count);
84    }
85
86    insertItem(start: number, count: number): void {
87        if (start < 0 || count < 0) {
88            return;
89        }
90        getUINativeModule().nodeAdapter.notifyItemInserted(this.nativePtr_, start, count);
91    }
92
93    moveItem(from: number, to: number): void {
94        if (from < 0 || to < 0) {
95            return;
96        }
97        getUINativeModule().nodeAdapter.notifyItemMoved(this.nativePtr_, from, to);
98    }
99
100    getAllAvailableItems(): Array<FrameNode> {
101        let result: Array<FrameNode> = new Array();
102        let nodes: Array<NodeInfo> = getUINativeModule().nodeAdapter.getAllItems(this.nativePtr_);
103        if (nodes !== undefined) {
104            nodes.forEach(node => {
105                let nodeId = node.nodeId;
106                if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) {
107                    let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref();
108                    result.push(frameNode);
109                }
110            });
111        }
112        return result;
113    }
114
115    onAttachToNodePtr(target: NodeInfo): void {
116        let nodeId = target.nodeId;
117        if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) {
118            let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref();
119            if (frameNode === undefined) {
120                return;
121            }
122            frameNode.setAdapterRef(this);
123            this.attachedNodeRef_ = new WeakRef(frameNode);
124            if (this.onAttachToNode !== undefined) {
125                this.onAttachToNode(frameNode);
126            }
127        }
128    }
129
130    onDetachFromNodePtr(): void {
131        if (this === undefined) {
132            return;
133        }
134        if (this.onDetachFromNode !== undefined) {
135            this.onDetachFromNode();
136        }
137        let attachedNode = this.attachedNodeRef_.deref();
138        if (attachedNode !== undefined) {
139            attachedNode.setAdapterRef(undefined);
140        }
141        this.nodeRefs_.splice(0, this.nodeRefs_.length);
142    }
143
144    onCreateNewNodePtr(index: number): NodePtr {
145        if (this.onCreateChild !== undefined) {
146            let node = this.onCreateChild(index);
147            if (!this.nodeRefs_.includes(node)) {
148                this.nodeRefs_.push(node);
149            }
150            return node.getNodePtr();
151        }
152        return null;
153    }
154
155    onDisposeNodePtr(id: number, node: NodeInfo): void {
156        let nodeId = node.nodeId;
157        if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) {
158            let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref();
159            if (this.onDisposeChild !== undefined && frameNode !== undefined) {
160                this.onDisposeChild(id, frameNode);
161                let index = this.nodeRefs_.indexOf(frameNode);
162                if (index > -1) {
163                    this.nodeRefs_.splice(index, 1);
164                }
165            }
166        }
167    }
168
169    onUpdateNodePtr(id: number, node: NodeInfo): void {
170        let nodeId = node.nodeId;
171        if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) {
172            let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref();
173            if (this.onUpdateChild !== undefined && frameNode !== undefined) {
174                this.onUpdateChild(id, frameNode);
175            }
176        }
177    }
178
179    static attachNodeAdapter(adapter: NodeAdapter, node: FrameNode): boolean {
180        if (node === null || node === undefined) {
181            return false;
182        }
183        if (!node.isModifiable()) {
184            return false;
185        }
186        const hasAttributeProperty = Object.prototype.hasOwnProperty.call(node, 'attribute_');
187        if (hasAttributeProperty) {
188            let frameeNode = node as TypedFrameNode<ArkComponent>;
189            if (frameeNode.attribute_.allowChildCount !== undefined) {
190                const allowCount = frameeNode.attribute_.allowChildCount();
191                if (allowCount <= 1) {
192                    return false;
193                }
194            }
195        }
196        return getUINativeModule().nodeAdapter.attachNodeAdapter(adapter.nativePtr_, node.getNodePtr());
197    }
198
199    static detachNodeAdapter(node: FrameNode) {
200        if (node === null || node === undefined) {
201            return;
202        }
203        getUINativeModule().nodeAdapter.detachNodeAdapter(node.getNodePtr());
204    }
205}