From e160282e06ebff280314cee31568d27c9f285c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 22 May 2018 16:30:38 +0200 Subject: [PATCH 01/96] [escher] Change the function expression cell to inherit from even odd expression cell --- apps/graph/function_title_cell.cpp | 2 +- apps/graph/list/list_controller.cpp | 4 +- apps/graph/list/list_controller.h | 4 +- apps/sequence/list/list_controller.cpp | 4 +- apps/sequence/list/list_controller.h | 4 +- apps/sequence/sequence_title_cell.cpp | 2 +- apps/shared/Makefile | 2 +- apps/shared/function_expression_cell.cpp | 58 ------------------------ apps/shared/function_expression_cell.h | 28 ------------ apps/shared/function_title_cell.cpp | 8 ++-- apps/shared/function_title_cell.h | 4 +- apps/shared/model_expression_cell.cpp | 28 ++++++++++++ apps/shared/model_expression_cell.h | 21 +++++++++ escher/src/even_odd_expression_cell.cpp | 6 ++- 14 files changed, 71 insertions(+), 104 deletions(-) delete mode 100644 apps/shared/function_expression_cell.cpp delete mode 100644 apps/shared/function_expression_cell.h create mode 100644 apps/shared/model_expression_cell.cpp create mode 100644 apps/shared/model_expression_cell.h diff --git a/apps/graph/function_title_cell.cpp b/apps/graph/function_title_cell.cpp index e4036acb58d..ed336ee185c 100644 --- a/apps/graph/function_title_cell.cpp +++ b/apps/graph/function_title_cell.cpp @@ -42,7 +42,7 @@ View * FunctionTitleCell::subviewAtIndex(int index) { void FunctionTitleCell::layoutSubviews() { KDRect textFrame(0, k_colorIndicatorThickness, bounds().width(), bounds().height() - k_colorIndicatorThickness); if (m_orientation == Orientation::VerticalIndicator){ - textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, bounds().height()-k_separatorThickness); + textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness-k_separatorThickness, bounds().height()-k_separatorThickness); } m_bufferTextView.setFrame(textFrame); } diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp index 9c84175d60f..5984590cbee 100644 --- a/apps/graph/list/list_controller.cpp +++ b/apps/graph/list/list_controller.cpp @@ -88,7 +88,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { } void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { - FunctionExpressionCell * myCell = (FunctionExpressionCell *)cell; + ModelExpressionCell * myCell = (ModelExpressionCell *)cell; Function * f = m_functionStore->functionAtIndex(j); myCell->setExpressionLayout(f->layout()); bool active = f->isActive(); @@ -107,7 +107,7 @@ bool ListController::removeFunctionRow(Function * function) { View * ListController::loadView() { for (int i = 0; i < k_maxNumberOfRows; i++) { m_functionTitleCells[i] = new FunctionTitleCell(FunctionTitleCell::Orientation::VerticalIndicator); - m_expressionCells[i] = new FunctionExpressionCell(); + m_expressionCells[i] = new ModelExpressionCell(); } return Shared::ListController::loadView(); } diff --git a/apps/graph/list/list_controller.h b/apps/graph/list/list_controller.h index 2eb9df23807..4bcedbe21cf 100644 --- a/apps/graph/list/list_controller.h +++ b/apps/graph/list/list_controller.h @@ -3,9 +3,9 @@ #include #include "../function_title_cell.h" -#include "../../shared/function_expression_cell.h" #include "../cartesian_function_store.h" #include "../../shared/new_function_cell.h" +#include "../../shared/model_expression_cell.h" #include "../../shared/list_controller.h" #include "../../shared/list_parameter_controller.h" @@ -30,7 +30,7 @@ class ListController : public Shared::ListController { void unloadView(View * view) override; constexpr static int k_maxNumberOfRows = 5; FunctionTitleCell * m_functionTitleCells[k_maxNumberOfRows]; - Shared::FunctionExpressionCell * m_expressionCells[k_maxNumberOfRows]; + Shared::ModelExpressionCell * m_expressionCells[k_maxNumberOfRows]; Shared::ListParameterController m_parameterController; }; diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 23e0ecf2c37..7c697c91f3a 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -197,7 +197,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { } void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { - FunctionExpressionCell * myCell = (FunctionExpressionCell *)cell; + ModelExpressionCell * myCell = (ModelExpressionCell *)cell; Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { myCell->setExpressionLayout(sequence->layout()); @@ -304,7 +304,7 @@ void ListController::reinitExpression(Shared::Function * function) { View * ListController::loadView() { for (int i = 0; i < k_maxNumberOfRows; i++) { m_sequenceTitleCells[i] = new SequenceTitleCell(FunctionTitleCell::Orientation::VerticalIndicator); - m_expressionCells[i] = new FunctionExpressionCell(); + m_expressionCells[i] = new ModelExpressionCell(); } return Shared::ListController::loadView(); } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index a6a95bc0631..98bfa1550fd 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -4,9 +4,9 @@ #include #include "../sequence_title_cell.h" #include "../sequence_store.h" -#include "../../shared/function_expression_cell.h" #include "../../shared/list_controller.h" #include "../../shared/new_function_cell.h" +#include "../../shared/model_expression_cell.h" #include "../../shared/expression_layout_field_delegate.h" #include "../../shared/text_field_delegate.h" #include "list_parameter_controller.h" @@ -49,7 +49,7 @@ class ListController : public Shared::ListController, public Shared::TextFieldDe constexpr static int k_maxNumberOfRows = 3*MaxNumberOfSequences; SequenceStore * m_sequenceStore; SequenceTitleCell * m_sequenceTitleCells[k_maxNumberOfRows]; - Shared::FunctionExpressionCell * m_expressionCells[k_maxNumberOfRows]; + Shared::ModelExpressionCell * m_expressionCells[k_maxNumberOfRows]; ListParameterController m_parameterController; TypeParameterController m_typeParameterController; StackViewController m_typeStackController; diff --git a/apps/sequence/sequence_title_cell.cpp b/apps/sequence/sequence_title_cell.cpp index 7138d103faa..b3371e88d14 100644 --- a/apps/sequence/sequence_title_cell.cpp +++ b/apps/sequence/sequence_title_cell.cpp @@ -43,7 +43,7 @@ View * SequenceTitleCell::subviewAtIndex(int index) { void SequenceTitleCell::layoutSubviews() { KDRect textFrame(0, k_colorIndicatorThickness, bounds().width(), bounds().height() - k_colorIndicatorThickness); if (m_orientation == Orientation::VerticalIndicator){ - textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness, bounds().height()-k_separatorThickness); + textFrame = KDRect(k_colorIndicatorThickness, 0, bounds().width() - k_colorIndicatorThickness-k_separatorThickness, bounds().height()-k_separatorThickness); } m_titleTextView.setFrame(textFrame); } diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 01c64faa43b..901685a3ca9 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -17,7 +17,6 @@ app_objs += $(addprefix apps/shared/,\ function_graph_view.o\ function_graph_controller.o\ function_store.o\ - function_expression_cell.o\ function_title_cell.o\ go_to_parameter_controller.o\ initialisation_parameter_controller.o\ @@ -31,6 +30,7 @@ app_objs += $(addprefix apps/shared/,\ list_parameter_controller.o\ memoized_curve_view_range.o\ message_view.o\ + model_expression_cell.o\ new_function_cell.o\ ok_view.o\ parameter_text_field_delegate.o\ diff --git a/apps/shared/function_expression_cell.cpp b/apps/shared/function_expression_cell.cpp deleted file mode 100644 index c9345ee71d1..00000000000 --- a/apps/shared/function_expression_cell.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "function_expression_cell.h" -#include - -using namespace Poincare; - -namespace Shared { - -FunctionExpressionCell::FunctionExpressionCell() : - EvenOddCell(), - m_expressionView() -{ -} - -void FunctionExpressionCell::setExpressionLayout(ExpressionLayout * expressionLayout) { - m_expressionView.setExpressionLayout(expressionLayout); -} - -void FunctionExpressionCell::setTextColor(KDColor textColor) { - m_expressionView.setTextColor(textColor); -} - -void FunctionExpressionCell::setEven(bool even) { - EvenOddCell::setEven(even); - m_expressionView.setBackgroundColor(backgroundColor()); -} - -void FunctionExpressionCell::setHighlighted(bool highlight) { - if (highlight != EvenOddCell::isHighlighted()) { - EvenOddCell::setHighlighted(highlight); - m_expressionView.setBackgroundColor(backgroundColor()); - } -} - -int FunctionExpressionCell::numberOfSubviews() const { - return 1; -} - -View * FunctionExpressionCell::subviewAtIndex(int index) { - assert(index == 0); - return &m_expressionView; -} - -void FunctionExpressionCell::layoutSubviews() { - KDRect expressionFrame(k_separatorThickness+k_margin, 0, bounds().width() - k_separatorThickness-k_margin, bounds().height()-k_separatorThickness); - m_expressionView.setFrame(expressionFrame); -} - -void FunctionExpressionCell::drawRect(KDContext * ctx, KDRect rect) const { - KDColor separatorColor = m_even ? Palette::WallScreen : KDColorWhite; - // Color the vertical separator - ctx->fillRect(KDRect(0, 0, k_separatorThickness, bounds().height()), Palette::GreyBright); - // Color the horizontal separator - ctx->fillRect(KDRect(k_separatorThickness, bounds().height()-k_separatorThickness, bounds().width()-k_separatorThickness, k_separatorThickness), separatorColor); - // Color the margin - ctx->fillRect(KDRect(k_separatorThickness, 0, k_margin, bounds().height()-k_separatorThickness), backgroundColor()); -} - -} diff --git a/apps/shared/function_expression_cell.h b/apps/shared/function_expression_cell.h deleted file mode 100644 index 351bbe3607c..00000000000 --- a/apps/shared/function_expression_cell.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SHARED_FUNCTION_EXPRESSION_CELL_H -#define SHARED_FUNCTION_EXPRESSION_CELL_H - -#include -#include "function.h" - -namespace Shared { - -class FunctionExpressionCell : public EvenOddCell { -public: - FunctionExpressionCell(); - void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout); - void setTextColor(KDColor color); - void setEven(bool even) override; - void setHighlighted(bool highlight) override; - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - void drawRect(KDContext * ctx, KDRect rect) const override; -private: - constexpr static KDCoordinate k_separatorThickness = 1; - constexpr static KDCoordinate k_margin = 5; - ExpressionView m_expressionView; -}; - -} - -#endif diff --git a/apps/shared/function_title_cell.cpp b/apps/shared/function_title_cell.cpp index 495d8008c32..76f57e7ca30 100644 --- a/apps/shared/function_title_cell.cpp +++ b/apps/shared/function_title_cell.cpp @@ -17,12 +17,14 @@ void FunctionTitleCell::setColor(KDColor color) { void FunctionTitleCell::drawRect(KDContext * ctx, KDRect rect) const { if (m_orientation == Orientation::VerticalIndicator){ ctx->fillRect(KDRect(0, 0, k_colorIndicatorThickness, bounds().height()), m_functionColor); + // Color the vertical separator + ctx->fillRect(KDRect(bounds().width()-k_separatorThickness, 0, k_separatorThickness, bounds().height()), Palette::GreyBright); + KDColor separatorColor = m_even ? Palette::WallScreen : KDColorWhite; + // Color the horizontal separator + ctx->fillRect(KDRect(k_colorIndicatorThickness, bounds().height()-k_separatorThickness, bounds().width()-k_colorIndicatorThickness-k_separatorThickness, k_separatorThickness), separatorColor); } else { ctx->fillRect(KDRect(0, 0, bounds().width(), k_colorIndicatorThickness), m_functionColor); } - KDColor separatorColor = m_even ? Palette::WallScreen : KDColorWhite; - // Color the horizontal separator - ctx->fillRect(KDRect(k_colorIndicatorThickness, bounds().height()-k_separatorThickness, bounds().width()-k_colorIndicatorThickness, k_separatorThickness), separatorColor); } } diff --git a/apps/shared/function_title_cell.h b/apps/shared/function_title_cell.h index eba48301e63..4279267581a 100644 --- a/apps/shared/function_title_cell.h +++ b/apps/shared/function_title_cell.h @@ -1,5 +1,5 @@ -#ifndef SEQUENCE_FUNCTION_TITLE_CELL_H -#define SEQUENCE_FUNCTION_TITLE_CELL_H +#ifndef SHARED_FUNCTION_TITLE_CELL_H +#define SHARED_FUNCTION_TITLE_CELL_H #include diff --git a/apps/shared/model_expression_cell.cpp b/apps/shared/model_expression_cell.cpp new file mode 100644 index 00000000000..e12971fe916 --- /dev/null +++ b/apps/shared/model_expression_cell.cpp @@ -0,0 +1,28 @@ +#include "model_expression_cell.h" + +namespace Shared { + +ModelExpressionCell::ModelExpressionCell() : + EvenOddExpressionCell() +{ +} + +KDSize ModelExpressionCell::minimalSizeForOptimalDisplay() const { + KDSize expressionSize = m_expressionView.minimalSizeForOptimalDisplay(); + return KDSize(k_margin+expressionSize.width(), expressionSize.height()+k_separatorThickness); +} + +void ModelExpressionCell::drawRect(KDContext * ctx, KDRect rect) const { + KDColor separatorColor = m_even ? Palette::WallScreen : KDColorWhite; + // Color the horizontal separator + ctx->fillRect(KDRect(0, bounds().height()-k_separatorThickness, bounds().width(), k_separatorThickness), separatorColor); + // Color the margin + ctx->fillRect(KDRect(0, 0, k_margin, bounds().height()-k_separatorThickness), backgroundColor()); +} + +void ModelExpressionCell::layoutSubviews() { + KDRect expressionFrame(k_margin, 0, bounds().width() - k_margin, bounds().height()-k_separatorThickness); + m_expressionView.setFrame(expressionFrame); +} + +} diff --git a/apps/shared/model_expression_cell.h b/apps/shared/model_expression_cell.h new file mode 100644 index 00000000000..a382caac2b7 --- /dev/null +++ b/apps/shared/model_expression_cell.h @@ -0,0 +1,21 @@ +#ifndef SHARED_MODEL_EXPRESSION_CELL_H +#define SHARED_MODEL_EXPRESSION_CELL_H + +#include + +namespace Shared { + +class ModelExpressionCell : public EvenOddExpressionCell { +public: + ModelExpressionCell(); + KDSize minimalSizeForOptimalDisplay() const override; + void drawRect(KDContext * ctx, KDRect rect) const override; + void layoutSubviews() override; +private: + constexpr static KDCoordinate k_separatorThickness = 1; + constexpr static KDCoordinate k_margin = 5; +}; + +} + +#endif diff --git a/escher/src/even_odd_expression_cell.cpp b/escher/src/even_odd_expression_cell.cpp index 4fb2e87393a..6b2de9165c8 100644 --- a/escher/src/even_odd_expression_cell.cpp +++ b/escher/src/even_odd_expression_cell.cpp @@ -10,8 +10,10 @@ EvenOddExpressionCell::EvenOddExpressionCell(float horizontalAlignment, float ve } void EvenOddExpressionCell::setHighlighted(bool highlight) { - EvenOddCell::setHighlighted(highlight); - m_expressionView.setBackgroundColor(backgroundColor()); + if (highlight != EvenOddCell::isHighlighted()) { + EvenOddCell::setHighlighted(highlight); + m_expressionView.setBackgroundColor(backgroundColor()); + } } void EvenOddExpressionCell::setEven(bool even) { From b266c4cbd105661a21bfd6e3538243e9de7d94c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 23 May 2018 10:50:34 +0200 Subject: [PATCH 02/96] [shared] Make a parent class to Function: ExpressionModel (factorize code for furtur model Equation) --- apps/shared/Makefile | 1 + apps/shared/expression_model.cpp | 87 ++++++++++++++++++++++++++++++++ apps/shared/expression_model.h | 35 +++++++++++++ apps/shared/function.cpp | 79 +---------------------------- apps/shared/function.h | 21 +------- 5 files changed, 127 insertions(+), 96 deletions(-) create mode 100644 apps/shared/expression_model.cpp create mode 100644 apps/shared/expression_model.h diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 901685a3ca9..f632ce825ae 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -7,6 +7,7 @@ app_objs += $(addprefix apps/shared/,\ curve_view_range.o\ editable_cell_table_view_controller.o\ expression_field_delegate_app.o\ + expression_model.o\ float_pair_store.o\ float_parameter_controller.o\ function.o\ diff --git a/apps/shared/expression_model.cpp b/apps/shared/expression_model.cpp new file mode 100644 index 00000000000..99103166357 --- /dev/null +++ b/apps/shared/expression_model.cpp @@ -0,0 +1,87 @@ +#include "function.h" +#include +#include +#include + +using namespace Poincare; + +namespace Shared { + +ExpressionModel::ExpressionModel() : + m_text{0}, + m_expression(nullptr), + m_layout(nullptr) +{ +} + +ExpressionModel::~ExpressionModel() { + if (m_layout != nullptr) { + delete m_layout; + m_layout = nullptr; + } + if (m_expression != nullptr) { + delete m_expression; + m_expression = nullptr; + } +} + +ExpressionModel& ExpressionModel::operator=(const ExpressionModel& other) { + // Self-assignment is benign + setContent(other.m_text); + return *this; +} + +const char * ExpressionModel::text() const { + return m_text; +} + +Poincare::Expression * ExpressionModel::expression(Poincare::Context * context) const { + if (m_expression == nullptr) { + m_expression = Expression::ParseAndSimplify(m_text, *context); + } + return m_expression; +} + +Poincare::ExpressionLayout * ExpressionModel::layout() { + if (m_layout == nullptr) { + Expression * nonSimplifiedExpression = Expression::parse(m_text); + if (nonSimplifiedExpression != nullptr) { + m_layout = nonSimplifiedExpression->createLayout(PrintFloat::Mode::Decimal); + delete nonSimplifiedExpression; + } + } + return m_layout; +} + +bool ExpressionModel::isDefined() { + return m_text[0] != 0; +} + +bool ExpressionModel::isEmpty() { + return m_text[0] == 0; +} + +void ExpressionModel::setContent(const char * c) { + strlcpy(m_text, c, sizeof(m_text)); + if (m_layout != nullptr) { + delete m_layout; + m_layout = nullptr; + } + if (m_expression != nullptr) { + delete m_expression; + m_expression = nullptr; + } +} + +void ExpressionModel::tidy() { + if (m_layout != nullptr) { + delete m_layout; + m_layout = nullptr; + } + if (m_expression != nullptr) { + delete m_expression; + m_expression = nullptr; + } +} + +} diff --git a/apps/shared/expression_model.h b/apps/shared/expression_model.h new file mode 100644 index 00000000000..8482e9f048f --- /dev/null +++ b/apps/shared/expression_model.h @@ -0,0 +1,35 @@ +#ifndef SHARED_EXPRESSION_MODEL_H +#define SHARED_EXPRESSION_MODEL_H + +#include +#include +#include + +namespace Shared { + +class ExpressionModel { +public: + ExpressionModel(); + virtual ~ExpressionModel(); // Delete expression and layout, if needed + ExpressionModel& operator=(const ExpressionModel& other); + ExpressionModel& operator=(ExpressionModel&& other) = delete; + ExpressionModel(const ExpressionModel& other) = delete; + ExpressionModel(ExpressionModel&& other) = delete; + const char * text() const; + Poincare::Expression * expression(Poincare::Context * context) const; + Poincare::ExpressionLayout * layout(); + virtual bool isDefined(); + virtual bool isEmpty(); + virtual void setContent(const char * c); + virtual void tidy(); +private: + constexpr static size_t k_dataLengthInBytes = (TextField::maxBufferSize())*sizeof(char); + static_assert((k_dataLengthInBytes & 0x3) == 0, "The expression model data size is not a multiple of 4 bytes (cannot compute crc)"); // Assert that dataLengthInBytes is a multiple of 4 + char m_text[TextField::maxBufferSize()]; + mutable Poincare::Expression * m_expression; + mutable Poincare::ExpressionLayout * m_layout; +}; + +} + +#endif diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index 7f612856dcf..5727f0beaa9 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -8,89 +8,29 @@ using namespace Poincare; namespace Shared { Function::Function(const char * name, KDColor color) : - m_expression(nullptr), - m_text{0}, + ExpressionModel(), m_name(name), m_color(color), - m_layout(nullptr), m_active(true) { } -Function& Function::operator=(const Function& other) { - // Self-assignment is benign - m_color = other.m_color; - m_name = other.m_name; - m_active = other.m_active; - setContent(other.m_text); - return *this; -} - uint32_t Function::checksum() { char data[k_dataLengthInBytes/sizeof(char)] = {}; - strlcpy(data, m_text, TextField::maxBufferSize()); + strlcpy(data, text(), TextField::maxBufferSize()); data[k_dataLengthInBytes-2] = m_name != nullptr ? m_name[0] : 0; data[k_dataLengthInBytes-1] = m_active ? 1 : 0; return Ion::crc32((uint32_t *)data, k_dataLengthInBytes/sizeof(uint32_t)); } -void Function::setContent(const char * c) { - strlcpy(m_text, c, sizeof(m_text)); - if (m_layout != nullptr) { - delete m_layout; - m_layout = nullptr; - } - if (m_expression != nullptr) { - delete m_expression; - m_expression = nullptr; - } -} - void Function::setColor(KDColor color) { m_color = color; } -Function::~Function() { - if (m_layout != nullptr) { - delete m_layout; - m_layout = nullptr; - } - if (m_expression != nullptr) { - delete m_expression; - m_expression = nullptr; - } -} - -const char * Function::text() const { - return m_text; -} - const char * Function::name() const { return m_name; } -Poincare::Expression * Function::expression(Poincare::Context * context) const { - if (m_expression == nullptr) { - m_expression = Expression::ParseAndSimplify(m_text, *context); - } - return m_expression; -} - -Poincare::ExpressionLayout * Function::layout() { - if (m_layout == nullptr) { - Expression * nonSimplifiedExpression = Expression::parse(m_text); - if (nonSimplifiedExpression != nullptr) { - m_layout = nonSimplifiedExpression->createLayout(PrintFloat::Mode::Decimal); - delete nonSimplifiedExpression; - } - } - return m_layout; -} - -bool Function::isDefined() { - return m_text[0] != 0; -} - bool Function::isActive() { return m_active; } @@ -99,10 +39,6 @@ void Function::setActive(bool active) { m_active = active; } -bool Function::isEmpty() { - return m_text[0] == 0; -} - template T Function::templatedApproximateAtAbscissa(T x, Poincare::Context * context) const { Poincare::VariableContext variableContext = Poincare::VariableContext(symbol(), context); @@ -112,17 +48,6 @@ T Function::templatedApproximateAtAbscissa(T x, Poincare::Context * context) con return expression(context)->approximateToScalar(variableContext); } -void Function::tidy() { - if (m_layout != nullptr) { - delete m_layout; - m_layout = nullptr; - } - if (m_expression != nullptr) { - delete m_expression; - m_expression = nullptr; - } -} - } template float Shared::Function::templatedApproximateAtAbscissa(float, Poincare::Context*) const; diff --git a/apps/shared/function.h b/apps/shared/function.h index a750ff36d42..74e83e4184c 100644 --- a/apps/shared/function.h +++ b/apps/shared/function.h @@ -1,31 +1,18 @@ #ifndef SHARED_FUNCTION_H #define SHARED_FUNCTION_H -#include -#include -#include +#include "expression_model.h" namespace Shared { -class Function { +class Function : public ExpressionModel { public: Function(const char * name = nullptr, KDColor color = KDColorBlack); - virtual ~Function(); // Delete expression and layout, if needed - Function& operator=(const Function& other); - Function& operator=(Function&& other) = delete; - Function(const Function& other) = delete; - Function(Function&& other) = delete; virtual uint32_t checksum(); - const char * text() const; const char * name() const; KDColor color() const { return m_color; } - Poincare::Expression * expression(Poincare::Context * context) const; - Poincare::ExpressionLayout * layout(); - virtual bool isDefined(); bool isActive(); void setActive(bool active); - virtual bool isEmpty(); - virtual void setContent(const char * c); void setColor(KDColor m_color); virtual float evaluateAtAbscissa(float x, Poincare::Context * context) const { return templatedApproximateAtAbscissa(x, context); @@ -34,17 +21,13 @@ class Function { return templatedApproximateAtAbscissa(x, context); } virtual double sumBetweenBounds(double start, double end, Poincare::Context * context) const = 0; - virtual void tidy(); private: constexpr static size_t k_dataLengthInBytes = (TextField::maxBufferSize()+2)*sizeof(char)+2; static_assert((k_dataLengthInBytes & 0x3) == 0, "The function data size is not a multiple of 4 bytes (cannot compute crc)"); // Assert that dataLengthInBytes is a multiple of 4 template T templatedApproximateAtAbscissa(T x, Poincare::Context * context) const; virtual char symbol() const = 0; - mutable Poincare::Expression * m_expression; - char m_text[TextField::maxBufferSize()]; const char * m_name; KDColor m_color; - Poincare::ExpressionLayout * m_layout; bool m_active; }; From e05709f097b57a2942562a73f4221e8012cca1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 23 May 2018 14:48:25 +0200 Subject: [PATCH 03/96] [shared] Factorize FunctionStore in ModelStore (for future implementation of equation store) --- apps/graph/cartesian_function_store.cpp | 93 ++++--------------- apps/graph/cartesian_function_store.h | 23 +++-- apps/graph/list/list_controller.cpp | 18 ++-- apps/sequence/Makefile | 2 +- apps/sequence/list/list_controller.cpp | 28 +++--- .../list/list_parameter_controller.cpp | 4 +- .../list/type_parameter_controller.cpp | 2 +- apps/sequence/sequence.cpp | 4 - apps/sequence/sequence.h | 3 +- apps/sequence/sequence_context.cpp | 4 +- apps/sequence/sequence_store.cpp | 86 ++--------------- apps/sequence/sequence_store.h | 27 ++++-- apps/sequence/test/sequence.cpp | 16 ++-- apps/shared/Makefile | 1 + apps/shared/function_store.cpp | 52 +++++++---- apps/shared/function_store.h | 16 ++-- apps/shared/list_controller.cpp | 28 +++--- apps/shared/list_parameter_controller.cpp | 4 +- apps/shared/model_store.cpp | 51 ++++++++++ apps/shared/model_store.h | 32 +++++++ 20 files changed, 236 insertions(+), 258 deletions(-) create mode 100644 apps/shared/model_store.cpp create mode 100644 apps/shared/model_store.h diff --git a/apps/graph/cartesian_function_store.cpp b/apps/graph/cartesian_function_store.cpp index d7acf19c9a0..ca028817baa 100644 --- a/apps/graph/cartesian_function_store.cpp +++ b/apps/graph/cartesian_function_store.cpp @@ -14,7 +14,7 @@ constexpr const char * CartesianFunctionStore::k_functionNames[k_maxNumberOfFunc CartesianFunctionStore::CartesianFunctionStore() : Shared::FunctionStore() { - addEmptyFunction(); + addEmptyModel(); } uint32_t CartesianFunctionStore::storeChecksum() { @@ -27,91 +27,30 @@ uint32_t CartesianFunctionStore::storeChecksum() { return Ion::crc32((uint32_t *)checksums, dataLengthInBytes/sizeof(uint32_t)); } -CartesianFunction * CartesianFunctionStore::functionAtIndex(int i) { - assert(i>=0 && i=0 && i=0 && i(f)); } } diff --git a/apps/graph/cartesian_function_store.h b/apps/graph/cartesian_function_store.h index ad2e0a4975d..abba37b7681 100644 --- a/apps/graph/cartesian_function_store.h +++ b/apps/graph/cartesian_function_store.h @@ -12,24 +12,31 @@ class CartesianFunctionStore : public Shared::FunctionStore { public: CartesianFunctionStore(); uint32_t storeChecksum() override; - CartesianFunction * functionAtIndex(int i) override; - CartesianFunction * activeFunctionAtIndex(int i) override; - CartesianFunction * definedFunctionAtIndex(int i) override; - CartesianFunction * addEmptyFunction() override; - void removeFunction(Shared::Function * f) override; - int maxNumberOfFunctions() override; + CartesianFunction * modelAtIndex(int i) override { return &m_functions[i]; } + CartesianFunction * activeFunctionAtIndex(int i) override { return (CartesianFunction *)Shared::FunctionStore::activeFunctionAtIndex(i); } + CartesianFunction * definedFunctionAtIndex(int i) override { return (CartesianFunction *)Shared::FunctionStore::definedFunctionAtIndex(i); } + int maxNumberOfModels() const override { + return k_maxNumberOfFunctions; + } char symbol() const override; void removeAll() override; static constexpr int k_maxNumberOfFunctions = 4; private: - const char * firstAvailableName() override; - const KDColor firstAvailableColor() override; static constexpr KDColor k_defaultColors[k_maxNumberOfFunctions] = { Palette::Red, Palette::Blue, Palette::Green, Palette::YellowDark, }; static constexpr const char * k_functionNames[k_maxNumberOfFunctions] = { "f", "g", "h", "p", }; + Shared::Function * emptyModel() override; + Shared::Function * nullModel() override; + void setModelAtIndex(Shared::Function * f, int i) override; + const char * firstAvailableName() override { + return firstAvailableAttribute(k_functionNames, FunctionStore::name); + } + const KDColor firstAvailableColor() override { + return firstAvailableAttribute(k_defaultColors, FunctionStore::color); + } CartesianFunction m_functions[k_maxNumberOfFunctions]; }; diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp index 5984590cbee..1627f983123 100644 --- a/apps/graph/list/list_controller.cpp +++ b/apps/graph/list/list_controller.cpp @@ -21,17 +21,17 @@ const char * ListController::title() { } int ListController::numberOfRows() { - if (m_functionStore->numberOfFunctions() == m_functionStore->maxNumberOfFunctions()) { - return m_functionStore->numberOfFunctions(); + if (m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels()) { + return m_functionStore->numberOfModels(); } - return 1 + m_functionStore->numberOfFunctions(); + return 1 + m_functionStore->numberOfModels(); }; KDCoordinate ListController::rowHeight(int j) { - if (m_functionStore->numberOfFunctions() < m_functionStore->maxNumberOfFunctions() && j == numberOfRows() - 1) { + if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && j == numberOfRows() - 1) { return Metric::StoreRowHeight; } - Function * function = m_functionStore->functionAtIndex(j); + Function * function = m_functionStore->modelAtIndex(j); if (function->layout() == nullptr) { return Metric::StoreRowHeight; } @@ -80,7 +80,7 @@ HighlightCell * ListController::expressionCells(int index) { void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { FunctionTitleCell * myFunctionCell = (FunctionTitleCell *)cell; - CartesianFunction * function = ((CartesianFunctionStore *)m_functionStore)->functionAtIndex(j); + CartesianFunction * function = ((CartesianFunctionStore *)m_functionStore)->modelAtIndex(j); char bufferName[5] = {*function->name(),'(', m_functionStore->symbol(),')', 0}; myFunctionCell->setText(bufferName); KDColor functionNameColor = function->isActive() ? function->color() : Palette::GreyDark; @@ -89,7 +89,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { ModelExpressionCell * myCell = (ModelExpressionCell *)cell; - Function * f = m_functionStore->functionAtIndex(j); + Function * f = m_functionStore->modelAtIndex(j); myCell->setExpressionLayout(f->layout()); bool active = f->isActive(); KDColor textColor = active ? KDColorBlack : Palette::GreyDark; @@ -97,8 +97,8 @@ void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int } bool ListController::removeFunctionRow(Function * function) { - if (m_functionStore->numberOfFunctions() > 1) { - m_functionStore->removeFunction(function); + if (m_functionStore->numberOfModels() > 1) { + m_functionStore->removeModel(function); return true; } return false; diff --git a/apps/sequence/Makefile b/apps/sequence/Makefile index 2c47f04dd0c..a39515a165f 100644 --- a/apps/sequence/Makefile +++ b/apps/sequence/Makefile @@ -35,6 +35,6 @@ tests += $(addprefix apps/sequence/test/,\ sequence.cpp\ ) test_objs += $(addprefix apps/sequence/, sequence.o sequence_store.o sequence_context.o cache_context.o) -test_objs += $(addprefix apps/shared/, function.o function_store.o) +test_objs += $(addprefix apps/shared/, expression_model.o function.o function_store.o model_store.o) app_images += apps/sequence/sequence_icon.png diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index 7c697c91f3a..afa32a6dd84 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -41,21 +41,21 @@ ExpressionFieldDelegateApp * ListController::expressionFieldDelegateApp() { int ListController::numberOfRows() { int numberOfRows = 0; - for (int i = 0; i < m_sequenceStore->numberOfFunctions(); i++) { - Sequence * sequence = m_sequenceStore->functionAtIndex(i); + for (int i = 0; i < m_sequenceStore->numberOfModels(); i++) { + Sequence * sequence = m_sequenceStore->modelAtIndex(i); numberOfRows += sequence->numberOfElements(); } - if (m_sequenceStore->numberOfFunctions() == m_sequenceStore->maxNumberOfFunctions()) { + if (m_sequenceStore->numberOfModels() == m_sequenceStore->maxNumberOfModels()) { return numberOfRows; } return 1 + numberOfRows; }; KDCoordinate ListController::rowHeight(int j) { - if (m_sequenceStore->numberOfFunctions() < m_sequenceStore->maxNumberOfFunctions() && j == numberOfRows() - 1) { + if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && j == numberOfRows() - 1) { return Metric::StoreRowHeight; } - Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j)); + Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(j)); KDCoordinate defaultHeight = sequence->type() == Sequence::Type::Explicit ? Metric::StoreRowHeight : k_emptySubRowHeight; ExpressionLayout * layout = sequence->layout(); if (sequenceDefinitionForRow(j) == 1) { @@ -87,7 +87,7 @@ Toolbox * ListController::toolboxForSender(Responder * sender) { // Set extra cells int recurrenceDepth = -1; int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); - Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow())); + Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(selectedRow())); if (sequenceDefinition == 0) { recurrenceDepth = sequence->numberOfElements()-1; } @@ -155,7 +155,7 @@ void ListController::editExpression(Sequence * sequence, int sequenceDefinition, } bool ListController::removeFunctionRow(Function * function) { - m_functionStore->removeFunction(function); + m_functionStore->removeModel(function); // Invalidate the sequences context cache static_cast(app())->localContext()->resetCache(); return true; @@ -182,7 +182,7 @@ HighlightCell * ListController::expressionCells(int index) { void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { SequenceTitleCell * myCell = (SequenceTitleCell *)cell; - Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j)); + Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { myCell->setExpressionLayout(sequence->definitionName()); } @@ -198,7 +198,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { ModelExpressionCell * myCell = (ModelExpressionCell *)cell; - Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j)); + Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { myCell->setExpressionLayout(sequence->layout()); } @@ -217,7 +217,7 @@ int ListController::functionIndexForRow(int j) { if (j < 0) { return j; } - if (m_sequenceStore->numberOfFunctions() < m_sequenceStore->maxNumberOfFunctions() && + if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && j == numberOfRows() - 1) { return functionIndexForRow(j-1)+1; } @@ -225,14 +225,14 @@ int ListController::functionIndexForRow(int j) { int sequenceIndex = -1; do { sequenceIndex++; - Sequence * sequence = m_sequenceStore->functionAtIndex(sequenceIndex); + Sequence * sequence = m_sequenceStore->modelAtIndex(sequenceIndex); rowIndex += sequence->numberOfElements(); } while (rowIndex <= j); return sequenceIndex; } const char * ListController::textForRow(int j) { - Sequence * sequence = (Sequence *)m_functionStore->functionAtIndex(functionIndexForRow(j)); + Sequence * sequence = ((SequenceStore *)m_functionStore)->modelAtIndex(functionIndexForRow(j)); switch (sequenceDefinitionForRow(j)) { case 0: return sequence->text(); @@ -250,7 +250,7 @@ int ListController::sequenceDefinitionForRow(int j) { if (j < 0) { return j; } - if (m_sequenceStore->numberOfFunctions() < m_sequenceStore->maxNumberOfFunctions() && + if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && j == numberOfRows() - 1) { return 0; } @@ -259,7 +259,7 @@ int ListController::sequenceDefinitionForRow(int j) { Sequence * sequence = nullptr; do { sequenceIndex++; - sequence = m_sequenceStore->functionAtIndex(sequenceIndex); + sequence = m_sequenceStore->modelAtIndex(sequenceIndex); rowIndex += sequence->numberOfElements(); } while (rowIndex <= j); return sequence->numberOfElements()-rowIndex+j; diff --git a/apps/sequence/list/list_parameter_controller.cpp b/apps/sequence/list/list_parameter_controller.cpp index 89fec88a00e..d119bcaaddf 100644 --- a/apps/sequence/list/list_parameter_controller.cpp +++ b/apps/sequence/list/list_parameter_controller.cpp @@ -61,8 +61,8 @@ bool ListParameterController::handleEvent(Ion::Events::Event event) { #else if (selectedRowIndex == 2+hasAdditionalRow) { #endif - if (m_functionStore->numberOfFunctions() > 0) { - m_functionStore->removeFunction(m_function); + if (m_functionStore->numberOfModels() > 0) { + m_functionStore->removeModel(m_function); static_cast(app())->localContext()->resetCache(); StackViewController * stack = (StackViewController *)(parentResponder()); stack->pop(); diff --git a/apps/sequence/list/type_parameter_controller.cpp b/apps/sequence/list/type_parameter_controller.cpp index 95f9c89188a..fc9d1b4ec43 100644 --- a/apps/sequence/list/type_parameter_controller.cpp +++ b/apps/sequence/list/type_parameter_controller.cpp @@ -82,7 +82,7 @@ bool TypeParameterController::handleEvent(Ion::Events::Event event) { stack->pop(); return true; } - Sequence * newSequence = m_sequenceStore->addEmptyFunction(); + Sequence * newSequence = static_cast(m_sequenceStore->addEmptyModel()); newSequence->setType((Sequence::Type)selectedRow()); app()->dismissModalViewController(); return true; diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index eab918afbf4..e9a317f0421 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -185,10 +185,6 @@ Poincare::ExpressionLayout * Sequence::secondInitialConditionLayout() { return m_secondInitialConditionLayout; } -void Sequence::setContent(const char * c) { - Function::setContent(c); -} - void Sequence::setFirstInitialConditionContent(const char * c) { strlcpy(m_firstInitialConditionText, c, sizeof(m_firstInitialConditionText)); if (m_firstInitialConditionExpression != nullptr) { diff --git a/apps/sequence/sequence.h b/apps/sequence/sequence.h index 12a3ecf4443..a40574c4e61 100644 --- a/apps/sequence/sequence.h +++ b/apps/sequence/sequence.h @@ -17,7 +17,7 @@ class Sequence : public Shared::Function { Sequence(const char * text = nullptr, KDColor color = KDColorBlack); ~Sequence(); Sequence& operator=(const Sequence& other); - Sequence& operator=(Sequence&& other) = delete; + //Sequence& operator=(Sequence&& other) = delete; Sequence(const Sequence& other) = delete; Sequence(Sequence&& other) = delete; uint32_t checksum() override; @@ -36,7 +36,6 @@ class Sequence : public Shared::Function { * invalidate the cache because the sequences evaluations might have changed. */ void setType(Type type); void setInitialRank(int rank); - void setContent(const char * c) override; void setFirstInitialConditionContent(const char * c); void setSecondInitialConditionContent(const char * c); int numberOfElements(); diff --git a/apps/sequence/sequence_context.cpp b/apps/sequence/sequence_context.cpp index fce83df19c1..193dc9b9881 100644 --- a/apps/sequence/sequence_context.cpp +++ b/apps/sequence/sequence_context.cpp @@ -49,9 +49,9 @@ void TemplatedSequenceContext::step(SequenceStore * sequenceStore, SequenceCo } /* Evaluate new u(n) and v(n) */ - Sequence * u = sequenceStore->numberOfFunctions() > 0 ? sequenceStore->functionAtIndex(0) : nullptr; + Sequence * u = sequenceStore->numberOfModels() > 0 ? sequenceStore->modelAtIndex(0) : nullptr; u = u && u->isDefined() ? u : nullptr; - Sequence * v = sequenceStore->numberOfFunctions() > 1 ? sequenceStore->functionAtIndex(1) : nullptr; + Sequence * v = sequenceStore->numberOfModels() > 1 ? sequenceStore->modelAtIndex(1) : nullptr; v = v && v->isDefined() ? v : nullptr; /* Switch u & v if the name of u is v */ if (u != nullptr && u->name()[0] == SequenceStore::k_sequenceNames[1][0]) { diff --git a/apps/sequence/sequence_store.cpp b/apps/sequence/sequence_store.cpp index 6a51047bc1e..b3180f72c57 100644 --- a/apps/sequence/sequence_store.cpp +++ b/apps/sequence/sequence_store.cpp @@ -20,90 +20,24 @@ uint32_t SequenceStore::storeChecksum() { return Ion::crc32((uint32_t *)checksums, dataLengthInBytes/sizeof(uint32_t)); } -Sequence * SequenceStore::functionAtIndex(int i) { - assert(i>=0 && i=0 && i=0 && i(f)); } } diff --git a/apps/sequence/sequence_store.h b/apps/sequence/sequence_store.h index 423bff97d3e..e335eb1ee1b 100644 --- a/apps/sequence/sequence_store.h +++ b/apps/sequence/sequence_store.h @@ -12,26 +12,33 @@ class SequenceStore : public Shared::FunctionStore { public: using Shared::FunctionStore::FunctionStore; uint32_t storeChecksum() override; - Sequence * functionAtIndex(int i) override; - Sequence * activeFunctionAtIndex(int i) override; - Sequence * definedFunctionAtIndex(int i) override; - Sequence * addEmptyFunction() override; - /* WARNING: after calling removeFunction or removeAll, the sequence context + Sequence * modelAtIndex(int i) override { + assert(i>=0 && i(store.addEmptyModel()); assert(u->name()[0] == 'u'); u->setType(typeU); u->setContent(definitionU); @@ -29,14 +29,14 @@ void check_sequences_defined_by(double result[2][10], Sequence::Type typeU, cons } } if (definitionV) { - if (store.numberOfFunctions() == 0) { - Sequence * tempU = store.addEmptyFunction(); - v = store.addEmptyFunction(); - store.removeFunction(tempU); - v = store.functionAtIndex(0); + if (store.numberOfModels() == 0) { + Sequence * tempU = static_cast(store.addEmptyModel()); + v = static_cast(store.addEmptyModel()); + store.removeModel(tempU); + v = store.modelAtIndex(0); } else { - assert(store.numberOfFunctions() == 1); - v = store.addEmptyFunction(); + assert(store.numberOfModels() == 1); + v = static_cast(store.addEmptyModel()); } v->setType(typeV); v->setContent(definitionV); diff --git a/apps/shared/Makefile b/apps/shared/Makefile index f632ce825ae..b09b72ff0dd 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -32,6 +32,7 @@ app_objs += $(addprefix apps/shared/,\ memoized_curve_view_range.o\ message_view.o\ model_expression_cell.o\ + model_store.o\ new_function_cell.o\ ok_view.o\ parameter_text_field_delegate.o\ diff --git a/apps/shared/function_store.cpp b/apps/shared/function_store.cpp index 0f7894076f3..c862d13d5ef 100644 --- a/apps/shared/function_store.cpp +++ b/apps/shared/function_store.cpp @@ -4,15 +4,15 @@ namespace Shared { FunctionStore::FunctionStore() : - m_numberOfFunctions(0) + ModelStore() { } Function * FunctionStore::activeFunctionAtIndex(int i) { - assert(i>=0 && i=0 && iisActive() && function->isDefined()) { if (i == index) { return function; @@ -25,12 +25,12 @@ Function * FunctionStore::activeFunctionAtIndex(int i) { } Function * FunctionStore::definedFunctionAtIndex(int i) { - assert(i>=0 && i=0 && iisDefined()) { + for (int k = 0; k < m_numberOfModels; k++) { + if (modelAtIndex(k)->isDefined()) { if (i == index) { - return functionAtIndex(k); + return modelAtIndex(k); } index++; } @@ -39,14 +39,10 @@ Function * FunctionStore::definedFunctionAtIndex(int i) { return nullptr; } -int FunctionStore::numberOfFunctions() { - return m_numberOfFunctions; -} - int FunctionStore::numberOfActiveFunctions() { int result = 0; - for (int i = 0; i < m_numberOfFunctions; i++) { - Function * function = functionAtIndex(i); + for (int i = 0; i < m_numberOfModels; i++) { + Function * function = modelAtIndex(i); if (function->isDefined() && function->isActive()) { result++; } @@ -56,18 +52,36 @@ int FunctionStore::numberOfActiveFunctions() { int FunctionStore::numberOfDefinedFunctions() { int result = 0; - for (int i = 0; i < m_numberOfFunctions; i++) { - if (functionAtIndex(i)->isDefined()) { + for (int i = 0; i < m_numberOfModels; i++) { + if (modelAtIndex(i)->isDefined()) { result++; } } return result; } -void FunctionStore::tidy() { - for (int i = 0; i < m_numberOfFunctions; i++) { - functionAtIndex(i)->tidy(); +void FunctionStore::tidyModelAtIndex(int i) { + modelAtIndex(i)->tidy(); +} + +template +T FunctionStore::firstAvailableAttribute(T attributes[], AttributeGetter attribute) { + for (int k = 0; k < maxNumberOfModels(); k++) { + int j = 0; + while (j < m_numberOfModels) { + if (attribute(modelAtIndex(j)) == attributes[k]) { + break; + } + j++; + } + if (j == m_numberOfModels) { + return attributes[k]; + } } + return attributes[0]; } } + +template char const* const Shared::FunctionStore::firstAvailableAttribute(char const* const*, char const* const (*)(Shared::Function*)); +template KDColor const Shared::FunctionStore::firstAvailableAttribute(KDColor const*, KDColor const (*)(Shared::Function*)); diff --git a/apps/shared/function_store.h b/apps/shared/function_store.h index 93d1c2397b3..d817a32bd18 100644 --- a/apps/shared/function_store.h +++ b/apps/shared/function_store.h @@ -2,6 +2,7 @@ #define SHARED_FUNCTION_STORE_H #include "function.h" +#include "model_store.h" #include namespace Shared { @@ -9,29 +10,26 @@ namespace Shared { /* FunctionStore is a dumb class. * Its only job is to store functions and to give them a color. */ -class FunctionStore { +class FunctionStore : public ModelStore { public: FunctionStore(); virtual uint32_t storeChecksum() = 0; - virtual Function * functionAtIndex(int i) = 0; virtual Function * activeFunctionAtIndex(int i); virtual Function * definedFunctionAtIndex(int i); - virtual Function * addEmptyFunction() = 0; - virtual void removeFunction(Function * f) = 0; - virtual void removeAll() = 0; - int numberOfFunctions(); // Functions can be undefined when they have a color and a name but no content int numberOfDefinedFunctions(); // An active function must be defined to be counted int numberOfActiveFunctions(); - virtual int maxNumberOfFunctions() = 0; virtual char symbol() const = 0; - void tidy(); protected: - int m_numberOfFunctions; + static const char * const name(Shared::Function * f) { return f->name(); } + static KDColor const color(Shared::Function * f) { return f->color(); } + template using AttributeGetter = T (*)(Function * f); + template T firstAvailableAttribute(T attributes[], AttributeGetter attribute); private: virtual const char * firstAvailableName() = 0; virtual const KDColor firstAvailableColor() = 0; + void tidyModelAtIndex(int i) override; }; } diff --git a/apps/shared/list_controller.cpp b/apps/shared/list_controller.cpp index 7bed4ad5e21..a2f83efc0ca 100644 --- a/apps/shared/list_controller.cpp +++ b/apps/shared/list_controller.cpp @@ -83,7 +83,7 @@ int ListController::indexFromCumulatedHeight(KDCoordinate offsetY) { } int ListController::typeAtLocation(int i, int j) { - if (m_functionStore->numberOfFunctions() < m_functionStore->maxNumberOfFunctions() + if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && j == numberOfRows() - 1) { return i + 2; } @@ -116,7 +116,7 @@ int ListController::reusableCellCount(int type) { } void ListController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { - if (j < numberOfRows() - 1 || m_functionStore->numberOfFunctions() == m_functionStore->maxNumberOfFunctions()) { + if (j < numberOfRows() - 1 || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels()) { if (i == 0) { willDisplayTitleCellAtIndex(cell, j); } else { @@ -182,21 +182,21 @@ bool ListController::handleEvent(Ion::Events::Event event) { switch (selectedColumn()) { case 0: { - if (m_functionStore->numberOfFunctions() < m_functionStore->maxNumberOfFunctions() && + if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && selectedRow() == numberOfRows() - 1) { return true; } - configureFunction(m_functionStore->functionAtIndex(functionIndexForRow(selectedRow()))); + configureFunction(m_functionStore->modelAtIndex(functionIndexForRow(selectedRow()))); return true; } case 1: { - if (m_functionStore->numberOfFunctions() < m_functionStore->maxNumberOfFunctions() && + if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && selectedRow() == numberOfRows() - 1) { addEmptyFunction(); return true; } - Shared::Function * function = m_functionStore->functionAtIndex(functionIndexForRow(selectedRow())); + Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(selectedRow())); editExpression(function, event); return true; } @@ -207,8 +207,8 @@ bool ListController::handleEvent(Ion::Events::Event event) { } } if (event == Ion::Events::Backspace && selectedRow() >= 0 && - (selectedRow() < numberOfRows() - 1 || m_functionStore->numberOfFunctions() == m_functionStore->maxNumberOfFunctions())) { - Shared::Function * function = m_functionStore->functionAtIndex(functionIndexForRow(selectedRow())); + (selectedRow() < numberOfRows() - 1 || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels())) { + Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(selectedRow())); if (selectedColumn() == 1 && !function->isEmpty()) { reinitExpression(function); } else { @@ -225,13 +225,13 @@ bool ListController::handleEvent(Ion::Events::Event event) { if ((event.hasText() || event == Ion::Events::XNT || event == Ion::Events::Paste || event == Ion::Events::Toolbox || event == Ion::Events::Var) && selectedColumn() == 1 && (selectedRow() != numberOfRows() - 1 - || m_functionStore->numberOfFunctions() == m_functionStore->maxNumberOfFunctions())) { - Shared::Function * function = m_functionStore->functionAtIndex(functionIndexForRow(selectedRow())); + || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels())) { + Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(selectedRow())); editExpression(function, event); return true; } if (event == Ion::Events::Copy && selectedColumn() == 1 && - (selectedRow() < numberOfRows() - 1 || m_functionStore->numberOfFunctions() == m_functionStore->maxNumberOfFunctions())) { + (selectedRow() < numberOfRows() - 1 || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels())) { Clipboard::sharedClipboard()->store(textForRow(selectedRow())); return true; } @@ -250,7 +250,7 @@ void ListController::willExitResponderChain(Responder * nextFirstResponder) { } void ListController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) { - if (m_functionStore->numberOfFunctions() < m_functionStore->maxNumberOfFunctions() && selectedRow() == numberOfRows() - 1 && selectedColumn() == 0) { + if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && selectedRow() == numberOfRows() - 1 && selectedColumn() == 0) { t->selectCellAtLocation(1, numberOfRows()-1); } } @@ -283,12 +283,12 @@ int ListController::functionIndexForRow(int j) { } const char * ListController::textForRow(int j) { - Shared::Function * function = m_functionStore->functionAtIndex(functionIndexForRow(j)); + Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(j)); return function->text(); } void ListController::addEmptyFunction() { - m_functionStore->addEmptyFunction(); + m_functionStore->addEmptyModel(); selectableTableView()->reloadData(); } diff --git a/apps/shared/list_parameter_controller.cpp b/apps/shared/list_parameter_controller.cpp index 2ca48879a39..c3eddfaae4a 100644 --- a/apps/shared/list_parameter_controller.cpp +++ b/apps/shared/list_parameter_controller.cpp @@ -99,8 +99,8 @@ bool ListParameterController::handleEnterOnRow(int rowIndex) { case 1: #endif { - if (m_functionStore->numberOfFunctions() > 1) { - m_functionStore->removeFunction(m_function); + if (m_functionStore->numberOfModels() > 1) { + m_functionStore->removeModel(m_function); StackViewController * stack = (StackViewController *)(parentResponder()); stack->pop(); return true; diff --git a/apps/shared/model_store.cpp b/apps/shared/model_store.cpp new file mode 100644 index 00000000000..10a7b19019c --- /dev/null +++ b/apps/shared/model_store.cpp @@ -0,0 +1,51 @@ +#include "model_store.h" +#include "function.h" +#include + +namespace Shared { + +template +ModelStore::ModelStore() : + m_numberOfModels(0) +{ +} + +template +T * ModelStore::addEmptyModel() { + assert(m_numberOfModels < maxNumberOfModels()); + setModelAtIndex(emptyModel(), m_numberOfModels++); + return modelAtIndex(m_numberOfModels-1); +} + +template +void ModelStore::removeModel(T * f) { + int i = 0; + while (modelAtIndex(i) != f && i < m_numberOfModels) { + i++; + } + assert(i>=0 && i +void ModelStore::removeAll() { + for (int i = 0; i < m_numberOfModels; i++) { + setModelAtIndex(nullModel(), i); + } + m_numberOfModels = 0; +} + +template +void ModelStore::tidy() { + for (int i = 0; i < m_numberOfModels; i++) { + tidyModelAtIndex(i); + } +} + +} + +template class Shared::ModelStore; diff --git a/apps/shared/model_store.h b/apps/shared/model_store.h new file mode 100644 index 00000000000..b9b48a38253 --- /dev/null +++ b/apps/shared/model_store.h @@ -0,0 +1,32 @@ +#ifndef SHARED_MODEL_STORE_H +#define SHARED_MODEL_STORE_H + +#include + +namespace Shared { + +/* ModelStore is a dumb class. + * Its only job is to store model */ + +template +class ModelStore { +public: + ModelStore(); + virtual T * modelAtIndex(int i) = 0; + T * addEmptyModel(); + void removeModel(T * f); + virtual void removeAll(); + int numberOfModels() const { return m_numberOfModels; }; + virtual int maxNumberOfModels() const = 0; + void tidy(); +protected: + virtual T * emptyModel() = 0; + virtual T * nullModel() = 0; + virtual void setModelAtIndex(T * f, int i) = 0; + virtual void tidyModelAtIndex(int i) = 0; + int m_numberOfModels; +}; + +} + +#endif From 78e750b0536822a6ad151f9761e60c6373c7266f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 23 May 2018 16:13:04 +0200 Subject: [PATCH 04/96] [shared] Change the ModelStore to store Expression Model Store --- apps/graph/cartesian_function_store.cpp | 8 ++--- apps/graph/cartesian_function_store.h | 6 ++-- apps/sequence/Makefile | 2 +- apps/sequence/sequence_store.cpp | 6 ++-- apps/sequence/sequence_store.h | 6 ++-- apps/shared/Makefile | 2 +- ...l_store.cpp => expression_model_store.cpp} | 21 ++++-------- apps/shared/expression_model_store.h | 31 ++++++++++++++++++ apps/shared/function_store.cpp | 6 +--- apps/shared/function_store.h | 6 ++-- apps/shared/model_store.h | 32 ------------------- 11 files changed, 57 insertions(+), 69 deletions(-) rename apps/shared/{model_store.cpp => expression_model_store.cpp} (64%) create mode 100644 apps/shared/expression_model_store.h delete mode 100644 apps/shared/model_store.h diff --git a/apps/graph/cartesian_function_store.cpp b/apps/graph/cartesian_function_store.cpp index ca028817baa..70b84f62b33 100644 --- a/apps/graph/cartesian_function_store.cpp +++ b/apps/graph/cartesian_function_store.cpp @@ -37,20 +37,20 @@ void CartesianFunctionStore::removeAll() { addEmptyModel(); } -Shared::Function * CartesianFunctionStore::emptyModel() { +CartesianFunction * CartesianFunctionStore::emptyModel() { static CartesianFunction addedFunction("", KDColorBlack); addedFunction = CartesianFunction(firstAvailableName(), firstAvailableColor()); return &addedFunction; } -Shared::Function * CartesianFunctionStore::nullModel() { +CartesianFunction * CartesianFunctionStore::nullModel() { static CartesianFunction emptyFunction("", KDColorBlack); return &emptyFunction; } -void CartesianFunctionStore::setModelAtIndex(Shared::Function * f, int i) { +void CartesianFunctionStore::setModelAtIndex(Shared::ExpressionModel * e, int i) { assert(i>=0 && i(f)); + m_functions[i] = *(static_cast(e)); } } diff --git a/apps/graph/cartesian_function_store.h b/apps/graph/cartesian_function_store.h index abba37b7681..3e60c41b33e 100644 --- a/apps/graph/cartesian_function_store.h +++ b/apps/graph/cartesian_function_store.h @@ -28,9 +28,9 @@ class CartesianFunctionStore : public Shared::FunctionStore { static constexpr const char * k_functionNames[k_maxNumberOfFunctions] = { "f", "g", "h", "p", }; - Shared::Function * emptyModel() override; - Shared::Function * nullModel() override; - void setModelAtIndex(Shared::Function * f, int i) override; + CartesianFunction * emptyModel() override; + CartesianFunction * nullModel() override; + void setModelAtIndex(Shared::ExpressionModel * f, int i) override; const char * firstAvailableName() override { return firstAvailableAttribute(k_functionNames, FunctionStore::name); } diff --git a/apps/sequence/Makefile b/apps/sequence/Makefile index a39515a165f..722141570e9 100644 --- a/apps/sequence/Makefile +++ b/apps/sequence/Makefile @@ -35,6 +35,6 @@ tests += $(addprefix apps/sequence/test/,\ sequence.cpp\ ) test_objs += $(addprefix apps/sequence/, sequence.o sequence_store.o sequence_context.o cache_context.o) -test_objs += $(addprefix apps/shared/, expression_model.o function.o function_store.o model_store.o) +test_objs += $(addprefix apps/shared/, expression_model.o expression_model_store.o function.o function_store.o) app_images += apps/sequence/sequence_icon.png diff --git a/apps/sequence/sequence_store.cpp b/apps/sequence/sequence_store.cpp index b3180f72c57..dd278170197 100644 --- a/apps/sequence/sequence_store.cpp +++ b/apps/sequence/sequence_store.cpp @@ -24,18 +24,18 @@ char SequenceStore::symbol() const { return 'n'; } -Shared::Function * SequenceStore::emptyModel() { +Sequence * SequenceStore::emptyModel() { static Sequence addedSequence("", KDColorBlack); addedSequence = Sequence(firstAvailableName(), firstAvailableColor()); return &addedSequence; } -Shared::Function * SequenceStore::nullModel() { +Sequence * SequenceStore::nullModel() { static Sequence emptyFunction("", KDColorBlack); return &emptyFunction; } -void SequenceStore::setModelAtIndex(Shared::Function * f, int i) { +void SequenceStore::setModelAtIndex(Shared::ExpressionModel * f, int i) { assert(i>=0 && i(f)); } diff --git a/apps/sequence/sequence_store.h b/apps/sequence/sequence_store.h index e335eb1ee1b..5ee9f8bc34d 100644 --- a/apps/sequence/sequence_store.h +++ b/apps/sequence/sequence_store.h @@ -30,12 +30,12 @@ class SequenceStore : public Shared::FunctionStore { return firstAvailableAttribute(k_sequenceNames, FunctionStore::name); } private: + Sequence * emptyModel() override; + Sequence * nullModel() override; + void setModelAtIndex(Shared::ExpressionModel * f, int i) override; static constexpr KDColor k_defaultColors[MaxNumberOfSequences] = { Palette::Red, Palette::Blue//, Palette::YellowDark }; - Shared::Function * emptyModel() override; - Shared::Function * nullModel() override; - void setModelAtIndex(Shared::Function * f, int i) override; const KDColor firstAvailableColor() override { return firstAvailableAttribute(k_defaultColors, FunctionStore::color); } diff --git a/apps/shared/Makefile b/apps/shared/Makefile index b09b72ff0dd..20e6df53d2f 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -8,6 +8,7 @@ app_objs += $(addprefix apps/shared/,\ editable_cell_table_view_controller.o\ expression_field_delegate_app.o\ expression_model.o\ + expression_model_store.o\ float_pair_store.o\ float_parameter_controller.o\ function.o\ @@ -32,7 +33,6 @@ app_objs += $(addprefix apps/shared/,\ memoized_curve_view_range.o\ message_view.o\ model_expression_cell.o\ - model_store.o\ new_function_cell.o\ ok_view.o\ parameter_text_field_delegate.o\ diff --git a/apps/shared/model_store.cpp b/apps/shared/expression_model_store.cpp similarity index 64% rename from apps/shared/model_store.cpp rename to apps/shared/expression_model_store.cpp index 10a7b19019c..043b7cebabb 100644 --- a/apps/shared/model_store.cpp +++ b/apps/shared/expression_model_store.cpp @@ -1,24 +1,21 @@ -#include "model_store.h" +#include "expression_model_store.h" #include "function.h" #include namespace Shared { -template -ModelStore::ModelStore() : +ExpressionModelStore::ExpressionModelStore() : m_numberOfModels(0) { } -template -T * ModelStore::addEmptyModel() { +ExpressionModel * ExpressionModelStore::addEmptyModel() { assert(m_numberOfModels < maxNumberOfModels()); setModelAtIndex(emptyModel(), m_numberOfModels++); return modelAtIndex(m_numberOfModels-1); } -template -void ModelStore::removeModel(T * f) { +void ExpressionModelStore::removeModel(ExpressionModel * f) { int i = 0; while (modelAtIndex(i) != f && i < m_numberOfModels) { i++; @@ -31,21 +28,17 @@ void ModelStore::removeModel(T * f) { m_numberOfModels--; } -template -void ModelStore::removeAll() { +void ExpressionModelStore::removeAll() { for (int i = 0; i < m_numberOfModels; i++) { setModelAtIndex(nullModel(), i); } m_numberOfModels = 0; } -template -void ModelStore::tidy() { +void ExpressionModelStore::tidy() { for (int i = 0; i < m_numberOfModels; i++) { - tidyModelAtIndex(i); + modelAtIndex(i)->tidy(); } } } - -template class Shared::ModelStore; diff --git a/apps/shared/expression_model_store.h b/apps/shared/expression_model_store.h new file mode 100644 index 00000000000..ce90778413b --- /dev/null +++ b/apps/shared/expression_model_store.h @@ -0,0 +1,31 @@ +#ifndef SHARED_EXPRESSION_MODEL_STORE_H +#define SHARED_EXPRESSION_MODEL_STORE_H + +#include "expression_model.h" +#include + +namespace Shared { + +/* ExpressionModelStore is a dumb class. + * Its only job is to store model */ + +class ExpressionModelStore { +public: + ExpressionModelStore(); + virtual ExpressionModel * modelAtIndex(int i) = 0; + ExpressionModel * addEmptyModel(); + void removeModel(ExpressionModel * f); + virtual void removeAll(); + int numberOfModels() const { return m_numberOfModels; }; + virtual int maxNumberOfModels() const = 0; + void tidy(); +protected: + virtual ExpressionModel * emptyModel() = 0; + virtual ExpressionModel * nullModel() = 0; + virtual void setModelAtIndex(ExpressionModel * f, int i) = 0; + int m_numberOfModels; +}; + +} + +#endif diff --git a/apps/shared/function_store.cpp b/apps/shared/function_store.cpp index c862d13d5ef..92ed2f6697d 100644 --- a/apps/shared/function_store.cpp +++ b/apps/shared/function_store.cpp @@ -4,7 +4,7 @@ namespace Shared { FunctionStore::FunctionStore() : - ModelStore() + ExpressionModelStore() { } @@ -60,10 +60,6 @@ int FunctionStore::numberOfDefinedFunctions() { return result; } -void FunctionStore::tidyModelAtIndex(int i) { - modelAtIndex(i)->tidy(); -} - template T FunctionStore::firstAvailableAttribute(T attributes[], AttributeGetter attribute) { for (int k = 0; k < maxNumberOfModels(); k++) { diff --git a/apps/shared/function_store.h b/apps/shared/function_store.h index d817a32bd18..a7afc979616 100644 --- a/apps/shared/function_store.h +++ b/apps/shared/function_store.h @@ -2,7 +2,7 @@ #define SHARED_FUNCTION_STORE_H #include "function.h" -#include "model_store.h" +#include "expression_model_store.h" #include namespace Shared { @@ -10,10 +10,11 @@ namespace Shared { /* FunctionStore is a dumb class. * Its only job is to store functions and to give them a color. */ -class FunctionStore : public ModelStore { +class FunctionStore : public ExpressionModelStore { public: FunctionStore(); virtual uint32_t storeChecksum() = 0; + virtual Function * modelAtIndex(int i) override = 0; virtual Function * activeFunctionAtIndex(int i); virtual Function * definedFunctionAtIndex(int i); // Functions can be undefined when they have a color and a name but no content @@ -29,7 +30,6 @@ class FunctionStore : public ModelStore { private: virtual const char * firstAvailableName() = 0; virtual const KDColor firstAvailableColor() = 0; - void tidyModelAtIndex(int i) override; }; } diff --git a/apps/shared/model_store.h b/apps/shared/model_store.h deleted file mode 100644 index b9b48a38253..00000000000 --- a/apps/shared/model_store.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SHARED_MODEL_STORE_H -#define SHARED_MODEL_STORE_H - -#include - -namespace Shared { - -/* ModelStore is a dumb class. - * Its only job is to store model */ - -template -class ModelStore { -public: - ModelStore(); - virtual T * modelAtIndex(int i) = 0; - T * addEmptyModel(); - void removeModel(T * f); - virtual void removeAll(); - int numberOfModels() const { return m_numberOfModels; }; - virtual int maxNumberOfModels() const = 0; - void tidy(); -protected: - virtual T * emptyModel() = 0; - virtual T * nullModel() = 0; - virtual void setModelAtIndex(T * f, int i) = 0; - virtual void tidyModelAtIndex(int i) = 0; - int m_numberOfModels; -}; - -} - -#endif From 837e0694d16622dfab4e860ec52a728991427824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 23 May 2018 16:40:51 +0200 Subject: [PATCH 05/96] [shared] Remove New Function Cell class which is a duplicate of Even Odd Message Text Cell --- apps/code/menu_controller.cpp | 3 ++- apps/code/menu_controller.h | 3 +-- apps/graph/list/list_controller.h | 1 - apps/sequence/list/list_controller.h | 1 - apps/shared/Makefile | 1 - apps/shared/list_controller.cpp | 3 ++- apps/shared/list_controller.h | 3 +-- apps/shared/new_function_cell.cpp | 35 ---------------------------- apps/shared/new_function_cell.h | 22 ----------------- 9 files changed, 6 insertions(+), 66 deletions(-) delete mode 100644 apps/shared/new_function_cell.cpp delete mode 100644 apps/shared/new_function_cell.h diff --git a/apps/code/menu_controller.cpp b/apps/code/menu_controller.cpp index 46c4488e185..fe2ff279341 100644 --- a/apps/code/menu_controller.cpp +++ b/apps/code/menu_controller.cpp @@ -12,7 +12,7 @@ MenuController::MenuController(Responder * parentResponder, ScriptStore * script ViewController(parentResponder), ButtonRowDelegate(nullptr, footer), m_scriptStore(scriptStore), - m_addNewScriptCell(I18n::Message::AddScript), + m_addNewScriptCell(), m_consoleButton(this, I18n::Message::Console, Invocation([](void * context, void * sender) { MenuController * menu = (MenuController *)context; if (menu->consoleController()->loadPythonEnvironment()) { @@ -29,6 +29,7 @@ MenuController::MenuController(Responder * parentResponder, ScriptStore * script { m_selectableTableView.setMargins(0); m_selectableTableView.setShowsIndicators(false); + m_addNewScriptCell.setMessage(I18n::Message::AddScript); for (int i = 0; i < k_maxNumberOfDisplayableScriptCells; i++) { m_scriptCells[i].setParentResponder(&m_selectableTableView); m_scriptCells[i].editableTextCell()->textField()->setDelegate(this); diff --git a/apps/code/menu_controller.h b/apps/code/menu_controller.h index a1665a3f089..61b5f565a00 100644 --- a/apps/code/menu_controller.h +++ b/apps/code/menu_controller.h @@ -2,7 +2,6 @@ #define CODE_MENU_CONTROLLER_H #include -#include #include "console_controller.h" #include "editor_controller.h" #include "script_parameter_controller.h" @@ -99,7 +98,7 @@ class MenuController : public ViewController, public TableViewDataSource, public * constructor of an EvenOddEditableTextCell. */ char m_draftTextBuffer[TextField::maxBufferSize()]; EvenOddCellWithEllipsis m_scriptParameterCells[k_maxNumberOfDisplayableScriptCells]; - Shared::NewFunctionCell m_addNewScriptCell; + EvenOddMessageTextCell m_addNewScriptCell; EvenOddCell m_emptyCell; Button m_consoleButton; SelectableTableView m_selectableTableView; diff --git a/apps/graph/list/list_controller.h b/apps/graph/list/list_controller.h index 4bcedbe21cf..e0684f0a0c9 100644 --- a/apps/graph/list/list_controller.h +++ b/apps/graph/list/list_controller.h @@ -4,7 +4,6 @@ #include #include "../function_title_cell.h" #include "../cartesian_function_store.h" -#include "../../shared/new_function_cell.h" #include "../../shared/model_expression_cell.h" #include "../../shared/list_controller.h" #include "../../shared/list_parameter_controller.h" diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index 98bfa1550fd..bbc932b86f8 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -5,7 +5,6 @@ #include "../sequence_title_cell.h" #include "../sequence_store.h" #include "../../shared/list_controller.h" -#include "../../shared/new_function_cell.h" #include "../../shared/model_expression_cell.h" #include "../../shared/expression_layout_field_delegate.h" #include "../../shared/text_field_delegate.h" diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 20e6df53d2f..69766774be6 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -33,7 +33,6 @@ app_objs += $(addprefix apps/shared/,\ memoized_curve_view_range.o\ message_view.o\ model_expression_cell.o\ - new_function_cell.o\ ok_view.o\ parameter_text_field_delegate.o\ range_parameter_controller.o\ diff --git a/apps/shared/list_controller.cpp b/apps/shared/list_controller.cpp index a2f83efc0ca..7698f6db4ec 100644 --- a/apps/shared/list_controller.cpp +++ b/apps/shared/list_controller.cpp @@ -294,7 +294,8 @@ void ListController::addEmptyFunction() { View * ListController::loadView() { m_emptyCell = new EvenOddCell(); - m_addNewFunction = new NewFunctionCell(m_addNewMessage); + m_addNewFunction = new EvenOddMessageTextCell(); + m_addNewFunction->setMessage(m_addNewMessage); SelectableTableView * selectableTableView = new SelectableTableView(this, this, this, this); selectableTableView->setMargins(0); selectableTableView->setVerticalCellOverlap(0); diff --git a/apps/shared/list_controller.h b/apps/shared/list_controller.h index 4a0824f48a7..8ce5575b236 100644 --- a/apps/shared/list_controller.h +++ b/apps/shared/list_controller.h @@ -4,7 +4,6 @@ #include #include "function_store.h" #include "list_parameter_controller.h" -#include "new_function_cell.h" #include "../i18n.h" namespace Shared { @@ -53,7 +52,7 @@ class ListController : public DynamicViewController, public ButtonRowDelegate, p virtual void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) = 0; EvenOddCell * m_emptyCell; I18n::Message m_addNewMessage; - NewFunctionCell * m_addNewFunction; + EvenOddMessageTextCell * m_addNewFunction; Button m_plotButton; Button m_valuesButton; }; diff --git a/apps/shared/new_function_cell.cpp b/apps/shared/new_function_cell.cpp deleted file mode 100644 index 18387df61c7..00000000000 --- a/apps/shared/new_function_cell.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "new_function_cell.h" -#include "assert.h" - -namespace Shared { - -NewFunctionCell::NewFunctionCell(I18n::Message text) : - EvenOddCell(), - m_messageTextView(KDText::FontSize::Large, text, 0.5f, 0.5f) -{ -} - -void NewFunctionCell::setEven(bool even) { - EvenOddCell::setEven(even); - m_messageTextView.setBackgroundColor(backgroundColor()); -} - -void NewFunctionCell::setHighlighted(bool highlight) { - EvenOddCell::setHighlighted(highlight); - m_messageTextView.setBackgroundColor(backgroundColor()); -} - -int NewFunctionCell::numberOfSubviews() const { - return 1; -} - -View * NewFunctionCell::subviewAtIndex(int index) { - assert(index == 0); - return &m_messageTextView; -} - -void NewFunctionCell::layoutSubviews() { - m_messageTextView.setFrame(bounds()); -} - -} diff --git a/apps/shared/new_function_cell.h b/apps/shared/new_function_cell.h deleted file mode 100644 index 7a8418b6cac..00000000000 --- a/apps/shared/new_function_cell.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SHARED_NEW_FUNCTION_CELL_H -#define SHARED_NEW_FUNCTION_CELL_H - -#include - -namespace Shared { - -class NewFunctionCell : public EvenOddCell { -public: - NewFunctionCell(I18n::Message text); - void setEven(bool even) override; - void setHighlighted(bool highlight) override; - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; -private: - MessageTextView m_messageTextView; -}; - -} - -#endif From 021262e3aa5451a39d3deaad575a0bb6bf99731a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 24 May 2018 09:40:34 +0200 Subject: [PATCH 06/96] [apps] Split List Controller in Expression Model List Controller and Function List Controller (factorize code for future solver app) --- apps/graph/list/list_controller.cpp | 52 +-- apps/graph/list/list_controller.h | 9 +- apps/sequence/list/list_controller.cpp | 52 +-- apps/sequence/list/list_controller.h | 19 +- apps/shared/Makefile | 3 +- .../expression_model_list_controller.cpp | 164 +++++++++ .../shared/expression_model_list_controller.h | 43 +++ apps/shared/function_list_controller.cpp | 226 +++++++++++++ ...ontroller.h => function_list_controller.h} | 46 ++- apps/shared/list_controller.cpp | 314 ------------------ 10 files changed, 511 insertions(+), 417 deletions(-) create mode 100644 apps/shared/expression_model_list_controller.cpp create mode 100644 apps/shared/expression_model_list_controller.h create mode 100644 apps/shared/function_list_controller.cpp rename apps/shared/{list_controller.h => function_list_controller.h} (56%) delete mode 100644 apps/shared/list_controller.cpp diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp index 1627f983123..2de0cde581e 100644 --- a/apps/graph/list/list_controller.cpp +++ b/apps/graph/list/list_controller.cpp @@ -9,7 +9,7 @@ using namespace Shared; namespace Graph { ListController::ListController(Responder * parentResponder, CartesianFunctionStore * functionStore, ButtonRowController * header, ButtonRowController * footer) : - Shared::ListController(parentResponder, functionStore, header, footer, I18n::Message::AddFunction), + Shared::FunctionListController(parentResponder, functionStore, header, footer, I18n::Message::AddFunction), m_functionTitleCells{}, m_expressionCells{}, m_parameterController(this, functionStore, I18n::Message::FunctionColor, I18n::Message::DeleteFunction) @@ -20,45 +20,6 @@ const char * ListController::title() { return I18n::translate(I18n::Message::FunctionTab); } -int ListController::numberOfRows() { - if (m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels()) { - return m_functionStore->numberOfModels(); - } - return 1 + m_functionStore->numberOfModels(); -}; - -KDCoordinate ListController::rowHeight(int j) { - if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && j == numberOfRows() - 1) { - return Metric::StoreRowHeight; - } - Function * function = m_functionStore->modelAtIndex(j); - if (function->layout() == nullptr) { - return Metric::StoreRowHeight; - } - KDCoordinate functionSize = function->layout()->size().height(); - return functionSize + Metric::StoreRowHeight - KDText::charSize().height(); -} - -void ListController::editExpression(Function * function, Ion::Events::Event event) { - char * initialText = nullptr; - char initialTextContent[TextField::maxBufferSize()]; - if (event == Ion::Events::OK || event == Ion::Events::EXE) { - strlcpy(initialTextContent, function->text(), sizeof(initialTextContent)); - initialText = initialTextContent; - } - App * myApp = (App *)app(); - InputViewController * inputController = myApp->inputViewController(); - inputController->edit(this, event, function, initialText, - [](void * context, void * sender){ - Shared::Function * myFunction = (Shared::Function *)context; - InputViewController * myInputViewController = (InputViewController *)sender; - const char * textBody = myInputViewController->textBody(); - myFunction->setContent(textBody); - }, - [](void * context, void * sender){ - }); -} - ListParameterController * ListController::parameterController() { return &m_parameterController; } @@ -88,18 +49,17 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { } void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { + Shared::FunctionListController::willDisplayExpressionCellAtIndex(cell, j); ModelExpressionCell * myCell = (ModelExpressionCell *)cell; Function * f = m_functionStore->modelAtIndex(j); - myCell->setExpressionLayout(f->layout()); bool active = f->isActive(); KDColor textColor = active ? KDColorBlack : Palette::GreyDark; myCell->setTextColor(textColor); } -bool ListController::removeFunctionRow(Function * function) { +bool ListController::removeModelRow(ExpressionModel * model) { if (m_functionStore->numberOfModels() > 1) { - m_functionStore->removeModel(function); - return true; + return Shared::FunctionListController::removeModelRow(model); } return false; } @@ -109,7 +69,7 @@ View * ListController::loadView() { m_functionTitleCells[i] = new FunctionTitleCell(FunctionTitleCell::Orientation::VerticalIndicator); m_expressionCells[i] = new ModelExpressionCell(); } - return Shared::ListController::loadView(); + return Shared::FunctionListController::loadView(); } void ListController::unloadView(View * view) { @@ -119,7 +79,7 @@ void ListController::unloadView(View * view) { delete m_expressionCells[i]; m_expressionCells[i] = nullptr; } - Shared::ListController::unloadView(view); + Shared::FunctionListController::unloadView(view); } } diff --git a/apps/graph/list/list_controller.h b/apps/graph/list/list_controller.h index e0684f0a0c9..0f8a2d7601a 100644 --- a/apps/graph/list/list_controller.h +++ b/apps/graph/list/list_controller.h @@ -5,26 +5,23 @@ #include "../function_title_cell.h" #include "../cartesian_function_store.h" #include "../../shared/model_expression_cell.h" -#include "../../shared/list_controller.h" +#include "../../shared/function_list_controller.h" #include "../../shared/list_parameter_controller.h" namespace Graph { -class ListController : public Shared::ListController { +class ListController : public Shared::FunctionListController { public: ListController(Responder * parentResponder, CartesianFunctionStore * functionStore, ButtonRowController * header, ButtonRowController * footer); const char * title() override; - int numberOfRows() override; - KDCoordinate rowHeight(int j) override; private: - void editExpression(Shared::Function * function, Ion::Events::Event event) override; Shared::ListParameterController * parameterController() override; int maxNumberOfRows() override; HighlightCell * titleCells(int index) override; HighlightCell * expressionCells(int index) override; void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) override; void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) override; - bool removeFunctionRow(Shared::Function * function) override; + bool removeModelRow(Shared::ExpressionModel * function) override; View * loadView() override; void unloadView(View * view) override; constexpr static int k_maxNumberOfRows = 5; diff --git a/apps/sequence/list/list_controller.cpp b/apps/sequence/list/list_controller.cpp index afa32a6dd84..c0f5d39045e 100644 --- a/apps/sequence/list/list_controller.cpp +++ b/apps/sequence/list/list_controller.cpp @@ -8,7 +8,7 @@ using namespace Poincare; namespace Sequence { ListController::ListController(Responder * parentResponder, SequenceStore * sequenceStore, ButtonRowController * header, ButtonRowController * footer) : - Shared::ListController(parentResponder, sequenceStore, header, footer, I18n::Message::AddSequence), + Shared::FunctionListController(parentResponder, sequenceStore, header, footer, I18n::Message::AddSequence), m_sequenceStore(sequenceStore), m_sequenceTitleCells{}, m_expressionCells{}, @@ -39,7 +39,7 @@ ExpressionFieldDelegateApp * ListController::expressionFieldDelegateApp() { return (App *)app(); } -int ListController::numberOfRows() { +int ListController::numberOfExpressionRows() { int numberOfRows = 0; for (int i = 0; i < m_sequenceStore->numberOfModels(); i++) { Sequence * sequence = m_sequenceStore->modelAtIndex(i); @@ -51,11 +51,11 @@ int ListController::numberOfRows() { return 1 + numberOfRows; }; -KDCoordinate ListController::rowHeight(int j) { +KDCoordinate ListController::expressionRowHeight(int j) { if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && j == numberOfRows() - 1) { return Metric::StoreRowHeight; } - Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(j)); + Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(j)); KDCoordinate defaultHeight = sequence->type() == Sequence::Type::Explicit ? Metric::StoreRowHeight : k_emptySubRowHeight; ExpressionLayout * layout = sequence->layout(); if (sequenceDefinitionForRow(j) == 1) { @@ -72,9 +72,9 @@ KDCoordinate ListController::rowHeight(int j) { } void ListController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { - Shared::ListController::willDisplayCellAtLocation(cell, i, j); + Shared::FunctionListController::willDisplayCellAtLocation(cell, i, j); EvenOddCell * myCell = (EvenOddCell *)cell; - myCell->setEven(functionIndexForRow(j)%2 == 0); + myCell->setEven(modelIndexForRow(j)%2 == 0); } void ListController::selectPreviousNewSequenceCell() { @@ -87,7 +87,7 @@ Toolbox * ListController::toolboxForSender(Responder * sender) { // Set extra cells int recurrenceDepth = -1; int sequenceDefinition = sequenceDefinitionForRow(selectedRow()); - Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(selectedRow())); + Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(selectedRow())); if (sequenceDefinition == 0) { recurrenceDepth = sequence->numberOfElements()-1; } @@ -154,8 +154,8 @@ void ListController::editExpression(Sequence * sequence, int sequenceDefinition, } } -bool ListController::removeFunctionRow(Function * function) { - m_functionStore->removeModel(function); +bool ListController::removeModelRow(ExpressionModel * model) { + Shared::FunctionListController::removeModelRow(model); // Invalidate the sequences context cache static_cast(app())->localContext()->resetCache(); return true; @@ -182,7 +182,7 @@ HighlightCell * ListController::expressionCells(int index) { void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { SequenceTitleCell * myCell = (SequenceTitleCell *)cell; - Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(j)); + Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { myCell->setExpressionLayout(sequence->definitionName()); } @@ -198,7 +198,7 @@ void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) { void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { ModelExpressionCell * myCell = (ModelExpressionCell *)cell; - Sequence * sequence = m_sequenceStore->modelAtIndex(functionIndexForRow(j)); + Sequence * sequence = m_sequenceStore->modelAtIndex(modelIndexForRow(j)); if (sequenceDefinitionForRow(j) == 0) { myCell->setExpressionLayout(sequence->layout()); } @@ -213,13 +213,12 @@ void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int myCell->setTextColor(textColor); } -int ListController::functionIndexForRow(int j) { +int ListController::modelIndexForRow(int j) { if (j < 0) { return j; } - if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && - j == numberOfRows() - 1) { - return functionIndexForRow(j-1)+1; + if (isAddEmptyRow(j)) { + return modelIndexForRow(j-1)+1; } int rowIndex = 0; int sequenceIndex = -1; @@ -231,8 +230,12 @@ int ListController::functionIndexForRow(int j) { return sequenceIndex; } +bool ListController::isAddEmptyRow(int j) { + return m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && j == numberOfRows() - 1; +} + const char * ListController::textForRow(int j) { - Sequence * sequence = ((SequenceStore *)m_functionStore)->modelAtIndex(functionIndexForRow(j)); + Sequence * sequence = ((SequenceStore *)m_functionStore)->modelAtIndex(modelIndexForRow(j)); switch (sequenceDefinitionForRow(j)) { case 0: return sequence->text(); @@ -250,8 +253,7 @@ int ListController::sequenceDefinitionForRow(int j) { if (j < 0) { return j; } - if (m_sequenceStore->numberOfModels() < m_sequenceStore->maxNumberOfModels() && - j == numberOfRows() - 1) { + if (isAddEmptyRow(j)) { return 0; } int rowIndex = 0; @@ -265,19 +267,19 @@ int ListController::sequenceDefinitionForRow(int j) { return sequence->numberOfElements()-rowIndex+j; } -void ListController::addEmptyFunction() { +void ListController::addEmptyModel() { app()->displayModalViewController(&m_typeStackController, 0.f, 0.f, Metric::TabHeight+Metric::ModalTopMargin, Metric::CommonRightMargin, Metric::ModalBottomMargin, Metric::CommonLeftMargin); } -void ListController::editExpression(Shared::Function * function, Ion::Events::Event event) { - Sequence * sequence = (Sequence *)function; +void ListController::editExpression(Shared::ExpressionModel * model, Ion::Events::Event event) { + Sequence * sequence = static_cast(model); editExpression(sequence, sequenceDefinitionForRow(selectedRow()), event); } -void ListController::reinitExpression(Shared::Function * function) { +void ListController::reinitExpression(Shared::ExpressionModel * model) { // Invalidate the sequences context cache static_cast(app())->localContext()->resetCache(); - Sequence * sequence = (Sequence *)function; + Sequence * sequence = static_cast(model); switch (sequenceDefinitionForRow(selectedRow())) { case 1: if (strlen(sequence->firstInitialConditionText()) == 0) { @@ -306,7 +308,7 @@ View * ListController::loadView() { m_sequenceTitleCells[i] = new SequenceTitleCell(FunctionTitleCell::Orientation::VerticalIndicator); m_expressionCells[i] = new ModelExpressionCell(); } - return Shared::ListController::loadView(); + return Shared::FunctionListController::loadView(); } void ListController::unloadView(View * view) { @@ -316,7 +318,7 @@ void ListController::unloadView(View * view) { delete m_expressionCells[i]; m_expressionCells[i] = nullptr; } - Shared::ListController::unloadView(view); + Shared::FunctionListController::unloadView(view); } } diff --git a/apps/sequence/list/list_controller.h b/apps/sequence/list/list_controller.h index bbc932b86f8..f24c8084919 100644 --- a/apps/sequence/list/list_controller.h +++ b/apps/sequence/list/list_controller.h @@ -4,8 +4,8 @@ #include #include "../sequence_title_cell.h" #include "../sequence_store.h" -#include "../../shared/list_controller.h" #include "../../shared/model_expression_cell.h" +#include "../../shared/function_list_controller.h" #include "../../shared/expression_layout_field_delegate.h" #include "../../shared/text_field_delegate.h" #include "list_parameter_controller.h" @@ -14,12 +14,12 @@ namespace Sequence { -class ListController : public Shared::ListController, public Shared::TextFieldDelegate, public Shared::ExpressionLayoutFieldDelegate { +class ListController : public Shared::FunctionListController, public Shared::TextFieldDelegate, public Shared::ExpressionLayoutFieldDelegate { public: ListController(Responder * parentResponder, SequenceStore * sequenceStore, ButtonRowController * header, ButtonRowController * footer); const char * title() override; - int numberOfRows() override; - virtual KDCoordinate rowHeight(int j) override; + int numberOfExpressionRows() override; + KDCoordinate expressionRowHeight(int j) override; void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; Toolbox * toolboxForTextInput(TextInput * textInput) override; Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override; @@ -35,13 +35,14 @@ class ListController : public Shared::ListController, public Shared::TextFieldDe HighlightCell * expressionCells(int index) override; void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) override; void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) override; - int functionIndexForRow(int j) override; + int modelIndexForRow(int j) override; + bool isAddEmptyRow(int j) override; const char * textForRow(int j) override; int sequenceDefinitionForRow(int j); - void addEmptyFunction() override; - void editExpression(Shared::Function * function, Ion::Events::Event event) override; - bool removeFunctionRow(Shared::Function * function) override; - void reinitExpression(Shared::Function * function) override; + void addEmptyModel() override; + void reinitExpression(Shared::ExpressionModel * model) override; + void editExpression(Shared::ExpressionModel * model, Ion::Events::Event event) override; + bool removeModelRow(Shared::ExpressionModel * model) override; View * loadView() override; void unloadView(View * view) override; static constexpr KDCoordinate k_emptySubRowHeight = 30; diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 69766774be6..d8795edd290 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -8,6 +8,7 @@ app_objs += $(addprefix apps/shared/,\ editable_cell_table_view_controller.o\ expression_field_delegate_app.o\ expression_model.o\ + expression_model_list_controller.o\ expression_model_store.o\ float_pair_store.o\ float_parameter_controller.o\ @@ -18,6 +19,7 @@ app_objs += $(addprefix apps/shared/,\ function_go_to_parameter_controller.o\ function_graph_view.o\ function_graph_controller.o\ + function_list_controller.o\ function_store.o\ function_title_cell.o\ go_to_parameter_controller.o\ @@ -28,7 +30,6 @@ app_objs += $(addprefix apps/shared/,\ interval.o\ interval_parameter_controller.o\ language_controller.o\ - list_controller.o\ list_parameter_controller.o\ memoized_curve_view_range.o\ message_view.o\ diff --git a/apps/shared/expression_model_list_controller.cpp b/apps/shared/expression_model_list_controller.cpp new file mode 100644 index 00000000000..acb438916b9 --- /dev/null +++ b/apps/shared/expression_model_list_controller.cpp @@ -0,0 +1,164 @@ +#include "expression_model_list_controller.h" +#include + +namespace Shared { + +ExpressionModelListController::ExpressionModelListController(Responder * parentResponder, I18n::Message text) : + DynamicViewController(parentResponder), + m_addNewMessage(text), + m_addNewModel(nullptr) +{ +} + +/* Table Data Source */ +int ExpressionModelListController::numberOfExpressionRows() { + if (modelStore()->numberOfModels() == modelStore()->maxNumberOfModels()) { + return modelStore()->numberOfModels(); + } + return 1 + modelStore()->numberOfModels(); +} + +KDCoordinate ExpressionModelListController::expressionRowHeight(int j) { + if (isAddEmptyRow(j)) { + return Metric::StoreRowHeight; + } + ExpressionModel * m = modelStore()->modelAtIndex(j); + if (m->layout() == nullptr) { + return Metric::StoreRowHeight; + } + KDCoordinate modelSize = m->layout()->size().height(); + return modelSize + Metric::StoreRowHeight - KDText::charSize().height(); +} + +KDCoordinate ExpressionModelListController::cumulatedExpressionHeightFromIndex(int j) { + int result = 0; + for (int k = 0; k < j; k++) { + result += expressionRowHeight(k); + } + return result; +} + +int ExpressionModelListController::indexFromCumulatedExpressionHeight(KDCoordinate offsetY) { + int result = 0; + int j = 0; + while (result < offsetY && j < numberOfExpressionRows()) { + result += expressionRowHeight(j++); + } + return (result < offsetY || offsetY == 0) ? j : j - 1; +} + +void ExpressionModelListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) { + EvenOddExpressionCell * myCell = (EvenOddExpressionCell *)cell; + ExpressionModel * m = modelStore()->modelAtIndex(j); + myCell->setExpressionLayout(m->layout()); +} + +/* Responder */ + +bool ExpressionModelListController::handleEventOnExpression(Ion::Events::Event event) { + if (selectedRow() < 0) { + return false; + } + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + if (isAddEmptyRow(selectedRow())) { + addEmptyModel(); + return true; + } + ExpressionModel * model = modelStore()->modelAtIndex(modelIndexForRow(selectedRow())); + editExpression(model, event); + return true; + } + if (event == Ion::Events::Backspace && !isAddEmptyRow(selectedRow())) { + ExpressionModel * model = modelStore()->modelAtIndex(modelIndexForRow(selectedRow())); + if (!model->isEmpty()) { + reinitExpression(model); + } else { + if (removeModelRow(model)) { + int newSelectedRow = selectedRow() >= numberOfExpressionRows() ? numberOfExpressionRows()-1 : selectedRow(); + selectCellAtLocation(selectedColumn(), newSelectedRow); + selectableTableView()->reloadData(); + } + } + return true; + } + if ((event.hasText() || event == Ion::Events::XNT || event == Ion::Events::Paste || event == Ion::Events::Toolbox || event == Ion::Events::Var) + && !isAddEmptyRow(selectedRow())) { + ExpressionModel * model = modelStore()->modelAtIndex(modelIndexForRow(selectedRow())); + editExpression(model, event); + return true; + } + if (event == Ion::Events::Copy && !isAddEmptyRow(selectedRow())) { + Clipboard::sharedClipboard()->store(textForRow(selectedRow())); + return true; + } + return false; +} + +void ExpressionModelListController::addEmptyModel() { + modelStore()->addEmptyModel(); + selectableTableView()->reloadData(); +} + +void ExpressionModelListController::reinitExpression(ExpressionModel * model) { + model->setContent(""); + selectableTableView()->reloadData(); +} + + +void ExpressionModelListController::editExpression(ExpressionModel * model, Ion::Events::Event event) { + char * initialText = nullptr; + char initialTextContent[TextField::maxBufferSize()]; + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + strlcpy(initialTextContent, model->text(), sizeof(initialTextContent)); + initialText = initialTextContent; + } + inputController()->edit(this, event, model, initialText, + [](void * context, void * sender){ + ExpressionModel * myModel = static_cast(context); + InputViewController * myInputViewController = (InputViewController *)sender; + const char * textBody = myInputViewController->textBody(); + myModel->setContent(textBody); + }, + [](void * context, void * sender){ + }); +} + +bool ExpressionModelListController::removeModelRow(ExpressionModel * model) { + modelStore()->removeModel(model); + return true; +} + +int ExpressionModelListController::modelIndexForRow(int j) { + return j; +} + +bool ExpressionModelListController::isAddEmptyRow(int j) { + return j == modelStore()->numberOfModels(); +} + +const char * ExpressionModelListController::textForRow(int j) { + ExpressionModel * model = modelStore()->modelAtIndex(modelIndexForRow(j)); + return model->text(); +} + +SelectableTableView * ExpressionModelListController::selectableTableView() { + return (SelectableTableView *)view(); +} + +View * ExpressionModelListController::loadView() { + m_addNewModel = new EvenOddMessageTextCell(); + m_addNewModel->setMessage(m_addNewMessage); + SelectableTableView * selectableTableView = new SelectableTableView(this, tableDataSource(), this, selectableTableDelegate()); + selectableTableView->setMargins(0); + selectableTableView->setVerticalCellOverlap(0); + selectableTableView->setShowsIndicators(false); + return selectableTableView; +} + +void ExpressionModelListController::unloadView(View * view) { + delete m_addNewModel; + m_addNewModel = nullptr; + delete view; +} + +} diff --git a/apps/shared/expression_model_list_controller.h b/apps/shared/expression_model_list_controller.h new file mode 100644 index 00000000000..686ba65d7bb --- /dev/null +++ b/apps/shared/expression_model_list_controller.h @@ -0,0 +1,43 @@ +#ifndef SHARED_EXPRESSION_MODEL_LIST_CONTROLLER_H +#define SHARED_EXPRESSION_MODEL_LIST_CONTROLLER_H + +#include +#include "expression_model_store.h" +#include "../i18n.h" + +namespace Shared { + +class ExpressionModelListController : public DynamicViewController, public SelectableTableViewDataSource { +public: + ExpressionModelListController(Responder * parentResponder, I18n::Message text); +protected: + /* Table Data Source */ + virtual int numberOfExpressionRows(); + virtual KDCoordinate expressionRowHeight(int j); + KDCoordinate cumulatedExpressionHeightFromIndex(int j); + int indexFromCumulatedExpressionHeight(KDCoordinate offsetY); + virtual void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j); + /* Responder */ + bool handleEventOnExpression(Ion::Events::Event event); + virtual void addEmptyModel(); + virtual void reinitExpression(ExpressionModel * model); + virtual void editExpression(ExpressionModel * model, Ion::Events::Event event); + virtual bool removeModelRow(ExpressionModel * function); + virtual int modelIndexForRow(int j); + virtual bool isAddEmptyRow(int j); + virtual const char * textForRow(int j); + /* Dynamic View Controller */ + SelectableTableView * selectableTableView(); + View * loadView() override; + void unloadView(View * view) override; + virtual ExpressionModelStore * modelStore() = 0; + virtual InputViewController * inputController() = 0; + virtual TableViewDataSource * tableDataSource() = 0; + virtual SelectableTableViewDelegate * selectableTableDelegate() = 0; + I18n::Message m_addNewMessage; + EvenOddMessageTextCell * m_addNewModel; +}; + +} + +#endif diff --git a/apps/shared/function_list_controller.cpp b/apps/shared/function_list_controller.cpp new file mode 100644 index 00000000000..6e5fb5b4eac --- /dev/null +++ b/apps/shared/function_list_controller.cpp @@ -0,0 +1,226 @@ +#include "function_list_controller.h" +#include + +namespace Shared { + +FunctionListController::FunctionListController(Responder * parentResponder, FunctionStore * functionStore, ButtonRowController * header, ButtonRowController * footer, I18n::Message text) : + ExpressionModelListController(parentResponder, text), + ButtonRowDelegate(header, footer), + m_functionStore(functionStore), + m_emptyCell(nullptr), + m_plotButton(this, I18n::Message::Plot, Invocation([](void * context, void * sender) { + FunctionListController * list = (FunctionListController *)context; + TabViewController * tabController = list->tabController(); + tabController->setActiveTab(1); + }, this), KDText::FontSize::Small, Palette::PurpleBright), + m_valuesButton(this, I18n::Message::DisplayValues, Invocation([](void * context, void * sender) { + FunctionListController * list = (FunctionListController *)context; + TabViewController * tabController = list->tabController(); + tabController->setActiveTab(2); + }, this), KDText::FontSize::Small, Palette::PurpleBright) +{ +} + +int FunctionListController::numberOfColumns() { + return 2; +}; + +KDCoordinate FunctionListController::columnWidth(int i) { + switch (i) { + case 0: + return k_functionNameWidth; + case 1: + return selectableTableView()->bounds().width()-k_functionNameWidth; + default: + assert(false); + return 0; + } +} + +KDCoordinate FunctionListController::cumulatedWidthFromIndex(int i) { + switch (i) { + case 0: + return 0; + case 1: + return k_functionNameWidth; + case 2: + return selectableTableView()->bounds().width(); + default: + assert(false); + return 0; + } +} + +int FunctionListController::indexFromCumulatedWidth(KDCoordinate offsetX) { + if (offsetX <= k_functionNameWidth) { + return 0; + } else { + if (offsetX <= selectableTableView()->bounds().width()) + return 1; + else { + return 2; + } + } +} + +int FunctionListController::typeAtLocation(int i, int j) { + if (isAddEmptyRow(j)){ + return i + 2; + } + return i; +} + +HighlightCell * FunctionListController::reusableCell(int index, int type) { + assert(index >= 0); + assert(index < maxNumberOfRows()); + switch (type) { + case 0: + return titleCells(index); + case 1: + return expressionCells(index); + case 2: + return m_emptyCell; + case 3: + return m_addNewModel; + default: + assert(false); + return nullptr; + } +} + +int FunctionListController::reusableCellCount(int type) { + if (type > 1) { + return 1; + } + return maxNumberOfRows(); +} + +void FunctionListController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { + if (!isAddEmptyRow(j)) { + if (i == 0) { + willDisplayTitleCellAtIndex(cell, j); + } else { + willDisplayExpressionCellAtIndex(cell, j); + } + } + EvenOddCell * myCell = (EvenOddCell *)cell; + myCell->setEven(j%2 == 0); + myCell->setHighlighted(i == selectedColumn() && j == selectedRow()); + myCell->reloadCell(); +} + +int FunctionListController::numberOfButtons(ButtonRowController::Position position) const { + if (position == ButtonRowController::Position::Bottom) { + return 2; + } + return 0; +} + +Button * FunctionListController::buttonAtIndex(int index, ButtonRowController::Position position) const { + if (position == ButtonRowController::Position::Top) { + return nullptr; + } + const Button * buttons[2] = {&m_plotButton, &m_valuesButton}; + return (Button *)buttons[index]; +} + +void FunctionListController::didBecomeFirstResponder() { + if (selectedRow() == -1) { + selectCellAtLocation(1, 0); + } else { + selectCellAtLocation(selectedColumn(), selectedRow()); + } + if (selectedRow() >= numberOfRows()) { + selectCellAtLocation(selectedColumn(), numberOfRows()-1); + } + footer()->setSelectedButton(-1); + app()->setFirstResponder(selectableTableView()); +} + +bool FunctionListController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Up) { + if (selectedRow() == -1) { + footer()->setSelectedButton(-1); + selectableTableView()->selectCellAtLocation(1, numberOfRows()-1); + app()->setFirstResponder(selectableTableView()); + return true; + } + selectableTableView()->deselectTable(); + assert(selectedRow() == -1); + app()->setFirstResponder(tabController()); + return true; + } + if (event == Ion::Events::Down) { + if (selectedRow() == -1) { + return false; + } + selectableTableView()->deselectTable(); + footer()->setSelectedButton(0); + return true; + } + if (selectedRow() < 0) { + return false; + } + if (selectedColumn() == 1) { + return handleEventOnExpression(event); + } + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + assert(selectedColumn() == 0); + configureFunction(m_functionStore->modelAtIndex(modelIndexForRow(selectedRow()))); + return true; + } + if (event == Ion::Events::Backspace) { + Shared::Function * function = m_functionStore->modelAtIndex(modelIndexForRow(selectedRow())); + if (removeModelRow(function)) { + int newSelectedRow = selectedRow() >= numberOfRows() ? numberOfRows()-1 : selectedRow(); + selectCellAtLocation(selectedColumn(), newSelectedRow); + selectableTableView()->reloadData(); + } + return true; + } + return false; +} + +void FunctionListController::didEnterResponderChain(Responder * previousFirstResponder) { + selectableTableView()->reloadData(); +} + +void FunctionListController::willExitResponderChain(Responder * nextFirstResponder) { + if (nextFirstResponder == tabController()) { + selectableTableView()->deselectTable(); + footer()->setSelectedButton(-1); + } +} + +void FunctionListController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) { + if (isAddEmptyRow(selectedRow()) && selectedColumn() == 0) { + t->selectCellAtLocation(1, numberOfRows()-1); + } +} + +StackViewController * FunctionListController::stackController() const{ + return (StackViewController *)(parentResponder()->parentResponder()->parentResponder()); +} + +void FunctionListController::configureFunction(Shared::Function * function) { + StackViewController * stack = stackController(); + parameterController()->setFunction(function); + stack->push(parameterController()); +} + +TabViewController * FunctionListController::tabController() const{ + return (TabViewController *)(parentResponder()->parentResponder()->parentResponder()->parentResponder()); +} + +View * FunctionListController::loadView() { + m_emptyCell = new EvenOddCell(); + return ExpressionModelListController::loadView(); +} + +void FunctionListController::unloadView(View * view) { + delete m_emptyCell; + m_emptyCell = nullptr; + Shared::ExpressionModelListController::unloadView(view); +} + +} diff --git a/apps/shared/list_controller.h b/apps/shared/function_list_controller.h similarity index 56% rename from apps/shared/list_controller.h rename to apps/shared/function_list_controller.h index 8ce5575b236..6cbefe3e989 100644 --- a/apps/shared/list_controller.h +++ b/apps/shared/function_list_controller.h @@ -1,58 +1,72 @@ -#ifndef SHARED_LIST_CONTROLLER_H -#define SHARED_LIST_CONTROLLER_H +#ifndef SHARED_FUNCTION_LIST_CONTROLLER_H +#define SHARED_FUNCTION_LIST_CONTROLLER_H #include #include "function_store.h" +#include "function_app.h" #include "list_parameter_controller.h" +#include "expression_model_list_controller.h" #include "../i18n.h" namespace Shared { -class ListController : public DynamicViewController, public ButtonRowDelegate, public TableViewDataSource, public SelectableTableViewDataSource, public SelectableTableViewDelegate { +class FunctionListController : public ExpressionModelListController, public ButtonRowDelegate, public TableViewDataSource, public SelectableTableViewDelegate { public: - ListController(Responder * parentResponder, FunctionStore * functionStore, ButtonRowController * header, ButtonRowController * footer, I18n::Message text); + FunctionListController(Responder * parentResponder, FunctionStore * functionStore, ButtonRowController * header, ButtonRowController * footer, I18n::Message text); + + /* TableViewDataSource */ + int numberOfRows() override { + return numberOfExpressionRows(); + } int numberOfColumns() override; + KDCoordinate rowHeight(int j) override { + return expressionRowHeight(j); + } KDCoordinate columnWidth(int i) override; + KDCoordinate cumulatedHeightFromIndex(int j) override { + return cumulatedExpressionHeightFromIndex(j); + } KDCoordinate cumulatedWidthFromIndex(int i) override; - KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override { + return indexFromCumulatedExpressionHeight(offsetY); + } int indexFromCumulatedWidth(KDCoordinate offsetX) override; - int indexFromCumulatedHeight(KDCoordinate offsetY) override; int typeAtLocation(int i, int j) override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; + /* ButtonRowDelegate */ int numberOfButtons(ButtonRowController::Position position) const override; Button * buttonAtIndex(int index, ButtonRowController::Position position) const override; + /* Responder */ void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; void didEnterResponderChain(Responder * previousFirstResponder) override; void willExitResponderChain(Responder * nextFirstResponder) override; + /* SelectableTableViewDelegate*/ void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override; protected: StackViewController * stackController() const; void configureFunction(Function * function); - virtual void reinitExpression(Function * function); - SelectableTableView * selectableTableView(); View * loadView() override; void unloadView(View * view) override; FunctionStore * m_functionStore; private: static constexpr KDCoordinate k_functionNameWidth = 65; TabViewController * tabController() const; - virtual int functionIndexForRow(int j); - virtual const char * textForRow(int j); - virtual void addEmptyFunction(); - virtual bool removeFunctionRow(Function * function) = 0; - virtual void editExpression(Function * function, Ion::Events::Event event) = 0; + ExpressionModelStore * modelStore() override { return m_functionStore; } + InputViewController * inputController() override { + FunctionApp * myApp = static_cast(app()); + return myApp->inputViewController(); + } + TableViewDataSource * tableDataSource() override { return this; } + SelectableTableViewDelegate * selectableTableDelegate() override { return this; } virtual ListParameterController * parameterController() = 0; virtual int maxNumberOfRows() = 0; virtual HighlightCell * titleCells(int index) = 0; virtual HighlightCell * expressionCells(int index) = 0; virtual void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) = 0; - virtual void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) = 0; EvenOddCell * m_emptyCell; - I18n::Message m_addNewMessage; - EvenOddMessageTextCell * m_addNewFunction; Button m_plotButton; Button m_valuesButton; }; diff --git a/apps/shared/list_controller.cpp b/apps/shared/list_controller.cpp deleted file mode 100644 index 7698f6db4ec..00000000000 --- a/apps/shared/list_controller.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include "list_controller.h" -#include - -namespace Shared { - -ListController::ListController(Responder * parentResponder, FunctionStore * functionStore, ButtonRowController * header, ButtonRowController * footer, I18n::Message text) : - DynamicViewController(parentResponder), - ButtonRowDelegate(header, footer), - m_functionStore(functionStore), - m_emptyCell(nullptr), - m_addNewMessage(text), - m_addNewFunction(nullptr), - m_plotButton(this, I18n::Message::Plot, Invocation([](void * context, void * sender) { - ListController * list = (ListController *)context; - TabViewController * tabController = list->tabController(); - tabController->setActiveTab(1); - }, this), KDText::FontSize::Small, Palette::PurpleBright), - m_valuesButton(this, I18n::Message::DisplayValues, Invocation([](void * context, void * sender) { - ListController * list = (ListController *)context; - TabViewController * tabController = list->tabController(); - tabController->setActiveTab(2); - }, this), KDText::FontSize::Small, Palette::PurpleBright) -{ -} - -int ListController::numberOfColumns() { - return 2; -}; - -KDCoordinate ListController::columnWidth(int i) { - switch (i) { - case 0: - return k_functionNameWidth; - case 1: - return selectableTableView()->bounds().width()-k_functionNameWidth; - default: - assert(false); - return 0; - } -} - -KDCoordinate ListController::cumulatedWidthFromIndex(int i) { - switch (i) { - case 0: - return 0; - case 1: - return k_functionNameWidth; - case 2: - return selectableTableView()->bounds().width(); - default: - assert(false); - return 0; - } -} - -KDCoordinate ListController::cumulatedHeightFromIndex(int j) { - int result = 0; - for (int k = 0; k < j; k++) { - result += rowHeight(k); - } - return result; -} - -int ListController::indexFromCumulatedWidth(KDCoordinate offsetX) { - if (offsetX <= k_functionNameWidth) { - return 0; - } else { - if (offsetX <= selectableTableView()->bounds().width()) - return 1; - else { - return 2; - } - } -} - -int ListController::indexFromCumulatedHeight(KDCoordinate offsetY) { - int result = 0; - int j = 0; - while (result < offsetY && j < numberOfRows()) { - result += rowHeight(j++); - } - return (result < offsetY || offsetY == 0) ? j : j - 1; -} - -int ListController::typeAtLocation(int i, int j) { - if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() - && j == numberOfRows() - 1) { - return i + 2; - } - return i; -} - -HighlightCell * ListController::reusableCell(int index, int type) { - assert(index >= 0); - assert(index < maxNumberOfRows()); - switch (type) { - case 0: - return titleCells(index); - case 1: - return expressionCells(index); - case 2: - return m_emptyCell; - case 3: - return m_addNewFunction; - default: - assert(false); - return nullptr; - } -} - -int ListController::reusableCellCount(int type) { - if (type > 1) { - return 1; - } - return maxNumberOfRows(); -} - -void ListController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { - if (j < numberOfRows() - 1 || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels()) { - if (i == 0) { - willDisplayTitleCellAtIndex(cell, j); - } else { - willDisplayExpressionCellAtIndex(cell, j); - } - } - EvenOddCell * myCell = (EvenOddCell *)cell; - myCell->setEven(j%2 == 0); - myCell->setHighlighted(i == selectedColumn() && j == selectedRow()); - myCell->reloadCell(); -} - -int ListController::numberOfButtons(ButtonRowController::Position position) const { - if (position == ButtonRowController::Position::Bottom) { - return 2; - } - return 0; -} - -Button * ListController::buttonAtIndex(int index, ButtonRowController::Position position) const { - if (position == ButtonRowController::Position::Top) { - return nullptr; - } - const Button * buttons[2] = {&m_plotButton, &m_valuesButton}; - return (Button *)buttons[index]; -} - -void ListController::didBecomeFirstResponder() { - if (selectedRow() == -1) { - selectCellAtLocation(1, 0); - } else { - selectCellAtLocation(selectedColumn(), selectedRow()); - } - if (selectedRow() >= numberOfRows()) { - selectCellAtLocation(selectedColumn(), numberOfRows()-1); - } - footer()->setSelectedButton(-1); - app()->setFirstResponder(selectableTableView()); -} - -bool ListController::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::Up) { - if (selectedRow() == -1) { - footer()->setSelectedButton(-1); - selectableTableView()->selectCellAtLocation(1, numberOfRows()-1); - app()->setFirstResponder(selectableTableView()); - return true; - } - selectableTableView()->deselectTable(); - assert(selectedRow() == -1); - app()->setFirstResponder(tabController()); - return true; - } - if (event == Ion::Events::Down) { - if (selectedRow() == -1) { - return false; - } - selectableTableView()->deselectTable(); - footer()->setSelectedButton(0); - return true; - } - if (event == Ion::Events::OK || event == Ion::Events::EXE) { - switch (selectedColumn()) { - case 0: - { - if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && - selectedRow() == numberOfRows() - 1) { - return true; - } - configureFunction(m_functionStore->modelAtIndex(functionIndexForRow(selectedRow()))); - return true; - } - case 1: - { - if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && - selectedRow() == numberOfRows() - 1) { - addEmptyFunction(); - return true; - } - Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(selectedRow())); - editExpression(function, event); - return true; - } - default: - { - return false; - } - } - } - if (event == Ion::Events::Backspace && selectedRow() >= 0 && - (selectedRow() < numberOfRows() - 1 || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels())) { - Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(selectedRow())); - if (selectedColumn() == 1 && !function->isEmpty()) { - reinitExpression(function); - } else { - if (removeFunctionRow(function)) { - selectCellAtLocation(selectedColumn(), selectedRow()); - if (selectedRow() >= numberOfRows()) { - selectCellAtLocation(selectedColumn(), numberOfRows()-1); - } - selectableTableView()->reloadData(); - } - } - return true; - } - if ((event.hasText() || event == Ion::Events::XNT || event == Ion::Events::Paste || event == Ion::Events::Toolbox || event == Ion::Events::Var) - && selectedColumn() == 1 - && (selectedRow() != numberOfRows() - 1 - || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels())) { - Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(selectedRow())); - editExpression(function, event); - return true; - } - if (event == Ion::Events::Copy && selectedColumn() == 1 && - (selectedRow() < numberOfRows() - 1 || m_functionStore->numberOfModels() == m_functionStore->maxNumberOfModels())) { - Clipboard::sharedClipboard()->store(textForRow(selectedRow())); - return true; - } - return false; -} - -void ListController::didEnterResponderChain(Responder * previousFirstResponder) { - selectableTableView()->reloadData(); -} - -void ListController::willExitResponderChain(Responder * nextFirstResponder) { - if (nextFirstResponder == tabController()) { - selectableTableView()->deselectTable(); - footer()->setSelectedButton(-1); - } -} - -void ListController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) { - if (m_functionStore->numberOfModels() < m_functionStore->maxNumberOfModels() && selectedRow() == numberOfRows() - 1 && selectedColumn() == 0) { - t->selectCellAtLocation(1, numberOfRows()-1); - } -} - -StackViewController * ListController::stackController() const{ - return (StackViewController *)(parentResponder()->parentResponder()->parentResponder()); -} - -void ListController::configureFunction(Shared::Function * function) { - StackViewController * stack = stackController(); - parameterController()->setFunction(function); - stack->push(parameterController()); -} - -void ListController::reinitExpression(Function * function) { - function->setContent(""); - selectableTableView()->reloadData(); -} - -SelectableTableView * ListController::selectableTableView() { - return (SelectableTableView *)view(); -} - -TabViewController * ListController::tabController() const{ - return (TabViewController *)(parentResponder()->parentResponder()->parentResponder()->parentResponder()); -} - -int ListController::functionIndexForRow(int j) { - return j; -} - -const char * ListController::textForRow(int j) { - Shared::Function * function = m_functionStore->modelAtIndex(functionIndexForRow(j)); - return function->text(); -} - -void ListController::addEmptyFunction() { - m_functionStore->addEmptyModel(); - selectableTableView()->reloadData(); -} - -View * ListController::loadView() { - m_emptyCell = new EvenOddCell(); - m_addNewFunction = new EvenOddMessageTextCell(); - m_addNewFunction->setMessage(m_addNewMessage); - SelectableTableView * selectableTableView = new SelectableTableView(this, this, this, this); - selectableTableView->setMargins(0); - selectableTableView->setVerticalCellOverlap(0); - selectableTableView->setShowsIndicators(false); - return selectableTableView; -} - -void ListController::unloadView(View * view) { - delete m_emptyCell; - m_emptyCell = nullptr; - delete m_addNewFunction; - m_addNewFunction = nullptr; - delete view; -} - -} From 5d2079cd9e01e7489491fcadcf5513f4dafaf849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 24 May 2018 11:33:55 +0200 Subject: [PATCH 07/96] [solver] First version of Solver app --- apps/solver/Makefile | 18 +++++ apps/solver/app.cpp | 68 +++++++++++++++++ apps/solver/app.h | 43 +++++++++++ apps/solver/base.de.i18n | 4 + apps/solver/base.en.i18n | 4 + apps/solver/base.es.i18n | 4 + apps/solver/base.fr.i18n | 4 + apps/solver/base.pt.i18n | 4 + apps/solver/equation.h | 13 ++++ apps/solver/equation_store.cpp | 14 ++++ apps/solver/equation_store.h | 30 ++++++++ apps/solver/list_controller.cpp | 131 ++++++++++++++++++++++++++++++++ apps/solver/list_controller.h | 55 ++++++++++++++ apps/solver/solver_icon.png | Bin 0 -> 3173 bytes build/config.mak | 2 +- 15 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 apps/solver/Makefile create mode 100644 apps/solver/app.cpp create mode 100644 apps/solver/app.h create mode 100644 apps/solver/base.de.i18n create mode 100644 apps/solver/base.en.i18n create mode 100644 apps/solver/base.es.i18n create mode 100644 apps/solver/base.fr.i18n create mode 100644 apps/solver/base.pt.i18n create mode 100644 apps/solver/equation.h create mode 100644 apps/solver/equation_store.cpp create mode 100644 apps/solver/equation_store.h create mode 100644 apps/solver/list_controller.cpp create mode 100644 apps/solver/list_controller.h create mode 100644 apps/solver/solver_icon.png diff --git a/apps/solver/Makefile b/apps/solver/Makefile new file mode 100644 index 00000000000..7fa8dab1514 --- /dev/null +++ b/apps/solver/Makefile @@ -0,0 +1,18 @@ +snapshots += Solver::App::Snapshot +snapshot_headers += apps/solver/app.h + +app_objs += $(addprefix apps/solver/,\ + app.o\ + equation_store.o\ + list_controller.o\ +) + +i18n_files += $(addprefix apps/solver/,\ + base.de.i18n\ + base.en.i18n\ + base.es.i18n\ + base.fr.i18n\ + base.pt.i18n\ +) + +app_images += apps/solver/solver_icon.png diff --git a/apps/solver/app.cpp b/apps/solver/app.cpp new file mode 100644 index 00000000000..5a554a5c618 --- /dev/null +++ b/apps/solver/app.cpp @@ -0,0 +1,68 @@ +#include "app.h" +#include "../i18n.h" +#include "solver_icon.h" + +using namespace Shared; + +namespace Solver { + +I18n::Message App::Descriptor::name() { + return I18n::Message::SolverApp; +} + +I18n::Message App::Descriptor::upperName() { + return I18n::Message::SolverAppCapital; +} + +const Image * App::Descriptor::icon() { + return ImageStore::SolverIcon; +} + +App::Snapshot::Snapshot() : + m_equationStore() +{ +} + +App * App::Snapshot::unpack(Container * container) { + return new App(container, this); +} + +App::Descriptor * App::Snapshot::descriptor() { + static Descriptor descriptor; + return &descriptor; +} + +void App::Snapshot::reset() { + // Delete all equations + m_equationStore.removeAll(); +} + +void App::Snapshot::tidy() { + // Delete all expressions of equations + m_equationStore.tidy(); +} + +App::App(Container * container, Snapshot * snapshot) : + ExpressionFieldDelegateApp(container, snapshot, &m_inputViewController), + m_listController(&m_stackViewController, snapshot->equationStore(), &m_listFooter), + m_listFooter(&m_stackViewController, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey), + m_stackViewController(&m_inputViewController, &m_listFooter), + m_inputViewController(&m_modalViewController, &m_stackViewController, this, this) +{ +} + +void App::willBecomeInactive() { + if (m_modalViewController.isDisplayingModal()) { + m_modalViewController.dismissModalViewController(); + } + if (inputViewController()->isDisplayingModal()) { + inputViewController()->abortEditionAndDismiss(); + } + ::App::willBecomeInactive(); +} + +const char * App::XNT() { + return "x"; +} + +} diff --git a/apps/solver/app.h b/apps/solver/app.h new file mode 100644 index 00000000000..bb83f8b9018 --- /dev/null +++ b/apps/solver/app.h @@ -0,0 +1,43 @@ +#ifndef SOLVER_SOLVER_APP_H +#define SOLVER_SOLVER_APP_H + +#include +#include "../shared/expression_field_delegate_app.h" +#include "list_controller.h" +#include "equation_store.h" + +namespace Solver { + +class App : public Shared::ExpressionFieldDelegateApp { +public: + class Descriptor : public ::App::Descriptor { + public: + I18n::Message name() override; + I18n::Message upperName() override; + const Image * icon() override; + }; + class Snapshot : public ::App::Snapshot { + public: + Snapshot(); + App * unpack(Container * container) override; + Descriptor * descriptor() override; + void reset() override; + EquationStore * equationStore() { return &m_equationStore; } + private: + void tidy() override; + EquationStore m_equationStore; + }; + InputViewController * inputViewController() { return &m_inputViewController; } + void willBecomeInactive() override; + const char * XNT() override; +private: + App(Container * container, Snapshot * snapshot); + ListController m_listController; + ButtonRowController m_listFooter; + StackViewController m_stackViewController; + InputViewController m_inputViewController; +}; + +} + +#endif diff --git a/apps/solver/base.de.i18n b/apps/solver/base.de.i18n new file mode 100644 index 00000000000..56ed27fb0a8 --- /dev/null +++ b/apps/solver/base.de.i18n @@ -0,0 +1,4 @@ +SolverApp = "Equation" +SolverAppCapital = "EQUATION" +AddEquation = "Ajouter une équation" +Resolve = "Résoudre" diff --git a/apps/solver/base.en.i18n b/apps/solver/base.en.i18n new file mode 100644 index 00000000000..f809f6f93b1 --- /dev/null +++ b/apps/solver/base.en.i18n @@ -0,0 +1,4 @@ +SolverApp = "Equation" +SolverAppCapital = "EQUATION" +AddEquation = "Ajouter une équation" +Resolve = "Résoudre l'équation" diff --git a/apps/solver/base.es.i18n b/apps/solver/base.es.i18n new file mode 100644 index 00000000000..56ed27fb0a8 --- /dev/null +++ b/apps/solver/base.es.i18n @@ -0,0 +1,4 @@ +SolverApp = "Equation" +SolverAppCapital = "EQUATION" +AddEquation = "Ajouter une équation" +Resolve = "Résoudre" diff --git a/apps/solver/base.fr.i18n b/apps/solver/base.fr.i18n new file mode 100644 index 00000000000..f809f6f93b1 --- /dev/null +++ b/apps/solver/base.fr.i18n @@ -0,0 +1,4 @@ +SolverApp = "Equation" +SolverAppCapital = "EQUATION" +AddEquation = "Ajouter une équation" +Resolve = "Résoudre l'équation" diff --git a/apps/solver/base.pt.i18n b/apps/solver/base.pt.i18n new file mode 100644 index 00000000000..56ed27fb0a8 --- /dev/null +++ b/apps/solver/base.pt.i18n @@ -0,0 +1,4 @@ +SolverApp = "Equation" +SolverAppCapital = "EQUATION" +AddEquation = "Ajouter une équation" +Resolve = "Résoudre" diff --git a/apps/solver/equation.h b/apps/solver/equation.h new file mode 100644 index 00000000000..d2c57f4c14c --- /dev/null +++ b/apps/solver/equation.h @@ -0,0 +1,13 @@ +#ifndef SOLVER_EQUATION_h +#define SOLVER_EQUATION_h + +#include "../shared/expression_model.h" + +namespace Solver { + +class Equation : public Shared::ExpressionModel { +}; + +} + +#endif diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp new file mode 100644 index 00000000000..f2a3e2a563d --- /dev/null +++ b/apps/solver/equation_store.cpp @@ -0,0 +1,14 @@ +#include "equation_store.h" + +namespace Solver { + +Equation * EquationStore::emptyModel() { + static Equation e; + return &e; +} + +void EquationStore::setModelAtIndex(Shared::ExpressionModel * e, int i) { + m_equations[i] = *(static_cast(e));; +} + +} diff --git a/apps/solver/equation_store.h b/apps/solver/equation_store.h new file mode 100644 index 00000000000..ab190c131da --- /dev/null +++ b/apps/solver/equation_store.h @@ -0,0 +1,30 @@ +#ifndef SOLVER_EQUATION_STORE_H +#define SOLVER_EQUATION_STORE_H + +#include "equation.h" +#include "../shared/expression_model_store.h" +#include + +namespace Solver { + +class EquationStore : public Shared::ExpressionModelStore { +public: + EquationStore() {} + Equation * modelAtIndex(int i) override { + assert(i>=0 && i + +using namespace Shared; + +namespace Solver { + +ListController::ListController(Responder * parentResponder, EquationStore * equationStore, ButtonRowController * footer) : + ExpressionModelListController(parentResponder, I18n::Message::AddEquation), + ButtonRowDelegate(nullptr, footer), + m_equationStore(equationStore), + m_resolveButton(this, I18n::Message::Resolve, Invocation([](void * context, void * sender) { + ListController * list = (ListController *)context; + StackViewController * stackController = list->stackController(); + // TODO + //stackController->push(list->solutionPage ??) + }, this), KDText::FontSize::Small, Palette::PurpleBright) +{ +} + +int ListController::numberOfButtons(ButtonRowController::Position position) const { + if (position == ButtonRowController::Position::Bottom) { + return 1; + } + return 0; +} + +Button * ListController::buttonAtIndex(int index, ButtonRowController::Position position) const { + if (position == ButtonRowController::Position::Top) { + return nullptr; + } + return const_cast