Files
Upsilon/apps/calculation/additional_outputs/scrollable_three_expressions_cell.cpp
Émilie Feral df74c2c551 [apps/calculation] The heights (common and expanded) of calculation cells are
computed when the calculation is added to the store and don't change afterwards.
Otherwise, if their heights change when scrolling (due to a modification of the
display output type - ExactOnly, ApproximateOnly...), it generates crashes.
2020-07-16 14:37:38 +02:00

102 lines
4.2 KiB
C++

#include "scrollable_three_expressions_cell.h"
#include <poincare/exception_checkpoint.h>
#include "../app.h"
namespace Calculation {
void ScrollableThreeExpressionsView::resetMemoization() {
setLayouts(Poincare::Layout(), Poincare::Layout(), Poincare::Layout());
}
// TODO: factorize with HistoryViewCell!
void ScrollableThreeExpressionsView::setCalculation(Calculation * calculation, bool canChangeDisplayOutput) {
Poincare::Context * context = App::app()->localContext();
// Clean the layouts to make room in the pool
resetMemoization();
// Create the input layout
Poincare::Layout inputLayout = calculation->createInputLayout();
// Create the exact output layout
Poincare::Layout exactOutputLayout = Poincare::Layout();
if (Calculation::DisplaysExact(calculation->displayOutput(context))) {
bool couldNotCreateExactLayout = false;
exactOutputLayout = calculation->createExactOutputLayout(&couldNotCreateExactLayout);
if (couldNotCreateExactLayout) {
if (canChangeDisplayOutput && calculation->displayOutput(context) != ::Calculation::Calculation::DisplayOutput::ExactOnly) {
calculation->forceDisplayOutput(::Calculation::Calculation::DisplayOutput::ApproximateOnly);
} else {
Poincare::ExceptionCheckpoint::Raise();
}
}
}
Calculation::DisplayOutput displayOutput = calculation->displayOutput(context);
// Create the approximate output layout
Poincare::Layout approximateOutputLayout = Poincare::Layout();
if (displayOutput == Calculation::DisplayOutput::ExactOnly) {
approximateOutputLayout = exactOutputLayout;
} else {
bool couldNotCreateApproximateLayout = false;
approximateOutputLayout = calculation->createApproximateOutputLayout(context, &couldNotCreateApproximateLayout);
if (couldNotCreateApproximateLayout) {
if (canChangeDisplayOutput && calculation->displayOutput(context) != ::Calculation::Calculation::DisplayOutput::ApproximateOnly) {
/* Set the display output to ApproximateOnly, make room in the pool by
* erasing the exact layout, and retry to create the approximate layout */
calculation->forceDisplayOutput(::Calculation::Calculation::DisplayOutput::ApproximateOnly);
exactOutputLayout = Poincare::Layout();
couldNotCreateApproximateLayout = false;
approximateOutputLayout = calculation->createApproximateOutputLayout(context, &couldNotCreateApproximateLayout);
if (couldNotCreateApproximateLayout) {
Poincare::ExceptionCheckpoint::Raise();
}
} else {
Poincare::ExceptionCheckpoint::Raise();
}
}
}
setLayouts(inputLayout, exactOutputLayout, approximateOutputLayout);
I18n::Message equalMessage = calculation->exactAndApproximateDisplayedOutputsAreEqual(context) == Calculation::EqualSign::Equal ? I18n::Message::Equal : I18n::Message::AlmostEqual;
setEqualMessage(equalMessage);
/* The displayed input and outputs have changed. We need to re-layout the cell
* and re-initialize the scroll. */
layoutSubviews();
}
KDCoordinate ScrollableThreeExpressionsCell::Height(Calculation * calculation) {
ScrollableThreeExpressionsCell cell;
cell.setCalculation(calculation, true);
KDRect leftFrame = KDRectZero;
KDRect centerFrame = KDRectZero;
KDRect approximateSignFrame = KDRectZero;
KDRect rightFrame = KDRectZero;
cell.subviewFrames(&leftFrame, &centerFrame, &approximateSignFrame, &rightFrame);
KDRect unionedFrame = leftFrame.unionedWith(centerFrame).unionedWith(rightFrame);
return unionedFrame.height() + 2 * ScrollableThreeExpressionsView::k_margin;
}
void ScrollableThreeExpressionsCell::didBecomeFirstResponder() {
reinitSelection();
Container::activeApp()->setFirstResponder(&m_view);
}
void ScrollableThreeExpressionsCell::reinitSelection() {
m_view.setSelectedSubviewPosition(ScrollableThreeExpressionsView::SubviewPosition::Left);
m_view.reloadScroll();
}
void ScrollableThreeExpressionsCell::setCalculation(Calculation * calculation, bool canChangeDisplayOutput) {
m_view.setCalculation(calculation, canChangeDisplayOutput);
layoutSubviews();
}
void ScrollableThreeExpressionsCell::setDisplayCenter(bool display) {
m_view.setDisplayCenter(display);
layoutSubviews();
}
}