[apps/calc] Display ApproximateOnly if exact layout cannot be created

This commit is contained in:
Léa Saviot
2020-01-14 14:41:44 +01:00
parent 8e407bd01e
commit 1af28d4310
4 changed files with 100 additions and 41 deletions

View File

@@ -1,4 +1,5 @@
#include "scrollable_input_exact_approximate_expressions_cell.h"
#include <poincare/exception_checkpoint.h>
#include "../app.h"
namespace Calculation {
@@ -17,9 +18,20 @@ void ScrollableInputExactApproximateExpressionsView::setCalculation(Calculation
contentCell()->leftExpressionView()->setLayout(Poincare::Layout());
setLayouts(Poincare::Layout(), Poincare::Layout());
Calculation::DisplayOutput displayOutput = calculation->displayOutput(context);
contentCell()->leftExpressionView()->setLayout(calculation->createInputLayout());
Poincare::Layout leftOutputLayout = calculation->createExactOutputLayout();
Poincare::Layout leftOutputLayout = Poincare::Layout();
if (Calculation::DisplaysExact(calculation->displayOutput(context))) {
bool couldNotCreateExactLayout = false;
leftOutputLayout = calculation->createExactOutputLayout(&couldNotCreateExactLayout);
if (couldNotCreateExactLayout) {
if (calculation->displayOutput(context) == ::Calculation::Calculation::DisplayOutput::ExactOnly) {
Poincare::ExceptionCheckpoint::Raise();
} else {
calculation->forceDisplayOutput(::Calculation::Calculation::DisplayOutput::ApproximateOnly);
}
}
}
Calculation::DisplayOutput displayOutput = calculation->displayOutput(context);
Poincare::Layout rightOutputLayout = (displayOutput == Calculation::DisplayOutput::ExactOnly) ? leftOutputLayout :
calculation->createApproximateOutputLayout(context);
setLayouts(rightOutputLayout, leftOutputLayout);

View File

@@ -72,33 +72,67 @@ Layout Calculation::createInputLayout() {
return input().createLayout(Preferences::PrintFloatMode::Decimal, PrintFloat::k_numberOfStoredSignificantDigits);
}
Layout Calculation::createExactOutputLayout() {
return PoincareHelpers::CreateLayout(exactOutput());
Layout Calculation::createExactOutputLayout(bool * couldNotCreateExactLayout) {
Poincare::ExceptionCheckpoint ecp;
if (ExceptionRun(ecp)) {
return PoincareHelpers::CreateLayout(exactOutput());
} else {
*couldNotCreateExactLayout = true;
return Layout();
}
}
Layout Calculation::createApproximateOutputLayout(Context * context) {
return PoincareHelpers::CreateLayout(approximateOutput(context));
Poincare::ExceptionCheckpoint ecp;
if (ExceptionRun(ecp)) {
return PoincareHelpers::CreateLayout(approximateOutput(context));
} else {
return Layout();
}
}
KDCoordinate Calculation::height(Context * context, bool expanded, bool allExpressionsInline) {
KDCoordinate result = expanded ? m_expandedHeight : m_height;
if (result < 0) {
DisplayOutput display = displayOutput(context);
Layout inputLayout = createInputLayout();
KDCoordinate inputHeight = inputLayout.layoutSize().height();
KDCoordinate inputBaseline = inputLayout.baseline();
if (display == DisplayOutput::ExactOnly) {
Layout exactLayout = createExactOutputLayout();
KDCoordinate exactOutputHeight = exactLayout.layoutSize().height();
if (allExpressionsInline) {
KDCoordinate exactOutputBaseline = exactLayout.baseline();
result = maxCoordinate(inputBaseline, exactOutputBaseline) + maxCoordinate(inputHeight - inputBaseline, exactOutputHeight-exactOutputBaseline);
KDCoordinate result = expanded ? m_expandedHeight : m_height;
if (result >= 0) {
// Height already computed
return result;
}
// Get input height
Layout inputLayout = createInputLayout();
KDCoordinate inputHeight = inputLayout.layoutSize().height();
KDCoordinate inputBaseline = inputLayout.baseline();
// Get exact output height if needed
Poincare::Layout exactLayout;
bool couldNotCreateExactLayout = false;
if (DisplaysExact(displayOutput(context))) {
// Create the exact output layout
exactLayout = createExactOutputLayout(&couldNotCreateExactLayout);
if (couldNotCreateExactLayout) {
if (displayOutput(context) != DisplayOutput::ExactOnly) {
forceDisplayOutput(DisplayOutput::ApproximateOnly);
} else {
result = inputHeight+exactOutputHeight;
/* We should only display the exact result, but we cannot create it
* -> raise an exception. */
ExceptionCheckpoint::Raise();
}
} else if (display == DisplayOutput::ApproximateOnly || (!expanded && display == DisplayOutput::ExactAndApproximateToggle)) {
Layout approximateLayout = createApproximateOutputLayout(context);
KDCoordinate approximateOutputHeight = approximateLayout.layoutSize().height();
}
}
DisplayOutput display = displayOutput(context);
if (display == DisplayOutput::ExactOnly) {
KDCoordinate exactOutputHeight = exactLayout.layoutSize().height();
if (allExpressionsInline) {
KDCoordinate exactOutputBaseline = exactLayout.baseline();
result = maxCoordinate(inputBaseline, exactOutputBaseline) + maxCoordinate(inputHeight - inputBaseline, exactOutputHeight-exactOutputBaseline);
} else {
result = inputHeight+exactOutputHeight;
}
} else {
Layout approximateLayout = createApproximateOutputLayout(context);
KDCoordinate approximateOutputHeight = approximateLayout.layoutSize().height();
if (display == DisplayOutput::ApproximateOnly || (!expanded && display == DisplayOutput::ExactAndApproximateToggle)) {
if (allExpressionsInline) {
KDCoordinate approximateOutputBaseline = approximateLayout.baseline();
result = maxCoordinate(inputBaseline, approximateOutputBaseline) + maxCoordinate(inputHeight - inputBaseline, approximateOutputHeight-approximateOutputBaseline);
@@ -107,31 +141,29 @@ KDCoordinate Calculation::height(Context * context, bool expanded, bool allExpre
}
} else {
assert(display == DisplayOutput::ExactAndApproximate || (display == DisplayOutput::ExactAndApproximateToggle && expanded));
Layout approximateLayout = createApproximateOutputLayout(context);
Layout exactLayout = createExactOutputLayout();
KDCoordinate approximateOutputHeight = approximateLayout.layoutSize().height();
KDCoordinate exactOutputHeight = exactLayout.layoutSize().height();
KDCoordinate exactOutputBaseline = exactLayout.baseline();
KDCoordinate approximateOutputBaseline = approximateLayout.baseline();
if (allExpressionsInline) {
result = maxCoordinate(inputBaseline, maxCoordinate(exactOutputBaseline, approximateOutputBaseline)) + maxCoordinate(inputHeight - inputBaseline, maxCoordinate(exactOutputHeight - exactOutputBaseline, approximateOutputHeight-approximateOutputBaseline));
} else {
KDCoordinate outputHeight = maxCoordinate(exactOutputBaseline, approximateOutputBaseline) + maxCoordinate(exactOutputHeight-exactOutputBaseline, approximateOutputHeight-approximateOutputBaseline);
result = inputHeight + outputHeight;
KDCoordinate outputHeight = maxCoordinate(exactOutputBaseline, approximateOutputBaseline) + maxCoordinate(exactOutputHeight-exactOutputBaseline, approximateOutputHeight-approximateOutputBaseline);
result = inputHeight + outputHeight;
}
}
/* For all display output except ExactAndApproximateToggle, the selected
* height and the usual height are identical. We update both heights in
* theses cases. */
if (display != DisplayOutput::ExactAndApproximateToggle) {
m_height = result;
}
/* For all display outputs except ExactAndApproximateToggle, the selected
* height and the usual height are identical. We update both heights in
* theses cases. */
if (display != DisplayOutput::ExactAndApproximateToggle) {
m_height = result;
m_expandedHeight = result;
} else {
if (expanded) {
m_expandedHeight = result;
} else {
if (expanded) {
m_expandedHeight = result;
} else {
m_height = result;
}
m_height = result;
}
}
return result;

View File

@@ -33,6 +33,7 @@ public:
ExactAndApproximate,
ExactAndApproximateToggle
};
static bool DisplaysExact(DisplayOutput d) { return d != DisplayOutput::ApproximateOnly; }
/* It is not really the minimal size, but it clears enough space for most
* calculations instead of clearing less space, then fail to serialize, clear
@@ -65,7 +66,7 @@ public:
// Layouts
Poincare::Layout createInputLayout();
Poincare::Layout createExactOutputLayout();
Poincare::Layout createExactOutputLayout(bool * couldNotCreateExactLayout);
Poincare::Layout createApproximateOutputLayout(Poincare::Context * context);
// Memoization of height
@@ -73,6 +74,7 @@ public:
// Displayed output
DisplayOutput displayOutput(Poincare::Context * context);
void forceDisplayOutput(DisplayOutput d) { m_displayOutput = d; }
bool shouldOnlyDisplayExactOutput();
EqualSign exactAndApproximateDisplayedOutputsAreEqual(Poincare::Context * context);

View File

@@ -2,6 +2,7 @@
#include "app.h"
#include "../constant.h"
#include "selectable_table_view.h"
#include <poincare/exception_checkpoint.h>
#include <assert.h>
#include <string.h>
@@ -177,15 +178,27 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) {
// Memoization
m_calculationCRC32 = newCalculationCRC;
m_calculationExpanded = expanded;
m_calculationDisplayOutput = calculation->displayOutput(context);
m_calculationAdditionInformation = calculation->additionalInformationType(context);
m_inputView.setLayout(calculation->createInputLayout());
/* Both output expressions have to be updated at the same time. Otherwise,
* when updating one layout, if the second one still points to a deleted
* layout, calling to layoutSubviews() would fail. */
Poincare::Layout leftOutputLayout = calculation->createExactOutputLayout();
Poincare::Layout rightOutputLayout = (m_calculationDisplayOutput == Calculation::DisplayOutput::ExactOnly) ? leftOutputLayout :
calculation->createApproximateOutputLayout(context);
Poincare::Layout leftOutputLayout = Poincare::Layout();
if (Calculation::DisplaysExact(calculation->displayOutput(context))) {
bool couldNotCreateExactLayout = false;
leftOutputLayout = calculation->createExactOutputLayout(&couldNotCreateExactLayout);
if (couldNotCreateExactLayout) {
if (calculation->displayOutput(context) != ::Calculation::Calculation::DisplayOutput::ExactOnly) {
calculation->forceDisplayOutput(::Calculation::Calculation::DisplayOutput::ApproximateOnly);
} else {
/* We should only display the exact result, but we cannot create it
* -> raise an exception. */
Poincare::ExceptionCheckpoint::Raise();
}
}
}
m_calculationDisplayOutput = calculation->displayOutput(context);
Poincare::Layout rightOutputLayout = (m_calculationDisplayOutput == Calculation::DisplayOutput::ExactOnly) ? leftOutputLayout : calculation->createApproximateOutputLayout(context);
// We must set which subviews are displayed before setLayouts to mark the right rectangle as dirty
m_scrollableOutputView.setDisplayLeft(m_calculationExpanded && m_calculationAdditionInformation != Poincare::Expression::AdditionalInformationType::None);
m_scrollableOutputView.setDisplayCenter(m_calculationDisplayOutput == Calculation::DisplayOutput::ExactAndApproximate || (m_calculationExpanded && m_calculationDisplayOutput == Calculation::DisplayOutput::ExactAndApproximateToggle));