From 8c0b3258cb9c012f58aa9ee8c4f9d3a9933a0a1f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 21 Aug 2019 17:48:25 +0200 Subject: [PATCH] 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) --- src/stage/timeline/body-canvas-widget.cpp | 21 +- src/stage/timeline/body-canvas-widget.hpp | 1 + src/stage/timeline/track-body.cpp | 4 +- wiki/renderengine.html | 28 ++- wiki/thinkPad.ichthyo.mm | 246 +++++++++++++++++----- 5 files changed, 237 insertions(+), 63 deletions(-) diff --git a/src/stage/timeline/body-canvas-widget.cpp b/src/stage/timeline/body-canvas-widget.cpp index b797b3757..62bb6dbb4 100644 --- a/src/stage/timeline/body-canvas-widget.cpp +++ b/src/stage/timeline/body-canvas-widget.cpp @@ -377,8 +377,7 @@ namespace timeline { { // for the initial empty canvas -- use all space the enclosing scrolled window got. auto currSize = get_allocation(); int height = currSize.get_height(); - rulerCanvas_.set_size (currSize.get_width(), INITIAL_TIMERULER_HEIGHT_px); - mainCanvas_.set_size (currSize.get_width(), max(0, height-INITIAL_TIMERULER_HEIGHT_px)); + adjustCanvasHeight(currSize.get_width(), height, INITIAL_TIMERULER_HEIGHT_px); } // realise all initially configured elements.... @@ -421,11 +420,29 @@ namespace timeline { if (rootBody_ and isnil (profile_)) { layout_.triggerDisplayEvaluation(); + TODO("retrieve the vertical extension established by the triggerDisplayEvaluation() "); +// adjustCanvasHeight(currSize.get_width(), height, INITIAL_TIMERULER_HEIGHT_px); //////////////////////////TODO rootBody_->establishTrackSpace (profile_); } } + /** + * After the (recent) [display evaluation pass](\ref DisplayManager::triggerDisplayEvaluation() ) + * 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 + */ + void + BodyCanvasWidget::adjustCanvasHeight(int canvasWidth, int totalHeight, int rulerHeight) + { + rulerCanvas_.set_size (canvasWidth, rulerHeight); + mainCanvas_.set_size (canvasWidth, max(0, totalHeight-rulerHeight)); + } + + + diff --git a/src/stage/timeline/body-canvas-widget.hpp b/src/stage/timeline/body-canvas-widget.hpp index d592094f1..3ad3e11f0 100644 --- a/src/stage/timeline/body-canvas-widget.hpp +++ b/src/stage/timeline/body-canvas-widget.hpp @@ -136,6 +136,7 @@ namespace timeline { void slotStructureChange() noexcept; void maybeRebuildLayout(); + void adjustCanvasHeight(int canvasWidth, int totalHeight, int rulerHeight); }; diff --git a/src/stage/timeline/track-body.cpp b/src/stage/timeline/track-body.cpp index d375f9fb8..2f749ffee 100644 --- a/src/stage/timeline/track-body.cpp +++ b/src/stage/timeline/track-body.cpp @@ -121,7 +121,7 @@ namespace timeline { * recursively establish the screen space allocation for this structure of nested tracks. * The TrackProfile is an abstracted description of the sequence of track elements, * which constitute a vertical cross section through the track bodies - * - pre: the given profile is built and complete up to the (upper side) start of this timeline + * - pre: the given profile is built and complete up to the (upper side) start of the current track. * - post: the profile is elaborated for this track and its children, down to the lower end. * @todo 6/19 this very much looks like the "display evaluation pass" envisioned for the timeline::DisplayManager. * Need to find out if we'll need a dedicated evaluation pass and how to interconnect both. @@ -135,7 +135,7 @@ namespace timeline { // global setup for the profile profile.append_prelude(); - // Profile elements are always visible on top: + // The first Profile elements are always visible on top: // Top-level rules and one additionally for the prelude profile.pinnedPrefixCnt = 1 + rulers_.size(); } diff --git a/wiki/renderengine.html b/wiki/renderengine.html index f44824ea0..075a8bd63 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
@@ -3545,6 +3545,32 @@ The actual expression of these elements depends on the content, which is injecte
 | | | !__Track-11__ |>|>|>|>|!__Track-12__ | |
 |~|~|>|  | |!__Track-121__ |!__Track-122__ | |~|
 |r(1),r(1),g,''c''(2)|⤵|r(1),g,''c''(3)|r(1),g,r(1)|⤵|r(1),''c''(2)  |r(1),''c''(1)|⤴|⤴|
+
+
+!!!Drawing strategy
+Once the fundamental decision towards a 3D structure is taken, there still is some room for choices regarding the actual strategy to perform the drawing primitives. However, there are also known limitations in what can be achieved by shading within an essentially flat drawing (unless we'll get some kind of holographic display technology at our disposal, somewhere in the future). The point to note is, we can not convey a fully three dimensional structure merely through shading -- rather we can only imply //local depth relations.// And since the actual structure of our nested tracks can be quite elaborate and wide spanning, we should focus on expressing such local relations, in order to support the user and help to grasp the presented structure.
+* shading can indicate a //barrier.//
+* shading can indicate a //slope// up or down.
+An immediate consequence to draw from this observation is that ~CSS3 effects are only of limited use for this purpose. They are more helpful to highlight compact and local structures, like a menu button, or some element or handle on the clips. We can (and likely will) use CSS shading for the [[track overview rulers|TrackRuler]] though. We possibly could use a slight inset box shadow within the actual track content area. However, it is rather pointless to use a box shadow to paint the nested track scope insets -- we rather need to rely on gradients and direct colour shading for that purpose.
+
+Another consequence  is that we do not need to apply an overall "stacked boxes" approach -- there is not much to gain from doing so (and we would do a lot of unnecessary filling operations, most of which will actually clipped away). For that reason, we define our ''track profile'' to represent a vertical //top-down drawing sweep.// Non the less, the actual colours and shades can be defined completely through CSS rules. To achieve this, we apply some tricks
+* we define //virtual widgets,// which are only used to match against selectors and pick up the attached CSS styles
+** the virtual element {{{fork}}} represents "a timeline track"
+** and a virtual {{{frame}}} element nested therein represents "a ruler on top of a timeline track"
+* this leads to the following selectors to attach the actual styling rules
+*;track fork
+*:attach rules to the selector {{{.timeline__page > .timeline__body fork.timeline__fork}}}
+*:* the {{{border top}}} and {{{border bottom}}} rules will be used to //draw the nested inset.//
+*:* a {{{margin}}} at top will add additional space between consecutive tracks
+*:* while the {{{padding}}} will be used within the track content area -- <br/> of course only in vertical direction, since the horizontal extension is ruled by the time position of elements within the track
+*:* please note that {{{background}}} stylings apply to the //content area// and not the track space at a whole.
+*;track ruler
+*:attach rules to the selector{{{fork.timeline__fork frame.timeline__ruler}}}
+*:* again the {{{border top}}} and {{{border bottom}}} settings will delimit the ruler form the other track content
+*:* while {{{margin}}} and {{{padding}}} apply as usual outside and within the border
+*:* here the {{{box shadow}}} will be drawn with the background -- however, only an {{{inset}}} makes sense here,<br/>since a regular (outer) box shadow will be covered by consecutive drawing actions, unless it sticks within the limits of the {{{margin}}}
+
+Please note also that our drawing code operates in several ''passes''. First, a ''background'' pass is used to fill the area, then GTK is invoked recursively for any widgets on the dawing canvas, most notably the ''clips''. Then, a final ''overlay'' pass allows to paint range markers, selections and indicators on top.
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index dcb92b637..a95646635 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -19392,8 +19392,8 @@ - + @@ -19453,8 +19453,7 @@ aber die tatsächliche Neuberechnung erfolgt erst spät, und bei Bedarf

- - + @@ -19470,8 +19469,7 @@ muß nach GTK's Behandlung gemacht werden

- - + @@ -19488,8 +19486,7 @@ Grundlagen müssen vor GTK's Behandlung erfolgen

- - + @@ -19514,8 +19511,7 @@ die Teilelements speichern ihren Wert

- - +
@@ -19527,8 +19523,7 @@ Zeichencode verwendet diesen

- -
+
@@ -21867,6 +21862,98 @@
+ + + + + + + + + + + + + + + + +

+ manchmal ist die alte Lösung besser +

+ + +
+ + + + + + + +

+ die Idee einer graphischen Benutzeroberfläche hat sich über die 60er / 70er-Jahre herausgebildet. +

+

+ Nachdem die Idee einmal gefaßt ist, gibt es nur noch Oberflächendifferenzierung. +

+

+ Und letztere neigt stets zur "Verschlimmbesserung" +

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

+ gestapelte Strukturen dieser Komplexität lassen sich nicht durch Schattierung vermitteln. +

+

+ Wohl aber lassen sich lokale Nachbarschafts-Beziehungen (höhe / tiefer) durch Schattierung hervorheben +

+ + +
+
+ + + + + + +

+ und zwar im Wesentliche zur Schattierung der Flanken. +

+

+ Die Inhalts-Flächen selber sind zu groß und zu strukturiert, um sie per Schattierung zu verdeutlichen +

+ + +
+
+
+
@@ -22604,6 +22691,13 @@ + + + + + + +
@@ -22848,8 +22942,7 @@ - - +
@@ -22865,14 +22958,49 @@ der GTK-Zeichencode achtet sogar explizit darauf, einen CSS-Effekt mit dem korrekten Mischmodus über den bereits auf den CairoCanvas gezeichneten Content zu legen

+ +
+
+ + + + + + +

+ und zwar für bestimmte Elemente (Konvention) +

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

+ weil über alles andere darübergezeichnet wird +

+
+ - - - - + + + + + + + @@ -22887,8 +23015,7 @@ den Zeichenvorgang für ein normales Frame-Widget analysieren

- - + @@ -22905,8 +23032,7 @@ Kommentar sagt: it is your responsibility that these two coordinates match

- - +
@@ -22934,8 +23060,7 @@ /home/hiv/.local/share/themes/PanRosewoodHIV/gtk-3.0/gtk-contained.css

- - + @@ -22965,8 +23090,7 @@   border: 1px solid @borders; }

- -
+
@@ -22978,8 +23102,7 @@   box-shadow: inset 0px 0px 0px 1px shade (@theme_bg_color, 1.15), 0px 1px 2px rgba(0, 0, 0, 0.1); }

- -
+
@@ -23014,8 +23137,7 @@ herausfinden, warum er solid gezeichnet wird

- - + @@ -23044,8 +23166,7 @@ - - + @@ -23077,8 +23198,7 @@ }

