Merge branch 'master' into f7

This commit is contained in:
Léa Saviot
2019-08-06 17:40:14 +02:00
238 changed files with 1349 additions and 1230 deletions

View File

@@ -38,7 +38,7 @@ snapshots_count = $(words $(apps))
snapshot_includes = $(foreach i,$(app_headers),-include $(i) )
epsilon_app_names = '$(foreach i,${EPSILON_APPS},"$(i)", )'
$(call object_for,apps/apps_container_storage.cpp apps/main.cpp): CXXFLAGS += $(snapshot_includes) -DAPPS_CONTAINER_APPS_DECLARATION="$(apps_declaration)" -DAPPS_CONTAINER_SNAPSHOT_DECLARATIONS="$(snapshots_declaration)" -DAPPS_CONTAINER_SNAPSHOT_CONSTRUCTORS="$(snapshots_construction)" -DAPPS_CONTAINER_SNAPSHOT_LIST="$(snapshots_list)" -DAPPS_CONTAINER_SNAPSHOT_COUNT=$(snapshots_count) -DEPSILON_APPS_NAMES=$(epsilon_app_names)
$(call object_for,apps/apps_container_storage.cpp apps/apps_container.cpp): CXXFLAGS += $(snapshot_includes) -DAPPS_CONTAINER_APPS_DECLARATION="$(apps_declaration)" -DAPPS_CONTAINER_SNAPSHOT_DECLARATIONS="$(snapshots_declaration)" -DAPPS_CONTAINER_SNAPSHOT_CONSTRUCTORS="$(snapshots_construction)" -DAPPS_CONTAINER_SNAPSHOT_LIST="$(snapshots_list)" -DAPPS_CONTAINER_SNAPSHOT_COUNT=$(snapshots_count) -DEPSILON_APPS_NAMES=$(epsilon_app_names)
# I18n file generation

View File

