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 * SynchedPropertyObjectTwoWayPU 18 * 19 * all definitions in this file are framework internal 20 */ 21class SynchedPropertyObjectTwoWayPU<C extends Object> 22 extends ObservedPropertyObjectAbstractPU<C> 23 implements ISinglePropertyChangeSubscriber<C> { 24 25 private linkedParentProperty_: ObservedPropertyObjectAbstract<C>; 26 private changeNotificationIsOngoing_: boolean = false; 27 28 constructor(linkSource: ObservedPropertyObjectAbstract<C>, 29 owningChildView: IPropertySubscriber, 30 thisPropertyName: PropertyInfo) { 31 super(owningChildView, thisPropertyName); 32 if (linkSource) { 33 this.linkedParentProperty_ = linkSource; 34 // register to the parent property 35 this.linkedParentProperty_.subscribeMe(this); 36 37 // register to the ObservedObject 38 ObservedObject.addOwningProperty(this.linkedParentProperty_.get(), this); 39 } 40 } 41 42 /* 43 like a destructor, need to call this before deleting 44 the property. 45 */ 46 aboutToBeDeleted() { 47 // unregister from parent of this link 48 if (this.linkedParentProperty_) { 49 this.linkedParentProperty_.unlinkSuscriber(this.id__()); 50 51 // unregister from the ObservedObject 52 ObservedObject.removeOwningProperty(this.linkedParentProperty_.getUnmonitored(), this); 53 } 54 super.aboutToBeDeleted(); 55 } 56 57 private setObject(newValue: C): void { 58 if (!this.linkedParentProperty_) { 59 stateMgmtConsole.warn(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: setObject, no linked parent property.`); 60 return; 61 } 62 this.linkedParentProperty_.set(newValue) 63 } 64 65 // this object is subscriber to ObservedObject 66 // will call this cb function when property has changed 67 hasChanged(newValue: C): void { 68 if (!this.changeNotificationIsOngoing_) { 69 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: contained ObservedObject hasChanged'.`) 70 this.notifyHasChanged(this.getUnmonitored()); 71 } 72 } 73 74 75 public getUnmonitored(): C { 76 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: getUnmonitored returns '${(this.linkedParentProperty_ ? JSON.stringify(this.linkedParentProperty_.getUnmonitored()) : "undefined")}' .`); 77 // unmonitored get access , no call to otifyPropertyRead ! 78 return (this.linkedParentProperty_ ? this.linkedParentProperty_.getUnmonitored() : undefined); 79 } 80 81 // get 'read through` from the ObservedProperty 82 public get(): C { 83 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: get`) 84 this.notifyPropertyRead(); 85 return this.getUnmonitored(); 86 } 87 88 // set 'writes through` to the ObservedProperty 89 public set(newValue: C): void { 90 if (this.getUnmonitored() == newValue) { 91 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}IP, '${this.info() || "unknown"}']: set with unchanged value '${newValue}'- ignoring.`); 92 return; 93 } 94 95 stateMgmtConsole.debug(`SynchedPropertyObjectTwoWayPU[${this.id__()}, '${this.info() || "unknown"}']: set to newValue: '${newValue}'.`); 96 97 ObservedObject.removeOwningProperty(this.getUnmonitored(), this); 98 99 // avoid circular notifications @Link -> source @State -> other but also back to same @Link 100 this.changeNotificationIsOngoing_ = true; 101 this.setObject(newValue); 102 ObservedObject.addOwningProperty(this.getUnmonitored(), this); 103 this.notifyHasChanged(newValue); 104 this.changeNotificationIsOngoing_ = false; 105 } 106} 107