Most dependencies within Lumiera are singletons and this approach remains adequate.
Singletons are not "EVIL" per se. But in some cases, there is an explicit
lifecycle, managed by some subsystem. E.g. some GUI services are only available
while the GTK event loop is running.
This special case can be integrated transparently into our lib::Depend<TY> front-end,
which defaults to creating a singleton otherwise.
we'll use a typedef to represent the default case
and provide the level within the UI-Tree as template parameter for the generic case
This avoids wrapping each definition into a builder function, which will be
the same function for 99% of the cases, and it looks rather compact and natural
for the default case, while still retaining genericity.
Another alternative would have been to inject the Tree-level at the invocation;
but doing so feels more like magic for me.
decided to add a very specific preprocessing here, to make the DSL notation more natural.
My guess is that most people won't spot the presence of this tiny bit of magic,
and it would be way more surprising to have rules like
UICoord::currentWindow().panel("viewer").create()
fail in most cases, simply because there is a wildcard on the perspective
and the panel viewer does not (yet) exist. In such a case, we now turn the
perspective into a "existential quantified" wildcard, which is treated as if
the actually existing element was written explicitly into the pattern.
...actually just more test coverage,
the feature is already implemented.
What *could* be done though is to inject that UIC_ELIDED marker
on missing perspective specs in create clauses automatically...
especially std::find is relevant here.
I consider this only a preliminary solution and need to think it over
more in detail. But, judging from the description given in
http://en.cppreference.com/w/cpp/iterator
and
http://en.cppreference.com/w/cpp/concept/InputIterator
...the standard concept of "input iterator" seems to be closest to our
own concept, albeit it requires things like post increment, and a
reference_type convertible to value_type -- requirements we do not
necessarily support with our more limited "Lumiera Forward Iterator"
util::contains used to pick the overload for strings,
i.e. it first converted the UI-Coordinates to diagnostic output format
and then searched that string for '*' to determine if the pattern is explicit
works as expected, but not what you'd intend....
...and breaks spectacularly once you search for something as innocuous as '.'
when used in a pattern for matching against the UI tree,
an element marked as UIC_ELIDED = "." is treated as existentially quantified.
This means, we assume / verify there *is* an element at that level,
but we do not care about what this element actually is. Within the
implementation, the handling is similar to a wildcard, yet such a
spec is not classified as a wildcard (it *is* an explicit element,
just not explicitly named).
The relevant consequence is that such an element matches at a leaf
position, while match on wildcards on leaf positions is prohibited,
to prevent arbitrary and nonsensical wildcard matches against
open ended patterns. Especially we need such an existential pattern
to express a rule to create elements from scratch, but within a
specific window with arbitrary (but existing) perspective.
This looks like YAGNI, and it would be non trivial to implement.
But since the feature looks important for slick UI behaviour,
I've made a new ticket and leave it for now
with the exception of some special situations,
which require additional features from the engine,
especially binding-on-context
Not sure though if I'll implement these or say YAGNI
turns out to be somewhat tricky.
The easy shot would be to use the comma operator,
but I don't like that idea, since in logic programming, comma means "and then".
So I prefer an || operator, similar to short-circuit evaluation of boolean OR
Unfortunately, OR binds stronger than assignment, so we need to trick our way
into a smooth DSL syntax by wrapping into intermediary marker types, and accept
rvalue references only, as additional safeguard to enforce the intended inline
definition syntax typical for DSL usage.
seems to be the most orthogonal way to strip adornments from the SIG type
Moreover, we want to move the functor into the closure, where it will be stored anyay.
From there on, we can pass as const& into the binder (for creating the partially closed functor)
...as it turned out, the result type was the problem: the lambda we provide
typically does not yield an Allocator, but only its baseclass function<UICoord(UICoord)>
solution: make Allocator a typedef, we don't expect any further functionality
...but not yet able to get it to compile.
Problem seems to be the generic lambda, which is itself a template.
Thus we need a way to instantiate that template with the correct arguments
prior to binding it into a std::function
been there, seen that recently (-> TreeExplorer, the Expander had a similar problem)
...this was quite an extensive digression, which basically gave us
a solid foundation for topological addressing and pattern matching
within the "interface space"
rationale: sometimes (likely this is even the standard case) we do not just
want to "extend", rather we want to extent at very specific levels.
This is easy to implement, based on the existing building blocks for path manipulation