From 2ba077af28a0865c386b6a84cbbaffdfe5649e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 22 Feb 2019 16:25:29 +0100 Subject: [PATCH] [solver] Make Solver::ListController inherits from StorageExpressionModelListController instead of ExpressionModelListController --- ...orage_expression_model_list_controller.cpp | 48 +++++++++++++++++-- ...storage_expression_model_list_controller.h | 5 +- .../storage_function_list_controller.cpp | 48 ------------------- .../shared/storage_function_list_controller.h | 13 +++-- apps/solver/equation_list_view.cpp | 9 ++-- apps/solver/equation_list_view.h | 4 +- .../equation_models_parameter_controller.cpp | 10 ++-- apps/solver/list_controller.cpp | 8 ++-- apps/solver/list_controller.h | 26 +++++----- 9 files changed, 90 insertions(+), 81 deletions(-) diff --git a/apps/shared/storage_expression_model_list_controller.cpp b/apps/shared/storage_expression_model_list_controller.cpp index 619eaf283..55ad03508 100644 --- a/apps/shared/storage_expression_model_list_controller.cpp +++ b/apps/shared/storage_expression_model_list_controller.cpp @@ -4,6 +4,8 @@ namespace Shared { +static inline int minInt(int x, int y) { return x < y ? x : y; } + /* Table Data Source */ StorageExpressionModelListController::StorageExpressionModelListController(Responder * parentResponder, I18n::Message text) : @@ -50,7 +52,7 @@ KDCoordinate StorageExpressionModelListController::memoizedRowHeight(int j) { if (j < 0) { return 0; } - int currentSelectedRow = selectedRow(); + int currentSelectedRow = selectedRow() < 0 ? 0 : selectedRow(); constexpr int halfMemoizationCount = k_memoizedCellsCount/2; if (j >= currentSelectedRow - halfMemoizationCount && j <= currentSelectedRow + halfMemoizationCount) { int memoizedIndex = j - (currentSelectedRow - halfMemoizationCount); @@ -66,7 +68,7 @@ KDCoordinate StorageExpressionModelListController::memoizedCumulatedHeightFromIn if (j <= 0) { return 0; } - int currentSelectedRow = selectedRow(); + int currentSelectedRow = selectedRow() < 0 ? 0 : selectedRow(); constexpr int halfMemoizationCount = k_memoizedCellsCount/2; /* If j is not easily computable from the memoized values, compute it the hard * way. */ @@ -97,7 +99,45 @@ KDCoordinate StorageExpressionModelListController::memoizedCumulatedHeightFromIn return result; } +int StorageExpressionModelListController::memoizedIndexFromCumulatedHeight(KDCoordinate offsetY) { + if (offsetY == 0) { + return 0; + } + /* We use memoization to speed up this method: if offsetY is "around" the + * memoized cumulatedHeightForIndex, we can compute its value easily by + * adding/substracting memoized row heights. */ + + int currentSelectedRow = selectedRow() < 0 ? 0 : selectedRow(); + int rowsCount = numberOfExpressionRows(); + if (rowsCount <= 1 || currentSelectedRow < 1) { + return notMemoizedIndexFromCumulatedHeight(offsetY); + } + + KDCoordinate currentCumulatedHeight = memoizedCumulatedHeightFromIndex(currentSelectedRow); + if (offsetY > currentCumulatedHeight) { + int iMax = minInt(k_memoizedCellsCount/2 + 1, rowsCount - currentSelectedRow); + for (int i = 0; i < iMax; i++) { + currentCumulatedHeight+= memoizedRowHeight(currentSelectedRow + i); + if (offsetY <= currentCumulatedHeight) { + return currentSelectedRow + i; + } + } + } else { + int iMax = minInt(k_memoizedCellsCount/2, currentSelectedRow); + for (int i = 1; i <= iMax; i++) { + currentCumulatedHeight-= memoizedRowHeight(currentSelectedRow-i); + if (offsetY > currentCumulatedHeight) { + return currentSelectedRow - i; + } + } + } + return notMemoizedIndexFromCumulatedHeight(offsetY); +} + int StorageExpressionModelListController::numberOfExpressionRows() { + if (modelStore()->numberOfModels() == modelStore()->maxNumberOfModels()) { + return modelStore()->numberOfModels(); + } return 1 + modelStore()->numberOfModels(); } @@ -195,8 +235,6 @@ void StorageExpressionModelListController::editExpression(Ion::Events::Event eve StorageExpressionModelListController * myController = static_cast(context); InputViewController * myInputViewController = (InputViewController *)sender; const char * textBody = myInputViewController->textBody(); - // Reset memoization of the selected cell which always corresponds to the k_memoizedCellsCount/2 memoized cell - myController->resetMemoizationForIndex(k_memoizedCellsCount/2); return myController->editSelectedRecordWithText(textBody); }, [](void * context, void * sender){ @@ -205,6 +243,8 @@ void StorageExpressionModelListController::editExpression(Ion::Events::Event eve } bool StorageExpressionModelListController::editSelectedRecordWithText(const char * text) { + // Reset memoization of the selected cell which always corresponds to the k_memoizedCellsCount/2 memoized cell + resetMemoizationForIndex(k_memoizedCellsCount/2); Ion::Storage::Record record = modelStore()->recordAtIndex(modelIndexForRow(selectedRow())); ExpiringPointer model = modelStore()->modelForRecord(record); return (model->setContent(text) == Ion::Storage::Record::ErrorStatus::None); diff --git a/apps/shared/storage_expression_model_list_controller.h b/apps/shared/storage_expression_model_list_controller.h index ac1d6d06c..f4976ccbf 100644 --- a/apps/shared/storage_expression_model_list_controller.h +++ b/apps/shared/storage_expression_model_list_controller.h @@ -35,8 +35,6 @@ protected: virtual SelectableTableView * selectableTableView() = 0; virtual StorageExpressionModelStore * modelStore() = 0; virtual InputViewController * inputController() = 0; - EvenOddMessageTextCell m_addNewModel; -protected: // Memoization static constexpr int k_memoizedCellsCount = 7; /* We use memoization to speed up indexFromHeight(offset) in the children @@ -57,11 +55,14 @@ protected: * || j > selectedRow + halfMemoizationCount) { ... } */ virtual void resetMemoizationForIndex(int index); virtual void shiftMemoization(bool newCellIsUnder); + EvenOddMessageTextCell m_addNewModel; private: // Memoization static constexpr int k_resetedMemoizedValue = -1; void resetMemoization(); + // TableViewDataSource virtual KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) = 0; + virtual int notMemoizedIndexFromCumulatedHeight(KDCoordinate offsetY) = 0; KDCoordinate m_memoizedCellHeight[k_memoizedCellsCount]; KDCoordinate m_cumulatedHeightForSelectedIndex; }; diff --git a/apps/shared/storage_function_list_controller.cpp b/apps/shared/storage_function_list_controller.cpp index 1e2bf357d..31ef84600 100644 --- a/apps/shared/storage_function_list_controller.cpp +++ b/apps/shared/storage_function_list_controller.cpp @@ -41,14 +41,6 @@ void StorageFunctionListController::viewWillAppear() { computeTitlesColumnWidth(); } -KDCoordinate StorageFunctionListController::rowHeight(int j) { - return StorageExpressionModelListController::memoizedRowHeight(j); -} - -KDCoordinate StorageFunctionListController::cumulatedHeightFromIndex(int j) { - return StorageExpressionModelListController::memoizedCumulatedHeightFromIndex(j); -} - KDCoordinate StorageFunctionListController::columnWidth(int i) { switch (i) { case 0: @@ -87,42 +79,6 @@ int StorageFunctionListController::indexFromCumulatedWidth(KDCoordinate offsetX) } } -int StorageFunctionListController::indexFromCumulatedHeight(KDCoordinate offsetY) { - if (offsetY == 0) { - return 0; - } - - /* We use memoization to speed up this method: if offsetY is "around" the - * memoized cumulatedHeightForIndex, we can compute its value easily by - * adding/substracting memoized row heights. */ - - int currentSelectedRow = selectedRow(); - int rowsCount = numberOfRows(); - if (rowsCount <= 1 || currentSelectedRow < 1) { - return TableViewDataSource::indexFromCumulatedHeight(offsetY); - } - - KDCoordinate currentCumulatedHeight = cumulatedHeightFromIndex(currentSelectedRow); - if (offsetY > currentCumulatedHeight) { - int iMax = minInt(k_memoizedCellsCount/2 + 1, rowsCount - currentSelectedRow); - for (int i = 0; i < iMax; i++) { - currentCumulatedHeight+= rowHeight(currentSelectedRow + i); - if (offsetY <= currentCumulatedHeight) { - return currentSelectedRow + i; - } - } - } else { - int iMax = minInt(k_memoizedCellsCount/2, currentSelectedRow); - for (int i = 1; i <= iMax; i++) { - currentCumulatedHeight-= rowHeight(currentSelectedRow-i); - if (offsetY > currentCumulatedHeight) { - return currentSelectedRow - i; - } - } - } - return TableViewDataSource::indexFromCumulatedHeight(offsetY); -} - int StorageFunctionListController::typeAtLocation(int i, int j) { if (isAddEmptyRow(j)){ return i + 2; @@ -320,10 +276,6 @@ void StorageFunctionListController::didChangeModelsList() { computeTitlesColumnWidth(); } -KDCoordinate StorageFunctionListController::notMemoizedCumulatedHeightFromIndex(int j) { - return TableViewDataSource::cumulatedHeightFromIndex(j); -} - KDCoordinate StorageFunctionListController::baseline(int j) { if (j < 0) { return -1; diff --git a/apps/shared/storage_function_list_controller.h b/apps/shared/storage_function_list_controller.h index e56ea212d..6a5e92e80 100644 --- a/apps/shared/storage_function_list_controller.h +++ b/apps/shared/storage_function_list_controller.h @@ -20,13 +20,13 @@ public: /* TableViewDataSource */ int numberOfRows() override { return this->numberOfExpressionRows(); } + KDCoordinate rowHeight(int j) override { return StorageExpressionModelListController::memoizedRowHeight(j); } + KDCoordinate cumulatedHeightFromIndex(int j) override { return StorageExpressionModelListController::memoizedCumulatedHeightFromIndex(j); } + int indexFromCumulatedHeight(KDCoordinate offsetY) override { return StorageExpressionModelListController::memoizedIndexFromCumulatedHeight(offsetY); } int numberOfColumns() override { return 2; } - KDCoordinate rowHeight(int j) override; KDCoordinate columnWidth(int i) override; KDCoordinate cumulatedWidthFromIndex(int i) override; - KDCoordinate cumulatedHeightFromIndex(int j) override; 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; @@ -66,7 +66,12 @@ private: InputViewController * inputController() override; KDCoordinate maxFunctionNameWidth(); void didChangeModelsList() override; - KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) override; + KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) override { + return TableViewDataSource::cumulatedHeightFromIndex(j); + } + int notMemoizedIndexFromCumulatedHeight(KDCoordinate offsetY) override { + return TableViewDataSource::indexFromCumulatedHeight(offsetY); + } virtual StorageListParameterController * parameterController() = 0; virtual int maxNumberOfDisplayableRows() = 0; virtual FunctionTitleCell * titleCells(int index) = 0; diff --git a/apps/solver/equation_list_view.cpp b/apps/solver/equation_list_view.cpp index c666a0bb3..a9fb8ab2c 100644 --- a/apps/solver/equation_list_view.cpp +++ b/apps/solver/equation_list_view.cpp @@ -1,21 +1,22 @@ #include "equation_list_view.h" +#include "list_controller.h" namespace Solver { /* EquationListView */ -EquationListView::EquationListView(Responder * parentResponder, TableViewDataSource * dataSource, SelectableTableViewDataSource * selectionDataSource) : - Responder(parentResponder), +EquationListView::EquationListView(ListController * listController) : + Responder(listController), View(), m_braceStyle(BraceStyle::None), - m_listView(this, dataSource, selectionDataSource), + m_listView(this, listController, listController, listController), m_braceView(), m_scrollBraceView(&m_braceView, this) { m_listView.setMargins(0); m_listView.setVerticalCellOverlap(0); m_listView.setDecoratorType(ScrollView::Decorator::Type::None); - selectionDataSource->setScrollViewDelegate(this); + listController->setScrollViewDelegate(this); m_scrollBraceView.setMargins(k_margin, k_margin, k_margin, k_margin); m_scrollBraceView.setDecoratorType(ScrollView::Decorator::Type::None); m_scrollBraceView.setBackgroundColor(KDColorWhite); diff --git a/apps/solver/equation_list_view.h b/apps/solver/equation_list_view.h index 59bbaed98..9363c7fe6 100644 --- a/apps/solver/equation_list_view.h +++ b/apps/solver/equation_list_view.h @@ -5,6 +5,8 @@ namespace Solver { +class ListController; + class EquationListView : public Responder, public View, public ScrollViewDelegate, public ScrollViewDataSource { public: enum class BraceStyle { @@ -12,7 +14,7 @@ public: OneRowShort, Full }; - EquationListView(Responder * parentResponder, TableViewDataSource * dataSource, SelectableTableViewDataSource * selectionDataSource); + EquationListView(ListController * listController); void setBraceStyle(BraceStyle style); void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override; void didBecomeFirstResponder() override; diff --git a/apps/solver/equation_models_parameter_controller.cpp b/apps/solver/equation_models_parameter_controller.cpp index d1ab2622c..67382c589 100644 --- a/apps/solver/equation_models_parameter_controller.cpp +++ b/apps/solver/equation_models_parameter_controller.cpp @@ -47,10 +47,14 @@ void EquationModelsParameterController::didBecomeFirstResponder() { bool EquationModelsParameterController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { - Equation * newEquation = static_cast(m_equationStore->addEmptyModel()); - newEquation->setContent(k_models[selectedRow()]); + Ion::Storage::Record::ErrorStatus error = m_equationStore->addEmptyModel(); + if (error == Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable) { + return false; + } + assert(error == Ion::Storage::Record::ErrorStatus::None); + m_listController->editSelectedRecordWithText(k_models[selectedRow()]); app()->dismissModalViewController(); - m_listController->editExpression(newEquation, Ion::Events::OK); + m_listController->editExpression(Ion::Events::OK); return true; } return false; diff --git a/apps/solver/list_controller.cpp b/apps/solver/list_controller.cpp index e5b8d21ab..363aee8d9 100644 --- a/apps/solver/list_controller.cpp +++ b/apps/solver/list_controller.cpp @@ -8,10 +8,10 @@ using namespace Shared; namespace Solver { ListController::ListController(Responder * parentResponder, EquationStore * equationStore, ButtonRowController * footer) : - ExpressionModelListController(parentResponder, I18n::Message::AddEquation), + StorageExpressionModelListController(parentResponder, I18n::Message::AddEquation), ButtonRowDelegate(nullptr, footer), m_equationStore(equationStore), - m_equationListView(this, this, this), + m_equationListView(this), m_expressionCells{}, m_resolveButton(this, equationStore->numberOfDefinedModels() > 1 ? I18n::Message::ResolveSystem : I18n::Message::ResolveEquation, Invocation([](void * context, void * sender) { ListController * list = (ListController *)context; @@ -214,8 +214,8 @@ void ListController::addEmptyModel() { app()->displayModalViewController(&m_modelsStackController, 0.f, 0.f, Metric::CommonTopMargin, Metric::CommonRightMargin, 0, Metric::CommonLeftMargin); } -bool ListController::removeModelRow(ExpressionModel * model) { - ExpressionModelListController::removeModelRow(model); +bool ListController::removeModelRow(Ion::Storage::Record record) { + StorageExpressionModelListController::removeModelRow(record); reloadButtonMessage(); reloadBrace(); return true; diff --git a/apps/solver/list_controller.h b/apps/solver/list_controller.h index 14ca87f87..82137cc7c 100644 --- a/apps/solver/list_controller.h +++ b/apps/solver/list_controller.h @@ -2,7 +2,7 @@ #define SOLVER_LIST_CONTROLLER_H #include -#include "../shared/expression_model_list_controller.h" +#include "../shared/storage_expression_model_list_controller.h" #include "../shared/layout_field_delegate.h" #include "../shared/text_field_delegate.h" #include "equation_store.h" @@ -12,19 +12,17 @@ namespace Solver { -class ListController : public Shared::ExpressionModelListController, public ButtonRowDelegate, public ListViewDataSource, public Shared::TextFieldDelegate, public Shared::LayoutFieldDelegate { +class ListController : public Shared::StorageExpressionModelListController, public ButtonRowDelegate, public ListViewDataSource, public Shared::TextFieldDelegate, public Shared::LayoutFieldDelegate { public: ListController(Responder * parentResponder, EquationStore * equationStore, ButtonRowController * footer); /* ButtonRowDelegate */ int numberOfButtons(ButtonRowController::Position position) const override; Button * buttonAtIndex(int index, ButtonRowController::Position position) const override; /* ListViewDataSource */ - int numberOfRows() override { - return numberOfExpressionRows(); - } - KDCoordinate rowHeight(int j) override { - return expressionRowHeight(j); - } + int numberOfRows() override { return numberOfExpressionRows(); } + KDCoordinate rowHeight(int j) override{ return StorageExpressionModelListController::memoizedRowHeight(j); } + KDCoordinate cumulatedHeightFromIndex(int j) override { return StorageExpressionModelListController::memoizedCumulatedHeightFromIndex(j); } + int indexFromCumulatedHeight(KDCoordinate offsetY) override { return StorageExpressionModelListController::memoizedIndexFromCumulatedHeight(offsetY); } int typeAtLocation(int i, int j) override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; @@ -33,7 +31,10 @@ public: bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; void didEnterResponderChain(Responder * previousFirstResponder) override; - void editExpression(Shared::ExpressionModel * model, Ion::Events::Event event) override { return Shared::ExpressionModelListController::editExpression(model, event); } + /* StorageExpressionModelListController */ + // Make methods public + void editExpression(Ion::Events::Event event) override { return Shared::StorageExpressionModelListController::editExpression(event); } + bool editSelectedRecordWithText(const char * text) override { return Shared::StorageExpressionModelListController::editSelectedRecordWithText(text); } /* ViewController */ View * view() override { return &m_equationListView; } /* Text/Layout Field Delegate */ @@ -50,11 +51,14 @@ private: SelectableTableView * selectableTableView() override; void reloadButtonMessage(); void addEmptyModel() override; - bool removeModelRow(Shared::ExpressionModel * function) override; + bool removeModelRow(Ion::Storage::Record record) override; void reloadBrace(); - Shared::ExpressionModelStore * modelStore() override { return m_equationStore; } + Shared::StorageExpressionModelStore * modelStore() override { return m_equationStore; } StackViewController * stackController() const; InputViewController * inputController() override; + // ListViewDataSource + KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) override { return ListViewDataSource::cumulatedHeightFromIndex(j); } + int notMemoizedIndexFromCumulatedHeight(KDCoordinate offsetY) override { return ListViewDataSource::indexFromCumulatedHeight(offsetY); } EquationStore * m_equationStore; EquationListView m_equationListView; EvenOddExpressionCell m_expressionCells[k_maxNumberOfRows];