Clip-Drag: integrate indirectly with the TimelineLayout for metric translation

The ClipPresenter can access the CanvasHook wired into its actual ClipDelegate (widget).
And this in turn exposes the DisplayMetric, with the ability to transform
presentation coordinates (pixels) into a model representation (Time)

The actual translation is still hardwired placeholder code,
since it is planned to build an generic component "ZoomWindow"
to provide all the typical zomming and view window translations
found in every timeline editor
This commit is contained in:
Fischlurch 2021-05-13 18:29:37 +02:00
parent 3e9aae30b3
commit 526f1d09e7
6 changed files with 75 additions and 20 deletions

View file

@ -40,7 +40,9 @@
** of time-like entities -- be it the running time display in a GUI widget, a ruler marker
** which can be dragged, a modifiable selection or the animated playhead cursor.
**
** \par usage scenarios
**
** # Usage scenarios
**
** The time::Control element provides mediating functionality, but doesn't assume or provide
** anything special regarding the usage pattern or the lifecycle, beyond the ability to
** attach listeners, attach to a (different) target and to detach from all connections.
@ -59,10 +61,10 @@
** may expose a time::Control, thus allowing to attach target and listeners, while the
** actual changes will originate somewhere within the opaque service implementation.
**
** Another usage pattern would be to expose a time::Control \c const&, allowing only to
** Another usage pattern would be to expose a `time::Control const&`, allowing only to
** impose changes, but not to change the target or listener attachments. To the contrary,
** when exposing only a time::Mutation \c const& through an interface allows only to
** attach new target elements, but not to change listeners or feed any value changes.
** exposing only a time::Mutation \c const& through some interface allows only to attach
** new target elements, but not to change listeners or feed any value changes.
**
** Using time::Control as an implementation building block and just exposing the
** change (function) operators or the listener attachment through an forwarding sub
@ -71,7 +73,7 @@
** @note time::Control is default constructible and freely copyable.
**
**
** \par changing quantised (grid aligned) time entities
** ## Changing quantised (grid aligned) time entities
**
** The time::Control element includes the functionality to handle grid aligned time values,
** both as target and as change/notification value. This ability is compiled in conditionally,
@ -80,7 +82,8 @@
** the LIB_TIME_TIMEQUANT_H header guard needs to be defined, which happens automatically
** if lib/time/mutation.hpp is included prior to lib/time/control.hpp.
**
** \par implementation notes
**
** # implementation notes
** - the validity of a given combination of change and target is checked immediately,
** when connecting to the target. Depending on the situation, the actual changes later
** are subject to specific treatment (e.g. frame quantisation)

View file

@ -88,6 +88,13 @@ namespace model {
/** extension point for time axis zoom management. */
virtual int translateTimeToPixels (TimeValue) const =0;
/** translate an offset in pixel coordinates into a temporal position
* @param anchor the start point on the time axis where to apply the delta
* @param deltaPx a delta given as canvas pixel displacement
* @return resulting TimeValue when applying the offset within current metric
*/
virtual TimeValue applyScreenDelta(Time anchor, double deltaPx) const =0;
};

View file

