diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 9fb134d2c..69be56c49 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -147,15 +147,16 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl if (evaluation) { /* TODO: implement list contexts */ // TODO: handle matrix and scalar! + ExpressionLayout * layout = expressionLayoutForIndex(index); const Matrix * matrixEvaluation = static_cast(evaluation); - myCell->setExpression(matrixEvaluation); + myCell->setExpressionLayout(layout); char buffer[2*PrintFloat::bufferSizeForFloatsWithPrecision(2)+1]; int numberOfChars = PrintFloat::convertFloatToText(matrixEvaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, PrintFloat::Mode::Decimal); buffer[numberOfChars++] = 'x'; PrintFloat::convertFloatToText(matrixEvaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, PrintFloat::Mode::Decimal); myCell->setSubtitle(buffer); } else { - myCell->setExpression(nullptr); + myCell->setExpressionLayout(nullptr); myCell->setSubtitle(I18n::translate(I18n::Message::Empty)); } } @@ -164,12 +165,9 @@ KDCoordinate VariableBoxController::ContentViewController::rowHeight(int index) if (m_currentPage == Page::RootMenu || m_currentPage == Page::Scalar) { return Metric::ToolboxRowHeight; } - const Expression * expression = expressionForIndex(index); - if (expression) { - ExpressionLayout * layout = expression->createLayout(); - KDCoordinate expressionHeight = layout->size().height(); - delete layout; - return expressionHeight+k_leafMargin; + ExpressionLayout * expressionLayout = expressionLayoutForIndex(index); + if (expressionLayout) { + return expressionLayout->size().height()+k_leafMargin; } return Metric::ToolboxRowHeight; } @@ -215,6 +213,19 @@ const Expression * VariableBoxController::ContentViewController::expressionForIn return nullptr; } +ExpressionLayout * VariableBoxController::ContentViewController::expressionLayoutForIndex(int index) { + if (m_currentPage == Page::Matrix) { + const Symbol symbol = Symbol::matrixSymbol('0'+(char)index); + return m_context->expressionLayoutForSymbol(&symbol); + } +#if LIST_VARIABLES + if (m_currentPage == Page::List) { + return nullptr; + } +#endif + return nullptr; +} + VariableBoxController::ContentViewController::Page VariableBoxController::ContentViewController::pageAtIndex(int index) { #if LIST_VARIABLES Page pages[3] = {Page::Scalar, Page::List, Page::Matrix}; diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 45218cd74..17d40bd71 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -55,6 +55,7 @@ private: void putLabelAtIndexInBuffer(int index, char * buffer); I18n::Message nodeLabelAtIndex(int index); const Poincare::Expression * expressionForIndex(int index); + Poincare::ExpressionLayout * expressionLayoutForIndex(int index); Poincare::GlobalContext * m_context; TextField * m_textFieldCaller; diff --git a/apps/variable_box_leaf_cell.cpp b/apps/variable_box_leaf_cell.cpp index 6806d64fc..c43affda1 100644 --- a/apps/variable_box_leaf_cell.cpp +++ b/apps/variable_box_leaf_cell.cpp @@ -5,7 +5,6 @@ using namespace Poincare; VariableBoxLeafCell::VariableBoxLeafCell() : HighlightCell(), - m_expressionLayout(nullptr), m_labelView(KDText::FontSize::Small, 0, 0.5, KDColorBlack, KDColorWhite), m_subtitleView(KDText::FontSize::Small, 0, 0.5, Palette::GreyDark, KDColorWhite), m_expressionView(1.0f, 0.5f), @@ -13,12 +12,6 @@ VariableBoxLeafCell::VariableBoxLeafCell() : { } -VariableBoxLeafCell::~VariableBoxLeafCell() { - if (m_expressionLayout != nullptr) { - delete m_expressionLayout; - m_expressionLayout = nullptr; - } -} void VariableBoxLeafCell::displayExpression(bool displayExpression) { m_displayExpression = displayExpression; } @@ -83,15 +76,8 @@ void VariableBoxLeafCell::setSubtitle(const char * text) { layoutSubviews(); } -void VariableBoxLeafCell::setExpression(const Expression * expression) { - if(m_expressionLayout != nullptr) { - delete m_expressionLayout; - m_expressionLayout = nullptr; - } - if (expression) { - m_expressionLayout = expression->createLayout(); - } - m_expressionView.setExpression(m_expressionLayout); +void VariableBoxLeafCell::setExpressionLayout(ExpressionLayout * expressionLayout) { + m_expressionView.setExpression(expressionLayout); } void VariableBoxLeafCell::drawRect(KDContext * ctx, KDRect rect) const { diff --git a/apps/variable_box_leaf_cell.h b/apps/variable_box_leaf_cell.h index 5de1e6a13..9ec1d56a0 100644 --- a/apps/variable_box_leaf_cell.h +++ b/apps/variable_box_leaf_cell.h @@ -7,12 +7,11 @@ class VariableBoxLeafCell : public HighlightCell { public: VariableBoxLeafCell(); - ~VariableBoxLeafCell(); void displayExpression(bool displayExpression); void reloadCell() override; void setLabel(const char * text); void setSubtitle(const char * text); - void setExpression(const Poincare::Expression * expression); + void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); void drawRect(KDContext * ctx, KDRect rect) const override; private: constexpr static KDCoordinate k_separatorThickness = 1; @@ -20,9 +19,6 @@ private: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; - /* The cell is responsible to delete the layout that may be created by its - * dynamic method 'setExpression'.*/ - Poincare::ExpressionLayout * m_expressionLayout; BufferTextView m_labelView; BufferTextView m_subtitleView; ExpressionView m_expressionView; diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index f0415199b..d6c4d480a 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -22,6 +22,7 @@ public: /* The expression recorded in global context is already a expression. * Otherwise, we would need the context and the angle unit to evaluate it */ const Expression * expressionForSymbol(const Symbol * symbol) override; + ExpressionLayout * expressionLayoutForSymbol(const Symbol * symbol); void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) override; static constexpr uint16_t k_maxNumberOfScalarExpressions = 26; static constexpr uint16_t k_maxNumberOfListExpressions = 10; @@ -31,6 +32,8 @@ private: int symbolIndex(const Symbol * symbol) const; Complex * m_expressions[k_maxNumberOfScalarExpressions]; Matrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; + /* Matrix layout memoization */ + ExpressionLayout * m_matrixLayout[k_maxNumberOfMatrixExpressions]; Complex m_pi; Complex m_e; Complex m_i; diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index caa4d6446..479e61cfe 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -17,6 +17,7 @@ GlobalContext::GlobalContext() : } for (int i = 0; i < k_maxNumberOfMatrixExpressions ; i++) { m_matrixExpressions[i] = nullptr; + m_matrixLayout[i] = nullptr; } } @@ -32,6 +33,10 @@ GlobalContext::~GlobalContext() { delete m_matrixExpressions[i]; } m_matrixExpressions[i] = nullptr; + if (m_matrixLayout[i] != nullptr) { + delete m_matrixLayout[i]; + } + m_matrixLayout[i] = nullptr; } } @@ -73,6 +78,17 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { return m_expressions[index]; } +ExpressionLayout * GlobalContext::expressionLayoutForSymbol(const Symbol * symbol) { + if (symbol->isMatrixSymbol()) { + int index = symbolIndex(symbol); + if (m_matrixLayout[index] == nullptr && m_matrixExpressions[index] != nullptr) { + m_matrixLayout[index] = m_matrixExpressions[index]->createLayout(); + } + return m_matrixLayout[index]; + } + return nullptr; +} + void GlobalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) { int index = symbolIndex(symbol); if (symbol->isMatrixSymbol()) { @@ -83,6 +99,10 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co delete m_matrixExpressions[indexMatrix]; m_matrixExpressions[indexMatrix] = nullptr; } + if (m_matrixLayout[indexMatrix] != nullptr) { + delete m_matrixLayout[indexMatrix]; + m_matrixLayout[indexMatrix] = nullptr; + } if (evaluation != nullptr) { if (evaluation->type() == Expression::Type::Complex) { m_matrixExpressions[indexMatrix] = new Matrix(&evaluation, 1, 1, false);