• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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 * Abstract class that manages subscribing properties
18 * that implement the interfaces ISinglePropertyChangeSubscriber
19 * and/or IMultiPropertiesChangeSubscriber. Each using @State, @Link, etc
20 * decorated varibale in a component will make its own subscription.
21 * When the component is created the subscription is added, and when the
22 * component is deleted it unsubscribes.
23 *
24 * About lifecycle: It is legal use for two components with two @State
25 * decorated variables to share the same instance to a SubscribaleAbstract
26 * object. Each such decorated variable implementation makes its own
27 * subscription to the SubscribaleAbstract object. Hence, when both variables
28 * have unsubscribed the SubscribaleAbstract may do its own de-initilization.,
29 * e.g. release held external resources.
30 *
31 * How to extend:
32 * A subclass manages the get and set to one or several properties on its own.
33 * The subclass needs to notify all relevant value changes to the framework for the
34 * UI to be updated. Notification should only be given for class properties that
35 * are used to generate the UI.
36 *
37 * A subclass must call super() in its constructor to let this base class
38 * initialize itself.
39 *
40 * A subclass must call 'notifyPropertyHasChanged' after the relevant property
41 * has changes. The framework will notify all dependent components to re-render.
42 *
43 * A sub-class may overwrite the 'addOwningProperty' function to add own
44 * functionality, but it must call super.addowningOwningProperty(..). E.g.
45 * the sub-class could connect to external resources upon the first subscriber.
46 *
47 * A sub-class may also overwrite the 'removeOwningProperty' function or
48 * 'removeOwningPropertyById' function to add own functionality,
49 * but it must call super.removeOwningProperty(..).
50 * E.g. the sub-class could release held external resources upon loosing the
51 * last subscriber.
52 *
53 */
54
55abstract class SubscribaleAbstract {
56
57  // keeps track of all subscribing properties
58  private owningProperties_: Set<number>;
59
60  /**
61   * make sure the call super from subclass constructor!
62   */
63  constructor() {
64    this.owningProperties_ = new Set<number>();
65    console.debug(`SubscribaleAbstract: construcstor done`);
66  }
67
68  /**
69  * A subsclass must call this function whenever one of its properties has
70   * changed that is used to construct the UI.
71   * @param propName name of the change property
72   * @param newValue the property value after the change
73   */
74  protected notifyPropertyHasChanged(propName: string, newValue: any) {
75    console.debug(`SubscribaleAbstract: notifyPropertyHasChanged '${propName}'.`)
76    var registry: IPropertySubscriberLookup = SubscriberManager.Get();
77    this.owningProperties_.forEach((subscribedId) => {
78      var owningProperty: IPropertySubscriber = registry!.get(subscribedId)
79      if (owningProperty) {
80        if ('hasChanged' in owningProperty) {
81          (owningProperty as ISinglePropertyChangeSubscriber<any>).hasChanged(newValue);
82        }
83        if ('propertyHasChanged' in owningProperty) {
84          (owningProperty as IMultiPropertiesChangeSubscriber).propertyHasChanged(propName);
85        }
86      } else {
87        console.error(`SubscribaleAbstract: notifyHasChanged: unknown subscriber.'${subscribedId}' error!.`);
88      }
89    });
90  }
91
92  /**
93   * Method used by the framework to add subscribing decorated variables
94   * Subclass may overwrite this function but must call the function of the base
95   * class from its own implementation.
96   * @param subscriber new subscriber that implements ISinglePropertyChangeSubscriber
97   * and/or IMultiPropertiesChangeSubscriber interfaces
98   */
99
100  public addOwningProperty(subscriber: IPropertySubscriber): void {
101    console.debug(`SubscribaleAbstract: addOwningProperty: subscriber '${subscriber.id__()}'.`)
102    this.owningProperties_.add(subscriber.id__());
103  }
104
105  /**
106   * Method used by the framework to ubsubscribing decorated variables
107   * Subclass may overwrite this function but must call the function of the base
108   * class from its own implementation.
109   * @param subscriber subscriber that implements ISinglePropertyChangeSubscriber
110   * and/or IMultiPropertiesChangeSubscriber interfaces
111   */
112  public removeOwningProperty(property: IPropertySubscriber): void {
113    return this.removeOwningPropertyById(property.id__());
114  }
115
116  public removeOwningPropertyById(subscriberId: number): void {
117    console.debug(`SubscribaleAbstract: removeOwningProperty '${subscriberId}'.`)
118    this.owningProperties_.delete(subscriberId);
119  }
120}
121