[apps/shared] Add Discard confirmation pop-up

Change-Id: Ida3878894090ecfa99145618b8e1ff0bbcb4743a
This commit is contained in:
Hugo Saint-Vignes
2020-10-09 15:57:36 +02:00
committed by Émilie Feral
parent 91dc5eb5ec
commit bd23135198
22 changed files with 257 additions and 300 deletions

View File

@@ -329,7 +329,7 @@ bool AppsContainer::updateAlphaLock() {
return m_window.updateAlphaLock();
}
OnBoarding::PopUpController * AppsContainer::promptController() {
OnBoarding::PromptController * AppsContainer::promptController() {
if (k_promptNumberOfMessages == 0) {
return nullptr;
}

View File

@@ -16,7 +16,7 @@
#include "global_preferences.h"
#include "backlight_dimming_timer.h"
#include "shared/global_context.h"
#include "on_boarding/pop_up_controller.h"
#include "on_boarding/prompt_controller.h"
#include <ion/events.h>
@@ -45,7 +45,7 @@ public:
void displayExamModePopUp(GlobalPreferences::ExamMode mode);
void shutdownDueToLowBattery();
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
OnBoarding::PopUpController * promptController();
OnBoarding::PromptController * promptController();
void redrawWindow();
void activateExamMode(GlobalPreferences::ExamMode examMode);
// Exam pop-up controller delegate
@@ -72,7 +72,7 @@ private:
MathToolbox m_mathToolbox;
MathVariableBoxController m_variableBoxController;
ExamPopUpController m_examPopUpController;
OnBoarding::PopUpController m_promptController;
OnBoarding::PromptController m_promptController;
BatteryTimer m_batteryTimer;
SuspendTimer m_suspendTimer;
BacklightDimmingTimer m_backlightDimmingTimer;

View File

@@ -1,13 +1,29 @@
#include "exam_pop_up_controller.h"
#include "apps_container.h"
#include "exam_mode_configuration.h"
#include <apps/i18n.h>
#include "global_preferences.h"
#include <assert.h>
ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate) :
ViewController(nullptr),
m_contentView(this),
PopUpController(
k_numberOfLines,
Invocation(
[](void * context, void * sender) {
ExamPopUpController * controller = (ExamPopUpController *)context;
GlobalPreferences::ExamMode mode = controller->targetExamMode();
assert(mode != GlobalPreferences::ExamMode::Unknown);
GlobalPreferences::sharedGlobalPreferences()->setExamMode(mode);
AppsContainer * container = AppsContainer::sharedAppsContainer();
if (mode == GlobalPreferences::ExamMode::Off) {
Ion::LED::setColor(KDColorBlack);
Ion::LED::updateColorWithPlugAndCharge();
} else {
container->activateExamMode(mode);
}
container->refreshPreferences();
Container::activeApp()->dismissModalViewController();
return true;
}, this)
),
m_targetExamMode(GlobalPreferences::ExamMode::Unknown),
m_delegate(delegate)
{
@@ -15,11 +31,9 @@ ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate)
void ExamPopUpController::setTargetExamMode(GlobalPreferences::ExamMode mode) {
m_targetExamMode = mode;
m_contentView.setMessagesForExamMode(mode);
}
View * ExamPopUpController::view() {
return &m_contentView;
for (int i = 0; i < k_numberOfLines; i++) {
m_contentView.setMessage(i, ExamModeConfiguration::examModeActivationWarningMessage(mode, i));
}
}
void ExamPopUpController::viewDidDisappear() {
@@ -27,103 +41,3 @@ void ExamPopUpController::viewDidDisappear() {
m_delegate->examDeactivatingPopUpIsDismissed();
}
}
void ExamPopUpController::didBecomeFirstResponder() {
m_contentView.setSelectedButton(0);
}
bool ExamPopUpController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Left && m_contentView.selectedButton() == 1) {
m_contentView.setSelectedButton(0);
return true;
}
if (event == Ion::Events::Right && m_contentView.selectedButton() == 0) {
m_contentView.setSelectedButton(1);
return true;
}
return false;
}
ExamPopUpController::ContentView::ContentView(Responder * parentResponder) :
m_cancelButton(parentResponder, I18n::Message::Cancel, Invocation([](void * context, void * sender) {
Container::activeApp()->dismissModalViewController();
return true;
}, parentResponder), KDFont::SmallFont),
m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) {
ExamPopUpController * controller = (ExamPopUpController *)context;
GlobalPreferences::ExamMode mode = controller->targetExamMode();
assert(mode != GlobalPreferences::ExamMode::Unknown);
GlobalPreferences::sharedGlobalPreferences()->setExamMode(mode);
AppsContainer * container = AppsContainer::sharedAppsContainer();
if (mode == GlobalPreferences::ExamMode::Off) {
Ion::LED::setColor(KDColorBlack);
Ion::LED::updateColorWithPlugAndCharge();
} else {
container->activateExamMode(mode);
}
container->refreshPreferences();
Container::activeApp()->dismissModalViewController();
return true;
}, parentResponder), KDFont::SmallFont),
m_warningTextView(KDFont::SmallFont, I18n::Message::Warning, 0.5, 0.5, KDColorWhite, KDColorBlack),
m_messageTextViews{}
{
for (int i = 0; i < k_maxNumberOfLines; i++) {
m_messageTextViews[i].setFont(KDFont::SmallFont);
m_messageTextViews[i].setAlignment(0.5f, 0.5f);
m_messageTextViews[i].setBackgroundColor(KDColorBlack);
m_messageTextViews[i].setTextColor(KDColorWhite);
}
}
void ExamPopUpController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), KDColorBlack);
}
void ExamPopUpController::ContentView::setSelectedButton(int selectedButton) {
m_cancelButton.setHighlighted(selectedButton == 0);
m_okButton.setHighlighted(selectedButton == 1);
Container::activeApp()->setFirstResponder(selectedButton == 0 ? &m_cancelButton : &m_okButton);
}
int ExamPopUpController::ContentView::selectedButton() {
if (m_cancelButton.isHighlighted()) {
return 0;
}
return 1;
}
void ExamPopUpController::ContentView::setMessagesForExamMode(GlobalPreferences::ExamMode mode) {
for (int i = 0; i < k_maxNumberOfLines; i++) {
m_messageTextViews[i].setMessage(ExamModeConfiguration::examModeActivationWarningMessage(mode, i));
}
}
int ExamPopUpController::ContentView::numberOfSubviews() const {
return 6;
}
View * ExamPopUpController::ContentView::subviewAtIndex(int index) {
switch (index) {
case 0:
return &m_warningTextView;
case 4:
return &m_cancelButton;
case 5:
return &m_okButton;
default:
return &m_messageTextViews[index-1];
}
}
void ExamPopUpController::ContentView::layoutSubviews(bool force) {
KDCoordinate height = bounds().height();
KDCoordinate width = bounds().width();
KDCoordinate textHeight = KDFont::SmallFont->glyphSize().height();
m_warningTextView.setFrame(KDRect(0, k_topMargin, width, textHeight), force);
for (int i = 0; i < k_maxNumberOfLines; i++) {
m_messageTextViews[i].setFrame(KDRect(0, k_topMargin+k_paragraphHeight+(i+1)*textHeight, width, textHeight), force);
}
m_cancelButton.setFrame(KDRect(k_buttonMargin, height-k_buttonMargin-k_buttonHeight, (width-3*k_buttonMargin)/2, k_buttonHeight), force);
m_okButton.setFrame(KDRect(2*k_buttonMargin+(width-3*k_buttonMargin)/2, height-k_buttonMargin-k_buttonHeight, (width-3*k_buttonMargin)/2, k_buttonHeight), force);
}

