diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index e497979df..c7da7e788 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -413,6 +413,14 @@ namespace time { return Offset(distance); } + inline Offset + operator- (Offset const& start, Offset const& toSubtract) + { + TimeVar distance(start); + distance -= toSubtract; + return Offset(distance); + } + template inline Offset operator* (Offset const& distance, INT factor) @@ -507,7 +515,7 @@ namespace time { }; - //-- support using a Duration to build offsets --------------- + //-- support combining and Durations --------------- inline Duration operator+ (Duration const& base, Duration const& toAdd) @@ -515,6 +523,13 @@ namespace time { return Offset(base) + Offset(toAdd); } + inline Duration + operator- (Duration const& base, Duration const& toRemove) + { + return base > toRemove? Offset(base) - Offset(toRemove) + : Duration::NIL; + } + template inline Offset operator* (INT factor, Duration const& dur) diff --git a/src/stage/model/zoom-window.hpp b/src/stage/model/zoom-window.hpp index 54603036d..a9ae76510 100644 --- a/src/stage/model/zoom-window.hpp +++ b/src/stage/model/zoom-window.hpp @@ -401,7 +401,6 @@ namespace model { setVisibleDuration (Duration duration) { mutateDuration (_FSecs(duration)); - mutateWindow (TimeSpan{startWin_, afterWin_}); fireChangeNotification(); } @@ -985,6 +984,7 @@ namespace model { duration = maxSaneWinExtension (px); Rat changedMetric = Rat(px) / duration; conformWindowToMetric (changedMetric); + ensureInvariants (px); } /** @internal resize window to span the given pixel with, diff --git a/tests/stage/model/zoom-window-test.cpp b/tests/stage/model/zoom-window-test.cpp index 6b02e5591..4000d1019 100644 --- a/tests/stage/model/zoom-window-test.cpp +++ b/tests/stage/model/zoom-window-test.cpp @@ -664,7 +664,7 @@ namespace test { /*--Test-4-----------*/ win.setVisiblePos(Time{Time::MIN + TimeValue(13)}); // Test: implicitly provoke poisonous factor through extreme offset - CHECK (win.visible().start() == Time::MIN + TimeValue(13)); // even while this position is far off, window start was alinget to it + CHECK (win.visible().start() == Time::MIN + TimeValue(13)); // even while this position is far off, window start was aligned to it CHECK (win.visible().end() == win.visible().start() + TimeValue{288}); CHECK (win.visible().duration() == TimeValue{288}); @@ -792,6 +792,7 @@ namespace test { void safeguard_extremeTimePos() { + /*--Test-1-----------*/ ZoomWindow win{559, TimeSpan{Time::MAX, Duration{TimeValue(3)}}}; // setup a very small window clinging to Time::MAX CHECK (win.visible().duration() == TimeValue(280)); // duration expanded due to MAX_ZOOM limit CHECK (win.visible().start() == TimeValue(307445734561825580)); // and properly oriented and aligned within domain @@ -800,15 +801,43 @@ namespace test { CHECK (win.visible() == win.overallSpan()); CHECK (win.px_per_sec() == 559_r/280*Time::SCALE); CHECK (win.px_per_sec() == 13975000_r/7); - CHECK (win.pxWidth() == 559); + CHECK (win.pxWidth() == 559); -// SHOW_EXPR(win.overallSpan()); -// SHOW_EXPR(_raw(win.overallSpan().duration())); -// SHOW_EXPR(_raw(win.visible().duration())); -// SHOW_EXPR(_raw(win.visible().start())); -// SHOW_EXPR(_raw(win.visible().end())); -// SHOW_EXPR(win.px_per_sec()); -// SHOW_EXPR(win.pxWidth()); + /*--Test-2-----------*/ + Time anchorPos{15_r/16 * Offset(Time::MIN)}; + win.setVisiblePos (anchorPos); // scroll to a target position extremely far off + CHECK (win.visible().duration() == TimeValue(280)); // window dimensions retained + CHECK (win.px_per_sec() == 13975000_r/7); + CHECK (win.pxWidth() == 559); + CHECK (win.visible().start() > Time::MIN); + CHECK (win.visible().start() == anchorPos); // window now at desired position + CHECK (win.visible().end() > anchorPos); + CHECK (win.visible().start() == TimeValue(-288230376151711744)); + CHECK (win.visible().end() == TimeValue(-288230376151711464)); + CHECK (win.overallSpan().start() == win.visible().start()); // canvas expanded accordingly + CHECK (win.overallSpan().end() == Time::MAX); + + /*--Test-3-----------*/ + win.setOverallDuration(Duration::MAX); // now use maximally expanded canvas + Duration targetDur{99_r/100 * Duration::MAX}; + win.setVisibleDuration(targetDur); // and demand the duration be expanded to 99% + + CHECK (win.visible().duration() > targetDur); // actual duration slightly more than requested, + CHECK (win.visible().duration() < Duration::MAX); + CHECK (win.visible().start() == Time::MIN); // expansion was anchored at previous position + CHECK (win.visible().start() < Time::MAX); // and thus the window now clings to the lower end + CHECK (win.visible().end() == TimeValue(301415533658088775)); + CHECK (win.px_per_sec() == 2019_r/2199023255552); // effective zoom metric has been sanitised numerically + CHECK (win.pxWidth() == 559); // but pixel count is matched precisely + + /*--Test-4-----------*/ + win.setVisiblePos(Rat{std::numeric_limits::max()-23}); + SHOW_EXPR(_raw(win.overallSpan().duration())); + SHOW_EXPR(_raw(win.visible().duration())); + SHOW_EXPR(_raw(win.visible().start())); + SHOW_EXPR(_raw(win.visible().end())); + SHOW_EXPR(win.px_per_sec()); + SHOW_EXPR(win.pxWidth()); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 00476d992..12956ef77 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -41249,11 +41249,22 @@ - - + + + + + + + + + + + + + @@ -41263,13 +41274,39 @@ - - + + - - + + + + + + + + + + + + + +

+ wir rechnen von der Duration auf eine Metrik um, weil wir den Mechanismus zur relativen Positionierung haben wollen. Dieser muß aber detox() verwenden, weil sonst die Division mit der Pixel-Zahl einen numeric-wrap machen würde.... +

+ +
+ + + + + + + + + +