[escher] Only one app is on the heap at one time

Change-Id: I6c77601cb0cc883083a4dd05370ca543fa7951cc
This commit is contained in:
Émilie Feral
2017-05-16 17:02:06 +02:00
parent e9b2717b17
commit 06de0dd9db
38 changed files with 414 additions and 212 deletions

View File

@@ -20,44 +20,27 @@ AppsContainer::AppsContainer() :
m_batteryTimer(BatteryTimer(this)),
m_USBTimer(USBTimer(this)),
m_suspendTimer(SuspendTimer(this)),
m_backlightDimmingTimer(BacklightDimmingTimer()),
m_onBoardingApp(new OnBoarding::App(this, &m_updateController)),
m_homeApp(new Home::App(this)),
m_graphApp(new Graph::App(this, &m_globalContext)),
m_probabilityApp(new Probability::App(this)),
m_calculationApp(new Calculation::App(this, &m_globalContext)),
m_hardwareTestApp(new HardwareTest::App(this)),
m_regressionApp(new Regression::App(this)),
m_sequenceApp(new Sequence::App(this, &m_globalContext)),
m_settingsApp(new Settings::App(this)),
m_statisticsApp(new Statistics::App(this))
m_backlightDimmingTimer(BacklightDimmingTimer())
{
m_descriptors[0] = Home::App::buildDescriptor();
m_descriptors[1] = Calculation::App::buildDescriptor();
m_descriptors[2] = Graph::App::buildDescriptor();
m_descriptors[3] = Sequence::App::buildDescriptor();
m_descriptors[4] = Settings::App::buildDescriptor();
m_descriptors[5] = Statistics::App::buildDescriptor();
m_descriptors[6] = Probability::App::buildDescriptor();
m_descriptors[7] = Regression::App::buildDescriptor();
m_descriptors[8] = OnBoarding::App::buildDescriptor();
m_descriptors[9] = HardwareTest::App::buildDescriptor();
refreshPreferences();
m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height));
Poincare::Expression::setCircuitBreaker(AppsContainer::poincareCircuitBreaker);
}
AppsContainer::~AppsContainer() {
delete m_onBoardingApp;
m_onBoardingApp = nullptr;
delete m_homeApp;
m_homeApp = nullptr;
delete m_graphApp;
m_graphApp = nullptr;
delete m_probabilityApp;
m_probabilityApp = nullptr;
delete m_calculationApp;
m_calculationApp = nullptr;
delete m_hardwareTestApp;
m_hardwareTestApp = nullptr;
delete m_regressionApp;
m_regressionApp = nullptr;
delete m_sequenceApp;
m_sequenceApp = nullptr;
delete m_settingsApp;
m_settingsApp = nullptr;
delete m_statisticsApp;
m_statisticsApp = nullptr;
for (int i = 0; i < k_totalNumberOfApps; i++) {
delete m_descriptors[i];
}
}
bool AppsContainer::poincareCircuitBreaker(const Poincare::Expression * e) {
@@ -66,58 +49,25 @@ bool AppsContainer::poincareCircuitBreaker(const Poincare::Expression * e) {
}
int AppsContainer::numberOfApps() {
return k_numberOfApps;
return k_numberOfCommonApps;
}
App * AppsContainer::appAtIndex(int index) {
if (index == -1) {
return m_onBoardingApp;
}
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::Descriptor * AppsContainer::appDescriptorAtIndex(int index) {
assert(index >= 0 && index < k_numberOfCommonApps);
return m_descriptors[index];
}
App * AppsContainer::hardwareTestApp() {
return m_hardwareTestApp;
App::Descriptor * AppsContainer::hardwareTestAppDescriptor() {
return m_descriptors[k_totalNumberOfApps-1];
}
App::Descriptor * AppsContainer::onBoardingAppDescriptor() {
return m_descriptors[k_totalNumberOfApps - 2];
}
void AppsContainer::reset() {
Clipboard::sharedClipboard()->reset();
if (m_calculationApp != nullptr) {
delete m_calculationApp;
}
m_calculationApp = new Calculation::App(this, &m_globalContext);
if (m_graphApp != nullptr) {
delete m_graphApp;
}
m_graphApp = new Graph::App(this, &m_globalContext);
if (m_sequenceApp != nullptr) {
delete m_sequenceApp;
}
m_sequenceApp = new Sequence::App(this, &m_globalContext);
if (m_statisticsApp != nullptr) {
delete m_statisticsApp;
}
m_statisticsApp = new Statistics::App(this);
if (m_probabilityApp != nullptr) {
delete m_probabilityApp;
}
m_probabilityApp = new Probability::App(this);
if (m_regressionApp != nullptr) {
delete m_regressionApp;
}
m_regressionApp = new Regression::App(this);
//TODO: persitence->reset()
}
Poincare::Context * AppsContainer::globalContext() {
@@ -133,7 +83,7 @@ VariableBoxController * AppsContainer::variableBoxController() {
}
void AppsContainer::suspend(bool checkIfPowerKeyReleased) {
if (activeApp() != m_onBoardingApp && GlobalPreferences::sharedGlobalPreferences()->showUpdatePopUp()) {
if (activeApp()->descriptor() != onBoardingAppDescriptor() && GlobalPreferences::sharedGlobalPreferences()->showUpdatePopUp()) {
activeApp()->displayModalViewController(&m_updateController, 0.f, 0.f);
}
Ion::Power::suspend(checkIfPowerKeyReleased);
@@ -153,20 +103,20 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
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 && activeApp() != m_onBoardingApp) {
switchTo(appAtIndex(0));
if (event == Ion::Events::Home && activeApp()->descriptor() != onBoardingAppDescriptor() && activeApp()->descriptor() != hardwareTestAppDescriptor() && activeApp()->descriptor() != appDescriptorAtIndex(0)) {
switchTo(appDescriptorAtIndex(0));
return true;
}
if (event == Ion::Events::OnOff && activeApp() != m_hardwareTestApp) {
if (activeApp() == m_onBoardingApp) {
m_onBoardingApp->reinitOnBoarding();
if (event == Ion::Events::OnOff && activeApp()->descriptor() != hardwareTestAppDescriptor()) {
if (activeApp()->descriptor() == onBoardingAppDescriptor()) {
((OnBoarding::App *)activeApp())->reinitOnBoarding();
}
suspend(true);
return true;
}
bool didProcessEvent = Container::dispatchEvent(event);
if (!didProcessEvent && event == Ion::Events::Back) {
switchTo(appAtIndex(0));
switchTo(appDescriptorAtIndex(0));
return true;
}
if (!didProcessEvent && alphaLockWantsRedraw) {
@@ -176,18 +126,18 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
return didProcessEvent;
}
void AppsContainer::switchTo(App * app) {
if (app == hardwareTestApp() || app == m_onBoardingApp) {
void AppsContainer::switchTo(App::Descriptor * descriptor) {
if (descriptor == hardwareTestAppDescriptor() || descriptor == onBoardingAppDescriptor()) {
m_window.hideTitleBarView(true);
} else {
m_window.hideTitleBarView(false);
}
if (app) {
m_window.setTitle(app->upperName());
if (descriptor) {
m_window.setTitle(descriptor->upperName());
}
Container::switchTo(app);
if (activeApp() == m_onBoardingApp) {
m_onBoardingApp->reinitOnBoarding();
Container::switchTo(descriptor);
if (activeApp()->descriptor() == onBoardingAppDescriptor()) {
((OnBoarding::App *)activeApp())->reinitOnBoarding();
}
}
@@ -219,32 +169,24 @@ void AppsContainer::reloadTitleBar() {
m_window.reloadTitleBar();
}
UpdateController * AppsContainer::updatePopUpController() {
return &m_updateController;
}
Window * AppsContainer::window() {
return &m_window;
}
int AppsContainer::numberOfTimers() {
return 4+(GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) + (m_onBoardingApp->hasTimer());
bool onBoardingTimer = activeApp()->descriptor() == onBoardingAppDescriptor() && ((OnBoarding::App *)activeApp())->hasTimer();
return 4+(GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) + onBoardingTimer;
}
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:
if (m_onBoardingApp->hasTimer() == 1) {
return m_onBoardingApp->timer();
}
case 5:
return &m_ledTimer;
default:
assert(false);
return nullptr;
bool onBoardingTimer = activeApp()->descriptor() == onBoardingAppDescriptor() && ((OnBoarding::App *)activeApp())->hasTimer();
if (onBoardingTimer && i == 4) {
return ((OnBoarding::App *)activeApp())->timer();
}
Timer * timers[6] = {&m_batteryTimer, &m_USBTimer, &m_suspendTimer, &m_backlightDimmingTimer, &m_ledTimer, &m_ledTimer};
return timers[i];
}

View File

@@ -42,28 +42,30 @@ public:
AppsContainer(AppsContainer&& other) = delete;
AppsContainer& operator=(const AppsContainer& other) = delete;
AppsContainer& operator=(AppsContainer&& other) = delete;
/* */
static bool poincareCircuitBreaker(const Poincare::Expression * e);
int numberOfApps();
App * appAtIndex(int index);
App * hardwareTestApp();
App::Descriptor * appDescriptorAtIndex(int index);
App::Descriptor * hardwareTestAppDescriptor();
App::Descriptor * onBoardingAppDescriptor();
void reset();
Poincare::Context * globalContext();
MathToolbox * mathToolbox();
VariableBoxController * variableBoxController();
void suspend(bool checkIfPowerKeyReleased = false);
virtual bool dispatchEvent(Ion::Events::Event event) override;
void switchTo(App * app) override;
void switchTo(App::Descriptor * descriptor) override;
void updateBatteryState();
void refreshPreferences();
void displayExamModePopUp(bool activate);
void shutdownDueToLowBattery();
void reloadTitleBar();
UpdateController * updatePopUpController();
private:
Window * window() override;
int numberOfTimers() override;
Timer * timerAtIndex(int i) override;
static constexpr int k_numberOfApps = 8;
static constexpr int k_numberOfCommonApps = 8;
static constexpr int k_totalNumberOfApps = 2+k_numberOfCommonApps;
AppsWindow m_window;
EmptyBatteryWindow m_emptyBatteryWindow;
#if USE_PIC_VIEW_APP
@@ -79,16 +81,7 @@ private:
USBTimer m_USBTimer;
SuspendTimer m_suspendTimer;
BacklightDimmingTimer m_backlightDimmingTimer;
OnBoarding::App * m_onBoardingApp;
Home::App * m_homeApp;
Graph::App * m_graphApp;
Probability::App * m_probabilityApp;
Calculation::App * m_calculationApp;
HardwareTest::App * m_hardwareTestApp;
Regression::App * m_regressionApp;
Sequence::App * m_sequenceApp;
Settings::App * m_settingsApp;
Statistics::App * m_statisticsApp;
App::Descriptor * m_descriptors[k_totalNumberOfApps];
};
#endif

View File

@@ -1,4 +1,5 @@
#include "app.h"
#include "../apps_container.h"
#include "calculation_icon.h"
#include "../i18n.h"
using namespace Poincare;
@@ -7,15 +8,35 @@ using namespace Shared;
namespace Calculation {
App::App(Container * container, Context * context) :
TextFieldDelegateApp(container, &m_editExpressionController, I18n::Message::CalculApp, I18n::Message::CalculAppCapital, ImageStore::CalculationIcon),
m_localContext((GlobalContext *)context, &m_calculationStore),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::CalculApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::CalculAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::CalculationIcon;
}
App::App(Container * container, Descriptor * descriptor) :
TextFieldDelegateApp(container, &m_editExpressionController, descriptor),
m_localContext((GlobalContext *)((AppsContainer *)container)->globalContext(), &m_calculationStore),
m_calculationStore(),
m_historyController(&m_editExpressionController, &m_calculationStore),
m_editExpressionController(&m_modalViewController, &m_historyController, &m_calculationStore)
{
}
App::App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
Context * App::localContext() {
return &m_localContext;
}

View File

@@ -11,9 +11,17 @@ namespace Calculation {
class App : public Shared::TextFieldDelegateApp {
public:
App(Container * container, Poincare::Context * context);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
Poincare::Context * localContext() override;
private:
App(Container * container, Descriptor * descriptor);
LocalContext m_localContext;
CalculationStore m_calculationStore;
HistoryController m_historyController;

View File

@@ -1,4 +1,5 @@
#include "app.h"
#include "../apps_container.h"
#include "graph_icon.h"
#include "../i18n.h"
@@ -7,10 +8,26 @@ using namespace Shared;
namespace Graph {
App::App(Container * container, Context * context) :
FunctionApp(container, &m_inputViewController, I18n::Message::FunctionApp, I18n::Message::FunctionAppCapital, ImageStore::GraphIcon),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::FunctionApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::FunctionAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::GraphIcon;
}
App::App(Container * container, Descriptor * descriptor) :
FunctionApp(container, &m_inputViewController, descriptor),
m_functionStore(),
m_xContext('x', context),
m_xContext('x',((AppsContainer *)container)->globalContext()),
m_listController(&m_listFooter, &m_functionStore, &m_listHeader, &m_listFooter),
m_listFooter(&m_listHeader, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey),
m_listHeader(&m_listStackViewController, &m_listFooter, &m_listController),
@@ -28,6 +45,10 @@ App::App(Container * container, Context * context) :
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
InputViewController * App::inputViewController() {
return &m_inputViewController;
}

View File

@@ -13,7 +13,14 @@ namespace Graph {
class App : public Shared::FunctionApp {
public:
App(Container * container, Poincare::Context * context);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
InputViewController * inputViewController() override;
/* This local context can parse x. However, it always stores NAN
* as x value. When we need to evaluate expression with a specific x value, we
@@ -21,6 +28,7 @@ public:
* weird x values after drawing curves or displaying the value table. */
Poincare::Context * localContext() override;
private:
App(Container * container, Descriptor * descriptor);
CartesianFunctionStore m_functionStore;
Poincare::VariableContext m_xContext;
ListController m_listController;

View File

@@ -7,10 +7,18 @@ extern "C" {
namespace HardwareTest {
App::App(AppsContainer * container) :
::App(container, &m_keyboardController),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
App::App(Container * container, Descriptor * descriptor) :
::App(container, &m_keyboardController, descriptor),
m_keyboardController(&m_modalViewController)
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
}

View File

@@ -8,10 +8,15 @@ class AppsContainer;
namespace HardwareTest {
class App : public ::App {
class App : public ::App {
public:
App(AppsContainer * container);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
};
static Descriptor * buildDescriptor();
private:
App(Container * container, Descriptor * descriptor);
KeyboardController m_keyboardController;
};

View File

@@ -20,7 +20,7 @@ bool ColorController::handleEvent(Ion::Events::Event event) {
m_view.setColors(nextColor(m_view.fillColor()), nextColor(m_view.outlineColor()));
if (m_view.fillColor() == KDColorBlack) {
AppsContainer * container = (AppsContainer *)app()->container();
container->switchTo(container->appAtIndex(0));
container->switchTo(container->appDescriptorAtIndex(0));
}
return true;
}

View File

@@ -8,10 +8,26 @@ extern "C" {
namespace Home {
App::App(AppsContainer * container) :
::App(container, &m_controller, I18n::Message::Apps, I18n::Message::AppsCapital, nullptr, I18n::Message::Warning),
m_controller(&m_modalViewController, container)
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::Apps;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::AppsCapital;
}
App::App(Container * container, Descriptor * descriptor) :
::App(container, &m_controller, descriptor, I18n::Message::Warning),
m_controller(&m_modalViewController, (AppsContainer *)container)
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
}

View File

@@ -10,8 +10,15 @@ namespace Home {
class App : public ::App {
public:
App(AppsContainer * container);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
};
static Descriptor * buildDescriptor();
private:
App(Container * container, Descriptor * descriptor);
Controller m_controller;
};

View File

@@ -31,9 +31,9 @@ void AppCell::layoutSubviews() {
m_nameView.setFrame(KDRect((bounds().width()-nameSize.width())/2-k_nameWidthMargin, bounds().height()-nameSize.height() - 2*k_nameHeightMargin, nameSize.width()+2*k_nameWidthMargin, nameSize.height()+2*k_nameHeightMargin));
}
void AppCell::setApp(::App * app) {
m_iconView.setImage(app->icon());
m_nameView.setMessage(app->name());
void AppCell::setAppDescriptor(::App::Descriptor * descriptor) {
m_iconView.setImage(descriptor->icon());
m_nameView.setMessage(descriptor->name());
layoutSubviews();
}

View File

@@ -16,7 +16,7 @@ public:
void setVisible(bool visible);
void reloadCell() override;
void setApp(::App * app);
void setAppDescriptor(::App::Descriptor * appDescriptor);
private:
static constexpr KDCoordinate k_iconMargin = 18;
static constexpr KDCoordinate k_iconWidth = 55;

View File

@@ -47,7 +47,7 @@ Controller::Controller(Responder * parentResponder, ::AppsContainer * container)
bool Controller::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
m_container->switchTo(m_container->appAtIndex(selectedRow()*k_numberOfColumns+selectedColumn()+1));
m_container->switchTo(m_container->appDescriptorAtIndex(selectedRow()*k_numberOfColumns+selectedColumn()+1));
return true;
}
return false;
@@ -101,8 +101,8 @@ void Controller::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) {
appCell->setVisible(false);
} else {
appCell->setVisible(true);
::App * app = m_container->appAtIndex((j*k_numberOfColumns+i)+1);
appCell->setApp(app);
::App::Descriptor * descriptor = m_container->appDescriptorAtIndex((j*k_numberOfColumns+i)+1);
appCell->setAppDescriptor(descriptor);
}
}

View File

@@ -3,7 +3,7 @@
AppsContainer container;
void ion_app() {
container.switchTo(container.appAtIndex(-1));
container.switchTo(container.onBoardingAppDescriptor());
container.run();
container.switchTo(nullptr);
}

View File

@@ -1,14 +1,23 @@
#include "app.h"
#include "../apps_container.h"
namespace OnBoarding {
App::App(Container * container, UpdateController * updateController) :
::App(container, &m_languageController),
m_languageController(&m_modalViewController, &m_logoController, updateController),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
App::App(Container * container, Descriptor * descriptor) :
::App(container, &m_languageController, descriptor),
m_languageController(&m_modalViewController, &m_logoController, ((AppsContainer *)container)->updatePopUpController()),
m_logoController()
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
void App::reinitOnBoarding() {
m_languageController.reinitOnBoarding();
}

View File

@@ -10,11 +10,16 @@ namespace OnBoarding {
class App : public ::App {
public:
App(Container * container, UpdateController * updateController);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
};
static Descriptor * buildDescriptor();
void reinitOnBoarding();
bool hasTimer();
Timer * timer();
private:
App(Container * container, Descriptor * descriptor);
LanguageController m_languageController;
LogoController m_logoController;
};

View File

@@ -16,7 +16,9 @@ bool UpdateController::handleEvent(Ion::Events::Event event) {
if (event != Ion::Events::Back) {
app()->dismissModalViewController();
AppsContainer * appsContainer = (AppsContainer *)app()->container();
appsContainer->switchTo(appsContainer->appAtIndex(0));
if (appsContainer->activeApp()->descriptor() == appsContainer->onBoardingAppDescriptor()) {
appsContainer->switchTo(appsContainer->appDescriptorAtIndex(0));
}
return true;
}
return false;

View File

@@ -5,11 +5,31 @@ using namespace Shared;
namespace Probability {
App::App(Container * container) :
TextFieldDelegateApp(container, &m_stackViewController, I18n::Message::ProbaApp, I18n::Message::ProbaAppCapital, ImageStore::ProbabilityIcon),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::ProbaApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::ProbaAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::ProbabilityIcon;
}
App::App(Container * container, Descriptor * descriptor) :
TextFieldDelegateApp(container, &m_stackViewController, descriptor),
m_lawController(nullptr),
m_stackViewController(&m_modalViewController, &m_lawController)
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
}

View File

@@ -10,8 +10,16 @@ namespace Probability {
class App : public Shared::TextFieldDelegateApp {
public:
App(Container * container);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
private:
App(Container * container, Descriptor * descriptor);
LawController m_lawController;
StackViewController m_stackViewController;
};

View File

@@ -6,8 +6,24 @@ using namespace Shared;
namespace Regression {
App::App(Container * container) :
TextFieldDelegateApp(container, &m_tabViewController, I18n::Message::RegressionApp, I18n::Message::RegressionAppCapital, ImageStore::RegressionIcon),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::RegressionApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::RegressionAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::RegressionIcon;
}
App::App(Container * container, Descriptor * descriptor) :
TextFieldDelegateApp(container, &m_tabViewController, descriptor),
m_store(),
m_calculationController(&m_calculationAlternateEmptyViewController, &m_calculationHeader, &m_store),
m_calculationAlternateEmptyViewController(&m_calculationHeader, &m_calculationController, &m_calculationController),
@@ -23,4 +39,8 @@ App::App(Container * container) :
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
}

View File

@@ -12,8 +12,16 @@ namespace Regression {
class App : public Shared::TextFieldDelegateApp {
public:
App(Container * container);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
private:
App(Container * container, Descriptor * descriptor);
Store m_store;
CalculationController m_calculationController;
AlternateEmptyViewController m_calculationAlternateEmptyViewController;

View File

@@ -1,14 +1,31 @@
#include "app.h"
#include "../apps_container.h"
#include "sequence_icon.h"
using namespace Poincare;
namespace Sequence {
App::App(Container * container, Context * context) :
FunctionApp(container, &m_inputViewController, I18n::Message::SequenceApp, I18n::Message::SequenceAppCapital, ImageStore::SequenceIcon),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::SequenceApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::SequenceAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::SequenceIcon;
}
App::App(Container * container, Descriptor * descriptor) :
FunctionApp(container, &m_inputViewController, descriptor),
m_sequenceStore(),
m_nContext(context),
m_nContext(((AppsContainer *)container)->globalContext()),
m_listController(&m_listFooter, &m_sequenceStore, &m_listHeader, &m_listFooter),
m_listFooter(&m_listHeader, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey),
m_listHeader(nullptr, &m_listFooter, &m_listController),
@@ -26,6 +43,10 @@ App::App(Container * container, Context * context) :
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
InputViewController * App::inputViewController() {
return &m_inputViewController;
}

View File

@@ -14,11 +14,19 @@ namespace Sequence {
class App : public Shared::FunctionApp {
public:
App(Container * container, Poincare::Context * context);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
InputViewController * inputViewController() override;
Poincare::Context * localContext() override;
const char * XNT() override;
private:
App(Container * container, Descriptor * descriptor);
SequenceStore m_sequenceStore;
LocalContext m_nContext;
ListController m_listController;

View File

@@ -4,11 +4,31 @@
namespace Settings {
App::App(Container * container) :
::App(container, &m_stackViewController, I18n::Message::SettingsApp, I18n::Message::SettingsAppCapital, ImageStore::SettingsIcon, I18n::Message::Warning),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::SettingsApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::SettingsAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::SettingsIcon;
}
App::App(Container * container, Descriptor * descriptor) :
::App(container, &m_stackViewController, descriptor, I18n::Message::Warning),
m_mainController(&m_stackViewController),
m_stackViewController(&m_modalViewController, &m_mainController)
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
}

View File

@@ -8,8 +8,16 @@ namespace Settings {
class App : public ::App {
public:
App(Container * container);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
private:
App(Container * container, Descriptor * descriptor);
MainController m_mainController;
StackViewController m_stackViewController;
};

View File

@@ -60,7 +60,7 @@ bool SubController::handleEvent(Ion::Events::Event event) {
* clicking on '6' on the serial number row. */
if (event == Ion::Events::Six && m_nodeModel->label() == I18n::Message::About && selectedRow() == 1) {
AppsContainer * appsContainer = (AppsContainer *)app()->container();
appsContainer->switchTo(appsContainer->hardwareTestApp());
appsContainer->switchTo(appsContainer->hardwareTestAppDescriptor());
return true;
}
if (event == Ion::Events::OK || event == Ion::Events::EXE) {

View File

@@ -5,8 +5,8 @@ using namespace Poincare;
namespace Shared {
FunctionApp::FunctionApp(Container * container, ViewController * rootViewController, I18n::Message name, I18n::Message upperName, const Image * icon) :
TextFieldDelegateApp(container, rootViewController, name, upperName, icon)
FunctionApp::FunctionApp(Container * container, ViewController * rootViewController, Descriptor * descriptor) :
TextFieldDelegateApp(container, rootViewController, descriptor)
{
}

View File

@@ -10,7 +10,7 @@ namespace Shared {
class FunctionApp : public TextFieldDelegateApp {
public:
FunctionApp(Container * container, ViewController * rootViewController, I18n::Message name = (I18n::Message)0, I18n::Message upperName = (I18n::Message)0, const Image * icon = nullptr);
FunctionApp(Container * container, ViewController * rootViewController, Descriptor * descriptor);
virtual InputViewController * inputViewController() = 0;
void willBecomeInactive() override;
};

View File

@@ -7,8 +7,8 @@ using namespace Poincare;
namespace Shared {
TextFieldDelegateApp::TextFieldDelegateApp(Container * container, ViewController * rootViewController, I18n::Message name, I18n::Message upperName, const Image * icon) :
::App(container, rootViewController, name, upperName, icon, I18n::Message::Warning),
TextFieldDelegateApp::TextFieldDelegateApp(Container * container, ViewController * rootViewController, Descriptor * descriptor) :
::App(container, rootViewController, descriptor, I18n::Message::Warning),
TextFieldDelegate()
{
}

View File

@@ -11,7 +11,7 @@ namespace Shared {
class TextFieldDelegateApp : public ::App, public TextFieldDelegate {
public:
TextFieldDelegateApp(Container * container, ViewController * rootViewController, I18n::Message name = (I18n::Message)0, I18n::Message upperName = (I18n::Message)0, const Image * icon = nullptr);
TextFieldDelegateApp(Container * container, ViewController * rootViewController, Descriptor * descriptor);
virtual Poincare::Context * localContext();
AppsContainer * container();
virtual const char * XNT();

View File

@@ -5,8 +5,24 @@ using namespace Shared;
namespace Statistics {
App::App(Container * container) :
TextFieldDelegateApp(container, &m_tabViewController, I18n::Message::StatsApp, I18n::Message::StatsAppCapital, ImageStore::StatIcon),
App * App::Descriptor::build(Container * container) {
return new App(container, this);
}
I18n::Message App::Descriptor::name() {
return I18n::Message::StatsApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::StatsAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::StatIcon;
}
App::App(Container * container, Descriptor * descriptor) :
TextFieldDelegateApp(container, &m_tabViewController, descriptor),
m_store(),
m_calculationController(&m_calculationAlternateEmptyViewController, &m_calculationHeader, &m_store),
m_calculationAlternateEmptyViewController(&m_calculationHeader, &m_calculationController, &m_calculationController),
@@ -25,4 +41,8 @@ App::App(Container * container) :
{
}
App::Descriptor * App::buildDescriptor() {
return new App::Descriptor();
}
}

View File

@@ -13,8 +13,16 @@ namespace Statistics {
class App : public Shared::TextFieldDelegateApp {
public:
App(Container * container);
class Descriptor : public ::App::Descriptor {
public:
App * build(Container * container) override;
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
static Descriptor * buildDescriptor();
private:
App(Container * container, Descriptor * descriptor);
Store m_store;
CalculationController m_calculationController;
AlternateEmptyViewController m_calculationAlternateEmptyViewController;

View File

@@ -21,9 +21,18 @@ class Container;
class App : public Responder {
public:
constexpr static uint8_t Magic = 0xA8;
App(Container * container, ViewController * rootViewController, I18n::Message name = (I18n::Message)0, I18n::Message upperName = (I18n::Message)0, const Image * icon = nullptr, I18n::Message warningMessage = (I18n::Message)0);
class Descriptor {
public:
virtual App * build(Container * container) = 0;
virtual I18n::Message name();
virtual I18n::Message upperName();
virtual const Image * icon();
};
/* Each App subclass must implement
* static Descriptor * builDescriptor(); */
Descriptor * descriptor();
virtual ~App() = default;
constexpr static uint8_t Magic = 0xA8;
void setFirstResponder(Responder * responder);
Responder * firstResponder();
bool processEvent(Ion::Events::Event event);
@@ -32,23 +41,19 @@ public:
void dismissModalViewController();
void displayWarning(I18n::Message warningMessage);
const Container * container() const;
I18n::Message name();
I18n::Message upperName();
const Image * icon();
uint8_t m_magic; // Poor man's RTTI
virtual void didBecomeActive(Window * window);
virtual void willBecomeInactive();
protected:
App(Container * container, ViewController * rootViewController, Descriptor * descriptor, I18n::Message warningMessage = (I18n::Message)0);
ModalViewController m_modalViewController;
private:
Descriptor * m_descriptor;
Container * m_container;
Responder * m_firstResponder;
WarningController m_warningController;
I18n::Message m_name;
I18n::Message m_upperName;
const Image * m_icon;
};
#endif

View File

@@ -18,10 +18,15 @@
class Container : public RunLoop {
public:
Container();
virtual ~Container();
Container(const Container& other) = delete;
Container(Container&& other) = delete;
Container& operator=(const Container& other) = delete;
Container& operator=(Container&& other) = delete;
void run();
App * activeApp();
virtual bool dispatchEvent(Ion::Events::Event event) override;
virtual void switchTo(App * app);
virtual void switchTo(App::Descriptor * descriptor);
protected:
virtual Window * window() = 0;
void windowRedraw() override;

View File

@@ -4,19 +4,33 @@ extern "C" {
#include <assert.h>
}
App::App(Container * container, ViewController * rootViewController, I18n::Message name, I18n::Message upperName, const Image * icon, I18n::Message warningMessage) :
I18n::Message App::Descriptor::name() {
return (I18n::Message)0;
}
I18n::Message App::Descriptor::upperName() {
return (I18n::Message)0;
}
const Image * App::Descriptor::icon() {
return nullptr;
}
App::App(Container * container, ViewController * rootViewController, Descriptor * descriptor, I18n::Message warningMessage) :
Responder(nullptr),
m_magic(Magic),
m_modalViewController(this, rootViewController),
m_descriptor(descriptor),
m_container(container),
m_firstResponder(nullptr),
m_warningController(this, warningMessage),
m_name(name),
m_upperName(upperName),
m_icon(icon)
m_warningController(this, warningMessage)
{
}
App::Descriptor * App::descriptor() {
return m_descriptor;
}
bool App::processEvent(Ion::Events::Event event) {
Responder * responder = m_firstResponder;
bool didHandleEvent = false;
@@ -57,18 +71,6 @@ void App::setFirstResponder(Responder * responder) {
}
}
I18n::Message App::name() {
return m_name;
}
I18n::Message App::upperName() {
return m_upperName;
}
const Image * App::icon() {
return m_icon;
}
void App::displayModalViewController(ViewController * vc, float verticalAlignment, float horizontalAlignment,
KDCoordinate topMargin, KDCoordinate leftMargin, KDCoordinate bottomMargin, KDCoordinate rightMargin) {
if (m_modalViewController.isDisplayingModal()) {

View File

@@ -7,14 +7,20 @@ Container::Container() :
{
}
void Container::switchTo(App * app) {
if (m_activeApp == app) {
return;
Container::~Container() {
if (m_activeApp) {
delete m_activeApp;
}
}
void Container::switchTo(App::Descriptor * descriptor) {
if (m_activeApp) {
m_activeApp->willBecomeInactive();
delete m_activeApp;
}
if (descriptor) {
m_activeApp = descriptor->build(this);
}
m_activeApp = app;
if (m_activeApp) {
m_activeApp->didBecomeActive(window());
}

View File

@@ -18,11 +18,9 @@ void Window::redraw(bool force) {
}
void Window::setContentView(View * contentView) {
if (m_contentView != contentView) {
m_contentView = contentView;
markRectAsDirty(bounds());
layoutSubviews();
}
m_contentView = contentView;
markRectAsDirty(bounds());
layoutSubviews();
}
const Window * Window::window() const {