OpenCPN Partial API docs
Loading...
Searching...
No Matches
observable.h
Go to the documentation of this file.
1/*************************************************************************
2 *
3 *
4 * Copyright (C) 2022 - 2025 Alec Leamas
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18 **************************************************************************/
19
31#ifndef OBSERVABLE_H
32#define OBSERVABLE_H
33
34#include <functional>
35#include <memory>
36#include <mutex>
37#include <string>
38#include <utility>
39#include <vector>
40
41#include <wx/event.h>
42
43#include "event.h"
44
45#ifndef DECL_EXP
46#if defined(_MSC_VER) || defined(__CYGWIN__)
47#define DECL_EXP __declspec(dllexport)
48#elif defined(__GNUC__) || defined(__clang__)
49#define DECL_EXP __attribute__((visibility("default")))
50#else
51#define DECL_EXP
52#endif
53#endif // DECL_EXP
54
55class ObservableListener; // forward
56
57namespace obs {
58class Listener; // forward
59
61std::string PtrKey(const void* ptr);
62
63class Observable; // forward
64
72public:
73 virtual ~KeyProvider() = default;
74
76 [[nodiscard]] virtual std::string GetKey() const = 0;
77};
78
84 friend class Observable;
85 friend ListenersByKey& GetInstance(const std::string& key);
86
87public:
88 ListenersByKey() = default;
89 ListenersByKey(const ListenersByKey&) = delete;
90
91private:
92 static ListenersByKey& GetInstance(const std::string& key);
93
94 ListenersByKey& operator=(const ListenersByKey&) = default;
95
96 std::vector<std::pair<wxEvtHandler*, wxEventType>> listeners;
97};
98
100class Observable : public KeyProvider {
101 friend class ::ObservableListener;
102
103public:
105 explicit Observable(const std::string& _key)
106 : key(_key), m_list(ListenersByKey::GetInstance(_key)) {}
107
109 explicit Observable(const KeyProvider& kp) : Observable(kp.GetKey()) {}
110
111 ~Observable() override = default;
112
114 virtual void Notify();
115
122 virtual void Notify(const std::shared_ptr<const void>& p) {
123 Notify(p, "", 0, nullptr);
124 }
125
130 bool Unlisten(wxEvtHandler* listener, wxEventType ev);
131
133 std::string GetKey() const override { return key; }
134
136 const std::string key;
137
138protected:
144 void Notify(const std::shared_ptr<const void>& ptr, const std::string& s,
145 int num, void* client_data);
146
152 void Notify(const std::string& s, void* client_data){
153 Notify(nullptr, s, 0, client_data);
154 }
155
156private:
158 void Listen(wxEvtHandler* listener, wxEventType ev_type);
159
160 ListenersByKey& m_list;
161
162 mutable std::mutex m_mutex;
163};
164
165} // namespace
166
175class DECL_EXP ObservableListener final {
176 friend class obs::Listener;
177
178public:
180 ObservableListener() : m_listener(nullptr), m_ev_type(wxEVT_NULL) {}
181
188 ObservableListener (std::string k, wxEvtHandler* l, wxEventType e)
189 : m_key(std::move(k)), m_listener(l), m_ev_type(e) {
190 Listen();
191 }
192
199 ObservableListener(const obs::KeyProvider& kp, wxEvtHandler* l, wxEventType e)
200 : ObservableListener(kp.GetKey(), l, e) {}
201
202 ~ObservableListener() { Unlisten(); }
203
206 m_key = other.m_key;
207 m_listener = other.m_listener;
208 m_ev_type = other.m_ev_type;
209 other.Unlisten();
210 Listen();
211 }
212
215 m_key = other.m_key;
216 m_listener = other.m_listener;
217 m_ev_type = other.m_ev_type;
218 other.Unlisten();
219 Listen();
220 return *this;
221 }
222
225
228
230 void Listen(const std::string& key, wxEvtHandler* listener, wxEventType evt);
231
233 void Listen(const obs::KeyProvider& kp, wxEvtHandler* l, wxEventType evt) {
234 Listen(kp.GetKey(), l, evt);
235 }
236
237private:
238 void Listen();
239 void Unlisten();
240
241 std::string m_key;
242 wxEvtHandler* m_listener;
243 wxEventType m_ev_type;
244};
245
246namespace obs {
247
293class Listener : public wxEvtHandler {
294public:
296 Listener() : m_obs_evt(wxNewEventType()) {}
297
299 Listener(Listener&& other) noexcept: m_obs_evt(wxNewEventType()) {
300 m_listener.Unlisten();
301 Unbind(other.m_obs_evt, other.m_action);
302 m_action = other.m_action;
303 Bind(m_obs_evt, m_action);
304 m_listener.Listen(other.m_listener.m_key, this, m_obs_evt);
305 }
306
308 Listener& operator=(Listener&& other) noexcept {
309 m_listener.Unlisten();
310 Unbind(other.m_obs_evt, other.m_action);
311 m_action = other.m_action;
312 Bind(m_obs_evt, m_action);
313 m_listener.Listen(other.m_listener.m_key, this, m_obs_evt);
314 return *this;
315 }
316
318 Listener(const Listener&) = delete;
319
321 Listener& operator=(Listener&) = delete;
322
324 Listener(const KeyProvider& kp,
325 const std::function<void(ObservedEvt& ev)>& action)
326 : m_obs_evt(wxNewEventType()) {
327 Init(kp, action);
328 }
329
331 Listener(const KeyProvider& kp, const std::function<void()>& action)
332 : Listener(kp, [&](ObservedEvt&) { action(); }) {}
333
338 void Init(const KeyProvider& kp,
339 const std::function<void(ObservedEvt& ev)>& action) {
340 m_action = action;
341 const wxEventTypeTag<ObservedEvt> EvtObs(wxNewEventType());
342 // i. e. wxDEFINE_EVENT(), avoiding the evil macro.
343 m_listener.Listen(kp, this, EvtObs);
344 Bind(EvtObs, action);
345 }
346
347private:
348 ::ObservableListener m_listener;
349 std::function<void(ObservedEvt& ev)> m_action;
350 const wxEventTypeTag<ObservedEvt> m_obs_evt;
351};
352
354template <typename T>
355std::shared_ptr<const T> UnpackEvtPointer(const ObservedEvt& ev) {
356 return std::static_pointer_cast<const T>(ev.GetSharedPtr());
357}
358
359} // namespace
360#endif // OBSERVABLE_H
Manages listening to an Observable instance.
Definition observable.h:175
ObservableListener(ObservableListener &&other) noexcept
std::move() support.
Definition observable.h:205
ObservableListener(const obs::KeyProvider &kp, wxEvtHandler *l, wxEventType e)
Construct a listening object.
Definition observable.h:199
ObservableListener(std::string k, wxEvtHandler *l, wxEventType e)
Construct a listening object.
Definition observable.h:188
ObservableListener & operator=(ObservableListener &)=delete
A listener is non copyable, can only be transferred using std::move().
void Listen(const obs::KeyProvider &kp, wxEvtHandler *l, wxEventType evt)
Set object to send wxEventType ev to listeners on changes in key.
Definition observable.h:233
ObservableListener(const ObservableListener &other)=delete
A listener is non copyable, can only be transferred using std::move().
ObservableListener & operator=(ObservableListener &&other) noexcept
std::move() support.
Definition observable.h:214
ObservableListener()
Default constructor, does not listen to anything.
Definition observable.h:180
Custom event class for OpenCPN's notification system.
std::shared_ptr< const void > GetSharedPtr() const
Gets the event's payload data.
Interface implemented by classes which listens.
Definition observable.h:71
virtual std::string GetKey() const =0
Return string used by Notify() and Listen().
Private helper class.
Definition observable.h:83
The observable notify/listen basic nuts and bolts.
Definition observable.h:100
const std::string key
The key used to create and clone.
Definition observable.h:136
Observable(const KeyProvider &kp)
Initiate an object which can apply Notify() and Listen() to given key.
Definition observable.h:109
virtual void Notify()
Notify all listeners to configured key about variable change.
virtual void Notify(const std::shared_ptr< const void > &p)
Notify all listeners to configured key about variable change.
Definition observable.h:122
void Notify(const std::string &s, void *client_data)
Notify all listeners: send them a 'type' ObservedEvt message as defined by Listen() with optional dat...
Definition observable.h:152
Observable(const std::string &_key)
Initiate an object which can apply Notify() and Listen() to given key.
Definition observable.h:105
std::string GetKey() const override
Return the key given to the constructor.
Definition observable.h:133
bool Unlisten(wxEvtHandler *listener, wxEventType ev)
Remove window listening to ev from list of listeners.
wxCommandEvt subclass which can carry also a shared_ptr<void>
std::string PtrKey(const void *ptr)
Return address as printable string.