From 96dfbf7d968a0f239208da376d994d94657a10d7 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 29 Jan 2021 14:15:18 +0100 Subject: [PATCH] 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 --- src/stage/model/canvas-hook.hpp | 2 +- src/stage/timeline/clip-presenter.cpp | 5 + src/stage/timeline/clip-presenter.hpp | 9 + src/stage/timeline/display-evaluation.cpp | 16 +- src/stage/timeline/display-evaluation.hpp | 4 + src/stage/timeline/marker-widget.cpp | 13 + src/stage/timeline/marker-widget.hpp | 2 + src/stage/timeline/track-presenter.hpp | 45 +- wiki/thinkPad.ichthyo.mm | 841 +++++++++++++++------- 9 files changed, 666 insertions(+), 271 deletions(-) diff --git a/src/stage/model/canvas-hook.hpp b/src/stage/model/canvas-hook.hpp index 6a210d0d1..f4db3a1b9 100644 --- a/src/stage/model/canvas-hook.hpp +++ b/src/stage/model/canvas-hook.hpp @@ -108,7 +108,7 @@ namespace model { * which is to be attached to some timeline canvas view. * @param start anchor point / nominal start point of the element * @param downshift (optional) vertical shift down from the baseline - * @return opaque registration argument for the ViewHooked ctor */ + * @return opaque registration argument for the CanvasHooked ctor */ Pos hookedAt (Time start, int downshift=0) { diff --git a/src/stage/timeline/clip-presenter.cpp b/src/stage/timeline/clip-presenter.cpp index 266eb4e3c..429fb5425 100644 --- a/src/stage/timeline/clip-presenter.cpp +++ b/src/stage/timeline/clip-presenter.cpp @@ -169,6 +169,11 @@ namespace timeline { + widget_->getVerticalOffset(); } + void + ClipPresenter::relink() + { + UNIMPLEMENTED ("attach the Delegate again at its nominal position, if applicable"); + } }}// namespace stage::timeline diff --git a/src/stage/timeline/clip-presenter.hpp b/src/stage/timeline/clip-presenter.hpp index 520a7bc1f..1431f0c1e 100644 --- a/src/stage/timeline/clip-presenter.hpp +++ b/src/stage/timeline/clip-presenter.hpp @@ -111,6 +111,15 @@ namespace timeline { */ int determineRequiredVerticalExtension() const; + /** update and re-attach the presentation widget into its presentation context. + * Will be called during the "re-link phase" of DisplayEvaluation, after the + * timeline layout has been (re)established globally. Often, this incurs + * attaching the presentation widget (ClipDelegate) at a different actual + * position onto the drawing canvas, be it due to a zoom change, or + * as result of layout re-flow. + */ + void relink(); + private:/* ===== Internals ===== */ /** reevaluate desired presentation mode and available data, diff --git a/src/stage/timeline/display-evaluation.cpp b/src/stage/timeline/display-evaluation.cpp index c47c9ab58..ea7399b4c 100644 --- a/src/stage/timeline/display-evaluation.cpp +++ b/src/stage/timeline/display-evaluation.cpp @@ -74,12 +74,24 @@ namespace timeline { * will cause adjustments and a re-evaluation. * @warning care has to be taken to not "overshoot" each adjustment, since this * might lead to never ending re-invocations and "layout oscillation". + * @remark the Layout is established in two phases + * - first the necessary screen extension is determined + * and the global profile of tracks is reconstructed + * - the second pass verifies and possibly reflows + * to achieve consistency, possibly triggering + * recursing through additional size adjustments. */ void DisplayEvaluation::perform() { - this->forkRoot_->establishLayout (*this); - this->canvas_->establishLayout (*this); + REQUIRE (collectLayout_ == true, + "Lifecycle error: DisplayEvaluation object reused"); + // Phase-1 : collect Layout information + forkRoot_->establishLayout (*this); + canvas_->establishLayout (*this); + // Phase-2 : reflow and balance the Layout + collectLayout_ = false; + forkRoot_->establishLayout (*this); } diff --git a/src/stage/timeline/display-evaluation.hpp b/src/stage/timeline/display-evaluation.hpp index 78cdb7496..673f5ef0b 100644 --- a/src/stage/timeline/display-evaluation.hpp +++ b/src/stage/timeline/display-evaluation.hpp @@ -106,12 +106,16 @@ namespace timeline { LayoutElement* forkRoot_{nullptr}; LayoutElement* canvas_{nullptr}; + bool collectLayout_{true}; + public: void perform(); void wireForkRoot (LayoutElement& r) { forkRoot_ = &r; } void wireCanvas (LayoutElement& c) { canvas_ = &c; } + bool isCollectPhase() const { return this->collectLayout_; } + private:/* ===== Internals ===== */ }; diff --git a/src/stage/timeline/marker-widget.cpp b/src/stage/timeline/marker-widget.cpp index 1eafb4c06..1cc235b64 100644 --- a/src/stage/timeline/marker-widget.cpp +++ b/src/stage/timeline/marker-widget.cpp @@ -94,6 +94,19 @@ namespace timeline { })); } + /** update and re-attach the presentation widget into its presentation context. + * Will be called during the "re-link phase" of DisplayEvaluation, after the + * timeline layout has been (re)established globally. Often, this incurs + * attaching the presentation widget (ClipDelegate) at a different actual + * position onto the drawing canvas, be it due to a zoom change, or + * as result of layout re-flow. + */ + void + MarkerWidget::relink() + { + UNIMPLEMENTED ("how to re-attach the Marker, depending on the actual context"); + } + diff --git a/src/stage/timeline/marker-widget.hpp b/src/stage/timeline/marker-widget.hpp index 7f147ca0f..ad8ad0bee 100644 --- a/src/stage/timeline/marker-widget.hpp +++ b/src/stage/timeline/marker-widget.hpp @@ -83,6 +83,8 @@ namespace timeline { /** set up a binding to respond to mutation messages via UiBus */ virtual void buildMutator (lib::diff::TreeMutator::Handle) override; + void relink(); + private:/* ===== Internals ===== */ }; diff --git a/src/stage/timeline/track-presenter.hpp b/src/stage/timeline/track-presenter.hpp index d419e18b2..1d9cb9834 100644 --- a/src/stage/timeline/track-presenter.hpp +++ b/src/stage/timeline/track-presenter.hpp @@ -173,6 +173,7 @@ namespace timeline { } void establishExtension (vector&, vector&); + void sync_and_balance (DisplayEvaluation&); }; @@ -231,6 +232,8 @@ namespace timeline { TODO_trackName_ = name; /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1201 : test/code... remove this } + + void relinkContents (DisplayEvaluation&); }; @@ -311,16 +314,33 @@ namespace timeline { /** handle the DisplayEvaluation pass for this track and its sub-tracks. - * @todo 2/2020 WIP-WIP initial draft; need to find out more about Clip display */ inline void TrackPresenter::establishLayout (DisplayEvaluation& displayEvaluation) { - display_.establishExtension (clips_, markers_); + if (displayEvaluation.isCollectPhase()) + display_.establishExtension (clips_, markers_); + else + relinkContents (displayEvaluation); for (auto& subTrack: subFork_) subTrack->establishLayout (displayEvaluation); } + /** second pass of the DisplayEvaluation: + * reassemble content to match adjusted layout + * @todo 2/2021 WIP-WIP initial draft; many aspects still unclear + */ + inline void + TrackPresenter::relinkContents (DisplayEvaluation& displayEvaluation) + { + for (auto& clip: clips_) + clip->relink(); + for (auto& mark: markers_) + mark->relink(); + // re-sync and match the header / body display + display_.sync_and_balance (displayEvaluation); + } + /** find out about the vertical extension of a single track display. */ inline void DisplayFrame::establishExtension (vector& clips, vector&) @@ -335,6 +355,27 @@ namespace timeline { int headSize = this->head_.get_height(); int bodySize = this->body_.calcHeight(); } + + /** re-flow and adjust after the global layout has been established + * At this point we can assume that both header and body are updated + * and have valid extensions within their perimeter. But the coordination + * of track head display and body content might be out of sync and needs + * readjustments. This second pass gives the opportunity to fix such + * discrepancies by further increasing vertical extension, but this + * also has the consequence to trigger yet another DisplayEvaluation, + * since any readjustment invalidates the global layout. However, since + * all adjustments are done by increasing monotonously, after several + * recursions the layout will be balanced eventually. + * @note any discrepancy not solvable at this local level should be + * propagated downwards, which can be achieved by transporting + * this information through the DisplayEvaluation object. + */ + inline void + DisplayFrame::sync_and_balance (DisplayEvaluation& displayEvaluation) + { + TODO ("actually do something to keep Header and Body in Sync. Save a delta into the displayEvaluation"); + } + diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index c3aec128a..bac0a5766 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -5426,8 +5426,8 @@ - - + + @@ -21160,7 +21160,8 @@ - + + @@ -21188,6 +21189,7 @@ + @@ -21206,6 +21208,71 @@ + + + + + + + + + + + + + + + + + + + + + + +

