Lumiera
0.pre.03
»edit your freedom«
|
Go to the source code of this file.
Presentation control element to model and manage a track within the timeline UI.
In the Lumiera timeline UI, we are mixing two different scope of concerns: For one, we have the globally tangible scope of actual session elements and operations performed on those. And then there are more local considerations regarding the "mechanics" of the UI elements, their state and immediate feedback to user interactions. The Presenter – as known from the MVP pattern – serves as link between both levels. For the global angle of view, it is a model::Tangible and thus plays the role of the View, while the Model and Controller roles are mediated through the stage::UiBus, exchanging command, state and mutation messages. On the other hand, for the local angle of view, the Presenter is a structural model element, kind of a view model, and corresponds to the respective element within the session. In addition, it manages actively the collaborative part of layout building, delegating to a mostly passive GTK widget for the actual display. This way it becomes possible to manage the actual UI resources on a global level, avoiding to represent potentially several thousand individual elements as GTK entities, while at any time only a small number of elements can be visible and active as far as user interaction is concerned.
Each TrackPresenter corresponds to a "sub-Fork" of timeline tracks. Since Lumiera always arranges tracks as nested scopes into a tree, there is one root fork, recursively holding several sub forks.
Since TrackPresenter is a model::Tangible, a central concern is the ability to respond to diff messages. In fact, any actual content, including all the nested sub-structures, is populated through such mutation messages sent from the session up via the stage::UiBus. Thus, the TrackPresenter::buildMutator() implementation hooks up the necessary callbacks, to allow adding and removing of sub elements and properties of a track.
Another concern handled here is the coordination of layout and display activities. A special twist arises here: The track header ("patchbay") display can be designed as a classical tree / grid control, while the actual timeline body contents require us to perform custom drawing activities. Which leads to the necessity to coordinate and connect two distinct presentation schemes to form a coherent layout. We solve this challenge by introducing a helper entity, the DisplayFrame. These act as a bridge to hook into both display hierarchies (the nested TrackHeaderWidget and the TrackBody record managed by the BodyCanvasWidget). Display frames are hooked down from their respective parent frame, thereby creating a properly interwoven fabric.
After assembling the necessary GTK widgets, typically our custom drawing code will be invoked at some point, thereby triggering BodyCanvasWidget::maybeRebuildLayout(). At this point the timeline::TrackProfile needs to be established, so to reflect the succession and extension of actual track spaces running alongside the time axis. This is accomplished through a global timeline::DisplayEvaluation pass, recursively visiting all the involved parts to perform size adjustments, until the layout is globally balanced.
With respect to the TrackBody, the DisplayFrame within each Track acts as a relative attachment point and relative coordinate system; this is implemented as stage::model::RelativeCanvasHook. The top-level anchor point is established in the ctor of timeline::TimelineController, where the actual TimelineLayout is passed as parent CanvasHook; hinged below this anchor, each parent track acts as reference CanvasHook for the child tracks.
as of 10/2018 timeline display in the UI is rebuilt to match the architecture
as of 3/2023, the basic structure is settled and the design validated
Definition in file track-presenter.hpp.
#include "stage/gtk-base.hpp"
#include "include/ui-protocol.hpp"
#include "stage/model/view-hook.hpp"
#include "stage/model/controller.hpp"
#include "stage/timeline/display-evaluation.hpp"
#include "stage/timeline/marker-widget.hpp"
#include "stage/timeline/clip-presenter.hpp"
#include "stage/timeline/track-head-widget.hpp"
#include "stage/timeline/track-body.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/iter-explorer.hpp"
#include "lib/util-coll.hpp"
#include "lib/nocopy.hpp"
#include <optional>
#include <utility>
#include <vector>
Classes | |
class | DisplayFrame |
Reference frame to organise the presentation related to a specific Track in the Timeline-GUI. More... | |
class | RelativeCanvasHook< WID > |
Special CanvasHook decorator to apply a (dynamic) offset when attaching or moving Widgets on the shared canvas. More... | |
class | TrackPresenter |
A View-Model entity to represent a timeline track in the UI. More... | |
Typedefs | |
using | PClip = unique_ptr< ClipPresenter > |
using | PFork = unique_ptr< TrackPresenter > |
using | PMark = unique_ptr< MarkerWidget > |
using | PRuler = unique_ptr< RulerTrack > |
Namespaces | |
stage | |
Lumiera GTK UI implementation root. | |
stage::timeline | |
The timeline display and editing operations. | |