(cont) analysis of timeline display control
This commit is contained in:
parent
f5ea31a533
commit
170c505a8a
4 changed files with 2379 additions and 217 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 9.8 KiB |
2512
uml/Lumiera.xmi
2512
uml/Lumiera.xmi
File diff suppressed because it is too large
Load diff
|
|
@ -1432,13 +1432,13 @@ Lumiera agrees to this common understanding (of most film editing and sound hand
|
|||
→ PipeHandling
|
||||
</pre>
|
||||
</div>
|
||||
<div title="ClipPresenter" creator="Ichthyostega" modifier="Ichthyostega" created="201611200101" modified="201611201650" tags="def GuiPattern img" changecount="9">
|
||||
<div title="ClipPresenter" creator="Ichthyostega" modifier="Ichthyostega" created="201611200101" modified="201611280204" tags="def GuiPattern img" changecount="10">
|
||||
<pre>//mediating entity used to guide and control the presentation of a clip in the UI.//
|
||||
|
||||
The clip representation in the UI links together two distinct realms and systems of concerns. For one, there are the properties and actions performed on the clip for sake of editing a movie. Everything which has a tangible effect on the resulting render. These information and operations are embodied into the HighLevelModel and can be manipulated script driven, without relying on an UI. But beyond that, there is also the local mechanics of the interface, everything which makes working on the edit and interacting with the model into a smooth experience and workflow. With respect to this concerns, a clip is a self-contained entity which owns its own state and behaviour. The ClipPresenter is the pivotal element to link together those two realms.
|
||||
|
||||
[>img[Clip presentation control|uml/Timeline-clip-display.png]]
|
||||
Regarding the global angle, the ClipPresenter is an UI-Element connected to the UI-Bus, and it is added as child element to some parent entity, typically the UI representation of a [[fork ("track")|Fork]]. Commands manipulating the clip can be sent via the embedded bus terminal, and status regarding clip properties and nested child elements (effects, transitions) is received as messages via the bus, which insofar plays the role of model and controller.
|
||||
Regarding the global angle, the ClipPresenter is an UI-Element connected to the UI-Bus, and it is added as child element to some parent entity, a TrackPresenter, which likewise serves as UI representation of a [[fork ("track")|Fork]], and controls widgets to render a track like working scope (in the header pane and in the timeline contents pane). Commands manipulating the clip can be sent via the embedded bus terminal, and status regarding clip properties and nested child elements (effects, transitions) is received as messages via the bus, which insofar plays the role of model and controller.
|
||||
|
||||
But regarding the local UI behaviour, the ClipPresenter acts autonomous. It controls an actual {{{ClipWidget}}} for presentation, negotiating the display strategy with some overarching presentation manager. Active parts of the widget are wired back to handling methods of the presenter.
|
||||
</pre>
|
||||
|
|
@ -2452,7 +2452,7 @@ we need a test setup for this investigation.
|
|||
* realistic: shall reflect the situation in our actual UI
|
||||
</pre>
|
||||
</div>
|
||||
<div title="GuiClipWidget" creator="Ichthyostega" modifier="Ichthyostega" created="201611180114" modified="201611200138" tags="GuiPattern design draft" changecount="17">
|
||||
<div title="GuiClipWidget" creator="Ichthyostega" modifier="Ichthyostega" created="201611180114" modified="201611272357" tags="GuiPattern design draft" changecount="18">
|
||||
<pre>//The representation of a [[media clip|Clip]] for manipulation by the user within the UI.//
|
||||
Within Lumiera, a clip is conceived as a //chunk of media,// which can be handled in compound. Clip as such is an abstract concept, which is treated with minimal assumptions...
|
||||
* we know that a clip has //media content,// which need not be uniform and can be inherently structured (e.g. several media, several channels)
|
||||
|
|
@ -2477,7 +2477,7 @@ Depending on specific circumstances within the presentation, we get a fundamenta
|
|||
* need to build a custom drawing container for a single widget, to produce the compact and expanded display; theoretically this display can be //reduced// to the abridged form.
|
||||
* alternatively we may omit the overhead of a custom drawing container, if we know that we'll most likely stick to the abridged form, or reduce display to a placeholder block
|
||||
* but in the extreme case, we do not even display anything for a given widget -- rather we need to create a placeholder to stand-in for //N clips.//
|
||||
This is unfortunate, since it defeats a self-contained control structure, where each widget holds its own model and manages its own state. Rather, we have to distinguish between child elements as belonging to the model and child widgets as far as the view is concerned. A given scope in the fork could have more clip child elements than child widgets for display. Which means, we have to separate between the view aspect and the modelling aspect. And this split happens already on a level global to the timeline.
|
||||
This is unfortunate, since it defeats a self-contained control structure, where each widget holds its own model and manages its own state. Rather, we have to distinguish between child elements as belonging to the model vs child widgets as far as the view is concerned. A given scope in the fork could have more clip child elements than child widgets for display. Which means, we have to separate between the view aspect and the modelling aspect. And this split happens already on a level global to the timeline.
|
||||
|
||||
This creates a tension related to the kind of architecture we want to build with the help of the UI-Bus. The intention is to split and separate between the application global concerns, like issuing an editing command or retrieving changed model contents, and the //local UI mechanics.// This separation can only work, if -- with respect to the global concerns -- the UI-Bus embodies (actually mediates) the roles of model //and// controler, while the UI widgets take on the role of a "mere view". While, for the local concerns, the same widgets are to act self-contained. But now, already the existence of aforementioned widgets becomes dependent from another, obviously local concern, which unfortunately cross-cuts the 1:1 relation between model entities and view counterpart.
|
||||
|
||||
|
|
@ -2827,7 +2827,7 @@ In the most general case, there can be per-track content and nested content at t
|
|||
&rarr; important question: how to [[organise the widgets|GuiTimelineWidgetStructure]]
|
||||
</pre>
|
||||
</div>
|
||||
<div title="GuiTimelineWidgetStructure" creator="Ichthyostega" modifier="Ichthyostega" created="201410250002" modified="201611260315" tags="GuiPattern discuss decision impl" changecount="79">
|
||||
<div title="GuiTimelineWidgetStructure" creator="Ichthyostega" modifier="Ichthyostega" created="201410250002" modified="201611280229" tags="GuiPattern discuss decision impl" changecount="85">
|
||||
<pre>The Timeline is probably the most prominent place in the GUI where we need to come up with a custom UI design.
|
||||
Instead of combining standard components in one of the well-known ways, here we need to come up with our own handling solution -- which also means to write one or several custom GTK widgets. Thus the question of layout and screen space division and organisation becomes a crucial design decision. The ~GTK-2 Gui, as implemented currently, did already take some steps along this route, yet this kind of decision should be cast and documented explicitly (be it after the fact).
|
||||
|
||||
|
|
@ -2853,7 +2853,7 @@ While the special setup for scrolling doesn't really count (since it is necessar
|
|||
!!!follow-up to the obvious choices
|
||||
We came to this point of re-considering the overall organisation of widgets, after having to re-write the initial version of our timeline widget. This initial version was developed by Joel Holdsworth, and it followed a similar reasoning, involving a global timeline layout manager. The distinction between the two panes was not so clear though, and the access to the model code was awkward at places, so the necessity to re-write the timeline widget due to the transition to ~GTK-3 looks like a good opportunity to re-do the same basic reasoning a second time, verify decisions taken and improve matters turning out as difficult on first attempt.
|
||||
|
||||
So we get a timeline custom widget, which at top level establishes this two-part layout, provides the global scrollbars and integrates custom widget components for both parts. And this top-level timeline widget owns a layout manager, plus it exposes a common view management interface, to be used both from internal components (e.g. zoom widgets within the UI) and from external actors controlling the timeline display from a global level. Also at this global level, we get to define a layout control interface, which has to be implemented by the recursively structured parts of the timeline display, and which is used by the global layout manager to execute its control over the layout as a whole. {{red{Note (11/2016)}}}: if this layout control interface works push or pull style is a decision yet to be worked out during the course of the implementation.
|
||||
So we get a timeline custom widget, which at top level establishes this two-part layout, provides the global scrollbars and integrates custom widget components for both parts. And this top-level timeline widget owns a layout manager, plus it exposes a common view management interface, to be used both from internal components (e.g. zoom widgets within the UI) and from external actors controlling the timeline display from a global level. Also at this global level, we get to define a layout control interface, the TimelineDisplayManager, which has to be implemented within the recursively structured parts of the timeline display, and which is used by the global layout manager to execute its control over the layout as a whole. {{red{Note (11/2016)}}}: if this layout control interface works push or pull style is a decision yet to be worked out during the course of the implementation.
|
||||
|
||||
|
||||
!dealing with nested structures
|
||||
|
|
@ -2864,15 +2864,15 @@ The structure of the display is extended or altered under two circumstances:
|
|||
# the display (style) of some component is expanded or collapsed.
|
||||
Here, the "component" relevant for such structural changes is always the UI representation of a track. Beyond that, the layout can also be changed //without changing the display structure,// when some embedded component, be it placement (in the track heads / the patchbay) or a clip, effect or transition, is expanded or collapsed. In such a case, a resizing challenge needs to be directed towards the next enclosing track container.
|
||||
|
||||
From these observations we can draw the conclusion, that we'll build a ''local structural model'', to reflect the logical relations between the parts comprising the timeline display. And each of these local representation components holds onto a display context, which in fact links it into two different display widget stacks in the two parts of the actual timeline display. Thus, if a component, especially a track, adds a child, it has to pass this child to its own display context, which in turn has to consult its parts, attach new child widgets to those parts and form a new child display context, which then has to be returned to the newly formed child and stored there for future referral.
|
||||
From these observations we can draw the conclusion, that we'll build a ''local structural model'', to reflect the logical relations between the parts comprising the timeline display. More precisely, these structuring components are not mere model objects, rather they are mediating entities used to guide and organise the actual view entities, which in turn are passive. They are more like a view model, while also bearing some local controller responsibilities. For this reason, we prefer to term these as ''presenters'' -- i.e. TrackPresenter and ClipPresenter. And each of these local representation components holds onto a display context, which generally links it into two different display widget stacks in the two parts of the actual timeline display. Adding a child component thus becomes a rather tricky operation, involving to link possibly two child widgets into two disjoint parent widgets, thereby forming a similar display context for the child presenter. Overall, the guiding idea is that of self similarity: on each level, we have to reproduce the same relations and collaborations as present in the parent level.
|
||||
|
||||
!!!interplay with diff mutation
|
||||
Applying a diff changes the structure, that is, the structure of the local model, not the structure of the display widgets. Because the latter are a entirely private concern of the UI and their structure is controlled by the model components in conjunction with the display manager. And since diff application effects the contents of the model such as to make the intended structural changes happen (indirectly), we are well advised to tie the display control and the widgets very closely to those local model elements, such as to //adjust the display automatically.//
|
||||
* when a new model element is added, it has automatically to inject something into the display
|
||||
Applying a diff changes the structure, that is, the structure of the local model, not the structure of the display widgets. Because the latter are an entirely private concern of the UI and their structure is controlled by the model components in conjunction with the display manager. And since diff application effects the contents of the model such as to make the intended structural changes happen (indirectly), we are well advised to tie the display control and the widgets very closely to those local model elements, such as to //adjust the display automatically.//
|
||||
* when a new model element is added, it has to inject something automatically into the display
|
||||
* when a model element happens to be destructed, the corresponding display element has to be removed.
|
||||
* such might be triggered indirectly, by clean-up of leftovers, since the DiffApplicator re-orders and deletes by leaving some data behind
|
||||
* such might be triggered indirectly, by clean-up of leftovers, since the {{{DiffApplicator}}} re-orders and deletes by leaving some data behind
|
||||
* the diff also re-orders model elements, which does not have an immediate effect on the display, but needs to be interpreted separately.
|
||||
Together this means we get a fix up stage after model changes, where the display is re-adjusted to fit the new situation. This works in concert with the display manager representing only those elements as actual widgets, which get a real chance to become visible. This way we can build on the assumption that the actual number of widgets to be managed any time remains so small as to get away with simple linear list processing. It remains to be seen how far this assumption can be pushed -- the problem is that the GTK container components don't support anything beyond such simple linear list processing; there isn't even a call to remove all child widgets of a container in a single pass.
|
||||
Together this means we get a fix up stage after model changes, where the display is re-adjusted to fit the new situation. This works in concert with the [[display manager|TimelineDisplayManager]] representing only those elements as actual widgets, which get a real chance to become visible. This way we can build on the assumption that the actual number of widgets to be managed any time remains so small as to get away with simple linear list processing. It remains to be seen how far this assumption can be pushed -- the problem is that the GTK container components don't support anything beyond such simple linear list processing; there isn't even a call to remove all child widgets of a container in a single pass.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="HighLevelModel" modifier="Ichthyostega" created="200808152311" modified="201505310109" tags="Model spec design discuss img" changecount="2">
|
||||
|
|
@ -8132,6 +8132,12 @@ Actually, Timeline is both an interface and acts as façade. Its an interface, b
|
|||
Besides building on the asset management, implementing Timeline (and Sequence) as StructAsset yields another benefit: ~StructAssets can be retrieved by query, allowing to specify more details of the configuration immediately on creation. //But on the short term, this approach causes problems:// there is no real inference engine integrated into Lumiera yet (as of 2/2010 the plan is to get an early alpha working end to end first). For now we're bound to use the {{{fake-configrules}}} and to rely on a hard wired simulation of the intended behaviour of a real query resolution. Just some special magic queries will work for now, but that's enough to get ahead.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="TimelineDisplayManager" creator="Ichthyostega" modifier="Ichthyostega" created="201611280235" tags="spec GuiPattern" changecount="1">
|
||||
<pre>//guide and control the concrete display properties of the various sub components (tracks, clips) comprising a timeline display.//
|
||||
|
||||
The TimelineDisplayManager actually is an abstraction, a control interface, revolving around the guidance individual components need in order to settle on a proper display. Those components are represented as mediating entities, the TrackPresenter and the ClipPresenter, each of which controls and manages a mostly passive GTK widget. To this end, the presenters need to know at which virtual coordinates their corresponding widgets would show up, and they need to know if these widgets need to be actually present at the moment. Also, especially the ClipPresenter needs to know which ''clip appearance style'' to choose for the corresponding slave widget.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="TimelineSequences" modifier="Ichthyostega" created="200811011836" modified="201505310138" tags="design decision img" changecount="4">
|
||||
<pre>There is a three-level hierarchy: [[Project|Session]], [[Timeline]], [[Sequence]]. Each project can contain ''multiple timelines'', to be viewed and rendered independently. But, being the top-level entities, these timelines may not be combined further. You can always just render (or view) one specific timeline. Each of those timelines refers to a Sequence, which is a bunch of [[media objects|MObject]] placed to a [[fork ("tree of tracks")|Fork]]. Of course it is possible to use ~sub-sequences within the top-level sequence within a timeline to organize a movie into several scenes or chapters.
|
||||
|
||||
|
|
@ -8233,6 +8239,12 @@ Placements are __resolved__ resulting in an ExplicitPlacement. In most cases thi
|
|||
&rarr; [[Definition|Pipe]] and [[handling of Pipes|PipeHandling]]
|
||||
</pre>
|
||||
</div>
|
||||
<div title="TrackPresenter" creator="Ichthyostega" modifier="Ichthyostega" created="201611280207" modified="201611280224" tags="def GuiPattern" changecount="3">
|
||||
<pre>//mediating entity used to guide and control the track-like nested working space in the timeline display of the UI.//
|
||||
|
||||
Similar to the ClipPresenter, from a global angle this element fulfils a model like role, while also guiding and controlling a mostly passive view component implemented as GTK widget. Here, the authority of the presenter over the widget must be total, since display management //needs to work automatically,// due to model updates and mutations arriving as [[diff messages|MutationMessage]]. In addition, this structure is prerequisite for (possibly) implementing UI rendering optimisations, since it allows us to leave out widgets entirely, when it is clear they won't become visible: A ''display evaluation pass'', which is effectively a //tree walk,// consecutively visits each part of the timeline structure, to negotiate its concrete display properties in collaboration with a global TimelineDisplayManager. As a result, the presenter knows where to show its corresponding view, and it knows if to show it at all, allowing to either adjust, create or destroy actual GTK widgets within its local reference frame.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="TransitionsHandling" modifier="Ichthyostega" created="200712080417" modified="200805300100" tags="def design">
|
||||
<pre>Transitions combine the data from at least two processing chains and do this combining in a time varying fashion. So, any transition has
|
||||
* N input connections
|
||||
|
|
|
|||
|
|
@ -316,6 +316,56 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1480300573857" ID="ID_434577605" MODIFIED="1480300855667" TEXT="Anzeige-Steuerung" VSHIFT="20">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1480300584454" ID="ID_202830560" MODIFIED="1480300592344" TEXT="globaler Layout-Manager">
|
||||
<node CREATED="1480300595820" ID="ID_1004344887" MODIFIED="1480300606631" TEXT="fungiert als Service"/>
|
||||
<node CREATED="1480300614873" ID="ID_895306481" MODIFIED="1480300625444" TEXT="Ermitteln konkreter Koordinaten"/>
|
||||
</node>
|
||||
<node CREATED="1480300627712" ID="ID_1748490788" MODIFIED="1480300640058" TEXT="Display-Manager">
|
||||
<node CREATED="1480300640790" ID="ID_1461181527" MODIFIED="1480300644825" TEXT="Abstraktion">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
<node CREATED="1480300645837" ID="ID_337010957" MODIFIED="1480300648544" TEXT="Interface"/>
|
||||
<node CREATED="1480300649437" ID="ID_704277125" MODIFIED="1480300673402">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
interagiert mit den <b>Presentern</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1480300682256" ID="ID_1828380850" MODIFIED="1480300684700" TEXT="Presenter">
|
||||
<node CREATED="1480300690191" ID="ID_1405428387" MODIFIED="1480300779304" TEXT="sind lokales Struktur-Modell">
|
||||
<node CREATED="1480300733506" ID="ID_186466790" MODIFIED="1480300739877" TEXT="werden per Diff manipuliert"/>
|
||||
<node CREATED="1480300740537" ID="ID_1322437138" MODIFIED="1480300765878" TEXT="enthalten die Modell-Binding-Daten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
d.h. eine LUID
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1480300699694" ID="ID_1686150984" MODIFIED="1480300712392" TEXT="aktiver Part der View-Steuerung"/>
|
||||
<node CREATED="1480300717747" ID="ID_1736166807" MODIFIED="1480300724214" TEXT="Master-Slave für die Widgets"/>
|
||||
<node CREATED="1480300804840" ID="ID_1330942810" MODIFIED="1480300820674" TEXT="Verbindung zum Anzeigekontext">
|
||||
<node CREATED="1480300822302" ID="ID_1819260908" MODIFIED="1480300833984" TEXT="zwei Kontexte für die Tracks"/>
|
||||
<node CREATED="1480300836092" ID="ID_1069009472" MODIFIED="1480300847326" TEXT="Anzeigekontext = Konkretes Vater-Widget"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1476376943985" HGAP="22" ID="ID_1422206856" MODIFIED="1479434895083" TEXT="Viewer" VSHIFT="10"/>
|
||||
<node CREATED="1479434763643" HGAP="25" ID="ID_1572413636" MODIFIED="1479434887744" TEXT="Clip" VSHIFT="31">
|
||||
|
|
|
|||
Loading…
Reference in a new issue