+ isnil (profile_) +

+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -21222,6 +21289,7 @@ + @@ -21496,6 +21564,8 @@ + + @@ -21598,7 +21668,9 @@ - + + + @@ -21612,6 +21684,9 @@ + + + @@ -21688,9 +21763,14 @@ - + + + + + + @@ -21876,8 +21956,9 @@ - + + @@ -21895,6 +21976,154 @@ + + + + + + + + + + + + + + +

+ noch nicht klar, welche Rolle der spielt; ich sehe ihn erst mal vor, weil er möglich ist. Denkbar wäre, daß er durch User-Interaktion entsteht, oder aber auch systematisch generiert wird, um bestimmte Arten von Clips optisch abzusetzen +

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

+ Clips dürften die häufigsten Entitäten in der Timeline-Anzeige werden. Es müssen tausende bis zehntausende Clips performant gehandhabt werden +

+ + +
+
+ + + + + + +

+ die Kontrollstruktur ist bereits gefährlich komplex; spezielle "Schleifen" durch die Innereien eigentlich nicht involvierter Entitäten allein aus Performance-Gründen sollten vermieden werden +

+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
    +
  • + denn eigentlich wäre das eine "interne Angelegenheit" von CanvasHook ↔ CanvasHooked +
  • +
  • + da aber die Koordinaten-Daten im Clip liegen, muß der Clip involviert werden +
  • +
  • + obwohl dies überhaupt nicht zu den Belangen des Clip gehört +
  • +
