• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 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
16/// <reference path='./import.ts' />
17
18class ArkRadioComponent extends ArkComponent implements RadioAttribute {
19  builder: WrappedBuilder<Object[]> | null = null;
20  radioNode: BuilderNode<[RadioConfiguration]> | null = null;
21  modifier: ContentModifier<RadioConfiguration>;
22  needRebuild: boolean = false;
23  constructor(nativePtr: KNode, classType?: ModifierType) {
24    super(nativePtr, classType);
25  }
26  allowChildCount(): number {
27    return 0;
28  }
29  initialize(value: Object[]): this {
30    if (!value.length) {
31      return this;
32    }
33    if (!isUndefined(value[0]) && !isNull(value[0]) && isObject(value[0])) {
34      modifierWithKey(this._modifiersWithKeys, RadioOptionsModifier.identity, RadioOptionsModifier, value[0]);
35    } else {
36      modifierWithKey(this._modifiersWithKeys, RadioOptionsModifier.identity, RadioOptionsModifier, undefined);
37    }
38    return this;
39  }
40  checked(value: boolean): this {
41    modifierWithKey(this._modifiersWithKeys, RadioCheckedModifier.identity, RadioCheckedModifier, value);
42    return this;
43  }
44  onChange(callback: (isChecked: boolean) => void): this {
45    modifierWithKey(this._modifiersWithKeys, RadioOnChangeModifier.identity, RadioOnChangeModifier,callback);
46    return this;
47  }
48  radioStyle(value: RadioStyle): this {
49    modifierWithKey(this._modifiersWithKeys, RadioStyleModifier.identity, RadioStyleModifier, value);
50    return this;
51  }
52  width(value: Length): this {
53    modifierWithKey(this._modifiersWithKeys, RadioWidthModifier.identity, RadioWidthModifier, value);
54    return this;
55  }
56  height(value: Length): this {
57    modifierWithKey(this._modifiersWithKeys, RadioHeightModifier.identity, RadioHeightModifier, value);
58    return this;
59  }
60  size(value: { width: Length; height: Length }): this {
61    modifierWithKey(this._modifiersWithKeys, RadioSizeModifier.identity, RadioSizeModifier, value);
62    return this;
63  }
64  hoverEffect(value: HoverEffect): this {
65    modifierWithKey(this._modifiersWithKeys, RadioHoverEffectModifier.identity, RadioHoverEffectModifier, value);
66    return this;
67  }
68  padding(value: Padding | Length): this {
69    modifierWithKey(this._modifiersWithKeys, RadioPaddingModifier.identity, RadioPaddingModifier, value);
70    return this;
71  }
72  responseRegion(value: Array<Rectangle> | Rectangle): this {
73    modifierWithKey(this._modifiersWithKeys, RadioResponseRegionModifier.identity,
74      RadioResponseRegionModifier, value);
75    return this;
76  }
77  contentModifier(value: ContentModifier<RadioConfiguration>): this {
78    modifierWithKey(this._modifiersWithKeys, RadioContentModifier.identity, RadioContentModifier, value);
79    return this;
80  }
81  setContentModifier(modifier: ContentModifier<RadioConfiguration>): this {
82    if (modifier === undefined || modifier === null) {
83      getUINativeModule().radio.setContentModifierBuilder(this.nativePtr, false);
84      return;
85    }
86    this.needRebuild = false;
87    if (this.builder !== modifier.applyContent()) {
88      this.needRebuild = true;
89    }
90    this.builder = modifier.applyContent();
91    this.modifier = modifier;
92    getUINativeModule().radio.setContentModifierBuilder(this.nativePtr, this);
93  }
94  makeContentModifierNode(context: UIContext, radioConfiguration: RadioConfiguration): FrameNode | null {
95    radioConfiguration.contentModifier = this.modifier;
96    if (isUndefined(this.radioNode) || this.needRebuild) {
97      const xNode = globalThis.requireNapi('arkui.node');
98      this.radioNode = new xNode.BuilderNode(context);
99      this.radioNode.build(this.builder, radioConfiguration);
100      this.needRebuild = false;
101    } else {
102      this.radioNode.update(radioConfiguration);
103    }
104    return this.radioNode.getFrameNode();
105  }
106}
107
108class RadioOptionsModifier extends ModifierWithKey<RadioOptions> {
109  constructor(value: RadioOptions) {
110    super(value);
111  }
112  static identity: Symbol = Symbol('radioOptions');
113  applyPeer(node: KNode, reset: boolean): void {
114    if (reset) {
115      getUINativeModule().radio.setRadioOptions(node, undefined, undefined, undefined);
116    } else {
117      getUINativeModule().radio.setRadioOptions(node, this.value.value, this.value.group, this.value.indicatorType);
118    }
119  }
120
121  checkObjectDiff(): boolean {
122    return !isBaseOrResourceEqual(this.stageValue.value, this.value.value) ||
123      !isBaseOrResourceEqual(this.stageValue.group, this.value.group) ||
124      !isBaseOrResourceEqual(this.stageValue.indicatorType, this.value.indicatorType);
125  }
126}
127
128class RadioCheckedModifier extends ModifierWithKey<boolean> {
129  constructor(value: boolean) {
130    super(value);
131  }
132  static identity: Symbol = Symbol('radioChecked');
133  applyPeer(node: KNode, reset: boolean): void {
134    if (reset) {
135      getUINativeModule().radio.resetRadioChecked(node);
136    } else {
137      getUINativeModule().radio.setRadioChecked(node, this.value!);
138    }
139  }
140}
141
142class RadioStyleModifier extends ModifierWithKey<RadioStyle> {
143  constructor(value: RadioStyle) {
144    super(value);
145  }
146  static identity: Symbol = Symbol('radioStyle');
147  applyPeer(node: KNode, reset: boolean): void {
148    if (reset) {
149      getUINativeModule().radio.resetRadioStyle(node);
150    } else {
151      getUINativeModule().radio.setRadioStyle(
152        node, this.value.checkedBackgroundColor, this.value.uncheckedBorderColor, this.value.indicatorColor);
153    }
154  }
155
156  checkObjectDiff(): boolean {
157    let checkedBackgroundColorEQ =
158      isBaseOrResourceEqual(this.stageValue.checkedBackgroundColor,
159        this.value.checkedBackgroundColor);
160    let uncheckedBorderColorEQ =
161      isBaseOrResourceEqual(this.stageValue.uncheckedBorderColor,
162        this.value.uncheckedBorderColor);
163    let indicatorColorEQ =
164      isBaseOrResourceEqual(this.stageValue.indicatorColor,
165        this.value.indicatorColor);
166    return !checkedBackgroundColorEQ ||
167      !uncheckedBorderColorEQ ||
168      !indicatorColorEQ;
169  }
170}
171
172class RadioWidthModifier extends ModifierWithKey<Length> {
173  constructor(value: Length) {
174    super(value);
175  }
176  static identity: Symbol = Symbol('radioWidth');
177  applyPeer(node: KNode, reset: boolean): void {
178    if (reset) {
179      getUINativeModule().radio.resetRadioWidth(node);
180    } else {
181      getUINativeModule().radio.setRadioWidth(node, this.value);
182    }
183  }
184
185  checkObjectDiff(): boolean {
186    return !isBaseOrResourceEqual(this.stageValue, this.value);
187  }
188}
189
190class RadioHeightModifier extends ModifierWithKey<Length> {
191  constructor(value: Length) {
192    super(value);
193  }
194  static identity: Symbol = Symbol('radioHeight');
195  applyPeer(node: KNode, reset: boolean): void {
196    if (reset) {
197      getUINativeModule().radio.resetRadioHeight(node);
198    } else {
199      getUINativeModule().radio.setRadioHeight(node, this.value);
200    }
201  }
202
203  checkObjectDiff(): boolean {
204    return !isBaseOrResourceEqual(this.stageValue, this.value);
205  }
206}
207
208class RadioSizeModifier extends ModifierWithKey<{ width: Length; height: Length }> {
209  constructor(value: { width: Length; height: Length }) {
210    super(value);
211  }
212  static identity: Symbol = Symbol('radioSize');
213  applyPeer(node: KNode, reset: boolean): void {
214    if (reset) {
215      getUINativeModule().radio.resetRadioSize(node);
216    } else {
217      getUINativeModule().radio.setRadioSize(node, this.value.width, this.value.height);
218    }
219  }
220
221  checkObjectDiff(): boolean {
222    return !isBaseOrResourceEqual(this.stageValue.width, this.value.width) ||
223      !isBaseOrResourceEqual(this.stageValue.height, this.value.height);
224  }
225}
226
227class RadioHoverEffectModifier extends ModifierWithKey<HoverEffect> {
228  constructor(value: HoverEffect) {
229    super(value);
230  }
231  static identity: Symbol = Symbol('radioHoverEffect');
232  applyPeer(node: KNode, reset: boolean): void {
233    if (reset) {
234      getUINativeModule().radio.resetRadioHoverEffect(node);
235    } else {
236      getUINativeModule().radio.setRadioHoverEffect(node, this.value);
237    }
238  }
239
240  checkObjectDiff(): boolean {
241    return !isBaseOrResourceEqual(this.stageValue, this.value);
242  }
243}
244
245class RadioPaddingModifier extends ModifierWithKey<Padding | Length> {
246  constructor(value: Padding | Length) {
247    super(value);
248  }
249  static identity: Symbol = Symbol('radioPadding');
250  applyPeer(node: KNode, reset: boolean): void {
251    if (reset) {
252      getUINativeModule().radio.resetRadioPadding(node);
253    } else {
254      let paddingTop: Length;
255      let paddingRight: Length;
256      let paddingBottom: Length;
257      let paddingLeft: Length;
258      if (this.value !== null && this.value !== undefined) {
259        if (isLengthType(this.value) || isResource(this.value)) {
260          paddingTop = <Length> this.value;
261          paddingRight = <Length> this.value;
262          paddingBottom = <Length> this.value;
263          paddingLeft = <Length> this.value;
264        } else {
265          paddingTop = (<Padding> this.value).top;
266          paddingRight = (<Padding> this.value).right;
267          paddingBottom = (<Padding> this.value).bottom;
268          paddingLeft = (<Padding> this.value).left;
269        }
270      }
271      getUINativeModule().radio.setRadioPadding(node, paddingTop, paddingRight, paddingBottom, paddingLeft);
272    }
273  }
274
275  checkObjectDiff(): boolean {
276    if (isResource(this.stageValue) && isResource(this.value)) {
277      return !isResourceEqual(this.stageValue, this.value);
278    } else if (!isResource(this.stageValue) && !isResource(this.value)) {
279      return !((this.stageValue as Padding).left === (this.value as Padding).left &&
280        (this.stageValue as Padding).right === (this.value as Padding).right &&
281        (this.stageValue as Padding).top === (this.value as Padding).top &&
282        (this.stageValue as Padding).bottom === (this.value as Padding).bottom);
283    } else {
284      return true;
285    }
286  }
287}
288
289class RadioResponseRegionModifier extends ModifierWithKey<Array<Rectangle> | Rectangle> {
290  constructor(value: Array<Rectangle> | Rectangle) {
291    super(value);
292  }
293  static identity = Symbol('radioResponseRegion');
294  applyPeer(node: KNode, reset: boolean): void {
295    if (reset) {
296      getUINativeModule().radio.resetRadioResponseRegion(node);
297    } else {
298      let responseRegion: (number | string | Resource)[] = [];
299      if (Array.isArray(this.value)) {
300        for (let i = 0; i < this.value.length; i++) {
301          responseRegion.push(this.value[i].x ?? 'PLACEHOLDER');
302          responseRegion.push(this.value[i].y ?? 'PLACEHOLDER');
303          responseRegion.push(this.value[i].width ?? 'PLACEHOLDER');
304          responseRegion.push(this.value[i].height ?? 'PLACEHOLDER');
305        }
306      } else {
307        responseRegion.push(this.value.x ?? 'PLACEHOLDER');
308        responseRegion.push(this.value.y ?? 'PLACEHOLDER');
309        responseRegion.push(this.value.width ?? 'PLACEHOLDER');
310        responseRegion.push(this.value.height ?? 'PLACEHOLDER');
311      }
312      getUINativeModule().radio.setRadioResponseRegion(node, responseRegion, responseRegion.length);
313    }
314  }
315
316  checkObjectDiff(): boolean {
317    if (Array.isArray(this.value) && Array.isArray(this.stageValue)) {
318      if (this.value.length !== this.stageValue.length) {
319        return true;
320      } else {
321        for (let i = 0; i < this.value.length; i++) {
322          if (!(isBaseOrResourceEqual(this.stageValue[i].x, this.value[i].x) &&
323            isBaseOrResourceEqual(this.stageValue[i].y, this.value[i].y) &&
324            isBaseOrResourceEqual(this.stageValue[i].width, this.value[i].width) &&
325            isBaseOrResourceEqual(this.stageValue[i].height, this.value[i].height)
326          )) {
327            return true;
328          }
329        }
330        return false;
331      }
332    } else if (!Array.isArray(this.value) && !Array.isArray(this.stageValue)) {
333      return (!(isBaseOrResourceEqual(this.stageValue.x, this.value.x) &&
334        isBaseOrResourceEqual(this.stageValue.y, this.value.y) &&
335        isBaseOrResourceEqual(this.stageValue.width, this.value.width) &&
336        isBaseOrResourceEqual(this.stageValue.height, this.value.height)
337      ));
338    } else {
339      return true;
340    }
341  }
342}
343
344class RadioContentModifier extends ModifierWithKey<ContentModifier<RadioConfiguration>> {
345  constructor(value: ContentModifier<RadioConfiguration>) {
346    super(value);
347  }
348  static identity: Symbol = Symbol('radioContentModifier');
349  applyPeer(node: KNode, reset: boolean, component: ArkComponent): void {
350    let radioComponent = component as ArkRadioComponent;
351    radioComponent.setContentModifier(this.value);
352  }
353}
354class RadioOnChangeModifier extends ModifierWithKey<(isChecked: boolean) => void>{
355  constructor(value:(isChecked: boolean) => void) {
356    super(value);
357  }
358  static identity: Symbol = Symbol('radioOnChange');
359  applyPeer(node: KNode, reset: boolean): void {
360    if (reset) {
361      getUINativeModule().radio.resetRadioOnChange(node);
362    } else {
363      getUINativeModule().radio.setRadioOnChange(node, this.value);
364    }
365  }
366}
367
368// @ts-ignore
369globalThis.Radio.attributeModifier = function (modifier: ArkComponent): void {
370  attributeModifierFunc.call(this, modifier, (nativePtr: KNode) => {
371    return new ArkRadioComponent(nativePtr);
372  }, (nativePtr: KNode, classType: ModifierType, modifierJS: ModifierJS) => {
373    return new modifierJS.RadioModifier(nativePtr, classType);
374  });
375};
376
377// @ts-ignore
378globalThis.Radio.contentModifier = function (modifier): void {
379  const elmtId = ViewStackProcessor.GetElmtIdToAccountFor();
380  let nativeNode = getUINativeModule().getFrameNodeById(elmtId);
381  let component = this.createOrGetNode(elmtId, () => {
382    return new ArkRadioComponent(nativeNode);
383  });
384  component.setContentModifier(modifier);
385};
386