20 selector_ (eventselector), handler_ (handler), dispatcher_ (&edispatcher)
23 bool connected ()
const {
return nullptr != handler_; }
27 if (connected() && (selector_ == event_type || selector_ == detailedevent))
37 bool needs_purging =
false;
46 needs_purging =
false;
47 for (
size_t i = connections.size() - 1; i < connections.size(); i--)
50 if (!conp || !conp->connected())
51 connections.erase (connections.begin() + i);
55 emit (
const Event &event)
57 const String event_type =
event.type();
59 const String event_detail =
event.detail();
60 const String detailedevent = event_detail.
empty() ? event_type : event_type +
":" + event_detail;
62 for (
size_t i = 0; i < connections.size(); i++)
66 conp->emit (event, event_type, detailedevent);
69 if (in_emission == 0 && needs_purging)
78 for (
auto &conw : old_connections)
89EventConnection::disconnect ()
91 const bool was_connected = connected();
95 dispatcher_->purge_connections();
96 dispatcher_ =
nullptr;
100EventConnection::~EventConnection()
103 dispatcher_ =
nullptr;
107Emittable::Connection::connected ()
const
109 const EventConnectionP &econp = *
this;
110 return econp && econp->connected();
114Emittable::Connection::disconnect ()
const
116 const EventConnectionP &econp = *
this;
122static CoalesceNotifies *coalesce_notifies_head =
nullptr;
124CoalesceNotifies::CoalesceNotifies ()
126 next_ = coalesce_notifies_head;
127 coalesce_notifies_head =
this;
131CoalesceNotifies::flush_notifications ()
133 while (!notifications_.empty())
135 NotificationSet notifications;
136 notifications.swap (notifications_);
137 for (
const auto &ns : notifications)
139 ns.emittable->emit_event (
"notify", ns.detail);
143CoalesceNotifies::~CoalesceNotifies ()
145 CoalesceNotifies **ptrp = &coalesce_notifies_head;
146 while (*ptrp !=
this && *ptrp)
147 ptrp = &(*ptrp)->next_;
150 flush_notifications();
154CoalesceNotifies::NotificationHash::operator() (
const Notification ¬ification)
const
166 EmittableP emittablep = this->
weak_from_this().expired() ? nullptr : shared_ptr_cast<Emittable> (
this);
167 if (emittablep && coalesce_notifies_head)
168 coalesce_notifies_head->notifications_.
insert ({ emittablep, detail });
170 this->emit_event (
"notify", detail);
173EmittableImpl::~EmittableImpl()
175 EventDispatcher *old = ed_;
181EmittableImpl::on_event (
const String &eventselector,
const EventHandler &eventhandler)
185 ed_ =
new EventDispatcher();
187 ed_->connections.push_back (cptr);
188 return *
static_cast<Connection*
> (&cptr);
192EmittableImpl::emit_event (
const String &type,
const String &detail,
const ValueR fields)
195 const char eventtype_chars[] = ASE_STRING_SET_ASCII_ALNUM
"_";
196 for (
size_t i = 0; type[i]; i++)
197 if (!strchr (eventtype_chars, type[i])) {
198 warning (
"invalid characters in Event type: %s", type);
201 for (
size_t i = 0; detail[i]; i++)
202 if (!strchr (eventtype_chars, detail[i])) {
204 warning (
"invalid characters in Event detail: %s:%s", type, detail);
209 Event ev { type, detail };
210 for (
auto &&e : fields)
211 if (e.name !=
"type" && e.name !=
"detail")
218Emittable::js_trigger (
const String &eventselector, JsTrigger trigger)
221 Emittable::Connection econ = on_event (eventselector, trigger);
222 trigger.ondestroy ([econ] () { econ.disconnect(); });
226ObjectImpl::~ObjectImpl()
void emit_notify(const String &detail) override
Emit notify:detail, multiple notifications maybe coalesced if a CoalesceNotifies instance exists.
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
The Anklang C++ API namespace.
bool string_is_ncname(const String &input)
std::string String
Convenience alias for std::string.
uint32_t uint
Provide 'uint' as convenience type.
Structure for callback based notifications.
T weak_from_this(T... args)