diff --git a/apps/settings/Makefile b/apps/settings/Makefile index 40bd2ac72..0a03bf605 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -3,11 +3,14 @@ app_headers += apps/settings/app.h app_objs += $(addprefix apps/settings/,\ app.o\ - helpers.o\ - language_controller.o\ main_controller.o\ settings_message_tree.o\ - sub_controller.o\ + sub_menu/about_controller.o\ + sub_menu/display_mode_controller.o\ + sub_menu/exam_mode_controller.o\ + sub_menu/generic_sub_controller.o\ + sub_menu/language_controller.o\ + sub_menu/preferences_controller.o\ ) i18n_files += $(addprefix apps/settings/,\ diff --git a/apps/settings/helpers.cpp b/apps/settings/helpers.cpp deleted file mode 100644 index 0f8cb8d7b..000000000 --- a/apps/settings/helpers.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "helpers.h" -#include -#include - -using namespace Poincare; - -namespace Settings { -namespace Helpers { - -Layout CartesianComplexFormat(KDText::FontSize fontSize) { - const char text[] = {'a','+', Ion::Charset::IComplex, 'b', ' '}; - return LayoutHelper::String(text, sizeof(text), fontSize); -} - -Layout PolarComplexFormat(KDText::FontSize fontSize) { - const char base[] = {'r', Ion::Charset::Exponential}; - const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta, ' '}; - return HorizontalLayout( - LayoutHelper::String(base, sizeof(base), fontSize), - VerticalOffsetLayout(LayoutHelper::String(superscript, sizeof(superscript), fontSize), VerticalOffsetLayoutNode::Type::Superscript) - ); -} - -} -} diff --git a/apps/settings/helpers.h b/apps/settings/helpers.h deleted file mode 100644 index dc1b2fc3b..000000000 --- a/apps/settings/helpers.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SETTINGS_HELPERS_H -#define SETTINGS_HELPERS_H - -#include - -namespace Settings { -namespace Helpers { - -Poincare::Layout CartesianComplexFormat(KDText::FontSize fontSize); -Poincare::Layout PolarComplexFormat(KDText::FontSize fontSize); - -} -} - -#endif diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 7fd26fcec..5b23cc79f 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -1,5 +1,4 @@ #include "main_controller.h" -#include "helpers.h" #include "../global_preferences.h" #include "../i18n.h" #include @@ -42,13 +41,14 @@ MainController::MainController(Responder * parentResponder) : #if EPSILON_SOFTWARE_UPDATE_PROMPT m_updateCell(I18n::Message::Default, KDText::FontSize::Large), #endif - m_complexFormatCell(I18n::Message::Default, KDText::FontSize::Large), m_brightnessCell(I18n::Message::Default, KDText::FontSize::Large), - m_complexFormatLayout(), m_selectableTableView(this), m_messageTreeModel((MessageTree *)&model), - m_subController(this), - m_languageController(this, 13) + m_preferencesController(this), + m_displayModeController(this), + m_languageController(this, 13), + m_examModeController(this), + m_aboutController(this) { for (int i = 0; i < k_numberOfSimpleChevronCells; i++) { m_cells[i].setMessageFontSize(KDText::FontSize::Large); @@ -97,9 +97,30 @@ bool MainController::handleEvent(Ion::Events::Event event) { } } if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { - m_subController.setMessageTreeModel(m_messageTreeModel->children(selectedRow())); + GenericSubController * subController = nullptr; + switch (selectedRow()) { + case 1: + subController = &m_displayModeController; + break; + case 4: + case 5: + assert(false); + case 6: + subController = &m_examModeController; + break; +#if EPSILON_SOFTWARE_UPDATE_PROMPT + case 8: +#else + case 7: +#endif + subController = &m_aboutController; + break; + default: + subController = &m_preferencesController; + } + subController->setMessageTreeModel(m_messageTreeModel->children(selectedRow())); StackViewController * stack = stackController(); - stack->push(&m_subController); + stack->push(subController); return true; } return false; @@ -128,15 +149,13 @@ HighlightCell * MainController::reusableCell(int index, int type) { return &m_cells[index]; } assert(index == 0); - if (type == 2) { - return &m_brightnessCell; - } #if EPSILON_SOFTWARE_UPDATE_PROMPT - if (type == 3) { + if (type == 2) { return &m_updateCell; } #endif - return &m_complexFormatCell; + assert(type == 1); + return &m_brightnessCell; } int MainController::reusableCellCount(int type) { @@ -147,15 +166,12 @@ int MainController::reusableCellCount(int type) { } int MainController::typeAtLocation(int i, int j) { - if (j == 3) { - return 1; - } if (j == 4) { - return 2; + return 1; } #if EPSILON_SOFTWARE_UPDATE_PROMPT if (j == 7) { - return 3; + return 2; } #endif return 0; @@ -164,17 +180,6 @@ int MainController::typeAtLocation(int i, int j) { void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { MessageTableCell * myCell = (MessageTableCell *)cell; myCell->setMessage(m_messageTreeModel->children(index)->label()); - - if (index == 3) { - if (Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Cartesian) { - m_complexFormatLayout = Helpers::CartesianComplexFormat(KDText::FontSize::Small); - } else { - m_complexFormatLayout = Helpers::PolarComplexFormat(KDText::FontSize::Small); - } - MessageTableCellWithChevronAndExpression * myExpCell = (MessageTableCellWithChevronAndExpression *)cell; - myExpCell->setLayout(m_complexFormatLayout); - return; - } if (index == 4) { MessageTableCellWithGauge * myGaugeCell = (MessageTableCellWithGauge *)cell; GaugeView * myGauge = (GaugeView *)myGaugeCell->accessoryView(); @@ -195,20 +200,23 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { } #endif MessageTableCellWithChevronAndMessage * myTextCell = (MessageTableCellWithChevronAndMessage *)cell; + int childIndex = -1; switch (index) { case 0: - myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->angleUnit())->label()); + childIndex = (int)Preferences::sharedPreferences()->angleUnit(); break; case 1: - myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->displayMode())->label()); + childIndex = (int)Preferences::sharedPreferences()->displayMode(); break; case 2: - myTextCell->setSubtitle(m_messageTreeModel->children(index)->children((int)Preferences::sharedPreferences()->editionMode())->label()); + childIndex = (int)Preferences::sharedPreferences()->editionMode(); break; - default: - myTextCell->setSubtitle(I18n::Message::Default); + case 3: + childIndex = (int)Preferences::sharedPreferences()->complexFormat(); break; } + I18n::Message message = childIndex >= 0 ? m_messageTreeModel->children(index)->children(childIndex)->label() : I18n::Message::Default; + myTextCell->setSubtitle(message); } void MainController::viewWillAppear() { diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 997b627f3..f1a6edbbd 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -2,9 +2,12 @@ #define SETTINGS_MAIN_CONTROLLER_H #include -#include "sub_controller.h" #include "settings_message_tree.h" -#include "language_controller.h" +#include "sub_menu/about_controller.h" +#include "sub_menu/display_mode_controller.h" +#include "sub_menu/exam_mode_controller.h" +#include "sub_menu/language_controller.h" +#include "sub_menu/preferences_controller.h" namespace Settings { @@ -31,15 +34,17 @@ private: #else constexpr static int k_totalNumberOfCell = 8; #endif - constexpr static int k_numberOfSimpleChevronCells = 6; + constexpr static int k_numberOfSimpleChevronCells = 7; MessageTableCellWithChevronAndMessage m_cells[k_numberOfSimpleChevronCells]; - MessageTableCellWithChevronAndExpression m_complexFormatCell; MessageTableCellWithGauge m_brightnessCell; - Poincare::Layout m_complexFormatLayout; SelectableTableView m_selectableTableView; MessageTree * m_messageTreeModel; - SubController m_subController; + PreferencesController m_preferencesController; + DisplayModeController m_displayModeController; LanguageController m_languageController; + ExamModeController m_examModeController; + AboutController m_aboutController; + }; } diff --git a/apps/settings/sub_controller.cpp b/apps/settings/sub_controller.cpp deleted file mode 100644 index cd7f8934a..000000000 --- a/apps/settings/sub_controller.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#include "sub_controller.h" -#include "helpers.h" -#include "../global_preferences.h" -#include "../apps_container.h" -#include "../shared/poincare_helpers.h" -#include -#include - -using namespace Poincare; -using namespace Shared; - -namespace Settings { - -SubController::SubController(Responder * parentResponder) : - ViewController(parentResponder), - m_editableCell(&m_selectableTableView, this, m_draftTextBuffer), - m_selectableTableView(this), - m_messageTreeModel(nullptr) -{ - m_selectableTableView.setTopMargin(k_topBottomMargin); - m_selectableTableView.setBottomMargin(k_topBottomMargin); - for (int i = 0; i < k_totalNumberOfCell; i++) { - m_cells[i].setMessageFontSize(KDText::FontSize::Large); - m_cells[i].setAccessoryFontSize(KDText::FontSize::Small); - m_cells[i].setAccessoryTextColor(Palette::GreyDark); - } - m_complexFormatLayout[0] = Helpers::CartesianComplexFormat(KDText::FontSize::Large); - m_complexFormatLayout[1] = Helpers::PolarComplexFormat(KDText::FontSize::Large); - for (int i = 0; i < 2; i++) { - m_complexFormatCells[i].setLayout(m_complexFormatLayout[i]); - } - m_editableCell.setMessage(I18n::Message::SignificantFigures); - m_editableCell.setMessageFontSize(KDText::FontSize::Large); -} - -const char * SubController::title() { - if (m_messageTreeModel) { - return I18n::translate(m_messageTreeModel->label()); - } - return ""; -} - -View * SubController::view() { - return &m_selectableTableView; -} - -void SubController::didEnterResponderChain(Responder * previousFirstResponder) { - if (m_messageTreeModel->label() == I18n::Message::ExamMode) { - m_selectableTableView.reloadData(); - } -} - -void SubController::didBecomeFirstResponder() { - selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label())); - app()->setFirstResponder(&m_selectableTableView); -} - -bool SubController::handleEvent(Ion::Events::Event event) { - /* We hide here the activation hardware test app: in the menu "about", by - * clicking on '6' on the last row. */ - if ((event == Ion::Events::Six || event == Ion::Events::LowerT || event == Ion::Events::UpperT) && m_messageTreeModel->label() == I18n::Message::About && selectedRow() == numberOfRows()-1) { - app()->displayModalViewController(&m_hardwareTestPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin); - return true; - } - if (event == Ion::Events::OK || event == Ion::Events::EXE) { - /* Behaviour of "Exam mode" menu*/ - if (m_messageTreeModel->label() == I18n::Message::ExamMode) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { - return false; - } - AppsContainer * container = (AppsContainer *)(app()->container()); - container->displayExamModePopUp(true); - return true; - } - /* Behaviour of "About" menu */ - if (m_messageTreeModel->label() == I18n::Message::About) { - if (selectedRow() == 0) { - MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)m_selectableTableView.selectedCell(); - if (strcmp(myCell->accessoryText(), Ion::patchLevel()) == 0) { - myCell->setAccessoryText(Ion::softwareVersion()); - return true; - } - myCell->setAccessoryText(Ion::patchLevel()); - return true; - } - 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(); - StackViewController * stack = stackController(); - stack->pop(); - return true; - } - if (event == Ion::Events::Left) { - stackController()->pop(); - return true; - } - return false; -} - -int SubController::numberOfRows() { - if (m_messageTreeModel) { - return m_messageTreeModel->numberOfChildren(); - } - return 0; -} - -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(int type) { - switch (type) { - case 0: - return k_totalNumberOfCell; - case 1: - return 2; - case 2: - return 1; - default: - assert(false); - return 0; - } -} - -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()).serialize(buffer, 3); - myCell->setAccessoryText(buffer); - return; - } - MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; - myCell->setMessage(m_messageTreeModel->children(index)->label()); - myCell->setMessageFontSize(KDText::FontSize::Large); - myCell->setAccessoryText(""); - if (m_messageTreeModel->label() == I18n::Message::ExamMode && GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { - myCell->setMessage(I18n::Message::ExamModeActive); - } - if (m_messageTreeModel->label() == I18n::Message::About) { - myCell->setMessageFontSize(KDText::FontSize::Small); - const char * messages[] = { - Ion::softwareVersion(), - Ion::serialNumber(), - Ion::fccId() - }; - assert(index >= 0 && index < 3); - myCell->setAccessoryText(messages[index]); - } -} - -void SubController::setMessageTreeModel(const MessageTree * messageTreeModel) { - m_messageTreeModel = (MessageTree *)messageTreeModel; -} - -void SubController::viewWillAppear() { - m_selectableTableView.reloadData(); -} - -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 = PoincareHelpers::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; -} - -StackViewController * SubController::stackController() const { - return (StackViewController *)parentResponder(); -} - -void SubController::setPreferenceWithValueIndex(I18n::Message message, int valueIndex) { - if (message == I18n::Message::AngleUnit) { - Preferences::sharedPreferences()->setAngleUnit((Preferences::AngleUnit)valueIndex); - } - if (message == I18n::Message::DisplayMode) { - Preferences::sharedPreferences()->setDisplayMode((Preferences::PrintFloatMode)valueIndex); - } - if (message == I18n::Message::EditionMode) { - Preferences::sharedPreferences()->setEditionMode((Preferences::EditionMode)valueIndex); - } - if (message == I18n::Message::ComplexFormat) { - Preferences::sharedPreferences()->setComplexFormat((Preferences::ComplexFormat)valueIndex); - } -} - -int SubController::valueIndexForPreference(I18n::Message message) { - if (message == I18n::Message::AngleUnit) { - return (int)Preferences::sharedPreferences()->angleUnit(); - } - if (message == I18n::Message::DisplayMode) { - return (int)Preferences::sharedPreferences()->displayMode(); - } - if (message == I18n::Message::EditionMode) { - return (int)Preferences::sharedPreferences()->editionMode(); - } - if (message == I18n::Message::ComplexFormat) { - return (int)Preferences::sharedPreferences()->complexFormat(); - } - return 0; -} - -Shared::TextFieldDelegateApp * SubController::textFieldDelegateApp() { - return (Shared::TextFieldDelegateApp *)app(); -} - -} diff --git a/apps/settings/sub_controller.h b/apps/settings/sub_controller.h deleted file mode 100644 index 50d758836..000000000 --- a/apps/settings/sub_controller.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef SETTINGS_SUB_CONTROLLER_H -#define SETTINGS_SUB_CONTROLLER_H - -#include -#include "settings_message_tree.h" -#include "../hardware_test/pop_up_controller.h" -#include "../shared/parameter_text_field_delegate.h" - -namespace Settings { - -class SubController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public Shared::ParameterTextFieldDelegate { -public: - SubController(Responder * parentResponder); - 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 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; -private: - StackViewController * stackController() const; - void setPreferenceWithValueIndex(I18n::Message message, int valueIndex); - int valueIndexForPreference(I18n::Message message); - Shared::TextFieldDelegateApp * textFieldDelegateApp() override; - constexpr static KDCoordinate k_topBottomMargin = 13; - constexpr static int k_totalNumberOfCell = (Ion::Display::Height-2*k_topBottomMargin-Metric::TitleBarHeight-Metric::StackTitleHeight)/Metric::ParameterCellHeight; - MessageTableCellWithBuffer m_cells[k_totalNumberOfCell]; - ExpressionTableCell m_complexFormatCells[2]; - Poincare::Layout m_complexFormatLayout[2]; - MessageTableCellWithEditableText m_editableCell; - char m_draftTextBuffer[MessageTableCellWithEditableText::k_bufferLength]; - SelectableTableView m_selectableTableView; - MessageTree * m_messageTreeModel; - HardwareTest::PopUpController m_hardwareTestPopUpController; -}; - -} - -#endif diff --git a/apps/settings/sub_menu/about_controller.cpp b/apps/settings/sub_menu/about_controller.cpp new file mode 100644 index 000000000..eeb96fe12 --- /dev/null +++ b/apps/settings/sub_menu/about_controller.cpp @@ -0,0 +1,65 @@ +#include "about_controller.h" +#include "../../apps_container.h" +#include +#include + +using namespace Shared; + +namespace Settings { + +AboutController::AboutController(Responder * parentResponder) : + GenericSubController(parentResponder) +{ + for (int i = 0; i < k_totalNumberOfCell; i++) { + m_cells[i].setMessageFontSize(KDText::FontSize::Large); + m_cells[i].setAccessoryFontSize(KDText::FontSize::Small); + m_cells[i].setAccessoryTextColor(Palette::GreyDark); + } +} + +bool AboutController::handleEvent(Ion::Events::Event event) { + /* We hide here the activation hardware test app: in the menu "about", by + * clicking on '6' on the last row. */ + if ((event == Ion::Events::Six || event == Ion::Events::LowerT || event == Ion::Events::UpperT) && m_messageTreeModel->label() == I18n::Message::About && selectedRow() == numberOfRows()-1) { + app()->displayModalViewController(&m_hardwareTestPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin); + return true; + } + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + if (selectedRow() == 0) { + MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)m_selectableTableView.selectedCell(); + if (strcmp(myCell->accessoryText(), Ion::patchLevel()) == 0) { + myCell->setAccessoryText(Ion::softwareVersion()); + return true; + } + myCell->setAccessoryText(Ion::patchLevel()); + return true; + } + return false; + } + return GenericSubController::handleEvent(event); +} + +HighlightCell * AboutController::reusableCell(int index, int type) { + assert(type == 0); + assert(index >= 0 && index < k_totalNumberOfCell); + return &m_cells[index]; +} + +int AboutController::reusableCellCount(int type) { + assert(type == 0); + return k_totalNumberOfCell; +} + +void AboutController::willDisplayCellForIndex(HighlightCell * cell, int index) { + GenericSubController::willDisplayCellForIndex(cell, index); + MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; + static const char * messages[] = { + Ion::softwareVersion(), + Ion::serialNumber(), + Ion::fccId() + }; + assert(index >= 0 && index < 3); + myCell->setAccessoryText(messages[index]); +} + +} diff --git a/apps/settings/sub_menu/about_controller.h b/apps/settings/sub_menu/about_controller.h new file mode 100644 index 000000000..57d66087b --- /dev/null +++ b/apps/settings/sub_menu/about_controller.h @@ -0,0 +1,24 @@ +#ifndef SETTINGS_ABOUT_CONTROLLER_H +#define SETTINGS_ABOUT_CONTROLLER_H + +#include "generic_sub_controller.h" +#include "../../hardware_test/pop_up_controller.h" + +namespace Settings { + +class AboutController : public GenericSubController { +public: + AboutController(Responder * parentResponder); + bool handleEvent(Ion::Events::Event event) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; +private: + constexpr static int k_totalNumberOfCell = 3; + MessageTableCellWithBuffer m_cells[k_totalNumberOfCell]; + HardwareTest::PopUpController m_hardwareTestPopUpController; +}; + +} + +#endif diff --git a/apps/settings/sub_menu/display_mode_controller.cpp b/apps/settings/sub_menu/display_mode_controller.cpp new file mode 100644 index 000000000..f558ed69e --- /dev/null +++ b/apps/settings/sub_menu/display_mode_controller.cpp @@ -0,0 +1,85 @@ +#include "display_mode_controller.h" +#include "../../shared/poincare_helpers.h" +#include +#include + +using namespace Poincare; +using namespace Shared; + +namespace Settings { + +DisplayModeController::DisplayModeController(Responder * parentResponder) : + PreferencesController(parentResponder), + m_editableCell(&m_selectableTableView, this, m_draftTextBuffer) +{ + m_editableCell.setMessage(I18n::Message::SignificantFigures); + m_editableCell.setMessageFontSize(KDText::FontSize::Large); +} + +HighlightCell * DisplayModeController::reusableCell(int index, int type) { + if (type == 1) { + assert(index == 0); + return &m_editableCell; + } + return PreferencesController::reusableCell(index, type); +} + +int DisplayModeController::reusableCellCount(int type) { + switch (type) { + case 0: + return PreferencesController::k_totalNumberOfCell; + case 1: + return 1; + default: + assert(false); + return 0; + } +} + +int DisplayModeController::typeAtLocation(int i, int j) { + return (j == numberOfRows() - 1 ? 1 : 0); +} + +void DisplayModeController::willDisplayCellForIndex(HighlightCell * cell, int index) { + /* Number of significants figure row */ + if (index == numberOfRows()-1) { + GenericSubController::willDisplayCellForIndex(cell, index); + MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *)cell; + char buffer[3]; + Integer(Preferences::sharedPreferences()->numberOfSignificantDigits()).serialize(buffer, 3); + myCell->setAccessoryText(buffer); + return; + } + PreferencesController::willDisplayCellForIndex(cell, index); +} + +bool DisplayModeController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) { + return (event == Ion::Events::Up && selectedRow() > 0) + || TextFieldDelegate::textFieldShouldFinishEditing(textField, event); +} + +bool DisplayModeController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { + Context * globalContext = textFieldDelegateApp()->localContext(); + float floatBody = PoincareHelpers::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; +} + +Shared::TextFieldDelegateApp * DisplayModeController::textFieldDelegateApp() { + return (Shared::TextFieldDelegateApp *)app(); +} + +} diff --git a/apps/settings/sub_menu/display_mode_controller.h b/apps/settings/sub_menu/display_mode_controller.h new file mode 100644 index 000000000..f28724ace --- /dev/null +++ b/apps/settings/sub_menu/display_mode_controller.h @@ -0,0 +1,26 @@ +#ifndef SETTINGS_DISPLAY_MODE_CONTROLLER_H +#define SETTINGS_DISPLAY_MODE_CONTROLLER_H + +#include "preferences_controller.h" +#include "../../shared/parameter_text_field_delegate.h" + +namespace Settings { + +class DisplayModeController : public PreferencesController, public Shared::ParameterTextFieldDelegate { +public: + DisplayModeController(Responder * parentResponder); + 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; + bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; + bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; +private: + Shared::TextFieldDelegateApp * textFieldDelegateApp() override; + MessageTableCellWithEditableText m_editableCell; + char m_draftTextBuffer[MessageTableCellWithEditableText::k_bufferLength]; +}; + +} + +#endif diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp new file mode 100644 index 000000000..6903add84 --- /dev/null +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -0,0 +1,52 @@ +#include "exam_mode_controller.h" +#include "../../global_preferences.h" +#include "../../apps_container.h" +#include +#include + +using namespace Poincare; +using namespace Shared; + +namespace Settings { + +ExamModeController::ExamModeController(Responder * parentResponder) : + GenericSubController(parentResponder), + m_cell(I18n::Message::ExamModeActive, KDText::FontSize::Large) +{ +} + +void ExamModeController::didEnterResponderChain(Responder * previousFirstResponder) { + m_selectableTableView.reloadData(); +} + +bool ExamModeController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + return false; + } + AppsContainer * container = (AppsContainer *)(app()->container()); + container->displayExamModePopUp(true); + return true; + } + return GenericSubController::handleEvent(event); +} + +HighlightCell * ExamModeController::reusableCell(int index, int type) { + assert(type == 0); + assert(index == 0); + return &m_cell; +} + +int ExamModeController::reusableCellCount(int type) { + return 1; +} + +void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) { + GenericSubController::willDisplayCellForIndex(cell, index); + if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + MessageTableCell * myCell = (MessageTableCell *)cell; + myCell->setMessage(I18n::Message::ExamModeActive); + } +} + +} diff --git a/apps/settings/sub_menu/exam_mode_controller.h b/apps/settings/sub_menu/exam_mode_controller.h new file mode 100644 index 000000000..22a0da0c7 --- /dev/null +++ b/apps/settings/sub_menu/exam_mode_controller.h @@ -0,0 +1,22 @@ +#ifndef SETTINGS_EXAM_MODE_CONTROLLER_H +#define SETTINGS_EXAM_MODE_CONTROLLER_H + +#include "generic_sub_controller.h" + +namespace Settings { + +class ExamModeController : public GenericSubController { +public: + ExamModeController(Responder * parentResponder); + void didEnterResponderChain(Responder * previousFirstResponder) override; + bool handleEvent(Ion::Events::Event event) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; +private: + MessageTableCell m_cell; +}; + +} + +#endif diff --git a/apps/settings/sub_menu/generic_sub_controller.cpp b/apps/settings/sub_menu/generic_sub_controller.cpp new file mode 100644 index 000000000..e70e3f747 --- /dev/null +++ b/apps/settings/sub_menu/generic_sub_controller.cpp @@ -0,0 +1,92 @@ +#include "generic_sub_controller.h" +#include "../../apps_container.h" +#include +#include + +using namespace Poincare; +using namespace Shared; + +namespace Settings { + +GenericSubController::GenericSubController(Responder * parentResponder) : + ViewController(parentResponder), + m_selectableTableView(this), + m_messageTreeModel(nullptr) +{ + m_selectableTableView.setTopMargin(k_topBottomMargin); + m_selectableTableView.setBottomMargin(k_topBottomMargin); +} + +const char * GenericSubController::title() { + if (m_messageTreeModel) { + return I18n::translate(m_messageTreeModel->label()); + } + return ""; +} + +View * GenericSubController::view() { + return &m_selectableTableView; +} + +void GenericSubController::didBecomeFirstResponder() { + selectCellAtLocation(0, 0); + app()->setFirstResponder(&m_selectableTableView); +} + +bool GenericSubController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Left) { + stackController()->pop(); + return true; + } + return false; +} + +int GenericSubController::numberOfRows() { + if (m_messageTreeModel) { + return m_messageTreeModel->numberOfChildren(); + } + return 0; +} + +KDCoordinate GenericSubController::rowHeight(int j) { + return Metric::ParameterCellHeight; +} + +KDCoordinate GenericSubController::cumulatedHeightFromIndex(int j) { + return rowHeight(0) * j; +} + +int GenericSubController::indexFromCumulatedHeight(KDCoordinate offsetY) { + KDCoordinate height = rowHeight(0); + if (height == 0) { + return 0; + } + return (offsetY - 1) / height; +} + +int GenericSubController::typeAtLocation(int i, int j) { + return 0; +} + +void GenericSubController::willDisplayCellForIndex(HighlightCell * cell, int index) { + MessageTableCell * myCell = (MessageTableCell *)cell; + myCell->setMessage(m_messageTreeModel->children(index)->label()); +} + +void GenericSubController::setMessageTreeModel(const MessageTree * messageTreeModel) { + m_messageTreeModel = (MessageTree *)messageTreeModel; +} + +void GenericSubController::viewWillAppear() { + m_selectableTableView.reloadData(); +} + +void GenericSubController::viewDidDisappear() { + m_selectableTableView.deselectTable(); +} + +StackViewController * GenericSubController::stackController() const { + return (StackViewController *)parentResponder(); +} + +} diff --git a/apps/settings/sub_menu/generic_sub_controller.h b/apps/settings/sub_menu/generic_sub_controller.h new file mode 100644 index 000000000..1325de9a7 --- /dev/null +++ b/apps/settings/sub_menu/generic_sub_controller.h @@ -0,0 +1,34 @@ +#ifndef SETTINGS_GENERIC_SUB_CONTROLLER_H +#define SETTINGS_GENERIC_SUB_CONTROLLER_H + +#include +#include "../settings_message_tree.h" + +namespace Settings { + +class GenericSubController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource { +public: + GenericSubController(Responder * parentResponder); + const char * title() override; + View * view() override; + void didBecomeFirstResponder() override; + bool handleEvent(Ion::Events::Event event) override; + int numberOfRows() override; + KDCoordinate rowHeight(int j) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) 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; +protected: + StackViewController * stackController() const; + constexpr static KDCoordinate k_topBottomMargin = 13; + SelectableTableView m_selectableTableView; + MessageTree * m_messageTreeModel; +}; + +} + +#endif diff --git a/apps/settings/language_controller.cpp b/apps/settings/sub_menu/language_controller.cpp similarity index 100% rename from apps/settings/language_controller.cpp rename to apps/settings/sub_menu/language_controller.cpp diff --git a/apps/settings/language_controller.h b/apps/settings/sub_menu/language_controller.h similarity index 87% rename from apps/settings/language_controller.h rename to apps/settings/sub_menu/language_controller.h index 92367959c..f552c9325 100644 --- a/apps/settings/language_controller.h +++ b/apps/settings/sub_menu/language_controller.h @@ -2,7 +2,7 @@ #define SETTINGS_LANGUAGE_CONTROLLER_H #include -#include "../shared/language_controller.h" +#include "../../shared/language_controller.h" namespace Settings { diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp new file mode 100644 index 000000000..680708a88 --- /dev/null +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -0,0 +1,127 @@ +#include "preferences_controller.h" +#include "../../global_preferences.h" +#include "../../apps_container.h" +#include +#include + +using namespace Poincare; + +namespace Settings { + +PreferencesController::PreferencesController(Responder * parentResponder) : + GenericSubController(parentResponder) +{ + for (int i = 0; i < k_totalNumberOfCell; i++) { + m_cells[i].setMessageFontSize(KDText::FontSize::Large); + } +} + +void PreferencesController::didBecomeFirstResponder() { + selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label())); + app()->setFirstResponder(&m_selectableTableView); +} + +bool PreferencesController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + /* 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(); + StackViewController * stack = stackController(); + stack->pop(); + return true; + } + return GenericSubController::handleEvent(event); +} + +HighlightCell * PreferencesController::reusableCell(int index, int type) { + assert(type == 0); + assert(index >= 0 && index < k_totalNumberOfCell); + return &m_cells[index]; +} + +int PreferencesController::reusableCellCount(int type) { + return k_totalNumberOfCell; +} + +Layout layoutForPreferences(I18n::Message message, int rowIndex) { + switch (message) { + case I18n::Message::AngleUnit: + return Layout(); + case I18n::Message::DisplayMode: + { + if (rowIndex == 0) { + return LayoutHelper::String("12.34", 5, KDText::FontSize::Small); + } + const char text[] = {'1','.', '2', '3', '4', Ion::Charset::Exponent, '1'}; + return LayoutHelper::String(text, sizeof(text), KDText::FontSize::Small); + } + case I18n::Message::EditionMode: + { + if (rowIndex == 0) { + return LayoutHelper::String("1+2/3", 5, KDText::FontSize::Small); + } + return HorizontalLayout( + LayoutHelper::String("1+", 2, KDText::FontSize::Small), + FractionLayout(LayoutHelper::String("2", 1, KDText::FontSize::Small), LayoutHelper::String("3", 1, KDText::FontSize::Small)) + ); + + } + case I18n::Message::ComplexFormat: + { + if (rowIndex == 0) { + const char text[] = {'a','+', Ion::Charset::IComplex, 'b'}; + return LayoutHelper::String(text, sizeof(text), KDText::FontSize::Small); + } + const char base[] = {'r', Ion::Charset::Exponential}; + const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta}; + return HorizontalLayout( + LayoutHelper::String(base, sizeof(base), KDText::FontSize::Small), + VerticalOffsetLayout(LayoutHelper::String(superscript, sizeof(superscript), KDText::FontSize::Small), VerticalOffsetLayoutNode::Type::Superscript) + ); + } + default: + assert(false); + return Layout(); + } +} + +void PreferencesController::willDisplayCellForIndex(HighlightCell * cell, int index) { + GenericSubController::willDisplayCellForIndex(cell, index); + MessageTableCellWithExpression * myCell = (MessageTableCellWithExpression *)cell; + myCell->setLayout(layoutForPreferences(m_messageTreeModel->label(), index)); +} + +void PreferencesController::setPreferenceWithValueIndex(I18n::Message message, int valueIndex) { + if (message == I18n::Message::AngleUnit) { + Preferences::sharedPreferences()->setAngleUnit((Preferences::AngleUnit)valueIndex); + } + if (message == I18n::Message::DisplayMode) { + Preferences::sharedPreferences()->setDisplayMode((Preferences::PrintFloatMode)valueIndex); + } + if (message == I18n::Message::EditionMode) { + Preferences::sharedPreferences()->setEditionMode((Preferences::EditionMode)valueIndex); + } + if (message == I18n::Message::ComplexFormat) { + Preferences::sharedPreferences()->setComplexFormat((Preferences::ComplexFormat)valueIndex); + } +} + +int PreferencesController::valueIndexForPreference(I18n::Message message) { + if (message == I18n::Message::AngleUnit) { + return (int)Preferences::sharedPreferences()->angleUnit(); + } + if (message == I18n::Message::DisplayMode) { + return (int)Preferences::sharedPreferences()->displayMode(); + } + if (message == I18n::Message::EditionMode) { + return (int)Preferences::sharedPreferences()->editionMode(); + } + if (message == I18n::Message::ComplexFormat) { + return (int)Preferences::sharedPreferences()->complexFormat(); + } + return 0; +} + +} diff --git a/apps/settings/sub_menu/preferences_controller.h b/apps/settings/sub_menu/preferences_controller.h new file mode 100644 index 000000000..05493caf0 --- /dev/null +++ b/apps/settings/sub_menu/preferences_controller.h @@ -0,0 +1,26 @@ +#ifndef SETTINGS_PREFERENCES_CONTROLLER_H +#define SETTINGS_PREFERENCES_CONTROLLER_H + +#include "generic_sub_controller.h" + +namespace Settings { + +class PreferencesController : public GenericSubController { +public: + PreferencesController(Responder * parentResponder); + void didBecomeFirstResponder() override; + bool handleEvent(Ion::Events::Event event) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; +protected: + constexpr static int k_totalNumberOfCell = 2; +private: + void setPreferenceWithValueIndex(I18n::Message message, int valueIndex); + int valueIndexForPreference(I18n::Message message); + MessageTableCellWithExpression m_cells[k_totalNumberOfCell]; +}; + +} + +#endif