diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 9423684e46e..995065b5abc 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -2,6 +2,7 @@ #include "apps_container_storage.h" #include "global_preferences.h" #include "exam_mode_configuration.h" +#include "shared/function_active_function_toggle.h" #include #include #include @@ -37,7 +38,8 @@ AppsContainer::AppsContainer() : m_homeSnapshot(), m_onBoardingSnapshot(), m_hardwareTestSnapshot(), - m_usbConnectedSnapshot() + m_usbConnectedSnapshot(), + m_activeFunctionTooggle(nullptr) { m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), false); // #if __EMSCRIPTEN__ @@ -459,3 +461,7 @@ void AppsContainer::resetShiftAlphaStatus() { Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); updateAlphaLock(); } + +FunctionActiveFunctionToggle *AppsContainer::getActiveFunctionToggle() { + return &m_activeFunctionTooggle; +} diff --git a/apps/apps_container.h b/apps/apps_container.h index f52d50b6c50..35122ff5005 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -18,6 +18,7 @@ #include "shared/global_context.h" #include "clock_timer.h" #include "on_boarding/prompt_controller.h" +#include "shared/function_active_function_toggle.h" #include @@ -55,6 +56,7 @@ class AppsContainer : public Container, ExamPopUpControllerDelegate, Ion::Storag // Ion::StorageDelegate void storageDidChangeForRecord(const Ion::Storage::Record record) override; void storageIsFull() override; + Shared::FunctionActiveFunctionToggle * getActiveFunctionToggle(); protected: Home::App::Snapshot * homeAppSnapshot() { return &m_homeSnapshot; } private: @@ -84,6 +86,10 @@ class AppsContainer : public Container, ExamPopUpControllerDelegate, Ion::Storag OnBoarding::App::Snapshot m_onBoardingSnapshot; HardwareTest::App::Snapshot m_hardwareTestSnapshot; USB::App::Snapshot m_usbConnectedSnapshot; + + // Shared Class that need to be initialized at the beginning + + Shared::FunctionActiveFunctionToggle m_activeFunctionTooggle; }; #endif diff --git a/apps/graph/graph/calculation_parameter_controller.cpp b/apps/graph/graph/calculation_parameter_controller.cpp index 93f98086fda..e093dcbecac 100644 --- a/apps/graph/graph/calculation_parameter_controller.cpp +++ b/apps/graph/graph/calculation_parameter_controller.cpp @@ -12,10 +12,9 @@ CalculationParameterController::CalculationParameterController(Responder * paren ViewController(parentResponder), m_preimageCell(I18n::Message::Preimage), m_selectableTableView(this), - m_record(), + m_recordDelegate(nullptr), m_preimageParameterController(nullptr, inputEventHandlerDelegate, range, cursor, &m_preimageGraphController), m_preimageGraphController(nullptr, graphView, bannerView, range, cursor), - m_tangentGraphController(nullptr, graphView, bannerView, range, cursor), m_integralGraphController(nullptr, inputEventHandlerDelegate, graphView, range, cursor), m_minimumGraphController(nullptr, graphView, bannerView, range, cursor), m_maximumGraphController(nullptr, graphView, bannerView, range, cursor), @@ -45,18 +44,16 @@ void CalculationParameterController::didBecomeFirstResponder() { bool CalculationParameterController::handleEvent(Ion::Events::Event event) { int row = selectedRow(); if (event == Ion::Events::OK || event == Ion::Events::EXE || (event == Ion::Events::Right && row == 0)) { - static ViewController * controllers[] = {&m_preimageParameterController, &m_intersectionGraphController, &m_maximumGraphController, &m_minimumGraphController, &m_rootGraphController, &m_tangentGraphController, &m_integralGraphController}; + static ViewController * controllers[] = {&m_preimageParameterController, &m_intersectionGraphController, &m_maximumGraphController, &m_minimumGraphController, &m_rootGraphController, &m_integralGraphController}; int displayIntersection = shouldDisplayIntersection(); int indexController = row == 0 ? 0 : row + !displayIntersection; ViewController * controller = controllers[indexController]; if (row == 0) { - m_preimageParameterController.setRecord(m_record); + m_preimageParameterController.setRecord(m_recordDelegate->getRecord()); } else if (row == 4 + displayIntersection) { - m_tangentGraphController.setRecord(m_record); - } else if (row == 5 + displayIntersection) { - m_integralGraphController.setRecord(m_record); + m_integralGraphController.setRecord(m_recordDelegate->getRecord()); } else { - static_cast(controller)->setRecord(m_record); + static_cast(controller)->setRecord(m_recordDelegate->getRecord()); } StackViewController * stack = static_cast(parentResponder()); if (row > 0) { @@ -108,13 +105,13 @@ int CalculationParameterController::typeAtLocation(int i, int j) { void CalculationParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { assert(index >= 0 && index <= numberOfRows()); if (cell != &m_preimageCell) { - I18n::Message titles[] = {I18n::Message::Intersection, I18n::Message::Maximum, I18n::Message::Minimum, I18n::Message::Zeros, I18n::Message::Tangent, I18n::Message::Integral}; + I18n::Message titles[] = {I18n::Message::Intersection, I18n::Message::Maximum, I18n::Message::Minimum, I18n::Message::Zeros, I18n::Message::Integral}; static_cast(cell)->setMessage(titles[index - 1 + !shouldDisplayIntersection()]); } } -void CalculationParameterController::setRecord(Ion::Storage::Record record) { - m_record = record; +void CalculationParameterController::setRecordDelegate(Shared::FunctionActiveFunctionToggle * record) { + m_recordDelegate = record; } bool CalculationParameterController::shouldDisplayIntersection() const { diff --git a/apps/graph/graph/calculation_parameter_controller.h b/apps/graph/graph/calculation_parameter_controller.h index ffb38e6919a..b108f59be5e 100644 --- a/apps/graph/graph/calculation_parameter_controller.h +++ b/apps/graph/graph/calculation_parameter_controller.h @@ -10,6 +10,7 @@ #include "root_graph_controller.h" #include "graph_view.h" #include "banner_view.h" +#include "apps/shared/function_active_function_toggle.h" #include namespace Graph { @@ -29,17 +30,16 @@ class CalculationParameterController : public ViewController, public ListViewDat int reusableCellCount(int type) override; int typeAtLocation(int i, int j) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; - void setRecord(Ion::Storage::Record record); + void setRecordDelegate(Shared::FunctionActiveFunctionToggle * record); private: bool shouldDisplayIntersection() const; MessageTableCellWithChevron m_preimageCell; - constexpr static int k_totalNumberOfReusableCells = 6; + constexpr static int k_totalNumberOfReusableCells = 5; MessageTableCell m_cells[k_totalNumberOfReusableCells]; SelectableTableView m_selectableTableView; - Ion::Storage::Record m_record; + Shared::FunctionActiveFunctionToggle * m_recordDelegate; PreimageParameterController m_preimageParameterController; PreimageGraphController m_preimageGraphController; - TangentGraphController m_tangentGraphController; IntegralGraphController m_integralGraphController; MinimumGraphController m_minimumGraphController; MaximumGraphController m_maximumGraphController; diff --git a/apps/graph/graph/curve_parameter_controller.cpp b/apps/graph/graph/curve_parameter_controller.cpp index f8fc1862b45..e4bcb9e26f8 100644 --- a/apps/graph/graph/curve_parameter_controller.cpp +++ b/apps/graph/graph/curve_parameter_controller.cpp @@ -14,7 +14,9 @@ CurveParameterController::CurveParameterController(InputEventHandlerDelegate * i m_graphController(graphController), m_calculationCell(I18n::Message::Compute), m_derivativeCell(I18n::Message::DerivateNumber), - m_calculationParameterController(this, inputEventHandlerDelegate, graphView, bannerView, graphRange, cursor) + m_calculationParameterController(this, inputEventHandlerDelegate, graphView, bannerView, graphRange, cursor), + m_tangenteCell(I18n::Message::Tangent), + m_tangentGraphController(nullptr, graphView, bannerView, graphRange, cursor) { } @@ -41,7 +43,7 @@ bool CurveParameterController::handleEvent(Ion::Events::Event event) { switch (index) { case 0: { - m_calculationParameterController.setRecord(m_record); + m_calculationParameterController.setRecordDelegate(m_recordDelegate); StackViewController * stack = (StackViewController *)parentResponder(); stack->push(&m_calculationParameterController); return true; @@ -54,6 +56,13 @@ bool CurveParameterController::handleEvent(Ion::Events::Event event) { m_selectableTableView.reloadData(); return true; } + case 3: + { + m_tangentGraphController.setRecordDelegate(m_recordDelegate); + StackViewController * stack = (StackViewController *)parentResponder(); + stack->push(&m_tangentGraphController); + return true; + } default: assert(false); return false; @@ -68,12 +77,12 @@ int CurveParameterController::numberOfRows() const { HighlightCell * CurveParameterController::reusableCell(int index) { assert(0 <= index && index < reusableCellCount()); - HighlightCell * cells[] = {&m_calculationCell, &m_goToCell, &m_derivativeCell}; + HighlightCell * cells[] = {&m_calculationCell, &m_goToCell, &m_derivativeCell, &m_tangenteCell}; return cells[cellIndex(index)]; } int CurveParameterController::reusableCellCount() const { - return 1 + (shouldDisplayCalculationAndDerivative() ? 2 : 0); + return 1 + (shouldDisplayCalculationAndDerivative() ? 3 : 0); } void CurveParameterController::viewWillAppear() { @@ -82,7 +91,7 @@ void CurveParameterController::viewWillAppear() { } bool CurveParameterController::shouldDisplayCalculationAndDerivative() const { - Shared::ExpiringPointer f = App::app()->functionStore()->modelForRecord(m_record); + Shared::ExpiringPointer f = App::app()->functionStore()->modelForRecord(m_recordDelegate->getRecord()); return f->plotType() == ContinuousFunction::PlotType::Cartesian; } diff --git a/apps/graph/graph/curve_parameter_controller.h b/apps/graph/graph/curve_parameter_controller.h index d5a587af16d..1172408bd01 100644 --- a/apps/graph/graph/curve_parameter_controller.h +++ b/apps/graph/graph/curve_parameter_controller.h @@ -28,6 +28,8 @@ class CurveParameterController : public Shared::FunctionCurveParameterController MessageTableCellWithChevron m_calculationCell; MessageTableCellWithSwitch m_derivativeCell; CalculationParameterController m_calculationParameterController; + MessageTableCell m_tangenteCell; + TangentGraphController m_tangentGraphController; }; } diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index 9d34bbf4d50..7f0c44539d9 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -15,10 +15,7 @@ GraphView::GraphView(InteractiveCurveViewRange * graphRange, } void GraphView::reload() { - if (m_tangent) { - KDRect dirtyZone(KDRect(0, 0, bounds().width(), bounds().height()-m_bannerView->bounds().height())); - markRectAsDirty(dirtyZone); - } + markRectAsDirty(bounds()); return FunctionGraphView::reload(); } diff --git a/apps/graph/graph/tangent_graph_controller.cpp b/apps/graph/graph/tangent_graph_controller.cpp index af70b1b4224..f96e7ed2c7e 100644 --- a/apps/graph/graph/tangent_graph_controller.cpp +++ b/apps/graph/graph/tangent_graph_controller.cpp @@ -14,7 +14,7 @@ TangentGraphController::TangentGraphController(Responder * parentResponder, Grap m_graphView(graphView), m_bannerView(bannerView), m_graphRange(curveViewRange), - m_record() + m_recordDelegate(nullptr) { } @@ -47,7 +47,7 @@ bool TangentGraphController::textFieldDidFinishEditing(TextField * textField, co if (myApp->hasUndefinedValue(text, floatBody)) { return false; } - ExpiringPointer function = App::app()->functionStore()->modelForRecord(m_record); + ExpiringPointer function = App::app()->functionStore()->modelForRecord(m_recordDelegate->getRecord()); assert(function->plotType() == Shared::ContinuousFunction::PlotType::Cartesian); double y = function->evaluate2DAtParameter(floatBody, myApp->localContext()).x2(); m_cursor->moveTo(floatBody, floatBody, y); @@ -57,17 +57,17 @@ bool TangentGraphController::textFieldDidFinishEditing(TextField * textField, co return true; } -void TangentGraphController::setRecord(Ion::Storage::Record record) { - m_graphView->selectRecord(record); - m_record = record; +void TangentGraphController::setRecordDelegate(Shared::FunctionActiveFunctionToggle * record) { + m_graphView->selectRecord(record->getRecord()); + m_recordDelegate = record; } void TangentGraphController::reloadBannerView() { - if (m_record.isNull()) { + if (m_recordDelegate->getRecord().isNull()) { return; } - FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(m_cursor, m_record, Shared::FunctionApp::app()->functionStore(), AppsContainer::sharedAppsContainer()->globalContext()); - GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, m_record); + FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(m_cursor, m_recordDelegate->getRecord(), Shared::FunctionApp::app()->functionStore(), AppsContainer::sharedAppsContainer()->globalContext()); + GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, m_recordDelegate->getRecord()); constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters + PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits); char buffer[bufferSize]; Poincare::Context * context = textFieldDelegateApp()->localContext(); @@ -75,7 +75,7 @@ void TangentGraphController::reloadBannerView() { constexpr int precision = Preferences::MediumNumberOfSignificantDigits; const char * legend = "a="; int legendLength = strlcpy(buffer, legend, bufferSize); - ExpiringPointer function = App::app()->functionStore()->modelForRecord(m_record); + ExpiringPointer function = App::app()->functionStore()->modelForRecord(m_recordDelegate->getRecord()); double y = function->approximateDerivative(m_cursor->x(), context); PoincareHelpers::ConvertFloatToText(y, buffer + legendLength, bufferSize - legendLength, precision); m_bannerView->aView()->setText(buffer); @@ -91,7 +91,7 @@ void TangentGraphController::reloadBannerView() { } bool TangentGraphController::moveCursorHorizontally(int direction, int scrollSpeed) { - return privateMoveCursorHorizontally(m_cursor, direction, m_graphRange, k_numberOfCursorStepsInGradUnit, m_record); + return privateMoveCursorHorizontally(m_cursor, direction, m_graphRange, k_numberOfCursorStepsInGradUnit, m_recordDelegate->getRecord()); } bool TangentGraphController::handleEnter() { @@ -100,4 +100,31 @@ bool TangentGraphController::handleEnter() { return true; } +bool TangentGraphController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Up) { + m_recordDelegate->moveUp(); + m_graphView->selectRecord(m_recordDelegate->getRecord()); + // TODO maybe do: Very ugly workaround... Needs something better to reload the data banner + moveCursorHorizontally(1); + moveCursorHorizontally(-1); + + m_graphView->reload(); + reloadBannerView(); + viewWillAppear(); + return true; + } else if (event == Ion::Events::Down) { + m_recordDelegate->moveDown(); + m_graphView->selectRecord(m_recordDelegate->getRecord()); + + moveCursorHorizontally(1); + moveCursorHorizontally(-1); + + m_graphView->reload(); + reloadBannerView(); + viewWillAppear(); + return true; + } + return SimpleInteractiveCurveViewController::handleEvent(event); +} + } diff --git a/apps/graph/graph/tangent_graph_controller.h b/apps/graph/graph/tangent_graph_controller.h index eed6d637929..4db9b520be7 100644 --- a/apps/graph/graph/tangent_graph_controller.h +++ b/apps/graph/graph/tangent_graph_controller.h @@ -6,6 +6,7 @@ #include "graph_controller_helper.h" #include "../../shared/simple_interactive_curve_view_controller.h" #include "../../shared/function_banner_delegate.h" +#include "apps/shared/function_active_function_toggle.h" namespace Graph { @@ -17,7 +18,7 @@ class TangentGraphController : public Shared::SimpleInteractiveCurveViewControll void didBecomeFirstResponder() override; TELEMETRY_ID("Tangent"); bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - void setRecord(Ion::Storage::Record record); + void setRecordDelegate(Shared::FunctionActiveFunctionToggle * record); private: float cursorBottomMarginRatio() override { return 0.22f; } Shared::InteractiveCurveViewRange * interactiveCurveViewRange() override { return m_graphRange; } @@ -25,11 +26,16 @@ class TangentGraphController : public Shared::SimpleInteractiveCurveViewControll BannerView * bannerView() override { return m_bannerView; }; void reloadBannerView() override; bool moveCursorHorizontally(int direction, int scrollSpeed = 1) override; + +public: + bool handleEvent(Ion::Events::Event event) override; + +private: bool handleEnter() override; GraphView * m_graphView; BannerView * m_bannerView; Shared::InteractiveCurveViewRange * m_graphRange; - Ion::Storage::Record m_record; + Shared::FunctionActiveFunctionToggle * m_recordDelegate; }; } diff --git a/apps/shared/Makefile b/apps/shared/Makefile index bd421f508a6..18edd44fa9a 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -45,6 +45,7 @@ app_shared_src = $(addprefix apps/shared/,\ function_store.cpp \ function_title_cell.cpp \ function_zoom_and_pan_curve_view_controller.cpp \ + function_active_function_toggle.cpp \ go_to_parameter_controller.cpp \ hideable_even_odd_buffer_text_cell.cpp \ hideable_even_odd_cell.cpp \ diff --git a/apps/shared/function_active_function_toggle.cpp b/apps/shared/function_active_function_toggle.cpp new file mode 100644 index 00000000000..779abb94b16 --- /dev/null +++ b/apps/shared/function_active_function_toggle.cpp @@ -0,0 +1,22 @@ +#include "function_active_function_toggle.h" + +Ion::Storage::Record Shared::FunctionActiveFunctionToggle::getRecord() { + if (m_functionStore == nullptr || m_functionStore->numberOfActiveFunctions() <= 0) { + return Ion::Storage::Record(); + } + return m_functionStore->activeRecordAtIndex(m_index); +} + +void Shared::FunctionActiveFunctionToggle::moveUp() { + if (m_functionStore == nullptr) { + return; + } + m_index = m_functionStore->numberOfActiveFunctions() <= m_index + 1 ? 0 : m_index + 1; +} + +void Shared::FunctionActiveFunctionToggle::moveDown() { + if (m_functionStore == nullptr) { + return; + } + m_index = 0 > m_index - 1 ? m_functionStore->numberOfActiveFunctions() - 1 : m_index - 1; +} diff --git a/apps/shared/function_active_function_toggle.h b/apps/shared/function_active_function_toggle.h new file mode 100644 index 00000000000..f66e43891b5 --- /dev/null +++ b/apps/shared/function_active_function_toggle.h @@ -0,0 +1,27 @@ +#ifndef FUNCTION_ACTIVE_FUNCTION_TOGGLE_H +#define FUNCTION_ACTIVE_FUNCTION_TOGGLE_H + + +#include "../../ion/include/ion/storage.h" +#include "function_store.h" + +namespace Shared { + +class FunctionActiveFunctionToggle { +public: + explicit FunctionActiveFunctionToggle(FunctionStore * store) : m_functionStore(store), m_index(0) {} + + Ion::Storage::Record getRecord(); + void setCurrentIndex(int ni) { m_index = ni; } + void setFunctionStorePtr(FunctionStore * store) { m_functionStore = store; } + void moveUp(); + void moveDown(); + +private: + FunctionStore * m_functionStore; + int m_index; + +}; +} + +#endif //FUNCTION_ACTIVE_FUNCTION_TOGGLE_H diff --git a/apps/shared/function_curve_parameter_controller.cpp b/apps/shared/function_curve_parameter_controller.cpp index e93e240e6ee..0e01cfaac04 100644 --- a/apps/shared/function_curve_parameter_controller.cpp +++ b/apps/shared/function_curve_parameter_controller.cpp @@ -7,7 +7,7 @@ FunctionCurveParameterController::FunctionCurveParameterController() : ViewController(nullptr), m_goToCell(I18n::Message::Goto), m_selectableTableView(this, this, this), - m_record() + m_recordDelegate(nullptr) { } @@ -19,10 +19,13 @@ void FunctionCurveParameterController::didBecomeFirstResponder() { } bool FunctionCurveParameterController::handleGotoSelection() { - if (m_record.isNull()) { + if (m_recordDelegate == nullptr) { return false; } - goToParameterController()->setRecord(m_record); + if (m_recordDelegate->getRecord().isNull()) { + return false; + } + goToParameterController()->setRecord(m_recordDelegate->getRecord()); StackViewController * stack = (StackViewController *)parentResponder(); stack->push(goToParameterController()); return true; diff --git a/apps/shared/function_curve_parameter_controller.h b/apps/shared/function_curve_parameter_controller.h index 96e8668445f..a28b89239eb 100644 --- a/apps/shared/function_curve_parameter_controller.h +++ b/apps/shared/function_curve_parameter_controller.h @@ -3,6 +3,7 @@ #include #include "function_go_to_parameter_controller.h" +#include "function_active_function_toggle.h" namespace Shared { @@ -13,12 +14,12 @@ class FunctionCurveParameterController : public ViewController, public SimpleLis TELEMETRY_ID("CurveParameter"); void didBecomeFirstResponder() override; KDCoordinate cellHeight() override; - void setRecord(Ion::Storage::Record record) { m_record = record; } + void setRecordDelegate(FunctionActiveFunctionToggle * toggle) { m_recordDelegate = toggle; } protected: bool handleGotoSelection(); MessageTableCellWithChevron m_goToCell; SelectableTableView m_selectableTableView; - Ion::Storage::Record m_record; + FunctionActiveFunctionToggle * m_recordDelegate; private: virtual FunctionGoToParameterController * goToParameterController() = 0; }; diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index f43985e9fb8..2abd9a69656 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -47,8 +47,9 @@ void FunctionGraphController::viewWillAppear() { } bool FunctionGraphController::handleEnter() { - Ion::Storage::Record record = functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor()); - curveParameterController()->setRecord(record); + AppsContainer::sharedAppsContainer()->getActiveFunctionToggle()->setFunctionStorePtr(functionStore()); + AppsContainer::sharedAppsContainer()->getActiveFunctionToggle()->setCurrentIndex(indexFunctionSelectedByCursor()); + curveParameterController()->setRecordDelegate(AppsContainer::sharedAppsContainer()->getActiveFunctionToggle()); StackViewController * stack = stackController(); stack->push(curveParameterController()); return true; diff --git a/apps/shared/function_graph_controller.h b/apps/shared/function_graph_controller.h index cac996fe815..fd41309cfe9 100644 --- a/apps/shared/function_graph_controller.h +++ b/apps/shared/function_graph_controller.h @@ -7,6 +7,7 @@ #include "function_store.h" #include "function_graph_view.h" #include "function_curve_parameter_controller.h" +#include "function_active_function_toggle.h" namespace Shared {