profile: set visibility of text and lines in constructor

The visibility of axis text / lines is never changed, so set
in axis constructor.

Moreover, instead of rendering the lines/text and then setting
them invisible, do not render them if invisible.

The whole thing appears superfluous, since the proper way to
not show lines/text is to just not call updateTicks on the
axis. But in the future we might want to have axes with text
but no lines, so keep for now.

Since this means breaking out the text / line rendering
into their own function, we might rename some variables to
make them (at least somewhat) more clear.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-10-03 21:51:56 +02:00 committed by Dirk Hohndel
parent a7a7bd182e
commit 7bc90b6dfe
3 changed files with 83 additions and 95 deletions

View file

@ -18,8 +18,9 @@ void DiveCartesianAxis::setBounds(double minimum, double maximum)
dataMax = max = maximum; dataMax = max = maximum;
} }
DiveCartesianAxis::DiveCartesianAxis(Position position, int integralDigits, int fractionalDigits, color_index_t gridColor, double dpr, DiveCartesianAxis::DiveCartesianAxis(Position position, int integralDigits, int fractionalDigits, color_index_t gridColor,
double labelScale, bool printMode, bool isGrayscale, ProfileScene &scene) : bool textVisible, bool linesVisible,
double dpr, double labelScale, bool printMode, bool isGrayscale, ProfileScene &scene) :
printMode(printMode), printMode(printMode),
position(position), position(position),
fractionalDigits(fractionalDigits), fractionalDigits(fractionalDigits),
@ -28,8 +29,8 @@ DiveCartesianAxis::DiveCartesianAxis(Position position, int integralDigits, int
orientation(LeftToRight), orientation(LeftToRight),
min(0), min(0),
max(0), max(0),
textVisibility(true), textVisibility(textVisible),
lineVisibility(true), lineVisibility(linesVisible),
labelScale(labelScale), labelScale(labelScale),
changed(true), changed(true),
dpr(dpr), dpr(dpr),
@ -90,28 +91,6 @@ QColor DiveCartesianAxis::colorForValue(double) const
return QColor(Qt::black); return QColor(Qt::black);
} }
void DiveCartesianAxis::setTextVisible(bool arg1)
{
if (textVisibility == arg1) {
return;
}
textVisibility = arg1;
Q_FOREACH (DiveTextItem *item, labels) {
item->setVisible(textVisibility);
}
}
void DiveCartesianAxis::setLinesVisible(bool arg1)
{
if (lineVisibility == arg1) {
return;
}
lineVisibility = arg1;
Q_FOREACH (DiveLineItem *item, lines) {
item->setVisible(lineVisibility);
}
}
template <typename T> template <typename T>
void emptyList(QList<T *> &list, int steps, int speed) void emptyList(QList<T *> &list, int steps, int speed)
{ {
@ -163,6 +142,9 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
if (dataMax - dataMin < 1e-5) if (dataMax - dataMin < 1e-5)
return; return;
if (!textVisibility && !lineVisibility)
return; // Nothing to display...
// Guess the number of tick marks. // Guess the number of tick marks.
QLineF m = line(); QLineF m = line();
double spaceNeeded = position == Position::Bottom ? labelWidth * 3.0 / 2.0 double spaceNeeded = position == Position::Bottom ? labelWidth * 3.0 / 2.0
@ -172,10 +154,10 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
int numTicks = lrint(size / spaceNeeded); int numTicks = lrint(size / spaceNeeded);
numTicks = std::clamp(numTicks, 2, 50); numTicks = std::clamp(numTicks, 2, 50);
double interval = (dataMax - dataMin) / numTicks; double stepValue = (dataMax - dataMin) / numTicks;
// Round the interval to a sensible size in display units // Round the interval to a sensible size in display units
double intervalDisplay = interval * transform.a; double intervalDisplay = stepValue * transform.a;
intervalDisplay = sensibleInterval(intervalDisplay, fractionalDigits); intervalDisplay = sensibleInterval(intervalDisplay, fractionalDigits);
// Choose full multiples of the interval as minumum and maximum values // Choose full multiples of the interval as minumum and maximum values
@ -185,17 +167,17 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
// The time axis is special: use the full width in that case. // The time axis is special: use the full width in that case.
// Other axes round to the next "nice" number // Other axes round to the next "nice" number
double firstDisplay, lastDisplay; double firstDisplay, lastDisplay;
double currValueText, currValueLine; double firstValue;
if (position == Position::Bottom) { if (position == Position::Bottom) {
firstDisplay = ceil(minDisplay / intervalDisplay * (1.0 - 1e-5)) * intervalDisplay; firstDisplay = ceil(minDisplay / intervalDisplay * (1.0 - 1e-5)) * intervalDisplay;
lastDisplay = floor(maxDisplay / intervalDisplay * (1.0 + 1e-5)) * intervalDisplay; lastDisplay = floor(maxDisplay / intervalDisplay * (1.0 + 1e-5)) * intervalDisplay;
currValueText = currValueLine = transform.from(firstDisplay); firstValue = transform.from(firstDisplay);
} else { } else {
firstDisplay = floor(minDisplay / intervalDisplay * (1.0 + 1e-5)) * intervalDisplay; firstDisplay = floor(minDisplay / intervalDisplay * (1.0 + 1e-5)) * intervalDisplay;
lastDisplay = ceil(maxDisplay / intervalDisplay * (1.0 - 1e-5)) * intervalDisplay; lastDisplay = ceil(maxDisplay / intervalDisplay * (1.0 - 1e-5)) * intervalDisplay;
min = transform.from(firstDisplay); min = transform.from(firstDisplay);
max = transform.from(lastDisplay); max = transform.from(lastDisplay);
currValueText = currValueLine = min; firstValue = min;
} }
numTicks = lrint((lastDisplay - firstDisplay) / intervalDisplay) + 1; numTicks = lrint((lastDisplay - firstDisplay) / intervalDisplay) + 1;
numTicks = std::max(numTicks, 0); numTicks = std::max(numTicks, 0);
@ -205,30 +187,39 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
if (numTicks == 0) if (numTicks == 0)
return; return;
interval = position == Position::Bottom ? stepValue = position == Position::Bottom ?
intervalDisplay / transform.a : // special case for time axis. intervalDisplay / transform.a : // special case for time axis.
numTicks > 1 ? (max - min) / (numTicks - 1) : 0; numTicks > 1 ? (max - min) / (numTicks - 1) : 0;
double stepSize = interval * size / (max - min); double stepScreen = stepValue * size / (max - min);
// Move the remaining grid lines / labels to their correct positions // Move the remaining grid lines / labels to their correct positions
// regarding the possible new values for the axis // regarding the possible new values for the axis
double begin; double firstPosScreen;
if (orientation == TopToBottom) { if (orientation == TopToBottom) {
begin = m.y1(); firstPosScreen = m.y1();
} else if (orientation == BottomToTop) { } else if (orientation == BottomToTop) {
begin = m.y2(); firstPosScreen = m.y2();
} else if (orientation == LeftToRight) { } else if (orientation == LeftToRight) {
begin = m.x1(); firstPosScreen = m.x1();
} else /* if (orientation == RightToLeft) */ { } else /* if (orientation == RightToLeft) */ {
begin = m.x2(); firstPosScreen = m.x2();
} }
for (int i = 0, count = labels.size(); i < count; i++, currValueText += interval) { if (textVisibility)
double childPos = (orientation == TopToBottom || orientation == LeftToRight) ? updateLabels(numTicks, firstPosScreen, firstValue, stepScreen, stepValue, animSpeed);
begin + i * stepSize : if (lineVisibility)
begin - i * stepSize; updateLines(numTicks, firstPosScreen, stepScreen, animSpeed);
changed = false;
}
labels[i]->set(textForValue(currValueText), colorForValue(currValueText)); void DiveCartesianAxis::updateLabels(int numTicks, double firstPosScreen, double firstValue, double stepScreen, double stepValue, int animSpeed)
{
for (int i = 0, count = labels.size(); i < count; i++, firstValue += stepValue) {
double childPos = (orientation == TopToBottom || orientation == LeftToRight) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
labels[i]->set(textForValue(firstValue), colorForValue(firstValue));
switch (position) { switch (position) {
default: default:
case Position::Bottom: case Position::Bottom:
@ -243,37 +234,19 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
} }
} }
for (int i = 0, count = lines.size(); i < count; i++, currValueLine += interval) {
double childPos = (orientation == TopToBottom || orientation == LeftToRight) ?
begin + i * stepSize :
begin - i * stepSize;
if (position == Position::Bottom) {
// Fix size in case the scene changed
QLineF old = lines[i]->line();
lines[i]->setLine(old.x1(), old.y1(), old.x1(), old.y1() + rect.height());
Animations::moveTo(lines[i], animSpeed, childPos, rect.top());
} else {
// Fix size in case the scene changed
QLineF old = lines[i]->line();
lines[i]->setLine(old.x1(), old.y1(), old.x1() + rect.width(), old.y1());
Animations::moveTo(lines[i], animSpeed, rect.left(), childPos);
}
}
// Add the rest of the needed labels. // Add the rest of the needed labels.
for (int i = labels.size(); i < numTicks; i++, currValueText += interval) { for (int i = labels.size(); i < numTicks; i++, firstValue += stepValue) {
double childPos; double childPos;
if (orientation == TopToBottom || orientation == LeftToRight) { if (orientation == TopToBottom || orientation == LeftToRight) {
childPos = begin + i * stepSize; childPos = firstPosScreen + i * stepScreen;
} else { } else {
childPos = begin - i * stepSize; childPos = firstPosScreen - i * stepScreen;
} }
int alignFlags = position == Position::Bottom ? Qt::AlignTop | Qt::AlignHCenter : int alignFlags = position == Position::Bottom ? Qt::AlignTop | Qt::AlignHCenter :
position == Position::Left ? Qt::AlignVCenter | Qt::AlignLeft: position == Position::Left ? Qt::AlignVCenter | Qt::AlignLeft:
Qt::AlignVCenter | Qt::AlignRight; Qt::AlignVCenter | Qt::AlignRight;
DiveTextItem *label = new DiveTextItem(dpr, labelScale, alignFlags, this); DiveTextItem *label = new DiveTextItem(dpr, labelScale, alignFlags, this);
label->set(textForValue(currValueText), colorForValue(currValueText)); label->set(textForValue(firstValue), colorForValue(firstValue));
label->setZValue(1); label->setZValue(1);
labels.push_back(label); labels.push_back(label);
switch (position) { switch (position) {
@ -292,14 +265,35 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
break; break;
} }
} }
}
void DiveCartesianAxis::updateLines(int numTicks, double firstPosScreen, double stepScreen, int animSpeed)
{
for (int i = 0, count = lines.size(); i < count; i++) {
double childPos = (orientation == TopToBottom || orientation == LeftToRight) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
if (position == Position::Bottom) {
// Fix size in case the scene changed
QLineF old = lines[i]->line();
lines[i]->setLine(old.x1(), old.y1(), old.x1(), old.y1() + rect.height());
Animations::moveTo(lines[i], animSpeed, childPos, rect.top());
} else {
// Fix size in case the scene changed
QLineF old = lines[i]->line();
lines[i]->setLine(old.x1(), old.y1(), old.x1() + rect.width(), old.y1());
Animations::moveTo(lines[i], animSpeed, rect.left(), childPos);
}
}
// Add the rest of the needed grid lines. // Add the rest of the needed grid lines.
for (int i = lines.size(); i < numTicks; i++, currValueText += interval) { for (int i = lines.size(); i < numTicks; i++) {
double childPos; double childPos;
if (orientation == TopToBottom || orientation == LeftToRight) { if (orientation == TopToBottom || orientation == LeftToRight) {
childPos = begin + i * stepSize; childPos = firstPosScreen + i * stepScreen;
} else { } else {
childPos = begin - i * stepSize; childPos = firstPosScreen - i * stepScreen;
} }
DiveLineItem *line = new DiveLineItem(this); DiveLineItem *line = new DiveLineItem(this);
line->setPen(gridPen); line->setPen(gridPen);
@ -315,12 +309,6 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
Animations::moveTo(line, animSpeed, rect.left(), childPos); Animations::moveTo(line, animSpeed, rect.left(), childPos);
} }
} }
Q_FOREACH (DiveTextItem *item, labels)
item->setVisible(textVisibility);
Q_FOREACH (DiveLineItem *item, lines)
item->setVisible(lineVisibility);
changed = false;
} }
void DiveCartesianAxis::setPosition(const QRectF &rectIn) void DiveCartesianAxis::setPosition(const QRectF &rectIn)

