Commit graph

4327 commits

Author SHA1 Message Date
4451d5bfc9 Clip: implement re-attachment after layout change
with these changes, essentially the clip is moved to the
new position established in the preceding DisplayEvaluation.

...there is still some problem when this DisplayEvaluation itself
is triggered from within draw(), because then GTK still uses the old
sub-widget coordinates within this draw code, pretty much as if
they were cached somewhere. The next draw() call then uses the
proper new coordinates.
2021-01-30 16:29:06 +01:00
2e4cd56f4f Relative-Hook: rectify the design
Partially as a leftover from the way more ambitious initial design,
we ended up with CanvasHook as an elaboration/specialisation of the
ViewHook abstraction. However, as it stands, this design is tilted,
since CanvasHook is not just an elaboration, but rather a variation
of the same basic idea.

And this is now more like a building pattern and less of a generic
framework, it seems adequate to separate these two variations completely,
even if this incurs a small amount of code duplication.


Actually this refactoring is necessary to resolve a bug, where
we ended up with the same Clip widgets attached two times to the
same Canvas control, one time through the ViewHook baseclass,
and a second time by the ctor of the "derived" CanvasHook
2021-01-30 13:29:50 +01:00
e175805481 Clip: rearrange storage of clip presentation data
This can only be a preliminary solution, since we do not know
the actual usage pattern of the ClipDelegate object yet.
We only know there will typically be a huge amount of clips
to represent in the UI, and we need to be careful to avoid
unneccesary reallocations.

Thus for now we use a data record as base class, and we
move the data record into the new allocation when switching gears.
However, this could easily be converted into a data delegate,
where we'd only transfer ownership without reallocation,
in case this turns out to be more efficient.
2021-01-29 23:08:53 +01:00
96dfbf7d96 DisplayEvaluation: introduce a 3rd pass to adjust widget positions
After some in-depth analysis, it seems best to reattach the Clips and Marker
top-down through the control structure, rather than building some additional
magic callback into the CanvasHook. Thus the 3rd DisplayEvaluation pass
now not only has to rebalance track header and body, but also
reatach or move each attached widget within the body, using its
nominal coordinates. This should then pick up the changed
layout decoration size
2021-01-29 14:15:18 +01:00
5b33605469 Clip: fill in minimal implementation to make the clip appear 2021-01-25 03:06:27 +01:00
21f6e61fd3 Clip: evaluate state of the clip display implementation
...as it turns out, a first preliminary clip display should be working by now;
seemingly I was able to the tough theoretical problems last spring,
and was at the point of actually allocating display extension space
within the custom drawing area of the timeline.

Thus a simple placeholder widget based on a Gtk::Button should show up
at the right position, when sending a suitable diff message. The only
thing missing seems to be a first rough draft for the function
determineRequiredVerticalExtension()
2021-01-24 14:54:53 +01:00
acb674a9d2 Project: update and clean-up Doxygen configuration
...in an attempt to clarify why numerous cross links are not generated.
In the end, this attempt was not very successful, yet I could find some breadcrumbs...

- file comments generally seem to have a problem with auto link generation;
  only fully qualified names seem to work reliably

- cross links to entities within a namespace do not work,
  if the corresponding namespace is not documented in Doxygen

- documentation for entities within anonymous namespaces
  must be explicitly enabled. Of course this makes only sense
  for detailed documentation (but we do generate detailed
  documentation here, including implementation notes)

- and the notorious problem: each file needs a valid @file comment

- the hierarchy of Markdown headings must be consistent within each
  documentation section. This entails also to individual documented
  entities. Basically, there must be a level-one heading (prefix "#"),
  otherwise all headings will just disappear...

- sometimes the doc/devel/doxygen-warnings.txt gives further clues
2021-01-24 19:35:45 +01:00
06dbb9fad5 DiffFramework: simplify existing bindings
...by relying on the newly implemented automatic standard binding
Looks like a significant improvement for me, now the actual bindings
only details aspects, which are related to the target, and no longer
such technicalitis like how to place a Child-Mutator into a buffer handle
2021-01-23 12:55:10 +01:00
c52576ffc7 Diff-Framework: fill in the access variations
no metaprogramming since almost a year ... kindof missed that queer feeling
2021-01-22 15:06:43 +01:00
05b5ee9a7e Diff-Framework: investigate simplification for the most common case
After this long break during the "Covid Year 2020",
I pick this clean-up task as a means to fresh up my knowledge about the code base

The point to note is, when looking at all the existing diff bindings,
seemingly there is a lot of redundancy on some technical details,
which do not cary much meaining or relevance at the usage site:

- the most prominent case is binding to a collection of DiffMutables hold by smart-ptr
- all these objects expose an object identity (getID() function), which can be used as »Matcher«
- and all these objects can just delegate to the child's buildMutator() function
  for entering a recursive mutation.
