From 8f572fc1223cc54651e7ed607e371960d6eb3733 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 7 Feb 2021 20:45:28 +0100 Subject: [PATCH] DisplayEvaluation: draft coordinated vertical layout (see #1211) a first rather simplistic attempt to establish a vertically synchronised layout between track header and body. TODO: doesn't yet work as intended --- src/stage/timeline/track-body.cpp | 2 +- src/stage/timeline/track-body.hpp | 2 +- src/stage/timeline/track-head-widget.cpp | 54 ++++++++- src/stage/timeline/track-head-widget.hpp | 6 + src/stage/timeline/track-presenter.hpp | 33 ++++-- src/stage/timeline/track-profile.hpp | 2 +- src/stage/workspace/ui-style.cpp | 2 +- wiki/thinkPad.ichthyo.mm | 136 ++++++++++++++++------- 8 files changed, 179 insertions(+), 58 deletions(-) diff --git a/src/stage/timeline/track-body.cpp b/src/stage/timeline/track-body.cpp index 77dec56ff..aca615ca3 100644 --- a/src/stage/timeline/track-body.cpp +++ b/src/stage/timeline/track-body.cpp @@ -127,7 +127,7 @@ namespace timeline { * within this track's content area */ void - TrackBody::accomodateHeight(uint contentExtension) + TrackBody::accommodateContentHeight(uint contentExtension) { if (contentExtension > contentHeight_) contentHeight_ = contentExtension; diff --git a/src/stage/timeline/track-body.hpp b/src/stage/timeline/track-body.hpp index 41f6917ce..fe96a4feb 100644 --- a/src/stage/timeline/track-body.hpp +++ b/src/stage/timeline/track-body.hpp @@ -118,7 +118,7 @@ namespace timeline { uint establishTrackSpace (TrackProfile&); uint calcRulerHeight(); uint calcHeight(); - void accomodateHeight(uint contentExtension); + void accommodateContentHeight(uint contentExtension); uint getContentOffsetY() { return startLine_ + contentOffset_; } diff --git a/src/stage/timeline/track-head-widget.cpp b/src/stage/timeline/track-head-widget.cpp index 87a8be7ca..ef1b08ca9 100644 --- a/src/stage/timeline/track-head-widget.cpp +++ b/src/stage/timeline/track-head-widget.cpp @@ -36,7 +36,7 @@ //#include "lib/format-string.hpp" //#include "lib/format-cout.hpp" -//#include "lib/util.hpp" +#include "lib/util.hpp" //#include //#include @@ -50,6 +50,7 @@ //using sigc::ptr_fun; //using std::cout; //using std::endl; +using util::max; namespace stage { @@ -81,15 +82,57 @@ namespace timeline { nameTODO_.set_label (trackName); } + uint + TrackHeadWidget::calcContentHeight() const + { + if (childCnt_ == 0) return calcOverallHeight(); + + auto* chld1 = this->get_child_at(0,0); + auto* chld2 = this->get_child_at(1,0); + int h1 = chld1? chld1->get_height() :0; + int h2 = chld2? chld2->get_height() :0; + + return max (0, max (h1,h2)); + } + + uint + TrackHeadWidget::calcOverallHeight() const + { + return this->get_height(); + } + + void + TrackHeadWidget::accommodateContentHeight(uint contentHeight) + { + uint localHeight = calcContentHeight(); + if (contentHeight > localHeight) + increaseContentHeight (contentHeight-localHeight); + } + + /** apply the Δ to some child in first row */ + void + TrackHeadWidget::increaseContentHeight(uint delta) + { + auto* cell = this->get_child_at(1,0); + if (not cell) + cell = this->get_child_at(0,0); + REQUIRE (cell); + int h = cell->get_height(); + cell->set_size_request (-1, h+delta); + } + + + /** * @remark The Lumiera Timeline model does not rely on a list of tracks, as most conventional * video editing software does -- rather, each sequence holds a _fork of nested scopes._ * This recursively nested structure is reflected in the patchbay area corresponding to * each track in the _header pane_ of the timeline display, located to the left. The * patchbay for each track is a grid with initially four quadrants, and the 4th quadrant - * holds the _content area,_ which is again a TrackHeadWidget. Additional sub-Tracks - * are added as additional lines to the grid, while nested sub-Tracks will be handled - * recursively by the corresponding nested TrackHeadWidget. + * corresponds to the _content area,_ in case this is a leaf track. Otherwise there would + * be nested sub-Tracks, and this lower right grid cell would then hold a TrackHeadWidget + * recursively. Additional sub-Tracks are added as additional lines to the grid, while + * further nested sub-Tracks will be handled by the corresponding nested TrackHeadWidget. * @note Child tracks are always appended. When tracks are reordered or deleted, * the whole structure has to be re-built accordingly. */ @@ -107,7 +150,8 @@ namespace timeline { * automatically decrements the refcount; alternatively we could as well * destroy the Gtkmm wrapper-Object (i.e. the `Gtk::Widget` subclass), * since this also destroys the underlying `gobj` and automatically - * detaches it from any container. + * detaches it from any container. (however, here this isn't necessary, + * since the TrackHeadWidget is managed by the DisplayFrame) */ void TrackHeadWidget::detachSubFork (TrackHeadWidget& subForkHead) diff --git a/src/stage/timeline/track-head-widget.hpp b/src/stage/timeline/track-head-widget.hpp index a7cc74dcb..9af3d38d8 100644 --- a/src/stage/timeline/track-head-widget.hpp +++ b/src/stage/timeline/track-head-widget.hpp @@ -89,6 +89,12 @@ namespace timeline { ~TrackHeadWidget(); void setTrackName (cuString&); + + uint calcContentHeight() const; + uint calcOverallHeight() const; + + void accommodateContentHeight(uint); + void increaseContentHeight(uint delta); private:/* ===== Internals ===== */ diff --git a/src/stage/timeline/track-presenter.hpp b/src/stage/timeline/track-presenter.hpp index f7b65c6e9..6898f3df9 100644 --- a/src/stage/timeline/track-presenter.hpp +++ b/src/stage/timeline/track-presenter.hpp @@ -341,7 +341,15 @@ namespace timeline { display_.sync_and_balance (displayEvaluation); } - /** find out about the vertical extension of a single track display. */ + /** + * Find out about the vertical extension of a single track display. + * @note will be invoked during the first recursive walk, at which point + * the TrackProfile has not yet been established; the latter will + * happen after returning from that recursive walk. Thus within this + * first pass, we can only adjust local sizes within the content area, + * while the second pass, in #relinkContents() can also investigate + * the track body vertical extension, defined by the TrackProfile. + */ inline void DisplayFrame::establishExtension (vector& clips, vector&) { @@ -350,10 +358,9 @@ namespace timeline { { return clip->determineRequiredVerticalExtension(); })); - this->body_.accomodateHeight(maxVSize); - //////////////////////////////////////////////////////////////////////////////////////////TICKET #1211 : actually implement a coordination of head / body sizes here - uint headSize = this->head_.get_height(); - uint bodySize = this->body_.calcHeight(); + maxVSize = max (maxVSize, head_.calcContentHeight()); + this->body_.accommodateContentHeight (maxVSize); + this->head_.accommodateContentHeight (maxVSize); } /** re-flow and adjust after the global layout has been established @@ -366,14 +373,20 @@ namespace timeline { * 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. + * @note We can increase a head to match body size. Otherwise, if the body + * is too small, we're out of luck, since the Profile is already calculated. + * However, since we accommodated the local extension within each content area + * prior to calculating the Profile, chances are that such a discrepancy is small. + * @remark we could also consider to transport a discrepancy downwards by using a + * state variable in the DisplayEvaluation */ inline void - DisplayFrame::sync_and_balance (DisplayEvaluation& displayEvaluation) + DisplayFrame::sync_and_balance (DisplayEvaluation&) { - TODO ("actually do something to keep Header and Body in Sync. Save a delta into the displayEvaluation"); + uint headSize = head_.calcOverallHeight(); + uint bodySize = body_.calcHeight(); + if (bodySize > headSize) + head_.increaseContentHeight (bodySize-headSize); } diff --git a/src/stage/timeline/track-profile.hpp b/src/stage/timeline/track-profile.hpp index 65ceb62e1..002a12927 100644 --- a/src/stage/timeline/track-profile.hpp +++ b/src/stage/timeline/track-profile.hpp @@ -24,7 +24,7 @@ /** @file track-profile.hpp ** Abstraction to build the layout for the track spaces within timeline display. ** In Lumiera, tracks are arranged into a fork of nested shapes, which structure - ** is parallelled into nested structure of TrackBody elements. A tree walk over + ** is parallelled into a nested structure of TrackBody elements. A tree walk over ** this structure yields a sequence of adjacent timeline elements, like overview ** rulers, content area and nested child track display. This sequence can then ** be transformed into suitable drawing instructions to create a 3D shaded diff --git a/src/stage/workspace/ui-style.cpp b/src/stage/workspace/ui-style.cpp index 06b3b4a95..28108f9a5 100644 --- a/src/stage/workspace/ui-style.cpp +++ b/src/stage/workspace/ui-style.cpp @@ -111,7 +111,7 @@ namespace workspace { * of widget parent relationships down from the top-level window * - this Gtk::WidgetPath is then used to match against CSS selectors of the GTK stylesheet, * either the global system theme, or (with precedence) an application stylesheet (`lumiera.css`) - * - but the Gtk::StyleContext and (and should) also be used outside of the core GTK framework to + * - but the Gtk::StyleContext can (and should) also be used outside of the core GTK framework to * carry out custom drawing tasks, which allows custom drawing to "blend in" with the desktop theme. * - to support this usage, we construct a "virtual widget" and place it at a systematically correct * position in the widget hierarchy, causing the corresponding style context to pick up the appropriate diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 38b03f299..1d862125a 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -21329,8 +21329,8 @@ - - + + @@ -21909,6 +21909,32 @@ + + + + + + + + + + + + + + +

+ Invariante gilt auf einem Fork +

+ +
+ + + + + + +
@@ -21923,14 +21949,16 @@ + + - + - - + + @@ -21952,27 +21980,44 @@ - - - - - - - - - - - + + + +

- in geometrischer Reihenfolge von oben nach unten + ...um die Widgets an die nun korrekte Position gemäß Track-Profil zu schieben

+ +
+ + + + + + + + + + + + + + + + + + + + + + @@ -22440,6 +22485,9 @@ + + + @@ -22539,6 +22587,7 @@

+ @@ -22575,7 +22624,18 @@ - + + + + + + + + + + + + @@ -22793,17 +22853,6 @@ - - - - - - - - - - - @@ -22874,6 +22923,17 @@ + + + + + + + + + + + @@ -23820,7 +23880,9 @@ - + + + @@ -27801,7 +27863,7 @@ - + @@ -29706,8 +29768,7 @@ das ist eine Flag in der privaten Widget-Struktur. Keine Ahnung was das bedeutet.
Und übrigens: sichtbar muß das Widget auch noch sein...

- - +
@@ -29729,8 +29790,7 @@ also stellt eigentlich grade nicht die versprochene Logik bereit

- - +
@@ -29768,8 +29828,7 @@ danach noch die adjust_baseline_allocation

- - +
@@ -29808,8 +29867,7 @@ also entweder in horizontaler, oder in vertikaler Richtung

- - +