1/* 2 * Copyright (c) 2023-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 LayoutConstraint { 17 maxSize: Size; 18 minSize: Size; 19 percentReference: Size; 20} 21 22class FrameNode { 23 public _nodeId: number; 24 protected _commonAttribute: ArkComponent; 25 protected _commonEvent: UICommonEvent; 26 protected _childList: Map<number, FrameNode>; 27 protected _nativeRef: NativeStrongRef | NativeWeakRef; 28 protected renderNode_: RenderNode; 29 protected baseNode_: BaseNode; 30 protected uiContext_: UIContext | undefined | null; 31 protected nodePtr_: NodePtr; 32 protected instanceId_?: number; 33 private nodeAdapterRef_?: NodeAdapter; 34 constructor(uiContext: UIContext, type: string, options?: object) { 35 if (uiContext === undefined) { 36 throw Error('Node constructor error, param uiContext error'); 37 } else { 38 if (!(typeof uiContext === "object") || !("instanceId_" in uiContext)) { 39 throw Error( 40 'Node constructor error, param uiContext is invalid' 41 ); 42 } 43 } 44 this.instanceId_ = uiContext.instanceId_; 45 this.uiContext_ = uiContext; 46 this._nodeId = -1; 47 this._childList = new Map(); 48 if (type === 'BuilderRootFrameNode') { 49 this.renderNode_ = new RenderNode(type); 50 this.renderNode_.setFrameNode(new WeakRef(this)); 51 return; 52 } 53 if (type === 'ProxyFrameNode') { 54 return; 55 } 56 let result; 57 __JSScopeUtil__.syncInstanceId(this.instanceId_); 58 if (type === undefined || type === "CustomFrameNode") { 59 this.renderNode_ = new RenderNode('CustomFrameNode'); 60 result = getUINativeModule().frameNode.createFrameNode(this); 61 } else { 62 result = getUINativeModule().frameNode.createTypedFrameNode(this, type, options); 63 } 64 __JSScopeUtil__.restoreInstanceId(); 65 this._nativeRef = result?.nativeStrongRef; 66 this._nodeId = result?.nodeId; 67 this.nodePtr_ = this._nativeRef?.getNativeHandle(); 68 this.renderNode_?.setNodePtr(result?.nativeStrongRef); 69 this.renderNode_?.setFrameNode(new WeakRef(this)); 70 if (result === undefined || this._nodeId === -1) { 71 return; 72 } 73 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.set(this._nodeId, new WeakRef(this)); 74 FrameNodeFinalizationRegisterProxy.register(this, this._nodeId); 75 76 } 77 invalidate() { 78 if (this.nodePtr_ === undefined || this.nodePtr_ === null) { 79 return; 80 } 81 getUINativeModule().frameNode.invalidate(this.nodePtr_); 82 } 83 getType(): string { 84 return 'CustomFrameNode'; 85 } 86 setRenderNode(nativeRef: NativeStrongRef): void { 87 this.renderNode_?.setNodePtr(nativeRef); 88 } 89 getRenderNode(): RenderNode | null { 90 if ( 91 this.renderNode_ !== undefined && 92 this.renderNode_ !== null && 93 this.renderNode_.getNodePtr() !== null 94 ) { 95 return this.renderNode_; 96 } 97 return null; 98 } 99 setNodePtr(nativeRef: NativeStrongRef | NativeWeakRef, nodePtr: NodePtr): void { 100 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.delete(this._nodeId); 101 this._nativeRef = nativeRef; 102 this.nodePtr_ = nodePtr ? nodePtr : this._nativeRef?.getNativeHandle(); 103 this._nodeId = getUINativeModule().frameNode.getIdByNodePtr(this.nodePtr_); 104 if (this._nodeId === -1) { 105 return; 106 } 107 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.set(this._nodeId, new WeakRef(this)); 108 FrameNodeFinalizationRegisterProxy.register(this, this._nodeId); 109 } 110 resetNodePtr(): void { 111 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.delete(this._nodeId); 112 this._nodeId = -1; 113 this._nativeRef = null; 114 this.nodePtr_ = null; 115 this.renderNode_?.resetNodePtr(); 116 } 117 setBaseNode(baseNode: BaseNode | null): void { 118 this.baseNode_ = baseNode; 119 this.renderNode_?.setBaseNode(baseNode); 120 } 121 setAdapterRef(adapter: NodeAdapter | undefined): void { 122 this.nodeAdapterRef_ = adapter; 123 } 124 getNodePtr(): NodePtr | null { 125 return this.nodePtr_; 126 } 127 dispose(): void { 128 this.renderNode_?.dispose(); 129 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.delete(this._nodeId); 130 this._nodeId = -1; 131 this._nativeRef = null; 132 this.nodePtr_ = null; 133 } 134 135 static disposeTreeRecursively(node: FrameNode | null): void { 136 if (node === null) { 137 return; 138 } 139 let child = node.getFirstChildWithoutExpand(); 140 FrameNode.disposeTreeRecursively(child); 141 let sibling = node.getNextSiblingWithoutExpand(); 142 FrameNode.disposeTreeRecursively(sibling); 143 node.dispose(); 144 } 145 146 disposeTree(): void { 147 let parent = this.getParent(); 148 if (parent?.getNodeType() === "NodeContainer") { 149 getUINativeModule().nodeContainer.clean(parent?.getNodePtr()); 150 } else { 151 parent?.removeChild(this); 152 } 153 FrameNode.disposeTreeRecursively(this); 154 } 155 156 checkType(): void { 157 if (!this.isModifiable()) { 158 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 159 } 160 } 161 isModifiable(): boolean { 162 return this._nativeRef !== undefined && this._nativeRef !== null; 163 } 164 165 convertToFrameNode(nodePtr: NodePtr, nodeId: number = -1): FrameNode | null { 166 if (nodeId === -1) { 167 nodeId = getUINativeModule().frameNode.getIdByNodePtr(nodePtr); 168 } 169 if (nodeId !== -1 && !getUINativeModule().frameNode.isModifiable(nodePtr)) { 170 let frameNode = new ProxyFrameNode(this.uiContext_); 171 let node = getUINativeModule().nativeUtils.createNativeWeakRef(nodePtr); 172 frameNode.setNodePtr(node); 173 frameNode._nodeId = nodeId; 174 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.set(frameNode._nodeId, new WeakRef(frameNode)); 175 FrameNodeFinalizationRegisterProxy.register(frameNode, frameNode._nodeId); 176 return frameNode; 177 } 178 return null; 179 } 180 181 checkValid(node?: FrameNode): boolean { 182 return true; 183 } 184 185 appendChild(node: FrameNode): void { 186 if (node === undefined || node === null) { 187 return; 188 } 189 if (node.getType() === 'ProxyFrameNode' || !this.checkValid(node)) { 190 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 191 } 192 __JSScopeUtil__.syncInstanceId(this.instanceId_); 193 let flag = getUINativeModule().frameNode.appendChild(this.nodePtr_, node.nodePtr_); 194 __JSScopeUtil__.restoreInstanceId(); 195 if (!flag) { 196 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 197 } 198 this._childList.set(node._nodeId, node); 199 } 200 201 addComponentContent(content: ComponentContent): void { 202 if (content === undefined || content === null || content.getNodePtr() === null || content.getNodePtr() == undefined) { 203 return; 204 } 205 if (!this.checkValid() || !this.isModifiable()) { 206 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 207 } 208 __JSScopeUtil__.syncInstanceId(this.instanceId_); 209 let flag = getUINativeModule().frameNode.appendChild(this.nodePtr_, content.getNodeWithoutProxy()); 210 __JSScopeUtil__.restoreInstanceId(); 211 if (!flag) { 212 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 213 } else { 214 content.setAttachedParent(new WeakRef<FrameNode>(this)); 215 } 216 } 217 218 removeComponentContent(content: ComponentContent): void { 219 if (content === undefined || content === null || content.getNodePtr() === null || content.getNodePtr() === undefined) { 220 return; 221 } 222 __JSScopeUtil__.syncInstanceId(this.instanceId_); 223 getUINativeModule().frameNode.removeChild(this.nodePtr_, content.getNodePtr()); 224 content.setAttachedParent(undefined); 225 __JSScopeUtil__.restoreInstanceId(); 226 } 227 228 insertChildAfter(child: FrameNode, sibling: FrameNode): void { 229 if (child === undefined || child === null) { 230 return; 231 } 232 if (child.getType() === 'ProxyFrameNode' || !this.checkValid(child)) { 233 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 234 } 235 let flag = true; 236 __JSScopeUtil__.syncInstanceId(this.instanceId_); 237 if (sibling === undefined || sibling === null) { 238 flag = getUINativeModule().frameNode.insertChildAfter(this.nodePtr_, child.nodePtr_, null); 239 } else { 240 flag = getUINativeModule().frameNode.insertChildAfter(this.nodePtr_, child.nodePtr_, sibling.getNodePtr()); 241 } 242 __JSScopeUtil__.restoreInstanceId(); 243 if (!flag) { 244 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 245 } 246 this._childList.set(child._nodeId, child); 247 } 248 249 removeChild(node: FrameNode): void { 250 if (node === undefined || node === null) { 251 return; 252 } 253 __JSScopeUtil__.syncInstanceId(this.instanceId_); 254 getUINativeModule().frameNode.removeChild(this.nodePtr_, node.nodePtr_); 255 __JSScopeUtil__.restoreInstanceId(); 256 this._childList.delete(node._nodeId); 257 } 258 259 clearChildren(): void { 260 __JSScopeUtil__.syncInstanceId(this.instanceId_); 261 getUINativeModule().frameNode.clearChildren(this.nodePtr_); 262 __JSScopeUtil__.restoreInstanceId(); 263 this._childList.clear(); 264 } 265 getChild(index: number, isExpanded?: boolean): FrameNode | null { 266 const result = getUINativeModule().frameNode.getChild(this.getNodePtr(), index, isExpanded); 267 const nodeId = result?.nodeId; 268 if (nodeId === undefined || nodeId === -1) { 269 return null; 270 } 271 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 272 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 273 return frameNode === undefined ? null : frameNode; 274 } 275 return this.convertToFrameNode(result.nodePtr, result.nodeId); 276 } 277 278 getFirstChild(isExpanded?: boolean): FrameNode | null { 279 const result = getUINativeModule().frameNode.getFirst(this.getNodePtr(), isExpanded); 280 const nodeId = result?.nodeId; 281 if (nodeId === undefined || nodeId === -1) { 282 return null; 283 } 284 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 285 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 286 return frameNode === undefined ? null : frameNode; 287 } 288 return this.convertToFrameNode(result.nodePtr, result.nodeId); 289 } 290 291 getFirstChildWithoutExpand(): FrameNode | null { 292 const result = getUINativeModule().frameNode.getFirst(this.getNodePtr(), false); 293 const nodeId = result?.nodeId; 294 if (nodeId === undefined || nodeId === -1) { 295 return null; 296 } 297 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 298 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 299 return frameNode === undefined ? null : frameNode; 300 } 301 return this.convertToFrameNode(result.nodePtr, result.nodeId); 302 } 303 304 getNextSibling(isExpanded?: boolean): FrameNode | null { 305 const result = getUINativeModule().frameNode.getNextSibling(this.getNodePtr(), isExpanded); 306 const nodeId = result?.nodeId; 307 if (nodeId === undefined || nodeId === -1) { 308 return null; 309 } 310 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 311 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 312 return frameNode === undefined ? null : frameNode; 313 } 314 return this.convertToFrameNode(result.nodePtr, result.nodeId); 315 } 316 317 getNextSiblingWithoutExpand(): FrameNode | null { 318 const result = getUINativeModule().frameNode.getNextSibling(this.getNodePtr(), false); 319 const nodeId = result?.nodeId; 320 if (nodeId === undefined || nodeId === -1) { 321 return null; 322 } 323 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 324 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 325 return frameNode === undefined ? null : frameNode; 326 } 327 return this.convertToFrameNode(result.nodePtr, result.nodeId); 328 } 329 330 getPreviousSibling(isExpanded?: boolean): FrameNode | null { 331 const result = getUINativeModule().frameNode.getPreviousSibling(this.getNodePtr(), isExpanded); 332 const nodeId = result?.nodeId; 333 if (nodeId === undefined || nodeId === -1) { 334 return null; 335 } 336 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 337 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 338 return frameNode === undefined ? null : frameNode; 339 } 340 return this.convertToFrameNode(result.nodePtr, result.nodeId); 341 } 342 343 getParent(): FrameNode | null { 344 const result = getUINativeModule().frameNode.getParent(this.getNodePtr()); 345 const nodeId = result?.nodeId; 346 if (nodeId === undefined || nodeId === -1) { 347 return null; 348 } 349 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 350 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 351 return frameNode === undefined ? null : frameNode; 352 } 353 return this.convertToFrameNode(result.nodePtr, result.nodeId); 354 } 355 356 getChildrenCount(isExpanded?: boolean): number { 357 return getUINativeModule().frameNode.getChildrenCount(this.nodePtr_, isExpanded); 358 } 359 360 getPositionToParent(): Position { 361 const position = getUINativeModule().frameNode.getPositionToParent(this.getNodePtr()); 362 return { x: position[0], y: position[1] }; 363 } 364 365 getPositionToScreen(): Position { 366 const position = getUINativeModule().frameNode.getPositionToScreen(this.getNodePtr()); 367 return { x: position[0], y: position[1] }; 368 } 369 370 getPositionToWindow(): Position { 371 const position = getUINativeModule().frameNode.getPositionToWindow(this.getNodePtr()); 372 return { x: position[0], y: position[1] }; 373 } 374 375 getPositionToParentWithTransform(): Position { 376 const position = getUINativeModule().frameNode.getPositionToParentWithTransform(this.getNodePtr()); 377 return { x: position[0], y: position[1] }; 378 } 379 380 getPositionToScreenWithTransform(): Position { 381 const position = getUINativeModule().frameNode.getPositionToScreenWithTransform(this.getNodePtr()); 382 return { x: position[0], y: position[1] }; 383 } 384 385 getPositionToWindowWithTransform(): Position { 386 const position = getUINativeModule().frameNode.getPositionToWindowWithTransform(this.getNodePtr()); 387 return { x: position[0], y: position[1] }; 388 } 389 390 getMeasuredSize(): Size { 391 const size = getUINativeModule().frameNode.getMeasuredSize(this.getNodePtr()); 392 return { width: size[0], height: size[1] }; 393 } 394 395 getLayoutPosition(): Position { 396 const position = getUINativeModule().frameNode.getLayoutPosition(this.getNodePtr()); 397 return { x: position[0], y: position[1] }; 398 } 399 400 getUserConfigBorderWidth(): EdgesT<LengthMetrics> { 401 const borderWidth = getUINativeModule().frameNode.getConfigBorderWidth(this.getNodePtr()); 402 return { 403 top: new LengthMetrics(borderWidth[0], borderWidth[1]), 404 right: new LengthMetrics(borderWidth[2], borderWidth[3]), 405 bottom: new LengthMetrics(borderWidth[4], borderWidth[5]), 406 left: new LengthMetrics(borderWidth[6], borderWidth[7]) 407 }; 408 } 409 410 getUserConfigPadding(): EdgesT<LengthMetrics> { 411 const borderWidth = getUINativeModule().frameNode.getConfigPadding(this.getNodePtr()); 412 return { 413 top: new LengthMetrics(borderWidth[0], borderWidth[1]), 414 right: new LengthMetrics(borderWidth[2], borderWidth[3]), 415 bottom: new LengthMetrics(borderWidth[4], borderWidth[5]), 416 left: new LengthMetrics(borderWidth[6], borderWidth[7]) 417 }; 418 } 419 420 getUserConfigMargin(): EdgesT<LengthMetrics> { 421 const margin = getUINativeModule().frameNode.getConfigMargin(this.getNodePtr()); 422 return { 423 top: new LengthMetrics(margin[0], margin[1]), 424 right: new LengthMetrics(margin[2], margin[3]), 425 bottom: new LengthMetrics(margin[4], margin[5]), 426 left: new LengthMetrics(margin[6], margin[7]) 427 }; 428 } 429 430 getUserConfigSize(): SizeT<LengthMetrics> { 431 const size = getUINativeModule().frameNode.getConfigSize(this.getNodePtr()); 432 return { 433 width: new LengthMetrics(size[0], size[1]), 434 height: new LengthMetrics(size[2], size[3]) 435 }; 436 } 437 438 getId(): string { 439 return getUINativeModule().frameNode.getId(this.getNodePtr()); 440 } 441 442 getUniqueId(): number { 443 return getUINativeModule().frameNode.getIdByNodePtr(this.getNodePtr()); 444 } 445 446 getNodeType(): string { 447 return getUINativeModule().frameNode.getNodeType(this.getNodePtr()); 448 } 449 450 getOpacity(): number { 451 return getUINativeModule().frameNode.getOpacity(this.getNodePtr()); 452 } 453 454 isVisible(): boolean { 455 return getUINativeModule().frameNode.isVisible(this.getNodePtr()); 456 } 457 458 isClipToFrame(): boolean { 459 return getUINativeModule().frameNode.isClipToFrame(this.getNodePtr()); 460 } 461 462 isAttached(): boolean { 463 return getUINativeModule().frameNode.isAttached(this.getNodePtr()); 464 } 465 466 getInspectorInfo(): Object { 467 const inspectorInfoStr = getUINativeModule().frameNode.getInspectorInfo(this.getNodePtr()); 468 const inspectorInfo = JSON.parse(inspectorInfoStr); 469 return inspectorInfo; 470 } 471 472 getCustomProperty(key: string): Object | undefined { 473 if (key === undefined) { 474 return undefined; 475 } 476 let value = __getCustomProperty__(this._nodeId, key); 477 if (value === undefined) { 478 const valueStr = getUINativeModule().frameNode.getCustomPropertyCapiByKey(this.getNodePtr(), key); 479 value = valueStr === undefined ? undefined : valueStr; 480 } 481 return value; 482 } 483 484 setMeasuredSize(size: Size): void { 485 getUINativeModule().frameNode.setMeasuredSize(this.getNodePtr(), Math.max(size.width, 0), 486 Math.max(size.height, 0)); 487 } 488 489 setLayoutPosition(position: Position): void { 490 getUINativeModule().frameNode.setLayoutPosition(this.getNodePtr(), position.x, position.y); 491 } 492 493 measure(constraint: LayoutConstraint): void { 494 const minSize: Size = constraint.minSize; 495 const maxSize: Size = constraint.maxSize; 496 const percentReference: Size = constraint.percentReference; 497 __JSScopeUtil__.syncInstanceId(this.instanceId_); 498 getUINativeModule().frameNode.measureNode(this.getNodePtr(), minSize.width, minSize.height, maxSize.width, 499 maxSize.height, percentReference.width, percentReference.height); 500 __JSScopeUtil__.restoreInstanceId(); 501 } 502 503 layout(position: Position): void { 504 getUINativeModule().frameNode.layoutNode(this.getNodePtr(), position.x, position.y); 505 } 506 507 setNeedsLayout(): void { 508 getUINativeModule().frameNode.setNeedsLayout(this.getNodePtr()); 509 } 510 511 get commonAttribute(): ArkComponent { 512 if (this._commonAttribute === undefined) { 513 this._commonAttribute = new ArkComponent(this.nodePtr_, ModifierType.FRAME_NODE); 514 this._commonAttribute.setInstanceId((this.uiContext_ === undefined || this.uiContext_ === null) ? -1 : this.uiContext_.instanceId_); 515 } 516 this._commonAttribute.setNodePtr(this.nodePtr_); 517 return this._commonAttribute; 518 } 519 520 get commonEvent(): UICommonEvent { 521 let node = this.getNodePtr(); 522 if (this._commonEvent === undefined) { 523 this._commonEvent = new UICommonEvent(node); 524 } 525 this._commonEvent.setNodePtr(node); 526 this._commonEvent.setInstanceId((this.uiContext_ === undefined || this.uiContext_ === null) ? -1 : this.uiContext_.instanceId_); 527 return this._commonEvent; 528 } 529 updateInstance(uiContext: UIContext): void { 530 this.uiContext_ = uiContext; 531 this.instanceId_ = uiContext.instanceId_; 532 } 533} 534 535class ImmutableFrameNode extends FrameNode { 536 isModifiable(): boolean { 537 return false; 538 } 539 invalidate() { 540 return; 541 } 542 appendChild(node: FrameNode): void { 543 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 544 } 545 insertChildAfter(child: FrameNode, sibling: FrameNode): void { 546 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 547 } 548 removeChild(node: FrameNode): void { 549 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 550 } 551 clearChildren(): void { 552 throw { message: 'The FrameNode is not modifiable.', code: 100021 }; 553 } 554 get commonAttribute(): ArkComponent { 555 if (this._commonAttribute === undefined) { 556 this._commonAttribute = new ArkComponent(undefined, ModifierType.FRAME_NODE); 557 } 558 this._commonAttribute.setNodePtr(undefined); 559 return this._commonAttribute; 560 } 561} 562 563class BuilderRootFrameNode extends ImmutableFrameNode { 564 constructor(uiContext: UIContext, type: string = 'BuilderRootFrameNode') { 565 super(uiContext, type); 566 } 567 getType(): string { 568 return 'BuilderRootFrameNode'; 569 } 570} 571 572class ProxyFrameNode extends ImmutableFrameNode { 573 _nativeRef: NativeWeakRef; 574 575 constructor(uiContext: UIContext, type: string = 'ProxyFrameNode') { 576 super(uiContext, type); 577 } 578 579 setNodePtr(nativeRef: NativeWeakRef) { 580 this._nativeRef = nativeRef; 581 this.nodePtr_ = this._nativeRef.getNativeHandle(); 582 } 583 getType(): string { 584 return 'ProxyFrameNode'; 585 } 586 getRenderNode(): RenderNode | null { 587 return null; 588 } 589 getNodePtr(): NodePtr | null { 590 if (this._nativeRef === undefined || this._nativeRef === null || this._nativeRef.invalid()) { 591 return null; 592 } 593 return this.nodePtr_; 594 } 595 dispose(): void { 596 this.renderNode_?.dispose(); 597 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.delete(this._nodeId); 598 this._nodeId = -1; 599 this._nativeRef = undefined; 600 this.nodePtr_ = undefined; 601 } 602} 603 604class FrameNodeUtils { 605 static searchNodeInRegisterProxy(nodePtr: NodePtr): FrameNode | null { 606 let nodeId = getUINativeModule().frameNode.getIdByNodePtr(nodePtr); 607 if (nodeId === -1) { 608 return null; 609 } 610 if (FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.has(nodeId)) { 611 let frameNode = FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.get(nodeId).deref(); 612 return frameNode === undefined ? null : frameNode; 613 } 614 return null; 615 } 616 617 static createFrameNode(uiContext: UIContext, nodePtr: NodePtr): FrameNode | null { 618 let nodeId = getUINativeModule().frameNode.getIdByNodePtr(nodePtr); 619 if (nodeId !== -1 && !getUINativeModule().frameNode.isModifiable(nodePtr)) { 620 let frameNode = new ProxyFrameNode(uiContext); 621 let node = getUINativeModule().nativeUtils.createNativeWeakRef(nodePtr); 622 frameNode.setNodePtr(node); 623 frameNode._nodeId = nodeId; 624 FrameNodeFinalizationRegisterProxy.ElementIdToOwningFrameNode_.set(nodeId, new WeakRef(frameNode)); 625 FrameNodeFinalizationRegisterProxy.register(frameNode, nodeId); 626 return frameNode; 627 } 628 return null; 629 } 630} 631 632class TypedFrameNode<T extends ArkComponent> extends FrameNode { 633 attribute_: T; 634 attrCreator_: (node: NodePtr, type: ModifierType) => T 635 636 constructor(uiContext: UIContext, type: string, attrCreator: (node: NodePtr, type: ModifierType) => T, options?: object) { 637 super(uiContext, type, options); 638 this.attrCreator_ = attrCreator; 639 } 640 641 initialize(...args: Object[]): T { 642 return this.attribute.initialize(args); 643 } 644 645 get attribute(): T { 646 if (this.attribute_ === undefined) { 647 this.attribute_ = this.attrCreator_(this.nodePtr_, ModifierType.FRAME_NODE); 648 } 649 this.attribute_.setNodePtr(this.nodePtr_); 650 this.attribute_.setInstanceId((this.uiContext_ === undefined || this.uiContext_ === null) ? -1 : this.uiContext_.instanceId_); 651 return this.attribute_; 652 } 653 654 checkValid(node?: FrameNode): boolean { 655 if (this.attribute_ === undefined) { 656 this.attribute_ = this.attrCreator_(this.nodePtr_, ModifierType.FRAME_NODE); 657 } 658 659 if (this.attribute_.allowChildCount !== undefined) { 660 const allowCount = this.attribute_.allowChildCount(); 661 if (this.getChildrenCount() >= allowCount) { 662 return false; 663 } 664 } 665 666 if (this.attribute_.allowChildTypes !== undefined && node !== undefined) { 667 const childType = node.getNodeType(); 668 const allowTypes = this.attribute_.allowChildTypes(); 669 let isValid = false; 670 allowTypes.forEach((nodeType: string) => { 671 if (nodeType === childType) { 672 isValid = true; 673 } 674 }); 675 return isValid; 676 } 677 return true; 678 } 679} 680 681const __creatorMap__ = new Map<string, (context: UIContext, options?: object) => FrameNode>( 682 [ 683 ['Text', (context: UIContext): FrameNode=> { 684 return new TypedFrameNode(context, 'Text', (node: NodePtr, type: ModifierType): ArkTextComponent => { 685 return new ArkTextComponent(node, type); 686 }) 687 }], 688 ['Column', (context: UIContext): FrameNode=> { 689 return new TypedFrameNode(context, 'Column', (node: NodePtr, type: ModifierType): ArkColumnComponent => { 690 return new ArkColumnComponent(node, type); 691 }) 692 }], 693 ['Row', (context: UIContext): FrameNode=> { 694 return new TypedFrameNode(context, 'Row', (node: NodePtr, type: ModifierType): ArkRowComponent => { 695 return new ArkRowComponent(node, type); 696 }) 697 }], 698 ['Stack', (context: UIContext): FrameNode=> { 699 return new TypedFrameNode(context, 'Stack', (node: NodePtr, type: ModifierType): ArkStackComponent => { 700 return new ArkStackComponent(node, type); 701 }) 702 }], 703 ['GridRow', (context: UIContext): FrameNode=> { 704 let node = new TypedFrameNode(context, 'GridRow', (node: NodePtr, type: ModifierType): ArkGridRowComponent => { 705 return new ArkGridRowComponent(node, type); 706 }) 707 node.initialize(); 708 return node; 709 }], 710 ['TextInput', (context: UIContext): FrameNode=> { 711 return new TypedFrameNode(context, 'TextInput', (node: NodePtr, type: ModifierType): ArkTextInputComponent => { 712 return new ArkTextInputComponent(node, type); 713 }) 714 }], 715 ['GridCol', (context: UIContext): FrameNode=> { 716 let node = new TypedFrameNode(context, 'GridCol', (node: NodePtr, type: ModifierType): ArkGridColComponent => { 717 return new ArkGridColComponent(node, type); 718 }) 719 node.initialize(); 720 return node; 721 }], 722 ['Blank', (context: UIContext): FrameNode=> { 723 return new TypedFrameNode(context, 'Blank', (node: NodePtr, type: ModifierType): ArkBlankComponent => { 724 return new ArkBlankComponent(node, type); 725 }) 726 }], 727 ['Image', (context: UIContext): FrameNode=> { 728 return new TypedFrameNode(context, 'Image', (node: NodePtr, type: ModifierType): ArkImageComponent => { 729 return new ArkImageComponent(node, type); 730 }) 731 }], 732 ['Flex', (context: UIContext): FrameNode=> { 733 return new TypedFrameNode(context, 'Flex', (node: NodePtr, type: ModifierType): ArkFlexComponent => { 734 return new ArkFlexComponent(node, type); 735 }) 736 }], 737 ['Swiper', (context: UIContext): FrameNode=> { 738 return new TypedFrameNode(context, 'Swiper', (node: NodePtr, type: ModifierType): ArkSwiperComponent => { 739 return new ArkSwiperComponent(node, type); 740 }) 741 }], 742 ['Progress', (context: UIContext): FrameNode=> { 743 return new TypedFrameNode(context, 'Progress', (node: NodePtr, type: ModifierType): ArkProgressComponent => { 744 return new ArkProgressComponent(node, type); 745 }) 746 }], 747 ['Scroll', (context: UIContext): FrameNode=> { 748 return new TypedFrameNode(context, 'Scroll', (node: NodePtr, type: ModifierType): ArkScrollComponent => { 749 return new ArkScrollComponent(node, type); 750 }) 751 }], 752 ['RelativeContainer', (context: UIContext): FrameNode=> { 753 return new TypedFrameNode(context, 'RelativeContainer', (node: NodePtr, type: ModifierType): ArkRelativeContainerComponent => { 754 return new ArkRelativeContainerComponent(node, type); 755 }) 756 }], 757 ['List', (context: UIContext): FrameNode=> { 758 return new TypedFrameNode(context, 'List', (node: NodePtr, type: ModifierType): ArkListComponent => { 759 return new ArkListComponent(node, type); 760 }) 761 }], 762 ['ListItem', (context: UIContext): FrameNode=> { 763 return new TypedFrameNode(context, 'ListItem', (node: NodePtr, type: ModifierType): ArkListItemComponent => { 764 return new ArkListItemComponent(node, type); 765 }) 766 }], 767 ['Divider', (context: UIContext): FrameNode=> { 768 return new TypedFrameNode(context, 'Divider', (node: NodePtr, type: ModifierType): ArkDividerComponent => { 769 return new ArkDividerComponent(node, type); 770 }) 771 }], 772 ['LoadingProgress', (context: UIContext): FrameNode=> { 773 return new TypedFrameNode(context, 'LoadingProgress', (node: NodePtr, type: ModifierType): ArkLoadingProgressComponent => { 774 return new ArkLoadingProgressComponent(node, type); 775 }) 776 }], 777 ['Search', (context: UIContext): FrameNode=> { 778 return new TypedFrameNode(context, 'Search', (node: NodePtr, type: ModifierType): ArkSearchComponent => { 779 return new ArkSearchComponent(node, type); 780 }) 781 }], 782 ['Button', (context: UIContext): FrameNode=> { 783 return new TypedFrameNode(context, 'Button', (node: NodePtr, type: ModifierType): ArkButtonComponent => { 784 return new ArkButtonComponent(node, type); 785 }) 786 }], 787 ['XComponent', (context: UIContext, options?: object): FrameNode=> { 788 return new TypedFrameNode(context, 'XComponent', (node: NodePtr, type: ModifierType): ArkXComponentComponent => { 789 return new ArkXComponentComponent(node, type); 790 }, options); 791 }], 792 ['ListItemGroup', (context: UIContext): FrameNode=> { 793 return new TypedFrameNode(context, 'ListItemGroup', (node: NodePtr, type: ModifierType): ArkListItemGroupComponent => { 794 return new ArkListItemGroupComponent(node, type); 795 }) 796 }], 797 ['WaterFlow', (context: UIContext): FrameNode=> { 798 return new TypedFrameNode(context, 'WaterFlow', (node: NodePtr, type: ModifierType): ArkWaterFlowComponent => { 799 return new ArkWaterFlowComponent(node, type); 800 }) 801 }], 802 ['FlowItem', (context: UIContext): FrameNode=> { 803 return new TypedFrameNode(context, 'FlowItem', (node: NodePtr, type: ModifierType): ArkFlowItemComponent => { 804 return new ArkFlowItemComponent(node, type); 805 }) 806 }], 807 ] 808) 809 810class typeNode { 811 static createNode(context: UIContext, type: string, options?: object): FrameNode { 812 let creator = __creatorMap__.get(type) 813 if (creator === undefined) { 814 return undefined 815 } 816 return creator(context, options); 817 } 818} 819