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