From bd23135198bc816a15c6536a3299428c9414f6d3 Mon Sep 17 00:00:00 2001 From: Hugo Saint-Vignes Date: Fri, 9 Oct 2020 15:57:36 +0200 Subject: [PATCH] [apps/shared] Add Discard confirmation pop-up Change-Id: Ida3878894090ecfa99145618b8e1ff0bbcb4743a --- apps/apps_container.cpp | 2 +- apps/apps_container.h | 6 +- apps/exam_pop_up_controller.cpp | 132 +++--------------- apps/exam_pop_up_controller.h | 39 +----- apps/hardware_test/pop_up_controller.cpp | 121 ++-------------- apps/hardware_test/pop_up_controller.h | 36 +---- apps/on_boarding/Makefile | 2 +- ...p_controller.cpp => prompt_controller.cpp} | 14 +- ...op_up_controller.h => prompt_controller.h} | 9 +- apps/shared.de.i18n | 2 + apps/shared.en.i18n | 2 + apps/shared.es.i18n | 2 + apps/shared.fr.i18n | 2 + apps/shared.it.i18n | 2 + apps/shared.nl.i18n | 2 + apps/shared.pt.i18n | 2 + apps/shared/Makefile | 1 + apps/shared/discard_pop_up_controller.cpp | 12 ++ apps/shared/discard_pop_up_controller.h | 15 ++ escher/Makefile | 1 + escher/include/escher/pop_up_controller.h | 46 ++++++ escher/src/pop_up_controller.cpp | 107 ++++++++++++++ 22 files changed, 257 insertions(+), 300 deletions(-) rename apps/on_boarding/{pop_up_controller.cpp => prompt_controller.cpp} (76%) rename apps/on_boarding/{pop_up_controller.h => prompt_controller.h} (80%) create mode 100644 apps/shared/discard_pop_up_controller.cpp create mode 100644 apps/shared/discard_pop_up_controller.h create mode 100644 escher/include/escher/pop_up_controller.h create mode 100644 escher/src/pop_up_controller.cpp diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index ca3c1be1c..d8631f3ac 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -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; } diff --git a/apps/apps_container.h b/apps/apps_container.h index 482999103..e217f2495 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -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 @@ -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; diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 2f9dc5a3b..0bc5982ac 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -1,13 +1,29 @@ #include "exam_pop_up_controller.h" #include "apps_container.h" #include "exam_mode_configuration.h" -#include -#include "global_preferences.h" #include 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); -} diff --git a/apps/exam_pop_up_controller.h b/apps/exam_pop_up_controller.h index 694bf5ca2..192f38f47 100644 --- a/apps/exam_pop_up_controller.h +++ b/apps/exam_pop_up_controller.h @@ -1,53 +1,20 @@ #ifndef APPS_EXAM_POP_UP_CONTROLLER_H #define APPS_EXAM_POP_UP_CONTROLLER_H -#include +#include #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 - diff --git a/apps/hardware_test/pop_up_controller.cpp b/apps/hardware_test/pop_up_controller.cpp index 76afaa19b..ed785d24a 100644 --- a/apps/hardware_test/pop_up_controller.cpp +++ b/apps/hardware_test/pop_up_controller.cpp @@ -1,116 +1,25 @@ #include "pop_up_controller.h" -#include #include "../apps_container.h" -#include -#include 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); } } diff --git a/apps/hardware_test/pop_up_controller.h b/apps/hardware_test/pop_up_controller.h index b04724e95..35b74e265 100644 --- a/apps/hardware_test/pop_up_controller.h +++ b/apps/hardware_test/pop_up_controller.h @@ -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 +#include 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 - diff --git a/apps/on_boarding/Makefile b/apps/on_boarding/Makefile index b85d410e7..ffefeaf11 100644 --- a/apps/on_boarding/Makefile +++ b/apps/on_boarding/Makefile @@ -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 \ ) diff --git a/apps/on_boarding/pop_up_controller.cpp b/apps/on_boarding/prompt_controller.cpp similarity index 76% rename from apps/on_boarding/pop_up_controller.cpp rename to apps/on_boarding/prompt_controller.cpp index c63328b9e..e938a43a0 100644 --- a/apps/on_boarding/pop_up_controller.cpp +++ b/apps/on_boarding/prompt_controller.cpp @@ -1,21 +1,21 @@ -#include "pop_up_controller.h" +#include "prompt_controller.h" #include "../apps_container.h" #include 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(); diff --git a/apps/on_boarding/pop_up_controller.h b/apps/on_boarding/prompt_controller.h similarity index 80% rename from apps/on_boarding/pop_up_controller.h rename to apps/on_boarding/prompt_controller.h index f092e8853..b0ce7b615 100644 --- a/apps/on_boarding/pop_up_controller.h +++ b/apps/on_boarding/prompt_controller.h @@ -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 #include @@ -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 - diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index a8e653419..759482210 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -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 " diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index 5c0405168..b793d7dc7 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -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 " diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index 547919edd..0a60eb2fe 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -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á " diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index 5207340ab..d75eed312 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -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 " diff --git a/apps/shared.it.i18n b/apps/shared.it.i18n index bb1c7850a..339a4db65 100644 --- a/apps/shared.it.i18n +++ b/apps/shared.it.i18n @@ -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 " diff --git a/apps/shared.nl.i18n b/apps/shared.nl.i18n index da20649c4..b3d5ab0a1 100644 --- a/apps/shared.nl.i18n +++ b/apps/shared.nl.i18n @@ -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 " diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index 35cb54cbb..b0fd4ac0e 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -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á " diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 0c6ead3e7..2d68eee91 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -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 \ diff --git a/apps/shared/discard_pop_up_controller.cpp b/apps/shared/discard_pop_up_controller.cpp new file mode 100644 index 000000000..19a5aa550 --- /dev/null +++ b/apps/shared/discard_pop_up_controller.cpp @@ -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); +} + +} diff --git a/apps/shared/discard_pop_up_controller.h b/apps/shared/discard_pop_up_controller.h new file mode 100644 index 000000000..6c54d4945 --- /dev/null +++ b/apps/shared/discard_pop_up_controller.h @@ -0,0 +1,15 @@ +#ifndef SHARED_DISCARD_POP_UP_CONTROLLER_H +#define SHARED_DISCARD_POP_UP_CONTROLLER_H + +#include + +namespace Shared { + +class DiscardPopUpController : public PopUpController { +public: + DiscardPopUpController(Invocation OkInvocation); +}; + +} + +#endif diff --git a/escher/Makefile b/escher/Makefile index d0f7b49b5..421fbed1e 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -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 \ diff --git a/escher/include/escher/pop_up_controller.h b/escher/include/escher/pop_up_controller.h new file mode 100644 index 000000000..fd601c87e --- /dev/null +++ b/escher/include/escher/pop_up_controller.h @@ -0,0 +1,46 @@ +#ifndef ESCHER_POP_UP_CONTROLLER_H +#define ESCHER_POP_UP_CONTROLLER_H + +#include +#include + + +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 diff --git a/escher/src/pop_up_controller.cpp b/escher/src/pop_up_controller.cpp new file mode 100644 index 000000000..d1afbae29 --- /dev/null +++ b/escher/src/pop_up_controller.cpp @@ -0,0 +1,107 @@ +#include +#include + +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); +}