MuseScore  3.4
Music composition and notation
notifier.hpp
Go to the documentation of this file.
1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2018 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __NOTIFIER_H__
14 #define __NOTIFIER_H__
15 
16 namespace Ms {
17 
18 template<typename Data> class Notifier;
19 
20 //---------------------------------------------------------
21 // Listener
22 //---------------------------------------------------------
23 
24 template<typename Data>
25 class Listener {
27 
28  public:
29  Listener() = default;
30  Listener(Notifier<Data>* n) : _notifier(n) {}
31  // do not copy notifier attachment
34  Listener& operator=(const Listener<Data>&) { return *this; }
36  ~Listener();
37 
38  void setNotifier(Notifier<Data>* n);
39 
40  void detachNotifier(Notifier<Data>* n) { if (_notifier == n) setNotifier(nullptr); }
41 
43  const Notifier<Data>* notifier() const { return _notifier; }
44 
45  virtual void receive(Data d) = 0;
46 
47  template<typename T>
48  friend void swap(Listener<T>& l1, Listener<T>& l2);
49  };
50 
51 //---------------------------------------------------------
52 // Notifier
53 //---------------------------------------------------------
54 
55 template<typename Data>
56 class Notifier {
57  std::vector<Listener<Data>*> _listeners;
58  bool _atChange = false;
59 
60  public:
61  Notifier() = default;
62  // do not copy listeners list
64  Notifier& operator=(const Notifier<Data>&) { return *this; }
66  {
67  _atChange = true; // we don't need to update listeners list anymore
68  for (Listener<Data>* l : _listeners)
69  l->detachNotifier(this);
70  }
71 
73  {
74  if (_atChange || !l)
75  return;
76  _atChange = true;
77  _listeners.push_back(l);
78  l->setNotifier(this);
79  _atChange = false;
80  }
81 
83  {
84  if (_atChange || !l)
85  return;
86  _atChange = true;
87  _listeners.erase(std::remove(_listeners.begin(), _listeners.end(), l), _listeners.end());
88  l->detachNotifier(this);
89  _atChange = false;
90  }
91 
92  void notify(Data d) const
93  {
94  for (Listener<Data>* l : _listeners)
95  l->receive(d);
96  }
97  };
98 
99 template<typename Data>
101  {
102  if (Notifier<Data>* n = other.notifier()) {
103  n->removeListener(other);
104  setNotifier(n);
105  }
106  }
107 
108 template<typename Data>
110  {
111  if (Notifier<Data>* n = other.notifier()) {
112  n->removeListener(other);
113  setNotifier(n);
114  }
115  else
116  setNotifier(nullptr);
117  }
118 
119 template<typename Data>
121  {
122  if (_notifier)
123  _notifier->removeListener(this);
124  }
125 
126 template<typename Data>
128  {
129  if (n == _notifier)
130  return;
131  Notifier<Data>* oldNotifier = _notifier;
132  _notifier = n;
133  if (oldNotifier)
134  oldNotifier->removeListener(this);
135  if (_notifier)
136  _notifier->addListener(this);
137  }
138 
139 template<typename Data>
141  {
142  Notifier<Data>* n1 = l1.notifier();
143  Notifier<Data>* n2 = l2.notifier();
144  l1.setNotifier(n2);
145  l2.setNotifier(n1);
146  }
147 
148 } // namespace Ms
149 #endif
150 
Listener()=default
Notifier(const Notifier< Data > &)
Definition: notifier.hpp:63
void setNotifier(Notifier< Data > *n)
Definition: notifier.hpp:127
~Notifier()
Definition: notifier.hpp:65
void removeListener(Listener< Data > *l)
Definition: notifier.hpp:82
Notifier & operator=(const Notifier< Data > &)
Definition: notifier.hpp:64
Definition: notifier.hpp:25
void addListener(Listener< Data > *l)
Definition: notifier.hpp:72
friend void swap(Listener< T > &l1, Listener< T > &l2)
const Notifier< Data > * notifier() const
Definition: notifier.hpp:43
void notify(Data d) const
Definition: notifier.hpp:92
Listener(const Listener< Data > &)
Definition: notifier.hpp:32
~Listener()
Definition: notifier.hpp:120
Notifier< Data > * notifier()
Definition: notifier.hpp:42
virtual void receive(Data d)=0
Definition: aeolus.cpp:26
Listener & operator=(const Listener< Data > &)
Definition: notifier.hpp:34
void detachNotifier(Notifier< Data > *n)
Definition: notifier.hpp:40
Definition: notifier.hpp:18
std::vector< Listener< Data > * > _listeners
Definition: notifier.hpp:57
Listener(Notifier< Data > *n)
Definition: notifier.hpp:30
Notifier< Data > * _notifier
Definition: notifier.hpp:26