- - +
@@ -23115,8 +23235,7 @@ weil er dann mehr oder weniger hartverdrahtet ist

- - +
@@ -23311,8 +23430,7 @@ Und der Oberpragmatiker generiert den ganzen Müllhaufen dann per SASS order SCSS

- - +
@@ -23334,8 +23452,7 @@ dann führt ein context_save() dazu, daß plötzlich die CSS-Werte auf Defaults zurückspringen

- - +
@@ -23353,8 +23470,7 @@ Allerdings hat es bisher auch ohne das bei mir funktioniert.

- -
+
@@ -23418,8 +23534,7 @@ allerdings verhält sich das normale Zeichnen ganz genauso; das sind allgemeine Einschränkungen (von CSS? GTK?)

- - +
@@ -23442,8 +23557,7 @@ box-shadow (inset) innerhalb des Rechteckss, und innerhalb der (gedachten) border

- - +
@@ -23456,8 +23570,30 @@ - + + + + + + + + +

+ weil die CSS-box-shadow-Effekte zum Zeichnen komplexerer Strukturen nur bedingt nützlich sind. +

+

+ Daher verzichte ich global (für die Slopes) darauf, wende sie aber lokal  an +

+ + +
+ +
+
+ + + @@ -45084,8 +45220,7 @@ d.h. die angegebenen Abmessungen entsprechen der bounding box

- - +
@@ -45109,8 +45244,7 @@ in diesem Falle würde die linke Border mit der geerben Farbe gezeichnet, und nicht gelb

- -
+
@@ -45129,8 +45263,7 @@ <offX> <offY> [<blur> [<spread>]] <colour>

- - +
@@ -45191,8 +45324,7 @@ automatisch eine höhere Priorität haben, als das, was sich aus den Path-match ergibt

- - +
@@ -45222,8 +45354,7 @@ Man muß also genügend Platz allozieren für border-top-width + border-bottom-width + gewünschter Content!

- -
+
@@ -46404,8 +46535,7 @@ This function is only used by Gtk::Container subclasses, to assign a size, position and (optionally) baseline to their child widgets.

- - +