2021-01-22 12:38:45 +01:00
657b94a4e3 ++ a strange year passed by ++
read the code, documentation and mindmap to find out
at what point I was when this story unfolded
2021-01-20 08:05:30 +01:00
710e35c87a Fix some further mentions and links to Cinelerra-CV
as indicated by Igor Vladimirsky
2020-12-11 23:48:30 +01:00
28adf9a642 Clip: pondering about the representation of clip timings 2020-04-09 00:15:05 +02:00
ea3ea811bf Clip: sort out access to the canvas abstraction 2020-04-08 22:55:33 +02:00
765d124fff Clip: draft the decision logic for the clip presentation mode 2020-04-03 19:44:46 +02:00
cfa8e87931 Relative-Hook: now able to push down time->pixel translation (see #1213)
the actual translation is still TODO;
we should delegate the calculation to the DisplayManager,
which is in focus within the TrackBody, where the coordinate
translation hook is now located.
2020-03-23 04:29:06 +01:00
e33eae729b Relative-Hook: complete refactoring down to tracks and clips (see #1213)
...and the result was very much worth the effort,
leading to more focused and cleaner code.

 - all the concerns of moving widgets and translating coordinates
   are now confined to the second abstraction layer (CanvasHook)

 - while the ViewHook now deals exclusively with attachment, detachment
   and reordering of attachment sequence
2020-03-23 04:16:10 +01:00
f956f27ff4 Relative-Hook: build CanvasHook abstraction based on ViewHook
this refactoring was expedient, as the code becomes
way more legible within each of the two levels of abstraction
2020-03-23 02:02:06 +01:00
22bc2167f9 Relative-Hook: prepare to split the abstraction into two levels
Level-1 : generic attachment into some kind of view
Level-2 : attachment by coordinates onto some kind of canvas
2020-03-22 16:37:58 +01:00
030fbd74c4 Clip: next step to establish a Delegate and appearance style
while the actual selection logic for the appearance style still remains
to be coded, this changeset basically settles the tricky initialisation sequence
2020-03-16 01:49:53 +01:00
dd016667ad Diff-Listener: add a variant to trigger also on value assignment (see #1206)
As it turned out, it is rather easy to extend the existing listener
for structural changes to detect also value assignments. Actually
it seems we'd need both flavours, so be it.
2020-03-15 23:11:14 +01:00
31116fb079 Clip: draft state-switching operation 2020-03-15 17:26:13 +01:00
4015a98d23 Clip: wire the optional startpoint parameter
...to indicate how the setting up the delegate might decide upon the appearance style

WIP: this is more than half baked
 - for one it seems doubtful to pass a hidden hint regarding appearance through that optional argument
 - and then, most importantly, we should be passing a time::TimeSpan
2020-03-15 00:47:55 +01:00
0f6f09180e Lib: simplified optional access to nested record attributes
Yeah, C++17, finally!

...not totally sure if we want to go that route.
However, the noise reduction in terms of code size at call site looks compelling
2020-03-14 23:52:04 +01:00
a9ed0c01db Lib: minor indentation fix
by convention, braces for member functions are only indented within a class body,
not for a stand-alone function definition (even if just inline)
2020-03-14 23:04:52 +01:00
e4db0dbfd1 Clip: draft initialisation of display delegate (see #1038)
...first steps towards a solution to switch the appearence style of clips
2020-03-14 22:02:03 +01:00
f763e90d2d DisplayEvaluation: prefer simpler solution without templates
...while the first solution looked as a nice API, abstracting away
the actual collections (and in fact helped me to sport and fix a problem
with type substitution), in the end I prefer a simpler solution.
Since we're now passing in a lambda for transform anyway, it is
completely pointless to create an abstracted iterator type, just
for the sole purpose of dereferencing an unique_ptr.

As it stands now, this is all tightly interwoven implementation code,
and the DisplayFrame is no longer intended to become an important
interface on it's own (this role has been taken by the ViewHook /
ViewHooked types).

Note: as an asside, this solution also highlights, that our
TreeExplorer framework has gradually turned into a generic
pipeline building framework, rendering the "monadic use" just
one usage scenario amongst others. And since C++20 will bring
us a language based framework for building iteration pipelines,
very similar to what we have here, we can expect to retrofit
this framework eventually. For this reason, I now start using
the simple name `lib::explore(IT)` as a synonym.
2020-03-08 02:31:49 +01:00
c7d157e295 Library: integrate generic min/max function
...built while investigating type deduction problems on PtrDerefIter
...also allow PtrDerefIter to work with std::unique_ptr
2020-03-08 02:05:39 +01:00
4070cc0d83 DisplayEvaluation: draft evaluation invocation per track
...however, running into some type deduction problems...
2020-03-08 01:11:21 +01:00
8d87029fd5 Timeline: make TrackPresenter header-only
...there is no need for yet another indirection here,
since TrackPresenter is not much of an interface and
only included at into two other translation units.
Moreover, header-only code simplifies the use of
templated lambdas, which come in handy when dealing
with the various nested sub-collections.
2020-03-07 18:21:24 +01:00
5ddf426add DisplayEvaluation: skeleton of the evaluation invocation 2020-03-07 00:30:06 +01:00
e9f05e4ac2 DisplayEvaluation: dependency wiring 2020-03-06 23:35:07 +01:00
5ad04edceb DisplayEvaluation: abandon the idea of scheduling batched resizes
- it seems such a feature is not possible to implement in a totally
   sane and safe way, since intermixed other UI messages might cause
   removal of some widgets for which we scheduled a change. And there
   is no simple and performant mechanism available to track the lifecycle
   of all the widgets involved

 - as it stands, it is actually not necessary to schedule the resizing
   for later, since the UI runs single-threaded, and thus GTK has no
   opportunity to act on them while our evaluation pass is running
2020-03-06 21:46:08 +01:00
1ea32c36a1 DisplayEvaluation: draft interfaces 2020-03-06 03:14:33 +01:00
33f299e45f Relative-Hook: observe CSS padding and margin
and voilà: now the placeholder buttons appear nicely within
the content area of each track
2020-02-29 00:24:22 +01:00
2bbbcf36bc Relative-Hook: decide on coordinate system usage
...and resolve associated problems with overal canvas size
2020-02-28 23:13:53 +01:00
99d0f0a0ae Relative-Hook: investigate and resolve wrong offset on child tracks
The reason was: each further ViewRefHook added again the full offset.
Need to change the hierarchy and allow for this chained hooking already
starting from the base interface ViewHook onward (with trivial default impl)
2020-02-28 22:11:00 +01:00
c252449388 problem with automatic scrollbar disappearing after focus loss (see #1208) 2020-02-28 01:49:35 +01:00
396bf9d1ec Relative-Hook: investigate wrong offset of attached widgets
...not fully conclusive yet.
However, the split into two canvas controls plays an important role here;
at some point we need to translate into the coordinates shifted by the height
of the first, pinned canvas (track profile "prefix").

This is an attempt to hide that away as a technical detail,
buried within the calculation of the track body height allocation.
2020-02-28 01:32:34 +01:00
1ee2f18d65 Relative-Hook: remove obsolete direct manipulation (test) code
the marked pars are diagnostics code anyway,
however, the first attempt used direct manipulation of the child offsets from "outside".
Now, after switching to the ViewHook-mechanism, such direct manipulation
of view innards is no longer neccessary, as can be verified by removing that test code now.
2020-02-27 21:42:53 +01:00
0837498cc0 Relative-Hook: proof-of-concept based on ViewHook (see #1207)
this draft commit reshifts the (meanwhile broken) test code from:
03c358fe86

Now the marker Buttons are injected again, but without any detailed
positioning code at call site. This demonstrates the viability of the
Structure-Change / ViewHook refactoring.

To make this change viable, it was necessary to remove the ViewHooked<>
marker template from the rehook() callback. As it turns out, this was
added rather for logical reasons, and is in fact not necessary in
any of the existing ViewHook implementations (and I don't expect any
other implementations to come)

BUT the actual positioning coordinates are still wrong (which seems
to re related to other conceptual problems in coordinate offset handling)
2020-02-27 21:03:46 +01:00
cf8c3c27d6 DummySessionConnection: fix structural defect in population diff
...which erroneously assumed the list of timelines to be empty.
When sending a further population diff, this assumption is broken,
since the first diff resulted in adding a timeline element.

This misatke was detected by the new consistency check added with
9f3fe8a88
2020-02-22 19:05:50 +01:00
d0cf027686 UI-Base: expunge the implicit conversion from UI-Element to BusTerm::ID
this conversion seemed to be somewhat cool,
but turned into a nuisance over time.

In the end its better to be explicit about such stuff.
2020-02-22 18:12:23 +01:00
14b6a1e6aa UI-Base: diagnostic self-ID for any "tangible" UI-Element
low hanging fruit, and quite helpful e.g. when a Diff flounders,
since it will automatically show up in the exception message.
2020-02-22 18:09:24 +01:00
b2b5cf0f6d MERGE: upgrade to Debian/Buster and to C++17 2020-02-22 02:16:25 +01:00
421a2ed49a C++17: some related clean-up 2020-02-21 23:55:09 +01:00
00c9ecb659 C++17: fix detector for function signatures
failure was likewise caused by `noexcept` being part of the signature type now
2020-02-21 20:16:59 +01:00
8c12e88fd3 C++17: fix detector for STL container iterability
the reason for the failure, as it turned out,
is that 'noexcept' is part of the function signature since C++17

And, since typically a STL container has const and non-const variants
of the begin() and end() function, the match to a member function pointer
became ambuguous, when probing with a signature without 'noexcept'

However, we deliberately want to support "any STL container like" types,
and this IMHO should include types with a possibly throwing iterator.
The rationale is, sometimes we want to expose some element *generator*
behind a container-like interface.

At this point I did an investigation if we can emulate something
in the way of a Concept -- i.e. rather than checking for the presence
of some functions on the interface, better try to cover the necessary
behaviour, like in a type class.

Unfortunately, while doable, this turns out to become quite technical;
and this highlights why the C++20 concepts are such an important addition
to the language.

So for the time being, we'll amend the existing solution
and look ahead to C++20
2020-02-21 18:57:49 +01:00
577592c66e C++17: isolate problematic code segments (see Ticket #1138)
as it turns out, "almost" the whole codebase compiles in C++17 mode.

with the exception of two metaprogramming-related problems:

 - our "duck detector" for STL containers does not trigger anymore
 - the Metafunction to dissect Function sigantures (meta::_Fun) flounders
2020-02-18 04:16:03 +01:00
38837da65e Timehandling: choose safer representation for fractional seconds (closes #939)
When drafting the time handling framework some years ago,
I foresaw the possible danger of mixing up numbers relating
to fractional seconds, with other plain numbers intended as
frame counts or as micro ticks. Thus I deliberately picked
an incompatible integer type for FSecs = boost::rational<long>

However, using long is problematic in itself, since its actual
bit length is not fixed, and especially on 32bit platforms long
is quite surprisingly defined to be the same as int.

However, meanwhile, using the new C++ features, I have blocked
pretty much any possible implicit conversion path, requiring
explicit conversions in the relevant ctor invocations. So,
after weighting in the alternatives, FSecs is now defined
as boost::rational<int64_t>.
2020-02-17 03:13:36 +01:00
8867ae55ad Clean-up: problematic function signature
GCC8 now spots and warns about such mismatches.

And we should take such warnings seriously;
code produced by the newer GCC versions tends to segfault,
especially under -O2 and above, when a return statement is
actually missing, even if the return value is actually not
used at call site.

Here, a functor to unlock the active "guard" is passed into
a macro construct, which basically allows to abstract the
various kinds of "guards", be it mutex, condition variable
or the like.

Seemingly, the intention was to deal with a failure when
unlocking -- however all the real implementations prefer
to kill the whole application without much ado.
2020-02-16 02:05:42 +01:00
e639558e2c Debian-Buster: compile Fix for GCC-8
Yeah... we are there, finally!
2020-02-16 02:05:42 +01:00
f7967a674f Structure-Change: complete refactoring of the DisplayFrame 2019-12-22 01:43:56 +01:00
e4049534fa Structure-Change: now able to turn the widgets within DisplayFrame into ViewHooked
...and implemented the base case (=Recursion) of the corresponding ViewHook(s)
2019-12-21 23:57:53 +01:00
c5d0ddb01b Structure-Change: push a set of suitable ViewHook-Interfaces into the DisplayFrame
...actual Operations not yet implemented (but trivial to implement in the end)
2019-12-20 22:15:35 +01:00
33a19c404b Structure-Change: introduce a common accessor interface
...to solve the problem with interwoven nested ctor invocation.
This interface also promises to help with nested invcations,
without being overly generic.
2019-12-20 20:06:26 +01:00
c5bffa21f4 Structure-Change: introduce new ViewHook interface into TimelineLayout
...with the goal to supersede the tricky DisplayFrame ctor closure used for this purpose
2019-12-20 00:21:31 +01:00
cef7917d8e Diff-Listener: finished and unit test pass (closes: #1206) 2019-12-15 21:40:09 +01:00
9f3fe8a885 Diff-Framework: add clean-up hook to diff-application
Our diff language requires a diff to handle the complete contents of the target.
Through this clean-up hook this is now in fact enforced.

The actual reason for adding this however was that I need to ensure
listeners are triggered
2019-12-15 15:06:04 +01:00
3e1d0036ed Diff-Listener: resolve template instantiation errors
As it turned out, the reason was a missing move-ctor.
The base of the whole DSL-Stack, TreeMutator, is defined MoveOnly,
and this is also the intended use (build an anonymous instance
through the DSL and move it into the work buffer prior to diff application)

However, C++ does *cease to define* a move ctor implicitly,
whenever /one of the "big five" is defined explicitly/.

So Detector4StructuralChanges was the culprit, it defined a dtor,
but failed to define the move ctor explicitly.


So.... well, this did cost me several hours to track down,
yet I still rather do not want to write all those ctors explicitly all the time,
and so I am still in favour of implicitly generated ctors, even if they hurt sometimes.
2019-12-15 13:54:29 +01:00
854f4eca58 Diff-Listener: investigate weird template errors
with the new decorator layer, we suddenly trigger a chain of template instantiation errors.
At first sight, they are almost undecipherable, yet after some experimentation, it becomes clear
that they relate down to the base class (TreeMutator), which is defined MoveOnly

This seems to indicate that, at some point in the call chain, we are
digressing from the move-construction scheme and switch over to copy construction,
which in the end failst (and shall fail).

Inconclusive, to be investigated further
2019-12-15 04:12:20 +01:00
d8e0ad179b TreeMutator: better invoke the Builder-ctor explicitly
...by relying on an implicit conversion,
the code does not become simpler, just shorter, and even more confusing :-/
2019-12-15 04:06:57 +01:00
d8b20ae497 Diff-Listener: fill in implementation
...basically just need to intercept three TreeMutator-operations
2019-12-15 04:04:25 +01:00
a33e236630 Diff-Listener: define API 2019-12-14 23:35:16 +01:00
806d569e06 Diff-Framework: resolve lurking problems with specific STL containers
basically the solution was a bit too naive and assumed everything is similar to a vector.
It is not, and this leads to some insidious problems with std::map, which hereby
are resolved by introducing ContainerTraits
2019-12-14 01:29:21 +01:00
3321e5bc6b Diff-Listener: need a really basic test
All of the existing "simple" tests for the »Diff Framework« are way to much low-level;
they might indeed be elementary, but not introductory and simple to grasp.
We need a very simplistic example to show off the idea of mutation by diff,
and this simple example can then be used to build further usage test cases.

My actual goal for #1206 to have such a very basic usage demonstration and then
to attach a listener to this setup, and verify it is actually triggered.

PS: the name "GenNodeBasic_test" is somewhat pathetic, this test covers a lot
of ground and is anything but "basic". GenNode in fact became a widely used
fundamental data structure within Lumiera, and -- admittedly -- the existing
implementation might be somewhat simplistic, while the whole concept as such
is demanding, and we should accept that as the state of affairs
2019-12-12 23:41:26 +01:00
f6a4ee3f89 Library: no need to log lifecycle of the advice system on each invocation
Basically the advice system is just some further helper component with
a lookup table, which "just works" transparently most of the time.

We'd need those diagnostic messages only when explicitly debugging
for some kind of access-after death, which should not happen as long
as we stick to the general policy not to allow any significant functionality
to be hooked up from dtors
2019-12-12 23:17:43 +01:00
c86f914915 Structure-Change: re-order entity naming
ViewHookable -> ViewHook
ViewHook -> ViewHooked
2019-12-12 17:02:24 +01:00
c501a38590 Structure-Change: fix test after refactoring / add lifecycle warning
now the lifecycle of widget and hook are tightly interwoven.
Indeed the test uncovered a situation where a call into the
already destroyed Canvas might halt the application.
2019-12-09 01:24:51 +01:00
0a20d18242 Structure-Change: implement the changed API and memory layout
NOTE: 2 test failures
2019-12-08 23:57:43 +01:00
ffcac2ea1e Structure-Change: implement a simplistic implementation of re-ordering
...verified by the rather conceptual unit test
2019-12-06 23:19:09 +01:00
305ff8e6cc Structure-Change: draft API for re-ordering attached widgets
basically this attempts to work around an "impedance mismatch" caused by relying on Lumiera's Diff framework.
Applying a diff might alter the structural order of components, without those componets
being aware of the change. If especially those components are attached into some
UI layout, or otherwise delegate to display widgets, we need a dedicated mechanism
to reestablish those display elements in proper order after applying the change.

The typical examples is a sequence of sub-Tracks, which might have been reordert due
to applying rules down in the Steam Layer. The resulting diff will propagate the
new order of sub-Tracks up into the UI, yet now all of the elaborate layout and
space allocation done in the presentation code needs to be adjusted or even
recomputed to accomodate the change.
2019-12-06 21:53:43 +01:00
c573630ac1 Structure-Change: draft a design based on ViewHook / ViewHookable
By applying a Diff, the children of some timeline element (track) may be re-ordered.
This imposes specific problems, since these elements hold onto slave-Widgets,
which are already attached into some elaborated and nested widget structure.
To keep complexity under control, we can not allow the TrackPresenter to have
any knowledge regarding the implementation structure of these target widgets.

Thus I am pondering the idea to represent that relation as an abstracted ViewHook link
2019-12-02 00:34:20 +01:00
bdf3351f55 ClipDisplay: basic implementation of ViewHook helper 2019-11-08 20:49:37 +01:00
bf283e8843 QA: check for possible misalignment through placement new (-> #1204) 2019-11-08 01:14:36 +01:00
f9d8f6eb55 ClipDisplay: draft desired properties of the ViewHook helper
...which serves to solve the problem with Canvas access.
Basically we do not want each and every Clip widget to be aware of the concrete canvas implementation widget;
and in addition, automated removal of widgets from the Canvas seems desirable
2019-09-30 02:49:02 +02:00
7c7b910545 ClipDisplay: plot a structure for connecting ClipWidgets with the display canvas 2019-09-29 01:32:34 +02:00
03c358fe86 Timeline: squeeze in some test/diagnostics code to inject a button onto each track
This is dummy/test/diagnostics code and should be removed when the track display code is complete!
It can be activated by sending a "mark"-Message via the UI-Bus, towards the
Timeline element to be tested (Tip: use the same ID as used when injecting
the Timeline via the TestControl Dialog box). When receiving this message
(asynchronously), the TimelineControler asks each nested TrackPresnter
to inject a Button with the corresponding track name onto the BodyCanvasWidget.

This allows us to verify the coordinate calculation and size allocation --
and indeed, the numbers are not yet correct (TODO)
2019-09-07 19:24:54 +02:00
cae013c4f4 Timeline: store current track start coordinates while calculating allocation
admittedly this is a bit sketchy, but I don't have a better framework to hinge upon right now.
Thus we store the vertical start coordinates and the offset of the content area
as a side effect, while calculating the TrackProfile
2019-09-07 17:31:58 +02:00
4785ff8caa Timeline: integrate support for a margin on the timeline content
...which has the nice additional effect of exposing box-shadow on the outside of the content area too.
Thus the content area now behaves equivalent to the rulers, and adjacent
content space of simple tracks without rulers and nesting can be slightly
offset from each other through a margin in CSS
2019-09-07 17:31:53 +02:00
fa4a9014a1 Timeline: nail the problem with calculating overall vertical space
In the end, I used the profile building pass to also calculate and sum up the vertical offsets.
Seems to be the only sane approach to get really precise values, since adjacent
upwards slopes can be combined at various places (and I do not want to use the
actual drawing code for this calculation)
2019-08-29 23:02:44 +02:00
4d2766963b Timeline: size allocation is not yet correct...
need to investigate and probably need to store per track offset values
already while building the track profile. The primary reason for the
observed discrepancy seems to be the rather flexible combination of
slope borders.
2019-08-29 16:19:47 +02:00
360209a381 Timeline: verify visible track structure (and fix a bug with header placement) 2019-08-29 16:19:40 +02:00
737505979b Timeline: also observe additional space for decorations added via CSS 2019-08-23 03:56:38 +02:00
346b5ae769 Timeline: now settle the drawing code with the insights gained thus far
Especially note the tricks we need to play in order to allow for (limited) usage of CSS3 box-shadows.
The reason is, all these CSS3 effects are rendered in one shot and combinend on the StyleContext::render_background() call
Thus we need to ensure that the background is properly aligned with the frames
2019-08-23 03:04:22 +02:00
fc5eaf857c Timeline: find a workaround to cause the Box to reflow the rulerCanvas
seemingly, the Box with PACK_SHRINK allocates a zero height to the rulerCanvas initally,
which is correct at that point, since the widgets are not yet realised.
However, when we later set_size() on the rulerCanvas, the enclosing Box should reflow.
It does indeed if the child widget is a button or something similar, however,
somehow this reflowing does not work when we set_size on the canvas.

A workaround is to place a new set_size_request().

TODO: do this more precisely, and only on the rulerCanvas. To the contrary,
the mainCanvas is placed into a scolling-pane and thus does not need a size-Request.
Moreover, the latter automatically communicates with the hadjustment() / vadjustment() of
the enclosing scrollbars.
2019-08-22 17:34:32 +02:00
2390385dc5 Timeline: implement function to set the drawing canvas size
as can be verified with the debugger, it sets the correct sizes now.
And it is called only once (unless the content size actually changes).

TODO: however, the visible display of the GTK widgets is not adjusted
2019-08-21 19:13:55 +02:00
8c0b3258cb Timeline: investigate details of CSS box-shadow and dawing strategy
- decide upon the actual drawing strategy
- document our approach chosen thus far
- add a new function to fill in the overall canvas size (TODO)
2019-08-21 17:48:25 +02:00
81253cb152 Timeline: some analysis and planning regarding space allocation 2019-08-08 19:08:04 +02:00
7bf7c51375 Investigation: inconclusive further research (context_save/restore)
Indeed I had missed to connect the new "free standing" StyleContext to
some Gdk::Screen, typically the default screen (connected to the current
top level window). But seemingly this was not really necessary, since,
somehow magically, the style context must have connected itself to some
screen, otherwise it wouldn't be able to access the CSS cascade.

Anyhow, fixing this omission does not resolve our problem.
Nor does any combination of re-connecting, invalidating etc.

I poked around in the GTK (C) code a lot, but could not spot any obvious
missing initialisation step. To much magic around here. Without massive
debugging into GTK internals, I don't see any way to further this
investigation. And, moreover there is a viable workaround
(namely to set and remove the classes explicitly, which works as intended)

I posted a question on Stackoverflow and for now
I'll file this topic as "inconclusive"
https://stackoverflow.com/q/57342478
2019-08-08 19:08:04 +02:00
e5371f66b8 UI-Style: reorganise style constants and introduce some BEM notation
Note however, we will not plaster our UI code and CSS with mangled-out selectors
on each and every single element. This is what cascading was meant to be used for.
2019-08-08 19:08:04 +02:00
8824be440a Investigation: integrate findings thus far into our timeline drawing code
DONE
 - can now control the border size through a set of modifier classes

OPEN
 - but context_save()/restore() does not work; seem to loose all styling
 - not clear how to deal with CSS3 effects like box-shadow
2019-08-03 16:41:46 +02:00
06aa5c4c8c Investigation: get the border resizing to work
...as it turns out, a problem with Cascading prevented the additional classes to become effective
2019-08-03 15:45:36 +02:00
e6e68e2e68 Timeline: investigate options to build a suitable ramp style
...somehow does not yet work as intended...

- unable to control the border-width from code
- Gtk::StyleContext::add_class(name) does not seem to have any effect
2019-07-30 19:20:58 +02:00
b5c2009933 Timeline: first attempt at drawing ramps and borders
...does not work out as expected
 - frames are painted solid, not inset/outset
 - unable to manipulate the border width from code
2019-07-20 17:39:49 +02:00
b2c2787ddc Timeline: populate additional Style-Advice for nested ruler tracks 2019-07-20 01:24:17 +02:00
e3cde9b78d 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
2019-07-20 01:24:17 +02:00
3102de9d8a Timeline: inject sub-track into the header pane structure 2019-07-20 01:24:17 +02:00
eca09e3ab5 Timeline: work out how Ruler tracks can be managed 2019-07-20 01:24:17 +02:00
d1e2ddc56e Timeline: refactor common drawing code into an abstract baseclass 2019-07-15 00:25:08 +02:00
713178aecd Timeline: better save the number of pinned elements as dedicated field
...within the Profile object, instead of sneaking this info into the prelude verb
2019-07-15 00:06:59 +02:00
ec50407167 Timeline: start implementing some bits of the drawing code
Use a "catchy" style definition with lime background to make the drawing visible
2019-07-14 17:53:21 +02:00
bc4f7604a2 Timeline: draft a scheme to use custom class names within CSS selectors
We can add our custom classes to custom widgets, and we can set the
widget name, which can be used as #id selector from CSS

Unfortunately we can not set the main CSS node name for CustomWidgets defined through GTKmm (C++)
The latter is only possible when deriving the custom widget in plain-C, which is quite tedious.
On a second thought, this limitation is not so severe as it might seem, because
most of the time you actually do *not* want to change the CSS node name,
because you want to match against existing rules in the theme (e.g. box, or paned)

The actual case here would have been an exception to this rule, since here
it would be nice to anchor the whole custom timeline drawing in an "body.timeline" element


NOTE: Current state for the selector path is now:

window.background box.vertical box[2/3].horizontal widget[2/2] widget paned.vertical widget box.vertical notebook[1/1].frame paned.horizontal.timeline-page box.vertical.timeline.timeline-body fork.timeline
2019-07-13 21:04:33 +02:00
826df93955 Timeline: publish virtual CSS path and style context via Advice system
...and perform the initialisation once, when attaching the first timeline to the UI
Now our code produces the following Gtk::WidgetPath (note the last node, which our code added)

window:backdrop:dir-ltr.background box:backdrop:dir-ltr.vertical box:backdrop:dir-ltr[2/3].horizontal widget:backdrop:dir-ltr[2/2] widget:backdrop:dir-ltr paned:backdrop:dir-ltr.vertical widget:backdrop:dir-ltr box:backdrop:dir-ltr.vertical notebook:backdrop:dir-ltr[1/1].frame paned:backdrop:dir-ltr.horizontal box:backdrop:dir-ltr.vertical fork.timeline
2019-07-13 18:04:02 +02:00
6b4bf0a6ea Library: allow to check if Advice was explicitly given
For context: The »Advice System« was coined a long time ago, in 2010,
based on the vague impression that it might be useful for that kind of application
we are about to build here. And, as can be expected, none of the usage situations
envisioned at that time was brought to bear. Non the less, the facility came in
handy at times, precisely because it is cross-cutting and allows to pass
information without imposing any systematic relationship between the
communication partners.

And now we've got again such a situation.
The global style manager in the UI has to build a virtual CSS path,
which is needed by drawing code somewhere deep down, and we absolutely
do not want to pass a reference to the style manager over 20 recursive calls.

The alternatives would be
 (1) to turn the style manager into a public service
 (2) to have a static access function somewhere
 (3) to use a global variable.
For rationale, (1) would be overblown, because we do not actually request
a service to do work for us, rather we need some global piece of information.
(2) would be equivalent to (1), just more confusing. And (3) is basically
what the Advice system does, with the added benefit of a clear-cut service
access point and a well defined lifecycle.

This changeset adds the ability to check if actual Advice has been published,
which allows us to invoke the (possibly expensive) GTK path building and
style context building code only once.
2019-07-13 17:00:23 +02:00
dde3778cad UiStyle: fix naming 2019-07-13 14:34:55 +02:00
d5cbeab2d8 Timeline: GTK-Code to construct a "virtal" CSS path (see #1168)
This code was cooked up by following the example of gtk_widget_path_append_for_widget()
See gtkwidget.c, 16413
2019-07-13 00:59:05 +02:00
60d28fea2c Timeline: establish a way to pass a StyleContext via Advice system
- at some (yet to be defined) location, a virtual WidgetPath is constructed
  and used to build a Gtk::StyleContext in accordance to the curren CSS

- within the drawing routine, we use Lumiera's Advice-System to access this info
2019-07-12 23:58:25 +02:00
8ffab2f002 Dependencies: get rid of boost-regexp (see #995)
Mostly, std::regexp can be used as a drop-in replacement.

Note: unfortunately ECMA regexps do not support lookbehind assertions.
This lookbehind is necesary here because we want to allow parsing values
from strings with additional content, which means we need explicitly to
exclude mismatches due to invalid syntax.

We can work around that issue like "either line start, or *not* one of these characters.


Alternatively we could consider to make the match more rigid,
i.e we would require the string to conain *only* the timecode spec to be parsed.
2019-06-24 02:41:02 +02:00
ab90d9c71d Functions-Commands: discard the ability to compare functors for equivalence (closes #294)
evil hack R.I.P
2019-06-23 19:45:30 +02:00
94edb5de86 BufferMetadata: likewise abandon use of function comparison for buffer handlers
The existing implementation created a Buffer-Type based on various traits,
including the constructor and destructor functions for the buffer content.
However, this necessitates calculating the hash_value of a std::function,
which (see #294) is generally not possible to implement.

So with this changeset we now store an additional identity hash value
right into the TypeHandler, based on the target type placed into the buffer
2019-06-23 18:57:21 +02:00
d57770ca89 Commands: disable equivalence-test on command equality
This was prompted by a test failing under Boost-1.65 (--> see #294)
When reviewed now, the whole idea of testing Steam-Layer Commands for
equivalence feels a bit sketchy.

Just the comparison for the command ''identity'' alone seems sufficient,
i.e. the test if a command-ID is associated with the same backend-handle
and thus the same functor binding.
2019-06-23 17:35:21 +02:00
aad71a496a Boost-1.65: fix another integer ambiguity problem with boost::rational
<rant>
the "improved" boost::rational can no longer compute 1/x
quite brilliant
</rant>

well... the reason is again signed vs unsigned int.
FrameRate is based on unsigned int (since a negative frame rate makes no sense).
2019-06-22 21:43:33 +02:00
dc301231cf Boost-1.65: resolve ambiguity in timevalue comparison
seemingly, the newer boost libraries added an internal type rational<I>::bool_type
together with an overload for the equality comparison operator.

Unfortunately this now renders a comparison ambiguous with the constant zero (i.e. int{0})
because in our use case we employ rational<uint>.

Workaround is to compare explicitly to a zero of the underlying integer type.
2019-06-22 19:15:19 +02:00
06163f6016 Timeline: filter to select the pinned prefix part of the profile
...when rendering this part, which shall be always visible.
And the rest of the profile needs to be rendered into a second canvas,
which is placed within a pane with scrollbar.

Implemented as a statefull iterator filter
2019-06-21 23:18:44 +02:00
ac3f1d8bef Timeline: implement access mechanism through getter lambda
works, but not really convinced yet...
2019-06-21 20:00:44 +02:00
6b6ed5e0eb Timeline: need accessor function for profile
TODO / WIP.
We can no longer just grab the profile by reference;
rather we need a sensible way how to activate the recomputation logic
2019-06-20 19:01:15 +02:00
77805a5c8c Timeline: handle notification of structural updates 2019-06-20 18:53:12 +02:00
83c462abc3 Timeline: investigate how to handle profile rebuilding
as it turns out, the core problem is that we need a way to detect and signal
structural changes to the logical UI model
2019-06-20 15:36:09 +02:00
d5af020520 Timeline: possible solution for construction of the TrackProfile
...not yet really convinced though
...how does this relate to the "display evaluation pass" of the Layout Manager?
2019-06-15 21:45:38 +02:00
c87ca5d632 Timeline: generalise unsafe access to embedded profile data
While somewhat ugly, I deem this acceptable in such a context,
where the implementation handles its own embedded storage structure.
2019-06-15 17:41:17 +02:00
371b7a487e Timeline: better parametrisation of timeline renderers
and yes, we indeed need the PixSpan: it defines the *horizontal* extension of what needs drawing...
2019-06-15 16:04:18 +02:00
a105e02b52 Timeline: wire distinct grounding/overlay renderers
TODO:
 - actual draw operations not yet implemented
 - find a way how to select the prelude / body part of the track profile

This is a consequence of subsuming the timeline ruler under the concept of an overview track
2019-06-13 18:17:46 +02:00
3f04bb8698 Timeline: sort out how to link the ProfileInterpreter into the draw function 2019-06-13 17:54:06 +02:00
223113ee44 Timeline: switch TrackProfile to hold a sequence of VerbPack entries
turns out to be mostly a drop-in replacement.
2019-06-12 03:29:00 +02:00
1a8917e60a Timeline: after a long break... reconsider how to integrate the new VerbPack
...into the draft skeleton of timeline drawing
2019-06-11 02:40:20 +02:00
f6e5886348 Library: complete test coverage of VerbPack 2019-06-11 02:40:20 +02:00
3d5a67ed14 Library: finish and clean-up the solution for VerbPack dispatch 2019-06-10 16:08:50 +02:00
8f43c2591e Library: investigate malfunction in metaprogramming
the template lib::PolymorphicValue seemingly picked the wrong
implementation strategy for "virtual copy support": In fact it is possible
to use the optimal strategy here, since our interface inherits from CloneSupport,
yet the metaprogramming logic picked the mix-in-adapter (which requires one additional "slot"
of storage plus a dynamic_cast at runtime).

The reason for this malfunction was the fact that we used META_DETECT_FUNCTION
to detect the presence of a clone-support-function. This is not correct, since
it can only detect a function in the *same* class, not an inherited function.

Thus, switching to META_DETECT_FUNCTION_NAME solves this problem
Well, this solution has some downsides, but since I intend to rewrite the
whole virtual copy support (#1197) anyway, I'll deem this acceptable for now


TODO / WIP: still some diagnostics code to clean up, plus a better solution for the EmptyBase
2019-05-10 02:19:01 +02:00
23c9da7c62 Library: solve the dilemma by inheriting from VerbToken
...which, in the end, can even be considered the more logical design choice,
since the "verb visitor" is a more elaborated and sophisiticated Verb-Token,
adding the special twist of embedded storage for variable function arguments
2019-05-09 23:40:47 +02:00
a530665769 Library: fix some reference passing errors
...but bad news on the main issue:
the workaround consumes the tuple and thus is not tenable!

And what is even worse: the textbook implementation of std::apply is
equivalent to our workaround and also consumes the argument tuple
2019-04-22 16:54:22 +02:00
e28635a11a Library: investigate copy behaviour in forwarding calls 2019-04-21 03:52:34 +02:00
5191073558 Library: continue Investigation with workaround, inconclusive yet
A simple yet weird workaround (and basically equivalent to our helper function)
is to wrap the argument tuple itself into std::forward<Args> -- which has the
effect of exposing RValue references to the forwarding function, thus silencing
the compiler.

I am not happy with this result, since it contradicts the notion of perfect forwarding.

As an asside, the ressearch has sorted out some secondary suspicions..
- it is *not* the Varargs argument pack as such
- it is *not* the VerbToken type as such

The problem clearly is related to exposing tuple elements to a forwarding function.
2019-04-20 17:27:47 +02:00
6fbd1021ba Library: first attempt to get the flexible VerbToken to work
...still not decided yet if this whole apporach is sound...
2019-04-17 18:32:21 +02:00
9b5fdd39b8 Library: draft for a visitor-like VerbToken
this is a generalisation of what we use in the diff framework;
typically you'd package the VerbToken into some kind of container,
together with the concrete invocation argument.

However, the specific twist here is that we want *variable arguments*,
depending on the actual operation called on the interpreter interface.
2019-04-16 18:21:51 +02:00
500af8aa34 Library: allow for subclassing PolymorphicValue
Up to now, PolymorphicValue was always used as-is, packaged into a typedef.
Now we consider using it as building block within an adapter for visitor-like tokens.

Which requires to pass-down the ctor call directly from the subclass, at least if we
want to emplace the resulting entity directly into a stdlib container.

As an asside, PolymorphicValue also used explicit specialisations for N-arguments,
which meanwhile can be replaced by variadic templates
2019-04-16 18:15:24 +02:00
ec9b2388da Timeline: consider how to integrate the drawing code
...which leads to a specific twist here; while in the simple version
we still could hope to get away with a simple uniform uint argument,
the situation has changed altogether now. The canvas has turned into
some generic component, since it is instantiated two times, onece for
the time ruler and once for the actual body content. Thus all of the
specifics of the drawing code need to be pushed into a new, dedicated
renderer component. And this more or less forces us to pass all the
actual presentation variations through the invocation arguments of
the visitor.

So we're now off again for a digression, we need a more generalised visitor
2019-04-14 15:38:57 +02:00
7ee0baa241 Timeline: reorganise widget structure within body pane to accommodate time ruler
After thinking the whole concept over several times, it occurred to me that
a separate implementation of a time ruler would be quite redundant with the
envisioned feature of per-track overview rulers. Following this line of thought,
the time ruler would just be some specifically configured overview ruler.

This has the somewhat unfortunate consequence, that it becomes the responsibility
of the body canvas to render the overview ruler, thereby somehow delegating
to a common renderer implementation. Which makes the whole setup of the body canvas
way more complex, because now we get *two* canvas like painting areas, one
always visible at top, and the second one, the content area, fully scrollable
within the lower part.
2019-04-13 17:55:28 +02:00
bd13df2308 Timeline: establish wiring with the timeline DisplayManager 2019-04-12 02:00:19 +02:00
9292da84f2 Timeline: generate the symbolic track profile description
...by recursive walk over the track structure
2019-04-11 17:31:09 +02:00
abdac7aab6 Timeline: setup the framework for building and rendering a track profile 2019-04-10 02:42:08 +02:00
972ec9851b Timeline: perform track profile with given interpreter object 2019-04-10 01:58:11 +02:00
e85f218045 Timeline: define representation of the profile verb tokens 2019-04-06 19:34:31 +02:00
df02258547 Timeline: use a sequence of structure description verbs
...like
 * ruler
 * gap
 * content
 * open/close sub scope
...
2019-04-06 18:21:26 +02:00
b005df1697 Timeline: pick up work on the track drawing logic
...there was a long intermission, first caused by some contribution to Yoshimi,
then by a private project related to Kubernetes
2019-04-05 23:37:56 +02:00
1cf2e459c6 Timeline: consider to turn RulerTrack into a part of the systematic UI model
...meaing
 - it can be diff mutated
 - it is attached to the UI-Bus
 - it has persistent presentation state
2018-12-15 06:05:18 +01:00
1452f1f022 Timeline: plan how to organise time ruler and overview ruler
...the idea is to subsume them within a generic ruler concept
2018-12-15 03:32:57 +01:00
ad9043ae1d Timeline: add the typical framework for custom drawing on the canvas
see gtk-canvas-experiment.cpp
2018-12-10 00:12:53 +01:00
615796d812 Timeline: set an initial size for the canvas 2018-12-10 00:12:53 +01:00
116600b20a Timeline: draft a concept to attack the custom layout
the core question is: how to translate time into pixel coordinates
2018-12-10 00:12:52 +01:00
7b7ec310b3 Dispatcher: rename in accordance to the layer
so now we've got a "SteamDispatcher" ... cute ;-)
2018-12-10 00:12:52 +01:00
2ea89fcb54 Dispatcher: rework loop control logic
- we got occasional hangups when waiting for disabled state
- the builder was not triggered properly, sometimes redundant, sometimes without timeout

As it turned out, the loop control logic is more like a state machine,
and the state variables need to be separated from the external influenced variables.

As a consequence, the inChange_ variable was not calculated properly when disabled in a race,
and then the loop went into infinite wait state, without propagating this to
the externally waiting client, which caused the deadlock
2018-12-10 00:12:52 +01:00
48a829d544 Library: clarify usage of the basic time scale
effectively we rely in the micro tick timescale promoted by libGAVL,
but it seems indicated to introduce our own constant definition.
And also clarify some comments and tests.

(this changeset does not change any values or functionality)
2018-12-10 00:12:52 +01:00
b68d0f24cb Library: settle long standing confusion regarding time border conditions
basically we can pick just any convention here, and so we should pick the convention in a way
that makes most sense informally, for a *human reader*. But what we previously did, was to pick
the condition such as to make it simple in some situations for the programmer....

With the predictable result: even with the disappointingly small number of usages we have up to now,
we got that condition backwards several times.

OK, so from now on!!!

Time::NEVER == Time::MAX, because "never" is as far as possible into the future
2018-12-10 00:12:43 +01:00
a49d79ffbd Library: fix spurious wake-up from (non)timed wait
A classical carry-over of dirty values...
Problem arises, when starting an unconditional wait on the same object monitor,
which previously conducted a timed wait. Then the obsolete timeout from the previous
wait remained in place, causing our Sync-Wrapper (erroneously) to assume a timed wait
and then pthread to return immediately from this timed wait.

The result was permanent idle looping in the ProcDispatcher, after the first command was processed
2018-12-10 00:09:56 +01:00
bc1cf3a0b5 Library: sharpen detection of possible string conversion
When invoking the util::toString conversion, we indeed to want any conversion,
including explicit conversion operators. However, probing the possibility to build a string
can be dangerous, since there is a string constructor from characters, and
integral types can be converted to characters.

OTOH, leaving out explicit conversions is likewise not desirable, since there are
class types, which deliberately do not offer an implicit conversion, but allow
explicit conversion for dump and diagnostic output. The notorious example for
such a situation is the lib::idi::EntryID<TY>. We certainly do not want an
EntryID to be converted into a string without further notice, but we do want
an EntryID to be automatically rendered to string in diagnostic output, since
this will include the human readable ID part.

See especially: 8432420726

Now we'll attempt to get out of this dilemma by probing explicitly for the presence
of a string conversion operator, which will fail for any non-class types, thereby
ruling out all those nasty indirect type -> character -> string conversion paths.

The rationale is: if someone queries the predicate can_convertToString, the intention
is really to get an string rendering, and not just to invoke some random function
with an string argument.
2018-12-10 00:09:56 +01:00
d3d7ea35ad Global-Layer-Renaming: fix remaining textual usages and IDs in the code
- most notably the NOBUG logging flags have been renamed now
 - but for the configuration, I'll stick to "GUI" for now,
   since "Stage" would be bewildering for an occasional user
 - in a similar vein, most documentation continues to refer to the GUI
2018-12-10 00:09:56 +01:00
8d6cb19e3f Global-Layer-Renaming: fix handling of GuiResources in the build
the new structure causes them now to be installed into $TARGET/stage
which is simply not what I want. I still consider $TARGET/gui the better choice,
since an administrator or packager is not aware of our layer namings.

The existing solution was half baked anyway, it did not really replicate the source tree.
On the other hand, I want to retain the location of the CSS files within the GUI tree,
since I consider it a good practice, to keep "code-like" resources with the actual code,
and not far away in some arcane "data" directory.

No I've noticed, that the env.GuiResource() function is only used once, for this very task.
So, for the time being, we can keep it simple and deditaced to that task, i.e
we pick up all CSS files we find and install it into a single target directory.

NOTE: this issue has brought to my attention two further, completely unrelated issues

 * Ticket #1192 (Lumiera hangs on failed GUI start)
 * The ProcDispatcher does an idle wait, due to an error in timed-wait implementation
2018-11-16 18:18:33 +01:00
480104b945 Global-Layer-Renaming: adapt the build system to the new layer names
...with one exception: I'll retain the name "gui" for the final product to be built.
2018-11-16 15:25:28 +01:00
02c5809707 Global-Layer-Renaming: adjust namespace qualification 2018-11-15 23:59:23 +01:00
555ca0bff9 Global-Layer-Renaming: rename namespaces 2018-11-15 23:55:13 +01:00
72b15b8e45 Global-Layer-Renaming: transform header include guards
btw... we could change to #pragma once
2018-11-15 23:52:02 +01:00
2d5ebcd5fa Global-Layer-Renaming: adjust header includes 2018-11-15 23:42:43 +01:00
6261779531 Global-Layer-Renaming: rearrange directories
backend -> vault
proc -> steam
gui -> stage
2018-11-15 23:28:03 +01:00
9e951e1eeb Global-Layer-Renaming: adapt lots of documentation 2018-11-15 21:13:52 +01:00
866d7efe0a Timeline: push the trackname attribute down into the widget/display
...in accordance to our general design guideline: we don't duplicate
actual model values within the controllers/presenters, since our widgets
act themselves as view-model
2018-11-10 03:02:24 +01:00
c8dc5a24a8 DummySessionConnection: extend population diff to send distinct root-track
This change demonstrates how to deal properly with possible duplicate entities
with similar symbolic ID: define a RandomID (to guarantee a distinct hash on each instance).
In the actual implementation, this should happen already within the domain model,
not when constructing the diff (obviously of course...)

This change also adds a mutation sequence to inject the actual track name
2018-11-10 02:39:17 +01:00
a4c37ed99c Library: allow for an explicitly random EntryID
same pattern as the existing EntryID, i.e. a human readable symbol plus a hash
but the hash is just random, instead of deriving it from the symbol text.

Use case is when we explicitly need a distinct identity, even when the
human readable symbolic name is the same. Actual example: the fork root in the timeline
2018-11-10 01:01:59 +01:00
8432420726 Library: fix unwanted implicit conversion
...it should have been explicit from start, since there is no point
in converting an EntryID into a plain flat string without further notice

this became evident, when the compiler picked the string overload on

MakeRec().genNode(specialID)

...which is in compliance to the rules, since string is a direct match,
while BareEntryID would be an (slicing) upcast. However, obviously we
want the BareEntryID here, and not an implicit string conversion,
thereby discarding the special hash value hidden within the ID
2018-11-09 23:09:28 +01:00
7cc68fadea GenNode / Timeline: allow to mutate attribute objects with explicitly given ID
so this seems to be the better approach for dealing with this insidious problem.
In some cases -- as here most prominently with the root track within the timeline --
we have to care within the domain model to prepare unique ids even for sub objects
treated as attributes. In the actual case, without that special attention,
all timelines would hold onto an attribute "fork" with the same ID, based
on the type of the nested object plus the string "fork". Thus all root track
representations in the GUI would end up listening to the same ID on the UI-Bus...
2018-11-09 22:55:08 +01:00
1bbe903202 GenNode: revert -- better not handle this problem on ETD level
...rather extend the "object builder" DSL notation to allow passing in a given EntryID literally.
Rationale is, we should handle the problem of unique IDs on the level of the domain model.
If we attempt to "fix" this within GenNode, the price would be to make the ETD creation stateful
2018-11-09 22:50:48 +01:00
83394a6f01 GenNode: investigate Problem with non-unique attribute IDs
this is not a problem, strictly sepaking, locally.
But it becomes a problem once the GUI uses those attribute IDs
as Element-IDs for tangible UI entities, which need to be uniquely
addressable via the UI-Bus.

An obvious solution is to inject randomness into the Attribute ID hash
2018-11-09 20:19:45 +01:00
20451c958a Timeline: add preliminary track-head display
just some labels, so that we can see the added content
TODO: unsolved problem: how to pass the track name
2018-11-06 01:01:00 +01:00
8ab6c54b9d DummySessionConnection: switch the dummy-ID on each use
...otherwise we'll get several seemingly identical Timeline tabs in the UI,
since this fake function just sends an INS for each newly injected Timeline,
and there is no deduplication in the UI (we assume that in a real session
and timeline-IDs will be unique)
2018-11-05 04:56:01 +01:00
320539344b Timeline: make the injected timeline basically visible 2018-11-01 21:35:09 +01:00
13286f4b90 ElementBox: define the desired properties of this fundamental building block (#1185) 2018-11-01 20:37:36 +01:00
04b665afd1 Timeline: concept for the TrackBody helpers
these recursively nested helper entities work together with the TimelineCanvas
and enable the latter to draw the track background in the Timeline Widget and
to find out about the vertical coordinates where to place content (Clip, Effects, Markers)
2018-10-31 03:52:24 +01:00
0aa4a8cb42 Timeline: make the Patchbay a Viewport container, to follow body scrolling
Gtk::Viewport allows to add the ability to scroll a partial view window
for a container larger than the available display area. The position
and movement of this window is controlled by Gtk::Adjustments,
which can be located elsewhere.

Here we use the existing Adjustments of the ScrolledWindow
holding the body canvas; this setup makes the header pane follow
the scroll movements of the body
2018-10-30 03:37:55 +01:00
8803af1a0a Timeline: further steps towards attaching the widget structure 2018-10-28 18:56:04 +01:00
3dd3fc7810 Timeline: decide upon the organisation of the header pane
we'll uses a recursive structure here, based on nested grids
2018-10-28 01:56:24 +02:00
c212ce94ca Timeline: setup basic widget structure 2018-10-28 01:30:02 +02:00
2d4e58db02 Timeline: consider how to manage size and layout of timeline contents
bottom line is to do most autmatically, and to establish a slave-relation
navigation-area -> timeline-ruler
header-pane-content -> corresponding track-body

this can be accomplished mostly by connecting the aproprieate signals,
thus these widgets will live within the Layout-Manager, which consequently
is renamed into TimelineLayout
2018-10-27 17:27:29 +02:00
c3d91d4ed3 Timeline: draft for building the nested recursive display structure
the solution idea is to use a helper frame, and an "anchor functor",
which is passed down from the respective parent context, and which
does the actual work of injecting the child widgets at the apropriate
position within the parent display.
2018-10-27 01:52:46 +02:00
572bd38fec DummySessionConnection: produce a simple population diff message
seems to work surprisingly well...
the diff application poceeds in the GUI up to the point
where the TrackPresenter need to be inserted into a two-fold display context
2018-10-15 02:54:42 +02:00
de5f0b85d4 DummySessionConnection: new tab in the TestControl dialog box
...to trigger the new fake-functionality
2018-10-14 23:59:35 +02:00
77902d54a6 DummySessionConnection: prepare schaffolding for fake-commands (see #1042)
To drive the timeline display in the UI ahead, the plan is to have
a faked action, which injects dummy population diff messages into the GUI,
resulting in the build-up of a typical simple session timeline
2018-10-14 17:24:13 +02:00
67cccbdc5d Timeline: actually accept and install the TimelineWidget
As starting point, provide an empty placeholder widget to fill the void
2018-10-14 03:48:39 +02:00
6e18452c37 Timeline: arrange for a tabbed notebook to hold the timeline widgets
...and remove all the leftover test and research code from 2016
which was archived to /research some days ago
in 3f87ef43ec
2018-10-13 21:56:36 +02:00
202b1e4dbd Timeline: implement handling of INS verb to create new Timeline
decision: for now we will represent *every* Timeline present in the Session.
Later it would also possible to skip some representation; however we'd need
a way to store such presentation state such that we'd be able to get at this
persisted stat right at this point here, when processing the Diff.
2018-10-13 03:47:31 +02:00
bfca473dce Timeline: decide upon the diff format expected for creating a timeline
other than the regular way of building an object,
we do expect a minimal structure to be sent right within the INS message.

Rationale: the standard way would allow for too much leeway and created
unwanted intermediary states. The non-standard way decided upon here
is well within the limits of our diff language
2018-10-13 02:46:09 +02:00
edf577187b Timeline: now able to define delegating diff mutation binding 2018-10-13 00:25:51 +02:00
a77ecb6d5d change util::sanitise to filter out '
Only reatain chars, numbers and -_.+$()@
Allowing the appostroph seems entirely random and unjustified here
2018-10-12 23:45:49 +02:00
d2309f003d fix an off-by one, spotted by chance 2018-10-12 23:43:36 +02:00
fa6ba76f85 investigate insidious ill-guided conversion
As it turns out, using the functional-notation form conversion
with *parentheses* will fall back on a C-style (wild, re-interpret) cast
when the target type is *not* a class. As in the case in question here, where
it is a const& to a class. To the contrary, using *curly braces* will always
attempt to go through a constructor, and thus fail as expected, when there is
no conversion path available.

I wasn't aware of that pitfall. I noticed it since the recently introduced
class TimelineGui lacked a conversion operator to BareEntryID const& and just
happily used the TimelineGui object itself and did a reinterpret_cast into BareEntryID
2018-10-12 23:42:56 +02:00
e81b0592d3 TreeMutator: combine no-op layer with selective other diff binding
...and complete unit test coverage.
This is complex stuff and we'd better be careful it actually works
2018-10-12 02:05:11 +02:00
0d5f29446b TreeMutator: provide no-op implementation
how to further your career with eight simple steps
2018-10-12 01:07:13 +02:00
fb93e349da TreeMutator: conjure up a black hole mutator
...which is a somewhat involved version of /dev/null
2018-10-11 23:56:33 +02:00
82321a7594 Timeline: draft solution how to delegate to the actual TimelineWidget
Problem is, the InteractionDirector, being the representation of the model root,
needs to manage and maintain the collection of "timelines". However, these
can not be widgets, rather, they need to attach to widgets living within
the GUI widget structure proper, i.e. within the TimelinePanel

proposed solution is to build a smart handle based on WLink,
but also delegating the DiffMutable interface
2018-10-11 17:21:47 +02:00
b65db50666 Timeline: some considerations regarding timeline slave display (#1083) 2018-10-11 14:29:55 +02:00
2adcabbef5 Timeline: draft the root attachment point where timelines are created by diff
This involves a fundamental decision about how to build structures in the Lumiera UI:
They shall be solely created in response to diff messages. Which leads us to
introduce a new (and quite challenging) concept: the »DiffConstituent«
2018-10-10 05:45:46 +02:00