diff --git a/src/stage/timeline/clip-presenter.cpp b/src/stage/timeline/clip-presenter.cpp deleted file mode 100644 index a5aace080..000000000 --- a/src/stage/timeline/clip-presenter.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - ClipPresenter - presentation control element for a clip within the timeline - - Copyright (C) Lumiera.org - 2016, Hermann Vosseler - - 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 clip-presenter.cpp - ** Implementation details of clip 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 "stage/gtk-base.hpp" -#include "include/ui-protocol.hpp" -#include "stage/timeline/clip-presenter.hpp" -#include "stage/timeline/marker-widget.hpp" - -//#include "stage/ui-bus.hpp" -//#include "lib/format-string.hpp" -//#include "lib/format-cout.hpp" - -//#include "lib/util.hpp" - -//#include -//#include - - - -//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 stage { -namespace timeline { - - - - - /** - * @param identity referring to the corresponding session::Clip in Steam-Layer. - * @param nexus a way to connect this Controller to the UI-Bus. - * @param view (abstracted) canvas or display framework to attach this clip to - * @param timing (optional) start time point and duration of the clip. - * @note Clip can not be displayed unless #timing is given - */ - ClipPresenter::ClipPresenter (ID identity, ctrl::BusTerm& nexus, WidgetHook& view, optional const& timing) - : Controller{identity, nexus} - , channels_{} - , effects_{} - , markers_{} - , widget_{} - { - establishAppearance (&view, timing); - ENSURE (widget_); - } - - - ClipPresenter::~ClipPresenter() - { - } - - - - - void - ClipPresenter::buildMutator (TreeMutator::Handle buffer) - { - using PChannel = unique_ptr; - using PEffect = unique_ptr; - using PMarker = unique_ptr; - - 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(); - }) - .constructFrom ([&](GenNode const& spec) -> PMarker - { - return make_unique (spec.idi, this->uiBus_); - })) - .attach (collection(effects_) - .isApplicableIf ([&](GenNode const& spec) -> bool - { // »Selector« : require object-like sub scope with type-field "Effect" - return TYPE_Effect == spec.data.recordType(); - }) - .constructFrom ([&](GenNode const& spec) -> PEffect - { - std::optional timing = spec.retrieveAttribute (string{ATTR_timing}); - return make_unique (spec.idi, this->uiBus_ - ,getClipContentCanvas() - ,timing); - })) - .attach (collection(channels_) - .isApplicableIf ([&](GenNode const& spec) -> bool - { // »Selector« : require object-like sub scope with type-field "Channel" - return TYPE_Channel == spec.data.recordType(); - }) - .constructFrom ([&](GenNode const& spec) -> PChannel - { - return make_unique (spec.idi, this->uiBus_ - ,getClipContentCanvas() - ,std::nullopt); /////////////////////////TICKET #1213 : time → horizontal extension : how to represent "always" / "the whole track"?? - })) - .change(ATTR_name, [&](string val) - { // »Attribute Setter« : receive a new value for the clip name field - REQUIRE (widget_); - widget_->setClipName (val); - }) - .change(ATTR_timing, [&](TimeSpan val) - { - REQUIRE (widget_); - widget_->changeTiming (val); - }) - //-Diff-Change-Listener---------------- - .onLocalChange ([this]() - { - this->establishAppearance(); - })); - } - - - - void - ClipPresenter::establishAppearance (WidgetHook* newView, optional const& timing) - { - ClipDelegate::selectAppearance (this->widget_, defaultAppearance, newView, timing); - } - - WidgetHook& - ClipPresenter::getClipContentCanvas() - { - UNIMPLEMENTED ("how to create and wire an embedded canvas for the clip contents/effects"); - } - - uint - ClipPresenter::determineRequiredVerticalExtension() const - { - REQUIRE (widget_); - return widget_->calcRequiredHeight() - + widget_->getVerticalOffset(); - } - - void - ClipPresenter::relink() - { - REQUIRE (widget_); - widget_->updatePosition(); - } - - -}}// namespace stage::timeline diff --git a/src/stage/timeline/clip-presenter.hpp b/src/stage/timeline/clip-presenter.hpp index a1c52b535..bb2740d82 100644 --- a/src/stage/timeline/clip-presenter.hpp +++ b/src/stage/timeline/clip-presenter.hpp @@ -53,8 +53,10 @@ #define STAGE_TIMELINE_CLIP_PRESENTER_H #include "stage/gtk-base.hpp" +#include "include/ui-protocol.hpp" #include "stage/model/controller.hpp" #include "stage/timeline/clip-widget.hpp" +#include "stage/timeline/marker-widget.hpp" #include "stage/interact/cmd-context.hpp" #include "lib/time/timevalue.hpp" @@ -73,8 +75,9 @@ namespace timeline { using std::optional; using std::unique_ptr; using lib::time::TimeSpan; - - class MarkerWidget; + using lib::diff::TreeMutator; + using lib::diff::collection; + using std::make_unique; /** @@ -100,43 +103,136 @@ namespace timeline { public: - ClipPresenter (ID, ctrl::BusTerm&, WidgetHook&, optional const&); + /** + * @param identity referring to the corresponding session::Clip in Steam-Layer. + * @param nexus a way to connect this Controller to the UI-Bus. + * @param view (abstracted) canvas or display framework to attach this clip to + * @param timing (optional) start time point and duration of the clip. + * @note Clip can not be displayed unless #timing is given + */ + ClipPresenter (ID identity, ctrl::BusTerm& nexus, WidgetHook& view, optional const& timing) + : Controller{identity, nexus} + , channels_{} + , effects_{} + , markers_{} + , widget_{} + { + establishAppearance (&view, timing); + ENSURE (widget_); + } - ~ClipPresenter(); + ~ClipPresenter() { }; /** set up a binding to respond to mutation messages via UiBus */ - virtual void buildMutator (lib::diff::TreeMutator::Handle) override; + virtual void + buildMutator (TreeMutator::Handle buffer) override + { + using PChannel = unique_ptr; + using PEffect = unique_ptr; + using PMarker = unique_ptr; + + 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(); + }) + .constructFrom ([&](GenNode const& spec) -> PMarker + { + return make_unique (spec.idi, this->uiBus_); + })) + .attach (collection(effects_) + .isApplicableIf ([&](GenNode const& spec) -> bool + { // »Selector« : require object-like sub scope with type-field "Effect" + return TYPE_Effect == spec.data.recordType(); + }) + .constructFrom ([&](GenNode const& spec) -> PEffect + { + std::optional timing = spec.retrieveAttribute (string{ATTR_timing}); + return make_unique (spec.idi, this->uiBus_ + ,getClipContentCanvas() + ,timing); + })) + .attach (collection(channels_) + .isApplicableIf ([&](GenNode const& spec) -> bool + { // »Selector« : require object-like sub scope with type-field "Channel" + return TYPE_Channel == spec.data.recordType(); + }) + .constructFrom ([&](GenNode const& spec) -> PChannel + { + return make_unique (spec.idi, this->uiBus_ + ,getClipContentCanvas() + ,std::nullopt); /////////////////////////TICKET #1213 : time → horizontal extension : how to represent "always" / "the whole track"?? + })) + .change(ATTR_name, [&](string val) + { // »Attribute Setter« : receive a new value for the clip name field + REQUIRE (widget_); + widget_->setClipName (val); + }) + .change(ATTR_timing, [&](TimeSpan val) + { + REQUIRE (widget_); + widget_->changeTiming (val); + }) + //-Diff-Change-Listener---------------- + .onLocalChange ([this]() + { + this->establishAppearance(); + })); + } - /** find out the number of pixels necessary to render this clip properly, - * assuming its current presentation mode (abbreviated, full, expanded). + /** + * find out the number of pixels necessary to render this clip properly, + * assuming its current presentation mode (abbreviated, full, expanded). */ - uint determineRequiredVerticalExtension() const; + uint + determineRequiredVerticalExtension() const + { + REQUIRE (widget_); + return widget_->calcRequiredHeight() + + widget_->getVerticalOffset(); + } - /** update and re-attach the presentation widget into its presentation context. - * Will be called during the "re-link phase" of DisplayEvaluation, after the - * timeline layout has been (re)established globally. Often, this incurs - * attaching the presentation widget (ClipDelegate) at a different actual - * position onto the drawing canvas, be it due to a zoom change, or - * as result of layout re-flow. + /** + * update and re-attach the presentation widget into its presentation context. + * Will be called during the "re-link phase" of DisplayEvaluation, after the timeline layout + * has been (re)established globally. Often, this incurs attaching the presentation widget + * (ClipDelegate) at a different actual position onto the drawing canvas, be it due to a + * zoom change, or as result of layout re-flow. */ - void relink(); + void + relink() + { + REQUIRE (widget_); + widget_->updatePosition(); + } + private:/* ===== Internals ===== */ - - /** reevaluate desired presentation mode and available data, + /** + * reevaluate desired presentation mode and available data, * possibly leading to a changed appearance style of the clip. - * @remark a typical example would be, when a clip's temporal position, - * previously unspecified, now becomes defined through a diff message. - * With this data, it becomes feasible _actually to show the clip_ in - * the timeline. Thus the [Appearance style](\ref ClipDelegate::Appearance) - * of the presentation widget (delegate) can be switched up from `PENDING` - * to `ABRIDGED`. + * @remark a typical example would be, when a clip's temporal position, previously unspecified, + * now becomes defined through a diff message. With this data, it becomes feasible + * _actually to show the clip_ in the timeline. Thus the [Appearance style](\ref ClipDelegate::Appearance) + * of the presentation widget (delegate) can be switched up from `PENDING` to `ABRIDGED`. */ - void establishAppearance(WidgetHook* newView =nullptr, optional const& timing =nullopt); + void + establishAppearance(WidgetHook* newView =nullptr, + optional const& timing =nullopt) + { + ClipDelegate::selectAppearance (this->widget_, defaultAppearance, newView, timing); + } - WidgetHook& getClipContentCanvas(); + + WidgetHook& + getClipContentCanvas() + { + UNIMPLEMENTED ("how to create and wire an embedded canvas for the clip contents/effects"); + } }; diff --git a/src/stage/timeline/clip-widget.cpp b/src/stage/timeline/clip-widget.cpp index d6deb06ed..ebd909644 100644 --- a/src/stage/timeline/clip-widget.cpp +++ b/src/stage/timeline/clip-widget.cpp @@ -73,8 +73,8 @@ ** ** When especially the optional argument `timing` is provided by the _population diff_ ** creating the clip, then we can use the given lib::time::TimeSpan data for actually - ** allocating a screen rectangle, and thus only in this case, a ClipWidget is constructed - ** and mapped into presentation. + ** allocating a screen rectangle, and thus only when this condition is met (which should + ** be the default), a ClipWidget is constructed and mapped into presentation. ** ** Later the appearance style can be switched, which might incur the necessity also to ** exchange the actual implementation of the clip delegate. The latter is the case whenever diff --git a/src/stage/timeline/ruler-track.cpp b/src/stage/timeline/ruler-track.cpp index 676072401..285a91965 100644 --- a/src/stage/timeline/ruler-track.cpp +++ b/src/stage/timeline/ruler-track.cpp @@ -34,7 +34,6 @@ #include "stage/gtk-base.hpp" #include "stage/style-scheme.hpp" /////////////////////TODO needed? #include "stage/timeline/ruler-track.hpp" -#include "stage/timeline/track-presenter.hpp" //#include "stage/ui-bus.hpp" //#include "lib/format-string.hpp"