Timeline: use a sequence of structure description verbs

...like
 * ruler
 * gap
 * content
 * open/close sub scope
...
This commit is contained in:
Fischlurch 2019-04-06 18:21:26 +02:00
parent f2eea38c07
commit df02258547
8 changed files with 133 additions and 28 deletions

View file

@ -23,16 +23,17 @@ the source directory structures.
This three Layers are:
The Stage Layer::
User interfaces are implemented as plug-ins, most commonly one will see
the default GUI. But also scripting interfaces or specialized GUI's are
possible.
Interaction and presentation. User interfaces are implemented as plug-ins,
and while most commonly one will see the GTK UI, it would be possible to
construct a entirely different user interface, a CLI intereface, or even
operate the application ``headless'', script driven.
The Steam Layer::
Keeps the Session, generates the rendering graphs for sequences,
arranges what to do when and how.
The Vault Layer::
Manages thread-queues, schedules jobs, does the memory management for the
Manages worker pools, schedules jobs, does the memory management for the
heavy multimedia data. Loads and delegates to external libraries for
media processing.

View file

@ -38,7 +38,7 @@
** the concrete receiver, e.g. `VERB_doit (receiver, arg1, arg2)`
** results in the invocation of \c receiver.doit(arg1,arg2)
**
** @see ...TODO
** @see [prominent usage: the Diff system](\ref lib::diff::DiffLanguage)
** @see VerbFunctionDispatch_test
**
*/
@ -66,6 +66,9 @@ namespace lib {
* as defined in the "receiver" interface (parameter \c REC).
* The token is typically part of a DSL and can be applied
* to a concrete receiver subclass.
* @tparam REC the type receiving the verb invocations
* @tparam SIG signature of the actual verb function, expected
* to exist on the receiver (REC) interface
* @remarks while the included ID Literal is mostly for diagnostics,
* it also serves as identity for comparisons. Conceptually what
* we want is to compare the function "offset", but this leads
@ -101,22 +104,18 @@ namespace lib {
, token_(token)
{ }
VerbToken() : token_("NIL") { }
VerbToken()
: handler_{}
, token_("NIL")
{ }
/* default copyable */
bool
operator== (VerbToken const& o) const ///< @remarks member pointers to virtual functions aren't comparable, for good reason
{
return token_ == o.token_;
}
bool
operator!= (VerbToken const& o) const
{
return token_ != o.token_;
}
/** equality of VerbToken, based on equality of the #token_ Literal
* @remarks member pointers to virtual functions aren't comparable, for good reason
*/
bool operator== (VerbToken const& o) const { return token_ == o.token_; }
bool operator!= (VerbToken const& o) const { return token_ != o.token_; }
};
#define VERB(RECEIVER, FUN) VERB_##FUN (&RECEIVER::FUN, STRINGIFY(FUN))

View file

@ -31,6 +31,7 @@
#include "stage/gtk-base.hpp"
#include "stage/timeline/body-canvas-widget.hpp"
#include "stage/timeline/track-profile.hpp"
#include "stage/timeline/track-body.hpp"
//#include "stage/ui-bus.hpp"

View file

@ -61,7 +61,7 @@
//#include "lib/util.hpp"
//#include <memory>
#include <memory>
//#include <vector>
@ -69,14 +69,18 @@
namespace stage {
namespace timeline {
class TrackProfile;
class TrackBody;
class TimelineCanvas
: public Gtk::Layout
{
using TProfile = std::unique_ptr<TrackProfile>;
public:
TrackBody* rootBody_;
TProfile profile_;
TimelineCanvas();

View file

@ -41,6 +41,7 @@
#define STAGE_TIMELINE_TRACK_BODY_H
#include "stage/gtk-base.hpp"
#include "stage/timeline/track-profile.hpp"
#include "stage/timeline/ruler-track.hpp"
//#include "lib/util.hpp"

View file

@ -0,0 +1,75 @@
/*
TRACK-PROFILE.hpp - building the 3D profile of tracks for timeline presentation
Copyright (C) Lumiera.org
2019, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file track-profile.hpp
** Abstraction build the layout for the track spaces for timeline display.
** In Lumiera, tracks are arranged into a fork of nested shapes, which structure
** is parallelled into nested structure of TrackBody elements. A tree walk over
** this structure yields a sequence of adjacent timeline elements, like overview
** rulers, content area and nested child track display. This sequence can then
** be transformed into suitable drawing instructions to create a 3D shaded
** display, clearly highlighting the complex structure of the track arrangement.
**
** @todo WIP-WIP-WIP as of 4/2019
**
*/
#ifndef STAGE_TIMELINE_TRACK_PROFILE_H
#define STAGE_TIMELINE_TRACK_PROFILE_H
#include "stage/gtk-base.hpp"
#include "lib/verb-token.hpp"
//#include "lib/util.hpp"
//#include <memory>
#include <vector>
namespace stage {
namespace timeline {
/**
* Description of the structure and arrangement of tracks for display in the UI.
* This sequence of verb tokens especially details the _profile_ of a vertical
* cross-section; the nested structure of the track fork is translated into
* a series of steps and insets, running alongside the timeline display.
* To decouple the drawing code -- thus allowing for later customisations --
* we let the individual TrackBody elements just emit these structure description.
* @todo WIP-WIP as of 4/2019
*/
class TrackProfile
{
public:
private:/* ===== Internals ===== */
};
}}// namespace stage::timeline
#endif /*STAGE_TIMELINE_TRACK_PROFILE_H*/

View file

@ -3517,7 +3517,7 @@ In accordance with the Lumiera application architecture in general, the UI is no
<pre>A specially configured LumieraPlugin, which actually contains or loads the complete code of the (GTK)GUI, and additionally is linked dynamically against the application core lib. During the [[UI startup process|GuiStart]], loading of this Plugin is triggered from {{{main()}}}. Actually this causes spawning of the GTK event thread and execution of the GTK main loop.
</pre>
</div>
<div title="GuiTimelineDraw" creator="Ichthyostega" modifier="Ichthyostega" created="201904052156" modified="201904060157" tags="GuiPattern spec impl img draft" changecount="48">
<div title="GuiTimelineDraw" creator="Ichthyostega" modifier="Ichthyostega" created="201904052156" modified="201904061546" tags="GuiPattern spec impl img draft" changecount="90">
<pre>The presentation of the track body area relies on the [[Gtk::Layout &quot;canvas widget&quot;|GtkLayoutWidget]], thus allowing for a mixture of custom drawing with embedded custom Gtk widgets. The actual drawing routine is activated in response to the {{{on_draw}}} signal -- and invoking the inherited handler function will initiate the standard drawing for the embedded child widgets. This partitions the additional, specific drawing activities into a pre-widget drawing phase to prepare the background and framework structure of the track area, and a post-widget drawing phase to show all kinds of overlays, markers cursors and similar UI indicators. A nested structure of {{{TrackBody}}} objects serves as organisational device to structure these custom drawing activities in accordance with the nested structure of the track fork.
!Building a nested 3D structure
@ -3526,16 +3526,18 @@ In accordance with the Lumiera application architecture in general, the UI is no
In Lumiera, the //tracks// represent an organisational device, a nested set of //scopes,// which -- for the UI representation -- is paralleled by nested insets holding the media content. One or several //rulers// as guiding devices run alongside the top of each scope, either representing the scope as a whole, or introducing the working area of this scope similar to a side walk running alongside a channel. A system of increasingly deeper nested scopes thus becomes a cadence of insets in the way of a lateral staircase.
Each individual track contributes a similar sequence of structure elements to this overall ''track profile'':
* a set of rulers, where each ruler may optionally inject a small additional //gap//
* a set of rulers
** where each ruler may optionally inject a small additional //gap//
* a content area
* the self similar recursive child track fork
* an inset
** holding the self similar recursive child track fork
!!!Assembling the track profile
The actual expression of these elements depends on the content, which is injected via diff message pushed up from the steam layer; additionally, some presentation state like collapsing of elements need to be taken into account. Assembling the complete profile of the track structure thus incurs a tree walk over the nested track body objects, which in turn communicate with the track presenters for layout state. At this point, it is advisable to separate the actual graphics drawing code from the content and state discovery scattered over the nested structure. Thus we produce a ''verb sequence'' as result of the tree walk, which can be stored into a (heap allocated) list for repeated evaluation when handling the actual draw events. Whenever the overall layout has been invalidated, this structure description has to be rebuilt by yet another tree walk. To illustrate this concept, with {{{r(#)}}} ruler, {{{g}}} gap, {{{c(#)}}} content and ''⤵⤴'' direction verbs, the profile above might yield a sequence
|&gt;|&gt;|&gt;|&gt;|!__Track-1__ |
| | !__Track-11__ |&gt;|&gt;|!__Track-12__ |
|&gt;|&gt;| |!__Track-121__ |!__Track-122__ |
|r(1),r(1),g,''c''(2)|⤵r(1),g,''c''(3)|r(1),g,r(1)|⤵r(1),''c''(2)|r(1),''c''(1)⤴⤴|
The actual expression of these elements depends on the content, which is injected via diff message pushed up from the steam layer; additionally, some presentation state like collapsing of elements need to be taken into account. Assembling the complete profile of the track structure thus incurs a tree walk over the nested track body objects, which in turn communicate with the track presenters for layout state. At this point, it is advisable to separate the actual graphics drawing code from the content and state discovery scattered over the nested structure. Thus we produce a ''verb sequence'' as result of the tree walk, which can be stored into a (heap allocated) list for repeated evaluation when handling the actual draw events. Whenever the overall layout has been invalidated, this structure description has to be rebuilt by yet another tree walk. To illustrate this concept, with {{{r(#)}}} ruler, {{{g}}} gap, {{{c(#)}}} content and ''⤵⤴'' direction verbs, the profile above might yield the sequence...
|&gt;|&gt;|&gt;|&gt;|&gt;|&gt;|&gt;|&gt;|!__Track-1__ |
| | | !__Track-11__ |&gt;|&gt;|&gt;|&gt;|!__Track-12__ | |
|~|~|&gt;| | |!__Track-121__ |!__Track-122__ | |~|
|r(1),r(1),g,''c''(2)|⤵|r(1),g,''c''(3)|r(1),g,r(1)|⤵|r(1),''c''(2) |r(1),''c''(1)||⤴|
</pre>
</div>
<div title="GuiTimelineSlave" creator="Ichthyostega" modifier="Ichthyostega" created="201810111210" tags="GuiPattern design decision draft" changecount="1">

View file

@ -19674,14 +19674,36 @@
<node CREATED="1554516172112" ID="ID_1550870826" MODIFIED="1554516185068" TEXT="leeren zum Invalidieren"/>
</node>
<node CREATED="1554516191248" ID="ID_379475221" MODIFIED="1554516205420" TEXT="on_draw() ist h&#xe4;ufiger als Struktur&#xe4;nderungen"/>
<node CREATED="1554567390096" ID="ID_611611667" MODIFIED="1554567398590" TEXT="Liste nicht verbergen">
<icon BUILTIN="yes"/>
<node CREATED="1554567399523" ID="ID_139156989" MODIFIED="1554567408216" TEXT="der draw-Code darf durchaus die Liste sehen"/>
<node CREATED="1554567408804" ID="ID_1274839361" MODIFIED="1554567445051" TEXT="ggfs mu&#xdf; er n&#xe4;mlich den Kontext beachten">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...zum Beispiel um einen &quot;Wall&quot; auch expressiv zu schattieren
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node CREATED="1554516243633" ID="ID_386714682" MODIFIED="1554516245860" TEXT="Verben">
<node CREATED="1554516247416" ID="ID_711078188" MODIFIED="1554516251040" TEXT="ruler"/>
<node CREATED="1554516251688" ID="ID_24688004" MODIFIED="1554516256283" TEXT="gap"/>
<node CREATED="1554516257065" ID="ID_389097560" MODIFIED="1554516261186" TEXT="content"/>
<node CREATED="1554516438055" ID="ID_1490793853" MODIFIED="1554516446110" TEXT="open / close"/>
<node CREATED="1554567321239" FOLDED="true" ID="ID_1638157583" MODIFIED="1554567367842" TEXT="prelude / coda">
<node CREATED="1554567338981" ID="ID_1124816442" MODIFIED="1554567365787" TEXT="damit der Display-Code da was Spezielles machen kann..."/>
</node>
<node CREATED="1554516547904" ID="ID_229346999" MODIFIED="1554516552054" TEXT="Implementierung">
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1554516547904" ID="ID_229346999" MODIFIED="1554567309965" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node CREATED="1554516552951" ID="ID_600745992" MODIFIED="1554516555251" TEXT="Festlegungen">
<node CREATED="1554516555943" ID="ID_1554446719" MODIFIED="1554516577129" TEXT="Argument = vertikal in Pixeln"/>
<node CREATED="1554516578588" ID="ID_520338948" MODIFIED="1554516923727" TEXT="Spannen inklusive Dekoration">