View file

@ -33,8 +33,9 @@ public:
Left, Right, Bottom Left, Right, Bottom
}; };
DiveCartesianAxis(Position position, int integralDigits, int fractionalDigits, color_index_t gridColor, double dpr, DiveCartesianAxis(Position position, int integralDigits, int fractionalDigits, color_index_t gridColor,
double labelScale, bool printMode, bool isGrayscale, ProfileScene &scene); bool textVisible, bool linesVisible,
double dpr, double labelScale, bool printMode, bool isGrayscale, ProfileScene &scene);
~DiveCartesianAxis(); ~DiveCartesianAxis();
void setBounds(double min, double max); void setBounds(double min, double max);
void setTransform(double a, double b = 0.0); void setTransform(double a, double b = 0.0);
@ -51,7 +52,7 @@ public:
double width() const; // only for vertical axes double width() const; // only for vertical axes
double height() const; // only for horizontal axes double height() const; // only for horizontal axes
protected: private:
Position position; Position position;
int fractionalDigits; int fractionalDigits;
QRectF rect; // Rectangle to fill with grid lines QRectF rect; // Rectangle to fill with grid lines
@ -81,6 +82,9 @@ protected:
double to(double x) const; double to(double x) const;
double from(double y) const; double from(double y) const;
} transform; } transform;
void updateLabels(int numTicks, double firstPosScreen, double firstValue, double stepScreen, double stepValue, int animSpeed);
void updateLines(int numTicks, double firstPosScreen, double stepScreen, int animSpeed);
}; };
class DepthAxis : public DiveCartesianAxis { class DepthAxis : public DiveCartesianAxis {

View file

@ -47,13 +47,20 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
maxtime(-1), maxtime(-1),
maxdepth(-1), maxdepth(-1),
dataModel(new DivePlotDataModel(this)), dataModel(new DivePlotDataModel(this)),
profileYAxis(new DepthAxis(DiveCartesianAxis::Position::Left, 3, 0, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)), profileYAxis(new DepthAxis(DiveCartesianAxis::Position::Left, 3, 0, TIME_GRID, true, true,
gasYAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 1, 2, TIME_GRID, dpr, 0.7, printMode, isGrayscale, *this)), dpr, 1.0, printMode, isGrayscale, *this)),
temperatureAxis(new TemperatureAxis(DiveCartesianAxis::Position::Right, 3, 0, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)), gasYAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 1, 2, TIME_GRID, true, true,
timeAxis(new TimeAxis(DiveCartesianAxis::Position::Bottom, 2, 2, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)), dpr, 0.7, printMode, isGrayscale, *this)),
cylinderPressureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 4, 0, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)), temperatureAxis(new TemperatureAxis(DiveCartesianAxis::Position::Right, 3, 0, TIME_GRID, false, false,
heartBeatAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, 3, 0, HR_AXIS, dpr, 0.7, printMode, isGrayscale, *this)), dpr, 1.0, printMode, isGrayscale, *this)),
percentageAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 2, 0, TIME_GRID, dpr, 0.7, printMode, isGrayscale, *this)), timeAxis(new TimeAxis(DiveCartesianAxis::Position::Bottom, 2, 2, TIME_GRID, true, true,
dpr, 1.0, printMode, isGrayscale, *this)),
cylinderPressureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 4, 0, TIME_GRID, false, false,
dpr, 1.0, printMode, isGrayscale, *this)),
heartBeatAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, 3, 0, HR_AXIS, true, true,
dpr, 0.7, printMode, isGrayscale, *this)),
percentageAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 2, 0, TIME_GRID, false, false,
dpr, 0.7, printMode, isGrayscale, *this)),
diveProfileItem(createItem<DiveProfileItem>(*profileYAxis, DivePlotDataModel::DEPTH, 0, dpr)), diveProfileItem(createItem<DiveProfileItem>(*profileYAxis, DivePlotDataModel::DEPTH, 0, dpr)),
temperatureItem(createItem<DiveTemperatureItem>(*temperatureAxis, DivePlotDataModel::TEMPERATURE, 1, dpr)), temperatureItem(createItem<DiveTemperatureItem>(*temperatureAxis, DivePlotDataModel::TEMPERATURE, 1, dpr)),
meanDepthItem(createItem<DiveMeanDepthItem>(*profileYAxis, DivePlotDataModel::INSTANT_MEANDEPTH, 1, dpr)), meanDepthItem(createItem<DiveMeanDepthItem>(*profileYAxis, DivePlotDataModel::INSTANT_MEANDEPTH, 1, dpr)),
@ -95,17 +102,6 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
cylinderPressureAxis->setOrientation(DiveCartesianAxis::BottomToTop); cylinderPressureAxis->setOrientation(DiveCartesianAxis::BottomToTop);
heartBeatAxis->setTextVisible(true);
heartBeatAxis->setLinesVisible(true);
percentageAxis->setTextVisible(true);
percentageAxis->setLinesVisible(true);
temperatureAxis->setTextVisible(false);
temperatureAxis->setLinesVisible(false);
cylinderPressureAxis->setTextVisible(false);
cylinderPressureAxis->setLinesVisible(false);
timeAxis->setLinesVisible(true);
profileYAxis->setLinesVisible(true);
gasYAxis->setZValue(timeAxis->zValue() + 1); gasYAxis->setZValue(timeAxis->zValue() + 1);
tankItem->setZValue(100); tankItem->setZValue(100);