diff --git a/apps/graph/Makefile b/apps/graph/Makefile index 1429ae558..8759bd5e8 100644 --- a/apps/graph/Makefile +++ b/apps/graph/Makefile @@ -7,6 +7,7 @@ app_objs += $(addprefix apps/graph/,\ cartesian_function_store.o\ function_title_cell.o\ graph/banner_view.o\ + graph/calculation_graph_controller.o\ graph/calculation_parameter_controller.o\ graph/curve_parameter_controller.o\ graph/extremum_graph_controller.o\ diff --git a/apps/graph/graph/calculation_graph_controller.cpp b/apps/graph/graph/calculation_graph_controller.cpp new file mode 100644 index 000000000..7c98b284d --- /dev/null +++ b/apps/graph/graph/calculation_graph_controller.cpp @@ -0,0 +1,87 @@ +#include "calculation_graph_controller.h" +#include "../app.h" + +using namespace Shared; +using namespace Poincare; + +namespace Graph { + +CalculationGraphController::CalculationGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, I18n::Message defaultMessage) : + ViewController(parentResponder), + m_graphView(graphView), + m_bannerView(bannerView), + m_graphRange(curveViewRange), + m_cursor(cursor), + m_function(nullptr), + m_defaultBannerView(KDText::FontSize::Small, defaultMessage, 0.5f, 0.5f, KDColorBlack, Palette::GreyMiddle), + m_isActive(false) +{ +} + +View * CalculationGraphController::view() { + return m_graphView; +} + +void CalculationGraphController::viewWillAppear() { + assert(m_function != nullptr); + CartesianFunction::Point pointOfInterest = computeNewPointOfInteresetFromAbscissa(m_graphRange->xMin(), 1); + if (std::isnan(pointOfInterest.abscissa)) { + m_isActive = false; + m_graphView->setCursorView(nullptr); + m_graphView->setBannerView(&m_defaultBannerView); + } else { + m_isActive = true; + m_cursor->moveTo(pointOfInterest.abscissa, pointOfInterest.value); + m_graphRange->panToMakePointVisible(m_cursor->x(), m_cursor->y(), k_cursorTopMarginRatio, SimpleInteractiveCurveViewController::k_cursorRightMarginRatio, k_cursorBottomMarginRatio, SimpleInteractiveCurveViewController::k_cursorLeftMarginRatio); + reloadBannerView(); + } + m_graphView->setOkView(nullptr); + m_graphView->reload(); +} + +bool CalculationGraphController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::EXE || event == Ion::Events::OK) { + StackViewController * stack = static_cast(parentResponder()); + stack->pop(); + return true; + } + if (m_isActive && (event == Ion::Events::Right || event == Ion::Events::Left)) { + int direction = event == Ion::Events::Right ? 1 : -1; + if (moveCursor(direction)) { + reloadBannerView(); + m_graphView->reload(); + return true; + } + } + return false; +} + +void CalculationGraphController::setFunction(CartesianFunction * function) { + m_graphView->selectFunction(function); + m_function = function; +} + +void CalculationGraphController::reloadBannerView() { + m_bannerView->setNumberOfSubviews(2); + reloadBannerViewForCursorOnFunction(m_cursor, m_function, 'x'); +} + +bool CalculationGraphController::moveCursor(int direction) { + CartesianFunction::Point newPointOfInterest = computeNewPointOfInteresetFromAbscissa(m_cursor->x(), direction); + if (std::isnan(newPointOfInterest.abscissa)) { + return false; + } + m_cursor->moveTo(newPointOfInterest.abscissa, newPointOfInterest.value); + m_graphRange->panToMakePointVisible(m_cursor->x(), m_cursor->y(), k_cursorTopMarginRatio, SimpleInteractiveCurveViewController::k_cursorRightMarginRatio, k_cursorBottomMarginRatio, SimpleInteractiveCurveViewController::k_cursorLeftMarginRatio); + return true; +} + +CartesianFunction::Point CalculationGraphController::computeNewPointOfInteresetFromAbscissa(double start, int direction) { + TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); + double step = m_graphRange->xGridUnit()/10.0; + step = direction < 0 ? -step : step; + double max = direction > 0 ? m_graphRange->xMax() : m_graphRange->xMin(); + return computeNewPointOfInterest(start, step, max, myApp->localContext()); +} + +} diff --git a/apps/graph/graph/calculation_graph_controller.h b/apps/graph/graph/calculation_graph_controller.h new file mode 100644 index 000000000..45338cb62 --- /dev/null +++ b/apps/graph/graph/calculation_graph_controller.h @@ -0,0 +1,39 @@ +#ifndef GRAPH_CALCULATION_GRAPH_CONTROLLER_H +#define GRAPH_CALCULATION_GRAPH_CONTROLLER_H + +#include "graph_view.h" +#include "banner_view.h" +#include "../../shared/curve_view_cursor.h" +#include "../../shared/interactive_curve_view_range.h" +#include "../../shared/function_banner_delegate.h" +#include "../cartesian_function.h" + +namespace Graph { + +class CalculationGraphController : public ViewController, public Shared::FunctionBannerDelegate { +public: + CalculationGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor, I18n::Message defaultMessage); + View * view() override; + void viewWillAppear() override; + bool handleEvent(Ion::Events::Event event) override; + void setFunction(CartesianFunction * function); +protected: + constexpr static float k_cursorTopMarginRatio = 0.07f; // (cursorHeight/2)/graphViewHeight + constexpr static float k_cursorBottomMarginRatio = 0.15f; // (cursorHeight/2+bannerHeigh)/graphViewHeight + BannerView * bannerView() override { return m_bannerView; } + void reloadBannerView(); + bool moveCursor(int direction); + CartesianFunction::Point computeNewPointOfInteresetFromAbscissa(double start, int direction); + virtual CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) = 0; + GraphView * m_graphView; + BannerView * m_bannerView; + Shared::InteractiveCurveViewRange * m_graphRange; + Shared::CurveViewCursor * m_cursor; + CartesianFunction * m_function; + MessageTextView m_defaultBannerView; + bool m_isActive; +}; + +} + +#endif diff --git a/apps/graph/graph/extremum_graph_controller.cpp b/apps/graph/graph/extremum_graph_controller.cpp index 254945669..1273fa756 100644 --- a/apps/graph/graph/extremum_graph_controller.cpp +++ b/apps/graph/graph/extremum_graph_controller.cpp @@ -6,86 +6,8 @@ using namespace Poincare; namespace Graph { -ExtremumGraphController::ExtremumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, I18n::Message defaultMessage) : - ViewController(parentResponder), - m_graphView(graphView), - m_bannerView(bannerView), - m_graphRange(curveViewRange), - m_cursor(cursor), - m_function(nullptr), - m_defaultBannerView(KDText::FontSize::Small, defaultMessage, 0.5f, 0.5f, KDColorBlack, Palette::GreyMiddle), - m_isActive(false) -{ -} - -View * ExtremumGraphController::view() { - return m_graphView; -} - -void ExtremumGraphController::viewWillAppear() { - assert(m_function != nullptr); - CartesianFunction::Point extremum = computeExtremumFromAbscissa(m_graphRange->xMin(), 1); - if (std::isnan(extremum.abscissa)) { - m_isActive = false; - m_graphView->setCursorView(nullptr); - m_graphView->setBannerView(&m_defaultBannerView); - } else { - m_isActive = true; - m_cursor->moveTo(extremum.abscissa, extremum.value); - m_graphRange->panToMakePointVisible(m_cursor->x(), m_cursor->y(), k_cursorTopMarginRatio, SimpleInteractiveCurveViewController::k_cursorRightMarginRatio, k_cursorBottomMarginRatio, SimpleInteractiveCurveViewController::k_cursorLeftMarginRatio); - reloadBannerView(); - } - m_graphView->setOkView(nullptr); - m_graphView->reload(); -} - -bool ExtremumGraphController::handleEvent(Ion::Events::Event event) { - if (event == Ion::Events::EXE || event == Ion::Events::OK) { - StackViewController * stack = static_cast(parentResponder()); - stack->pop(); - return true; - } - if (m_isActive && (event == Ion::Events::Right || event == Ion::Events::Left)) { - int direction = event == Ion::Events::Right ? 1 : -1; - if (moveCursor(direction)) { - reloadBannerView(); - m_graphView->reload(); - return true; - } - } - return false; -} - -void ExtremumGraphController::setFunction(CartesianFunction * function) { - m_graphView->selectFunction(function); - m_function = function; -} - -void ExtremumGraphController::reloadBannerView() { - m_bannerView->setNumberOfSubviews(2); - reloadBannerViewForCursorOnFunction(m_cursor, m_function, 'x'); -} - -bool ExtremumGraphController::moveCursor(int direction) { - CartesianFunction::Point newExtremum = computeExtremumFromAbscissa(m_cursor->x(), direction); - if (std::isnan(newExtremum.abscissa)) { - return false; - } - m_cursor->moveTo(newExtremum.abscissa, newExtremum.value); - m_graphRange->panToMakePointVisible(m_cursor->x(), m_cursor->y(), k_cursorTopMarginRatio, SimpleInteractiveCurveViewController::k_cursorRightMarginRatio, k_cursorBottomMarginRatio, SimpleInteractiveCurveViewController::k_cursorLeftMarginRatio); - return true; -} - -CartesianFunction::Point ExtremumGraphController::computeExtremumFromAbscissa(double start, int direction) { - TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); - double step = m_graphRange->xGridUnit()/100.0; - step = direction < 0 ? -step : step; - double max = direction > 0 ? m_graphRange->xMax() : m_graphRange->xMin(); - return computeExtremum(start, step, max, myApp->localContext()); -} - MinimumGraphController::MinimumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor) : - ExtremumGraphController(parentResponder, graphView, bannerView, curveViewRange, cursor, I18n::Message::NoMinimumFound) + CalculationGraphController(parentResponder, graphView, bannerView, curveViewRange, cursor, I18n::Message::NoMinimumFound) { } @@ -93,12 +15,12 @@ const char * MinimumGraphController::title() { return I18n::translate(I18n::Message::Minimum); } -CartesianFunction::Point MinimumGraphController::computeExtremum(double start, double step, double max, Context * context) { +CartesianFunction::Point MinimumGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { return m_function->nextMinimumFrom(start, step, max, context); } MaximumGraphController::MaximumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor) : - ExtremumGraphController(parentResponder, graphView, bannerView, curveViewRange, cursor, I18n::Message::NoMaximumFound) + CalculationGraphController(parentResponder, graphView, bannerView, curveViewRange, cursor, I18n::Message::NoMaximumFound) { } @@ -106,7 +28,7 @@ const char * MaximumGraphController::title() { return I18n::translate(I18n::Message::Maximum); } -CartesianFunction::Point MaximumGraphController::computeExtremum(double start, double step, double max, Context * context) { +CartesianFunction::Point MaximumGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) { return m_function->nextMaximumFrom(start, step, max, context); } diff --git a/apps/graph/graph/extremum_graph_controller.h b/apps/graph/graph/extremum_graph_controller.h index 69f9ed1b6..dc1f5bc30 100644 --- a/apps/graph/graph/extremum_graph_controller.h +++ b/apps/graph/graph/extremum_graph_controller.h @@ -1,53 +1,24 @@ #ifndef GRAPH_EXTREMUM_GRAPH_CONTROLLER_H #define GRAPH_EXTREMUM_GRAPH_CONTROLLER_H -#include "graph_view.h" -#include "banner_view.h" -#include "../../shared/curve_view_cursor.h" -#include "../../shared/interactive_curve_view_range.h" -#include "../../shared/function_banner_delegate.h" -#include "../cartesian_function.h" +#include "calculation_graph_controller.h" namespace Graph { -class ExtremumGraphController : public ViewController, public Shared::FunctionBannerDelegate { -public: - ExtremumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor, I18n::Message defaultMessage); - View * view() override; - void viewWillAppear() override; - bool handleEvent(Ion::Events::Event event) override; - void setFunction(CartesianFunction * function); -protected: - constexpr static float k_cursorTopMarginRatio = 0.07f; // (cursorHeight/2)/graphViewHeight - constexpr static float k_cursorBottomMarginRatio = 0.15f; // (cursorHeight/2+bannerHeigh)/graphViewHeight - BannerView * bannerView() override { return m_bannerView; } - void reloadBannerView(); - bool moveCursor(int direction); - CartesianFunction::Point computeExtremumFromAbscissa(double start, int direction); - virtual CartesianFunction::Point computeExtremum(double start, double step, double max, Poincare::Context * context) = 0; - GraphView * m_graphView; - BannerView * m_bannerView; - Shared::InteractiveCurveViewRange * m_graphRange; - Shared::CurveViewCursor * m_cursor; - CartesianFunction * m_function; - MessageTextView m_defaultBannerView; - bool m_isActive; -}; - -class MinimumGraphController : public ExtremumGraphController { +class MinimumGraphController : public CalculationGraphController { public: MinimumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor); const char * title() override; private: - CartesianFunction::Point computeExtremum(double start, double step, double max, Poincare::Context * context) override; + CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; }; -class MaximumGraphController : public ExtremumGraphController { +class MaximumGraphController : public CalculationGraphController { public: MaximumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor); const char * title() override; private: - CartesianFunction::Point computeExtremum(double start, double step, double max, Poincare::Context * context) override; + CartesianFunction::Point computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override; }; }