diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index ca0422fcb..ee076fbbe 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -126,6 +126,9 @@ Layout Calculation::createApproximateOutputLayout(Context * context, bool * coul } KDCoordinate Calculation::height(Context * context, KDCoordinate verticalMarginBetweenLayouts, KDCoordinate verticalMarginAroundLayouts, bool expanded, bool forceSingleLine, LayoutsCanBeSingleLineFunction canBeSingleLine) { + /* WARNING: this method must return the same result as + * Calculation::HistoryViewCell::layoutSubviews. */ + KDCoordinate result = expanded ? m_expandedHeight : m_height; if (result >= 0) { // Height already computed @@ -138,12 +141,19 @@ KDCoordinate Calculation::height(Context * context, KDCoordinate verticalMarginB KDCoordinate inputWidth = inputLayout.layoutSize().width(); KDCoordinate inputBaseline = inputLayout.baseline(); + // Get output height KDCoordinate outputWidth; KDCoordinate outputBaseline; KDCoordinate outputHeightBelowBaseline; + + DisplayOutput displayType = displayOutput(context); + /* If the display output is ExactAndApproximateToggle, we want to use the + * expanded width to compute if the calculaton is in single line or not. */ + bool shouldComputeMaxOutputWidthForSingleLine = !forceSingleLine && (!expanded && displayType == DisplayOutput::ExactAndApproximateToggle); + KDCoordinate maxOutputWidth = -1; + { - DisplayOutput displayType = displayOutput(context); bool displaysExactOnly = displayType == DisplayOutput::ExactOnly; bool displayApproximateOnly = displayType == DisplayOutput::ApproximateOnly || (!expanded @@ -154,7 +164,8 @@ KDCoordinate Calculation::height(Context * context, KDCoordinate verticalMarginB KDCoordinate exactOutputBelowBaseline = 0; // Get exact output info if needed - if (displaysExactOnly || !displayApproximateOnly) { + bool displaysExact = displaysExactOnly || !displayApproximateOnly; + if (displaysExact || shouldComputeMaxOutputWidthForSingleLine) { bool couldNotCreateExactLayout = false; Poincare::Layout exactLayout = createExactOutputLayout(&couldNotCreateExactLayout); if (couldNotCreateExactLayout) { @@ -170,9 +181,12 @@ KDCoordinate Calculation::height(Context * context, KDCoordinate verticalMarginB } } else { KDSize exactSize = exactLayout.layoutSize(); - exactOutputWidth = exactSize.width(); - exactOutputBaseline = exactLayout.baseline(); - exactOutputBelowBaseline = exactSize.height() - exactOutputBaseline; + maxOutputWidth = exactSize.width(); + if (displaysExact) { + exactOutputWidth = exactSize.width(); + exactOutputBaseline = exactLayout.baseline(); + exactOutputBelowBaseline = exactSize.height() - exactOutputBaseline; + } } } @@ -181,19 +195,24 @@ KDCoordinate Calculation::height(Context * context, KDCoordinate verticalMarginB KDCoordinate approximateOutputBelowBaseline = 0; // Get approximate output info if needed - if (displayApproximateOnly || !displaysExactOnly) { + bool displaysApproximate = displayApproximateOnly || !displaysExactOnly; + if (displaysApproximate || shouldComputeMaxOutputWidthForSingleLine) { bool couldNotCreateApproximateLayout = false; Layout approximateLayout = createApproximateOutputLayout(context, &couldNotCreateApproximateLayout); if (couldNotCreateApproximateLayout) { Poincare::ExceptionCheckpoint::Raise(); } KDSize approximateOutputSize = approximateLayout.layoutSize(); - approximateOutputWidth = approximateOutputSize.width(); - approximateOutputBaseline = approximateLayout.baseline(); - approximateOutputBelowBaseline = approximateOutputSize.height() - approximateOutputBaseline; + maxOutputWidth += approximateOutputSize.width(); + if (displaysApproximate) { + approximateOutputWidth = approximateOutputSize.width(); + approximateOutputBaseline = approximateLayout.baseline(); + approximateOutputBelowBaseline = approximateOutputSize.height() - approximateOutputBaseline; + } } // Compute the output info + maxOutputWidth += AbstractScrollableMultipleExpressionsView::StandardApproximateViewAndMarginsSize(); outputWidth = exactOutputWidth + ((exactOutputWidth > 0 && approximateOutputWidth > 0) ? AbstractScrollableMultipleExpressionsView::StandardApproximateViewAndMarginsSize() : 0) + approximateOutputWidth; @@ -201,7 +220,7 @@ KDCoordinate Calculation::height(Context * context, KDCoordinate verticalMarginB outputHeightBelowBaseline = std::max(exactOutputBelowBaseline, approximateOutputBelowBaseline); } - if (forceSingleLine || canBeSingleLine(inputWidth, outputWidth)) { + if (forceSingleLine || canBeSingleLine(inputWidth, maxOutputWidth)) { result = std::max(inputBaseline, outputBaseline) // Above the baseline + std::max(static_cast(inputHeight - inputBaseline), outputHeightBelowBaseline) // Below the baseline + 2 * verticalMarginAroundLayouts; diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 53b42f0f1..981a34018 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -155,7 +155,6 @@ View * HistoryViewCell::subviewAtIndex(int index) { } bool HistoryViewCell::LayoutsCanBeSingleLine(KDCoordinate inputLayoutWidth, KDCoordinate outputLayoutWidth) { - // k_margin is the separation between the input and output. return ViewsCanBeSingleLine(inputLayoutWidth + 2 * k_inputOutputViewsHorizontalMargin, outputLayoutWidth + 2 * k_inputOutputViewsHorizontalMargin); } @@ -175,7 +174,9 @@ void HistoryViewCell::layoutSubviews(bool force) { KDSize inputSize = m_inputView.minimalSizeForOptimalDisplay(); KDSize outputSize = m_scrollableOutputView.minimalSizeForOptimalDisplay(); - m_calculationSingleLine = ViewsCanBeSingleLine(inputSize.width(), outputSize.width()); + /* To compute if the calculation is on a single line, use the expanded width + * if there is both an exact and an approximate layout. */ + m_calculationSingleLine = ViewsCanBeSingleLine(inputSize.width(), m_scrollableOutputView.minimalSizeForOptimalDisplayFullSize().width()); KDCoordinate inputY = k_margin; KDCoordinate outputY = k_margin; diff --git a/apps/shared/scrollable_multiple_expressions_view.cpp b/apps/shared/scrollable_multiple_expressions_view.cpp index 0af626941..497647f8b 100644 --- a/apps/shared/scrollable_multiple_expressions_view.cpp +++ b/apps/shared/scrollable_multiple_expressions_view.cpp @@ -55,37 +55,11 @@ void AbstractScrollableMultipleExpressionsView::ContentCell::reloadTextColor() { } KDSize AbstractScrollableMultipleExpressionsView::ContentCell::minimalSizeForOptimalDisplay() const { - KDCoordinate width = 0; + return privateMinimalSizeForOptimalDisplay(false); +} - // Compute baselines - KDCoordinate leftBaseline = 0; - KDCoordinate centerBaseline = 0; - KDCoordinate rightBaseline = 0; - KDCoordinate viewBaseline = baseline(&leftBaseline, ¢erBaseline, &rightBaseline); - - KDSize leftSize = KDSizeZero; - if (leftExpressionView() && !leftExpressionView()->layout().isUninitialized()) { - leftSize = leftExpressionView()->minimalSizeForOptimalDisplay(); - width += leftSize.width() + AbstractScrollableMultipleExpressionsView::k_horizontalMargin; - } - - KDSize centerSize = KDSizeZero; - if (displayCenter()) { - centerSize = m_centeredExpressionView.minimalSizeForOptimalDisplay(); - width += centerSize.width() + 2 * AbstractScrollableMultipleExpressionsView::k_horizontalMargin + m_approximateSign.minimalSizeForOptimalDisplay().width(); - } - - KDSize rightSize = m_rightExpressionView.minimalSizeForOptimalDisplay(); - width += rightSize.width(); - - KDCoordinate height = viewBaseline - + std::max( - std::max( - centerSize.height() - centerBaseline, - rightSize.height() - rightBaseline), - leftSize.height() - leftBaseline); - - return KDSize(width, height); +KDSize AbstractScrollableMultipleExpressionsView::ContentCell::minimalSizeForOptimalDisplayFullSize() const { + return privateMinimalSizeForOptimalDisplay(true); } void AbstractScrollableMultipleExpressionsView::ContentCell::setSelectedSubviewPosition(AbstractScrollableMultipleExpressionsView::SubviewPosition subviewPosition) { @@ -147,6 +121,40 @@ KDCoordinate AbstractScrollableMultipleExpressionsView::ContentCell::baseline(KD return std::max(std::max(leftViewBaseline, centerViewBaseline), rightViewBaseline); } +KDSize AbstractScrollableMultipleExpressionsView::ContentCell::privateMinimalSizeForOptimalDisplay(bool forceFullDisplay) const { + KDCoordinate width = 0; + + // Compute baselines + KDCoordinate leftBaseline = 0; + KDCoordinate centerBaseline = 0; + KDCoordinate rightBaseline = 0; + KDCoordinate viewBaseline = baseline(&leftBaseline, ¢erBaseline, &rightBaseline); + + KDSize leftSize = KDSizeZero; + if (leftExpressionView() && !leftExpressionView()->layout().isUninitialized()) { + leftSize = leftExpressionView()->minimalSizeForOptimalDisplay(); + width += leftSize.width() + AbstractScrollableMultipleExpressionsView::k_horizontalMargin; + } + + KDSize centerSize = KDSizeZero; + if (displayCenter() || (forceFullDisplay && !m_centeredExpressionView.layout().isUninitialized())) { + centerSize = m_centeredExpressionView.minimalSizeForOptimalDisplay(); + width += centerSize.width() + 2 * AbstractScrollableMultipleExpressionsView::k_horizontalMargin + m_approximateSign.minimalSizeForOptimalDisplay().width(); + } + + KDSize rightSize = m_rightExpressionView.minimalSizeForOptimalDisplay(); + width += rightSize.width(); + + KDCoordinate height = viewBaseline + + std::max( + std::max( + centerSize.height() - centerBaseline, + rightSize.height() - rightBaseline), + leftSize.height() - leftBaseline); + + return KDSize(width, height); +} + View * AbstractScrollableMultipleExpressionsView::ContentCell::subviewAtIndex(int index) { bool leftIsVisible = leftExpressionView() != nullptr; if (leftIsVisible && index == 0) { diff --git a/apps/shared/scrollable_multiple_expressions_view.h b/apps/shared/scrollable_multiple_expressions_view.h index 9e8961d21..5e4574415 100644 --- a/apps/shared/scrollable_multiple_expressions_view.h +++ b/apps/shared/scrollable_multiple_expressions_view.h @@ -47,6 +47,7 @@ protected: void setEven(bool even) override; void reloadTextColor(); KDSize minimalSizeForOptimalDisplay() const override; + KDSize minimalSizeForOptimalDisplayFullSize() const; virtual ExpressionView * leftExpressionView() const { return nullptr; } ExpressionView * rightExpressionView() { return &m_rightExpressionView; @@ -70,6 +71,7 @@ protected: private: constexpr static const KDFont * k_font = KDFont::LargeFont; const static I18n::Message k_defaultApproximateMessage = I18n::Message::AlmostEqual; + KDSize privateMinimalSizeForOptimalDisplay(bool forceFullDisplay) const; View * subviewAtIndex(int index) override; ExpressionView m_rightExpressionView; MessageTextView m_approximateSign; @@ -91,7 +93,9 @@ public: Metric::CommonLargeMargin ); } - + KDSize minimalSizeForOptimalDisplayFullSize() const { + return constContentCell()->minimalSizeForOptimalDisplayFullSize(); + } private: ContentCell * contentCell() override { return &m_contentCell; }; const ContentCell * constContentCell() const override { return &m_contentCell; };