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