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