Timeline: fabricate a (test/dummy) population diff for a more complex track

The population message is just made up, in order to create more interesting structures
in the UI and so to further the development of the timeline display.

For the actual structure I choose to mirror my example drawing in draw/UI-TimelineLayout-1.png
which is also used in the TiddlyWiki, on the #GuiTimelineView tiddler

https://lumiera.org/wiki/renderengine.html#GuiTimelineView
This commit is contained in:
Fischlurch 2019-07-19 18:07:47 +02:00
parent 3102de9d8a
commit e3cde9b78d
4 changed files with 93 additions and 16 deletions

View file

@ -283,26 +283,48 @@ verb `emu(ID)`::
made at the generation side.] At this point, this child scope is left
and the parent scope with all existing diff state is _popped from an
internal stack._
verb `set(GenNode)`::
assign a new value to the designated element. This is primarily intended
for primitive data values and requires the payload type to be assignable,
without changing the element's identity. The element is identified by the
payload's ID and -- similar as with the `mut()` verb -- needs to be present
already, i.e. it has to be mentioned by preceding order defining verbs.
In practical application, a diff thus is typically comprised of two parts or ``phases'':
In a first pass, we have to mention, confirm or supply all the elements, and as second step
we may assign new values or enter recursive mutation for some child elements. However, it is
possible to deviate from that general scheme, as long as all elements are _confirmed_ prior to
mutation. Some typical ``degenerated'' patterns of spelling out a diff are as follows:
- just a ``population diff'' without any `set` or `mut` verbs
- on the other hand, if we just want to mutate something, with the first verb `after(Ref::END)`
we accept all of the content as-is, while the next verbs may mutate some selected elements
- however, single assignment- or mutation operations can be interspersed into the first phase
of sequence confirmation (or re-ordering): because, whenever an element has just been mentioned,
it can (in fact without further search) be mutated right away. Thus, e.g. a `pick(ID)` verb can
immediately followed by a `set(GenNode)` to assign changed payload data without altering the
position or the identity of the element.
representation of objects
~~~~~~~~~~~~~~~~~~~~~~~~~
While we are talking about _structured data,_ in fact what are about to handle are *objects*, understood in the standard
flavour of object orientation, where an object is the instance of a type and offers a contract. Incidentally, this is
not the original, ``pure'' meaning of object orientation, but the one that became prolific in brining our daily practice
closer to the inherent structuring of modern human organisation. And in dealing with this kind of object, we sometimes
get into conflict with the essentially open and permissive nature of structured data. So we need to establish a
mapping rule, which translates into additional conventions about how to spell out matters in the diff language.
While we are talking about _structured data,_ in fact the entities we are about to handle are *objects*, understood in
the standard flavour of object orientation, where an object is the instance of a type and offers a contract. Incidentally,
this is not the original, ``pure'' meaning of object orientation, but the one that became prolific to bring our daily
practice closer to the inherent structuring of modern human organisation. And in dealing with this kind of object, we
sometimes get into conflict with the essentially open and permissive nature of structured data. So we need to establish
a mapping rule, which translates into additional conventions about how to spell out matters in the diff language.
We choose to leave this largely on the level of stylistic rules, thus stressing the language nature of the diff.
Even when this bears the danger to produce an exception very late, when it comes to applying the diff to a target
data structure. The intention behind this whole diff approach is to transform tight coupling with strict rules
into a loose collaboration based on a common understanding. So generally we'll assume the diff is just right,
and if not, we'll get what we deserve.footnote:[This gives rise to a tricky discussion about loss of strictness
and the costs incurred by that happening. We should not treat this topic in isolation, but rather consider that
loose coupling was chosen to avoid far more serious problems caused by tight coupling, and especially the poisoning
and dire consequences of a global fixed common data model, when used in a large, not homogeneous system.
But when a system indeed is not homogeneous, we better try to make each part open-closed, open for change
and the costs incurred by that happening. We should not treat this topic in isolation; we should recall that
loose coupling was chosen to avoid far more serious problems caused by tight coupling, and especially the
deteriorating and poisoning effect on architecture and the further dire consequences of a global fixed common
data model -- which become prdominant when used in a large, not homogeneous system.
And _when a system indeed is not homogeneous,_ we better try to make each part open-closed, open for change
but closed against extension. This is especially true in the case of the UI.]

