From 3dbe526a92a0a49fb288078f2cf79fc4ce5a2d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 30 Nov 2017 16:41:29 +0100 Subject: [PATCH] [apps] In settings, add a row in display mode menu to choose the number of significant digits Change-Id: I5ff19740e0ee7258a6d77054df547f916d9b04c4 --- apps/settings/app.cpp | 2 +- apps/settings/app.h | 4 +- apps/settings/base.de.i18n | 1 + apps/settings/base.en.i18n | 1 + apps/settings/base.es.i18n | 1 + apps/settings/base.fr.i18n | 1 + apps/settings/base.pt.i18n | 1 + apps/settings/main_controller.cpp | 4 +- apps/settings/sub_controller.cpp | 127 ++++++++++++++++++++++++++---- apps/settings/sub_controller.h | 21 +++-- 10 files changed, 136 insertions(+), 27 deletions(-) diff --git a/apps/settings/app.cpp b/apps/settings/app.cpp index 137768557..b9013a437 100644 --- a/apps/settings/app.cpp +++ b/apps/settings/app.cpp @@ -26,7 +26,7 @@ App::Descriptor * App::Snapshot::descriptor() { } App::App(Container * container, Snapshot * snapshot) : - ::App(container, snapshot, &m_stackViewController, I18n::Message::Warning), + Shared::TextFieldDelegateApp(container, snapshot, &m_stackViewController), m_mainController(&m_stackViewController), m_stackViewController(&m_modalViewController, &m_mainController) { diff --git a/apps/settings/app.h b/apps/settings/app.h index ea9170848..a84c79b16 100644 --- a/apps/settings/app.h +++ b/apps/settings/app.h @@ -1,12 +1,12 @@ #ifndef SETTINGS_APP_H #define SETTINGS_APP_H -#include #include "main_controller.h" +#include "../shared/text_field_delegate_app.h" namespace Settings { -class App : public ::App { +class App : public Shared::TextFieldDelegateApp { public: class Descriptor : public ::App::Descriptor { public: diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 5c8afecaf..58505a7c2 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -17,6 +17,7 @@ Degres = "Grad " Radian = "Bogenmass " Auto = "Auto " Scientific = "Wissenschaftlich " +SignificantFigures = "Signifikante Stellen " Deg = "gra" Rad = "rad" Sci = "sci/" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 3880a44cb..975e2893e 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -17,6 +17,7 @@ Degres = "Degrees " Radian = "Radians " Auto = "Auto " Scientific = "Scientific " +SignificantFigures = "Significant figures " Deg = "deg" Rad = "rad" Sci = "sci/" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index a50f4e084..d759afc75 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -17,6 +17,7 @@ Degres = "Grados " Radian = "Radianes " Auto = "Auto " Scientific = "Cientifico " +SignificantFigures = "Cifras significativas " Deg = "gra" Rad = "rad" Sci = "sci/" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 9cfbbda93..5a12de95a 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -17,6 +17,7 @@ Degres = "Degres " Radian = "Radians " Auto = "Auto " Scientific = "Scientifique " +SignificantFigures = "Chiffres significatifs " Deg = "deg" Rad = "rad" Sci = "sci/" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 11f86cc8f..cf03bb47a 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -17,6 +17,7 @@ Degres = "Graus " Radian = "Radianos " Auto = "Auto " Scientific = "Cientifico " +SignificantFigures = "Algarismo significativo " Deg = "gra" Rad = "rad" Sci = "sci/" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 5e4c91032..1f4aca5fd 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -11,7 +11,7 @@ using namespace Poincare; namespace Settings { const SettingsMessageTree angleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)}; -const SettingsMessageTree FloatDisplayModeChildren[2] = {SettingsMessageTree(I18n::Message::Auto), SettingsMessageTree(I18n::Message::Scientific)}; +const SettingsMessageTree FloatDisplayModeChildren[3] = {SettingsMessageTree(I18n::Message::Auto), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::SignificantFigures)}; const SettingsMessageTree complexFormatChildren[2] = {SettingsMessageTree(I18n::Message::Default), SettingsMessageTree(I18n::Message::Default)}; const SettingsMessageTree examChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; const SettingsMessageTree aboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; @@ -21,7 +21,7 @@ const SettingsMessageTree menu[8] = #else const SettingsMessageTree menu[7] = #endif - {SettingsMessageTree(I18n::Message::AngleUnit, angleChildren, 2), SettingsMessageTree(I18n::Message::DisplayMode, FloatDisplayModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 2), + {SettingsMessageTree(I18n::Message::AngleUnit, angleChildren, 2), SettingsMessageTree(I18n::Message::DisplayMode, FloatDisplayModeChildren, 3), SettingsMessageTree(I18n::Message::ComplexFormat, complexFormatChildren, 2), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), SettingsMessageTree(I18n::Message::ExamMode, examChildren, 1), #if OS_WITH_SOFTWARE_UPDATE_PROMPT SettingsMessageTree(I18n::Message::UpdatePopUp), diff --git a/apps/settings/sub_controller.cpp b/apps/settings/sub_controller.cpp index e89c03945..8fc44b8b3 100644 --- a/apps/settings/sub_controller.cpp +++ b/apps/settings/sub_controller.cpp @@ -4,6 +4,7 @@ #include "../../poincare/src/layout/baseline_relative_layout.h" #include "../../poincare/src/layout/string_layout.h" #include +#include using namespace Poincare; @@ -11,8 +12,9 @@ namespace Settings { SubController::SubController(Responder * parentResponder) : ViewController(parentResponder), + m_editableCell(&m_selectableTableView, this, m_draftTextBuffer), m_selectableTableView(this, this, 0, 1, k_topBottomMargin, Metric::CommonRightMargin, - k_topBottomMargin, Metric::CommonLeftMargin, this), + k_topBottomMargin, Metric::CommonLeftMargin, this, this), m_messageTreeModel(nullptr) { for (int i = 0; i < k_totalNumberOfCell; i++) { @@ -28,6 +30,8 @@ SubController::SubController(Responder * parentResponder) : for (int i = 0; i < 2; i++) { m_complexFormatCells[i].setExpression(m_complexFormatLayout[i]); } + m_editableCell.setMessage(I18n::Message::SignificantFigures); + m_editableCell.setMessageFontSize(KDText::FontSize::Large); } SubController::~SubController() { @@ -50,13 +54,8 @@ View * SubController::view() { return &m_selectableTableView; } -void SubController::didEnterResponderChain(Responder * previousResponder) { - if (previousResponder->commonAncestorWith(this) == parentResponder()) { - /* We want to select the prefered SettingMessageTree only when the previous page - * was the main setting page. We do not to change the selection when - * dismissing a pop-up for instance. */ - selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label())); - } +void SubController::didBecomeFirstResponder() { + selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label())); if (m_messageTreeModel->label() == I18n::Message::ExamMode) { m_selectableTableView.reloadData(); } @@ -94,6 +93,7 @@ bool SubController::handleEvent(Ion::Events::Event event) { return false; } /* Generic behaviour of preference menu*/ + assert(m_messageTreeModel->label() != I18n::Message::DisplayMode || selectedRow() != numberOfRows()-1); // In that case, events OK and EXE are handled by the cell setPreferenceWithValueIndex(m_messageTreeModel->label(), selectedRow()); AppsContainer * myContainer = (AppsContainer * )app()->container(); myContainer->refreshPreferences(); @@ -115,30 +115,70 @@ int SubController::numberOfRows() { return 0; } -HighlightCell * SubController::reusableCell(int index) { - assert(index >= 0); - assert(index < k_totalNumberOfCell); - if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { +HighlightCell * SubController::reusableCell(int index, int type) { + if (type == 2) { + assert(index == 0); + return &m_editableCell; + } else if (type == 1) { + assert(index >= 0 && index < 2); return &m_complexFormatCells[index]; } + assert(index >= 0 && index < k_totalNumberOfCell); return &m_cells[index]; } -int SubController::reusableCellCount() { - if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { - return 2; +int SubController::reusableCellCount(int type) { + switch (type) { + case 0: + return k_totalNumberOfCell; + case 1: + return 2; + case 2: + return 1; + default: + assert(false); + return 0; } - return k_totalNumberOfCell; } -KDCoordinate SubController::cellHeight() { +int SubController::typeAtLocation(int i, int j) { + if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { + return 1; + } + if (m_messageTreeModel->label() == I18n::Message::DisplayMode && j == numberOfRows()-1) { + return 2; + } + return 0; +} + +KDCoordinate SubController::rowHeight(int j) { return Metric::ParameterCellHeight; } +KDCoordinate SubController::cumulatedHeightFromIndex(int j) { + return rowHeight(0) * j; +} + +int SubController::indexFromCumulatedHeight(KDCoordinate offsetY) { + KDCoordinate height = rowHeight(0); + if (height == 0) { + return 0; + } + return (offsetY - 1) / height; +} + void SubController::willDisplayCellForIndex(HighlightCell * cell, int index) { if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) { return; } + /* Number of significants figure row */ + if (m_messageTreeModel->label() == I18n::Message::DisplayMode && index == numberOfRows()-1) { + MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *)cell; + char buffer[3]; + Integer(Preferences::sharedPreferences()->numberOfSignificantDigits()).writeTextInBuffer(buffer, 3); + myCell->setAccessoryText(buffer); + return; + } MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; myCell->setMessage(m_messageTreeModel->children(index)->label()); myCell->setMessageFontSize(KDText::FontSize::Large); @@ -179,6 +219,56 @@ void SubController::viewDidDisappear() { m_selectableTableView.deselectTable(); } +bool SubController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) { + return (event == Ion::Events::Up && selectedRow() > 0) + || TextFieldDelegate::textFieldShouldFinishEditing(textField, event); +} + +bool SubController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { + Context * globalContext = textFieldDelegateApp()->localContext(); + float floatBody = Expression::approximateToScalar(text, *globalContext); + if (std::isnan(floatBody) || std::isinf(floatBody)) { + floatBody = PrintFloat::k_numberOfPrintedSignificantDigits; + } + if (floatBody < 1) { + floatBody = 1; + } + if (floatBody > PrintFloat::k_numberOfStoredSignificantDigits) { + floatBody = PrintFloat::k_numberOfStoredSignificantDigits; + } + Preferences::sharedPreferences()->setNumberOfSignificantDigits((char)std::round(floatBody)); + m_selectableTableView.reloadCellAtLocation(0, selectedRow()); + if (event == Ion::Events::Up || event == Ion::Events::OK) { + m_selectableTableView.handleEvent(event); + } + return true; +} + +bool SubController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) { + if (event == Ion::Events::Backspace && !textField->isEditing()) { + textField->setEditing(true); + return true; + } + return TextFieldDelegate::textFieldDidReceiveEvent(textField, event); +} + +void SubController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) { + if (m_messageTreeModel->label() != I18n::Message::DisplayMode) { + return; + } + if (previousSelectedCellX == t->selectedColumn() && previousSelectedCellY == t->selectedRow()) { + return; + } + if (previousSelectedCellY == numberOfRows()-1) { + MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *)t->cellAtLocation(previousSelectedCellX, previousSelectedCellY); + myCell->setEditing(false); + } + if (t->selectedRow() == numberOfRows() -1) { + MessageTableCellWithEditableText * myNewCell = (MessageTableCellWithEditableText *)t->selectedCell(); + app()->setFirstResponder(myNewCell); + } +} + StackViewController * SubController::stackController() const { return (StackViewController *)parentResponder(); } @@ -208,5 +298,8 @@ int SubController::valueIndexForPreference(I18n::Message message) { return 0; } +Shared::TextFieldDelegateApp * SubController::textFieldDelegateApp() { + return (Shared::TextFieldDelegateApp *)app(); +} } diff --git a/apps/settings/sub_controller.h b/apps/settings/sub_controller.h index 5e4c81d67..42a78c329 100644 --- a/apps/settings/sub_controller.h +++ b/apps/settings/sub_controller.h @@ -4,10 +4,11 @@ #include #include "settings_message_tree.h" #include "../hardware_test/pop_up_controller.h" +#include "../shared/text_field_delegate.h" namespace Settings { -class SubController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource { +class SubController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public SelectableTableViewDelegate, public Shared::TextFieldDelegate { public: SubController(Responder * parentResponder); ~SubController(); @@ -18,24 +19,34 @@ public: View * view() override; const char * title() override; bool handleEvent(Ion::Events::Event event) override; - void didEnterResponderChain(Responder * previousFirstResponder) override; + void didBecomeFirstResponder() override; int numberOfRows() override; - KDCoordinate cellHeight() override; - HighlightCell * reusableCell(int index) override; - int reusableCellCount() override; + KDCoordinate rowHeight(int j) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; void setMessageTreeModel(const MessageTree * messageTreeModel); void viewWillAppear() override; void viewDidDisappear() override; + bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; + bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; + bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; + void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override; private: StackViewController * stackController() const; void setPreferenceWithValueIndex(I18n::Message message, int valueIndex); int valueIndexForPreference(I18n::Message message); + Shared::TextFieldDelegateApp * textFieldDelegateApp() override; constexpr static int k_totalNumberOfCell = I18n::NumberOfLanguages; constexpr static KDCoordinate k_topBottomMargin = 13; MessageTableCellWithBuffer m_cells[k_totalNumberOfCell]; ExpressionTableCell m_complexFormatCells[2]; Poincare::ExpressionLayout * m_complexFormatLayout[2]; + MessageTableCellWithEditableText m_editableCell; + char m_draftTextBuffer[MessageTableCellWithEditableText::k_bufferLength]; SelectableTableView m_selectableTableView; MessageTree * m_messageTreeModel; HardwareTest::PopUpController m_hardwareTestPopUpController;