Timeline: make the Patchbay a Viewport container, to follow body scrolling

Gtk::Viewport allows to add the ability to scroll a partial view window
for a container larger than the available display area. The position
and movement of this window is controlled by Gtk::Adjustments,
which can be located elsewhere.

Here we use the existing Adjustments of the ScrolledWindow
holding the body canvas; this setup makes the header pane follow
the scroll movements of the body
This commit is contained in:
Fischlurch 2018-10-30 03:37:55 +01:00
parent 8803af1a0a
commit 0aa4a8cb42
8 changed files with 110 additions and 46 deletions

View file

@ -63,6 +63,9 @@
namespace gui {
namespace timeline {
using PAdjustment = Glib::RefPtr<Gtk::Adjustment>;
class TrackHeadWidget;
@ -78,10 +81,10 @@ namespace timeline {
public:
~HeaderPaneWidget() { }
HeaderPaneWidget()
HeaderPaneWidget (PAdjustment const& vScroll)
: Gtk::Box{Gtk::ORIENTATION_VERTICAL}
, navigator_{}
, patchbay_{}
, patchbay_{vScroll}
{
this->pack_start (navigator_, Gtk::PACK_SHRINK);
this->pack_start (patchbay_, Gtk::PACK_EXPAND_WIDGET);

View file

@ -32,7 +32,7 @@
#include "gui/gtk-base.hpp"
#include "gui/timeline/patchbay-widget.hpp"
#include "gui/timeline/track-head-widget.hpp"
//#include "gui/ui-bus.hpp"
//#include "lib/format-string.hpp"
//#include "lib/format-cout.hpp"
@ -46,6 +46,7 @@
//using util::_Fmt;
//using util::contains;
using Gtk::Adjustment;
//using Gtk::Widget;
//using sigc::mem_fun;
//using sigc::ptr_fun;
@ -63,25 +64,29 @@ namespace timeline {
PatchbayWidget::~PatchbayWidget() { }
PatchbayWidget::PatchbayWidget ()
: Gtk::Grid{}
/**
* Set up the patchbay area of the timeline UI.
* The patchbay is a container to hold the actual placement control widgets
* arranged alongside with each track, according to the nested track structure.
* The header pane and thus especially the patchbay needs to follow as a slave
* to the vertical scrolling adjustments of the Timeline display; if the users
* scrolls up or down over the more or less expanded tree of tracks, the header
* has to follow this scrolled display in sync. Thus the implementation of the
* patchbay is based on a Gtk::Viewport, which is attached to the vertical
* Gtk::Adjustment, as exposed by the Gtk::ScrolledWindow holding the
* timeline body canvas on the right side of the Timeline UI.
* @note the Patchbay is not scrollable in horizontal direction,
* thus we create a disabled Adjustment for this parameter.
*/
PatchbayWidget::PatchbayWidget (PAdjustment const& vScroll)
: Gtk::Viewport{Gtk::Adjustment::create (0,0,0,0,0,0), vScroll}
{ }
/**
* 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 four quadrants, and the 4th quadrant is the
* _content area,_ which is recursively extended to hold nested PatchbayWidget elements,
* corresponding to the child tracks of this track. To _fund_ this recursively extensible
* structure, we need to set up the first four quadrants
*/
void
PatchbayWidget::installFork (TrackHeadWidget& rootTrackHead)
{
UNIMPLEMENTED ("how actually to represent the track in the patchbay");
this->add (rootTrackHead);
}

View file

@ -22,22 +22,14 @@
/** @file patchbay-widget.hpp
** Widget to control the placement parameters of a fork within the timeline header pane UI.
** Widget to hold the track head controls within the timeline header pane UI.
** [The fork](\ref session::Fork), a recursively nested system of scopes, is rendered within
** the timeline display as a system of nested tracks. Each of these tracks possibly holds some
** child tracks plus some actual media clips, which all inherit parameters of placement from
** this fork ("track"). These parameters address various aspects of how content is attached
** ("placed") into the model at large, examples being
** - how to route the output
** - how to "place" this content into an _output space_, like e.g.
** + sound panning
** + video overlay parameters (additive, opaque, transparent)
** + video or audio _level_ (=fader)
** - how to locate this content in time (e.g. relative to some marker)
** For each track, we show a patchbay in the timeline header pane, which serves to control
** such aspects relevant for all content contained within the scope of this track.
** the timeline display as a system of nested tracks. For each of these tracks we get a header
** section, allowing to control its placement parameters, including start time, output routing
** level and panning. The _Patch Bay_ is the container holding all those track header controls,
** arranged into a recursively nested structure.
**
** @todo WIP-WIP-WIP as of 12/2016
** @todo WIP-WIP-WIP as of 10/2018
**
*/
@ -56,7 +48,9 @@
namespace gui {
namespace timeline {
using PAdjustment = Glib::RefPtr<Gtk::Adjustment>;
class TrackHeadWidget;
@ -68,13 +62,13 @@ namespace timeline {
* @todo WIP-WIP as of 12/2016
*/
class PatchbayWidget
: public Gtk::Grid
: public Gtk::Viewport
{
public:
PatchbayWidget();
PatchbayWidget (PAdjustment const& vScroll);
~PatchbayWidget();
/** @internal Initially install the contents corresponding to this track fork */
/** @internal Initially install the contents corresponding to the track fork root */
void installFork (TrackHeadWidget& rootTrackHead);
private:/* ===== Internals ===== */

View file

@ -63,8 +63,8 @@ namespace timeline {
TimelineLayout::TimelineLayout (Gtk::Paned& topLevelContainer)
: paneSplitPosition_{topLevelContainer.property_position()}
, headerPane_{}
, bodyCanvas_{}
, headerPane_{bodyCanvas_.get_vadjustment()} // wire the header pane (Gtk::Viewport) to follow the body vertical scroll movement
{
topLevelContainer.add1 (headerPane_);
topLevelContainer.add2 (bodyCanvas_);

View file

@ -110,8 +110,8 @@ namespace timeline {
{
Glib::PropertyProxy<int> paneSplitPosition_;
HeaderPaneWidget headerPane_;
BodyCanvasWidget bodyCanvas_;
HeaderPaneWidget headerPane_;
public:

View file

@ -22,8 +22,7 @@
/** @file track-head-widget.cpp
** Implementation details regarding display of the track heads
** within the timeline UI.
** Implementation details regarding display of the track heads within the timeline UI.
**
** @todo WIP-WIP-WIP as of 12/2016
**
@ -59,17 +58,32 @@ namespace timeline {
TrackHeadWidget::~TrackHeadWidget() { }
TrackHeadWidget::TrackHeadWidget ()
: Gtk::Grid{}
{
}
TrackHeadWidget::~TrackHeadWidget()
/**
* @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 four quadrants, and the 4th quadrant is the
* _content area,_ which is recursively extended to hold nested PatchbayWidget elements,
* corresponding to the child tracks of this track. To _fund_ this recursively extensible
* structure, we need to set up the first four quadrants
*/
void
TrackHeadWidget::injectSubFork (TrackHeadWidget& subForkHead)
{
UNIMPLEMENTED ("how actually to represent the track in the patchbay");
}
}}// namespace gui::timeline

View file

@ -22,10 +22,22 @@
/** @file track-head-widget.hpp
** Widget to represent a track head with placement control patchbay
** within Lumiera's timeline UI.
** Widget to represent a track head with placement parameters, within the timeline header pane.
** [The fork](\ref session::Fork), a recursively nested system of scopes, is rendered within
** the timeline display as a system of nested tracks. Each of these tracks possibly holds some
** child tracks plus some actual media clips, which all inherit parameters of placement from
** this fork ("track"). These parameters address various aspects of how content is attached
** ("placed") into the model at large, examples being
** - how to route the output
** - how to "place" this content into an _output space_, like e.g.
** + sound panning
** + video overlay parameters (additive, opaque, transparent)
** + video or audio _level_ (=fader)
** - how to locate this content in time (e.g. relative to some marker)
** For each track, we show a patchbay in the timeline header pane, which serves to control
** such aspects relevant for all content contained within the scope of this track.
**
** @todo WIP-WIP-WIP as of 12/2016
** @todo WIP-WIP-WIP as of 10/2018
**
*/
@ -47,14 +59,22 @@ namespace timeline {
/**
* Header pane control area corresponding to a Track with nested child Tracks.
* This structure is used recursively to build up the Fork of nested Tracks.
* - first row: Placement + Property pane
* - second row: content or nested tracks.
* @todo WIP-WIP as of 12/2016
*/
class TrackHeadWidget
: public Gtk::Grid
{
public:
TrackHeadWidget ();
~TrackHeadWidget();
/** Integrate the control area for a nested sub track fork. */
void injectSubFork (TrackHeadWidget& subForkHead);
private:/* ===== Internals ===== */
};

View file

@ -19088,9 +19088,12 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1540747470806" HGAP="97" ID="ID_831752558" MODIFIED="1540747508242" TEXT="Frage: wieviel Indirektion?" VSHIFT="5">
<node COLOR="#435e98" CREATED="1540747470806" HGAP="97" ID="ID_831752558" MODIFIED="1540866703223" TEXT="Frage: Patchbay vs TrackHead?" VSHIFT="5">
<icon BUILTIN="help"/>
<node CREATED="1540747516509" ID="ID_1965076800" MODIFIED="1540747526726" TEXT="ist TimelineHeaderWidget &#xfc;berfl&#xfc;ssig?"/>
<node CREATED="1540747516509" ID="ID_1965076800" MODIFIED="1540862756644" TEXT="ist TrackHeadWidget &#xfc;berfl&#xfc;ssig?">
<arrowlink COLOR="#6ba7db" DESTINATION="ID_415092517" ENDARROW="Default" ENDINCLINATION="-390;0;" ID="Arrow_ID_1346421423" STARTARROW="None" STARTINCLINATION="445;0;"/>
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1540747533463" ID="ID_1845120165" MODIFIED="1540747546555" TEXT="dann w&#xe4;re TimelineHeader == PatchbayWidget"/>
<node CREATED="1540747550734" ID="ID_843399235" MODIFIED="1540748388723" TEXT="macht Sinn...">
<richcontent TYPE="NOTE"><html>
@ -19108,6 +19111,31 @@
</html>
</richcontent>
</node>
<node CREATED="1540862631576" ID="ID_136673309" MODIFIED="1540862656534" TEXT="aber: Patchbay ist mehr als ein TrackHead">
<icon BUILTIN="yes"/>
<node CREATED="1540862657930" ID="ID_505897358" MODIFIED="1540862669986" TEXT="das Scrollen nicht vergessen">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1540862671211" ID="ID_1297724441" MODIFIED="1540862683893" TEXT="brauche eine Scroll-Pane ohne Scrolbar">
<node CREATED="1540862789523" ID="ID_1163137569" MODIFIED="1540862795073" TEXT="geht das?">
<icon BUILTIN="help"/>
<node CREATED="1540863135984" ID="ID_1095034635" MODIFIED="1540863144583" TEXT="wohl nicht direkt"/>
<node CREATED="1540863146507" ID="ID_1788133857" MODIFIED="1540863181887" TEXT="ScrolledWindow verwendet Gtk::Viewport">
<icon BUILTIN="idea"/>
</node>
</node>
<node CREATED="1540863578545" ID="ID_1986597218" LINK="https://developer.gnome.org/gtkmm-tutorial/stable/sec-adjustments-easy.html.en" MODIFIED="1540863596133" TEXT="Tutorial: separate Scrollbar f&#xfc;r TextView"/>
<node CREATED="1540863719920" ID="ID_1675657033" MODIFIED="1540863737439" TEXT="analog: das Adjustment von der BodyPane verwenden"/>
<node CREATED="1540863740331" ID="ID_432547471" MODIFIED="1540863760988" TEXT="und ein (passives) Adjustment f&#xfc;r horizontal"/>
<node COLOR="#338800" CREATED="1540866723618" ID="ID_943818911" MODIFIED="1540866732106" TEXT="sofort im ctor verdrahten">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1540862691920" ID="ID_415092517" MODIFIED="1540862773212" TEXT="das ist dann sinnvollerweise die Patchbay als Ganzes">
<linktarget COLOR="#6ba7db" DESTINATION="ID_415092517" ENDARROW="Default" ENDINCLINATION="-390;0;" ID="Arrow_ID_1346421423" SOURCE="ID_1965076800" STARTARROW="None" STARTINCLINATION="445;0;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
</node>