From ef775133865ac61612c3192b62ec5bfdbe2911d9 Mon Sep 17 00:00:00 2001
From: "francois.grand" <francois.grand@irstea.fr>
Date: Fri, 20 Apr 2018 11:16:30 +0200
Subject: [PATCH] =?UTF-8?q?=20#46=20classes=20relatives=20au=20pattern=20o?=
 =?UTF-8?q?bservateur/observ=C3=A9=20d=C3=A9plac=C3=A9es=20depuis=20l'inte?=
 =?UTF-8?q?rface=20-=20la=20classe=20Props=20impl=C3=A9mente=20Observable?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/index.ts         |  1 +
 src/nub_factory.ts   |  4 +++
 src/session_nub.ts   | 62 +++++++++++++++++++++++++++++++++++++++++---
 src/util/observer.ts | 53 +++++++++++++++++++++++++++++++++++++
 4 files changed, 116 insertions(+), 4 deletions(-)
 create mode 100644 src/util/observer.ts

diff --git a/src/index.ts b/src/index.ts
index 8d0ea149..f904a4e2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -27,6 +27,7 @@ export * from "./util/result";
 export * from "./util/resultelement";
 export * from "./util/pair";
 export * from "./util/interval";
+export * from "./util/observer";
 export * from "./pab/pab_dimension";
 export * from "./pab/pab_puissance";
 export * from "./util/iterator";
diff --git a/src/nub_factory.ts b/src/nub_factory.ts
index 2301efbb..56a6a128 100644
--- a/src/nub_factory.ts
+++ b/src/nub_factory.ts
@@ -268,4 +268,8 @@ export class NubFactory {
                 throw new Error(`type de section ${ComputeNodeType[nt]} non pris en charge`);
         }
     }
+
+    // public get sessionNubIterator(): IterableIterator<SessionNub> {
+    //     return this._session[Symbol.iterator](); // crée un itérateur à partir d'un tableau
+    // }
 }
\ No newline at end of file
diff --git a/src/session_nub.ts b/src/session_nub.ts
index faf6c122..d1f320d1 100644
--- a/src/session_nub.ts
+++ b/src/session_nub.ts
@@ -1,10 +1,16 @@
 import { Nub } from "./nub";
+import { IObservable, Observer, Observable } from "./util/observer";
 
 /**
  * gestion d'un ensemble de propriétés (clé/valeur)
  */
-export class Props {
-    constructor(private _props: any = {}) { }
+export class Props implements IObservable {
+    // implémentation de IObservable par délégation
+    private _observable: Observable;
+
+    constructor(private _props: any = {}) {
+        this._observable = new Observable();
+    }
 
     public hasProperties(props: Props | {}): boolean {
         const keys = Object.keys(this._props);
@@ -24,8 +30,22 @@ export class Props {
         return this._props[key];
     }
 
-    public setPropValue(key: string, val: any): any {
-        this._props[key] = val;
+    private notifyPropChange(prop: string, val: any, sender: any) {
+        this.notifyObservers({
+            "action": "propertyChange",
+            "name": prop,
+            "value": val
+        }, sender)
+    }
+
+    public setPropValue(key: string, val: any, sender?: any): boolean {
+        const oldValue = this._props[key];
+        const changed = oldValue !== val;
+        if (changed) {
+            this._props[key] = val;
+            this.notifyPropChange(key, val, sender);
+        }
+        return changed;
     }
 
     public get props() {
@@ -38,6 +58,40 @@ export class Props {
             res._props[k] = this._props[k];
         return res;
     }
+
+    public toString(): string {
+        let res = "[";
+        for (const k in this._props) {
+            if (res != "[")
+                res += ", ";
+            res += `${k}:${this.props[k]}`;
+        }
+        res += "]"
+        return res;
+    }
+
+    // interface IObservable
+
+    /**
+     * ajoute un observateur à la liste
+     */
+    public addObserver(o: Observer) {
+        this._observable.addObserver(o);
+    }
+
+    /**
+     * supprime un observateur de la liste
+     */
+    public removeObserver(o: Observer) {
+        this._observable.removeObserver(o);
+    }
+
+    /**
+     * notifie un événement aux observateurs
+     */
+    public notifyObservers(data: any, sender?: any) {
+        this._observable.notifyObservers(data, sender);
+    }
 }
 
 /**
diff --git a/src/util/observer.ts b/src/util/observer.ts
new file mode 100644
index 00000000..6a17beb9
--- /dev/null
+++ b/src/util/observer.ts
@@ -0,0 +1,53 @@
+export interface Observer {
+    update(sender: any, data: any): void;
+}
+
+export interface IObservable {
+    /**
+     * ajoute un observateur à la liste
+     */
+    addObserver(o: Observer): void;
+
+    /**
+     * supprime un observateur de la liste
+     */
+    removeObserver(o: Observer): void;
+
+    /**
+     * notifie un événement aux observateurs
+     */
+    notifyObservers(data: any, sender?: any): void;
+}
+
+export class Observable implements IObservable {
+    private _observers: Observer[];
+
+    constructor() {
+        this._observers = [];
+    }
+
+    /**
+     * ajoute un observateur à la liste
+     */
+    public addObserver(o: Observer) {
+        if (this._observers.indexOf(o) == -1)
+            this._observers.push(o);
+    }
+
+    /**
+     * supprime un observateur de la liste
+     */
+    public removeObserver(o: Observer) {
+        this._observers = this._observers.filter(a => a !== o);
+    }
+
+    /**
+     * notifie un événement aux observateurs
+     */
+    public notifyObservers(data: any, sender?: any) {
+        if (sender == undefined)
+            sender = this;
+        for (let o of this._observers)
+            o.update(sender, data);
+    }
+}
-- 
GitLab