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