Files
Upsilon/apps/shared/localization_controller.cpp
Gabriel Ozouf 62f598110e [apps/shared] Created LocalizationController
Classes LanguageController and CountryController have been fused into
one class LocalizationController, as they were very similar. This allows
the Settings and OnBoarding apps to only keep one controller for both
functions.

Change-Id: Ic23f300c37122249d34caaf18a633b5815240a78
2020-11-04 15:11:44 +01:00

177 lines
6.9 KiB
C++

#include "localization_controller.h"
#include <apps/apps_container.h>
#include <apps/global_preferences.h>
namespace Shared {
// ContentView
constexpr int LocalizationController::ContentView::k_numberOfCountryWarningLines;
LocalizationController::ContentView::ContentView(LocalizationController * controller, SelectableTableViewDataSource * dataSource) :
m_controller(controller),
m_selectableTableView(controller, controller, dataSource),
m_countryTitleMessage(KDFont::LargeFont, I18n::Message::Country)
{
m_countryTitleMessage.setBackgroundColor(Palette::WallScreen);
m_countryTitleMessage.setAlignment(0.5f, 0.5f);
I18n::Message textMessages[k_numberOfCountryWarningLines] = {I18n::Message::CountryWarning1, I18n::Message::CountryWarning2};
for (int i = 0; i < k_numberOfCountryWarningLines; i++) {
m_countryWarningLines[i].setBackgroundColor(Palette::WallScreen);
m_countryWarningLines[i].setFont(KDFont::SmallFont);
m_countryWarningLines[i].setAlignment(0.5f, 0.5f);
m_countryWarningLines[i].setMessage(textMessages[i]);
}
}
int LocalizationController::ContentView::numberOfSubviews() const {
return 1 + m_controller->shouldDisplayTitle() + k_numberOfCountryWarningLines * m_controller->shouldDisplayWarning();
}
View * LocalizationController::ContentView::subviewAtIndex(int i) {
assert(i < numberOfSubviews());
/* FIXME : This relies on the fact that the title is never displayed without the warning. */
switch (i) {
case 0:
return &m_selectableTableView;
case 3:
return &m_countryTitleMessage;
default:
return &m_countryWarningLines[i-1];
}
}
void LocalizationController::ContentView::modeHasChanged() {
layoutSubviews();
markRectAsDirty(bounds());
}
void LocalizationController::ContentView::layoutSubviews(bool force) {
KDCoordinate origin = 0;
if (m_controller->shouldDisplayTitle()) {
origin = layoutTitleSubview(force, Metric::CommonTopMargin + origin);
}
if (m_controller->shouldDisplayWarning()) {
origin = layoutWarningSubview(force, Metric::CommonTopMargin + origin) + Metric::CommonTopMargin;
}
origin = layoutTableSubview(force, origin);
assert(origin <= bounds().height());
}
KDCoordinate LocalizationController::ContentView::layoutTitleSubview(bool force, KDCoordinate verticalOrigin) {
KDCoordinate titleHeight = m_countryTitleMessage.font()->glyphSize().height();
m_countryTitleMessage.setFrame(KDRect(0, verticalOrigin, bounds().width(), titleHeight), force);
return verticalOrigin + titleHeight;
}
KDCoordinate LocalizationController::ContentView::layoutWarningSubview(bool force, KDCoordinate verticalOrigin) {
assert(k_numberOfCountryWarningLines > 0);
KDCoordinate textHeight = m_countryWarningLines[0].font()->glyphSize().height();
for (int i = 0; i < k_numberOfCountryWarningLines; i++) {
m_countryWarningLines[i].setFrame(KDRect(0, verticalOrigin, bounds().width(), textHeight), force);
verticalOrigin += textHeight;
}
return verticalOrigin;
}
KDCoordinate LocalizationController::ContentView::layoutTableSubview(bool force, KDCoordinate verticalOrigin) {
KDCoordinate tableHeight = std::min<KDCoordinate>(
bounds().height() - verticalOrigin,
m_selectableTableView.minimalSizeForOptimalDisplay().height());
m_selectableTableView.setFrame(KDRect(0, verticalOrigin, bounds().width(), tableHeight), force);
return verticalOrigin + tableHeight;
}
// LocalizationController
constexpr int LocalizationController::k_numberOfCells;
int LocalizationController::IndexOfCountry(I18n::Country country) {
/* As we want to order the countries alphabetically in the selected language,
* the index of a country in the table is the number of other countries that
* go before it in alphabetical order. */
int res = 0;
for (int c = 0; c < I18n::NumberOfCountries; c++) {
if (country != static_cast<I18n::Country>(c) && strcmp(I18n::translate(I18n::CountryNames[static_cast<uint8_t>(country)]), I18n::translate(I18n::CountryNames[c])) > 0) {
res += 1;
}
}
return res;
}
I18n::Country LocalizationController::CountryAtIndex(int i) {
/* This method is called for each country one after the other, so we could
* save a lot of computations by memoizing the IndexInTableOfCountry.
* However, since the number of countries is fairly small, and the country
* menu is unlikely to be used more than once or twice in the device's
* lifespan, we skim on memory usage here.*/
for (int c = 0; c < I18n::NumberOfCountries; c++) {
I18n::Country country = static_cast<I18n::Country>(c);
if (i == IndexOfCountry(country)) {
return country;
}
}
assert(false);
return (I18n::Country)0;
}
LocalizationController::LocalizationController(Responder * parentResponder, KDCoordinate verticalMargin, LocalizationController::Mode mode) :
ViewController(parentResponder),
m_contentView(this, this),
m_mode(mode)
{
selectableTableView()->setTopMargin((shouldDisplayWarning()) ? 0 : verticalMargin);
selectableTableView()->setBottomMargin(verticalMargin);
for (int i = 0; i < k_numberOfCells; i++) {
m_cells[i].setMessageFont(KDFont::LargeFont);
}
}
void LocalizationController::resetSelection() {
selectableTableView()->deselectTable();
selectCellAtLocation(0, (shouldResetSelectionToTopCell()) ? 0 : (mode() == Mode::Language) ? static_cast<int>(GlobalPreferences::sharedGlobalPreferences()->language()) : IndexOfCountry(GlobalPreferences::sharedGlobalPreferences()->country()));
}
void LocalizationController::setMode(LocalizationController::Mode mode) {
selectableTableView()->deselectTable();
m_mode = mode;
selectableTableView()->setTopMargin((shouldDisplayWarning()) ? 0 : selectableTableView()->bottomMargin());
m_contentView.modeHasChanged();
}
const char * LocalizationController::title() {
if (mode() == Mode::Language) {
return I18n::translate(I18n::Message::Language);
}
assert(mode() == Mode::Country);
return I18n::translate(I18n::Message::Country);
}
void LocalizationController::viewWillAppear() {
ViewController::viewWillAppear();
resetSelection();
selectableTableView()->reloadData();
}
bool LocalizationController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if (mode() == Mode::Language) {
GlobalPreferences::sharedGlobalPreferences()->setLanguage(static_cast<I18n::Language>(selectedRow()));
AppsContainer::sharedAppsContainer()->reloadTitleBarView();
} else {
assert(mode() == Mode::Country);
GlobalPreferences::sharedGlobalPreferences()->setCountry(CountryAtIndex(selectedRow()));
}
return true;
}
return false;
}
void LocalizationController::willDisplayCellForIndex(HighlightCell * cell, int index) {
if (mode() == Mode::Language) {
static_cast<MessageTableCell *>(cell)->setMessage(I18n::LanguageNames[index]);
return;
}
assert(mode() == Mode::Country);
static_cast<MessageTableCell *>(cell)->setMessage(I18n::CountryNames[static_cast<uint8_t>(CountryAtIndex(index))]);
}
}