Timeline: define basic ZoomWindow setters on top of the normalisation
Rearrange the internal mutator functions to follow a common scheme, so that most of the setters can be implemented by simple forwarding. Move the change-listener triggering up into the actual setters. This makes further test cases pass - verify_setup - verify_calibration ...implying that the pixel width is now retained and basic behaviour matches expectations
This commit is contained in:
parent
14da237d5c
commit
a9df13f078
3 changed files with 127 additions and 37 deletions
|
|
@ -231,16 +231,28 @@ namespace model {
|
|||
|
||||
/* === Mutators === */
|
||||
|
||||
/**
|
||||
* define the extension of the window in pixels.
|
||||
* @note all other manipulations will always retain this value
|
||||
*/
|
||||
void
|
||||
calibrateExtension (uint pxWidth)
|
||||
{
|
||||
UNIMPLEMENTED ("calibrateExtension");
|
||||
adaptWindowToPixels (pxWidth);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* explicitly set the zoom factor, defined as pixel per second
|
||||
* @note the given factor will be capped to remain below a maximal
|
||||
* zoom of 2px per µ-tick; also the window may not be expanded
|
||||
* beyond the current overall canvas size
|
||||
*/
|
||||
void
|
||||
setMetric (Rat px_per_sec)
|
||||
{
|
||||
mutateScale (px_per_sec);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -249,48 +261,68 @@ namespace model {
|
|||
* and the visible window is adjusted accordingly, using
|
||||
* the current #anchorPoint as centre for scaling.
|
||||
* @note the zoom factor is limited to be between
|
||||
* 2px per µ-tick and 1px per second (~20min
|
||||
* on a typical 1280 monitor)
|
||||
* @todo support for overview mode ////////////////////////////////////////////////////////////////////TICKET #1255 : implement overview mode
|
||||
* 2px per µ-tick and showing the full canvas
|
||||
*/
|
||||
void
|
||||
nudgeMetric (int steps)
|
||||
{
|
||||
mutateScale(
|
||||
setMetric(
|
||||
steps > 0 ? Rat{px_per_sec_.numerator() << steps
|
||||
,px_per_sec_.denominator()}
|
||||
: Rat{px_per_sec_.numerator()
|
||||
,px_per_sec_.denominator() << -steps});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set both the overall canvas, as well as the visible part
|
||||
* within that canvas. Given values will possibly be adjusted
|
||||
* to retain overall consistency, according to the following rules:
|
||||
* - all ranges are non empty and properly oriented
|
||||
* - the extension in pixels will always be retained
|
||||
* - zoom factor is only allowed to range between showing
|
||||
* the full canvas and a maximum factor (2 pixel per µ-tick)
|
||||
* - the visible window will always be within the canvas area
|
||||
*/
|
||||
void
|
||||
setRanges (TimeSpan overall, TimeSpan visible)
|
||||
{
|
||||
UNIMPLEMENTED ("setOverallRange");
|
||||
mutateRanges (overall, visible);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* redefine the overall canvas range.
|
||||
* @note the currently visible window may be shifted or
|
||||
* capped to fit within the new range, which may also
|
||||
* change the zoom factor, while the overall pixel width
|
||||
* is always retained unaltered
|
||||
*/
|
||||
void
|
||||
setOverallRange (TimeSpan range)
|
||||
{
|
||||
UNIMPLEMENTED ("setOverallRange");
|
||||
mutateCanvas (range);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
void
|
||||
setOverallStart (TimeValue start)
|
||||
{
|
||||
UNIMPLEMENTED ("setOverallStart");
|
||||
mutateCanvas (TimeSpan{start, Duration(afterAll_-startAll_)});
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
void
|
||||
setOverallDuration (Duration duration)
|
||||
{
|
||||
UNIMPLEMENTED ("setOverallDuration");
|
||||
mutateCanvas (TimeSpan{startAll_, duration});
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
void
|
||||
setVisibleRange (TimeSpan newWindow)
|
||||
{
|
||||
mutateWindow (newWindow.start(), newWindow.end());
|
||||
mutateWindow (newWindow);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -302,7 +334,8 @@ namespace model {
|
|||
void
|
||||
setVisibleDuration (Duration duration)
|
||||
{
|
||||
UNIMPLEMENTED ("setVisibleDuration");
|
||||
mutateWindow (TimeSpan{startWin_, duration});
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -398,14 +431,8 @@ namespace model {
|
|||
if (not isMicroGridAligned (dur))
|
||||
timeDur = timeDur + TimeValue(1);
|
||||
// resize window relative to anchor point
|
||||
startWin_ = Time{anchorPoint()} - Time{dur*relativeAnchor()};
|
||||
if (startWin_<= Time::MAX - timeDur)
|
||||
afterWin_ = startWin_ + timeDur;
|
||||
else
|
||||
{
|
||||
startWin_ = Time::MAX - timeDur;
|
||||
afterWin_ = Time::MAX;
|
||||
}
|
||||
placeWindowRelativeToAnchor (dur);
|
||||
changeWindowDuration (timeDur);
|
||||
// re-check metric to maintain precise pxWidth
|
||||
px_per_sec_ = conformMetricToWindow (pxWidth);
|
||||
ENSURE (_FSecs(afterWin_-startWin_) < MAX_TIMESPAN);
|
||||
|
|
@ -485,16 +512,39 @@ namespace model {
|
|||
|
||||
/* === adjust and coordinate window parameters === */
|
||||
|
||||
/** @internal set a different overall canvas range,
|
||||
* possibly set window and metrics to fit */
|
||||
void
|
||||
mutateCanvas (TimeSpan canvas)
|
||||
{
|
||||
startAll_ = canvas.start();
|
||||
afterAll_ = ensureNonEmpty (startAll_, canvas.end());
|
||||
ensureInvariants();
|
||||
}
|
||||
|
||||
/** @internal change Window TimeSpan, validate and adjust all params */
|
||||
void
|
||||
mutateWindow (TimeVar start, TimeVar after)
|
||||
mutateWindow (TimeSpan window)
|
||||
{
|
||||
uint px{pxWidth()};
|
||||
startWin_ = start;
|
||||
afterWin_ = ensureNonEmpty (startWin_, after);
|
||||
startWin_ = window.start();
|
||||
afterWin_ = ensureNonEmpty (startWin_, window.end());
|
||||
px_per_sec_ = conformMetricToWindow (px);
|
||||
ensureInvariants (px);
|
||||
}
|
||||
|
||||
/** @internal change canvas and window position in one call,
|
||||
* then validate and adjust to maintain invariants */
|
||||
void
|
||||
mutateRanges (TimeSpan canvas, TimeSpan window)
|
||||
{
|
||||
uint px{pxWidth()};
|
||||
startAll_ = canvas.start();
|
||||
afterAll_ = ensureNonEmpty (startAll_, canvas.end());
|
||||
startWin_ = window.start();
|
||||
afterWin_ = ensureNonEmpty (startWin_, window.end());
|
||||
px_per_sec_ = conformMetricToWindow (px);
|
||||
ensureInvariants (px);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -516,7 +566,6 @@ namespace model {
|
|||
afterWin_ = afterAll_;
|
||||
px_per_sec_ = conformMetricToWindow(px);
|
||||
ensureInvariants (px);
|
||||
fireChangeNotification();
|
||||
}
|
||||
else
|
||||
mutateDuration (dur);
|
||||
|
|
@ -534,7 +583,37 @@ namespace model {
|
|||
|
||||
conformWindowToMetric (changedMetric);
|
||||
ensureInvariants(px);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
/** @internal resize window to span the given pixel with,
|
||||
* validate and adjust all other params */
|
||||
void
|
||||
adaptWindowToPixels (uint pxWidth)
|
||||
{
|
||||
pxWidth = util::limited (1u, pxWidth, MAX_PX_WIDTH);
|
||||
FSecs adaptedWindow{Rat{pxWidth} / px_per_sec_};
|
||||
changeWindowDuration (adaptedWindow);
|
||||
px_per_sec_ = conformMetricToWindow (pxWidth);
|
||||
ensureInvariants (pxWidth);
|
||||
}
|
||||
|
||||
void
|
||||
placeWindowRelativeToAnchor (FSecs duration)
|
||||
{
|
||||
FSecs partBeforeAnchor = relativeAnchor() * duration;
|
||||
startWin_ = Time{anchorPoint()} - Time{partBeforeAnchor};
|
||||
}
|
||||
|
||||
void
|
||||
changeWindowDuration (TimeVar duration)
|
||||
{
|
||||
if (startWin_<= Time::MAX - duration)
|
||||
afterWin_ = startWin_ + duration;
|
||||
else
|
||||
{
|
||||
startWin_ = Time::MAX - duration;
|
||||
afterWin_ = Time::MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ namespace test {
|
|||
CHECK (win3.px_per_sec() == 555_r/23);
|
||||
|
||||
ZoomWindow win4{555, TimeSpan{_t(-10), _t(-5)}};
|
||||
CHECK (win4.overallSpan() == TimeSpan(_t(10), FSecs(5)));
|
||||
CHECK (win4.overallSpan() == TimeSpan(-Time(0,10), FSecs(5)));
|
||||
CHECK (win4.visible() == win4.overallSpan());
|
||||
CHECK (win4.pxWidth() == 555);
|
||||
CHECK (win4.px_per_sec() == 111);
|
||||
|
|
@ -211,7 +211,7 @@ namespace test {
|
|||
|
||||
win.nudgeMetric(+1);
|
||||
CHECK (win.overallSpan() == TimeSpan(_t(0), _t(64)));
|
||||
CHECK (win.visible() == TimeSpan(_t(-32,2), FSecs(32)));
|
||||
CHECK (win.visible() == TimeSpan(_t(32,2), FSecs(32)));
|
||||
CHECK (win.px_per_sec() == 40);
|
||||
CHECK (win.pxWidth() == 1280);
|
||||
|
||||
|
|
|
|||
|
|
@ -38363,7 +38363,7 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1666913256394" ID="ID_562681542" MODIFIED="1666913269396" TEXT="erster Entwurf 10/2022">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#690f14" CREATED="1666913293560" ID="ID_1249096607" MODIFIED="1666966326093" TEXT="das time::Control verwenden">
|
||||
<node COLOR="#690f14" CREATED="1666913293560" FOLDED="true" ID="ID_1249096607" MODIFIED="1666966326093" TEXT="das time::Control verwenden">
|
||||
<icon BUILTIN="idea"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1666913316709" ID="ID_134581234" MODIFIED="1666913343061" TEXT="Kenn-Parameter wären damit zwei TimeSpan"/>
|
||||
|
|
@ -38410,7 +38410,7 @@
|
|||
<node CREATED="1666966304273" ID="ID_1096389407" MODIFIED="1666966312732" TEXT="API-Nutzung insgesamt nicht selbsterklärend"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1666913370781" ID="ID_1691713188" MODIFIED="1666966354349" TEXT="klassisches Klassen-Design">
|
||||
<node COLOR="#435e98" CREATED="1666913370781" ID="ID_1691713188" MODIFIED="1667787385844" TEXT="klassisches Klassen-Design">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1666913375117" ID="ID_1377108042" MODIFIED="1667158257168" TEXT="ZoomWindow ist unkopierbare Klasse mit internem State"/>
|
||||
<node CREATED="1666913471725" ID="ID_1373767277" MODIFIED="1666966473259" TEXT="Master-Setter führen die Range-Chacks durch"/>
|
||||
|
|
@ -38459,7 +38459,7 @@
|
|||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1667156043109" ID="ID_234377752" MODIFIED="1667156067733" TEXT="ist sogar noch präziser als µs — und exakt"/>
|
||||
<node COLOR="#338800" CREATED="1667156072512" ID="ID_951906064" MODIFIED="1667156093493" TEXT="TimeVar für Konversionen "aufbohren"">
|
||||
<node COLOR="#338800" CREATED="1667156072512" FOLDED="true" ID="ID_951906064" MODIFIED="1667787375816" TEXT="TimeVar für Konversionen "aufbohren"">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1667156098084" ID="ID_1341404738" MODIFIED="1667156104554" TEXT="potentiell gefährlich">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
|
|
@ -38520,8 +38520,8 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667260101665" ID="ID_1250580560" MODIFIED="1667260118385" TEXT="muß die Ausdehnung in Pixel beachten">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667260101665" ID="ID_1250580560" MODIFIED="1667787352264" TEXT="muß die Ausdehnung in Pixel beachten">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1667260119686" ID="ID_1154266769" MODIFIED="1667780434377" TEXT="neuer Getter dafür">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -38692,9 +38692,9 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667603646312" ID="ID_1507636517" MODIFIED="1667603891148" TEXT="muß Invarianten sicherstellen">
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667603646312" ID="ID_1507636517" MODIFIED="1667787352264" TEXT="muß Invarianten sicherstellen">
|
||||
<linktarget COLOR="#ec1941" DESTINATION="ID_1507636517" ENDARROW="Default" ENDINCLINATION="27;-47;" ID="Arrow_ID_49426086" SOURCE="ID_162164091" STARTARROW="None" STARTINCLINATION="-122;6;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#6a1790" CREATED="1667603900358" ID="ID_353785530" MODIFIED="1667780480867" TEXT="das gewählte Implementierungs-Schema ist nicht beherrschbar">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1667603974758" ID="ID_1895105732" MODIFIED="1667603997149" TEXT="Konstuktor legt sichere Startwerte fest"/>
|
||||
|
|
@ -39336,8 +39336,8 @@
|
|||
<node CREATED="1667659867147" ID="ID_1797487380" MODIFIED="1667659882100" TEXT="jeweils den beweglichen Teil als Argument"/>
|
||||
<node CREATED="1667659890055" ID="ID_1728452596" MODIFIED="1667659897292" TEXT="immer nur einen Aspekt justieren"/>
|
||||
<node CREATED="1667659931146" ID="ID_1567516385" MODIFIED="1667659944676" TEXT="die jeweilige Ziel-Invariante per Assertion dokumentieren"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667698387387" ID="ID_1173911153" MODIFIED="1667698425495" TEXT="Normalisierungs-Sequenz auf Basis der einzel-Normalisierungen definieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1667698387387" ID="ID_1173911153" MODIFIED="1667787327395" TEXT="Normalisierungs-Sequenz auf Basis der einzel-Normalisierungen definieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667774188104" ID="ID_377878203" MODIFIED="1667774207918" TEXT="alle externen Manipulationen darauf aufsetzen (und erfolgreich testen)">
|
||||
<icon BUILTIN="pencil"/>
|
||||
|
|
@ -39389,7 +39389,18 @@
|
|||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1667528185832" ID="ID_1091652690" MODIFIED="1667528199122" TEXT="schrittweise incl Canvas erweitern"/>
|
||||
<node CREATED="1667528199785" ID="ID_1692959674" MODIFIED="1667528207840" TEXT="limits bei relativem positionieren"/>
|
||||
<node CREATED="1667528209948" ID="ID_914020436" MODIFIED="1667528219542" TEXT="explizit setzen und Canvas erweitern"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667787116332" ID="ID_538942533" MODIFIED="1667787124519" TEXT="relativ nach Position und Prozentsatz">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667528209948" ID="ID_914020436" MODIFIED="1667787027641" TEXT="explizit setzen und Canvas erweitern">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667787036706" ID="ID_192598582" MODIFIED="1667787077769" TEXT="muß hierfür die Limitierung explizit aufheben">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1667787054759" ID="ID_280714694" MODIFIED="1667787063999" TEXT="auf welcher Ebene am Besten einbauen?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue