1/* 2 * Copyright (c) 2022 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/** 17 * SynchedPropertySimpleTwoWayPU 18 * 19 * all definitions in this file are framework internal 20 */ 21 22class SynchedPropertySimpleTwoWayPU<T> extends ObservedPropertySimpleAbstractPU<T> 23 implements ISinglePropertyChangeSubscriber<T> { 24 25 private source_: ObservedPropertyAbstract<T>; 26 private changeNotificationIsOngoing_: boolean = false; 27 28 constructor(source: ObservedPropertyAbstract<T>, owningView: IPropertySubscriber, owningViewPropNme: PropertyInfo) { 29 super(owningView, owningViewPropNme); 30 this.source_ = source; 31 this.source_.subscribeMe(this); 32 } 33 34 /* 35 like a destructor, need to call this before deleting 36 the property. 37*/ 38 aboutToBeDeleted() { 39 if (this.source_) { 40 this.source_.unlinkSuscriber(this.id__()); 41 this.source_ = undefined; 42 } 43 super.aboutToBeDeleted(); 44 } 45 46 // this object is subscriber to SynchedPropertySimpleTwoWayPU 47 // will call this cb function when property has changed 48 // a set (newValue) is not done because get reads through for the source_ 49 hasChanged(newValue: T): void { 50 if (!this.changeNotificationIsOngoing_) { 51 stateMgmtConsole.debug(`SynchedPropertySimpleTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: hasChanged to '${newValue}'.`) 52 this.notifyHasChanged(newValue); 53 } 54 } 55 56 public getUnmonitored(): T { 57 stateMgmtConsole.debug(`SynchedPropertySimpleTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored`); 58 return (this.source_ ? this.source_.getUnmonitored() : undefined); 59 } 60 61 // get 'read through` from the ObservedProperty 62 public get(): T { 63 stateMgmtConsole.debug(`SynchedPropertySimpleTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: get`); 64 this.notifyPropertyRead(); 65 return this.getUnmonitored(); 66 } 67 68 // set 'writes through` to the ObservedProperty 69 public set(newValue: T): void { 70 if (!this.source_) { 71 stateMgmtConsole.debug(`SynchedPropertySimpleTwoWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set, no source, returning.`); 72 return; 73 } 74 75 if (this.source_.get() == newValue) { 76 stateMgmtConsole.debug(`SynchedPropertySimpleTwoWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set with unchanged value '${newValue}'- ignoring.`); 77 return; 78 } 79 80 stateMgmtConsole.debug(`SynchedPropertySimpleTwoWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set to newValue: '${newValue}'.`); 81 82 // avoid circular notifications @Link -> source @State -> other but also to same @Link 83 this.changeNotificationIsOngoing_ = true; 84 85 // the source_ ObservedProeprty will call: this.hasChanged(newValue); 86 this.source_.set(newValue); 87 this.notifyHasChanged(newValue); 88 89 this.changeNotificationIsOngoing_ = false; 90 } 91} 92