profile: implement panning of profile

When zoomed in, the profile position was moved by hovering with
the mouse. What a horrible user experience. This is especially
useless if we want to implement an interactive profile on mobile.

Instead, let the user start the panning with a mouse click. The
code is somewhat nasty, because the position is given as a
real in the [0,1] range, which represents all possible positions
from completely to the left to completely to the right.

This commit also removes the restriction that the planner handles
can only be moved when fully zoomed out. It is not completely
clear what the implications are. Let's see.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2022-08-28 22:42:54 +02:00 committed by Dirk Hohndel
parent 0d92ef2835
commit edf2a2f4f4
7 changed files with 63 additions and 29 deletions

View file

@ -12,6 +12,7 @@
#include "core/pref.h"
#include "core/profile.h"
#include "core/qthelper.h" // for decoMode()
#include "core/subsurface-float.h"
#include "core/subsurface-string.h"
#include "core/settings/qPrefDisplay.h"
#include "qt-models/diveplannermodel.h"
@ -491,11 +492,9 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
percentageAxis->updateTicks(animSpeed);
animatedAxes.push_back(percentageAxis);
if (calcMax) {
double relStart = (1.0 - 1.0/zoom) * zoomedPosition;
double relEnd = relStart + 1.0/zoom;
timeAxis->setBounds(round(relStart * maxtime), round(relEnd * maxtime));
}
double relStart = (1.0 - 1.0/zoom) * zoomedPosition;
double relEnd = relStart + 1.0/zoom;
timeAxis->setBounds(round(relStart * maxtime), round(relEnd * maxtime));
// Find first and last plotInfo entry
int firstSecond = lrint(timeAxis->minimum());
@ -627,3 +626,19 @@ void ProfileScene::draw(QPainter *painter, const QRect &pos,
}
painter->drawImage(pos, image);
}
// Calculate the new zoom position when the mouse is dragged by delta.
// This is annoyingly complex, because the zoom position is given as
// a real between 0 and 1.
double ProfileScene::calcZoomPosition(double zoom, double originalPos, double delta)
{
double factor = 1.0 - 1.0/zoom;
if (nearly_0(factor))
return 0.0;
double relStart = factor * originalPos;
double start = relStart * maxtime;
double newStart = start + timeAxis->deltaToValue(delta);
double newRelStart = newStart / maxtime;
double newPos = newRelStart / factor;
return std::clamp(newPos, 0.0, 1.0);
}