@ -226,14 +226,18 @@ namespace timeline {
: public interact::GestureObserver
{
ClipPresenter& subject_;
model::DisplayMetric const& metric_;
void
updateOffset (double deltaX, double deltaY) override
{
std::cerr << _Fmt{"Gesture(%s) --> Δ := (%3.1f,%3.1f)"}
TimeValue newStartTime = metric_.applyScreenDelta(subject_.widget_->getStartTime(), deltaX);
std::cerr << _Fmt{"Gesture(%s) → Δ ≔ (%3.1f,%3.1f) ⟹ %s ↷ %s"}
% getCmdID()
% deltaX
% deltaY
% subject_.widget_->getStartTime()
% newStartTime
<< std::endl;
}
@ -249,6 +253,7 @@ namespace timeline {
DragRelocateObserver(Symbol cmdID, ClipPresenter& clipPresenter)
: interact::GestureObserver{cmdID}
, subject_{clipPresenter}
, metric_{clipPresenter.widget_->getCanvas().getMetric()}
{ }
};

View file

@ -129,9 +129,16 @@ namespace timeline {
int
TimelineLayout::translateTimeToPixels (TimeValue startTimePoint) const
{
return _raw(startTimePoint) * TODO_px_per_second / Time::SCALE; //////////TICKET #1213 : delegate zoom handling to the display manager (field #layout_) !!
return _raw(startTimePoint) * TODO_px_per_second / Time::SCALE; //////////TICKET #1213 : use a mix-in component, which in turn relies on the "ZoomWindow" !!
}
TimeValue
TimelineLayout::applyScreenDelta(Time anchor, double deltaPx) const
{ //////////TICKET #1213 : use a mix-in component, which in turn relies on the "ZoomWindow" !!
return anchor + TimeValue{gavl_time_t(Time::SCALE * deltaPx / TODO_px_per_second)};
}
/**
* Perform a complete recursive pass over all elements relevant for layout,

View file

@ -89,6 +89,7 @@
#include "stage/timeline/body-canvas-widget.hpp"
#include "stage/model/canvas-hook.hpp"
#include "stage/model/view-hook.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/util.hpp"
@ -100,6 +101,8 @@
namespace stage {
namespace timeline {
using lib::time::Time;
class LayoutElement;
class TrackHeadWidget;
class TrackBody;
@ -140,8 +143,9 @@ namespace timeline {
void triggerDisplayEvaluation() override;
/////////////////////////////////////////////////////////////////////////////////////////////TICKET 1218 : better extract into a sub component when providing a non-dummy implementation
virtual lib::time::TimeSpan coveredTime() const override;
virtual int translateTimeToPixels (TimeValue) const override;
virtual lib::time::TimeSpan coveredTime() const override;
virtual int translateTimeToPixels (TimeValue) const override;
virtual TimeValue applyScreenDelta(Time, double) const override;
/////////////////////////////////////////////////////////////////////////////////////////////TICKET 1218 : better extract into a sub component when providing a non-dummy implementation

View file

@ -32884,7 +32884,23 @@
<node CREATED="1618778672386" ID="ID_1242087872" MODIFIED="1618778698205" TEXT="Bisher in BodyCanvasWidget angelegt">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1618778688276" ID="ID_1895003083" MODIFIED="1618778695704" TEXT="aber &#xfc;berhaupt noch nicht implementiert">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1620922762073" ID="ID_878659189" MODIFIED="1620922781290" TEXT="vorl&#xe4;ufige Dummy-Implementierung in TimelineLayout"/>
<node CREATED="1620922782734" ID="ID_1695744984" MODIFIED="1620922815553">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
verwendet hart gedrahtete Konstante <font color="#b42e2e">TODO_px_per_second</font>
</p>
</body>
</html></richcontent>
</node>
<node COLOR="#338800" CREATED="1620922817299" ID="ID_849178366" MODIFIED="1620922830205" TEXT="der Rest der Berechnung ist aber hiermit schon mal korrekt ausgef&#xfc;hrt">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1619104316816" FOLDED="true" ID="ID_907598549" MODIFIED="1619880556650" TEXT="zu Kl&#xe4;ren: Rolle und Zugang zum Layout-Manager">
<icon BUILTIN="yes"/>
@ -33072,7 +33088,7 @@
<body>
<ul>
<li>
der clipHook() delegiert an seinen jweiligen refHook_
der clipHook() delegiert an seinen jeweiligen refHook_
</li>
<li>
dieser wird bei der Konstruktion tats&#228;chlich jweils auf den Anchor-Hook des Parent-Hook gesetzt
@ -33168,15 +33184,15 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1619104345461" ID="ID_414006920" MODIFIED="1619880189377" TEXT="Aufgabe: API">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1619104345461" ID="ID_414006920" MODIFIED="1620922860429" TEXT="Aufgabe: API">
<icon BUILTIN="button_ok"/>
<node CREATED="1619104353964" ID="ID_1748021574" MODIFIED="1619104378116" TEXT="vorhanden: translateTimeToPixels(TimeValue startTimePoint)"/>
<node CREATED="1619132261261" ID="ID_1989281789" MODIFIED="1619132284186" TEXT="erst mal nach Bedarf &#x2015; aber genau">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1619132344961" ID="ID_168747829" MODIFIED="1619132509806" TEXT="konkret hier...">
<node CREATED="1619132510942" ID="ID_1513485460" MODIFIED="1619132510942" TEXT="applyScreenDelta(TimeValue, deltaPx)"/>
<node CREATED="1619132513720" ID="ID_718240764" MODIFIED="1619132619351" TEXT="translateScreenDeltaToTime(deltaPx)"/>
<node COLOR="#435e98" CREATED="1619132510942" ID="ID_1513485460" MODIFIED="1620922851937" TEXT="applyScreenDelta(TimeValue, deltaPx)"/>
<node COLOR="#435e98" CREATED="1619132513720" ID="ID_718240764" MODIFIED="1619132619351" TEXT="translateScreenDeltaToTime(deltaPx)"/>
</node>
<node COLOR="#338800" CREATED="1619698634099" ID="ID_1185723124" MODIFIED="1619804547408" TEXT="Sub-Interface einf&#xfc;hren">
<icon BUILTIN="button_ok"/>
@ -33215,6 +33231,9 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1620913903207" ID="ID_236784465" MODIFIED="1620913912953" TEXT="L&#xf6;sung time::Control (Mutator)">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1620917838309" ID="ID_1646116499" MODIFIED="1620917859760" TEXT="das time::Control lebt dann wohl im Observer">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1618753085285" ID="ID_560686142" MODIFIED="1618753216324" TEXT="noch keinerlei Infrastruktur f&#xfc;r die vertikale Anordnung">
<icon BUILTIN="hourglass"/>
@ -33298,8 +33317,8 @@
<arrowlink COLOR="#22d66c" DESTINATION="ID_1241205333" ENDARROW="Default" ENDINCLINATION="35;105;" ID="Arrow_ID_1887863096" STARTARROW="None" STARTINCLINATION="348;20;"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1618691013997" ID="ID_429908834" MODIFIED="1618691021757" TEXT="Delta an das Subject weitergeben">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1618691013997" ID="ID_429908834" MODIFIED="1620922873764" TEXT="Delta an das Subject weitergeben">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1619887175393" FOLDED="true" ID="ID_54981427" MODIFIED="1619887223546" TEXT="Problem: Aufwand f&#xfc;r Gesten-Verfolgung">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1619887230011" ID="ID_1178141750" MODIFIED="1619887552418" TEXT="Push von low-Level-Events erzeugt &#xdc;bersetzungsaufwand">
@ -33607,8 +33626,18 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1618691023427" ID="ID_1396949384" MODIFIED="1618691041225" TEXT="im Subject in Modell-Koordinaten transformieren">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1618691023427" ID="ID_1396949384" MODIFIED="1620922896886" TEXT="im Subject in Modell-Koordinaten transformieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
funktioniert... Zeit-Werte werden an der Konsole ausgegeben
</p>
</body>
</html></richcontent>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1618691042073" ID="ID_1909659922" MODIFIED="1618691048993" TEXT="tats&#xe4;chlich im Canvas verschieben">
<icon BUILTIN="flag-yellow"/>