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' /> 17class ArkToggleComponent extends ArkComponent implements ToggleAttribute { 18 builder: WrappedBuilder<Object[]> | null = null; 19 toggleNode: BuilderNode<[ToggleConfiguration]> | null = null; 20 modifier: ContentModifier<ToggleConfiguration>; 21 needRebuild: boolean = false; 22 toggleType: ToggleType = ToggleType.Switch; 23 constructor(nativePtr: KNode, classType?: ModifierType) { 24 super(nativePtr, classType); 25 } 26 allowChildCount(): number { 27 if (this.toggleType === ToggleType.Button) { 28 return 1; 29 } 30 return 0; 31 } 32 initialize(value: Object[]): this { 33 if (!value.length) { 34 return this; 35 } 36 if (!isUndefined(value[0]) && !isNull(value[0]) && isObject(value[0])) { 37 this.toggleType = (value[0] as ToggleOptions).type; 38 modifierWithKey(this._modifiersWithKeys, ToggleOptionsModifier.identity, ToggleOptionsModifier, value[0]); 39 } else { 40 modifierWithKey(this._modifiersWithKeys, ToggleOptionsModifier.identity, ToggleOptionsModifier, undefined); 41 } 42 return this; 43 } 44 onChange(callback: (isOn: boolean) => void): this { 45 modifierWithKey(this._modifiersWithKeys, ToggleOnChangeModifier.identity, ToggleOnChangeModifier, callback); 46 return this; 47 } 48 selectedColor(value: ResourceColor): this { 49 modifierWithKey(this._modifiersWithKeys, ToggleSelectedColorModifier.identity, ToggleSelectedColorModifier, value); 50 return this; 51 } 52 switchPointColor(value: ResourceColor): this { 53 modifierWithKey(this._modifiersWithKeys, ToggleSwitchPointColorModifier.identity, ToggleSwitchPointColorModifier, value); 54 return this; 55 } 56 height(value: Length): this { 57 modifierWithKey(this._modifiersWithKeys, ToggleHeightModifier.identity, ToggleHeightModifier, value); 58 return this; 59 } 60 responseRegion(value: Rectangle | Rectangle[]): this { 61 modifierWithKey(this._modifiersWithKeys, ToggleResponseRegionModifier.identity, ToggleResponseRegionModifier, value); 62 return this; 63 } 64 padding(value: Padding | Length): this { 65 modifierWithKey(this._modifiersWithKeys, TogglePaddingModifier.identity, TogglePaddingModifier, value); 66 return this; 67 } 68 backgroundColor(value: ResourceColor): this { 69 modifierWithKey(this._modifiersWithKeys, ToggleBackgroundColorModifier.identity, ToggleBackgroundColorModifier, value); 70 return this; 71 } 72 hoverEffect(value: HoverEffect): this { 73 modifierWithKey(this._modifiersWithKeys, ToggleHoverEffectModifier.identity, ToggleHoverEffectModifier, value); 74 return this; 75 } 76 switchStyle(value: SwitchStyle): this { 77 modifierWithKey(this._modifiersWithKeys, ToggleSwitchStyleModifier.identity, ToggleSwitchStyleModifier, value); 78 return this; 79 } 80 contentModifier(value: ContentModifier<ToggleConfiguration>): this { 81 modifierWithKey(this._modifiersWithKeys, ToggleContentModifier.identity, ToggleContentModifier, value); 82 return this; 83 } 84 setContentModifier(modifier: ContentModifier<ToggleConfiguration>): this { 85 if (modifier === undefined || modifier === null) { 86 getUINativeModule().toggle.setContentModifierBuilder(this.nativePtr, false); 87 return; 88 } 89 this.needRebuild = false; 90 if (this.builder !== modifier.applyContent()) { 91 this.needRebuild = true; 92 } 93 this.builder = modifier.applyContent(); 94 this.modifier = modifier; 95 getUINativeModule().toggle.setContentModifierBuilder(this.nativePtr, this); 96 } 97 makeContentModifierNode(context: UIContext, toggleConfiguration: ToggleConfiguration): FrameNode | null { 98 toggleConfiguration.contentModifier = this.modifier; 99 if (isUndefined(this.toggleNode) || this.needRebuild) { 100 const xNode = globalThis.requireNapi('arkui.node'); 101 this.toggleNode = new xNode.BuilderNode(context); 102 this.toggleNode.build(this.builder, toggleConfiguration); 103 this.needRebuild = false; 104 } else { 105 this.toggleNode.update(toggleConfiguration); 106 } 107 return this.toggleNode.getFrameNode(); 108 } 109} 110 111class ToggleOnChangeModifier extends ModifierWithKey<(isOn:boolean) => void> { 112 constructor(value: (isOn:boolean) => void) { 113 super(value); 114 } 115 static identity = Symbol('toggleOnChange'); 116 applyPeer(node: KNode, reset: boolean): void { 117 if (reset) { 118 getUINativeModule().toggle.resetOnChange(node); 119 } else { 120 getUINativeModule().toggle.setOnChange(node, this.value); 121 } 122 } 123} 124 125class ToggleSelectedColorModifier extends ModifierWithKey<ResourceColor> { 126 constructor(value: ResourceColor) { 127 super(value); 128 } 129 static identity = Symbol('toggleSelectedColor'); 130 applyPeer(node: KNode, reset: boolean): void { 131 if (reset) { 132 getUINativeModule().toggle.resetSelectedColor(node); 133 } else { 134 getUINativeModule().toggle.setSelectedColor(node, this.value); 135 } 136 } 137 138 checkObjectDiff(): boolean { 139 return !isBaseOrResourceEqual(this.stageValue, this.value); 140 } 141} 142class ToggleSwitchPointColorModifier extends ModifierWithKey<ResourceColor> { 143 constructor(value: ResourceColor) { 144 super(value); 145 } 146 static identity = Symbol('toggleSwitchPointColor'); 147 applyPeer(node: KNode, reset: boolean): void { 148 if (reset) { 149 getUINativeModule().toggle.resetSwitchPointColor(node); 150 } else { 151 getUINativeModule().toggle.setSwitchPointColor(node, this.value); 152 } 153 } 154 155 checkObjectDiff(): boolean { 156 return !isBaseOrResourceEqual(this.stageValue, this.value); 157 } 158} 159class ToggleHeightModifier extends ModifierWithKey<Length> { 160 constructor(value: Length) { 161 super(value); 162 } 163 static identity = Symbol('toggleHeight'); 164 applyPeer(node: KNode, reset: boolean): void { 165 if (reset) { 166 getUINativeModule().toggle.resetHeight(node); 167 } else { 168 getUINativeModule().toggle.setHeight(node, this.value); 169 } 170 } 171 checkObjectDiff(): boolean { 172 return !isBaseOrResourceEqual(this.stageValue, this.value); 173 } 174} 175class ToggleResponseRegionModifier extends ModifierWithKey<Rectangle | Array<Rectangle>> { 176 constructor(value: Rectangle | Array<Rectangle>) { 177 super(value); 178 } 179 static identity = Symbol('toggleResponseRegion'); 180 applyPeer(node: KNode, reset: boolean): void { 181 if (reset) { 182 getUINativeModule().toggle.resetResponseRegion(node); 183 } else { 184 let responseRegion: (number | string | Resource)[] = []; 185 if (Array.isArray(this.value)) { 186 for (let i = 0; i < this.value.length; i++) { 187 responseRegion.push(this.value[i].x ?? 'PLACEHOLDER'); 188 responseRegion.push(this.value[i].y ?? 'PLACEHOLDER'); 189 responseRegion.push(this.value[i].width ?? 'PLACEHOLDER'); 190 responseRegion.push(this.value[i].height ?? 'PLACEHOLDER'); 191 } 192 } else { 193 responseRegion.push(this.value.x ?? 'PLACEHOLDER'); 194 responseRegion.push(this.value.y ?? 'PLACEHOLDER'); 195 responseRegion.push(this.value.width ?? 'PLACEHOLDER'); 196 responseRegion.push(this.value.height ?? 'PLACEHOLDER'); 197 } 198 getUINativeModule().toggle.setResponseRegion(node, responseRegion, responseRegion.length); 199 } 200 } 201 checkObjectDiff(): boolean { 202 if (Array.isArray(this.stageValue) && Array.isArray(this.value)) { 203 if (this.value.length !== this.stageValue.length) { 204 return true; 205 } else { 206 for (let i = 0; i < this.value.length; i++) { 207 if (!(isBaseOrResourceEqual(this.stageValue[i].x, this.value[i].x) && 208 isBaseOrResourceEqual(this.stageValue[i].y, this.value[i].y) && 209 isBaseOrResourceEqual(this.stageValue[i].width, this.value[i].width) && 210 isBaseOrResourceEqual(this.stageValue[i].height, this.value[i].height) 211 )) { 212 return true; 213 } 214 } 215 return false; 216 } 217 } else if (typeof this.stageValue === 'object' && typeof this.value === 'object') { 218 return !((this.stageValue as Rectangle).x === (this.value as Rectangle).x && 219 (this.stageValue as Rectangle).y === (this.value as Rectangle).y && 220 (this.stageValue as Rectangle).height === (this.value as Rectangle).height && 221 (this.stageValue as Rectangle).width === (this.value as Rectangle).width); 222 } else { 223 return true; 224 } 225 } 226} 227class TogglePaddingModifier extends ModifierWithKey<Padding | Length> { 228 constructor(value: Padding | Length) { 229 super(value); 230 } 231 static identity = Symbol('togglePadding'); 232 applyPeer(node: KNode, reset: boolean): void { 233 if (reset) { 234 getUINativeModule().toggle.resetPadding(node); 235 } else { 236 let top = undefined; 237 let right = undefined; 238 let bottom = undefined; 239 let left = undefined; 240 if (isLengthType(this.value) || isResource(this.value)) { 241 top = this.value; 242 right = this.value; 243 bottom = this.value; 244 left = this.value; 245 } else if (typeof this.value === 'object') { 246 top = (this.value as Padding).top; 247 right = (this.value as Padding).right; 248 bottom = (this.value as Padding).bottom; 249 left = (this.value as Padding).left; 250 } 251 getUINativeModule().toggle.setPadding(node, top, right, bottom, left); 252 } 253 } 254 checkObjectDiff(): boolean { 255 if (isResource(this.stageValue) && isResource(this.value)) { 256 return !isResourceEqual(this.stageValue, this.value); 257 } else if (!isResource(this.stageValue) && !isResource(this.value)) { 258 if (typeof this.stageValue === 'object' && typeof this.value === 'object') { 259 return !((this.stageValue as Padding).left === (this.value as Padding).left && 260 (this.stageValue as Padding).right === (this.value as Padding).right && 261 (this.stageValue as Padding).top === (this.value as Padding).top && 262 (this.stageValue as Padding).bottom === (this.value as Padding).bottom); 263 } else { 264 return !(this.stageValue === this.value); 265 } 266 } 267 return true; 268 } 269} 270class ToggleBackgroundColorModifier extends ModifierWithKey<ResourceColor> { 271 constructor(value: ResourceColor) { 272 super(value); 273 } 274 static identity = Symbol('toggleBackgroundColor'); 275 applyPeer(node: KNode, reset: boolean): void { 276 if (reset) { 277 getUINativeModule().toggle.resetBackgroundColor(node); 278 } else { 279 getUINativeModule().toggle.setBackgroundColor(node, this.value); 280 } 281 } 282 checkObjectDiff(): boolean { 283 return !isBaseOrResourceEqual(this.stageValue, this.value); 284 } 285} 286class ToggleHoverEffectModifier extends ModifierWithKey<HoverEffect> { 287 constructor(value: HoverEffect) { 288 super(value); 289 } 290 static identity = Symbol('toggleHoverEffect'); 291 applyPeer(node: KNode, reset: boolean): void { 292 if (reset) { 293 getUINativeModule().toggle.resetHoverEffect(node); 294 } else { 295 getUINativeModule().toggle.setHoverEffect(node, this.value); 296 } 297 } 298} 299 300class ToggleSwitchStyleModifier extends ModifierWithKey<SwitchStyle> { 301 constructor(value: SwitchStyle) { 302 super(value); 303 } 304 static identity = Symbol('toggleSwitchStyle'); 305 applyPeer(node: KNode, reset: boolean): void { 306 if (reset) { 307 getUINativeModule().toggle.resetSwitchStyle(node); 308 } else { 309 getUINativeModule().toggle.setSwitchStyle(node, this.value.pointRadius, this.value.unselectedColor, 310 this.value.pointColor, this.value.trackBorderRadius); 311 } 312 } 313 314 checkObjectDiff(): boolean { 315 if (!isResource(this.stageValue) && !isResource(this.value)) { 316 return !(this.stageValue.pointRadius === this.value.pointRadius && 317 this.stageValue.unselectedColor === this.value.unselectedColor && 318 this.stageValue.pointColor === this.value.pointColor && 319 this.stageValue.trackBorderRadius === this.value.trackBorderRadius); 320 } else if (isResource(this.stageValue) && isResource(this.value)) { 321 return !(isResourceEqual(this.stageValue.pointRadius, this.value.pointRadius) && 322 isResourceEqual(this.stageValue.unselectedColor, this.value.unselectedColor) && 323 isResourceEqual(this.stageValue.pointColor, this.value.pointColor) && 324 isResourceEqual(this.stageValue.trackBorderRadius, this.value.trackBorderRadius)); 325 } else { 326 return true; 327 } 328 } 329} 330 331class ToggleContentModifier extends ModifierWithKey<ContentModifier<ToggleConfiguration>> { 332 constructor(value: ContentModifier<ToggleConfiguration>) { 333 super(value); 334 } 335 static identity: Symbol = Symbol('toggleContentModifier'); 336 applyPeer(node: KNode, reset: boolean, component: ArkComponent) { 337 let toggleComponent = component as ArkToggleComponent; 338 toggleComponent.setNodePtr(node); 339 toggleComponent.setContentModifier(this.value); 340 } 341} 342class ToggleOptionsModifier extends ModifierWithKey<object> { 343 constructor(value: object) { 344 super(value); 345 } 346 static identity: Symbol = Symbol('toggleOptions'); 347 applyPeer(node: KNode, reset: boolean): void { 348 if (reset) { 349 getUINativeModule().toggle.setToggleOptions(node, undefined); 350 } else { 351 getUINativeModule().toggle.setToggleOptions(node, this.value?.isOn); 352 } 353 } 354 355 checkObjectDiff(): boolean { 356 return !isBaseOrResourceEqual(this.stageValue.isOn, this.value.isOn); 357 } 358} 359// @ts-ignore 360globalThis.Toggle.attributeModifier = function (modifier: ArkComponent): void { 361 attributeModifierFunc.call(this, modifier, (nativePtr: KNode) => { 362 return new ArkToggleComponent(nativePtr); 363 }, (nativePtr: KNode, classType: ModifierType, modifierJS: ModifierJS) => { 364 return new modifierJS.ToggleModifier(nativePtr, classType); 365 }); 366}; 367// @ts-ignore 368globalThis.Toggle.contentModifier = function (modifier): void { 369 const elmtId = ViewStackProcessor.GetElmtIdToAccountFor(); 370 let nativeNode = getUINativeModule().getFrameNodeById(elmtId); 371 let component = this.createOrGetNode(elmtId, () => { 372 return new ArkToggleComponent(nativeNode); 373 }); 374 component.setNodePtr(nativeNode); 375 component.setContentModifier(modifier); 376};