From 6de497c2ed7834bcb645b68da9ffab4ebde92c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Sep 2019 11:48:43 +0200 Subject: [PATCH] [apps/shared] Templatize FloatParameterController to handle float/double parameters. Fix bug: when entering "e^234" as a parameter of a model keeping floats, the FloatParameterController would accept the number (because e^234 is defined in double) and store an undefined value in the model (because e^234 is undefined in float). --- .../list/domain_parameter_controller.cpp | 2 +- apps/graph/list/domain_parameter_controller.h | 2 +- apps/probability/parameters_controller.cpp | 4 +- apps/probability/parameters_controller.h | 6 +- apps/shared/float_parameter_controller.cpp | 58 +++++++++++++------ apps/shared/float_parameter_controller.h | 5 +- apps/shared/go_to_parameter_controller.cpp | 2 +- apps/shared/go_to_parameter_controller.h | 2 +- apps/shared/interval_parameter_controller.cpp | 2 +- apps/shared/interval_parameter_controller.h | 2 +- apps/shared/range_parameter_controller.cpp | 6 +- apps/shared/range_parameter_controller.h | 6 +- apps/shared/text_field_delegate_app.cpp | 8 ++- apps/shared/text_field_delegate_app.h | 3 +- apps/solver/interval_controller.cpp | 2 +- apps/solver/interval_controller.h | 2 +- .../histogram_parameter_controller.cpp | 2 +- .../histogram_parameter_controller.h | 2 +- 18 files changed, 71 insertions(+), 45 deletions(-) diff --git a/apps/graph/list/domain_parameter_controller.cpp b/apps/graph/list/domain_parameter_controller.cpp index 7de22e658..60113e21b 100644 --- a/apps/graph/list/domain_parameter_controller.cpp +++ b/apps/graph/list/domain_parameter_controller.cpp @@ -8,7 +8,7 @@ using namespace Shared; namespace Graph { DomainParameterController::DomainParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) : - FloatParameterController(parentResponder), + FloatParameterController(parentResponder), m_domainCells{}, m_record() { diff --git a/apps/graph/list/domain_parameter_controller.h b/apps/graph/list/domain_parameter_controller.h index d64ce5770..1be8d8b5c 100644 --- a/apps/graph/list/domain_parameter_controller.h +++ b/apps/graph/list/domain_parameter_controller.h @@ -9,7 +9,7 @@ namespace Graph { -class DomainParameterController : public Shared::FloatParameterController { +class DomainParameterController : public Shared::FloatParameterController { public: DomainParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate); diff --git a/apps/probability/parameters_controller.cpp b/apps/probability/parameters_controller.cpp index 49e60a13a..96d9dfbb2 100644 --- a/apps/probability/parameters_controller.cpp +++ b/apps/probability/parameters_controller.cpp @@ -137,11 +137,11 @@ int ParametersController::reusableParameterCellCount(int type) { return m_distribution->numberOfParameter(); } -double ParametersController::parameterAtIndex(int index) { +float ParametersController::parameterAtIndex(int index) { return m_distribution->parameterValueAtIndex(index); } -bool ParametersController::setParameterAtIndex(int parameterIndex, double f) { +bool ParametersController::setParameterAtIndex(int parameterIndex, float f) { if (!m_distribution->authorizedValueAtIndex(f, parameterIndex)) { Container::activeApp()->displayWarning(I18n::Message::ForbiddenValue); return false; diff --git a/apps/probability/parameters_controller.h b/apps/probability/parameters_controller.h index d20f9df34..833854cd9 100644 --- a/apps/probability/parameters_controller.h +++ b/apps/probability/parameters_controller.h @@ -8,7 +8,7 @@ namespace Probability { -class ParametersController : public Shared::FloatParameterController { +class ParametersController : public Shared::FloatParameterController { public: ParametersController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, Distribution * m_distribution, CalculationController * calculationController); const char * title() override; @@ -23,8 +23,8 @@ private: HighlightCell * reusableParameterCell(int index, int type) override; int reusableParameterCellCount(int type) override; void buttonAction() override; - double parameterAtIndex(int index) override; - bool setParameterAtIndex(int parameterIndex, double f) override; + float parameterAtIndex(int index) override; + bool setParameterAtIndex(int parameterIndex, float f) override; bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; class ContentView : public View { public: diff --git a/apps/shared/float_parameter_controller.cpp b/apps/shared/float_parameter_controller.cpp index d8b6729ae..c1725835d 100644 --- a/apps/shared/float_parameter_controller.cpp +++ b/apps/shared/float_parameter_controller.cpp @@ -8,7 +8,8 @@ using namespace Poincare; namespace Shared { -FloatParameterController::FloatParameterController(Responder * parentResponder) : +template +FloatParameterController::FloatParameterController(Responder * parentResponder) : ViewController(parentResponder), m_selectableTableView(this, this, this), m_okButton(&m_selectableTableView, I18n::Message::Ok, Invocation([](void * context, void * sender) { @@ -19,7 +20,8 @@ FloatParameterController::FloatParameterController(Responder * parentResponder) { } -void FloatParameterController::didBecomeFirstResponder() { +template +void FloatParameterController::didBecomeFirstResponder() { if (selectedRow() >= 0) { int selRow = selectedRow(); selRow = selRow >= numberOfRows() ? numberOfRows()-1 : selRow; @@ -30,7 +32,8 @@ void FloatParameterController::didBecomeFirstResponder() { Container::activeApp()->setFirstResponder(&m_selectableTableView); } -void FloatParameterController::viewWillAppear() { +template +void FloatParameterController::viewWillAppear() { if (selectedRow() == -1 || selectedRow() == numberOfRows()-1) { selectCellAtLocation(0, 0); } else { @@ -43,14 +46,16 @@ void FloatParameterController::viewWillAppear() { m_selectableTableView.reloadData(); } -void FloatParameterController::willExitResponderChain(Responder * nextFirstResponder) { +template +void FloatParameterController::willExitResponderChain(Responder * nextFirstResponder) { if (parentResponder() == nullptr) { m_selectableTableView.deselectTable(); m_selectableTableView.scrollToCell(0,0); } } -bool FloatParameterController::handleEvent(Ion::Events::Event event) { +template +bool FloatParameterController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Back) { stackController()->pop(); return true; @@ -58,49 +63,56 @@ bool FloatParameterController::handleEvent(Ion::Events::Event event) { return false; } -int FloatParameterController::typeAtLocation(int i, int j) { +template +int FloatParameterController::typeAtLocation(int i, int j) { if (j == numberOfRows()-1) { return 0; } return 1; } -int FloatParameterController::reusableCellCount(int type) { +template +int FloatParameterController::reusableCellCount(int type) { if (type == 0) { return 1; } return reusableParameterCellCount(type); } -HighlightCell * FloatParameterController::reusableCell(int index, int type) { +template +HighlightCell * FloatParameterController::reusableCell(int index, int type) { if (type == 0) { return &m_okButton; } return reusableParameterCell(index, type); } -KDCoordinate FloatParameterController::rowHeight(int j) { +template +KDCoordinate FloatParameterController::rowHeight(int j) { if (j == numberOfRows()-1) { return Metric::ParameterCellHeight+k_buttonMargin; } return Metric::ParameterCellHeight; } -KDCoordinate FloatParameterController::cumulatedHeightFromIndex(int j) { +template +KDCoordinate FloatParameterController::cumulatedHeightFromIndex(int j) { if (j == numberOfRows()) { return j*Metric::ParameterCellHeight+k_buttonMargin; } return Metric::ParameterCellHeight*j; } -int FloatParameterController::indexFromCumulatedHeight(KDCoordinate offsetY) { +template +int FloatParameterController::indexFromCumulatedHeight(KDCoordinate offsetY) { if (offsetY > numberOfRows()*Metric::ParameterCellHeight + k_buttonMargin) { return numberOfRows(); } return (offsetY - 1) / Metric::ParameterCellHeight; } -void FloatParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { +template +void FloatParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { if (index == numberOfRows()-1) { return; } @@ -111,18 +123,20 @@ void FloatParameterController::willDisplayCellForIndex(HighlightCell * cell, int constexpr int precision = Preferences::LargeNumberOfSignificantDigits; constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision); char buffer[bufferSize]; - PrintFloat::ConvertFloatToText(parameterAtIndex(index), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal); + PrintFloat::ConvertFloatToText(parameterAtIndex(index), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal); myCell->setAccessoryText(buffer); } -bool FloatParameterController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) { +template +bool FloatParameterController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) { return (event == Ion::Events::Down && selectedRow() < numberOfRows()-1) || (event == Ion::Events::Up && selectedRow() > 0) || TextFieldDelegate::textFieldShouldFinishEditing(textField, event); } -bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { - double floatBody; +template +bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { + T floatBody; if (textFieldDelegateApp()->hasUndefinedValue(text, floatBody)) { return false; } @@ -139,17 +153,23 @@ bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, return true; } -int FloatParameterController::activeCell() { +template +int FloatParameterController::activeCell() { return selectedRow(); } -StackViewController * FloatParameterController::stackController() { +template +StackViewController * FloatParameterController::stackController() { return (StackViewController *)parentResponder(); } -void FloatParameterController::buttonAction() { +template +void FloatParameterController::buttonAction() { StackViewController * stack = stackController(); stack->pop(); } +template class FloatParameterController; +template class FloatParameterController; + } diff --git a/apps/shared/float_parameter_controller.h b/apps/shared/float_parameter_controller.h index 2ed08719f..cc34d3fbc 100644 --- a/apps/shared/float_parameter_controller.h +++ b/apps/shared/float_parameter_controller.h @@ -10,6 +10,7 @@ namespace Shared { /* This controller edits float parameter of any model (given through * parameterAtIndex and setParameterAtIndex). */ +template class FloatParameterController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public ParameterTextFieldDelegate { public: FloatParameterController(Responder * parentResponder); @@ -31,7 +32,7 @@ public: protected: int activeCell(); StackViewController * stackController(); - virtual double parameterAtIndex(int index) = 0; + virtual T parameterAtIndex(int index) = 0; SelectableTableView m_selectableTableView; ButtonWithSeparator m_okButton; private: @@ -39,7 +40,7 @@ private: virtual void buttonAction(); virtual int reusableParameterCellCount(int type) = 0; virtual HighlightCell * reusableParameterCell(int index, int type) = 0; - virtual bool setParameterAtIndex(int parameterIndex, double f) = 0; + virtual bool setParameterAtIndex(int parameterIndex, T f) = 0; }; } diff --git a/apps/shared/go_to_parameter_controller.cpp b/apps/shared/go_to_parameter_controller.cpp index 1bb241ade..e99391202 100644 --- a/apps/shared/go_to_parameter_controller.cpp +++ b/apps/shared/go_to_parameter_controller.cpp @@ -4,7 +4,7 @@ namespace Shared { GoToParameterController::GoToParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, InteractiveCurveViewRange * graphRange, CurveViewCursor * cursor, I18n::Message symbol) : - FloatParameterController(parentResponder), + FloatParameterController(parentResponder), m_cursor(cursor), m_graphRange(graphRange), m_abscisseCell(&m_selectableTableView, inputEventHandlerDelegate, this, symbol) diff --git a/apps/shared/go_to_parameter_controller.h b/apps/shared/go_to_parameter_controller.h index 1f768eac4..118514df2 100644 --- a/apps/shared/go_to_parameter_controller.h +++ b/apps/shared/go_to_parameter_controller.h @@ -8,7 +8,7 @@ namespace Shared { -class GoToParameterController : public FloatParameterController { +class GoToParameterController : public FloatParameterController { public: GoToParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, InteractiveCurveViewRange * graphRange, CurveViewCursor * cursor, I18n::Message symbol); int numberOfRows() override; diff --git a/apps/shared/interval_parameter_controller.cpp b/apps/shared/interval_parameter_controller.cpp index 4a9bf0078..4dae8432a 100644 --- a/apps/shared/interval_parameter_controller.cpp +++ b/apps/shared/interval_parameter_controller.cpp @@ -4,7 +4,7 @@ namespace Shared { IntervalParameterController::IntervalParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, Interval * interval) : - FloatParameterController(parentResponder), + FloatParameterController(parentResponder), m_interval(interval), m_intervalCells{} { diff --git a/apps/shared/interval_parameter_controller.h b/apps/shared/interval_parameter_controller.h index e7b5d12f7..d5aa62831 100644 --- a/apps/shared/interval_parameter_controller.h +++ b/apps/shared/interval_parameter_controller.h @@ -7,7 +7,7 @@ namespace Shared { -class IntervalParameterController : public Shared::FloatParameterController { +class IntervalParameterController : public Shared::FloatParameterController { public: IntervalParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, Interval * interval); Interval * interval(); diff --git a/apps/shared/range_parameter_controller.cpp b/apps/shared/range_parameter_controller.cpp index b49e4bc6a..fd45e352a 100644 --- a/apps/shared/range_parameter_controller.cpp +++ b/apps/shared/range_parameter_controller.cpp @@ -6,7 +6,7 @@ using namespace Poincare; namespace Shared { RangeParameterController::RangeParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, InteractiveCurveViewRange * interactiveRange) : - FloatParameterController(parentResponder), + FloatParameterController(parentResponder), m_interactiveRange(interactiveRange), m_xRangeCells{}, m_yRangeCells{}, @@ -79,14 +79,14 @@ bool RangeParameterController::handleEvent(Ion::Events::Event event) { return FloatParameterController::handleEvent(event); } -double RangeParameterController::parameterAtIndex(int parameterIndex) { +float RangeParameterController::parameterAtIndex(int parameterIndex) { ParameterGetterPointer getters[k_numberOfTextCell] = {&InteractiveCurveViewRange::xMin, &InteractiveCurveViewRange::xMax, &InteractiveCurveViewRange::yMin, &InteractiveCurveViewRange::yMax}; int index = parameterIndex > 2 ? parameterIndex - 1 : parameterIndex; return (m_interactiveRange->*getters[index])(); } -bool RangeParameterController::setParameterAtIndex(int parameterIndex, double f) { +bool RangeParameterController::setParameterAtIndex(int parameterIndex, float f) { ParameterSetterPointer setters[k_numberOfTextCell] = {&InteractiveCurveViewRange::setXMin, &InteractiveCurveViewRange::setXMax, &InteractiveCurveViewRange::setYMin, &InteractiveCurveViewRange::setYMax}; int index = parameterIndex > 2 ? parameterIndex - 1 : parameterIndex; diff --git a/apps/shared/range_parameter_controller.h b/apps/shared/range_parameter_controller.h index 1fea8effd..b787476a1 100644 --- a/apps/shared/range_parameter_controller.h +++ b/apps/shared/range_parameter_controller.h @@ -7,7 +7,7 @@ namespace Shared { -class RangeParameterController : public FloatParameterController { +class RangeParameterController : public FloatParameterController { public: RangeParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, InteractiveCurveViewRange * interactiveCurveViewRange); const char * title() override; @@ -32,8 +32,8 @@ private: }; HighlightCell * reusableParameterCell(int index, int type) override; int reusableParameterCellCount(int type) override; - double parameterAtIndex(int index) override; - bool setParameterAtIndex(int parameterIndex, double f) override; + float parameterAtIndex(int index) override; + bool setParameterAtIndex(int parameterIndex, float f) override; constexpr static int k_numberOfEditableTextCell = 2; constexpr static int k_numberOfConvertibleTextCell = 2; constexpr static int k_numberOfTextCell = k_numberOfEditableTextCell+k_numberOfConvertibleTextCell; diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index 8420cc394..3406e8b29 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -40,8 +40,9 @@ bool TextFieldDelegateApp::isAcceptableText(const char * text) { return isAcceptable; } -bool TextFieldDelegateApp::hasUndefinedValue(const char * text, double & value) { - value = PoincareHelpers::ApproximateToScalar(text, localContext()); +template +bool TextFieldDelegateApp::hasUndefinedValue(const char * text, T & value) { + value = PoincareHelpers::ApproximateToScalar(text, localContext()); bool isUndefined = std::isnan(value) || std::isinf(value); if (isUndefined) { displayWarning(I18n::Message::UndefinedValue); @@ -115,4 +116,7 @@ bool TextFieldDelegateApp::ExpressionCanBeSerialized(const Expression expression return true; } +template bool TextFieldDelegateApp::hasUndefinedValue(const char * text, float & value); +template bool TextFieldDelegateApp::hasUndefinedValue(const char * text, double & value); + } diff --git a/apps/shared/text_field_delegate_app.h b/apps/shared/text_field_delegate_app.h index c7341903b..1ecb60576 100644 --- a/apps/shared/text_field_delegate_app.h +++ b/apps/shared/text_field_delegate_app.h @@ -18,7 +18,8 @@ public: bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool isAcceptableText(const char * text); - bool hasUndefinedValue(const char * text, double & value); + template + bool hasUndefinedValue(const char * text, T & value); protected: TextFieldDelegateApp(Snapshot * snapshot, ViewController * rootViewController); bool fieldDidReceiveEvent(EditableField * field, Responder * responder, Ion::Events::Event event); diff --git a/apps/solver/interval_controller.cpp b/apps/solver/interval_controller.cpp index bcef34147..a1ab7e131 100644 --- a/apps/solver/interval_controller.cpp +++ b/apps/solver/interval_controller.cpp @@ -42,7 +42,7 @@ void IntervalController::ContentView::layoutSubviews() { /* IntervalController Controller */ IntervalController::IntervalController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, EquationStore * equationStore) : - FloatParameterController(parentResponder), + FloatParameterController(parentResponder), m_contentView(&m_selectableTableView), m_intervalCell{}, m_equationStore(equationStore) diff --git a/apps/solver/interval_controller.h b/apps/solver/interval_controller.h index 0b8c6d6b5..acf1ddc34 100644 --- a/apps/solver/interval_controller.h +++ b/apps/solver/interval_controller.h @@ -7,7 +7,7 @@ namespace Solver { -class IntervalController : public Shared::FloatParameterController { +class IntervalController : public Shared::FloatParameterController { public: IntervalController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, EquationStore * equationStore); const char * title() override; diff --git a/apps/statistics/histogram_parameter_controller.cpp b/apps/statistics/histogram_parameter_controller.cpp index 61e7be032..6e58a2d8e 100644 --- a/apps/statistics/histogram_parameter_controller.cpp +++ b/apps/statistics/histogram_parameter_controller.cpp @@ -8,7 +8,7 @@ using namespace Shared; namespace Statistics { HistogramParameterController::HistogramParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, Store * store) : - FloatParameterController(parentResponder), + FloatParameterController(parentResponder), m_cells{}, m_store(store) { diff --git a/apps/statistics/histogram_parameter_controller.h b/apps/statistics/histogram_parameter_controller.h index 8a86dfb6f..7c12a4fa4 100644 --- a/apps/statistics/histogram_parameter_controller.h +++ b/apps/statistics/histogram_parameter_controller.h @@ -7,7 +7,7 @@ namespace Statistics { -class HistogramParameterController : public Shared::FloatParameterController { +class HistogramParameterController : public Shared::FloatParameterController { public: HistogramParameterController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegateApp, Store * store); const char * title() override;