View File

@@ -1,53 +1,20 @@
#ifndef APPS_EXAM_POP_UP_CONTROLLER_H
#define APPS_EXAM_POP_UP_CONTROLLER_H
#include <escher.h>
#include <escher/pop_up_controller.h>
#include "exam_pop_up_controller_delegate.h"
#include "global_preferences.h"
class HighContrastButton : public Button {
public:
using Button::Button;
KDColor highlightedBackgroundColor() const override { return Palette::YellowDark; }
};
class ExamPopUpController : public ViewController {
class ExamPopUpController : public PopUpController {
public:
ExamPopUpController(ExamPopUpControllerDelegate * delegate);
void setTargetExamMode(GlobalPreferences::ExamMode mode);
GlobalPreferences::ExamMode targetExamMode() const { return m_targetExamMode; }
// View Controller
View * view() override;
void viewDidDisappear() override;
// Responder
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
private:
class ContentView : public View {
public:
ContentView(Responder * parentResponder);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setSelectedButton(int selectedButton);
int selectedButton();
void setMessagesForExamMode(GlobalPreferences::ExamMode mode);
private:
constexpr static KDCoordinate k_buttonMargin = 10;
constexpr static KDCoordinate k_buttonHeight = 20;
constexpr static KDCoordinate k_topMargin = 12;
constexpr static KDCoordinate k_paragraphHeight = 20;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews(bool force = false) override;
HighContrastButton m_cancelButton;
HighContrastButton m_okButton;
MessageTextView m_warningTextView;
constexpr static int k_maxNumberOfLines = 3;
MessageTextView m_messageTextViews[k_maxNumberOfLines];
};
ContentView m_contentView;
constexpr static int k_numberOfLines = 3;
GlobalPreferences::ExamMode m_targetExamMode;
ExamPopUpControllerDelegate * m_delegate;
};
#endif

View File

@@ -1,116 +1,25 @@
#include "pop_up_controller.h"
#include <apps/i18n.h>
#include "../apps_container.h"
#include <assert.h>
#include <escher/app.h>
namespace HardwareTest {
PopUpController::PopUpController() :
ViewController(nullptr),
m_contentView(this)
::PopUpController(
4,
Invocation(
[](void * context, void * sender) {
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();
bool switched = appsContainer->switchTo(appsContainer->hardwareTestAppSnapshot());
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
return true;
}, this)
)
{
}
View * PopUpController::view() {
return &m_contentView;
}
void PopUpController::didBecomeFirstResponder() {
m_contentView.setSelectedButton(0);
}
bool PopUpController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Left && m_contentView.selectedButton() == 1) {
m_contentView.setSelectedButton(0);
return true;
}
if (event == Ion::Events::Right && m_contentView.selectedButton() == 0) {
m_contentView.setSelectedButton(1);
return true;
}
return false;
}
PopUpController::ContentView::ContentView(Responder * parentResponder) :
Responder(parentResponder),
m_cancelButton(this, I18n::Message::Cancel, Invocation([](void * context, void * sender) {
Container::activeApp()->dismissModalViewController();
return true;
}, this), KDFont::SmallFont),
m_okButton(this, I18n::Message::Ok, Invocation([](void * context, void * sender) {
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();
bool switched = appsContainer->switchTo(appsContainer->hardwareTestAppSnapshot());
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
return true;
}, this), KDFont::SmallFont),
m_warningTextView(KDFont::SmallFont, I18n::Message::Warning, 0.5, 0.5, KDColorWhite, KDColorBlack),
m_messageTextView1(KDFont::SmallFont, I18n::Message::HardwareTestLaunch1, 0.5, 0.5, KDColorWhite, KDColorBlack),
m_messageTextView2(KDFont::SmallFont, I18n::Message::HardwareTestLaunch2, 0.5, 0.5, KDColorWhite, KDColorBlack),
m_messageTextView3(KDFont::SmallFont, I18n::Message::HardwareTestLaunch3, 0.5, 0.5, KDColorWhite, KDColorBlack),
m_messageTextView4(KDFont::SmallFont, I18n::Message::HardwareTestLaunch4, 0.5, 0.5, KDColorWhite, KDColorBlack)
{
}
void PopUpController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), KDColorBlack);
}
void PopUpController::ContentView::setSelectedButton(int selectedButton) {
m_cancelButton.setHighlighted(selectedButton == 0);
m_okButton.setHighlighted(selectedButton == 1);
if (selectedButton == 0) {
Container::activeApp()->setFirstResponder(&m_cancelButton);
} else {
Container::activeApp()->setFirstResponder(&m_okButton);
}
}
int PopUpController::ContentView::selectedButton() {
if (m_cancelButton.isHighlighted()) {
return 0;
}
return 1;
}
int PopUpController::ContentView::numberOfSubviews() const {
return 7;
}
View * PopUpController::ContentView::subviewAtIndex(int index) {
switch (index) {
case 0:
return &m_warningTextView;
case 1:
return &m_messageTextView1;
case 2:
return &m_messageTextView2;
case 3:
return &m_messageTextView3;
case 4:
return &m_messageTextView4;
case 5:
return &m_cancelButton;
case 6:
return &m_okButton;
default:
assert(false);
return nullptr;
}
}
void PopUpController::ContentView::layoutSubviews(bool force) {
KDCoordinate height = bounds().height();
KDCoordinate width = bounds().width();
KDCoordinate textHeight = KDFont::SmallFont->glyphSize().height();
m_warningTextView.setFrame(KDRect(0, k_topMargin, width, textHeight), force);
m_messageTextView1.setFrame(KDRect(0, k_topMargin+k_paragraphHeight+textHeight, width, textHeight), force);
m_messageTextView2.setFrame(KDRect(0, k_topMargin+k_paragraphHeight+2*textHeight, width, textHeight), force);
m_messageTextView3.setFrame(KDRect(0, k_topMargin+k_paragraphHeight+3*textHeight, width, textHeight), force);
m_messageTextView4.setFrame(KDRect(0, k_topMargin+k_paragraphHeight+4*textHeight, width, textHeight), force);
m_cancelButton.setFrame(KDRect(k_buttonMargin, height-k_buttonMargin-k_buttonHeight, (width-3*k_buttonMargin)/2, k_buttonHeight), force);
m_okButton.setFrame(KDRect(2*k_buttonMargin+(width-3*k_buttonMargin)/2, height-k_buttonMargin-k_buttonHeight, (width-3*k_buttonMargin)/2, k_buttonHeight), force);
m_contentView.setMessage(0, I18n::Message::HardwareTestLaunch1);
m_contentView.setMessage(1, I18n::Message::HardwareTestLaunch2);
m_contentView.setMessage(2, I18n::Message::HardwareTestLaunch3);
m_contentView.setMessage(3, I18n::Message::HardwareTestLaunch4);
}
}

