From c0e4eaa56b81277edd110d928647f7e25cab82d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 12 Oct 2018 11:18:04 +0200 Subject: [PATCH] [apps/graph] Use storage controllers in Values --- apps/graph/Makefile | 6 +- apps/graph/app.cpp | 2 +- apps/graph/app.h | 4 +- .../derivative_parameter_controller.cpp | 90 ----- .../values/derivative_parameter_controller.h | 44 --- .../values/function_parameter_controller.cpp | 77 ----- .../values/function_parameter_controller.h | 34 -- apps/graph/values/values_controller.cpp | 167 --------- apps/graph/values/values_controller.h | 44 --- apps/shared/Makefile | 2 + apps/shared/storage_values_controller.cpp | 322 ++++++++++++++++++ apps/shared/storage_values_controller.h | 81 +++++ ...e_values_function_parameter_controller.cpp | 24 ++ ...age_values_function_parameter_controller.h | 44 +++ 14 files changed, 479 insertions(+), 462 deletions(-) delete mode 100644 apps/graph/values/derivative_parameter_controller.cpp delete mode 100644 apps/graph/values/derivative_parameter_controller.h delete mode 100644 apps/graph/values/function_parameter_controller.cpp delete mode 100644 apps/graph/values/function_parameter_controller.h delete mode 100644 apps/graph/values/values_controller.cpp delete mode 100644 apps/graph/values/values_controller.h create mode 100644 apps/shared/storage_values_controller.cpp create mode 100644 apps/shared/storage_values_controller.h create mode 100644 apps/shared/storage_values_function_parameter_controller.cpp create mode 100644 apps/shared/storage_values_function_parameter_controller.h diff --git a/apps/graph/Makefile b/apps/graph/Makefile index c014d5ea7..6db21faeb 100644 --- a/apps/graph/Makefile +++ b/apps/graph/Makefile @@ -17,9 +17,9 @@ app_objs += $(addprefix apps/graph/,\ graph/root_graph_controller.o\ graph/tangent_graph_controller.o\ list/storage_list_controller.o\ - values/derivative_parameter_controller.o\ - values/function_parameter_controller.o\ - values/values_controller.o\ + values/storage_derivative_parameter_controller.o\ + values/storage_function_parameter_controller.o\ + values/storage_values_controller.o\ ) i18n_files += $(addprefix apps/graph/,\ diff --git a/apps/graph/app.cpp b/apps/graph/app.cpp index 3b92a42c9..8fde0ed90 100644 --- a/apps/graph/app.cpp +++ b/apps/graph/app.cpp @@ -65,7 +65,7 @@ App::App(Container * container, Snapshot * snapshot) : m_graphAlternateEmptyViewController(&m_graphHeader, &m_graphController, &m_graphController), m_graphHeader(&m_graphStackViewController, &m_graphAlternateEmptyViewController, &m_graphController), m_graphStackViewController(&m_tabViewController, &m_graphHeader), - m_valuesController(&m_valuesAlternateEmptyViewController, nullptr/*TODOsnapshot->functionStore()*/, snapshot->interval(), &m_valuesHeader), + m_valuesController(&m_valuesAlternateEmptyViewController, snapshot->functionStore(), snapshot->interval(), &m_valuesHeader), m_valuesAlternateEmptyViewController(&m_valuesHeader, &m_valuesController, &m_valuesController), m_valuesHeader(&m_valuesStackViewController, &m_valuesAlternateEmptyViewController, &m_valuesController), m_valuesStackViewController(&m_tabViewController, &m_valuesHeader), diff --git a/apps/graph/app.h b/apps/graph/app.h index 792bae216..4bdb03449 100644 --- a/apps/graph/app.h +++ b/apps/graph/app.h @@ -5,7 +5,7 @@ #include "storage_cartesian_function_store.h" #include "graph/graph_controller.h" #include "list/storage_list_controller.h" -#include "values/values_controller.h" +#include "values/storage_values_controller.h" #include "../shared/function_app.h" namespace Graph { @@ -43,7 +43,7 @@ private: AlternateEmptyViewController m_graphAlternateEmptyViewController; ButtonRowController m_graphHeader; StackViewController m_graphStackViewController; - ValuesController m_valuesController; + StorageValuesController m_valuesController; AlternateEmptyViewController m_valuesAlternateEmptyViewController; ButtonRowController m_valuesHeader; StackViewController m_valuesStackViewController; diff --git a/apps/graph/values/derivative_parameter_controller.cpp b/apps/graph/values/derivative_parameter_controller.cpp deleted file mode 100644 index 6c042781f..000000000 --- a/apps/graph/values/derivative_parameter_controller.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "derivative_parameter_controller.h" -#include "values_controller.h" -#include - -namespace Graph { - -DerivativeParameterController::DerivativeParameterController(ValuesController * valuesController) : - ViewController(valuesController), - m_hideColumn(I18n::Message::HideDerivativeColumn), -#if COPY_COLUMN - m_copyColumn(I18n::Message::CopyColumnInList), -#endif - m_selectableTableView(this), - m_function(nullptr), - m_valuesController(valuesController) -{ -} - -const char * DerivativeParameterController::title() { - strlcpy(m_pageTitle, I18n::translate(I18n::Message::DerivativeColumn), k_maxNumberOfCharsInTitle); - for (int currentChar = 0; currentChar < k_maxNumberOfCharsInTitle; currentChar++) { - if (m_pageTitle[currentChar] == '(') { - m_pageTitle[currentChar-2] = *m_function->name(); - break; - } - } - return m_pageTitle; -} - -View * DerivativeParameterController::view() { - return &m_selectableTableView; -} - -void DerivativeParameterController::setFunction(CartesianFunction * function) { - m_function = function; -} - -void DerivativeParameterController::didBecomeFirstResponder() { - selectCellAtLocation(0, 0); - app()->setFirstResponder(&m_selectableTableView); -} - -bool DerivativeParameterController::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::OK || event == Ion::Events::EXE) { - switch (selectedRow()) { - case 0: - { - m_valuesController->selectCellAtLocation(m_valuesController->selectedColumn()-1, m_valuesController->selectedRow()); - m_function->setDisplayDerivative(false); - StackViewController * stack = (StackViewController *)(parentResponder()); - stack->pop(); - return true; - } -#if COPY_COLUMN - case 1: - /* TODO: implement function copy column */ - return true; -#endif - default: - assert(false); - return false; - } - } - return false; -} - -int DerivativeParameterController::numberOfRows() { - return k_totalNumberOfCell; -}; - -HighlightCell * DerivativeParameterController::reusableCell(int index) { - assert(index >= 0); - assert(index < k_totalNumberOfCell); -#if COPY_COLUMN - HighlightCell * cells[] = {&m_hideColumn, &m_copyColumn}; -#else - HighlightCell * cells[] = {&m_hideColumn}; -#endif - return cells[index]; -} - -int DerivativeParameterController::reusableCellCount() { - return k_totalNumberOfCell; -} - -KDCoordinate DerivativeParameterController::cellHeight() { - return Metric::ParameterCellHeight; -} - -} diff --git a/apps/graph/values/derivative_parameter_controller.h b/apps/graph/values/derivative_parameter_controller.h deleted file mode 100644 index 9cc346053..000000000 --- a/apps/graph/values/derivative_parameter_controller.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef GRAPH_DERIVATIVE_PARAM_CONTROLLER_H -#define GRAPH_DERIVATIVE_PARAM_CONTROLLER_H - -#include -#include "../cartesian_function.h" - -namespace Graph { - -class ValuesController; - -class DerivativeParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource { -public: - DerivativeParameterController(ValuesController * valuesController); - - View * view() override; - const char * title() override; - bool handleEvent(Ion::Events::Event event) override; - void didBecomeFirstResponder() override; - int numberOfRows() override; - KDCoordinate cellHeight() override; - HighlightCell * reusableCell(int index) override; - int reusableCellCount() override; - - void setFunction(CartesianFunction * function); -private: -#if COPY_COLUMN - constexpr static int k_totalNumberOfCell = 2; -#else - constexpr static int k_totalNumberOfCell = 1; -#endif - constexpr static int k_maxNumberOfCharsInTitle = 16; - char m_pageTitle[k_maxNumberOfCharsInTitle]; - MessageTableCell m_hideColumn; -#if COPY_COLUMN - MessageTableCellWithChevron m_copyColumn; -#endif - SelectableTableView m_selectableTableView; - CartesianFunction * m_function; - ValuesController * m_valuesController; -}; - -} - -#endif diff --git a/apps/graph/values/function_parameter_controller.cpp b/apps/graph/values/function_parameter_controller.cpp deleted file mode 100644 index 4ddb639b0..000000000 --- a/apps/graph/values/function_parameter_controller.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "function_parameter_controller.h" -#include "values_controller.h" -#include - -using namespace Shared; - -namespace Graph { - -FunctionParameterController::FunctionParameterController(ValuesController * valuesController) : - ValuesFunctionParameterController('x'), - m_displayDerivativeColumn(I18n::Message::DerivativeFunctionColumn), - m_cartesianFunction(nullptr), - m_valuesController(valuesController) -{ -} - -void FunctionParameterController::setFunction(Function * function) { - m_cartesianFunction = (CartesianFunction *)function; - ValuesFunctionParameterController::setFunction(function); -} - -bool FunctionParameterController::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::OK || event == Ion::Events::EXE) { - switch (selectedRow()) { - case 0: - { - m_cartesianFunction->setDisplayDerivative(!m_cartesianFunction->displayDerivative()); - m_selectableTableView.reloadData(); - return true; - } -#if COPY_COLUMN - case 1: - /* TODO: implement function copy column */ - return true; -#endif - default: - assert(false); - return false; - } - } - return false; -} - -int FunctionParameterController::numberOfRows() { - return k_totalNumberOfCell; -}; - -HighlightCell * FunctionParameterController::reusableCell(int index) { - assert(index >= 0); - assert(index < k_totalNumberOfCell); -#if COPY_COLUMN - HighlightCell * cells[] = {&m_displayDerivativeColumn, &m_copyColumn}; -#else - HighlightCell * cells[] = {&m_displayDerivativeColumn}; -#endif - return cells[index]; -} - -int FunctionParameterController::reusableCellCount() { - return k_totalNumberOfCell; -} - -void FunctionParameterController::viewWillAppear() { - ValuesFunctionParameterController::viewWillAppear(); - if (m_cartesianFunction->displayDerivative()) { - m_valuesController->selectCellAtLocation(m_valuesController->selectedColumn()+1, m_valuesController->selectedRow()); - } -} - -void FunctionParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { - if (cell == &m_displayDerivativeColumn) { - SwitchView * switchView = (SwitchView *)m_displayDerivativeColumn.accessoryView(); - switchView->setState(m_cartesianFunction->displayDerivative()); - } -} - -} diff --git a/apps/graph/values/function_parameter_controller.h b/apps/graph/values/function_parameter_controller.h deleted file mode 100644 index 4c9f44ab9..000000000 --- a/apps/graph/values/function_parameter_controller.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef GRAPH_FUNCTION_PARAM_CONTROLLER_H -#define GRAPH_FUNCTION_PARAM_CONTROLLER_H - -#include "../cartesian_function.h" -#include "../../shared/values_function_parameter_controller.h" - -namespace Graph { - -class ValuesController; - -class FunctionParameterController : public Shared::ValuesFunctionParameterController { -public: - FunctionParameterController(ValuesController * valuesController); - bool handleEvent(Ion::Events::Event event) override; - int numberOfRows() override; - HighlightCell * reusableCell(int index) override; - int reusableCellCount() override; - void willDisplayCellForIndex(HighlightCell * cell, int index) override; - void setFunction(Shared::Function * function) override; - void viewWillAppear() override; -private: -#if COPY_COLUMN - constexpr static int k_totalNumberOfCell = 2; -#else - constexpr static int k_totalNumberOfCell = 1; -#endif - MessageTableCellWithSwitch m_displayDerivativeColumn; - CartesianFunction * m_cartesianFunction; - ValuesController * m_valuesController; -}; - -} - -#endif diff --git a/apps/graph/values/values_controller.cpp b/apps/graph/values/values_controller.cpp deleted file mode 100644 index d97c351aa..000000000 --- a/apps/graph/values/values_controller.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "values_controller.h" -#include -#include "../../constant.h" - -using namespace Shared; -using namespace Poincare; - -namespace Graph { - -ValuesController::ValuesController(Responder * parentResponder, CartesianFunctionStore * functionStore, Interval * interval, ButtonRowController * header) : - Shared::ValuesController(parentResponder, header, I18n::Message::XColumn, &m_intervalParameterController, interval), - m_functionTitleCells{}, - m_floatCells{}, - m_functionStore(functionStore), - m_functionParameterController(this), - m_intervalParameterController(this, m_interval), - m_derivativeParameterController(this) -{ - for (int i = 0; i < k_maxNumberOfFunctions; i++) { - m_functionTitleCells[i].setOrientation(FunctionTitleCell::Orientation::HorizontalIndicator); - m_functionTitleCells[i].setFont(KDFont::SmallFont); - } -} - -bool ValuesController::handleEvent(Ion::Events::Event event) { - if ((event == Ion::Events::OK || event == Ion::Events::EXE) && selectedRow() == 0 - && selectedColumn()>0 && isDerivativeColumn(selectedColumn())) { - configureDerivativeFunction(); - return true; - } - return Shared::ValuesController::handleEvent(event); -} - -void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { - Shared::ValuesController::willDisplayCellAtLocation(cell, i, j); - // The cell is the abscissa title cell: - if (j == 0 && i == 0) { - EvenOddMessageTextCell * mytitleCell = (EvenOddMessageTextCell *)cell; - mytitleCell->setMessage(I18n::Message::X); - return; - } - // The cell is a function title cell: - if (j == 0 && i > 0) { - Shared::BufferFunctionTitleCell * myFunctionCell = (Shared::BufferFunctionTitleCell *)cell; - CartesianFunction * function = functionAtColumn(i); - char bufferName[6] = {0, 0, '(', 'x', ')', 0}; - const char * name = nullptr; - if (isDerivativeColumn(i)) { - bufferName[0] = *function->name(); - bufferName[1] = '\''; - name = bufferName; - } else { - bufferName[1] = *function->name(); - name = &bufferName[1]; - } - myFunctionCell->setText(name); - myFunctionCell->setColor(function->color()); - } -} - -I18n::Message ValuesController::emptyMessage() { - if (m_functionStore->numberOfDefinedModels() == 0) { - return I18n::Message::NoFunction; - } - return I18n::Message::NoActivatedFunction; -} - -IntervalParameterController * ValuesController::intervalParameterController() { - return &m_intervalParameterController; -} - -CartesianFunction * ValuesController::functionAtColumn(int i) { - assert(i > 0); - int index = 1; - for (int k = 0; k < m_functionStore->numberOfDefinedModels(); k++) { - if (m_functionStore->definedFunctionAtIndex(k)->isActive()) { - if (i == index) { - return m_functionStore->definedFunctionAtIndex(k); - } - index++; - if (m_functionStore->definedFunctionAtIndex(k)->displayDerivative()) { - if (i == index) { - return m_functionStore->definedFunctionAtIndex(k); - } - index++; - } - } - } - assert(false); - return nullptr; -} - -bool ValuesController::isDerivativeColumn(int i) { - assert(i >= 1); - int index = 1; - for (int k = 0; k < m_functionStore->numberOfDefinedModels(); k++) { - if (m_functionStore->definedFunctionAtIndex(k)->isActive()) { - if (i == index) { - return false; - } - index++; - if (m_functionStore->definedFunctionAtIndex(k)->displayDerivative()) { - if (i == index) { - return true; - } - index++; - } - } - } - assert(false); - return false; -} - -void ValuesController::configureDerivativeFunction() { - CartesianFunction * function = functionAtColumn(selectedColumn()); - m_derivativeParameterController.setFunction(function); - StackViewController * stack = stackController(); - stack->push(&m_derivativeParameterController); -} - -int ValuesController::maxNumberOfCells() { - return k_maxNumberOfCells; -} - -int ValuesController::maxNumberOfFunctions() { - return k_maxNumberOfFunctions; -} - -Shared::BufferFunctionTitleCell * ValuesController::functionTitleCells(int j) { - assert(j >= 0 && j < k_maxNumberOfFunctions); - return &m_functionTitleCells[j]; -} - -EvenOddBufferTextCell * ValuesController::floatCells(int j) { - assert(j >= 0 && j < k_maxNumberOfCells); - return &m_floatCells[j]; -} - -CartesianFunctionStore * ValuesController::functionStore() const { - return m_functionStore; -} - -FunctionParameterController * ValuesController::functionParameterController() { - return &m_functionParameterController; -} - -double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) { - CartesianFunction * function = functionAtColumn(columnIndex); - TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); - if (isDerivativeColumn(columnIndex)) { - return function->approximateDerivative(abscissa, myApp->localContext()); - } - return function->evaluateAtAbscissa(abscissa, myApp->localContext()); -} - -void ValuesController::updateNumberOfColumns() { - int result = 1; - for (int i = 0; i < m_functionStore->numberOfActiveFunctions(); i++) { - if (m_functionStore->activeFunctionAtIndex(i)->isActive()) { - result += 1 + m_functionStore->activeFunctionAtIndex(i)->displayDerivative(); - } - } - m_numberOfColumns = result; -} - -} - diff --git a/apps/graph/values/values_controller.h b/apps/graph/values/values_controller.h deleted file mode 100644 index 89747d732..000000000 --- a/apps/graph/values/values_controller.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef GRAPH_VALUES_CONTROLLER_H -#define GRAPH_VALUES_CONTROLLER_H - -#include "../cartesian_function_store.h" -#include "../../shared/buffer_function_title_cell.h" -#include "../../shared/values_controller.h" -#include "../../shared/interval_parameter_controller.h" -#include "derivative_parameter_controller.h" -#include "function_parameter_controller.h" - -namespace Graph { - -class ValuesController : public Shared::ValuesController { -public: - ValuesController(Responder * parentResponder, CartesianFunctionStore * functionStore, Shared::Interval * interval, ButtonRowController * header); - bool handleEvent(Ion::Events::Event event) override; - void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; - I18n::Message emptyMessage() override; - Shared::IntervalParameterController * intervalParameterController() override; - void updateNumberOfColumns() override; -private: - CartesianFunction * functionAtColumn(int i) override; - bool isDerivativeColumn(int i); - void configureDerivativeFunction(); - int maxNumberOfCells() override; - int maxNumberOfFunctions() override; - double evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) override; - constexpr static int k_maxNumberOfCells = 50; - constexpr static int k_maxNumberOfFunctions = 5; - Shared::BufferFunctionTitleCell m_functionTitleCells[k_maxNumberOfFunctions]; - Shared::BufferFunctionTitleCell * functionTitleCells(int j) override; - EvenOddBufferTextCell m_floatCells[k_maxNumberOfCells]; - EvenOddBufferTextCell * floatCells(int j) override; - CartesianFunctionStore * m_functionStore; - CartesianFunctionStore * functionStore() const override; - FunctionParameterController m_functionParameterController; - FunctionParameterController * functionParameterController() override; - Shared::IntervalParameterController m_intervalParameterController; - DerivativeParameterController m_derivativeParameterController; -}; - -} - -#endif diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 9c3af4565..d221c4c4b 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -64,6 +64,8 @@ app_objs += $(addprefix apps/shared/,\ storage_function_store.o\ storage_list_parameter_controller.o\ storage_sum_graph_controller.o\ + storage_values_function_parameter_controller.o\ + storage_values_controller.o\ store_cell.o\ store_context.o\ store_controller.o\ diff --git a/apps/shared/storage_values_controller.cpp b/apps/shared/storage_values_controller.cpp new file mode 100644 index 000000000..a961c967c --- /dev/null +++ b/apps/shared/storage_values_controller.cpp @@ -0,0 +1,322 @@ +#include "storage_values_controller.h" +#include "text_field_delegate_app.h" +#include "../constant.h" +#include "../apps_container.h" +#include "poincare_helpers.h" +#include + +using namespace Poincare; + +namespace Shared { + +StorageValuesController::StorageValuesController(Responder * parentResponder, ButtonRowController * header, I18n::Message parameterTitle, IntervalParameterController * intervalParameterController, Interval * interval) : + EditableCellTableViewController(parentResponder), + ButtonRowDelegate(header, nullptr), + m_interval(interval), + m_numberOfColumns(0), + m_numberOfColumnsNeedUpdate(true), + m_selectableTableView(this), + m_abscissaTitleCell(), + m_abscissaCells{}, + m_abscissaParameterController(this, intervalParameterController, parameterTitle), + m_setIntervalButton(this, I18n::Message::IntervalSet, Invocation([](void * context, void * sender) { + StorageValuesController * valuesController = (StorageValuesController *) context; + StackViewController * stack = ((StackViewController *)valuesController->stackController()); + stack->push(valuesController->intervalParameterController()); + }, this), KDText::FontSize::Small) +{ + m_selectableTableView.setVerticalCellOverlap(0); + m_selectableTableView.setTopMargin(k_topMargin); + m_selectableTableView.setRightMargin(k_rightMargin); + m_selectableTableView.setBottomMargin(k_bottomMargin); + m_selectableTableView.setLeftMargin(k_leftMargin); + m_selectableTableView.setBackgroundColor(Palette::WallScreenDark); + m_selectableTableView.setIndicatorThickness(13); + m_abscissaTitleCell.setMessageFontSize(KDText::FontSize::Small); + for (int i = 0; i < k_maxNumberOfAbscissaCells; i++) { + m_abscissaCells[i].setParentResponder(&m_selectableTableView); + m_abscissaCells[i].editableTextCell()->textField()->setDelegate(this); + m_abscissaCells[i].editableTextCell()->textField()->setDraftTextBuffer(m_draftTextBuffer); + m_abscissaCells[i].editableTextCell()->textField()->setFontSize(KDText::FontSize::Small); + } +} + +const char * StorageValuesController::title() { + return I18n::translate(I18n::Message::ValuesTab); +} + +int StorageValuesController::numberOfColumns() { + if (m_numberOfColumnsNeedUpdate) { + updateNumberOfColumns(); + m_numberOfColumnsNeedUpdate = false; + } + return m_numberOfColumns; +} + +Interval * StorageValuesController::interval() { + return m_interval; +} + +bool StorageValuesController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Down) { + if (selectedRow() == -1) { + header()->setSelectedButton(-1); + selectableTableView()->selectCellAtLocation(0,0); + app()->setFirstResponder(selectableTableView()); + return true; + } + return false; + } + + if (event == Ion::Events::Up) { + if (selectedRow() == -1) { + header()->setSelectedButton(-1); + app()->setFirstResponder(tabController()); + return true; + } + selectableTableView()->deselectTable(); + header()->setSelectedButton(0); + return true; + } + if (event == Ion::Events::Backspace && selectedRow() > 0 && + (selectedRow() < numberOfRows()-1 || m_interval->numberOfElements() == Interval::k_maxNumberOfElements)) { + m_interval->deleteElementAtIndex(selectedRow()-1); + selectableTableView()->reloadData(); + return true; + } + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + if (selectedRow() == -1) { + return header()->handleEvent(event); + } + if (selectedRow() == 0) { + if (selectedColumn() == 0) { + configureAbscissa(); + return true; + } + configureFunction(); + return true; + } + return false; + } + if (selectedRow() == -1) { + return header()->handleEvent(event); + } + return false; +} + +void StorageValuesController::didBecomeFirstResponder() { + EditableCellTableViewController::didBecomeFirstResponder(); + if (selectedRow() == -1) { + selectableTableView()->deselectTable(); + header()->setSelectedButton(0); + } else { + header()->setSelectedButton(-1); + } +} + +void StorageValuesController::willExitResponderChain(Responder * nextFirstResponder) { + if (nextFirstResponder == tabController()) { + selectableTableView()->deselectTable(); + selectableTableView()->scrollToCell(0,0); + header()->setSelectedButton(-1); + } +} + +int StorageValuesController::numberOfButtons(ButtonRowController::Position) const { + if (isEmpty()) { + return 0; + } + return 1; +} + +Button * StorageValuesController::buttonAtIndex(int index, ButtonRowController::Position position) const { + return (Button *)&m_setIntervalButton; +} + +void StorageValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { + willDisplayCellAtLocationWithDisplayMode(cell, i, j, Preferences::sharedPreferences()->displayMode()); + if (cellAtLocationIsEditable(i, j)) { + return; + } + // The cell is not a title cell and not editable + if (j > 0 && i > 0) { + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + // Special case: last row + if (j == numberOfRows() - 1) { + int numberOfIntervalElements = m_interval->numberOfElements(); + if (numberOfIntervalElements < Interval::k_maxNumberOfElements) { + buffer[0] = 0; + EvenOddBufferTextCell * myValueCell = (EvenOddBufferTextCell *)cell; + myValueCell->setText(buffer); + return; + } + } + // The cell is a value cell + EvenOddBufferTextCell * myValueCell = (EvenOddBufferTextCell *)cell; + double x = m_interval->element(j-1); + PoincareHelpers::ConvertFloatToText(evaluationOfAbscissaAtColumn(x, i), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + myValueCell->setText(buffer); + } +} + +KDCoordinate StorageValuesController::columnWidth(int i) { + switch (i) { + case 0: + return k_abscissaCellWidth; + default: + return k_ordinateCellWidth; + } +} + +KDCoordinate StorageValuesController::cumulatedWidthFromIndex(int i) { + if (i == 0) { + return 0; + } else { + return k_abscissaCellWidth + (i-1)*k_ordinateCellWidth; + } +} + +int StorageValuesController::indexFromCumulatedWidth(KDCoordinate offsetX) { + if (offsetX <= k_abscissaCellWidth) { + return 0; + } + return (offsetX - k_abscissaCellWidth)/k_ordinateCellWidth+1; +} + +HighlightCell * StorageValuesController::reusableCell(int index, int type) { + assert(index >= 0); + switch (type) { + case 0: + assert(index == 0); + return &m_abscissaTitleCell; + case 1: + return functionTitleCells(index); + case 2: + assert(index < k_maxNumberOfAbscissaCells); + return &m_abscissaCells[index]; + case 3: + return floatCells(index); + default: + assert(false); + return nullptr; + } +} + +int StorageValuesController::reusableCellCount(int type) { + switch (type) { + case 0: + return 1; + case 1: + return maxNumberOfFunctions(); + case 2: + return k_maxNumberOfAbscissaCells; + case 3: + return maxNumberOfCells(); + default: + assert(false); + return 0; + } +} + +int StorageValuesController::typeAtLocation(int i, int j) { + if (j == 0) { + if (i == 0) { + return 0; + } + return 1; + } + if (i == 0) { + return 2; + } + return 3; +} + +bool StorageValuesController::isEmpty() const { + if (functionStore()->numberOfActiveFunctions() == 0) { + return true; + } + return false; +} + +Responder * StorageValuesController::defaultController() { + return tabController(); +} + +void StorageValuesController::viewWillAppear() { + EditableCellTableViewController::viewWillAppear(); + header()->setSelectedButton(-1); +} + +void StorageValuesController::viewDidDisappear() { + m_numberOfColumnsNeedUpdate = true; + EditableCellTableViewController::viewDidDisappear(); +} + +StorageFunction * StorageValuesController::functionAtColumn(int i) { + assert(i > 0); + return functionStore()->activeFunctionAtIndex(i-1); +} + +Responder * StorageValuesController::tabController() const { + return (parentResponder()->parentResponder()->parentResponder()->parentResponder()); +} + +StackViewController * StorageValuesController::stackController() const { + return (StackViewController *)(parentResponder()->parentResponder()->parentResponder()); +} + +void StorageValuesController::configureAbscissa() { + StackViewController * stack = stackController(); + stack->push(&m_abscissaParameterController); +} + +void StorageValuesController::configureFunction() { +#if COPY_COLUMN +#else + /* Temporary: the sequence value controller does not have a function parameter + * controller yet but it shoult come soon. */ + if (functionParameterController() == nullptr) { + return; + } +#endif + functionParameterController()->setFunction(functionAtColumn(selectedColumn())); + StackViewController * stack = stackController(); + stack->push(functionParameterController()); +} + +bool StorageValuesController::cellAtLocationIsEditable(int columnIndex, int rowIndex) { + if (rowIndex > 0 && columnIndex == 0) { + return true; + } + return false; +} + +bool StorageValuesController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) { + m_interval->setElement(rowIndex-1, floatBody); + return true; +} + +double StorageValuesController::dataAtLocation(int columnIndex, int rowIndex) { + return m_interval->element(rowIndex-1); +} + +int StorageValuesController::numberOfElements() { + return m_interval->numberOfElements(); +} + +int StorageValuesController::maxNumberOfElements() const { + return Interval::k_maxNumberOfElements; +} + +double StorageValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) { + StorageFunction * function = functionAtColumn(columnIndex); + TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); + return function->evaluateAtAbscissa(abscissa, myApp->localContext()); +} + +void StorageValuesController::updateNumberOfColumns() { + m_numberOfColumns = 1+functionStore()->numberOfActiveFunctions(); +} + +} + diff --git a/apps/shared/storage_values_controller.h b/apps/shared/storage_values_controller.h new file mode 100644 index 000000000..e2c17e8da --- /dev/null +++ b/apps/shared/storage_values_controller.h @@ -0,0 +1,81 @@ +#ifndef SHARED_STORAGE_VALUES_CONTROLLER_H +#define SHARED_STORAGE_VALUES_CONTROLLER_H + +#include +#include "storage_function_store.h" +#include "function_title_cell.h" +#include "editable_cell_table_view_controller.h" +#include "interval.h" +#include "values_parameter_controller.h" +#include "storage_values_function_parameter_controller.h" +#include "interval_parameter_controller.h" +#include "../i18n.h" + +namespace Shared { + +class StorageValuesController : public EditableCellTableViewController, public ButtonRowDelegate, public AlternateEmptyViewDefaultDelegate { +public: + StorageValuesController(Responder * parentResponder, ButtonRowController * header, I18n::Message parameterTitle, IntervalParameterController * intervalParameterController, Interval * interval); + const char * title() override; + Interval * interval(); + int numberOfColumns() override; + virtual bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; + void willExitResponderChain(Responder * nextFirstResponder) override; + virtual IntervalParameterController * intervalParameterController() = 0; + int numberOfButtons(ButtonRowController::Position) const override; + Button * buttonAtIndex(int index, ButtonRowController::Position position) const override; + virtual void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; + KDCoordinate columnWidth(int i) override; + KDCoordinate cumulatedWidthFromIndex(int i) override; + int indexFromCumulatedWidth(KDCoordinate offsetX) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; + bool isEmpty() const override; + Responder * defaultController() override; + void viewWillAppear() override; + void viewDidDisappear() override; + static constexpr KDCoordinate k_topMargin = 10; + static constexpr KDCoordinate k_bottomMargin = 15; + static constexpr KDCoordinate k_leftMargin = 1; + static constexpr KDCoordinate k_rightMargin = 15; + static constexpr KDCoordinate k_abscissaCellWidth = 100; + static constexpr KDCoordinate k_ordinateCellWidth = 100; +protected: + StackViewController * stackController() const; + bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override; + virtual void updateNumberOfColumns(); + Interval * m_interval; + int m_numberOfColumns; + bool m_numberOfColumnsNeedUpdate; +private: + virtual StorageFunction * functionAtColumn(int i); + Responder * tabController() const override; + SelectableTableView * selectableTableView() override { return &m_selectableTableView; } + void configureAbscissa(); + void configureFunction(); + bool cellAtLocationIsEditable(int columnIndex, int rowIndex) override; + double dataAtLocation(int columnIndex, int rowIndex) override; + int numberOfElements() override; + int maxNumberOfElements() const override; + virtual double evaluationOfAbscissaAtColumn(double abscissa, int columnIndex); + constexpr static int k_maxNumberOfAbscissaCells = 10; + virtual int maxNumberOfCells() = 0; + virtual int maxNumberOfFunctions() = 0; + SelectableTableView m_selectableTableView; + EvenOddMessageTextCell m_abscissaTitleCell; + virtual FunctionTitleCell * functionTitleCells(int j) = 0; + virtual EvenOddBufferTextCell * floatCells(int j) = 0; + char m_draftTextBuffer[TextField::maxBufferSize()]; + EvenOddEditableTextCell m_abscissaCells[k_maxNumberOfAbscissaCells]; + virtual StorageFunctionStore * functionStore() const = 0; + virtual StorageValuesFunctionParameterController * functionParameterController() = 0; + ValuesParameterController m_abscissaParameterController; + Button m_setIntervalButton; +}; + +} + +#endif + diff --git a/apps/shared/storage_values_function_parameter_controller.cpp b/apps/shared/storage_values_function_parameter_controller.cpp new file mode 100644 index 000000000..517467442 --- /dev/null +++ b/apps/shared/storage_values_function_parameter_controller.cpp @@ -0,0 +1,24 @@ +#include "storage_values_function_parameter_controller.h" +#include + +namespace Shared { + +const char * StorageValuesFunctionParameterController::title() { + strlcpy(m_pageTitle, I18n::translate(I18n::Message::FunctionColumn), k_maxNumberOfCharsInTitle); + for (int currentChar = 0; currentChar < k_maxNumberOfCharsInTitle-1; currentChar++) { + if (m_pageTitle[currentChar] == '(') { + m_pageTitle[currentChar-1] = *m_function->fullName(); + m_pageTitle[currentChar+1] = m_symbol; + break; + } + } + return m_pageTitle; +} + +void StorageValuesFunctionParameterController::didBecomeFirstResponder() { + m_selectableTableView.reloadData(); + selectCellAtLocation(0, 0); + app()->setFirstResponder(&m_selectableTableView); +} + +} diff --git a/apps/shared/storage_values_function_parameter_controller.h b/apps/shared/storage_values_function_parameter_controller.h new file mode 100644 index 000000000..d74cc9d81 --- /dev/null +++ b/apps/shared/storage_values_function_parameter_controller.h @@ -0,0 +1,44 @@ +#ifndef SHARED_STORAGE_VALUES_FUNCTION_PARAM_CONTROLLER_H +#define SHARED_STORAGE_VALUES_FUNCTION_PARAM_CONTROLLER_H + +#include +#include "storage_function.h" +#include "../i18n.h" + +namespace Shared { + +class StorageValuesFunctionParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource { +public: + StorageValuesFunctionParameterController(char symbol) : + ViewController(nullptr), + m_copyColumn(I18n::Message::CopyColumnInList), + m_selectableTableView(this, this, this), + m_function(nullptr), + m_symbol(symbol) + {} + + View * view() override { return &m_selectableTableView; } + const char * title() override; + void didBecomeFirstResponder() override; + virtual int numberOfRows() override { return 1; } + KDCoordinate cellHeight() override { return Metric::ParameterCellHeight; } + virtual HighlightCell * reusableCell(int index) override { + assert(index == 0); + return &m_copyColumn; + } + virtual int reusableCellCount() override { return 1; } + virtual void setFunction(StorageFunction * function) { m_function = function; } +protected: + MessageTableCellWithChevron m_copyColumn; + SelectableTableView m_selectableTableView; +private: + constexpr static int k_maxNumberOfCharsInTitle = 16; + char m_pageTitle[k_maxNumberOfCharsInTitle]; + StorageFunction * m_function; + char m_symbol; +}; + +} + +#endif +