From c573630ac1f1d0910ea6b881118bc420569cb654 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 28 Nov 2019 23:14:16 +0100 Subject: [PATCH] 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 --- src/stage/timeline/body-canvas-widget.cpp | 19 +- src/stage/timeline/track-body.cpp | 2 +- src/stage/timeline/track-body.hpp | 4 +- wiki/renderengine.html | 12 +- wiki/thinkPad.ichthyo.mm | 687 ++++++++++++++++++++-- 5 files changed, 656 insertions(+), 68 deletions(-) diff --git a/src/stage/timeline/body-canvas-widget.cpp b/src/stage/timeline/body-canvas-widget.cpp index 8a35a223b..eb1b43672 100644 --- a/src/stage/timeline/body-canvas-widget.cpp +++ b/src/stage/timeline/body-canvas-widget.cpp @@ -163,7 +163,7 @@ namespace timeline { int line_ = 0; void - fillBackground (StyleC& style, int height) + fillBackground (StyleC style, int height) { style->render_background (cox_ ,visible_.b // left start of the rectangle @@ -176,7 +176,7 @@ namespace timeline { public: AbstractTrackRenderer (CairoC currentDrawContext, DisplayManager& layout) : cox_{currentDrawContext} - , style_{trackBodyStyle.getAdvice()} + , style_{trackBodyStyle.getAdvice()} // storing a const& to the advice is potentially dangerous, but safe here, since it is not long-lived , styleR_{trackRulerStyle.getAdvice()} , visible_{layout.getPixSpan()} { } @@ -485,6 +485,7 @@ namespace timeline { uint overallHeight = rootBody_->establishTrackSpace (profile_); uint rulerHeight = rootBody_->calcRulerHeight() + TrackBody::decoration.topMar; adjustCanvasSize(layout_.getPixSpan().delta(), overallHeight, rulerHeight); + ENSURE (not isnil (profile_)); } } @@ -494,7 +495,7 @@ namespace timeline { * has negotiated the required space for the currently presented content, this function adjusts * the actual Gtk::Layout canvas extension to match. Note that we use two Gtk::Layout controls, * one to show the always visible overview rules, while the second one is placed into a scrollable - * pane to accommodate an arbitrary numbers of tracks + * pane to accommodate an arbitrary number of tracks */ void BodyCanvasWidget::adjustCanvasSize(int canvasWidth, int totalHeight, int rulerHeight) @@ -506,7 +507,7 @@ namespace timeline { if (currWidth != newWidth or currHeight != newHeight) { canvas.set_size(newWidth, newHeight); - canvas.set_size_request(newWidth, newHeight); //////TODO the width might be more than actually is available. Better do this with precise spacing, and do it for the rulerCanvas only!! + canvas.set_size_request(newWidth, newHeight); //////TODO the width might be more than actually is available. Better do this with precisely the dimensions we need, and do it for the rulerCanvas only!! } }; @@ -551,7 +552,7 @@ namespace timeline { * becomes crucial for responsiveness on large sessions ////////////////////////////////////TICKET #1191 */ bool - TimelineCanvas::on_draw (CairoC const& cox) + TimelineCanvas::on_draw (CairoC cox) { // draw track structure behind all widgets openCanvas (cox); @@ -578,7 +579,7 @@ namespace timeline { * only for the child widgets on the canvas, not for any custom painting. */ void - TimelineCanvas::openCanvas (CairoC const& cox) + TimelineCanvas::openCanvas (CairoC cox) { auto adjH = get_hadjustment(); auto adjV = get_vadjustment(); @@ -595,7 +596,7 @@ namespace timeline { * Discard any coordinate offsets, stroke and drawing settings applied within. */ void - TimelineCanvas::closeCanvas (CairoC const& cox) + TimelineCanvas::closeCanvas (CairoC cox) { cox->restore(); } @@ -606,7 +607,7 @@ namespace timeline { * @param cox cairo drawing context for custom drawing, adjusted for our virtual canvas. */ void - TimelineCanvas::drawGrounding (CairoC const& cox) + TimelineCanvas::drawGrounding (CairoC cox) { renderGrounding_(cox); /////////////////////////////////////////////TICKET #1039 : placeholder drawing @@ -627,7 +628,7 @@ namespace timeline { * @param cox cairo drawing context of the virtual canvas for custom drawing. */ void - TimelineCanvas::drawOverlays (CairoC const& cox) + TimelineCanvas::drawOverlays (CairoC cox) { renderOverlay_(cox); /////////////////////////////////////////////TICKET #1039 : placeholder drawing diff --git a/src/stage/timeline/track-body.cpp b/src/stage/timeline/track-body.cpp index 37071785e..2ee02191d 100644 --- a/src/stage/timeline/track-body.cpp +++ b/src/stage/timeline/track-body.cpp @@ -142,7 +142,7 @@ namespace timeline { namespace { /** helper to get the width of combined slope borders. - * Upwards slopes are combined up to a certain level; + * Upwards slopes are combined up to a certain degree; * however, the actual width of such a combined border * is defined through a class in the CSS stylesheet. * The TrackBody::decoration.borders array holds the diff --git a/src/stage/timeline/track-body.hpp b/src/stage/timeline/track-body.hpp index 878f86099..9717235cb 100644 --- a/src/stage/timeline/track-body.hpp +++ b/src/stage/timeline/track-body.hpp @@ -30,7 +30,7 @@ ** track display is coordinated by a TrackPresenter, which corresponds ** to a session::Fork and directly controls the respective display elements ** in the [header pane](\ref timeline::HeaderPaneWidget) and the display of the - ** timeline body, which is actually a canvas for custom drawing. + ** timeline body; the latter is actually a canvas for custom drawing. ** ** @todo WIP-WIP-WIP as of 12/2016 ** @@ -75,7 +75,7 @@ namespace timeline { uint botMar = 0; using Borders = std::array; - Borders borders{0,0,0,0,0,0}; + Borders borders{0,0,0,0,0,0}; ///< width of up to 6 levels of combined upward slope borders (defined in CSS) }; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index ba9334c5c..eddbf0fdb 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -3524,7 +3524,7 @@ In accordance with the Lumiera application architecture in general, the UI is no
A specially configured LumieraPlugin, which actually contains or loads the complete code of the (GTK)GUI, and additionally is linked dynamically against the application core lib. During the [[UI startup process|GuiStart]], loading of this Plugin is triggered from {{{main()}}}. Actually this causes spawning of the GTK event thread and execution of the GTK main loop.
 
-
+
The presentation of the track body area relies on the [[Gtk::Layout "canvas widget"|GtkLayoutWidget]], thus allowing for a mixture of custom drawing with embedded custom Gtk widgets. The actual drawing routine is activated in response to the {{{on_draw}}} signal -- and invoking the inherited handler function will initiate the standard drawing for the embedded child widgets. This partitions the additional, specific drawing activities into a pre-widget drawing phase to prepare the background and framework structure of the track area, and a post-widget drawing phase to show all kinds of overlays, markers cursors and similar UI indicators. A nested structure of {{{TrackBody}}} objects serves as organisational device to structure these custom drawing activities in accordance with the nested structure of the track fork.
 
 !Building a nested 3D structure
@@ -3573,7 +3573,7 @@ Another consequence  is that we do not need to apply an overall "stacked bo
 *;slopes
 *:we use several classes to define the effect of consecutive nested frames forming a common slope; however, we perform this combination effect only 5 steps deep
 *:* we use class {{{.track-slope--deep1}}} for a simple slope (inset by one nested level)
-*:* class {{{.track-slope--deep2}}} for two consecutive nested steps combined. Note this only ever happens on closing (upward) slopes
+*:* class {{{.track-slope--deep2}}} for two consecutive nested steps combined. Only closing (upward) slopes can be combined.
 *:* likewise class {{{.track-slope--deep3}}} for three and class {{{.track-slope--deep4}}} for four combined slopes
 *:* finally, class {{{.track-slope--verydeep}}} is used for five and more combined upward (closing) slopes
 
@@ -9151,7 +9151,7 @@ Besides building on the asset management, implementing Timeline (and Sequence) a
 This topic is {{red{postponed as of 10/2018}}} &rarr; [[#1083|http://issues.lumiera.org/ticket/1083]]
 
-
+
//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.
@@ -9159,10 +9159,10 @@ The TimelineDisplayManager actually is an abstraction, a control interface, revo
 !display evaluation pass
 [>img[Clip presentation control|uml/Timeline-display-evaluation.png]]Since the timeline display is formed by several nested collections of elements, a proper display layout must incorporate information from all those parts. A naive approach likely would just iterate over them and reach in to extract data -- or even worse, build a separate display data store, which then needs to be kept in sync with the component hierarchy. Any of these naive working styles would lead to high coupling and it turns the necessary adjustment and changes into a liability, which raises due to evolution of requirements. Over time, such a dangerous situation can only be avoided altogether by admitting the collaborative nature of the task at hand. To get there, we need to distil the abstraction shared between the global and the local concerns, and we need to shape it such as to build onto some kind of invariant, allowing that abstraction to re-emerge at several levels of locality.
 
-!translation service for the widgets
-Another, closely related topic, handled within this context, is the translation from model structures and units in to display layout coordinates. Within the model, we can distinguish several dimensions (degrees of freedom). For one, there is the topology, the ''location or part'' of the model to expose through the UI. Moreover, there is the ''degree of detail'' for this UI representation. And then, there is the ''temporal position and extension'' to represent.
+!mapping service for the widgets
+Another, closely related topic, handled within this context, is the mapping from model structures and units into display layout coordinates. Within the model, we can distinguish several dimensions (degrees of freedom). For one, there is the topology, the ''location or part'' of the model to expose through the UI. Moreover, there is the ''degree of detail'' for this UI representation. And then, there is the ''temporal position and extension'' to represent.
 
-By principle, //widgets always work exclusively in pixel coordinates// -- thus we need the help of a coordinating entity to find out where some entity shall be located on the GTK drawing canvas. This becomes especially relevant for the timeline body, since there we're relying on a GuiCustomWidget to perform and control some of the UI drawing by specific custom rules and procedures.
+By principle, //widgets always work exclusively in pixel coordinates// -- thus we need the help of a coordinating entity to find out where some entity shall be located on the GTK drawing canvas. This becomes especially relevant for the timeline body, since there we're relying on a GuiCustomWidget to perform and control some of the UI drawing by specific custom rules and procedures. And to add to this complexity, several structures are //nested,// thus anchoring their coordinates relative to the parent entity.
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index aad9d383e..08f4afce2 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -4948,7 +4948,7 @@ - + @@ -6179,8 +6179,8 @@ - - + + @@ -6461,7 +6461,7 @@ - + @@ -18330,7 +18330,7 @@ - + @@ -18352,6 +18352,7 @@ + @@ -18360,24 +18361,36 @@ - - - - - - - +

- "the children of your friends ain't your friends" + da der ViewHook schon zwei Pointer zu zwei Entitäten halten muß, kann man Redundanzen vermeiden, indem man ihn an einem dritten Ort anbringt. Nämlich an einem Ort, an dem ohnehin schon eine Dreiecksbeziehung mit diesen beiden Elementen besteht

- -
+ + +
+
+ + + + + + + + + + + +

+ "the children of your friends ain't necessarily your friends" +

+ +
@@ -18389,8 +18402,7 @@ ...sonst müßte man das Einfügen als eine weitere (protected)-Operation auf dem ViewHookable ausdrücken und könnte dann die Erzeugung des ViewHook fest in den ViewHookable ABC implementieren....

- -
+
@@ -18399,6 +18411,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Jeder neue TrackPresenter bekommt zur Erzeugung einen Funktor, mit dem sich der von ihm gehaltene DisplayFrame in einen Vater-Kontext "einhäkeln" kann... +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...wohl ehr nicht, aber sie sind nicht allgemeingültig, das ist das Problem +

+ + +
+ +
+
+ + + +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...weil der Vater ja auch neue Kinder "hooken" kann +

+ + +
+
+
+ + + + + + + + +

+ d.h. zugleich wird die alte Verbindung gelöst und die neue konstruiert +

+ + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ es gibt keinen prinzipiellen Grund, warum sie scheitern könnte +

+ + +
+
+ + + + + + + + + + + + + + + + + + @@ -18410,6 +18656,10 @@ + + + + @@ -18468,6 +18718,19 @@
+ + + + + + +

+ Das muß auch so sein, denn sonst wäre das systematische Modell und die Controller zu eng mit dem Display-Code verwoben. Der Nachteil ist aber, daß derart aufgedoppelte Struktur bei jeder Strukturänderung invalide wird +

+ +
+ +
@@ -18733,6 +18996,18 @@ + + + + + + + + + + + + @@ -18758,8 +19033,8 @@ - - + + @@ -18945,6 +19220,14 @@ + + + + + + + + @@ -19807,8 +20090,8 @@ - - + + @@ -19823,12 +20106,27 @@ - - + + + + + + + + + + + + + + + + + @@ -19847,8 +20145,8 @@ - - + + @@ -19891,7 +20189,10 @@ - + + + + @@ -20043,7 +20344,7 @@ - + @@ -20057,6 +20358,7 @@

+
@@ -20077,9 +20379,9 @@ - - - + + + @@ -20095,6 +20397,13 @@
+ + + + + + +
@@ -20109,8 +20418,9 @@ - - + + + @@ -20170,7 +20480,17 @@ - + + + + + + +

+ "This interface is used for all single item holding containers. Multi-item containers provide their own unique interface as their items are generally more complex. The methods of the derived classes should be prefered over these..." +

+ +
@@ -20186,6 +20506,196 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ es läuft auf eine Sortier-Operation hinaus +

+ + +
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ und müßte es danach explizit manuell löschen!! +

+

+ d.h. es wird dann nicht mehr gemanaged (was in diesem Fall hilfreich ist) +

+ +
+
+ + + + + + + +
+
+ + + + + + +

+ ...das ist zunächst ein Versuch, ein mühsam errungenes Design zu verifizieren... +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -24663,6 +25173,9 @@ + + + @@ -26440,7 +26953,7 @@ - + @@ -34298,7 +34811,7 @@ - + @@ -36814,13 +37327,14 @@ - + + - - + + @@ -36899,7 +37413,7 @@ - + @@ -37461,7 +37975,7 @@ - + @@ -37661,8 +38175,8 @@ - - + + @@ -37861,7 +38375,80 @@ - + + + + + + + + + + + + + + + + + + + + + + +

+ diese Delegates sind anderswo in eine Collection eingebunden +

+ +
+
+ + + + + + +

+ und deren Reihenfolge ist dort von Bedeutung +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38064,7 +38651,7 @@ - + @@ -38451,7 +39038,8 @@ - + + @@ -38550,7 +39138,7 @@ - + @@ -38894,7 +39482,7 @@ - + @@ -39023,7 +39611,7 @@ - + @@ -41939,8 +42527,7 @@ - - +