+ + +
+ +
+
+ + + + + + + + + + + + + + +

+ ...ich hab ja nicht umsonst in der theoretischen Analyse herausgefunden, daß dieses Schema auf ein Phasen-Modell hinausläuft; die Hoffnung wäre höchstens gewesen, daß in der Praxis der 3.Pass derart degeneriert,  daß man ihn in den 1.Pass einfalten kann +

+ + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+
@@ -27824,6 +28053,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -27921,21 +28171,28 @@ - - + + + + + + + + + + + + + + - - - - - - - - + + + @@ -27953,7 +28210,7 @@ - + @@ -28222,6 +28479,18 @@ + + + + + + + + + + + + @@ -28316,6 +28585,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ERR: nexus.hpp:189: worker_3: ~Nexus: Some UI components are still connected to the backbone. +

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

+ Ein Clip hat verschiedene Erscheinungsformen im UI +

+

+ +

+

+ Verwende das als Leitgedanke, um das Layout zu entwickeln +

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

+ UI-Bus gilt nur für globale Belange +

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

+ es geht nur um Rollen +

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

+ das lokale Element muß nur als View fungieren +

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

+ kann sich selbst +

+

+ transformieren +

+ +
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + @@ -28377,6 +28926,7 @@ + @@ -28661,258 +29211,17 @@ - + + - - - - - + + - - + + + - - - - - - - - - - - - - - - - - - -

- ERR: nexus.hpp:189: worker_3: ~Nexus: Some UI components are still connected to the backbone. -

- -
- - -
-
- - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - -

- Ein Clip hat verschiedene Erscheinungsformen im UI -

-

- -

-

- Verwende das als Leitgedanke, um das Layout zu entwickeln -

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- UI-Bus gilt nur für globale Belange -

- -
- - - - - - - - - - - - - - - -

- es geht nur um Rollen -

- -
-
- - - - - - - - - -

- das lokale Element muß nur als View fungieren -

- -
-
- - - - - - - - - - - - - - - -

- kann sich selbst -

-

- transformieren -

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