=begin pod
=PREFACE

Sorry, but I didn't solve the problem of the first word. So, let me use this paragraph as a cheat, not as a solution.

=CONCEPTS

This section is briefly describing the basic building blocks of the framework and the ideas moartaring them together.

=head2 L<Vikna::Object|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Object.md>

This is the root parent class of almost any other Vikna class except for a few basic data types. It implements the
followin key functions:

=item object identification (id and name)
=item object-aware exception throwing
=item object creation with custom profile support
=item code flow

As usual, more details are provided in the class documentation. Code flow will be explaned later in this document. But
right now I would focus a bit on ...

=head2 ... Custom Profiles

A I<profile> is a set of named parameters passed over to a class constructor to create a new class instance. For example:

    my %profile = name => 'myName', foo => 42;
    my $foo = Foo.new: |%profile;

The example demoes the most simple case we can imagine. In real life when one creates a new object it's profile values
can come from:

=item hard-coded arguments of C<new> method
=item an external configuration
=item defaults of the class itself or its parents

Vikna provide a unified way to merge all sources into a final profile to be used. This is done by allowing any type object
to have its own C<submethod> C<profile-default> which is expected to return a profile object coercable into a
L<C<Hash>|https://docs.raku.org/type/Hash> which would contain what the type object conisders to be viable defaults.
L<Vikna::Object|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Object.md>
then iterates over the C<submethods> in reverse RMRO order (the same as for the construction time submethods, see
L<RMRO|#RMRO> below), collects the profiles, and merges them into a final default one.

When the default profile is built, L<Vikna::Object|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Object.md> then runs it alongside with profiles obtained from the constructor
method arguments and from a config file (not implemented yet) through another C<submethod> C<profile-checkin>. The job
of C<profile-checkin> is to adjust the final profile so as to adjust some values according to demands of its owning
type object. For example, C<Vikna::Object::profile-checkin>, which would be invoked first, simply merges default, config,
and constructor profiles in the order mentioned into the destination hash. Any subsequent C<profile-checkin> would need
to modify that final profile if necessary.

An example of how it works can be found in L<Vikna::Widget|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Widget.md> class. It allows creating a new widget by either specifying
widget's geometry explicitly, via an instance of
L<Vikna::Rect|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Rect.md>,
or by passing C<x>, C<y>, C<w>, C<h> keys. In the latter case L<Vikna::Widget|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Widget.md>
implicitly create a new C<geom> key and removes redundant coordinate keys from the profile. Similarly it handles widget
attribute parameters.

One of the future concepts I plan to be implemented with custom profiles is I<themes> support. A theme could have own
configuration file which would be read by the application and passed into the custom profile processing.

=head3 RMRO

Despite the greatest efforts of Raku/Rakudo documentation team, they can't keep up with the pace of core development.
For this reason I'd try to briefly explain the RMRO principle here because there no documentation for it yet. Additional
information can be found in L<my blog post|http://blogs.perl.org/users/vadim_belman/2019/12/post.html>.

Actually, everything is rather simple here. L<MRO|https://docs.raku.org/language/objects#Inheritance> is well documented
and basically it is an order in which parent classes of a given class are considered when, say, a method is resolved.
RMRO is almost the same thing but in addition to classes it also includes consumed roles.

=head2 Lazy Attributes

Vikna use lazy attribute implementation by
L<C<AttrX::Mooish>|https://modules.raku.org/dist/AttrX::Mooish:cpan:VRURG>.

=head2 Code Flows

One of the problems with debugging a heavily threaded application without a debugger is tracing down messages belonging
to a particular thread. A situation could be worsened by the fact that sometimes two or more threads could be logically
linked to each other. And in few cases I said myself: even though this method doesn't fork into a thread, it still worth
considering it separately from the surrounding code!

So, the I<code flows> were born. They turned out to be especially useful with code tracing sub-framework provided
by L<Vikna::Tracer|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Tracer.md>
and revealed via C<Vikna::Object::trace> method. But they proved to be useful in exception reporting too.

=head2 Canvas And Invalidating

Canvas is something we draw on. And the drawing is mostly implemented via I<imprinting>. Sorry, a quirk of a text-based
UI!

A canvas in its normal state is actually immutable. It means, no imprinting would change its state. Drawing is only
allowed on invalidated rectangles. This way two goals are achieved. First, it might simplify drawing logic in many
cases so that a client using canvas doesn't need to test for boundaries to only update a part of its canvas. Second,
it works as an optimization cutting off unnecessary operations.

Canvas is a rectangle of cells. Each cell is represented by four of its attributes: a I<character>, a I<foreground> and
a I<background> colors, and I<style> (like B<bold> or I<italic>, etc.). One or many cells on a canvas can be partially
or fully transparent. No, it doesn't mean alpha blending or anything like this! It only means that any of cell
attributes can be transparent on its own. So, when one canvas is imprinted onto another and one of its cells has
transparent background (just unspecified, for that matter), and the target cell has it set to I<blue>, then the result
of imprinting will have I<blue> background.

The L<README|https://github.com/vrurg/raku-Vikna> contains a GIFed demo where this behavior is nicely demonstrated when
the moving window floats under the static one.

=head2 Widget

Do I need to explain this one? Ok, dear visitor, it's time to move on to another exhibit...

=head2 Events And Event Handling

An event is a class instance inheriting from
L<Vikna::Event|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Event.md>.
Events are split into categories. But what's more important, events in Vikna also have priorities. But I'll get back to
it a little later.

Handling of events always happens in a dedicated thread. Literally, almost every object capable of event handling has
an associated thread which runs its event loop. While it might sound like "wow, isn't it gonna be too many threads?", I'd
say: yes, most like it is. But considering the nature of a UI application, most of the time these threads would be
spending awaiting. Memory consuming – yes, but otherwise no harm is expected. For example, Rakudo re-uses OS-level
threads so that one system thread could be shared among many application threads unless they all is ran simultaneously.

The advantage we get with this model is as fast widget response to an event as possible.

Let me step aside here and tell you a bit of Vikna history. At some point I needed to develop a web scraper to assist
my wife in her work. In the process I wished I could output reports from different scraper threads into individual
windows. So, the scraper turned out to be unneeded after all, but the initial idea is currently implemented by Vikna.
Say, an instance of L<Vikna::TextScroll|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/TextScroll.md>
can be used like this:

    $!reporter = self.create: Vikna::TextScroll, ...;
    ...
    $!reporter.print: "Hello";
    $!reporter.say: " World!";

Simple, heh? More importantly, the same object can be used from many threads at the same time!

This is what I call I<the principle of kick and go>: you kick a widget and while it does its job, you do yours.

Another problem we get solved with single-threaded event loop is avoidance of a I<lock mayhem>. What I mean here is
a situation where race conditions are avoided with locks protecting internal object state. Or with a single lock
protecting the whole object itself (see L<C<OO::Monitors>|https://modules.raku.org/dist/OO::Monitors:cpan:JNTHN>.
The first case is risking ending up with many cases of deadlock. The second could suffer from performance loss in some
cases.

As a bottom line we can say that the model chosen for Vikna allows combining the advantages of a state machine
architecture for maintaining object state while providing all the advantages of fully async interfaces for code
using it.

I<Note> that to model be the most effective any reaction to an event must be as short in time as possible. So far, the
longest operation happening within an event loop thread is actual widget drawing. Yet a measure was taken to minimize
its impact on the overall performance.

=head2 Event Origin And Dispatcher

Every event has two key properties attached: I<origin> and I<dispatcher> objects. The I<origin> is purely informative
but very important property as it allows in certain cases to make a decision on whether we must or must not react to an
event. For example, command events handling code throws if a command received has been originated by another another
object.

I<dispatcher> has more influence over the event lifecycle as it is explicitly tells the even loop code which object is
to handle the event. Commonly, both I<origin> and I<dispatcher> point to the same originating object. But, for example,
events coming event sources (see
L<Vikna::EventHandling|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/EventHandling.md>)
would typically have their I<origin> set to the source while dispatcher will point to the widget the source is attached
to.

=head2 Event Priority

The I<kick and go> principle mentioned above have a downside. Imagine a situation where your widget moves and changes a lot but have
to react to user keypresses as fast as possible? Your code basically would look this way:

    until $done {
        $!widget.set-geom: self.calculate-new-geom;
    }

Apparently, this would involve both moving and redrawing. Our loop would flood the widget with geometry change events it
wouldn't be able to handle timely. And even though redraw events are postponed and dropped if another redraw is requested,
it would still cause any other event thrown into the queue to wait for its turn too long than it is considered acceptable
for a user interaction handling. Not to be mentioned that geometry change events on their own could cause the postponed
redraw events to come too late!

The solution is to give every event a priority. This way we could ensure that a key pressed by a user will be taken care
of as soon as the current event is processed. And that a postponed redraw event would push back any geometry change one
and we wouldn't observe a widget jumping from it's initial position to the final one with no intermediates.

I<BTW, implementation of this concept has resulted in
L<C<Concurrent::PChannel|https://modules.raku.org/dist/Concurrent::PChannel:cpan:VRURG>> development which is now in
the core of Vikna's event loop.>

Each event category has a default priority value assigned, but each individual event could get it's own one too.

=head2 Event Sources

What are the typical sources for events? Keyboard, mouse, internal program state changes. Ok, but what if I have, say,
a remote device of any kind producing them for me? One solution would be to simply have something like:

    $device.Supply.tap: -> $ev { self.dispatch: $ev };

but sometimes things are a bit more complicated than that. To provide a way for incapsulation of the code taking care
of such case, event handling subsystem supports so called I<event sources>. A I<source> is an object which produces
Vikna-capable events. Examples of such objects are
L<Vikna::Screen::ANSI|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Screen/ANSI.md> and
C<Input> defined in L<Vikna::OS::unix|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/OS/unix.md>.

An event source can be attached to any event handling object. For example, imagine one having a bunch of sensor reporting
their status back to our application. We can have a window per sensor with an event source translating sensor data into
specific events and injecting them into window's event loop. In this case the rest of the system won't care about those
events, the window doesn't need to filter out the events belonging to it. And to stop monitoring of a sensor it'd be
enough to just close its associated window! Besides, the driver for the sensor can be supplied by a third party, so we
would just C<use> a module:

    use MyApp::Sensor;

    class SensorWin is Vikna::Window {
        multi method event(Event::Init:D) {
            self.add-event-source: MyApp::Sensor, :$!device-IP;
        }
        multi method event(Event::Sensor::Overload:D $ev) {
            self.alert-report: $ev.cause;
        }
    }

=head2 Event Tagging

An event could have tags attached to it. A tag is an object which would help us identify the event in the stream of all
events handled by an object. For example, if an event is tagged with a string I<"foo"> then we can take a special action
against it somewhere in a handler:

=begin code
multi method event(Event::Foo:D $ev) {
    if "foo" ∈ $ev.tags {
        # Gotcha!
        self.take-the-foo-action;
    }
}
=end code

Tags are event more useful that that because they're I<viral>. If a new event dispatched in a dynamic context with
C<$*VIKNA-CURRENT-EVENT> then it is considered to be the event-initiator and the new event will inherit it's tags
from the initiator unless they were manually set.

Another way to tag events is to use routine C<tag-event> from
L<C<Vikna::Utils>|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Utils.md>.
If both event-initiator has tags and a C<tag-event> is in effect then the new event instance will have all tags merged
into one set.

Tag inheritance allows tracking series of events logically linked together. See for example
L<C<Vikna::Widget::Group>|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Widget/Group.md>
and how it implements synchronous group flattening.

=head2 Parent/Child Strata

Nothing has been said so far about parent/child relations of widgets because this is something intrinsic to probaly
every UI architecture out there. But what has to be mentioned is that in Vikna children are grouped into strata. There
are three of them whith self-explaining names: C<StBack>, C<StMain>, and C<StModal>. Apparently, the purpose is to
simplify management of children Z-order. Simply put, if a child widget is installed into C<StBack> then whenever it
requests to be moved atop, it won't overlap any window from C<STMain>.

You can see how widget C<EventList> from
L<the window example script|https://github.com/vrurg/raku-Vikna/blob/master/examples/window.raku> is using C<StBack>
stratum to stay below both windows.

As long as any widget can be both parent and child, strata are per-widget thing. It makes per-widget modality possible.

=head2 Application

An application is a glue which binds together OS-dependant layer (I<drivers> of a kind) and desktop widget.

=PRINCIPLES

The framework is built upon a few principles enlisted in this chapter.

=head2 Kick And Go Use Pattern

While user code does its work, Vikna do the work for the user code. I.e. the best implementation of anything is when
users can focus on solving their problems and only send as simple as possible commands to Vikna or receive simple and
clear responses. One of the best example of the implemenation of this principle is
L<C<Vikna::TextScroll>|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/TextScroll.md>
widget which can be used as a kind of simple terminal object with C<say> and C<print> methods:

    $ts.say: "Put something\rSay\non the widget";

That's it. We I<kick> a C<Vikna::TextScroll> object in C<$ts> with C<say> command and we I<go> on with own business.
Vikna will do the rest transparently.

=head2 Responsive Event Handling

No event should be processed longer than it takes to irritate the end user. If an event results in an unavoidably long
code run then the code must be forked into a separate async flow.

=head1 SEE ALSO

L<C<Vikna>|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna.md>,
L<C<Vikna::Classes>|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Classes.md>,
L<C<Vikna::Widget>|https://github.com/vrurg/raku-Vikna/blob/v0.0.3/docs/md/Vikna/Widget.md>

=AUTHOR

Vadim Belman <github:vrurg>

=end pod