From ad9043ae1d3438338364523938b888b682a13f73 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 6 Dec 2018 23:41:28 +0100 Subject: [PATCH] Timeline: add the typical framework for custom drawing on the canvas see gtk-canvas-experiment.cpp --- src/stage/timeline/body-canvas-widget.cpp | 102 +++++++++++++++++++++- src/stage/timeline/body-canvas-widget.hpp | 21 +++-- src/stage/timeline/timeline-layout.hpp | 4 +- src/stage/timeline/track-body.cpp | 2 +- src/stage/timeline/track-body.hpp | 2 +- wiki/thinkPad.ichthyo.mm | 17 ++-- 6 files changed, 125 insertions(+), 23 deletions(-) diff --git a/src/stage/timeline/body-canvas-widget.cpp b/src/stage/timeline/body-canvas-widget.cpp index c8a8621df..8d57dccb9 100644 --- a/src/stage/timeline/body-canvas-widget.cpp +++ b/src/stage/timeline/body-canvas-widget.cpp @@ -77,12 +77,12 @@ namespace timeline { this->property_expand() = true; // dynamically grab any available additional space this->add(canvas_); - { // for the initial empty canvas -- use space the enclosing scrolled window got. + { // for the initial empty canvas -- use all space the enclosing scrolled window got. auto currSize = get_allocation(); canvas_.set_size (currSize.get_width(), currSize.get_height()); } - // show everything.... + // realise all initially configured elements.... this->show_all(); } @@ -101,7 +101,103 @@ namespace timeline { { canvas_.rootBody_ = &rootTrackBody; } - + + + /** + * Custom drawing of the timeline content area. + * The inherited `Gtk::Layout::on_raw(Context)` handles all drawing of child widgets placed onto the virtual canvas. + * Thus we need to fill in the structure of the tracks in the timeline background, and any non-standard overlay elements, + * including tags and markers, indicators, locators (edit point and playhead) and (semi-transparent) range selections. + * @todo according to the documentation for `signal_draw()`, the framework passes the actually visible area as clipping + * region. In theory, this information could be used to reduce the load of canvas painting and repainting, which + * becomes crucial for responsiveness on large sessions ////////////////////////////////////TICKET #1191 + */ + bool + TimelineCanvas::on_draw (Cairo::RefPtr const& cox) + { + // draw track structure behind all widgets + openCanvas (cox); + drawGrounding (cox); + closeCanvas (cox); + + // cause child widgets to be redrawn + bool event_is_handled = Gtk::Layout::on_draw(cox); + + // draw dynamic markers and locators on top + openCanvas (cox); + drawOverlays (cox); + closeCanvas (cox); + + return event_is_handled; + } + + + /** + * Prepare the drawing canvas to work within our virtual canvas coordinate system. + * @remarks GTK passes a context related to the actual window area; however, we need to create + * a uniform virtual canvas, shared by the child widgets, the backgrounding and any overlays. + * To make this work, we have to connect to the scrollbar adjustments, since GTK does this + * only for the child widgets on the canvas, not for any custom painting. + */ + void + TimelineCanvas::openCanvas (Cairo::RefPtr const& cox) + { + auto adjH = get_hadjustment(); + auto adjV = get_vadjustment(); + double offH = adjH->get_value(); + double offV = adjV->get_value(); + + cox->save(); + cox->translate(-offH, -offV); + } + + + /** + * Finish and close the virtual drawing canvas established by #openCanvas(). + * Discard any coordinate offsets, stroke and drawing settings applied within. + */ + void + TimelineCanvas::closeCanvas (Cairo::RefPtr const& cox) + { + cox->restore(); + } + + + /** + * Establish and render the structure of (possibly nested) tracks and overview rulers. + * @param cox cairo drawing context for custom drawing, adjusted for our virtual canvas. + */ + void + TimelineCanvas::drawGrounding (Cairo::RefPtr const& cox) + { + /////////////////////////////////////////////TICKET #1139 : placeholder drawing + cox->set_source_rgb(0.8, 0.0, 0.0); + cox->set_line_width (5.0); + cox->rectangle(0,0, 80, 40); + cox->stroke(); + /////////////////////////////////////////////TICKET #1139 : placeholder drawing + } + + + /** + * + * @param cox cairo drawing context of the virtual canvas for custom drawing. + */ + void + TimelineCanvas::drawOverlays (Cairo::RefPtr const& cox) + { + /////////////////////////////////////////////TICKET #1139 : placeholder drawing + auto alloc = get_allocation(); + int w = alloc.get_width(); + int h = alloc.get_height(); + int rad = MIN (w,h) / 2; + + cox->set_source_rgb(0.2, 0.4, 0.9); // blue + cox->set_line_width (2.0); + cox->arc(rad, rad, rad, 0.0, 2.0*M_PI); // full circle + cox->stroke(); + /////////////////////////////////////////////TICKET #1139 : placeholder drawing + } diff --git a/src/stage/timeline/body-canvas-widget.hpp b/src/stage/timeline/body-canvas-widget.hpp index 932a8cb57..95e87ac3c 100644 --- a/src/stage/timeline/body-canvas-widget.hpp +++ b/src/stage/timeline/body-canvas-widget.hpp @@ -31,13 +31,13 @@ ** on top of Gtk::Layout, allows to combine _custom drawing_ with the placement of ** embedded child widgets, where the latter's layout is again managed automatically ** by the toolkit set. This approach allows us to circumvent some of the perils of - ** custom drawing, where we might forfeit several of the benefits of using a toolkit - ** unintentionally, and create an UI which feels foreign and brittle in comparison - ** to standard software. + ** custom drawing, where we might forfeit several of the benefits of using a toolkit, + ** unintentionally of course, and create an UI which feels foreign and brittle + ** in comparison to standard software. ** ** # Layout management ** - ** To create a consistent layout of the timeline, header pane and body need to react + ** To create a consistent timeline layout, the header pane and body need to react ** to the same scrolling adjustments, and use the same vertical size allocations for ** each embedded track. Such a consistent global layout needs to be built up in a ** *display evaluation pass*, carried out collaboratively between the building blocks @@ -45,8 +45,8 @@ ** as (view) model entities, visited by the timeline::LayoutManager to establish ** coherent display parameters. From within this evaluation pass, the individual ** presenters communicate with their _slave widgets,_ which are inserted into the - ** display context of the track header pane or this body widget respectively. As - ** a result, some new widgets may be injected, existing widgets may be removed or + ** display context of the track header pane or into this body widget respectively. + ** As result, some new widgets may be injected, existing widgets might be removed or ** hidden, and other widgets may be relocated to different virtual canvas coordinates. ** ** @todo WIP-WIP-WIP as of 12/2016 @@ -79,6 +79,15 @@ namespace timeline { TrackBody* rootBody_; TimelineCanvas(); + + private: + virtual bool on_draw (Cairo::RefPtr const&) override; + + void openCanvas (Cairo::RefPtr const&); + void closeCanvas (Cairo::RefPtr const&); + + void drawGrounding (Cairo::RefPtr const&); + void drawOverlays (Cairo::RefPtr const&); }; diff --git a/src/stage/timeline/timeline-layout.hpp b/src/stage/timeline/timeline-layout.hpp index a070f2fff..155c2e07f 100644 --- a/src/stage/timeline/timeline-layout.hpp +++ b/src/stage/timeline/timeline-layout.hpp @@ -51,8 +51,8 @@ ** Thus we strive to break up the whole process of controlling the layout into several ** local concerns, each of which can be made self contained. The backbone is formed by ** a recursive collaboration between two abstractions (interfaces) - ** - the building blocks of the timeline expose the interface timeline::Element - ** - the global timeline widget implements a timeline::LayoutManager interface + ** - the building blocks of the timeline expose the interface timeline::Element (TODO 12/18 really?) + ** - the global timeline widget implements a timeline::LayoutManager interface (TODO 12/18 work out the crucial point of that interface!) ** ** ## Display evaluation pass ** diff --git a/src/stage/timeline/track-body.cpp b/src/stage/timeline/track-body.cpp index 8b297dbbc..e2241240b 100644 --- a/src/stage/timeline/track-body.cpp +++ b/src/stage/timeline/track-body.cpp @@ -66,7 +66,7 @@ namespace timeline { TrackBody::TrackBody() : overviewHeight_{DEFAULT_OVERVIEW_HEIGHT_px} - , contentHeight_{DEFAULT_OVERVIEW_HEIGHT_px} + , contentHeight_{DEFAULT_CONTENT_HEIGHT_px} , subTracks_{} { } diff --git a/src/stage/timeline/track-body.hpp b/src/stage/timeline/track-body.hpp index 3f05000ed..1bb2bddad 100644 --- a/src/stage/timeline/track-body.hpp +++ b/src/stage/timeline/track-body.hpp @@ -64,7 +64,7 @@ namespace timeline { * A given TrackBody works with coordinates relative to its vertical starting point; * coordinates on the TimelineCanvas operate from top downwards. The fundamental * task of a TrackBody is to find out about its own overall height, including the - * overall height require by all its nesting children. Moreover, the height of + * overall height required by all its nested children. Moreover, the height of * the content area needs to be negotiated with the actual content elements. * @todo WIP-WIP as of 10/2018 */ diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index ae52c8a18..0ca780a1c 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -19423,8 +19423,7 @@ ...in dem der Timeline body-canvas nämlich liegt

- - + @@ -19577,7 +19576,7 @@ - + @@ -21297,7 +21296,7 @@ - + @@ -21319,7 +21318,7 @@ - + @@ -21334,8 +21333,7 @@ - - + @@ -21383,7 +21381,7 @@ - + @@ -40734,8 +40732,7 @@ ...also abzüglich Dekoration und Margin

- - +