[settings] Split SubController in several controllers: about_controller,

display_mode_controller, exam_mode_controller, preferences_controller
This commit is contained in:
Émilie Feral
2018-09-25 11:34:36 +02:00
committed by LeaNumworks
parent 1fb84e31e1
commit 1b9bfe6255
19 changed files with 612 additions and 404 deletions

View File

@@ -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/,\

View File

@@ -1,25 +0,0 @@
#include "helpers.h"
#include <poincare/layout_helper.h>
#include <ion/charset.h>
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)
);
}
}
}

View File

@@ -1,15 +0,0 @@
#ifndef SETTINGS_HELPERS_H
#define SETTINGS_HELPERS_H
#include <poincare.h>
namespace Settings {
namespace Helpers {
Poincare::Layout CartesianComplexFormat(KDText::FontSize fontSize);
Poincare::Layout PolarComplexFormat(KDText::FontSize fontSize);
}
}
#endif

View File

@@ -1,5 +1,4 @@
#include "main_controller.h"
#include "helpers.h"
#include "../global_preferences.h"
#include "../i18n.h"
#include <assert.h>
@@ -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() {

View File

@@ -2,9 +2,12 @@
#define SETTINGS_MAIN_CONTROLLER_H
#include <escher.h>
#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;
};
}

View File

@@ -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 <assert.h>
#include <cmath>
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<float>(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();
}
}

View File

@@ -1,51 +0,0 @@
#ifndef SETTINGS_SUB_CONTROLLER_H
#define SETTINGS_SUB_CONTROLLER_H
#include <escher.h>
#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

View File

@@ -0,0 +1,65 @@
#include "about_controller.h"
#include "../../apps_container.h"
#include <assert.h>
#include <cmath>
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]);
}
}

View File

@@ -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

View File

@@ -0,0 +1,85 @@
#include "display_mode_controller.h"
#include "../../shared/poincare_helpers.h"
#include <assert.h>
#include <cmath>
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<float>(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();
}
}

View File

@@ -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

View File

@@ -0,0 +1,52 @@
#include "exam_mode_controller.h"
#include "../../global_preferences.h"
#include "../../apps_container.h"
#include <assert.h>
#include <cmath>
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);
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,92 @@
#include "generic_sub_controller.h"
#include "../../apps_container.h"
#include <assert.h>
#include <cmath>
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();
}
}

View File

@@ -0,0 +1,34 @@
#ifndef SETTINGS_GENERIC_SUB_CONTROLLER_H
#define SETTINGS_GENERIC_SUB_CONTROLLER_H
#include <escher.h>
#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

View File

@@ -2,7 +2,7 @@
#define SETTINGS_LANGUAGE_CONTROLLER_H
#include <escher.h>
#include "../shared/language_controller.h"
#include "../../shared/language_controller.h"
namespace Settings {

View File

@@ -0,0 +1,127 @@
#include "preferences_controller.h"
#include "../../global_preferences.h"
#include "../../apps_container.h"
#include <assert.h>
#include <cmath>
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;
}
}

View File

@@ -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