diff --git a/profile-widget/divecartesianaxis.cpp b/profile-widget/divecartesianaxis.cpp index 1515b78d6..12b9999c4 100644 --- a/profile-widget/divecartesianaxis.cpp +++ b/profile-widget/divecartesianaxis.cpp @@ -70,15 +70,6 @@ void DiveCartesianAxis::setTransform(double a, double b) transform.b = b; } -template -void emptyList(QList &list, int steps, int speed) -{ - while (list.size() > steps) { - T *removedItem = list.takeLast(); - Animations::animDelete(removedItem, speed); - } -} - double DiveCartesianAxis::width() const { return labelWidth + labelSpaceHorizontal * dpr; @@ -151,6 +142,10 @@ void DiveCartesianAxis::updateTicks(int animSpeed) if (!textVisibility && !lineVisibility) return; // Nothing to display... + // Remember the old range for animations. + double dataMaxOld = dataMax; + double dataMinOld = dataMin; + // Guess the number of tick marks. QLineF m = line(); double spaceNeeded = position == Position::Bottom ? labelWidth * 3.0 / 2.0 @@ -188,8 +183,6 @@ void DiveCartesianAxis::updateTicks(int animSpeed) numTicks = lrint((lastDisplay - firstDisplay) / intervalDisplay) + 1; numTicks = std::max(numTicks, 0); - emptyList(labels, numTicks, animSpeed); - emptyList(lines, numTicks, animSpeed); if (numTicks == 0) return; @@ -209,100 +202,151 @@ void DiveCartesianAxis::updateTicks(int animSpeed) (inverted ? m.x2() - offsetScreen : m.x1() + offsetScreen) : (inverted ? m.y1() + offsetScreen : m.y2() - offsetScreen); - if (textVisibility) - updateLabels(numTicks, firstPosScreen, firstValue, stepScreen, stepValue, animSpeed); - if (lineVisibility) - updateLines(numTicks, firstPosScreen, stepScreen, animSpeed); + updateLabels(numTicks, firstPosScreen, firstValue, stepScreen, stepValue, animSpeed, dataMinOld, dataMaxOld); } -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 = ((position == Position::Bottom) != inverted) ? - firstPosScreen + i * stepScreen : - firstPosScreen - i * stepScreen; - labels[i]->set(textForValue(firstValue), textColor); - switch (position) { - default: - case Position::Bottom: - Animations::moveTo(labels[i], animSpeed, childPos, rect.bottom() + labelSpaceVertical * dpr); - break; - case Position::Left: - Animations::moveTo(labels[i], animSpeed, rect.left() - labelSpaceHorizontal * dpr, childPos); - break; - case Position::Right: - Animations::moveTo(labels[i], animSpeed, rect.right() + labelSpaceHorizontal * dpr, childPos); - break; - } - } - // Add the rest of the needed labels. - for (int i = labels.size(); i < numTicks; i++, firstValue += stepValue) { - double childPos = ((position == Position::Bottom) != inverted) ? - firstPosScreen + i * stepScreen : - firstPosScreen - i * stepScreen; +QPointF DiveCartesianAxis::labelPos(double pos) const +{ + return position == Position::Bottom ? QPointF(pos, rect.bottom() + labelSpaceVertical * dpr) : + position == Position::Left ? QPointF(rect.left() - labelSpaceHorizontal * dpr, pos) : + QPointF(rect.right() + labelSpaceHorizontal * dpr, pos); +} + +QLineF DiveCartesianAxis::linePos(double pos) const +{ + return position == Position::Bottom ? QLineF(pos, rect.top(), pos, rect.bottom()) : + QLineF(rect.left(), pos, rect.right(), pos); +} + +void DiveCartesianAxis::updateLabel(Label &label, double opacityEnd, double pos) const +{ + label.opacityStart = textVisibility ? label.label->opacity() + : label.line->opacity(); + label.opacityEnd = opacityEnd; + if (textVisibility) { + label.labelPosStart = label.label->pos(); + label.labelPosEnd = labelPos(pos); + } + if (lineVisibility) { + label.lineStart = label.line->line(); + label.lineEnd = linePos(pos); + } +} + +DiveCartesianAxis::Label DiveCartesianAxis::createLabel(double value, double pos, double dataMinOld, double dataMaxOld, int animSpeed) +{ + Label label { value, 0.0, 1.0 }; + double posStart = posAtValue(value, dataMaxOld, dataMinOld); + if (textVisibility) { + label.labelPosStart = labelPos(posStart); + label.labelPosEnd = labelPos(pos); int alignFlags = position == Position::Bottom ? Qt::AlignTop | Qt::AlignHCenter : position == Position::Left ? Qt::AlignVCenter | Qt::AlignLeft: Qt::AlignVCenter | Qt::AlignRight; - DiveTextItem *label = new DiveTextItem(dpr, labelScale, alignFlags, this); - label->set(textForValue(firstValue), textColor); - label->setZValue(1); - labels.push_back(label); - switch (position) { - default: - case Position::Bottom: - label->setPos(scene.sceneRect().width() + 10, rect.bottom() + labelSpaceVertical * dpr); // position it outside of the scene; - Animations::moveTo(labels[i], animSpeed, childPos, rect.bottom() + labelSpaceVertical * dpr); - break; - case Position::Left: - label->setPos(rect.left() - labelSpaceHorizontal * dpr, scene.sceneRect().height() + 10); - Animations::moveTo(labels[i], animSpeed, rect.left() - labelSpaceHorizontal * dpr, childPos); - break; - case Position::Right: - label->setPos(rect.right() + labelSpaceHorizontal * dpr, scene.sceneRect().height() + 10); - Animations::moveTo(labels[i], animSpeed, rect.right() + labelSpaceHorizontal * dpr, childPos); - break; - } + label.label = std::make_unique(dpr, labelScale, alignFlags, this); + label.label->set(textForValue(value), textColor); + label.label->setZValue(1); + label.label->setPos(animSpeed <= 0 ? label.labelPosEnd : label.labelPosStart); + label.label->setOpacity(animSpeed <= 0 ? 1.0 : 0.0); } + if (lineVisibility) { + label.lineStart = linePos(posStart); + label.lineEnd = linePos(pos); + label.line = std::make_unique(this); + label.line->setPen(gridPen); + label.line->setZValue(0); + label.line->setLine(animSpeed <= 0 ? label.lineEnd : label.lineStart); + label.line->setOpacity(animSpeed <= 0 ? 1.0 : 0.0); + } + return label; } -void DiveCartesianAxis::updateLines(int numTicks, double firstPosScreen, double stepScreen, int animSpeed) +void DiveCartesianAxis::updateLabels(int numTicks, double firstPosScreen, double firstValue, double stepScreen, double stepValue, + int animSpeed, double dataMinOld, double dataMaxOld) { - for (int i = 0, count = lines.size(); i < count; i++) { - double childPos = ((position == Position::Bottom) != inverted) ? - firstPosScreen + i * stepScreen : - firstPosScreen - i * stepScreen; + if (animSpeed <= 0) + labels.clear(); // No animation? Simply redo the labels. - 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()); + std::vector