lumiera_documentation/src/gui/timeline/track-presenter.cpp
Ichthyostega c3d91d4ed3 Timeline: draft for building the nested recursive display structure
the solution idea is to use a helper frame, and an "anchor functor",
which is passed down from the respective parent context, and which
does the actual work of injecting the child widgets at the apropriate
position within the parent display.
2018-10-27 01:52:46 +02:00

160 lines
5.7 KiB
C++

/*
TrackPresenter - presentation control element for a track within the timeline
Copyright (C) Lumiera.org
2016, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file track-presenter.cpp
** Implementation details of track presentation management.
**
** @todo WIP-WIP-WIP as of 12/2016
** @todo as of 10/2018 timeline display in the UI is rebuilt to match the architecture
**
*/
#include "gui/gtk-base.hpp"
#include "include/ui-protocol.hpp"
#include "gui/timeline/track-presenter.hpp"
//#include "gui/ui-bus.hpp"
//#include "lib/format-string.hpp"
//#include "lib/format-cout.hpp"
//#include "lib/util.hpp"
//#include <algorithm>
//#include <vector>
//using util::_Fmt;
using lib::diff::TreeMutator;
using lib::diff::collection;
using std::make_unique;
//using util::contains;
//using Gtk::Widget;
//using sigc::mem_fun;
//using sigc::ptr_fun;
//using std::cout;
//using std::endl;
namespace gui {
namespace timeline {
TrackPresenter::~TrackPresenter()
{
}
/**
* @note we distinguish between the contents of our three nested child collections
* based on the symbolic type field sent in the Record type within the diff representation
* - "Marker" designates a Marker object
* - "Clip" designates a Clip placed on this track
* - "Fork" designates a nested sub-track
* @see TimelineController::buildMutator() for a basic explanation of the data binding mechanism
*/
void
TrackPresenter::buildMutator (TreeMutator::Handle buffer)
{
using PFork = unique_ptr<TrackPresenter>;
using PClip = unique_ptr<ClipPresenter>;
using PMarker = unique_ptr<MarkerWidget>;
buffer.create (
TreeMutator::build()
.attach (collection(markers_)
.isApplicableIf ([&](GenNode const& spec) -> bool
{ // »Selector« : require object-like sub scope with type-field "Marker"
return TYPE_Marker == spec.data.recordType();
})
.matchElement ([&](GenNode const& spec, PMarker const& elm) -> bool
{
return spec.idi == ID{*elm};
})
.constructFrom ([&](GenNode const& spec) -> PMarker
{
return make_unique<MarkerWidget> (spec.idi, this->uiBus_);
})
.buildChildMutator ([&](PMarker& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool
{
if (ID{*target} != subID) return false;
target->buildMutator (buff);
return true;
}))
.attach (collection(clips_)
.isApplicableIf ([&](GenNode const& spec) -> bool
{ // »Selector« : require object-like sub scope with type-field "Clip"
return TYPE_Clip == spec.data.recordType();
})
.matchElement ([&](GenNode const& spec, PClip const& elm) -> bool
{
return spec.idi == ID{*elm};
})
.constructFrom ([&](GenNode const& spec) -> PClip
{
return make_unique<ClipPresenter> (spec.idi, this->uiBus_);
})
.buildChildMutator ([&](PClip& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool
{
if (ID{*target} != subID) return false;
target->buildMutator (buff);
return true;
}))
.attach (collection(subFork_)
.isApplicableIf ([&](GenNode const& spec) -> bool
{ // »Selector« : require object-like sub scope with type-field "Fork"
return TYPE_Fork == spec.data.recordType();
})
.matchElement ([&](GenNode const& spec, PFork const& elm) -> bool
{
return spec.idi == ID{*elm};
})
.constructFrom ([&](GenNode const& spec) -> PFork
{
return make_unique<TrackPresenter> (spec.idi
,this->uiBus_
,[&](TrackHeadWidget& head,TrackBody& body)
{
display_.injectSubTrack (head, body);
});
})
.buildChildMutator ([&](PFork& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool
{
if (ID{*target} != subID) return false;
target->buildMutator (buff);
return true;
})));
}
}}// namespace gui::timeline