subsurface/profile-widget/profilescene.h
Berthold Stoeger edf2a2f4f4 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>
2022-09-03 13:51:00 -07:00

107 lines
4 KiB
C++

// SPDX-License-Identifier: GPL-2.0
// Displays the dive profile. Used by the interactive profile widget
// and the printing/exporting code.
#ifndef PROFILESCENE_H
#define PROFILESCENE_H
#include "core/color.h"
#include "core/profile.h"
#include <QGraphicsScene>
#include <QPainter>
#include <memory>
class AbstractProfilePolygonItem;
class DiveCalculatedCeiling;
class DiveCalculatedTissue;
class DiveCartesianAxis;
class DiveEventItem;
class DiveGasPressureItem;
class DiveHeartrateItem;
class DiveMeanDepthItem;
class DivePercentageItem;
class DivePixmaps;
class DivePlannerPointsModel;
class DiveProfileItem;
class DiveReportedCeiling;
class DiveTemperatureItem;
class DiveTextItem;
class PartialPressureGasItem;
class ProfileAnimation;
class TankItem;
class ProfileScene : public QGraphicsScene {
public:
ProfileScene(double dpr, bool printMode, bool isGrayscale);
~ProfileScene();
void resize(QSizeF size);
void clear();
bool pointOnProfile(const QPointF &point) const;
void anim(double fraction); // Called by the animation with 0.0-1.0 (start to stop).
// Can be compared with literal 1.0 to determine "end" state.
// If a plannerModel is passed, the deco-information is taken from there.
void plotDive(const struct dive *d, int dc, DivePlannerPointsModel *plannerModel = nullptr, bool inPlanner = false,
bool instant = false, bool keepPlotInfo = false, bool calcMax = true, double zoom = 1.0, double zoomedPosition = 0.0);
void draw(QPainter *painter, const QRect &pos,
const struct dive *d, int dc,
DivePlannerPointsModel *plannerModel = nullptr, bool inPlanner = false);
double calcZoomPosition(double zoom, double originalPos, double delta);
const struct dive *d;
int dc;
private:
using DataAccessor = double (*)(const plot_data &data);
template<typename T, class... Args> T *createItem(const DiveCartesianAxis &vAxis, DataAccessor accessor, int z, Args&&... args);
PartialPressureGasItem *createPPGas(DataAccessor accessor, color_index_t color, color_index_t colorAlert,
const double *thresholdSettingsMin, const double *thresholdSettingsMax);
template <int ACT, int MAX> void addTissueItems(double dpr);
void updateVisibility(bool diveHasHeartBeat, bool simplified); // Update visibility of non-interactive chart features according to preferences
void updateAxes(bool diveHasHeartBeat, bool simplified); // Update axes according to preferences
friend class ProfileWidget2; // For now, give the ProfileWidget full access to the objects on the scene
double dpr; // Device Pixel Ratio. A DPR of one corresponds to a "standard" PC screen.
bool printMode;
bool isGrayscale;
int maxtime;
int maxdepth;
struct plot_info plotInfo;
QRectF profileRegion; // Region inside the axes, where the crosshair is painted in plan and edit mode.
DiveCartesianAxis *profileYAxis;
DiveCartesianAxis *gasYAxis;
DiveCartesianAxis *temperatureAxis;
DiveCartesianAxis *timeAxis;
DiveCartesianAxis *cylinderPressureAxis;
DiveCartesianAxis *heartBeatAxis;
DiveCartesianAxis *percentageAxis;
std::vector<AbstractProfilePolygonItem *> profileItems;
DiveProfileItem *diveProfileItem;
DiveTemperatureItem *temperatureItem;
DiveMeanDepthItem *meanDepthItem;
DiveGasPressureItem *gasPressureItem;
QList<DiveEventItem *> eventItems;
DiveTextItem *diveComputerText;
DiveReportedCeiling *reportedCeiling;
PartialPressureGasItem *pn2GasItem;
PartialPressureGasItem *pheGasItem;
PartialPressureGasItem *po2GasItem;
PartialPressureGasItem *o2SetpointGasItem;
PartialPressureGasItem *ccrsensor1GasItem;
PartialPressureGasItem *ccrsensor2GasItem;
PartialPressureGasItem *ccrsensor3GasItem;
PartialPressureGasItem *ocpo2GasItem;
DiveCalculatedCeiling *diveCeiling;
DiveTextItem *decoModelParameters;
std::vector<DiveCalculatedTissue *> allTissues;
DiveHeartrateItem *heartBeatItem;
DivePercentageItem *percentageItem;
TankItem *tankItem;
std::shared_ptr<const DivePixmaps> pixmaps;
std::unique_ptr<ProfileAnimation> animation;
std::vector<DiveCartesianAxis *> animatedAxes;
};
#endif