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