#include "apps_container.h" #include "global_preferences.h" #include extern "C" { #include } using namespace Poincare; using namespace Shared; AppsContainer::AppsContainer() : Container(), m_window(AppsWindow()), m_emptyBatteryWindow(EmptyBatteryWindow()), m_homeApp(this), m_graphApp(this, &m_globalContext), m_probabilityApp(this), m_calculationApp(this, &m_globalContext), m_hardwareTestApp(this), m_regressionApp(this), m_sequenceApp(this, &m_globalContext), m_settingsApp(this), m_statisticsApp(this), m_globalContext(GlobalContext()), m_variableBoxController(&m_globalContext), m_examPopUpController(ExamPopUpController()), m_ledTimer(LedTimer()), m_batteryTimer(BatteryTimer(this)), m_USBTimer(USBTimer(this)), m_suspendTimer(SuspendTimer(this)), m_backlightDimmingTimer(BacklightDimmingTimer()) { refreshPreferences(); m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)); Expression::setCircuitBreaker(AppsContainer::poincareCircuitBreaker); } bool AppsContainer::poincareCircuitBreaker(const Poincare::Expression * e) { Ion::Keyboard::State state = Ion::Keyboard::scan(); return Ion::Keyboard::keyDown(Ion::Keyboard::Key::A6, state); } int AppsContainer::numberOfApps() { return k_numberOfApps; } App * AppsContainer::appAtIndex(int index) { static App * apps[] = { &m_homeApp, &m_calculationApp, &m_graphApp, &m_sequenceApp, &m_settingsApp, &m_statisticsApp, &m_probabilityApp, &m_regressionApp, }; assert(sizeof(apps)/sizeof(apps[0]) == k_numberOfApps); assert(index >= 0 && index < k_numberOfApps); return apps[index]; } App * AppsContainer::hardwareTestApp() { return &m_hardwareTestApp; } void AppsContainer::reset() { Clipboard::sharedClipboard()->reset(); } Context * AppsContainer::globalContext() { return &m_globalContext; } MathToolbox * AppsContainer::mathToolbox() { return &m_mathToolbox; } VariableBoxController * AppsContainer::variableBoxController() { return &m_variableBoxController; } void AppsContainer::suspend() { Ion::Power::suspend(); /* Ion::Power::suspend() completely shuts down the LCD controller. Therefore * the frame memory is lost. That's why we need to force a window redraw * upon wakeup, otherwise the screen is filled with noise. */ Ion::Backlight::setBrightness(Ion::Backlight::MaxBrightness); m_backlightDimmingTimer.reset(); window()->redraw(true); } bool AppsContainer::dispatchEvent(Ion::Events::Event event) { m_backlightDimmingTimer.reset(); m_suspendTimer.reset(); Ion::Backlight::setBrightness(Ion::Backlight::MaxBrightness); bool alphaLockWantsRedraw = m_window.updateAlphaLock(); // Home and Power buttons are not sent to apps. We handle them straight away. if (event == Ion::Events::Home && activeApp() != &m_hardwareTestApp) { switchTo(appAtIndex(0)); return true; } if (event == Ion::Events::OnOff && activeApp() != &m_hardwareTestApp) { suspend(); return true; } bool didProcessEvent = Container::dispatchEvent(event); if (!didProcessEvent && event == Ion::Events::Back) { switchTo(appAtIndex(0)); return true; } if (!didProcessEvent && alphaLockWantsRedraw) { window()->redraw(); return true; } return didProcessEvent; } void AppsContainer::switchTo(App * app) { m_window.setTitle(app->upperName()); Container::switchTo(app); } void AppsContainer::updateBatteryState() { if (m_window.updateBatteryLevel() || m_window.updateIsChargingState()) { m_window.redraw(); } } void AppsContainer::refreshPreferences() { m_window.refreshPreferences(); } void AppsContainer::displayExamModePopUp(bool activate, bool forceWindowRedraw) { m_examPopUpController.setActivatingExamMode(activate); activeApp()->displayModalViewController(&m_examPopUpController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpRightMargin, Metric::PopUpBottomMargin, Metric::PopUpLeftMargin); if (forceWindowRedraw) { m_window.redraw(true); } } void AppsContainer::shutdownDueToLowBattery() { while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) { m_emptyBatteryWindow.redraw(true); Ion::msleep(3000); Ion::Power::suspend(); } window()->redraw(true); } Window * AppsContainer::window() { return &m_window; } int AppsContainer::numberOfTimers() { return 4+(GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate); } Timer * AppsContainer::timerAtIndex(int i) { switch (i) { case 0: return &m_batteryTimer; case 1: return &m_USBTimer; case 2: return &m_suspendTimer; case 3: return &m_backlightDimmingTimer; case 4: return &m_ledTimer; default: assert(false); return nullptr; } }