Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
track-presenter.hpp
Go to the documentation of this file.
1/*
2 TRACK-PRESENTER.hpp - presentation control element for a track within the timeline
3
4 Copyright (C)
5 2016, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
87#ifndef STAGE_TIMELINE_TRACK_PRESENTER_H
88#define STAGE_TIMELINE_TRACK_PRESENTER_H
89
90#include "stage/gtk-base.hpp"
100#include "lib/iter-explorer.hpp"
101#include "lib/util-coll.hpp"
102
103#include "lib/nocopy.hpp"
104
105#include <optional>
106#include <utility>
107#include <vector>
108
109
110
111namespace stage {
112namespace timeline {
113
114 using std::vector;
115 using std::unique_ptr;
116 using std::make_unique;
117
120 using lib::diff::collection;
121 using lib::explore;
122 using util::max;
123
124
125
137 template<class WID>
139 : public model::CanvasHook<WID>
140 {
142
143
144 /* ==== Interface: ViewHook ===== */
145
146 void
147 hook (WID& widget, int xPos=0, int yPos=0) override
148 {
149 refHook_.hook (widget, hookAdjX (xPos), hookAdjY (yPos));
150 }
151
152 void
153 move (WID& widget, int xPos, int yPos) override
154 {
155 refHook_.move (widget, hookAdjX (xPos), hookAdjY (yPos));
156 }
157
158 void
159 remove (WID& widget) override
160 {
161 refHook_.remove (widget);
162 }
163
166 getAnchorHook() noexcept override
167 {
168 return this->refHook_;
169 }
170
171 protected: /* === extended Interface for relative canvas hook === */
172 virtual int hookAdjX (int xPos) =0;
173 virtual int hookAdjY (int yPos) =0;
174
177 getMetric() const override
178 {
179 return refHook_.getMetric();
180 }
181
182 public:
186 };
187
188
189
190 using PFork = unique_ptr<TrackPresenter>;
191 using PClip = unique_ptr<ClipPresenter>;
192 using PMark = unique_ptr<MarkerWidget>;
193 using PRuler = unique_ptr<RulerTrack>;
194
206 , public DisplayViewHooks
207 , public RelativeCanvasHook<Gtk::Widget>
208 {
211
212 /* === extended Interface for relative view/canvas hook === */
213
214 int hookAdjX (int xPos) override { return xPos; };
215 int hookAdjY (int yPos) override { return yPos + body_.getContentOffsetY(); };
216
217 public: /* ==== Interface: DisplayViewHooks===== */
218
221 model::CanvasHook<Gtk::Widget>& getClipHook() override { return *this; };
222
223 public:
225 : RelativeCanvasHook{displayAnchor.getClipHook()}
226 , head_{displayAnchor.getHeadHook()}
227 , body_{displayAnchor.getBodyHook()}
228 { }
229
230 void
232 {
233 head_.setTrackName (name);
234 body_.setTrackName (name);
235 }
236
237 vector<unique_ptr<RulerTrack>>&
239 {
240 return body_.bindRulers();
241 }
242
243 void establishExtension (vector<PClip>&, vector<PMark>&);
245 };
246
247
253 : public model::Controller
254 , public LayoutElement
255 {
257
258 vector<PFork> subFork_;
259 vector<PMark> markers_;
260 vector<PClip> clips_;
261
262
263 public:
269 TrackPresenter (ID id, ctrl::BusTerm& nexus, DisplayViewHooks& displayAnchor)
270 : Controller{id, nexus}
271 , display_{displayAnchor}
272 , subFork_{}
273 , markers_{}
274 , clips_{}
275 {
276 setTrackName (id.getSym()); // fallback initialise track-name from human-readable ID symbol
277 }
278
279
281 virtual void buildMutator (lib::diff::TreeMutator::Handle) override;
282
283
284 protected: /* ==== Interface: LayoutElement ===== */
285
286 void establishLayout (DisplayEvaluation&) override;
287 void completeLayout (DisplayEvaluation&) override;
288
289 private:/* ===== Internals ===== */
290
292 void
293 setTrackName (string name)
294 {
295 display_.setTrackName (name);
296 }
297
298 void relinkContents ();
299 };
300
301
302
303
313 inline void
315 {
316 buffer.emplace(
318 .attach (collection(display_.bindRulers())
319 .isApplicableIf ([&](GenNode const& spec) -> bool
320 { // »Selector« : require object-like sub scope with type-field "Ruler"
321 return TYPE_Ruler == spec.data.recordType();
322 })
323 .constructFrom ([&](GenNode const& spec) -> PRuler
324 { // »Constructor« : how to attach a new ruler track
325 return make_unique<RulerTrack> (spec.idi, this->uiBus_, *this);
326 }))
327 .attach (collection(markers_)
328 .isApplicableIf ([&](GenNode const& spec) -> bool
329 { // »Selector« : require object-like sub scope with type-field "Marker"
330 return TYPE_Marker == spec.data.recordType();
331 })
332 .constructFrom ([&](GenNode const& spec) -> PMark
333 {
334 return make_unique<MarkerWidget> (spec.idi, this->uiBus_);
335 }))
336 .attach (collection(clips_)
337 .isApplicableIf ([&](GenNode const& spec) -> bool
338 { // »Selector« : require object-like sub scope with type-field "Clip"
339 return TYPE_Clip == spec.data.recordType();
340 })
341 .constructFrom ([&](GenNode const& spec) -> PClip
342 {
343 std::optional<TimeSpan> timing = spec.retrieveAttribute<TimeSpan> (string{ATTR_timing});
344 return make_unique<ClipPresenter> (spec.idi, this->uiBus_, display_.getClipHook(), timing);
345 }))
346 .attach (collection(subFork_)
347 .isApplicableIf ([&](GenNode const& spec) -> bool
348 { // »Selector« : require object-like sub scope with type-field "Fork"
349 return TYPE_Fork == spec.data.recordType();
350 })
351 .constructFrom ([&](GenNode const& spec) -> PFork
352 {
353 return make_unique<TrackPresenter> (spec.idi, uiBus_, this->display_);
354 }))
355 .change(ATTR_name, [&](string val)
356 { // »Attribute Setter« : receive a new value for the track name field
357 this->setTrackName (val);
358 }));
359 }
360
361
362
364 inline void
366 {
367 ASSERT (displayEvaluation.isCollectPhase());
369 for (auto& subTrack: subFork_)
370 subTrack->establishLayout (displayEvaluation);
371 }
372
374 inline void
376 {
377 ASSERT (not displayEvaluation.isCollectPhase());
378 // recursion first, so all sub-Tracks are already balanced
379 for (auto& subTrack: subFork_)
380 subTrack->completeLayout (displayEvaluation);
381 this->relinkContents();
382 // re-sync and match the header / body display
383 display_.sync_and_balance (displayEvaluation);
384 }
385
395 inline void
396 DisplayFrame::establishExtension (vector<PClip>& clips, vector<PMark>&)
397 {
398 uint maxVSize = max (explore (clips)
399 .transform([](PClip const& clip)
400 {
401 return clip->determineRequiredVerticalExtension();
402 }));
403 maxVSize = max (maxVSize, head_.getContentHeight());
404 this->body_.accommodateContentHeight (maxVSize);
405 this->head_.accommodateContentHeight (maxVSize);
406 }
407
412 inline void
414 {
415 for (auto& clip: clips_)
416 clip->relink();
417 for (auto& mark: markers_)
418 mark->relink();
419 }
420
421
439 inline void
441 {
442 uint contentHeight = body_.calcContentHeight();
443 uint overallHeight = contentHeight + body_.calcSubtrackHeight();
444 head_.syncSubtrackStartHeight (contentHeight);
445 head_.accommodateOverallHeight (overallHeight);
446 }
447
448
449
450
451
452}}// namespace stage::timeline
453#endif /*STAGE_TIMELINE_TRACK_PRESENTER_H*/
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
SUB & emplace(SUB &&implementation)
move-construct an instance of a subclass into the opaque buffer
string recordType() const
peek into the type field of a nested Record<GenNode>
Definition gen-node.hpp:761
Customisable intermediary to abstract mutating operations on arbitrary, hierarchical object-like data...
static Builder< TreeMutator > build()
DSL: start building a custom adapted tree mutator, where the operations are tied by closures or wrapp...
A time interval anchored at a specific point in time.
connection point at the UI-Bus.
Definition bus-term.hpp:98
Interface to represent _"some presentation layout entity",_ with the ability to place widgets (manage...
Mix-in interface to allow for concrete CanvasHooked widgets to adapt themselves to the metric current...
ctrl::BusTerm::ID ID
Definition tangible.hpp:162
void mark(GenNode const &)
generic handler for all incoming "state mark" messages
Definition tangible.cpp:251
ctrl::BusTerm uiBus_
Definition tangible.hpp:168
Interface to represent _"some presentation layout entity",_ with the ability to attach widgets (manag...
Definition view-hook.hpp:76
A widget attached onto a display canvas or similar central presentation context.
Visitor and state holder for a collaborative layout adjustment pass.
Reference frame to organise the presentation related to a specific Track in the Timeline-GUI.
int hookAdjY(int yPos) override
void establishExtension(vector< PClip > &, vector< PMark > &)
Find out about the vertical extension of a single track display.
model::ViewHooked< TrackBody > body_
vector< unique_ptr< RulerTrack > > & bindRulers()
int hookAdjX(int xPos) override
model::CanvasHook< Gtk::Widget > & getClipHook() override
void sync_and_balance(DisplayEvaluation &)
re-flow and adjust after the global layout has been established At this point we can assume that both...
DisplayFrame(DisplayViewHooks &displayAnchor)
model::ViewHooked< TrackHeadWidget > head_
model::ViewHook< TrackHeadWidget > & getHeadHook() override
model::ViewHook< TrackBody > & getBodyHook() override
void setTrackName(cuString &name)
Interface: a compound of anchoring facilities.
Special CanvasHook decorator to apply a (dynamic) offset when attaching or moving Widgets on the shar...
RelativeCanvasHook(model::CanvasHook< WID > &baseHook)
void remove(WID &widget) override
void hook(WID &widget, int xPos=0, int yPos=0) override
virtual int hookAdjY(int yPos)=0
model::CanvasHook< WID > & getAnchorHook() noexcept override
allow to build a derived relative hook with different offset
model::DisplayMetric & getMetric() const override
delegating layout metric to the root canvas
virtual int hookAdjX(int xPos)=0
model::CanvasHook< WID > & refHook_
void move(WID &widget, int xPos, int yPos) override
A View-Model entity to represent a timeline track in the UI.
void relinkContents()
second pass of the DisplayEvaluation: reassemble content to match adjusted layout
void establishLayout(DisplayEvaluation &) override
handle Phase-1 of the DisplayEvaluation pass for this track and its sub-tracks.
void completeLayout(DisplayEvaluation &) override
handle Phase-2 (collect/balancing phase) for this track and its sub-tracks.
void setTrackName(string name)
invoked via diff to show a (changed) track name
TrackPresenter(ID id, ctrl::BusTerm &nexus, DisplayViewHooks &displayAnchor)
virtual void buildMutator(lib::diff::TreeMutator::Handle) override
set up a binding to respond to mutation messages via UiBus
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Presentation control element to model and manage a clip within the timeline UI.
Common Abstraction of all sub-controller, coordinated by the UI-Bus.
A collaboration to establish a globally coherent timeline display layout.
A set of basic GTK includes for the UI.
unsigned int uint
Definition integral.hpp:29
Building tree expanding and backtracking evaluations within hierarchical scopes.
Widget to show a marker at various places.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
unique_ptr< RulerTrack > PRuler
unique_ptr< ClipPresenter > PClip
unique_ptr< TrackPresenter > PFork
unique_ptr< MarkerWidget > PMark
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
const Symbol ATTR_name
const uString cuString
Definition gtk-base.hpp:93
const Symbol TYPE_Clip
const Symbol TYPE_Marker
const Symbol ATTR_timing
const Symbol TYPE_Fork
auto max(IT &&elms)
Mix-Ins to allow or prohibit various degrees of copying and cloning.
generic data element node within a tree
Definition gen-node.hpp:224
std::optional< X > retrieveAttribute(string key) const
mismatch tolerant convenience shortcut to peek into the attributes of a nested Record
Definition gen-node.hpp:801
a family of time value like entities and their relationships.
This helper class serves to manage the layout and display of the horizontally extended space of a "tr...
Widget to represent a track head with placement parameters, within the timeline header pane.
Hard wired key constants and basic definitions for communication with the GUI.
Some small helpers and convenience shortcuts to ease working with collections and sequences (given by...
Allow widgets to connect to a common shared presentation context.