Timeline: add the typical framework for custom drawing on the canvas

see gtk-canvas-experiment.cpp
This commit is contained in:
Fischlurch 2018-12-06 23:41:28 +01:00
parent 615796d812
commit ad9043ae1d
6 changed files with 125 additions and 23 deletions

View file

@ -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<Cairo::Context> 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<Cairo::Context> 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<Cairo::Context> 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<Cairo::Context> 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<Cairo::Context> 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
}

View file

@ -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<Cairo::Context> const&) override;
void openCanvas (Cairo::RefPtr<Cairo::Context> const&);
void closeCanvas (Cairo::RefPtr<Cairo::Context> const&);
void drawGrounding (Cairo::RefPtr<Cairo::Context> const&);
void drawOverlays (Cairo::RefPtr<Cairo::Context> const&);
};

View file

@ -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
**

View file

@ -66,7 +66,7 @@ namespace timeline {
TrackBody::TrackBody()
: overviewHeight_{DEFAULT_OVERVIEW_HEIGHT_px}
, contentHeight_{DEFAULT_OVERVIEW_HEIGHT_px}
, contentHeight_{DEFAULT_CONTENT_HEIGHT_px}
, subTracks_{}
{ }

View file

@ -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
*/

View file

@ -19423,8 +19423,7 @@
...in dem der Timeline body-canvas n&#228;mlich liegt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
@ -19577,7 +19576,7 @@
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1540640109628" ID="ID_147809215" MODIFIED="1540640128945" TEXT="TODO: TimelineGui (proxy) mu&#xdf; kaskadieren">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1544135984042" ID="ID_429363053" MODIFIED="1544310842213" TEXT="Grund f&#xfc;r den Fehler im Nexus?">
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1544135984042" ID="ID_429363053" MODIFIED="1544136004274" TEXT="Grund f&#xfc;r den Fehler im Nexus?">
<richcontent TYPE="NOTE"><html>
<head>
@ -21297,7 +21296,7 @@
<node CREATED="1541860174509" ID="ID_983216306" MODIFIED="1541860194622" TEXT="position within window">
<node CREATED="1541860195426" ID="ID_1143510761" MODIFIED="1541860197638" TEXT="relative"/>
<node CREATED="1541860198222" ID="ID_847832000" MODIFIED="1541860200197" TEXT="absolute">
<node CREATED="1544126105472" ID="ID_1636490570" MODIFIED="1544310842664" TEXT="relative-absolute">
<node CREATED="1544126105472" ID="ID_1636490570" MODIFIED="1544126149549" TEXT="relative-absolute">
<richcontent TYPE="NOTE"><html>
<head>
@ -21319,7 +21318,7 @@
</node>
<node CREATED="1542384160498" ID="ID_1252241860" MODIFIED="1542384163677" TEXT="TimeWindow">
<node CREATED="1542384165737" ID="ID_705415129" MODIFIED="1542384177115" TEXT="die konkret sichbare TimeSpan"/>
<node CREATED="1542384188438" ID="ID_444895141" MODIFIED="1544310842677" TEXT="stets in realem relativem Zeitma&#xdf;">
<node CREATED="1542384188438" ID="ID_444895141" MODIFIED="1542384280140" TEXT="stets in realem relativem Zeitma&#xdf;">
<richcontent TYPE="NOTE"><html>
<head>
@ -21334,8 +21333,7 @@
</li>
</ul>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1541859633805" ID="ID_304890799" MODIFIED="1541859637628" TEXT="Scale">
@ -21383,7 +21381,7 @@
<node CREATED="1541860828603" ID="ID_111513506" MODIFIED="1541860839002" TEXT="Zeit"/>
<node CREATED="1541860831875" ID="ID_1775831703" MODIFIED="1541860835311" TEXT="Extension"/>
</node>
<node CREATED="1541860818012" FOLDED="true" ID="ID_814200290" MODIFIED="1541860825864" TEXT="vertikale Dimension stets topologisch">
<node CREATED="1541860818012" FOLDED="true" ID="ID_814200290" MODIFIED="1544127129504" TEXT="vertikale Dimension stets topologisch">
<node CREATED="1544127119809" ID="ID_431805088" MODIFIED="1544127122858" TEXT="nicht immer...."/>
<node CREATED="1544127123803" ID="ID_1360167609" MODIFIED="1544127127665" TEXT="Ausnahme: Kurven"/>
</node>
@ -40734,8 +40732,7 @@
...also <i>abz&#252;glich</i>&#160;Dekoration und Margin
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1542308990570" ID="ID_1371068296" MODIFIED="1542309000371" TEXT="stets komplett in der zugewiesenen Allocation enthalten"/>
</node>