View file

@ -108,7 +108,7 @@ namespace diff{
* to the first child element, while \c after(Ref::END) means to accept
* all of the existing data contents as-is (presumably to append further
* elements beyond that point).
* - \c set assign a new value to the element designated element.
* - \c set assign a new value to the designated element.
* This is primarily intended for primitive data values and requires
* the payload type to be assignable, without changing the element's
* identity. The element is identified by the payload's ID and needs

View file

@ -253,6 +253,14 @@ namespace diff{
* compound is able to consume tree diff messages and apply the respective
* changes and mutations to an otherwise opaque implementation data structure.
* @remarks in practice, this is the most relevant and typical `TreeMutator` setup.
* @tparam PAR base implementation TreeMutator; anything not implemented within
* this current "onion layer", is delegated down to the parent. This way,
* a complete TreeMutator implementation is assembled from several layers.
* @tparam BIN binding adapter to the actual target collection. This implementation
* of TreeMutator operations does not directly manipulate the attached
* collection, but rather uses the primitive operation building blocks
* provided through the binding; typically these building blocks are
* in fact lambdas, provided when setting up this binding to the target.
*/
template<class PAR, class BIN>
class ChildCollectionMutator

View file

@ -100,7 +100,17 @@ namespace session {
GenNode
ruler()
{
UNIMPLEMENTED("send diff to constitute a new ruler track");
return MakeRec()
.type (string{stage::TYPE_Ruler})
.genNode("Ruler");
}
/** fabricate an attribute node based on the
* human-readable part of the given elemen's ID */
GenNode
makeName (GenNode const& elm)
{
return GenNode{string{stage::ATTR_name}, elm.idi.getSym() };
}
} //(End)Implementation details....
@ -147,14 +157,51 @@ namespace session {
const GenNode timeline = emptyTimeline (baseID, forkRootID);
const GenNode rootTrackName = GenNode{string{stage::ATTR_name}, "Fork-Root"};
const GenNode forkRoot = MakeRec().genNode(forkRootID);
const GenNode track1 = emptyTrack ("Track-1");
const GenNode track2 = emptyTrack ("Track-2");
const GenNode track21 = emptyTrack ("Track-21");
const GenNode track22 = emptyTrack ("Track-22");
const GenNode track221 = emptyTrack ("Track-221");
const GenNode track222 = emptyTrack ("Track-222");
const GenNode timeRuler = ruler();
const GenNode scopeRuler0 = ruler();
const GenNode scopeRuler2 = ruler();
const GenNode scopeRuler22 = ruler();
const GenNode scopeRuler221 = ruler();
return MutationMessage{ ins (timeline)
, mut (timeline)
, mut (forkRoot)
, set (rootTrackName)
, ins (emptyTrack ("Track-1"))
, ins (emptyTrack ("Track-2"))
, ins (ruler())
, ins (rootTrackName)
, ins (track1)
, ins (track2)
, ins (timeRuler)
, ins (scopeRuler0)
, mut (track1)
, ins (makeName(track1))
, emu (track1)
, mut (track2)
, ins (makeName(track2))
, ins (track21)
, ins (track22)
, ins (scopeRuler2)
, mut (track21)
, ins (makeName(track21))
, emu (track21)
, mut (track22)
, ins (makeName(track22))
, ins (track221)
, ins (track222)
, ins (scopeRuler22)
, mut (track221)
, ins (makeName(track221))
, ins (scopeRuler221)
, emu (track221)
, mut (track222)
, ins (makeName(track222))
, emu (track222)
, emu (track22)
, emu (track2)
, emu (forkRoot)
, emu (timeline)
};