View File

@@ -1,43 +1,15 @@
#ifndef HARDWARE_TEST_POP_UP_CONTROLLER_H
#define HARDWARE_TEST_POP_UP_CONTROLLER_H
#ifndef POP_UP_CONTROLLER_H
#define POP_UP_CONTROLLER_H
#include <escher.h>
#include <escher/pop_up_controller.h>
namespace HardwareTest {
class PopUpController : public ViewController {
class PopUpController : public ::PopUpController {
public:
PopUpController();
View * view() override;
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
private:
class ContentView : public View, public Responder {
public:
ContentView(Responder * parentResponder);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setSelectedButton(int selectedButton);
int selectedButton();
private:
constexpr static KDCoordinate k_buttonMargin = 10;
constexpr static KDCoordinate k_buttonHeight = 20;
constexpr static KDCoordinate k_topMargin = 8;
constexpr static KDCoordinate k_paragraphHeight = 20;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews(bool force = false) override;
Button m_cancelButton;
Button m_okButton;
MessageTextView m_warningTextView;
MessageTextView m_messageTextView1;
MessageTextView m_messageTextView2;
MessageTextView m_messageTextView3;
MessageTextView m_messageTextView4;
};
ContentView m_contentView;
};
}
#endif

View File

@@ -3,7 +3,7 @@ app_on_boarding_src = $(addprefix apps/on_boarding/,\
logo_controller.cpp \
logo_view.cpp \
localization_controller.cpp \
pop_up_controller.cpp \
prompt_controller.cpp \
power_on_self_test.cpp \
)

View File

@@ -1,21 +1,21 @@
#include "pop_up_controller.h"
#include "prompt_controller.h"
#include "../apps_container.h"
#include <assert.h>
namespace OnBoarding {
PopUpController::MessageViewWithSkip::MessageViewWithSkip(I18n::Message * messages, KDColor * colors, uint8_t numberOfMessages) :
PromptController::MessageViewWithSkip::MessageViewWithSkip(I18n::Message * messages, KDColor * colors, uint8_t numberOfMessages) :
MessageView(messages, colors, numberOfMessages),
m_skipView(KDFont::SmallFont, I18n::Message::Skip, 1.0f, 0.5f),
m_okView()
{
}
int PopUpController::MessageViewWithSkip::numberOfSubviews() const {
int PromptController::MessageViewWithSkip::numberOfSubviews() const {
return MessageView::numberOfSubviews() + 2;
}
View * PopUpController::MessageViewWithSkip::subviewAtIndex(int index) {
View * PromptController::MessageViewWithSkip::subviewAtIndex(int index) {
uint8_t numberOfMainMessages = MessageView::numberOfSubviews();
if (index < numberOfMainMessages) {
return MessageView::subviewAtIndex(index);
@@ -30,7 +30,7 @@ View * PopUpController::MessageViewWithSkip::subviewAtIndex(int index) {
return nullptr;
}
void PopUpController::MessageViewWithSkip::layoutSubviews(bool force) {
void PromptController::MessageViewWithSkip::layoutSubviews(bool force) {
// Layout the main message
MessageView::layoutSubviews();
// Layout the "skip (OK)"
@@ -42,13 +42,13 @@ void PopUpController::MessageViewWithSkip::layoutSubviews(bool force) {
m_okView.setFrame(KDRect(width - okSize.width()-k_okMargin, height-okSize.height()-k_okMargin, okSize), force);
}
PopUpController::PopUpController(I18n::Message * messages, KDColor * colors, uint8_t numberOfMessages) :
PromptController::PromptController(I18n::Message * messages, KDColor * colors, uint8_t numberOfMessages) :
ViewController(nullptr),
m_messageViewWithSkip(messages, colors, numberOfMessages)
{
}
bool PopUpController::handleEvent(Ion::Events::Event event) {
bool PromptController::handleEvent(Ion::Events::Event event) {
if (event != Ion::Events::Back && event != Ion::Events::OnOff && event != Ion::Events::USBPlug && event != Ion::Events::USBEnumeration) {
Container::activeApp()->dismissModalViewController();
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();

View File

@@ -1,5 +1,5 @@
#ifndef ON_BOARDING_POP_UP_CONTROLLER_H
#define ON_BOARDING_POP_UP_CONTROLLER_H
#ifndef ON_PROMPT_CONTROLLER_H
#define ON_PROMPT_CONTROLLER_H
#include <escher.h>
#include <apps/i18n.h>
@@ -8,9 +8,9 @@
namespace OnBoarding {
class PopUpController : public ViewController {
class PromptController : public ViewController {
public:
PopUpController(I18n::Message * messages, KDColor * colors, uint8_t numberOfMessages);
PromptController(I18n::Message * messages, KDColor * colors, uint8_t numberOfMessages);
View * view() override { return &m_messageViewWithSkip; }
bool handleEvent(Ion::Events::Event event) override;
private:
@@ -34,4 +34,3 @@ private:
}
#endif

View File

@@ -11,6 +11,8 @@ Axis = "Achse"
Cancel = "Abbrechen"
ClearColumn = "Spalte löschen"
ColumnOptions = "Optionen der Spalte"
ConfirmDiscard1 = "Alle Änderungen werden verworfen"
ConfirmDiscard2 = ""
CopyColumnInList = "Die Spalte in einer Liste kopieren"
Country = "Land"
CountryCA = "Kanada "

View File

@@ -11,6 +11,8 @@ Axis = "Axes"
Cancel = "Cancel"
ClearColumn = "Clear column"
ColumnOptions = "Column options"
ConfirmDiscard1 = "All changes will be discarded"
ConfirmDiscard2 = ""
CopyColumnInList = "Export the column to a list"
Country = "Country"
CountryCA = "Canada "

View File

@@ -11,6 +11,8 @@ Axis = "Ejes"
Cancel = "Cancelar"
ClearColumn = "Borrar la columna"
ColumnOptions = "Opciones de la columna"
ConfirmDiscard1 = "Se perderán todos los cambios"
ConfirmDiscard2 = ""
CopyColumnInList = "Copiar la columna en una lista"
Country = "País"
CountryCA = "Canadá "

View File

@@ -11,6 +11,8 @@ Axis = "Axes"
Cancel = "Annuler"
ClearColumn = "Effacer la colonne"
ColumnOptions = "Options de la colonne"
ConfirmDiscard1 = "Toutes les modifications apportées"
ConfirmDiscard2 = "seront perdues"
CopyColumnInList = "Copier la colonne dans une liste"
Country = "Pays"
CountryCA = "Canada "

View File

@@ -11,6 +11,8 @@ Axis = "Assi"
Cancel = "Annullare"
ClearColumn = "Cancella la colonna"
ColumnOptions = "Opzioni colonna"
ConfirmDiscard1 = "Tutte le modifiche verranno perse"
ConfirmDiscard2 = ""
CopyColumnInList = "Copia colonna in una lista"
Country = "Paese"
CountryCA = "Canada "

View File

@@ -11,6 +11,8 @@ Axis = "Assen"
Cancel = "Annuleer"
ClearColumn = "Wis kolom"
ColumnOptions = "Kolomopties"
ConfirmDiscard1 = "Alle wijzigingen worden verwijderd"
ConfirmDiscard2 = ""
CopyColumnInList = "Exporteer de kolom naar een lijst"
Country = "Land"
CountryCA = "Canada "

View File

@@ -11,6 +11,8 @@ Axis = "Eixos"
Cancel = "Cancelar"
ClearColumn = "Excluir coluna"
ColumnOptions = "Opções de coluna"
ConfirmDiscard1 = "Todas as alterações serão perdidas"
ConfirmDiscard2 = ""
CopyColumnInList = "Copiar a coluna para uma lista"
Country = "País"
CountryCA = "Canadá "

View File

@@ -59,6 +59,7 @@ app_shared_src = $(addprefix apps/shared/,\
message_view.cpp \
ok_view.cpp \
parameter_text_field_delegate.cpp \
discard_pop_up_controller.cpp \
post_and_hardware_tests.cpp \
range_parameter_controller.cpp \
regular_table_view_data_source.cpp \

View File

@@ -0,0 +1,12 @@
#include "discard_pop_up_controller.h"
namespace Shared {
DiscardPopUpController::DiscardPopUpController(Invocation OkInvocation) :
PopUpController(2, OkInvocation)
{
m_contentView.setMessage(0, I18n::Message::ConfirmDiscard1);
m_contentView.setMessage(1, I18n::Message::ConfirmDiscard2);
}
}

View File

@@ -0,0 +1,15 @@
#ifndef SHARED_DISCARD_POP_UP_CONTROLLER_H
#define SHARED_DISCARD_POP_UP_CONTROLLER_H
#include <escher/pop_up_controller.h>
namespace Shared {
class DiscardPopUpController : public PopUpController {
public:
DiscardPopUpController(Invocation OkInvocation);
};
}
#endif

View File

@@ -51,6 +51,7 @@ escher_src += $(addprefix escher/src/,\
nested_menu_controller.cpp \
palette.cpp \
pointer_text_view.cpp \
pop_up_controller.cpp \
responder.cpp \
run_loop.cpp \
scroll_view.cpp \

View File

@@ -0,0 +1,46 @@
#ifndef ESCHER_POP_UP_CONTROLLER_H
#define ESCHER_POP_UP_CONTROLLER_H
#include <escher/invocation.h>
#include <apps/i18n.h>
class HighContrastButton : public Button {
public:
using Button::Button;
KDColor highlightedBackgroundColor() const override { return Palette::YellowDark; }
};
class PopUpController : public ViewController {
public:
PopUpController(int numberOfLines, Invocation OkInvocation);
View * view() override;
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
protected:
class ContentView : public View, public Responder {
public:
ContentView(Responder * parentResponder, int numberOfLines, Invocation okInvocation);
void drawRect(KDContext * ctx, KDRect rect) const override { ctx->fillRect(bounds(), KDColorBlack); }
void setSelectedButton(int selectedButton);
int selectedButton();
void setMessage(int index, I18n::Message message);
private:
constexpr static KDCoordinate k_buttonMargin = 10;
constexpr static KDCoordinate k_buttonHeight = 20;
constexpr static KDCoordinate k_topMargin = 8;
constexpr static KDCoordinate k_paragraphHeight = 20;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews(bool force = false) override;
HighContrastButton m_cancelButton;
HighContrastButton m_okButton;
MessageTextView m_warningTextView;
const int m_numberOfLines;
constexpr static int k_maxNumberOfLines = 4;
MessageTextView m_messageTextViews[k_maxNumberOfLines];
};
ContentView m_contentView;
};
#endif

View File

@@ -0,0 +1,107 @@
#include <escher/pop_up_controller.h>
#include <assert.h>
PopUpController::PopUpController(int numberOfLines, Invocation OkInvocation) :
ViewController(nullptr),
m_contentView(this, numberOfLines, OkInvocation)
{
}
View * PopUpController::view() {
return &m_contentView;
}
void PopUpController::didBecomeFirstResponder() {
m_contentView.setSelectedButton(0);
}
bool PopUpController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Left && m_contentView.selectedButton() == 1) {
m_contentView.setSelectedButton(0);
return true;
}
if (event == Ion::Events::Right && m_contentView.selectedButton() == 0) {
m_contentView.setSelectedButton(1);
return true;
}
return false;
}
PopUpController::ContentView::ContentView(Responder * parentResponder, int numberOfLines, Invocation okInvocation) :
Responder(parentResponder),
m_cancelButton(
this, I18n::Message::Cancel,
Invocation(
[](void * context, void * sender) {
Container::activeApp()->dismissModalViewController();
return true;
}, this),
KDFont::SmallFont),
m_okButton(this, I18n::Message::Ok, okInvocation, KDFont::SmallFont),
m_warningTextView(KDFont::SmallFont, I18n::Message::Warning, 0.5, 0.5, KDColorWhite, KDColorBlack),
m_numberOfLines(numberOfLines),
m_messageTextViews{}
{
assert(m_numberOfLines <= k_maxNumberOfLines && m_numberOfLines >= 0);
for (int i = 0; i < m_numberOfLines; i++) {
m_messageTextViews[i].setFont(KDFont::SmallFont);
m_messageTextViews[i].setAlignment(0.5f, 0.5f);
m_messageTextViews[i].setBackgroundColor(KDColorBlack);
m_messageTextViews[i].setTextColor(KDColorWhite);
}
}
void PopUpController::ContentView::setSelectedButton(int selectedButton) {
m_cancelButton.setHighlighted(selectedButton == 0);
m_okButton.setHighlighted(selectedButton == 1);
Container::activeApp()->setFirstResponder(selectedButton == 0 ? &m_cancelButton : &m_okButton);
}
int PopUpController::ContentView::selectedButton() {
return m_cancelButton.isHighlighted() ? 0 : 1;
}
void PopUpController::ContentView::setMessage(int index, I18n::Message message) {
assert(index >=0 && index < m_numberOfLines);
m_messageTextViews[index].setMessage(message);
}
int PopUpController::ContentView::numberOfSubviews() const {
// MessageTextViews + WarningTextView + CancelButton + OkButton
return m_numberOfLines + 3;
}
View * PopUpController::ContentView::subviewAtIndex(int index) {
int totalSubviews = numberOfSubviews();
if (index < 0 || index >= totalSubviews) {
assert(false);
return nullptr;
}
if (index == 0) {
return &m_warningTextView;
}
if (index == totalSubviews - 2) {
return &m_cancelButton;
}
if (index == totalSubviews - 1) {
return &m_okButton;
}
return &m_messageTextViews[index-1];
}
void PopUpController::ContentView::layoutSubviews(bool force) {
KDCoordinate height = bounds().height();
KDCoordinate width = bounds().width();
KDCoordinate textHeight = KDFont::SmallFont->glyphSize().height();
m_warningTextView.setFrame(KDRect(0, k_topMargin, width, textHeight), force);
// Offset to center text vertically
const int offset = (k_maxNumberOfLines - m_numberOfLines) / 2;
for (int i = 0; i < m_numberOfLines; i++) {
m_messageTextViews[i].setFrame(KDRect(0, k_topMargin + k_paragraphHeight + (i + 1 + offset) * textHeight, width, textHeight), force);
}
m_cancelButton.setFrame(KDRect(k_buttonMargin, height - k_buttonMargin - k_buttonHeight, (width - 3 * k_buttonMargin) / 2, k_buttonHeight), force);
m_okButton.setFrame(KDRect(2 * k_buttonMargin + (width - 3 * k_buttonMargin) / 2, height - k_buttonMargin - k_buttonHeight, (width - 3 * k_buttonMargin) / 2, k_buttonHeight), force);
}