@@ -1,4 +1,5 @@
#include "apps_container.h"
#include "apps_container_storage.h"
#include "global_preferences.h"
#include <ion.h>
#include <poincare/init.h>
@@ -52,6 +53,11 @@ static KDColor sPromptColors[] = {
#endif
AppsContainer * AppsContainer::sharedAppsContainer() {
static AppsContainerStorage appsContainerStorage;
return &appsContainerStorage;
}
AppsContainer::AppsContainer() :
Container(),
m_window(),
@@ -64,8 +70,8 @@ AppsContainer::AppsContainer() :
#elif EPSILON_BOOT_PROMPT == EPSILON_UPDATE_PROMPT
m_promptController(sPromptMessages, sPromptColors, 6),
#endif
m_batteryTimer(BatteryTimer(this)),
m_suspendTimer(SuspendTimer(this)),
m_batteryTimer(),
m_suspendTimer(),
m_backlightDimmingTimer(),
m_homeSnapshot(),
m_onBoardingSnapshot(),
@@ -132,8 +138,8 @@ void AppsContainer::suspend(bool checkIfOnOffKeyReleased) {
resetShiftAlphaStatus();
GlobalPreferences * globalPreferences = GlobalPreferences::sharedGlobalPreferences();
#ifdef EPSILON_BOOT_PROMPT
if (activeApp()->snapshot()!= onBoardingAppSnapshot() && activeApp()->snapshot() != hardwareTestAppSnapshot() && globalPreferences->showPopUp()) {
activeApp()->displayModalViewController(&m_promptController, 0.f, 0.f);
if (s_activeApp->snapshot()!= onBoardingAppSnapshot() && s_activeApp->snapshot() != hardwareTestAppSnapshot() && globalPreferences->showPopUp()) {
s_activeApp->displayModalViewController(&m_promptController, 0.f, 0.f);
}
#endif
Ion::Power::suspend(checkIfOnOffKeyReleased);
@@ -154,7 +160,7 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
}
if (event == Ion::Events::USBEnumeration) {
if (Ion::USB::isPlugged()) {
App::Snapshot * activeSnapshot = (activeApp() == nullptr ? appSnapshotAtIndex(0) : activeApp()->snapshot());
App::Snapshot * activeSnapshot = (s_activeApp == nullptr ? appSnapshotAtIndex(0) : s_activeApp->snapshot());
/* Just after a software update, the battery timer does not have time to
* fire before the calculator enters DFU mode. As the DFU mode blocks the
* event loop, we update the battery state "manually" here.
@@ -233,7 +239,7 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
}
bool AppsContainer::switchTo(App::Snapshot * snapshot) {
if (activeApp() && snapshot != activeApp()->snapshot()) {
if (s_activeApp && snapshot != s_activeApp->snapshot()) {
resetShiftAlphaStatus();
}
if (snapshot == hardwareTestAppSnapshot() || snapshot == onBoardingAppSnapshot()) {
@@ -271,11 +277,11 @@ void AppsContainer::run() {
(void) switched; // Silence compilation warning about unused variable.
} else {
// Exception
if (activeApp() != nullptr) {
if (s_activeApp != nullptr) {
/* The app models can reference layouts or expressions that have been
* destroyed from the pool. To avoid using them before packing the app
* (in App::willBecomeInactive for instance), we tidy them early on. */
activeApp()->snapshot()->tidy();
s_activeApp->snapshot()->tidy();
/* When an app encoutered an exception due to a full pool, the next time
* the user enters the app, the same exception could happen again which
* would prevent from reopening the app. To avoid being stuck outside the
@@ -283,13 +289,13 @@ void AppsContainer::run() {
* exception. For instance, the calculation app can encounter an
* exception when displaying too many huge layouts, if we don't clean the
* history here, we will be stuck outside the calculation app. */
activeApp()->snapshot()->reset();
s_activeApp->snapshot()->reset();
}
bool switched = switchTo(appSnapshotAtIndex(0));
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
Poincare::Tidy();
activeApp()->displayWarning(I18n::Message::PoolMemoryFull1, I18n::Message::PoolMemoryFull2, true);
s_activeApp->displayWarning(I18n::Message::PoolMemoryFull1, I18n::Message::PoolMemoryFull2, true);
}
Container::run();
switchTo(nullptr);
@@ -315,7 +321,7 @@ void AppsContainer::reloadTitleBarView() {
void AppsContainer::displayExamModePopUp(bool activate) {
m_examPopUpController.setActivatingExamMode(activate);
activeApp()->displayModalViewController(&m_examPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin);
s_activeApp->displayModalViewController(&m_examPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin);
}
void AppsContainer::shutdownDueToLowBattery() {
@@ -368,14 +374,14 @@ void AppsContainer::examDeactivatingPopUpIsDismissed() {
}
void AppsContainer::storageDidChangeForRecord(const Ion::Storage::Record record) {
if (activeApp()) {
activeApp()->snapshot()->storageDidChangeForRecord(record);
if (s_activeApp) {
s_activeApp->snapshot()->storageDidChangeForRecord(record);
}
}
void AppsContainer::storageIsFull() {
if (activeApp()) {
activeApp()->displayWarning(I18n::Message::StorageMemoryFull1, I18n::Message::StorageMemoryFull2, true);
if (s_activeApp) {
s_activeApp->displayWarning(I18n::Message::StorageMemoryFull1, I18n::Message::StorageMemoryFull2, true);
}
}

View File

@@ -24,6 +24,7 @@
class AppsContainer : public Container, ExamPopUpControllerDelegate, Ion::StorageDelegate {
public:
static AppsContainer * sharedAppsContainer();
AppsContainer();
static bool poincareCircuitBreaker();
virtual int numberOfApps() = 0;

View File

@@ -14,11 +14,6 @@
constexpr int k_numberOfCommonApps = 1+APPS_CONTAINER_SNAPSHOT_COUNT; // Take the Home app into account
AppsContainerStorage * AppsContainerStorage::sharedContainer() {
static AppsContainerStorage appsContainerStorage;
return &appsContainerStorage;
}
AppsContainerStorage::AppsContainerStorage() :
AppsContainer()
APPS_CONTAINER_SNAPSHOT_CONSTRUCTORS

View File

@@ -9,7 +9,6 @@
class AppsContainerStorage : public AppsContainer {
public:
static AppsContainerStorage * sharedContainer();
AppsContainerStorage();
int numberOfApps() override;
App::Snapshot * appSnapshotAtIndex(int index) override;

View File

@@ -1,16 +1,16 @@
#include "battery_timer.h"
#include "apps_container.h"
BatteryTimer::BatteryTimer(AppsContainer * container) :
Timer(1),
m_container(container)
BatteryTimer::BatteryTimer() :
Timer(1)
{
}
bool BatteryTimer::fire() {
bool needRedrawing = m_container->updateBatteryState();
AppsContainer * container = AppsContainer::sharedAppsContainer();
bool needRedrawing = container->updateBatteryState();
if (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) {
m_container->shutdownDueToLowBattery();
container->shutdownDueToLowBattery();
}
return needRedrawing;
}

View File

@@ -3,14 +3,11 @@
#include <escher.h>
class AppsContainer;
class BatteryTimer : public Timer {
public:
BatteryTimer(AppsContainer * container);
BatteryTimer();
private:
bool fire() override;
AppsContainer * m_container;
};
#endif

View File

@@ -1,5 +1,4 @@
#include "app.h"
#include "../apps_container.h"
#include "calculation_icon.h"
#include <apps/i18n.h>
#include <poincare/symbol.h>
@@ -23,7 +22,7 @@ const Image * App::Descriptor::icon() {
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
void App::Snapshot::reset() {
@@ -39,8 +38,8 @@ void App::Snapshot::tidy() {
m_calculationStore.tidy();
}
App::App(Container * container, Snapshot * snapshot) :
ExpressionFieldDelegateApp(container, snapshot, &m_editExpressionController),
App::App(Snapshot * snapshot) :
ExpressionFieldDelegateApp(snapshot, &m_editExpressionController),
m_historyController(&m_editExpressionController, snapshot->calculationStore()),
m_editExpressionController(&m_modalViewController, this, &m_historyController, snapshot->calculationStore())
{

View File

@@ -27,6 +27,9 @@ public:
void tidy() override;
CalculationStore m_calculationStore;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
bool layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) override;
// TextFieldDelegateApp
@@ -34,7 +37,7 @@ public:
bool storeExpressionAllowed() const override { return true; }
char XNT() override;
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
HistoryController m_historyController;
EditExpressionController m_editExpressionController;
};

View File

@@ -1,6 +1,5 @@
#include "edit_expression_controller.h"
#include "app.h"
#include "../apps_container.h"
#include <ion/display.h>
#include <poincare/preferences.h>
#include <assert.h>
@@ -62,7 +61,7 @@ void EditExpressionController::didBecomeFirstResponder() {
int lastRow = m_calculationStore->numberOfCalculations() > 0 ? m_calculationStore->numberOfCalculations()-1 : 0;
m_historyController->scrollToCell(0, lastRow);
((ContentView *)view())->expressionField()->setEditing(true, false);
app()->setFirstResponder(((ContentView *)view())->expressionField());
Container::activeApp()->setFirstResponder(((ContentView *)view())->expressionField());
}
bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) {
@@ -109,14 +108,6 @@ void EditExpressionController::layoutFieldDidChangeSize(::LayoutField * layoutFi
}
}
TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() {
return (App *)app();
}
ExpressionFieldDelegateApp * EditExpressionController::expressionFieldDelegateApp() {
return (App *)app();
}
void EditExpressionController::reloadView() {
((ContentView *)view())->reload();
m_historyController->reload();
@@ -127,14 +118,13 @@ void EditExpressionController::reloadView() {
bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event, bool shouldDuplicateLastCalculation) {
if (shouldDuplicateLastCalculation && m_cacheBuffer[0] != 0) {
App * calculationApp = (App *)app();
/* The input text store in m_cacheBuffer might have beed correct the first
* time but then be too long when replacing ans in another context */
if (!calculationApp->isAcceptableText(m_cacheBuffer)) {
calculationApp->displayWarning(I18n::Message::SyntaxError);
Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp();
if (!myApp->isAcceptableText(m_cacheBuffer)) {
return true;
}
m_calculationStore->push(m_cacheBuffer, calculationApp->localContext());
m_calculationStore->push(m_cacheBuffer, myApp->localContext());
m_historyController->reload();
((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1);
return true;
@@ -143,7 +133,7 @@ bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event
if (m_calculationStore->numberOfCalculations() > 0) {
m_cacheBuffer[0] = 0;
((ContentView *)view())->expressionField()->setEditing(false, false);
app()->setFirstResponder(m_historyController);
Container::activeApp()->setFirstResponder(m_historyController);
}
return true;
}
@@ -152,14 +142,13 @@ bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event
bool EditExpressionController::inputViewDidFinishEditing(const char * text, Layout layoutR) {
App * calculationApp = (App *)app();
if (layoutR.isUninitialized()) {
assert(text);
strlcpy(m_cacheBuffer, text, k_cacheBufferSize);
} else {
layoutR.serializeParsedExpression(m_cacheBuffer, k_cacheBufferSize);
}
m_calculationStore->push(m_cacheBuffer, calculationApp->localContext());
m_calculationStore->push(m_cacheBuffer, textFieldDelegateApp()->localContext());
m_historyController->reload();
((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1);
((ContentView *)view())->expressionField()->setEditing(true, true);

View File

@@ -53,8 +53,6 @@ private:
bool inputViewDidReceiveEvent(Ion::Events::Event event, bool shouldDuplicateLastCalculation);
bool inputViewDidFinishEditing(const char * text, Poincare::Layout layoutR);
bool inputViewDidAbortEditing(const char * text);
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override;
static constexpr int k_cacheBufferSize = Constant::MaxSerializedExpressionSize;
char m_cacheBuffer[k_cacheBufferSize];
HistoryController * m_historyController;

View File

@@ -1,6 +1,5 @@
#include "history_controller.h"
#include "app.h"
#include "../apps_container.h"
#include <assert.h>
using namespace Shared;
@@ -25,7 +24,7 @@ void HistoryController::reload() {
void HistoryController::didBecomeFirstResponder() {
selectCellAtLocation(0, numberOfRows()-1);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
void HistoryController::willExitResponderChain(Responder * nextFirstResponder) {
@@ -37,7 +36,7 @@ void HistoryController::willExitResponderChain(Responder * nextFirstResponder) {
bool HistoryController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Down) {
m_selectableTableView.deselectTable();
app()->setFirstResponder(parentResponder());
Container::activeApp()->setFirstResponder(parentResponder());
return true;
}
if (event == Ion::Events::Up) {
@@ -49,7 +48,7 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
SubviewType subviewType = selectedSubviewType();
EditExpressionController * editController = (EditExpressionController *)parentResponder();
m_selectableTableView.deselectTable();
app()->setFirstResponder(editController);
Container::activeApp()->setFirstResponder(editController);
Calculation * calculation = m_calculationStore->calculationAtIndex(focusRow);
if (subviewType == SubviewType::Input) {
editController->insertTextBody(calculation->inputText());
@@ -73,7 +72,7 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
m_calculationStore->deleteCalculationAtIndex(focusRow);
reload();
if (numberOfRows()== 0) {
app()->setFirstResponder(editController);
Container::activeApp()->setFirstResponder(editController);
return true;
}
if (focusRow > 0) {
@@ -93,13 +92,13 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
m_selectableTableView.deselectTable();
m_calculationStore->deleteAll();
reload();
app()->setFirstResponder(parentResponder());
Container::activeApp()->setFirstResponder(parentResponder());
return true;
}
if (event == Ion::Events::Back) {
EditExpressionController * editController = (EditExpressionController *)parentResponder();
m_selectableTableView.deselectTable();
app()->setFirstResponder(editController);
Container::activeApp()->setFirstResponder(editController);
return true;
}
return false;
@@ -121,7 +120,7 @@ void HistoryController::tableViewDidChangeSelection(SelectableTableView * t, int
if (selectedCell == nullptr) {
return;
}
app()->setFirstResponder(selectedCell);
Container::activeApp()->setFirstResponder(selectedCell);
}
int HistoryController::numberOfRows() {
@@ -152,8 +151,7 @@ KDCoordinate HistoryController::rowHeight(int j) {
return 0;
}
Calculation * calculation = m_calculationStore->calculationAtIndex(j);
App * calculationApp = (App *)app();
return calculation->height(calculationApp->localContext(), j == selectedRow() && selectedSubviewType() == SubviewType::Output) + 4 * Metric::CommonSmallMargin;
return calculation->height(App::app()->localContext(), j == selectedRow() && selectedSubviewType() == SubviewType::Output) + 4 * Metric::CommonSmallMargin;
}
int HistoryController::typeAtLocation(int i, int j) {

View File

@@ -75,8 +75,7 @@ void HistoryViewCell::reloadScroll() {
}
void HistoryViewCell::reloadOutputSelection() {
App * calculationApp = (App *)app();
Calculation::DisplayOutput display = m_calculation.displayOutput(calculationApp->localContext());
Calculation::DisplayOutput display = m_calculation.displayOutput(App::app()->localContext());
/* Select the right output according to the calculation display output. This
* will reload the scroll to display the selected output. */
if (display == Calculation::DisplayOutput::ExactAndApproximate) {
@@ -137,11 +136,11 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) {
if (m_calculationExpanded == expanded && *calculation == m_calculation) {
return;
}
Poincare::Context * context = App::app()->localContext();
// Memoization
m_calculation = *calculation;
m_calculationExpanded = expanded;
App * calculationApp = (App *)app();
Calculation::DisplayOutput display = calculation->displayOutput(calculationApp->localContext());
Calculation::DisplayOutput display = calculation->displayOutput(context);
m_inputView.setLayout(calculation->createInputLayout());
/* Both output expressions have to be updated at the same time. Otherwise,
* when updating one layout, if the second one still points to a deleted
@@ -151,13 +150,13 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) {
if (display == Calculation::DisplayOutput::ExactOnly) {
rightOutputLayout = calculation->createExactOutputLayout();
} else {
rightOutputLayout = calculation->createApproximateOutputLayout(calculationApp->localContext());
rightOutputLayout = calculation->createApproximateOutputLayout(context);
if (display == Calculation::DisplayOutput::ExactAndApproximate || (display == Calculation::DisplayOutput::ExactAndApproximateToggle && expanded)) {
leftOutputLayout = calculation->createExactOutputLayout();
}
}
m_scrollableOutputView.setLayouts(rightOutputLayout, leftOutputLayout);
I18n::Message equalMessage = calculation->exactAndApproximateDisplayedOutputsAreEqual(calculationApp->localContext()) == Calculation::EqualSign::Equal ? I18n::Message::Equal : I18n::Message::AlmostEqual;
I18n::Message equalMessage = calculation->exactAndApproximateDisplayedOutputsAreEqual(context) == Calculation::EqualSign::Equal ? I18n::Message::Equal : I18n::Message::AlmostEqual;
m_scrollableOutputView.setEqualMessage(equalMessage);
/* The displayed input and outputs have changed. We need to re-layout the cell
@@ -169,9 +168,9 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) {
void HistoryViewCell::didBecomeFirstResponder() {
assert(m_dataSource);
if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Input) {
app()->setFirstResponder(&m_inputView);
Container::activeApp()->setFirstResponder(&m_inputView);
} else {
app()->setFirstResponder(&m_scrollableOutputView);
Container::activeApp()->setFirstResponder(&m_scrollableOutputView);
}
}
@@ -183,7 +182,7 @@ bool HistoryViewCell::handleEvent(Ion::Events::Event event) {
m_dataSource->setSelectedSubviewType(otherSubviewType, this);
CalculationSelectableTableView * tableView = (CalculationSelectableTableView *)parentResponder();
tableView->scrollToSubviewOfTypeOfCellAtLocation(otherSubviewType, tableView->selectedColumn(), tableView->selectedRow());
app()->setFirstResponder(this);
Container::activeApp()->setFirstResponder(this);
return true;
}
return false;

View File

@@ -77,10 +77,12 @@ void assertCalculationDisplay(const char * input, ::Calculation::Calculation::Di
quiz_assert(lastCalculation->exactAndApproximateDisplayedOutputsAreEqual(context) == sign);
}
if (exactOutput) {
quiz_assert(strcmp(lastCalculation->exactOutputText(), exactOutput) == 0);
constexpr int bufferSize = 500;
char buffer[bufferSize];
quiz_assert(strcmpWithSystemParentheses(lastCalculation->exactOutputText(), exactOutput) == 0);
}
if (approximateOutput) {
quiz_assert(strcmp(lastCalculation->approximateOutputText(), approximateOutput) == 0);
quiz_assert(strcmpWithSystemParentheses(lastCalculation->approximateOutputText(), approximateOutput) == 0);
}
store->deleteAll();
}

View File

@@ -1,5 +1,4 @@
#include "app.h"
#include "../apps_container.h"
#include "code_icon.h"
#include <apps/i18n.h>
#include "helpers.h"
@@ -28,7 +27,7 @@ App::Snapshot::Snapshot() :
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor() {
@@ -72,8 +71,8 @@ void App::Snapshot::setOpt(const char * name, char * value) {
}
#endif
App::App(Container * container, Snapshot * snapshot) :
Shared::InputEventHandlerDelegateApp(container, snapshot, &m_codeStackViewController),
App::App(Snapshot * snapshot) :
Shared::InputEventHandlerDelegateApp(snapshot, &m_codeStackViewController),
m_pythonHeap{},
m_pythonUser(nullptr),
m_consoleController(nullptr, this, snapshot->scriptStore()

View File

@@ -36,6 +36,9 @@ public:
#endif
ScriptStore m_scriptStore;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
~App();
bool prepareForExit() override {
if (m_consoleController.inputRunLoopActive()) {
@@ -75,7 +78,7 @@ private:
char m_pythonHeap[k_pythonHeapSize];
const void * m_pythonUser;
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
ConsoleController m_consoleController;
ButtonRowController m_listFooter;
MenuController m_menuController;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -57,7 +57,7 @@ bool ConsoleController::loadPythonEnvironment() {
/* We load functions and variables names in the variable box before running
* any other python code to avoid failling to load functions and variables
* due to memory exhaustion. */
static_cast<App *>(app())->variableBoxController()->loadFunctionsAndVariables();
App::app()->variableBoxController()->loadFunctionsAndVariables();
return true;
}
@@ -90,9 +90,14 @@ void ConsoleController::terminateInputLoop() {
}
const char * ConsoleController::inputText(const char * prompt) {
AppsContainer * a = (AppsContainer *)(app()->container());
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();
m_inputRunLoopActive = true;
// Hide the sandbox if it is displayed
if (sandboxIsDisplayed()) {
hideSandbox();
}
const char * promptText = prompt;
char * s = const_cast<char *>(prompt);
@@ -119,10 +124,10 @@ const char * ConsoleController::inputText(const char * prompt) {
// Reload the history
m_selectableTableView.reloadData();
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
a->redrawWindow();
appsContainer->redrawWindow();
// Launch a new input loop
a->runWhile([](void * a){
appsContainer->runWhile([](void * a){
ConsoleController * c = static_cast<ConsoleController *>(a);
return c->inputRunLoopActive();
}, this);
@@ -153,7 +158,7 @@ void ConsoleController::viewWillAppear() {
}
void ConsoleController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_editCell);
Container::activeApp()->setFirstResponder(&m_editCell);
}
bool ConsoleController::handleEvent(Ion::Events::Event event) {
@@ -162,7 +167,7 @@ bool ConsoleController::handleEvent(Ion::Events::Event event) {
const char * text = m_consoleStore.lineAtIndex(m_selectableTableView.selectedRow()).text();
m_editCell.setEditing(true);
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
app()->setFirstResponder(&m_editCell);
Container::activeApp()->setFirstResponder(&m_editCell);
return m_editCell.insertText(text);
}
} else if (event == Ion::Events::Clear) {
@@ -290,7 +295,7 @@ bool ConsoleController::textFieldDidReceiveEvent(TextField * textField, Ion::Eve
return true;
}
}
return static_cast<App *>(textField->app())->textInputDidReceiveEvent(textField, event);
return App::app()->textInputDidReceiveEvent(textField, event);
}
bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {

View File

@@ -35,11 +35,11 @@ void ConsoleEditCell::layoutSubviews() {
}
void ConsoleEditCell::didBecomeFirstResponder() {
app()->setFirstResponder(&m_textField);
Container::activeApp()->setFirstResponder(&m_textField);
}
void ConsoleEditCell::setEditing(bool isEditing, bool reinitDraftBuffer) {
m_textField.setEditing(isEditing, reinitDraftBuffer);
void ConsoleEditCell::setEditing(bool isEditing) {
m_textField.setEditing(isEditing);
}
void ConsoleEditCell::setText(const char * text) {

View File

@@ -27,7 +27,7 @@ public:
}
// Edit cell
void setEditing(bool isEditing, bool reinitDraftBuffer = false);
void setEditing(bool isEditing);
const char * text() const override { return m_textField.text(); }
void setText(const char * text);
bool insertText(const char * text);

View File

@@ -90,7 +90,7 @@ void ConsoleLineCell::layoutSubviews() {
}
void ConsoleLineCell::didBecomeFirstResponder() {
app()->setFirstResponder(&m_scrollableView);
Container::activeApp()->setFirstResponder(&m_scrollableView);
}
}

View File

@@ -39,7 +39,7 @@ bool EditorController::handleEvent(Ion::Events::Event event) {
}
void EditorController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_editorView);
Container::activeApp()->setFirstResponder(&m_editorView);
}
void EditorController::viewWillAppear() {
@@ -58,7 +58,7 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
saveScript();
return false;
}
if (static_cast<App *>(textArea->app())->textInputDidReceiveEvent(textArea, event)) {
if (App::app()->textInputDidReceiveEvent(textArea, event)) {
return true;
}
if (event == Ion::Events::EXE) {
@@ -84,7 +84,7 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
numberOfSpaces = numberOfSpaces / UTF8Decoder::CharSizeOfCodePoint(' ');
if (cursorIsPrecededOnTheLineBySpacesOnly && numberOfSpaces >= k_indentationSpacesNumber) {
for (int i = 0; i < k_indentationSpacesNumber; i++) {
textArea->removeCodePoint();
textArea->removePreviousGlyph();
}
return true;
}
@@ -109,15 +109,11 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
}
VariableBoxController * EditorController::variableBoxForInputEventHandler(InputEventHandler * textInput) {
VariableBoxController * varBox = static_cast<App *>(app())->variableBoxController();
VariableBoxController * varBox = App::app()->variableBoxController();
varBox->loadFunctionsAndVariables();
return varBox;
}
InputEventHandlerDelegateApp * EditorController::inputEventHandlerDelegateApp() {
return static_cast<App *>(app());
}
StackViewController * EditorController::stackController() {
return static_cast<StackViewController *>(parentResponder());
}

View File

@@ -33,7 +33,6 @@ public:
VariableBoxController * variableBoxForInputEventHandler(InputEventHandler * textInput) override;
private:
Shared::InputEventHandlerDelegateApp * inputEventHandlerDelegateApp() override;
static constexpr int k_indentationSpacesNumber = 2; //TODO LEA merge with text area k_indentationSpaces
StackViewController * stackController();
void saveScript();

View File

@@ -31,7 +31,7 @@ View * EditorView::subviewAtIndex(int index) {
}
void EditorView::didBecomeFirstResponder() {
app()->setFirstResponder(&m_textArea);
Container::activeApp()->setFirstResponder(&m_textArea);
}
void EditorView::layoutSubviews() {

View File

@@ -36,7 +36,7 @@ MenuController::MenuController(Responder * parentResponder, App * pythonDelegate
}
ConsoleController * MenuController::consoleController() {
return static_cast<App *>(app())->consoleController();
return App::app()->consoleController();
}
StackViewController * MenuController::stackViewController() {
@@ -49,7 +49,7 @@ void MenuController::willExitResponderChain(Responder * nextFirstResponder) {
if (selectedRow >= 0 && selectedRow < m_scriptStore->numberOfScripts() && selectedColumn == 0) {
TextField * tf = static_cast<ScriptNameCell *>(m_selectableTableView.selectedCell())->textField();
if (tf->isEditing()) {
tf->setEditing(false, false);
tf->setEditing(false);
privateTextFieldDidAbortEditing(tf, false);
}
}
@@ -61,14 +61,14 @@ void MenuController::didBecomeFirstResponder() {
}
if (footer()->selectedButton() == 0) {
assert(m_selectableTableView.selectedRow() < 0);
app()->setFirstResponder(&m_consoleButton);
Container::activeApp()->setFirstResponder(&m_consoleButton);
return;
}
if (m_selectableTableView.selectedRow() < 0) {
m_selectableTableView.selectCellAtLocation(0,0);
}
assert(m_selectableTableView.selectedRow() < m_scriptStore->numberOfScripts() + 1);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
#if EPSILON_GETOPT
if (consoleController()->locked()) {
consoleController()->setAutoImport(true);
@@ -92,7 +92,7 @@ bool MenuController::handleEvent(Ion::Events::Event event) {
if (footer()->selectedButton() == 0) {
footer()->setSelectedButton(-1);
m_selectableTableView.selectCellAtLocation(0, numberOfRows()-1);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
return true;
}
}
@@ -121,12 +121,12 @@ bool MenuController::handleEvent(Ion::Events::Event event) {
void MenuController::renameSelectedScript() {
assert(m_selectableTableView.selectedRow() >= 0);
assert(m_selectableTableView.selectedRow() < m_scriptStore->numberOfScripts());
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock);
AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock);
m_selectableTableView.selectCellAtLocation(0, (m_selectableTableView.selectedRow()));
ScriptNameCell * myCell = static_cast<ScriptNameCell *>(m_selectableTableView.selectedCell());
app()->setFirstResponder(myCell);
Container::activeApp()->setFirstResponder(myCell);
myCell->setHighlighted(false);
myCell->textField()->setEditing(true, false);
myCell->textField()->setEditing(true);
myCell->textField()->setCursorLocation(myCell->textField()->text() + strlen(myCell->textField()->text()));
}
@@ -337,16 +337,16 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char
}
m_selectableTableView.selectedCell()->setHighlighted(true);
reloadConsole();
app()->setFirstResponder(&m_selectableTableView);
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
return true;
} else if (error == Script::ErrorStatus::NameTaken) {
app()->displayWarning(I18n::Message::NameTaken);
Container::activeApp()->displayWarning(I18n::Message::NameTaken);
} else if (error == Script::ErrorStatus::NonCompliantName) {
app()->displayWarning(I18n::Message::AllowedCharactersaz09, I18n::Message::NameCannotStartWithNumber);
Container::activeApp()->displayWarning(I18n::Message::AllowedCharactersaz09, I18n::Message::NameCannotStartWithNumber);
} else {
assert(error == Script::ErrorStatus::NotEnoughSpaceAvailable);
app()->displayWarning(I18n::Message::NameTooLong);
Container::activeApp()->displayWarning(I18n::Message::NameTooLong);
}
return false;
}
@@ -420,9 +420,9 @@ bool MenuController::privateTextFieldDidAbortEditing(TextField * textField, bool
textField->setText(scriptName);
if (menuControllerStaysInResponderChain) {
m_selectableTableView.selectCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
return true;
}

View File

@@ -370,7 +370,7 @@ bool PythonToolbox::selectLeaf(int selectedRow) {
editedText = strippedEditedText;
}
sender()->handleEventWithText(editedText, true);
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}

View File

@@ -48,7 +48,7 @@ bool SandboxController::handleEvent(Ion::Events::Event event) {
}
void SandboxController::redrawWindow() {
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->redrawWindow();
AppsContainer::sharedAppsContainer()->redrawWindow();
}
}

View File

@@ -26,7 +26,7 @@ KDSize ScriptNameCell::minimalSizeForOptimalDisplay() const {
}
void ScriptNameCell::didBecomeFirstResponder() {
app()->setFirstResponder(&m_textField);
Container::activeApp()->setFirstResponder(&m_textField);
}
void ScriptNameCell::layoutSubviews() {

View File

@@ -45,7 +45,7 @@ bool ScriptParameterController::handleEvent(Ion::Events::Event event) {
m_script.toggleImportationStatus();
m_selectableTableView.reloadData();
m_menuController->reloadConsole();
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
return true;
case 3:
dismissScriptParameterController();
@@ -67,7 +67,7 @@ void ScriptParameterController::viewWillAppear() {
void ScriptParameterController::didBecomeFirstResponder() {
selectCellAtLocation(0, 0);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
HighlightCell * ScriptParameterController::reusableCell(int index) {

View File

@@ -33,7 +33,7 @@ void VariableBoxController::didEnterResponderChain(Responder * previousFirstResp
* environment where Python has already been inited. This way, we do not
* deinit Python when leaving the VariableBoxController, so we do not lose the
* environment that was loaded when entering the VariableBoxController. */
assert(static_cast<App *>(app())->pythonIsInited());
assert(App::app()->pythonIsInited());
}
static bool shouldAddObject(const char * name, int maxLength) {
@@ -100,7 +100,7 @@ bool VariableBoxController::selectLeaf(int rowIndex) {
if (selectedScriptNode.type() == ScriptNode::Type::Function) {
insertTextInCaller(ScriptNodeCell::k_parenthesesWithEmpty);
}
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}

View File

@@ -30,16 +30,16 @@ void ExamPopUpController::viewDidDisappear() {
}
void ExamPopUpController::didBecomeFirstResponder() {
m_contentView.setSelectedButton(0, app());
m_contentView.setSelectedButton(0);
}
bool ExamPopUpController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Left && m_contentView.selectedButton() == 1) {
m_contentView.setSelectedButton(0, app());
m_contentView.setSelectedButton(0);
return true;
}
if (event == Ion::Events::Right && m_contentView.selectedButton() == 0) {
m_contentView.setSelectedButton(1, app());
m_contentView.setSelectedButton(1);
return true;
}
return false;
@@ -47,16 +47,14 @@ bool ExamPopUpController::handleEvent(Ion::Events::Event event) {
ExamPopUpController::ContentView::ContentView(Responder * parentResponder) :
m_cancelButton(parentResponder, I18n::Message::Cancel, Invocation([](void * context, void * sender) {
ExamPopUpController * controller = (ExamPopUpController *)context;
Container * container = (Container *)controller->app()->container();
container->activeApp()->dismissModalViewController();
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 nextExamMode = controller->isActivatingExamMode() ? GlobalPreferences::ExamMode::Activate : GlobalPreferences::ExamMode::Deactivate;
GlobalPreferences::sharedGlobalPreferences()->setExamMode(nextExamMode);
AppsContainer * container = (AppsContainer *)controller->app()->container();
AppsContainer * container = AppsContainer::sharedAppsContainer();
if (controller->isActivatingExamMode()) {
container->reset();
Ion::LED::setColor(KDColorRed);
@@ -66,7 +64,7 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) :
Ion::LED::updateColorWithPlugAndCharge();
}
container->refreshPreferences();
container->activeApp()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}, parentResponder), KDFont::SmallFont),
m_warningTextView(KDFont::SmallFont, I18n::Message::Warning, 0.5, 0.5, KDColorWhite, KDColorBlack),
@@ -80,14 +78,10 @@ void ExamPopUpController::ContentView::drawRect(KDContext * ctx, KDRect rect) co
ctx->fillRect(bounds(), KDColorBlack);
}
void ExamPopUpController::ContentView::setSelectedButton(int selectedButton, App * app) {
void ExamPopUpController::ContentView::setSelectedButton(int selectedButton) {
m_cancelButton.setHighlighted(selectedButton == 0);
m_okButton.setHighlighted(selectedButton == 1);
if (selectedButton == 0) {
app->setFirstResponder(&m_cancelButton);
} else {
app->setFirstResponder(&m_okButton);
}
Container::activeApp()->setFirstResponder(selectedButton == 0 ? &m_cancelButton : &m_okButton);
}
int ExamPopUpController::ContentView::selectedButton() {

View File

@@ -26,7 +26,7 @@ private:
public:
ContentView(Responder * parentResponder);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setSelectedButton(int selectedButton, App * app);
void setSelectedButton(int selectedButton);
int selectedButton();
void setMessages(bool activingExamMode);
private:

View File

@@ -28,7 +28,7 @@ App::Snapshot::Snapshot() :
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor() {
@@ -49,8 +49,8 @@ void App::Snapshot::tidy() {
m_graphRange.setDelegate(nullptr);
}
App::App(Container * container, Snapshot * snapshot) :
FunctionApp(container, snapshot, &m_inputViewController),
App::App(Snapshot * snapshot) :
FunctionApp(snapshot, &m_inputViewController),
m_listController(&m_listFooter, &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),
@@ -77,7 +77,7 @@ char App::XNT() {
}
NestedMenuController * App::variableBoxForInputEventHandler(InputEventHandler * textInput) {
VariableBoxController * varBox = container()->variableBoxController();
VariableBoxController * varBox = AppsContainer::sharedAppsContainer()->variableBoxController();
varBox->setSender(textInput);
varBox->lockDeleteEvent(VariableBoxController::Page::Function);
return varBox;

View File

@@ -30,12 +30,15 @@ public:
CartesianFunctionStore m_functionStore;
Shared::InteractiveCurveViewRange m_graphRange;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
InputViewController * inputViewController() override;
char XNT() override;
NestedMenuController * variableBoxForInputEventHandler(InputEventHandler * textInput) override;
CartesianFunctionStore * functionStore() override { return static_cast<CartesianFunctionStore *>(Shared::FunctionApp::functionStore()); }
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
ListController m_listController;
ButtonRowController m_listFooter;
ButtonRowController m_listHeader;

View File

@@ -45,16 +45,14 @@ void CalculationGraphController::reloadBannerView() {
}
Expression::Coordinate2D CalculationGraphController::computeNewPointOfInteresetFromAbscissa(double start, int direction) {
App * myApp = static_cast<App *>(app());
double step = m_graphRange->xGridUnit()/10.0;
step = direction < 0 ? -step : step;
double max = direction > 0 ? m_graphRange->xMax() : m_graphRange->xMin();
return computeNewPointOfInterest(start, step, max, myApp->localContext());
return computeNewPointOfInterest(start, step, max, textFieldDelegateApp()->localContext());
}
CartesianFunctionStore * CalculationGraphController::functionStore() const {
App * a = static_cast<App *>(app());
return a->functionStore();
return App::app()->functionStore();
}
bool CalculationGraphController::handleLeftRightEvent(Ion::Events::Event event) {

View File

@@ -33,7 +33,7 @@ View * CalculationParameterController::view() {
void CalculationParameterController::didBecomeFirstResponder() {
m_selectableTableView.selectCellAtLocation(0, 0);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool CalculationParameterController::handleEvent(Ion::Events::Event event) {

View File

@@ -7,7 +7,7 @@ namespace Graph {
static inline float maxFloat(float x, float y) { return x > y ? x : y; }
GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
GraphController::GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, curveViewRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion),
m_bannerView(this, inputEventHandlerDelegate, this),
m_view(functionStore, curveViewRange, m_cursor, &m_bannerView, &m_cursorView),
@@ -43,10 +43,10 @@ void GraphController::setDisplayDerivativeInBanner(bool displayDerivative) {
float GraphController::interestingXHalfRange() const {
float characteristicRange = 0.0f;
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
Poincare::Context * context = textFieldDelegateApp()->localContext();
for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) {
ExpiringPointer<CartesianFunction> f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i));
float fRange = f->expressionReduced(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Poincare::Preferences::sharedPreferences()->angleUnit());
float fRange = f->expressionReduced(context).characteristicXRange(*context, Poincare::Preferences::sharedPreferences()->angleUnit());
if (!std::isnan(fRange)) {
characteristicRange = maxFloat(fRange, characteristicRange);
}
@@ -74,14 +74,12 @@ void GraphController::reloadBannerView() {
return;
}
Ion::Storage::Record record = functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor());
App * myApp = static_cast<App *>(app());
reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, record, myApp);
reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, record);
}
bool GraphController::moveCursorHorizontally(int direction) {
Ion::Storage::Record record = functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor());
App * myApp = static_cast<App *>(app());
return privateMoveCursorHorizontally(m_cursor, direction, m_graphRange, k_numberOfCursorStepsInGradUnit, record, myApp);
return privateMoveCursorHorizontally(m_cursor, direction, m_graphRange, k_numberOfCursorStepsInGradUnit, record);
}
InteractiveCurveViewRange * GraphController::interactiveCurveViewRange() {

View File

@@ -15,7 +15,7 @@ namespace Graph {
class GraphController : public Shared::FunctionGraphController, public GraphControllerHelper {
public:
GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
I18n::Message emptyMessage() override;
void viewWillAppear() override;
bool displayDerivativeInBanner() const;

View File

@@ -9,24 +9,24 @@ using namespace Poincare;
namespace Graph {
bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCursor * cursor, int direction, Shared::InteractiveCurveViewRange * range, int numberOfStepsInGradUnit, Ion::Storage::Record record, App * app) {
ExpiringPointer<CartesianFunction> function = app->functionStore()->modelForRecord(record);
bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCursor * cursor, int direction, Shared::InteractiveCurveViewRange * range, int numberOfStepsInGradUnit, Ion::Storage::Record record) {
ExpiringPointer<CartesianFunction> function = App::app()->functionStore()->modelForRecord(record);
double xCursorPosition = cursor->x();
double x = direction > 0 ? xCursorPosition + range->xGridUnit()/numberOfStepsInGradUnit : xCursorPosition - range->xGridUnit()/numberOfStepsInGradUnit;
double y = function->evaluateAtAbscissa(x, app->localContext());
double y = function->evaluateAtAbscissa(x, App::app()->localContext());
cursor->moveTo(x, y);
return true;
}
void GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record, App * app) {
ExpiringPointer<CartesianFunction> function = app->functionStore()->modelForRecord(record);
void GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record) {
ExpiringPointer<CartesianFunction> function = App::app()->functionStore()->modelForRecord(record);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
const char * space = " ";
int numberOfChar = function->derivativeNameWithArgument(buffer, bufferSize, CartesianFunction::Symbol());
const char * legend = "=";
numberOfChar += strlcpy(buffer+numberOfChar, legend, bufferSize-numberOfChar);
double y = function->approximateDerivative(cursor->x(), app->localContext());
double y = function->approximateDerivative(cursor->x(), App::app()->localContext());
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(y, buffer + numberOfChar, bufferSize-numberOfChar, Constant::ShortNumberOfSignificantDigits);
strlcpy(buffer+numberOfChar, space, bufferSize-numberOfChar);
bannerView()->derivativeView()->setText(buffer);

View File

@@ -11,8 +11,8 @@ class App;
class GraphControllerHelper {
protected:
bool privateMoveCursorHorizontally(Shared::CurveViewCursor * cursor, int direction, Shared::InteractiveCurveViewRange * range, int numberOfStepsInGradUnit, Ion::Storage::Record record, App * app);
void reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record, App * app);
bool privateMoveCursorHorizontally(Shared::CurveViewCursor * cursor, int direction, Shared::InteractiveCurveViewRange * range, int numberOfStepsInGradUnit, Ion::Storage::Record record);
void reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record);
virtual BannerView * bannerView() = 0;
};

View File

@@ -34,18 +34,18 @@ void TangentGraphController::didBecomeFirstResponder() {
if (curveView()->isMainViewSelected()) {
m_bannerView->abscissaValue()->setParentResponder(this);
m_bannerView->abscissaValue()->setDelegates(textFieldDelegateApp(), this);
app()->setFirstResponder(m_bannerView->abscissaValue());
Container::activeApp()->setFirstResponder(m_bannerView->abscissaValue());
}
}
bool TangentGraphController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp();
double floatBody;
if (textFieldDelegateApp()->hasUndefinedValue(text, floatBody)) {
if (myApp->hasUndefinedValue(text, floatBody)) {
return false;
}
App * myApp = static_cast<App *>(app());
ExpiringPointer<CartesianFunction> function = myApp->functionStore()->modelForRecord(m_record);
double y = function->evaluateAtAbscissa(floatBody, textFieldDelegateApp()->localContext());
ExpiringPointer<CartesianFunction> function = App::app()->functionStore()->modelForRecord(m_record);
double y = function->evaluateAtAbscissa(floatBody, myApp->localContext());
m_cursor->moveTo(floatBody, y);
interactiveCurveViewRange()->panToMakePointVisible(m_cursor->x(), m_cursor->y(), cursorTopMarginRatio(), k_cursorRightMarginRatio, cursorBottomMarginRatio(), k_cursorLeftMarginRatio);
reloadBannerView();
@@ -62,29 +62,29 @@ void TangentGraphController::reloadBannerView() {
if (m_record.isNull()) {
return;
}
App * myApp = static_cast<App *>(app());
FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(m_cursor, m_record, myApp->functionStore(), CartesianFunction::Symbol());
GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, m_record, myApp);
FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(m_cursor, m_record, Shared::FunctionApp::app()->functionStore(), CartesianFunction::Symbol());
GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, m_record);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
Poincare::Context * context = textFieldDelegateApp()->localContext();
const char * legend = "a=";
int legendLength = strlcpy(buffer, legend, bufferSize);
ExpiringPointer<CartesianFunction> function = myApp->functionStore()->modelForRecord(m_record);
double y = function->approximateDerivative(m_cursor->x(), myApp->localContext());
ExpiringPointer<CartesianFunction> function = App::app()->functionStore()->modelForRecord(m_record);
double y = function->approximateDerivative(m_cursor->x(), context);
PoincareHelpers::ConvertFloatToText<double>(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
m_bannerView->aView()->setText(buffer);
legend = "b=";
legendLength = strlcpy(buffer, legend, bufferSize);
y = -y*m_cursor->x()+function->evaluateAtAbscissa(m_cursor->x(), myApp->localContext());
y = -y*m_cursor->x()+function->evaluateAtAbscissa(m_cursor->x(), context);
PoincareHelpers::ConvertFloatToText<double>(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
m_bannerView->bView()->setText(buffer);
m_bannerView->reload();
}
bool TangentGraphController::moveCursorHorizontally(int direction) {
App * myApp = static_cast<App *>(app());
return privateMoveCursorHorizontally(m_cursor, direction, m_graphRange, k_numberOfCursorStepsInGradUnit, m_record, myApp);
return privateMoveCursorHorizontally(m_cursor, direction, m_graphRange, k_numberOfCursorStepsInGradUnit, m_record);
}
bool TangentGraphController::handleEnter() {

View File

@@ -38,10 +38,10 @@ void ListController::renameSelectedFunction() {
computeTitlesColumnWidth(true);
selectableTableView()->reloadData();
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock);
AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock);
TextFieldFunctionTitleCell * selectedTitleCell = (TextFieldFunctionTitleCell *)(selectableTableView()->selectedCell());
selectedTitleCell->setHorizontalAlignment(1.0f);
app()->setFirstResponder(selectedTitleCell);
Container::activeApp()->setFirstResponder(selectedTitleCell);
selectedTitleCell->setEditing(true);
}
@@ -73,7 +73,7 @@ bool ListController::textFieldDidFinishEditing(TextField * textField, const char
// Handle any error
if (error == Ion::Storage::Record::ErrorStatus::None) {
bool selectTab = false;
textField->setEditing(false, false);
textField->setEditing(false);
computeTitlesColumnWidth();
int currentRow = m_selectableTableView.selectedRow();
if (event == Ion::Events::Down && currentRow < numberOfRows() - 1) {
@@ -87,29 +87,29 @@ bool ListController::textFieldDidFinishEditing(TextField * textField, const char
}
m_selectableTableView.selectedCell()->setHighlighted(true);
m_selectableTableView.reloadData();
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
if (selectTab) {
m_selectableTableView.parentResponder()->handleEvent(event);
}
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
return true;
} else if (error == Ion::Storage::Record::ErrorStatus::NameTaken) {
app()->displayWarning(I18n::Message::NameTaken);
Container::activeApp()->displayWarning(I18n::Message::NameTaken);
} else if (error == Ion::Storage::Record::ErrorStatus::NonCompliantName) {
assert(nameError != Function::NameNotCompliantError::None);
if (nameError == Function::NameNotCompliantError::CharacterNotAllowed) {
app()->displayWarning(I18n::Message::AllowedCharactersAZaz09);
Container::activeApp()->displayWarning(I18n::Message::AllowedCharactersAZaz09);
} else if (nameError == Function::NameNotCompliantError::NameCannotStartWithNumber) {
app()->displayWarning(I18n::Message::NameCannotStartWithNumber);
Container::activeApp()->displayWarning(I18n::Message::NameCannotStartWithNumber);
} else {
assert(nameError == Function::NameNotCompliantError::ReservedName);
app()->displayWarning(I18n::Message::ReservedName);
Container::activeApp()->displayWarning(I18n::Message::ReservedName);
}
} else {
assert(error == Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable);
app()->displayWarning(I18n::Message::NameTooLong);
Container::activeApp()->displayWarning(I18n::Message::NameTooLong);
}
textField->setEditing(true, false);
textField->setEditing(true);
return false;
}
@@ -121,8 +121,8 @@ bool ListController::textFieldDidAbortEditing(TextField * textField) {
ExpiringPointer<Function> function = modelStore()->modelForRecord(modelStore()->recordAtIndex(selectedRow()));
setFunctionNameInTextField(function, textField);
m_selectableTableView.selectedCell()->setHighlighted(true);
app()->setFirstResponder(&m_selectableTableView);
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
return true;
}

View File

@@ -29,9 +29,6 @@ private:
HighlightCell * expressionCells(int index) override;
void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) override;
void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) override;
Shared::TextFieldDelegateApp * textFieldDelegateApp() override {
return static_cast<Shared::TextFieldDelegateApp *>(app());
}
void setFunctionNameInTextField(Shared::ExpiringPointer<Shared::Function> function, TextField * textField);
TextFieldFunctionTitleCell m_functionTitleCells[k_maxNumberOfDisplayableRows];
Shared::FunctionExpressionCell m_expressionCells[k_maxNumberOfDisplayableRows];

View File

@@ -24,9 +24,9 @@ Responder * TextFieldFunctionTitleCell::responder() {
}
void TextFieldFunctionTitleCell::setEditing(bool editing) {
app()->setFirstResponder(&m_textField);
Container::activeApp()->setFirstResponder(&m_textField);
const char * previousText = m_textField.text();
m_textField.setEditing(true, false);
m_textField.setEditing(true);
m_textField.setText(previousText);
}
@@ -67,7 +67,7 @@ void TextFieldFunctionTitleCell::layoutSubviews() {
void TextFieldFunctionTitleCell::didBecomeFirstResponder() {
if (isEditing()) {
app()->setFirstResponder(&m_textField);
Container::activeApp()->setFirstResponder(&m_textField);
}
}

View File

@@ -31,7 +31,7 @@ View * DerivativeParameterController::view() {
void DerivativeParameterController::didBecomeFirstResponder() {
selectCellAtLocation(0, 0);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool DerivativeParameterController::handleEvent(Ion::Events::Event event) {
@@ -82,8 +82,7 @@ KDCoordinate DerivativeParameterController::cellHeight() {
}
CartesianFunctionStore * DerivativeParameterController::functionStore() {
App * a = static_cast<App *>(app());
return a->functionStore();
return App::app()->functionStore();
}
}

View File

@@ -70,8 +70,7 @@ void FunctionParameterController::willDisplayCellForIndex(HighlightCell * cell,
}
ExpiringPointer<CartesianFunction> FunctionParameterController::function() {
App * a = static_cast<App *>(app());
return a->functionStore()->modelForRecord(m_record);
return App::app()->functionStore()->modelForRecord(m_record);
}
}

View File

@@ -1,6 +1,7 @@
#include "values_controller.h"
#include <assert.h>
#include "../../constant.h"
#include "../app.h"
using namespace Shared;
using namespace Poincare;
@@ -142,15 +143,15 @@ FunctionParameterController * ValuesController::functionParameterController() {
}
double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) {
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
bool isDerivative = isDerivativeColumn(columnIndex);
/* isDerivativeColumn uses expiring pointers, so "function" must be created
* after the isDerivativeColumn call, else it will expire. */
Shared::ExpiringPointer<CartesianFunction> function = functionStore()->modelForRecord(recordAtColumn(columnIndex));
Poincare::Context * context = textFieldDelegateApp()->localContext();
if (isDerivative) {
return function->approximateDerivative(abscissa, myApp->localContext());
return function->approximateDerivative(abscissa, context);
}
return function->evaluateAtAbscissa(abscissa, myApp->localContext());
return function->evaluateAtAbscissa(abscissa, context);
}
void ValuesController::updateNumberOfColumns() {

View File

@@ -1,10 +1,9 @@
#include "app.h"
#include "../apps_container.h"
namespace HardwareTest {
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor() {
@@ -12,8 +11,8 @@ App::Descriptor * App::Snapshot::descriptor() {
return &descriptor;
}
App::App(Container * container, Snapshot * snapshot) :
::App(container, snapshot, &m_wizardViewController),
App::App(Snapshot * snapshot) :
::App(snapshot, &m_wizardViewController),
m_wizardViewController(&m_modalViewController)
{
}

View File

@@ -12,8 +12,6 @@
#include "serial_number_controller.h"
#include "vblank_test_controller.h"
class AppsContainer;
namespace HardwareTest {
class App : public ::App {
@@ -42,7 +40,7 @@ private:
VBlankTestController m_vBlankTestController;
};
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
WizardViewController m_wizardViewController;
};

View File

@@ -2,6 +2,7 @@
#include <apps/i18n.h>
#include "../apps_container.h"
#include <assert.h>
#include <escher/app.h>
namespace HardwareTest {
@@ -34,13 +35,11 @@ bool PopUpController::handleEvent(Ion::Events::Event event) {
PopUpController::ContentView::ContentView(Responder * parentResponder) :
Responder(parentResponder),
m_cancelButton(this, I18n::Message::Cancel, Invocation([](void * context, void * sender) {
PopUpController::ContentView * view = (PopUpController::ContentView *)context;
view->app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}, this), KDFont::SmallFont),
m_okButton(this, I18n::Message::Ok, Invocation([](void * context, void * sender) {
PopUpController::ContentView * view = (PopUpController::ContentView *)context;
AppsContainer * appsContainer = (AppsContainer *)view->app()->container();
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();
bool switched = appsContainer->switchTo(appsContainer->hardwareTestAppSnapshot());
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
@@ -62,9 +61,9 @@ void PopUpController::ContentView::setSelectedButton(int selectedButton) {
m_cancelButton.setHighlighted(selectedButton == 0);
m_okButton.setHighlighted(selectedButton == 1);
if (selectedButton == 0) {
app()->setFirstResponder(&m_cancelButton);
Container::activeApp()->setFirstResponder(&m_cancelButton);
} else {
app()->setFirstResponder(&m_okButton);
Container::activeApp()->setFirstResponder(&m_okButton);
}
}

View File

@@ -1,6 +1,5 @@
#include "app.h"
#include <apps/i18n.h>
#include "../apps_container.h"
extern "C" {
#include <assert.h>
@@ -17,7 +16,7 @@ I18n::Message App::Descriptor::upperName() {
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor() {
@@ -25,9 +24,9 @@ App::Descriptor * App::Snapshot::descriptor() {
return &descriptor;
}
App::App(Container * container, Snapshot * snapshot) :
::App(container, snapshot, &m_controller, I18n::Message::Warning),
m_controller(&m_modalViewController, (AppsContainer *)container, snapshot)
App::App(Snapshot * snapshot) :
::App(snapshot, &m_controller, I18n::Message::Warning),
m_controller(&m_modalViewController, snapshot)
{
}

View File

@@ -4,8 +4,6 @@
#include <escher.h>
#include "controller.h"
class AppsContainer;
namespace Home {
class App : public ::App {
@@ -20,8 +18,14 @@ public:
App * unpack(Container * container) override;
Descriptor * descriptor() override;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
Snapshot * snapshot() const {
return static_cast<Snapshot *>(::App::snapshot());
}
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
Controller m_controller;
};

View File

@@ -1,4 +1,5 @@
#include "controller.h"
#include "app.h"
#include "../apps_container.h"
extern "C" {
#include <assert.h>
@@ -47,17 +48,16 @@ void Controller::ContentView::layoutSubviews() {
m_selectableTableView.setFrame(bounds());
}
Controller::Controller(Responder * parentResponder, ::AppsContainer * container, SelectableTableViewDataSource * selectionDataSource) :
Controller::Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource) :
ViewController(parentResponder),
m_container(container),
m_view(this, selectionDataSource),
m_selectionDataSource(selectionDataSource)
m_view(this, selectionDataSource)
{
}
bool Controller::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
bool switched = m_container->switchTo(m_container->appSnapshotAtIndex(m_selectionDataSource->selectedRow()*k_numberOfColumns+m_selectionDataSource->selectedColumn()+1));
AppsContainer * container = AppsContainer::sharedAppsContainer();
bool switched = container->switchTo(container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1));
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
return true;
@@ -67,23 +67,21 @@ bool Controller::handleEvent(Ion::Events::Event event) {
return m_view.selectableTableView()->selectCellAtLocation(0,0);
}
if (event == Ion::Events::Right && m_selectionDataSource->selectedRow() < numberOfRows()) {
return m_view.selectableTableView()->selectCellAtLocation(0, m_selectionDataSource->selectedRow()+1);
if (event == Ion::Events::Right && selectionDataSource()->selectedRow() < numberOfRows()) {
return m_view.selectableTableView()->selectCellAtLocation(0, selectionDataSource()->selectedRow()+1);
}
if (event == Ion::Events::Left && m_selectionDataSource->selectedRow() > 0) {
return m_view.selectableTableView()->selectCellAtLocation(numberOfColumns()-1, m_selectionDataSource->selectedRow()-1);
if (event == Ion::Events::Left && selectionDataSource()->selectedRow() > 0) {
return m_view.selectableTableView()->selectCellAtLocation(numberOfColumns()-1, selectionDataSource()->selectedRow()-1);
}
return false;
}
void Controller::didBecomeFirstResponder() {
if (m_selectionDataSource->selectedRow() == -1) {
m_selectionDataSource->selectCellAtLocation(0, 0);
} else {
m_selectionDataSource->selectCellAtLocation(m_selectionDataSource->selectedColumn(), m_selectionDataSource->selectedRow());
if (selectionDataSource()->selectedRow() == -1) {
selectionDataSource()->selectCellAtLocation(0, 0);
}
app()->setFirstResponder(m_view.selectableTableView());
Container::activeApp()->setFirstResponder(m_view.selectableTableView());
}
void Controller::viewWillAppear() {
@@ -119,22 +117,25 @@ int Controller::reusableCellCount() {
void Controller::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) {
AppCell * appCell = (AppCell *)cell;
AppsContainer * container = AppsContainer::sharedAppsContainer();
int appIndex = (j*k_numberOfColumns+i)+1;
if (appIndex >= m_container->numberOfApps()) {
if (appIndex >= container->numberOfApps()) {
appCell->setVisible(false);
} else {
appCell->setVisible(true);
::App::Descriptor * descriptor = m_container->appSnapshotAtIndex(appIndex)->descriptor();
::App::Descriptor * descriptor = container->appSnapshotAtIndex(appIndex)->descriptor();
appCell->setAppDescriptor(descriptor);
}
}
int Controller::numberOfIcons() {
assert(m_container->numberOfApps() > 0);
return m_container->numberOfApps() - 1;
AppsContainer * container = AppsContainer::sharedAppsContainer();
assert(container->numberOfApps() > 0);
return container->numberOfApps() - 1;
}
void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) {
AppsContainer * container = AppsContainer::sharedAppsContainer();
if (withinTemporarySelection) {
return;
}
@@ -147,7 +148,7 @@ void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previo
* background complete redrawing but the code is a bit
* clumsy. */
if (t->selectedRow() == numberOfRows()-1) {
m_view.reloadBottomRow(this, m_container->numberOfApps()-1, k_numberOfColumns);
m_view.reloadBottomRow(this, container->numberOfApps()-1, k_numberOfColumns);
}
/* To prevent the selectable table view to select cells that are unvisible,
* we reselect the previous selected cell as soon as the selected cell is
@@ -155,9 +156,13 @@ void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previo
* stay on a unvisible cell and to initialize the first cell on a visible one
* (so the previous one is always visible). */
int appIndex = (t->selectedColumn()+t->selectedRow()*k_numberOfColumns)+1;
if (appIndex >= m_container->numberOfApps()) {
if (appIndex >= container->numberOfApps()) {
t->selectCellAtLocation(previousSelectedCellX, previousSelectedCellY);
}
}
SelectableTableViewDataSource * Controller::selectionDataSource() const {
return App::app()->snapshot();
}
}

View File

@@ -4,13 +4,11 @@
#include <escher.h>
#include "app_cell.h"
class AppsContainer;
namespace Home {
class Controller : public ViewController, public SimpleTableViewDataSource, public SelectableTableViewDelegate {
public:
Controller(Responder * parentResponder, ::AppsContainer * container, SelectableTableViewDataSource * selectionDataSource);
Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource);
View * view() override;
@@ -28,6 +26,7 @@ public:
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) override;
private:
int numberOfIcons();
SelectableTableViewDataSource * selectionDataSource() const;
class ContentView : public View {
public:
ContentView(Controller * controller, SelectableTableViewDataSource * selectionDataSource);
@@ -40,7 +39,6 @@ private:
void layoutSubviews() override;
SelectableTableView m_selectableTableView;
};
AppsContainer * m_container;
static constexpr KDCoordinate k_sideMargin = 4;
static constexpr KDCoordinate k_bottomMargin = 14;
static constexpr KDCoordinate k_indicatorMargin = 61;
@@ -50,7 +48,6 @@ private:
static constexpr int k_cellWidth = 104;
ContentView m_view;
AppCell m_cells[k_maxNumberOfCells];
SelectableTableViewDataSource * m_selectionDataSource;
};
}

View File

@@ -1 +1 @@
LanguagePT = "Portugués "
LanguagePT = "Português "

View File

@@ -1,4 +1,4 @@
#include "apps_container_storage.h"
#include "apps_container.h"
#include "global_preferences.h"
#include <poincare/init.h>
@@ -46,8 +46,8 @@ void ion_main(int argc, char * argv[]) {
* $ ./epsilon.elf --code-script hello_world.py:print("hello") --code-lock-on-console
*/
const char * appNames[] = {"home", EPSILON_APPS_NAMES};
for (int j = 0; j < AppsContainerStorage::sharedContainer()->numberOfApps(); j++) {
App::Snapshot * snapshot = AppsContainerStorage::sharedContainer()->appSnapshotAtIndex(j);
for (int j = 0; j < AppsContainer::sharedAppsContainer()->numberOfApps(); j++) {
App::Snapshot * snapshot = AppsContainer::sharedAppsContainer()->appSnapshotAtIndex(j);
int cmp = strcmp(argv[i]+2, appNames[j]);
if (cmp == '-') {
snapshot->setOpt(argv[i]+2+strlen(appNames[j])+1, argv[i+1]);
@@ -56,7 +56,7 @@ void ion_main(int argc, char * argv[]) {
}
}
#endif
AppsContainerStorage::sharedContainer()->run();
AppsContainer::sharedAppsContainer()->run();
}
#endif

View File

@@ -120,7 +120,7 @@ bool MathToolbox::selectLeaf(int selectedRow) {
text = textToInsert;
}
sender()->handleEventWithText(text);
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}

View File

@@ -4,7 +4,7 @@
namespace OnBoarding {
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor() {
@@ -12,9 +12,9 @@ App::Descriptor * App::Snapshot::descriptor() {
return &descriptor;
}
App::App(Container * container, Snapshot * snapshot) :
::App(container, snapshot, &m_languageController),
m_languageController(&m_modalViewController, &m_logoController),
App::App(Snapshot * snapshot) :
::App(snapshot, &m_languageController),
m_languageController(&m_modalViewController),
m_logoController()
{
}
@@ -40,7 +40,12 @@ bool App::processEvent(Ion::Events::Event e) {
void App::didBecomeActive(Window * window) {
::App::didBecomeActive(window);
m_languageController.reinitOnBoarding();
reinitOnBoarding();
}
void App::reinitOnBoarding() {
m_languageController.resetSelection();
displayModalViewController(&m_logoController, 0.5f, 0.5f);
}
}

View File

@@ -19,7 +19,8 @@ public:
bool processEvent(Ion::Events::Event) override;
void didBecomeActive(Window * window) override;
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
void reinitOnBoarding();
LanguageController m_languageController;
LogoController m_logoController;
};

View File

@@ -4,22 +4,16 @@
namespace OnBoarding {
LanguageController::LanguageController(Responder * parentResponder, LogoController * logoController) :
Shared::LanguageController(parentResponder, (Ion::Display::Height - I18n::NumberOfLanguages*Metric::ParameterCellHeight)/2),
m_logoController(logoController)
LanguageController::LanguageController(Responder * parentResponder) :
Shared::LanguageController(parentResponder, (Ion::Display::Height - I18n::NumberOfLanguages*Metric::ParameterCellHeight)/2)
{
}
void LanguageController::reinitOnBoarding() {
resetSelection();
app()->displayModalViewController(m_logoController, 0.5f, 0.5f);
}
bool LanguageController::handleEvent(Ion::Events::Event event) {
if (Shared::LanguageController::handleEvent(event)) {
AppsContainer * appsContainer = (AppsContainer *)app()->container();
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();
#ifdef EPSILON_BOOT_PROMPT
app()->displayModalViewController(appsContainer->promptController(), 0.5f, 0.5f);
Container::activeApp()->displayModalViewController(appsContainer->promptController(), 0.5f, 0.5f);
#else
appsContainer->switchTo(appsContainer->appSnapshotAtIndex(0));
#endif

View File

@@ -9,11 +9,8 @@ namespace OnBoarding {
class LanguageController : public Shared::LanguageController {
public:
LanguageController(Responder * parentResponder, LogoController * logoController);
void reinitOnBoarding();
LanguageController(Responder * parentResponder);
bool handleEvent(Ion::Events::Event event) override;
private:
LogoController * m_logoController;
};
}

View File

@@ -14,7 +14,7 @@ LogoController::LogoController() :
}
bool LogoController::fire() {
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}

View File

@@ -52,8 +52,8 @@ PopUpController::PopUpController(I18n::Message * messages, KDColor * colors, uin
bool PopUpController::handleEvent(Ion::Events::Event event) {
if (event != Ion::Events::Back && event != Ion::Events::OnOff && event != Ion::Events::USBPlug && event != Ion::Events::USBEnumeration) {
app()->dismissModalViewController();
AppsContainer * appsContainer = (AppsContainer *)app()->container();
Container::activeApp()->dismissModalViewController();
AppsContainer * appsContainer = AppsContainer::sharedAppsContainer();
if (appsContainer->activeApp()->snapshot() == appsContainer->onBoardingAppSnapshot()) {
bool switched = appsContainer->switchTo(appsContainer->appSnapshotAtIndex(0));
assert(switched);

View File

@@ -35,7 +35,7 @@ App::Snapshot::~Snapshot() {
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor() {
@@ -67,8 +67,8 @@ App::Snapshot::Page App::Snapshot::activePage() {
return m_activePage;
}
App::App(Container * container, Snapshot * snapshot) :
TextFieldDelegateApp(container, snapshot, &m_stackViewController),
App::App(Snapshot * snapshot) :
TextFieldDelegateApp(snapshot, &m_stackViewController),
m_calculationController(&m_stackViewController, this, snapshot->law(), snapshot->calculation()),
m_parametersController(&m_stackViewController, this, snapshot->law(), &m_calculationController),
m_lawController(&m_stackViewController, snapshot->law(), &m_parametersController),

View File

@@ -54,8 +54,12 @@ public:
char m_calculation[k_calculationSize];
Page m_activePage;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
Snapshot * snapshot() const { return static_cast<Snapshot *>(::App::snapshot()); }
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
CalculationController m_calculationController;
ParametersController m_parametersController;
LawController m_lawController;

View File

@@ -1,6 +1,5 @@
#include "calculation_controller.h"
#include "../constant.h"
#include "../apps_container.h"
#include "../shared/poincare_helpers.h"
#include "app.h"
#include "calculation/discrete_calculation.h"
@@ -80,15 +79,14 @@ CalculationController::CalculationController(Responder * parentResponder, InputE
}
void CalculationController::didEnterResponderChain(Responder * previousResponder) {
App::Snapshot * snapshot = (App::Snapshot *)app()->snapshot();
snapshot->setActivePage(App::Snapshot::Page::Calculations);
App::app()->snapshot()->setActivePage(App::Snapshot::Page::Calculations);
updateTitle();
reloadLawCurveView();
m_selectableTableView.reloadData();
}
void CalculationController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
View * CalculationController::view() {
@@ -194,7 +192,7 @@ bool CalculationController::textFieldDidHandleEvent(::TextField * textField, boo
/* We do not reload the responder because the first responder might be the
* toolbox (or the variable box) and reloading the responder would corrupt
* the first responder. */
bool shouldUpdateFirstResponder = app()->firstResponder() == textField;
bool shouldUpdateFirstResponder = Container::activeApp()->firstResponder() == textField;
m_selectableTableView.reloadData(shouldUpdateFirstResponder);
// The textField frame might have increased which forces to reload the textField scroll
textField->scrollToCursor();
@@ -268,10 +266,6 @@ void CalculationController::setCalculationAccordingToIndex(int index, bool force
m_calculation->setLaw(m_law);
}
TextFieldDelegateApp * CalculationController::textFieldDelegateApp() {
return (App *)app();
}
void CalculationController::updateTitle() {
int currentChar = 0;
for (int index = 0; index < m_law->numberOfParameter(); index++) {

View File

@@ -47,7 +47,6 @@ public:
private:
constexpr static int k_numberOfCalculationCells = 3;
constexpr static KDCoordinate k_tableMargin = 3;
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
void updateTitle();
class ContentView : public View {
public:

View File

@@ -39,21 +39,21 @@ void CalculationTypeController::viewDidDisappear() {
}
void CalculationTypeController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool CalculationTypeController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
m_calculationController->setCalculationAccordingToIndex(selectedRow());
m_calculationController->reload();
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}
if (event == Ion::Events::Back || event == Ion::Events::Right) {
if (event == Ion::Events::Right) {
m_calculationController->selectCellAtLocation(1,0);
}
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}
return false;

View File

@@ -73,14 +73,13 @@ void Probability::LawController::viewWillAppear() {
}
void Probability::LawController::didBecomeFirstResponder() {
App::Snapshot * snapshot = (App::Snapshot *)app()->snapshot();
snapshot->setActivePage(App::Snapshot::Page::Law);
App::app()->snapshot()->setActivePage(App::Snapshot::Page::Law);
if (selectedRow() == -1) {
selectCellAtLocation(0, 0);
} else {
selectCellAtLocation(selectedColumn(), selectedRow());
}
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool Probability::LawController::handleEvent(Ion::Events::Event event) {

View File

@@ -21,13 +21,11 @@ void LawCurveView::drawRect(KDContext * ctx, KDRect rect) const {
drawLabels(ctx, rect, Axis::Horizontal, false, false, false, 0, k_backgroundColor);
if (m_law->type() == Law::Type::Normal) {
// Special case for the normal law, which has always the same curve
float pixelColorLowerBound = std::round(floatToPixel(Axis::Horizontal, lowerBound));
float pixelColorUpperBound = std::round(floatToPixel(Axis::Horizontal, upperBound));
drawStandardNormal(ctx, rect, pixelColorLowerBound, pixelColorUpperBound);
drawStandardNormal(ctx, rect, lowerBound, upperBound);
return;
}
if (m_law->isContinuous()) {
drawCurve(ctx, rect, EvaluateAtAbscissa, m_law, nullptr, Palette::YellowDark, true, lowerBound, upperBound, true);
drawCurve(ctx, rect, EvaluateAtAbscissa, m_law, nullptr, Palette::YellowDark, true, lowerBound, upperBound);
} else {
drawHistogram(ctx, rect, EvaluateAtAbscissa, m_law, nullptr, 0, 1, false, Palette::GreyMiddle, Palette::YellowDark, lowerBound, upperBound+0.5f);
}
@@ -48,12 +46,12 @@ float LawCurveView::EvaluateAtAbscissa(float abscissa, void * model, void * cont
void LawCurveView::drawStandardNormal(KDContext * ctx, KDRect rect, float colorLowerBound, float colorUpperBound) const {
// Save the previous curve view range
LawCurveView * constCastedThis = const_cast<LawCurveView *>(this);
CurveViewRange * previousRange = constCastedThis->curveViewRange();
CurveViewRange * previousRange = curveViewRange();
// Draw a centered reduced normal curve
NormalLaw n;
constCastedThis->setCurveViewRange(&n);
drawCurve(ctx, rect, EvaluateAtAbscissa, &n, nullptr, Palette::YellowDark, true, pixelToFloat(Axis::Horizontal, colorLowerBound), pixelToFloat(Axis::Horizontal, colorUpperBound), true);
drawCurve(ctx, rect, EvaluateAtAbscissa, &n, nullptr, Palette::YellowDark, true, colorLowerBound, colorUpperBound);
// Put back the previous curve view range
constCastedThis->setCurveViewRange(previousRange);

View File

@@ -99,8 +99,7 @@ void ParametersController::reinitCalculation() {
}
void ParametersController::didBecomeFirstResponder() {
App::Snapshot * snapshot = (App::Snapshot *)app()->snapshot();
snapshot->setActivePage(App::Snapshot::Page::Parameters);
App::app()->snapshot()->setActivePage(App::Snapshot::Page::Parameters);
FloatParameterController::didBecomeFirstResponder();
}
@@ -145,7 +144,7 @@ double ParametersController::parameterAtIndex(int index) {
bool ParametersController::setParameterAtIndex(int parameterIndex, double f) {
if (!m_law->authorizedValueAtIndex(f, parameterIndex)) {
app()->displayWarning(I18n::Message::ForbiddenValue);
Container::activeApp()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
m_law->setParameterAtIndex(f, parameterIndex);

View File

@@ -21,8 +21,8 @@ KDSize ResponderImageCell::minimalSizeForOptimalDisplay() const {
bool ResponderImageCell::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Down) {
KDPoint topLeftAngle = app()->modalView()->pointFromPointInView(this, KDPoint(k_outline, k_outline));
app()->displayModalViewController(&m_calculationTypeController, 0.0f, 0.0f, topLeftAngle.y(), topLeftAngle.x());
KDPoint topLeftAngle = Container::activeApp()->modalView()->pointFromPointInView(this, KDPoint(k_outline, k_outline));
Container::activeApp()->displayModalViewController(&m_calculationTypeController, 0.0f, 0.0f, topLeftAngle.y(), topLeftAngle.x());
return true;
}
return false;

View File

@@ -29,7 +29,7 @@ App::Snapshot::Snapshot() :
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
void App::Snapshot::reset() {
@@ -50,8 +50,8 @@ void App::Snapshot::tidy() {
m_store.tidy();
}
App::App(Container * container, Snapshot * snapshot) :
TextFieldDelegateApp(container, snapshot, &m_tabViewController),
App::App(Snapshot * snapshot) :
TextFieldDelegateApp(snapshot, &m_tabViewController),
m_calculationController(&m_calculationAlternateEmptyViewController, &m_calculationHeader, snapshot->store()),
m_calculationAlternateEmptyViewController(&m_calculationHeader, &m_calculationController, &m_calculationController),
m_calculationHeader(&m_tabViewController, &m_calculationAlternateEmptyViewController, &m_calculationController),

View File

@@ -40,9 +40,12 @@ public:
uint32_t m_rangeVersion;
int m_selectedSeriesIndex;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
RegressionController * regressionController() { return &m_regressionController; }
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
CalculationController m_calculationController;
AlternateEmptyViewController m_calculationAlternateEmptyViewController;
ButtonRowController m_calculationHeader;

View File

@@ -5,5 +5,5 @@ LogarithmicRegressionFormula = " y=a·ln(x)+b "
ExponentialRegressionFormula = " y=a·exp(b·x) "
PowerRegressionFormula = " y=a·x^b "
TrigonometricRegressionFormula = " y=a·sin(b·x+c)+d "
LogisticRegressionFormula = " y=c/(a+exp(-b·x)) "
LogisticRegressionFormula = " y=c/(1+a·exp(-b·x)) "
Dash = "-"

View File

@@ -50,7 +50,7 @@ const char * CalculationController::title() {
bool CalculationController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Up) {
selectableTableView()->deselectTable();
app()->setFirstResponder(tabController());
Container::activeApp()->setFirstResponder(tabController());
return true;
}
return false;
@@ -78,7 +78,7 @@ void CalculationController::tableViewDidChangeSelection(SelectableTableView * t,
if (t->selectedRow() == 0 && t->selectedColumn() == 0) {
if (previousSelectedCellX == 0 && previousSelectedCellY == 1) {
selectableTableView()->deselectTable();
app()->setFirstResponder(tabController());
Container::activeApp()->setFirstResponder(tabController());
} else {
t->selectCellAtLocation(0, 1);
}
@@ -203,7 +203,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
Model::Type modelType = m_store->seriesRegressionType(seriesNumber);
// Put dashes if regression is not defined
Poincare::Context * globContext = const_cast<AppsContainer *>(static_cast<const AppsContainer *>(app()->container()))->globalContext();
Poincare::Context * globContext = AppsContainer::sharedAppsContainer()->globalContext();
double * coefficients = m_store->coefficientsForSeries(seriesNumber, globContext);
bool coefficientsAreDefined = true;
int numberOfCoefs = m_store->modelForSeries(seriesNumber)->numberOfCoefficients();

View File

@@ -40,7 +40,7 @@ double GoToParameterController::parameterAtIndex(int index) {
bool GoToParameterController::setParameterAtIndex(int parameterIndex, double f) {
assert(parameterIndex == 0);
int series = m_graphController->selectedSeriesIndex();
Poincare::Context * globContext = const_cast<AppsContainer *>(static_cast<const AppsContainer *>(app()->container()))->globalContext();
Poincare::Context * globContext = AppsContainer::sharedAppsContainer()->globalContext();
double unknown = m_xPrediction ?
m_store->yValueForXValue(series, f, globContext) :
m_store->xValueForYValue(series, f, globContext);
@@ -57,7 +57,7 @@ bool GoToParameterController::setParameterAtIndex(int parameterIndex, double f)
}
}
// Value not reached
app()->displayWarning(I18n::Message::ValueNotReachedByRegression);
Container::activeApp()->displayWarning(I18n::Message::ValueNotReachedByRegression);
return false;
}
m_graphController->selectRegressionCurve();
@@ -68,7 +68,7 @@ bool GoToParameterController::setParameterAtIndex(int parameterIndex, double f)
/* We here compute y2 = a*((y1-b)/a)+b, which does not always give y1,
* because of computation precision. y2 migth thus be invalid. */
if (std::isnan(yFromX) || std::isinf(yFromX)) {
app()->displayWarning(I18n::Message::ForbiddenValue);
Container::activeApp()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
m_cursor->moveTo(unknown, yFromX);

View File

@@ -18,7 +18,7 @@ GraphController::GraphController(Responder * parentResponder, InputEventHandlerD
m_crossCursorView(),
m_roundCursorView(),
m_bannerView(this, inputEventHandlerDelegate, this),
m_view(store, m_cursor, &m_bannerView, &m_crossCursorView, this),
m_view(store, m_cursor, &m_bannerView, &m_crossCursorView),
m_store(store),
m_initialisationParameterController(this, m_store),
m_graphOptionsController(this, inputEventHandlerDelegate, m_store, m_cursor, this),
@@ -97,7 +97,7 @@ void GraphController::selectRegressionCurve() {
// Private
Poincare::Context * GraphController::globalContext() {
return const_cast<AppsContainer *>(static_cast<const AppsContainer *>(app()->container()))->globalContext();
return AppsContainer::sharedAppsContainer()->globalContext();
}
// SimpleInteractiveCurveViewController

View File

@@ -2,7 +2,6 @@
#include "app.h"
#include "graph_controller.h"
#include "regression_controller.h"
#include <apps/apps_container.h>
#include <assert.h>
using namespace Shared;
@@ -32,7 +31,7 @@ void GraphOptionsController::didBecomeFirstResponder() {
if (selectedRow() < 0) {
selectCellAtLocation(0, 0);
}
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
void GraphOptionsController::viewWillAppear() {
@@ -42,7 +41,7 @@ void GraphOptionsController::viewWillAppear() {
bool GraphOptionsController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
if (selectedRow() == numberOfRows() -1) {
RegressionController * regressionController = static_cast<Regression::App *>(app())->regressionController();
RegressionController * regressionController = App::app()->regressionController();
regressionController->setSeries(m_graphController->selectedSeriesIndex());
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
stack->push(regressionController);

View File

@@ -8,12 +8,11 @@ using namespace Shared;
namespace Regression {
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, View * cursorView, Responder * controller) :
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) :
CurveView(store, cursor, bannerView, cursorView),
m_store(store),
m_xLabels{},
m_yLabels{},
m_controller(controller)
m_yLabels{}
{
}
@@ -22,11 +21,11 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
drawGrid(ctx, rect);
drawAxes(ctx, rect);
simpleDrawBothAxesLabels(ctx, rect);
Poincare::Context * globContext = AppsContainer::sharedAppsContainer()->globalContext();
for (int series = 0; series < Store::k_numberOfSeries; series++) {
if (!m_store->seriesIsEmpty(series)) {
KDColor color = Palette::DataColor[series];
Model * seriesModel = m_store->modelForSeries(series);
Poincare::Context * globContext = const_cast<AppsContainer *>(static_cast<const AppsContainer *>(m_controller->app()->container()))->globalContext();
drawCurve(ctx, rect, [](float abscissa, void * model, void * context) {
Model * regressionModel = static_cast<Model *>(model);
double * regressionCoefficients = static_cast<double *>(context);

View File

@@ -1,7 +1,6 @@
#ifndef REGRESSION_GRAPH_VIEW_H
#define REGRESSION_GRAPH_VIEW_H
#include <escher.h>
#include "store.h"
#include "../constant.h"
#include "../shared/curve_view.h"
@@ -10,14 +9,13 @@ namespace Regression {
class GraphView : public Shared::CurveView {
public:
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView, Responder * controller);
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView);
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
char * label(Axis axis, int index) const override;
Store * m_store;
char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize];
Responder * m_controller;
};
}

View File

@@ -22,7 +22,7 @@ View * InitialisationParameterController::view() {
void InitialisationParameterController::didBecomeFirstResponder() {
selectCellAtLocation(0, 0);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool InitialisationParameterController::handleEvent(Ion::Events::Event event) {

View File

@@ -30,7 +30,7 @@ const char * RegressionController::title() {
void RegressionController::didBecomeFirstResponder() {
selectCellAtLocation(0, 0);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool RegressionController::handleEvent(Ion::Events::Event event) {

View File

@@ -1,6 +1,5 @@
#include "store.h"
#include "linear_model_helper.h"
#include "apps/apps_container.h"
#include <poincare/preferences.h>
#include <assert.h>
#include <float.h>

View File

@@ -19,7 +19,7 @@ StoreController::StoreController(Responder * parentResponder, InputEventHandlerD
}
StoreContext * StoreController::storeContext() {
m_regressionContext.setParentContext(const_cast<AppsContainer *>(static_cast<const AppsContainer *>(app()->container()))->globalContext());
m_regressionContext.setParentContext(AppsContainer::sharedAppsContainer()->globalContext());
return &m_regressionContext;
}

View File

@@ -20,7 +20,7 @@ void StoreParameterController::viewWillAppear() {
bool StoreParameterController::handleEvent(Ion::Events::Event event) {
if ((event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) && selectedRow() == numberOfRows() - 1) {
RegressionController * regressionController = static_cast<Regression::App *>(app())->regressionController();
RegressionController * regressionController = App::app()->regressionController();
regressionController->setSeries(m_series);
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
stack->push(regressionController);
@@ -37,7 +37,7 @@ void StoreParameterController::didBecomeFirstResponder() {
selectCellAtLocation(0, 0);
}
m_lastSelectionIsRegression = false;
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
HighlightCell * StoreParameterController::reusableCell(int index, int type) {

View File

@@ -26,7 +26,7 @@ App::Snapshot::Snapshot() :
}
App * App::Snapshot::unpack(Container * container) {
return new (container->currentAppBuffer()) App(container, this);
return new (container->currentAppBuffer()) App(this);
}
void App::Snapshot::reset() {
@@ -53,9 +53,9 @@ void App::Snapshot::tidy() {
m_graphRange.setDelegate(nullptr);
}
App::App(Container * container, Snapshot * snapshot) :
FunctionApp(container, snapshot, &m_inputViewController),
m_sequenceContext(((AppsContainer *)container)->globalContext(), snapshot->functionStore()),
App::App(Snapshot * snapshot) :
FunctionApp(snapshot, &m_inputViewController),
m_sequenceContext(AppsContainer::sharedAppsContainer()->globalContext(), snapshot->functionStore()),
m_listController(&m_listFooter, this, &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),

View File

@@ -33,6 +33,9 @@ public:
SequenceStore m_sequenceStore;
CurveViewRange m_graphRange;
};
static App * app() {
return static_cast<App *>(Container::activeApp());
}
InputViewController * inputViewController() override;
// TODO: override variableBoxForInputEventHandler to lock sequence in the variable box once they appear there
// NestedMenuController * variableBoxForInputEventHandler(InputEventHandler * textInput) override;
@@ -40,7 +43,7 @@ public:
SequenceContext * localContext() override;
SequenceStore * functionStore() override { return static_cast<SequenceStore *>(Shared::FunctionApp::functionStore()); }
private:
App(Container * container, Snapshot * snapshot);
App(Snapshot * snapshot);
SequenceContext m_sequenceContext;
ListController m_listController;
ButtonRowController m_listFooter;

View File

@@ -1,6 +1,7 @@
#include "graph_controller.h"
#include <cmath>
#include <limits.h>
#include "../app.h"
using namespace Shared;
using namespace Poincare;
@@ -10,7 +11,7 @@ namespace Sequence {
static inline int minInt(int x, int y) { return (x < y ? x : y); }
static inline int maxInt(int x, int y) { return (x > y ? x : y); }
GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
GraphController::GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, graphRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion),
m_bannerView(this, inputEventHandlerDelegate, this),
m_view(sequenceStore, graphRange, m_cursor, &m_bannerView, &m_cursorView),
@@ -60,12 +61,13 @@ float GraphController::interestingXHalfRange() const {
}
bool GraphController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp();
double floatBody;
if (textFieldDelegateApp()->hasUndefinedValue(text, floatBody)) {
if (myApp->hasUndefinedValue(text, floatBody)) {
return false;
}
floatBody = std::fmax(0, std::round(floatBody));
double y = yValue(selectedCurveIndex(), floatBody, textFieldDelegateApp()->localContext());
double y = yValue(selectedCurveIndex(), floatBody, myApp->localContext());
m_cursor->moveTo(floatBody, y);
interactiveCurveViewRange()->panToMakePointVisible(m_cursor->x(), m_cursor->y(), cursorTopMarginRatio(), k_cursorRightMarginRatio, cursorBottomMarginRatio(), k_cursorLeftMarginRatio);
reloadBannerView();
@@ -84,19 +86,15 @@ bool GraphController::moveCursorHorizontally(int direction) {
if (direction < 0 && xCursorPosition <= 0) {
return false;
}
/* The cursor moves by step of at minimum 1. If the windowRange is to large
* compared to the resolution, the cursor takes bigger round step to cross
* the window in approximatively resolution steps. */
double step = std::ceil((interactiveCurveViewRange()->xMax()-interactiveCurveViewRange()->xMin())/m_view.resolution());
step = step < 1.0 ? 1.0 : step;
// The cursor moves by step that is larger than 1 and than a pixel's width.
const int step = std::ceil(m_view.pixelWidth());
double x = direction > 0 ? xCursorPosition + step:
xCursorPosition - step;
if (x < 0.0) {
return false;
}
Sequence * s = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor()));
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
double y = s->evaluateAtAbscissa(x, myApp->localContext());
double y = s->evaluateAtAbscissa(x, textFieldDelegateApp()->localContext());
m_cursor->moveTo(x, y);
return true;
}

View File

@@ -14,7 +14,7 @@ namespace Sequence {
class GraphController final : public Shared::FunctionGraphController {
public:
GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
I18n::Message emptyMessage() override;
void viewWillAppear() override;
TermSumController * termSumController() { return &m_termSumController; }

View File

@@ -14,16 +14,15 @@ GraphView::GraphView(SequenceStore * sequenceStore, InteractiveCurveViewRange *
void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
FunctionGraphView::drawRect(ctx, rect);
/* A dot is drawn at every step where step is larger than 1
* and than a pixel's width. */
const int step = std::ceil(pixelWidth());
for (int i = 0; i < m_sequenceStore->numberOfActiveFunctions(); i++) {
Ion::Storage::Record record = m_sequenceStore->activeRecordAtIndex(i);
Sequence * s = m_sequenceStore->modelForRecord(record);;
float rectXMin = pixelToFloat(Axis::Horizontal, rect.left() - k_externRectMargin);
rectXMin = rectXMin < 0 ? 0 : rectXMin;
float rectXMax = pixelToFloat(Axis::Horizontal, rect.right() + k_externRectMargin);
/* We draw a dot at every integer if WindowRange/Resolution < 1. Otherwise,
* we draw a dot at every step where step is an integer wider than 1. */
float windowRange = pixelToFloat(Axis::Horizontal, bounds().width()) - pixelToFloat(Axis::Horizontal, 0);
int step = std::ceil(windowRange/resolution());
for (int x = rectXMin; x < rectXMax; x += step) {
float y = s->evaluateAtAbscissa((float)x, context());
if (std::isnan(y)) {
@@ -42,8 +41,4 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
}
}
float GraphView::samplingRatio() const {
return 2.0f;
}
}

View File

@@ -12,7 +12,6 @@ public:
Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView);
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
float samplingRatio() const override;
SequenceStore * m_sequenceStore;
};

View File

@@ -107,10 +107,9 @@ void ListController::editExpression(int sequenceDefinition, Ion::Events::Event e
// Replace UCodePointUnknownN with 'n'
replaceUnknownSymbolWithReadableSymbol(initialText);
}
App * myApp = (App *)app();
InputViewController * inputController = myApp->inputViewController();
InputViewController * inputController = Shared::FunctionApp::app()->inputViewController();
// Invalidate the sequences context cache
static_cast<App *>(app())->localContext()->resetCache();
App::app()->localContext()->resetCache();
switch (sequenceDefinition) {
case 0:
inputController->edit(this, event, this, initialText,
@@ -159,18 +158,6 @@ bool ListController::editInitialConditionOfSelectedRecordWithText(const char * t
return (error == Ion::Storage::Record::ErrorStatus::None);
}
TextFieldDelegateApp * ListController::textFieldDelegateApp() {
return (App *)app();
}
ExpressionFieldDelegateApp * ListController::expressionFieldDelegateApp() {
return (App *)app();
}
InputEventHandlerDelegateApp * ListController::inputEventHandlerDelegateApp() {
return (App *)app();
}
ListParameterController * ListController::parameterController() {
return &m_parameterController;
}
@@ -271,7 +258,7 @@ int ListController::sequenceDefinitionForRow(int j) {
}
void ListController::addEmptyModel() {
app()->displayModalViewController(&m_typeStackController, 0.f, 0.f, Metric::TabHeight+Metric::ModalTopMargin, Metric::CommonRightMargin, Metric::ModalBottomMargin, Metric::CommonLeftMargin);
Container::activeApp()->displayModalViewController(&m_typeStackController, 0.f, 0.f, Metric::TabHeight+Metric::ModalTopMargin, Metric::CommonRightMargin, Metric::ModalBottomMargin, Metric::CommonLeftMargin);
}
void ListController::editExpression(Ion::Events::Event event) {
@@ -280,7 +267,7 @@ void ListController::editExpression(Ion::Events::Event event) {
void ListController::reinitSelectedExpression(ExpiringPointer<ExpressionModelHandle> model) {
// Invalidate the sequences context cache
static_cast<App *>(app())->localContext()->resetCache();
App::app()->localContext()->resetCache();
Sequence * sequence = static_cast<Sequence *>(model.pointer());
switch (sequenceDefinitionForRow(selectedRow())) {
case 1:
@@ -308,7 +295,7 @@ void ListController::reinitSelectedExpression(ExpiringPointer<ExpressionModelHan
bool ListController::removeModelRow(Ion::Storage::Record record) {
Shared::FunctionListController::removeModelRow(record);
// Invalidate the sequences context cache
static_cast<App *>(app())->localContext()->resetCache();
App::app()->localContext()->resetCache();
return true;
}

View File

@@ -28,9 +28,6 @@ public:
private:
static constexpr KDCoordinate k_expressionCellVerticalMargin = 3;
bool editInitialConditionOfSelectedRecordWithText(const char * text, bool firstInitialCondition);
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override;
Shared::InputEventHandlerDelegateApp * inputEventHandlerDelegateApp() override;
ListParameterController * parameterController() override;
int maxNumberOfDisplayableRows() override;
Shared::FunctionTitleCell * titleCells(int index) override;

View File

@@ -1,7 +1,6 @@
#include "list_parameter_controller.h"
#include "list_controller.h"
#include "../app.h"
#include "../../apps_container.h"
#include "../../shared/poincare_helpers.h"
using namespace Poincare;
@@ -57,7 +56,7 @@ bool ListParameterController::handleEvent(Ion::Events::Event event) {
#else
if (selectedRowIndex == 2+hasAdditionalRow) {
#endif
static_cast<App *>(app())->localContext()->resetCache();
App::app()->localContext()->resetCache();
return handleEnterOnRow(selectedRowIndex-hasAdditionalRow-1);
}
}
@@ -78,12 +77,12 @@ bool ListParameterController::textFieldDidFinishEditing(TextField * textField, c
}
int index = std::round(floatBody);
if (index < 0 || floatBody >= maxFirstIndex) {
app()->displayWarning(I18n::Message::ForbiddenValue);
Container::activeApp()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
sequence()->setInitialRank(index);
// Invalidate sequence context cache when changing sequence type
static_cast<App *>(app())->localContext()->resetCache();
App::app()->localContext()->resetCache();
m_selectableTableView.reloadCellAtLocation(0, selectedRow());
m_selectableTableView.handleEvent(event);
return true;
@@ -105,7 +104,7 @@ void ListParameterController::tableViewDidChangeSelection(SelectableTableView *
if (myCell) {
myCell->setEditing(false);
}
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
#if FUNCTION_COLOR_CHOICE
if (t->selectedRow() == 2) {
@@ -113,7 +112,7 @@ void ListParameterController::tableViewDidChangeSelection(SelectableTableView *
if (t->selectedRow() == 1) {
#endif
MessageTableCellWithEditableText * myNewCell = (MessageTableCellWithEditableText *)t->selectedCell();
app()->setFirstResponder(myNewCell);
Container::activeApp()->setFirstResponder(myNewCell);
}
}
@@ -149,10 +148,6 @@ void ListParameterController::willDisplayCellForIndex(HighlightCell * cell, int
}
}
TextFieldDelegateApp * ListParameterController::textFieldDelegateApp() {
return (TextFieldDelegateApp *)app();
}
int ListParameterController::totalNumberOfCells() const {
if (hasInitialRankRow()) {
return k_totalNumberOfCell;

View File

@@ -20,7 +20,6 @@ public:
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) override;
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
// ListViewDataSource
HighlightCell * reusableCell(int index, int type) override;

View File

@@ -99,7 +99,7 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){
char buffer[bufferSize];
m_addedCellLayout[selectedRow].serializeParsedExpression(buffer, bufferSize);
sender()->handleEventWithText(buffer);
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
return true;
}

View File

@@ -49,7 +49,7 @@ void TypeParameterController::viewDidDisappear() {
void TypeParameterController::didBecomeFirstResponder() {
selectCellAtLocation(0, 0);
app()->setFirstResponder(&m_selectableTableView);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool TypeParameterController::handleEvent(Ion::Events::Event event) {
@@ -60,7 +60,7 @@ bool TypeParameterController::handleEvent(Ion::Events::Event event) {
m_listController->selectPreviousNewSequenceCell();
sequence()->setType(sequenceType);
// Invalidate sequence context cache when changing sequence type
static_cast<App *>(app())->localContext()->resetCache();
App::app()->localContext()->resetCache();
// Reset the first index if the new type is "Explicit"
if (sequenceType == Sequence::Type::Explicit) {
sequence()->setInitialRank(0);
@@ -81,7 +81,7 @@ bool TypeParameterController::handleEvent(Ion::Events::Event event) {
Ion::Storage::Record record = sequenceStore()->recordAtIndex(sequenceStore()->numberOfModels()-1);
Sequence * newSequence = sequenceStore()->modelForRecord(record);
newSequence->setType((Sequence::Type)selectedRow());
app()->dismissModalViewController();
Container::activeApp()->dismissModalViewController();
m_listController->editExpression(0, Ion::Events::OK);
return true;
}
@@ -135,8 +135,7 @@ void TypeParameterController::setRecord(Ion::Storage::Record record) {
}
SequenceStore * TypeParameterController::sequenceStore() {
App * a = static_cast<App *>(app());
return a->functionStore();
return App::app()->functionStore();
}
StackViewController * TypeParameterController::stackController() const {

View File

@@ -5,6 +5,10 @@
#include "sequence_context.h"
#include <assert.h>
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif
namespace Sequence {
/* WARNING: after calling setType, setInitialRank, setContent, setFirstInitialConditionContent
@@ -70,7 +74,9 @@ private:
constexpr static double k_maxNumberOfTermsInSum = 100000.0;
/* SequenceRecordDataBuffer is the layout of the data buffer of Record
* representing a Sequence. */
* representing a Sequence. See comment in
* Shared::Function::FunctionRecordDataBuffer about packing. */
#pragma pack(push,1)
class SequenceRecordDataBuffer : public FunctionRecordDataBuffer {
public:
SequenceRecordDataBuffer(KDColor color) :
@@ -91,13 +97,19 @@ private:
assert(conditionIndex >= 0 && conditionIndex < 2);
m_initialConditionSizes[conditionIndex] = size;
}
private:
static_assert((1 << 8*sizeof(uint16_t)) > Ion::Storage::k_storageSize, "Potential overflows of Sequence initial condition sizes");
Type m_type;
uint8_t m_initialRank;
#if __EMSCRIPTEN__
// See comment about emscripten alignement in Shared::Function::FunctionRecordDataBuffer
static_assert(sizeof(emscripten_align1_short) == sizeof(uint16_t), "emscripten_align1_short should have the same size as uint16_t");
emscripten_align1_short m_initialConditionSizes[2];
#else
uint16_t m_initialConditionSizes[2];
#endif
};
#pragma pack(pop)
class SequenceModel : public Shared::ExpressionModel {
public:

View File

@@ -22,7 +22,7 @@ void IntervalParameterController::willDisplayCellForIndex(HighlightCell * cell,
bool IntervalParameterController::setParameterAtIndex(int parameterIndex, double f) {
if (f < 0) {
app()->displayWarning(I18n::Message::ForbiddenValue);
Container::activeApp()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
double parameter = std::round(f);

Some files were not shown because too many files have changed in this diff Show More