mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[apps/code][python] ConsoleController doesn't keep any pointer/boolean to know
if the sandbox/matplotlib view controller is displayed. Its state won't be always right; instead, use the StackViewController depth. This fixes the following bug: when popping the sandbox/matplotlib view controller, the first responder token was not given to the console controller!
This commit is contained in:
@@ -33,7 +33,7 @@ ConsoleController::ConsoleController(Responder * parentResponder, App * pythonDe
|
|||||||
m_selectableTableView(this, this, this, this),
|
m_selectableTableView(this, this, this, this),
|
||||||
m_editCell(this, pythonDelegate, this),
|
m_editCell(this, pythonDelegate, this),
|
||||||
m_scriptStore(scriptStore),
|
m_scriptStore(scriptStore),
|
||||||
m_sandboxController(this, this),
|
m_sandboxController(this),
|
||||||
m_inputRunLoopActive(false)
|
m_inputRunLoopActive(false)
|
||||||
#if EPSILON_GETOPT
|
#if EPSILON_GETOPT
|
||||||
, m_locked(lockOnConsole)
|
, m_locked(lockOnConsole)
|
||||||
@@ -190,7 +190,7 @@ void ConsoleController::viewWillAppear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleController::didBecomeFirstResponder() {
|
void ConsoleController::didBecomeFirstResponder() {
|
||||||
if (viewControllerIsDisplayed(nullptr)) {
|
if (!isDisplayingViewController()) {
|
||||||
Container::activeApp()->setFirstResponder(&m_editCell);
|
Container::activeApp()->setFirstResponder(&m_editCell);
|
||||||
} else {
|
} else {
|
||||||
/* A view controller might be displayed: for example, when pushing the
|
/* A view controller might be displayed: for example, when pushing the
|
||||||
@@ -198,7 +198,7 @@ void ConsoleController::didBecomeFirstResponder() {
|
|||||||
* 'viewWillAppear' and then we set the console as first responder. The
|
* 'viewWillAppear' and then we set the console as first responder. The
|
||||||
* sandbox or the matplotlib controller might have been pushed in the
|
* sandbox or the matplotlib controller might have been pushed in the
|
||||||
* auto-import. */
|
* auto-import. */
|
||||||
Container::activeApp()->setFirstResponder(m_displayedViewController);
|
Container::activeApp()->setFirstResponder(stackViewController()->topViewController());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const c
|
|||||||
}
|
}
|
||||||
telemetryReportEvent("Console", text);
|
telemetryReportEvent("Console", text);
|
||||||
runAndPrintForCommand(text);
|
runAndPrintForCommand(text);
|
||||||
if (viewControllerIsDisplayed(nullptr)) {
|
if (!isDisplayingViewController()) {
|
||||||
reloadData(true);
|
reloadData(true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -377,14 +377,14 @@ bool ConsoleController::textFieldDidAbortEditing(TextField * textField) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleController::resetSandbox() {
|
void ConsoleController::resetSandbox() {
|
||||||
if (!viewControllerIsDisplayed(sandbox())) {
|
if (stackViewController()->topViewController() != sandbox()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_sandboxController.reset();
|
m_sandboxController.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleController::displayViewController(ViewController * controller) {
|
void ConsoleController::displayViewController(ViewController * controller) {
|
||||||
if (m_displayedViewController == controller) {
|
if (stackViewController()->topViewController() == controller) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hideAnyDisplayedViewController();
|
hideAnyDisplayedViewController();
|
||||||
@@ -392,14 +392,23 @@ void ConsoleController::displayViewController(ViewController * controller) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleController::hideAnyDisplayedViewController() {
|
void ConsoleController::hideAnyDisplayedViewController() {
|
||||||
if (m_displayedViewController == nullptr) {
|
if (!isDisplayingViewController()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stackViewController()->pop();
|
stackViewController()->pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConsoleController::isDisplayingViewController() {
|
||||||
|
/* The StackViewController model state is the best way to know wether the
|
||||||
|
* console is displaying a View Controller (Sandbox or Matplotlib). Indeed,
|
||||||
|
* keeping a boolean or a pointer raises the issue of when updating it - when
|
||||||
|
* 'viewWillAppear' or when 'didEnterResponderChain' - in both cases, the
|
||||||
|
* state would be wrong at some point... */
|
||||||
|
return stackViewController()->depth() > 2;
|
||||||
|
}
|
||||||
|
|
||||||
void ConsoleController::refreshPrintOutput() {
|
void ConsoleController::refreshPrintOutput() {
|
||||||
if (viewControllerIsDisplayed(nullptr) && reloadData(false)) {
|
if (!isDisplayingViewController() && reloadData(false)) {
|
||||||
AppsContainer::sharedAppsContainer()->redrawWindow();
|
AppsContainer::sharedAppsContainer()->redrawWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +502,7 @@ void ConsoleController::autoImportScript(Script script, bool force) {
|
|||||||
// Step 2 - Run the command
|
// Step 2 - Run the command
|
||||||
runAndPrintForCommand(command);
|
runAndPrintForCommand(command);
|
||||||
}
|
}
|
||||||
if (viewControllerIsDisplayed(nullptr) && force) {
|
if (!isDisplayingViewController() && force) {
|
||||||
reloadData(true);
|
reloadData(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ private:
|
|||||||
static constexpr int k_numberOfLineCells = (Ion::Display::Height - Metric::TitleBarHeight) / 14 + 2; // 14 = KDFont::SmallFont->glyphSize().height()
|
static constexpr int k_numberOfLineCells = (Ion::Display::Height - Metric::TitleBarHeight) / 14 + 2; // 14 = KDFont::SmallFont->glyphSize().height()
|
||||||
// k_numberOfLineCells = (240 - 18)/14 ~ 15.9. The 0.1 cell can be above and below the 15 other cells so we add +2 cells.
|
// k_numberOfLineCells = (240 - 18)/14 ~ 15.9. The 0.1 cell can be above and below the 15 other cells so we add +2 cells.
|
||||||
static constexpr int k_outputAccumulationBufferSize = 100;
|
static constexpr int k_outputAccumulationBufferSize = 100;
|
||||||
|
bool isDisplayingViewController();
|
||||||
bool reloadData(bool isEditing);
|
bool reloadData(bool isEditing);
|
||||||
void flushOutputAccumulationBufferToStore();
|
void flushOutputAccumulationBufferToStore();
|
||||||
void appendTextToOutputAccumulationBuffer(const char * text, size_t length);
|
void appendTextToOutputAccumulationBuffer(const char * text, size_t length);
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
#include "sandbox_controller.h"
|
#include "sandbox_controller.h"
|
||||||
#include <apps/apps_container.h>
|
#include <apps/apps_container.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <python/port/mod/turtle/modturtle.h>
|
||||||
|
}
|
||||||
|
|
||||||
namespace Code {
|
namespace Code {
|
||||||
|
|
||||||
SandboxController::SandboxController(Responder * parentResponder, MicroPython::ExecutionEnvironment * executionEnvironment) :
|
SandboxController::SandboxController(Responder * parentResponder) :
|
||||||
ViewController(parentResponder),
|
ViewController(parentResponder),
|
||||||
ExecutionViewControllerHelper(executionEnvironment),
|
|
||||||
m_solidColorView(KDColorWhite)
|
m_solidColorView(KDColorWhite)
|
||||||
{
|
{
|
||||||
assert(executionEnvironment != nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StackViewController * SandboxController::stackViewController() {
|
StackViewController * SandboxController::stackViewController() {
|
||||||
@@ -21,10 +23,13 @@ void SandboxController::reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SandboxController::viewWillAppear() {
|
void SandboxController::viewWillAppear() {
|
||||||
ExecutionViewControllerHelper::viewWillAppear(this);
|
|
||||||
redrawWindow();
|
redrawWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SandboxController::viewDidDisappear() {
|
||||||
|
modturtle_view_did_disappear();
|
||||||
|
}
|
||||||
|
|
||||||
bool SandboxController::handleEvent(Ion::Events::Event event) {
|
bool SandboxController::handleEvent(Ion::Events::Event event) {
|
||||||
// The sandbox handles or "absorbs" all keyboard events except Home and OnOff
|
// The sandbox handles or "absorbs" all keyboard events except Home and OnOff
|
||||||
if (event == Ion::Events::Home || event == Ion::Events::OnOff) {
|
if (event == Ion::Events::Home || event == Ion::Events::OnOff) {
|
||||||
|
|||||||
@@ -9,16 +9,16 @@
|
|||||||
|
|
||||||
namespace Code {
|
namespace Code {
|
||||||
|
|
||||||
class SandboxController : public ViewController, public MicroPython::ExecutionViewControllerHelper {
|
class SandboxController : public ViewController {
|
||||||
public:
|
public:
|
||||||
SandboxController(Responder * parentResponder, MicroPython::ExecutionEnvironment * executionEnvironment);
|
SandboxController(Responder * parentResponder);
|
||||||
StackViewController * stackViewController();
|
StackViewController * stackViewController();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
// ViewController
|
// ViewController
|
||||||
View * view() override { return &m_solidColorView; }
|
View * view() override { return &m_solidColorView; }
|
||||||
void viewWillAppear() override;
|
void viewWillAppear() override;
|
||||||
void viewDidDisappear() override { MicroPython::ExecutionViewControllerHelper::viewDidDisappear(this); }
|
void viewDidDisappear() override;
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
ViewController::DisplayParameter displayParameter() override { return ViewController::DisplayParameter::WantsMaximumSpace; }
|
ViewController::DisplayParameter displayParameter() override { return ViewController::DisplayParameter::WantsMaximumSpace; }
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ static size_t extractAndValidatePlotInput(mp_obj_t x, mp_obj_t y, mp_obj_t ** xI
|
|||||||
|
|
||||||
mp_obj_t modpyplot___init__() {
|
mp_obj_t modpyplot___init__() {
|
||||||
static Matplotlib::PlotStore plotStore;
|
static Matplotlib::PlotStore plotStore;
|
||||||
static Matplotlib::PlotController plotController(&plotStore, MicroPython::ExecutionEnvironment::currentExecutionEnvironment());
|
static Matplotlib::PlotController plotController(&plotStore);
|
||||||
sPlotStore = &plotStore;
|
sPlotStore = &plotStore;
|
||||||
sPlotController = &plotController;
|
sPlotController = &plotController;
|
||||||
sPlotStore->flush();
|
sPlotStore->flush();
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
namespace Matplotlib {
|
namespace Matplotlib {
|
||||||
|
|
||||||
void PlotController::viewWillAppear() {
|
void PlotController::viewWillAppear() {
|
||||||
MicroPython::ExecutionViewControllerHelper::viewWillAppear(this);
|
|
||||||
curveView()->reload();
|
curveView()->reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlotController::viewDidDisappear() {
|
void PlotController::viewDidDisappear() {
|
||||||
MicroPython::ExecutionViewControllerHelper::viewDidDisappear(this);
|
|
||||||
m_store->flush();
|
m_store->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,14 @@
|
|||||||
#define PYTHON_MATPLOTLIB_PLOT_CONTROLLER_H
|
#define PYTHON_MATPLOTLIB_PLOT_CONTROLLER_H
|
||||||
|
|
||||||
#include <apps/shared/zoom_and_pan_curve_view_controller.h>
|
#include <apps/shared/zoom_and_pan_curve_view_controller.h>
|
||||||
#include <python/port/port.h>
|
|
||||||
#include "plot_view.h"
|
#include "plot_view.h"
|
||||||
#include "plot_store.h"
|
#include "plot_store.h"
|
||||||
|
|
||||||
namespace Matplotlib {
|
namespace Matplotlib {
|
||||||
|
|
||||||
class PlotController : public Shared::ZoomAndPanCurveViewController, public MicroPython::ExecutionViewControllerHelper {
|
class PlotController : public Shared::ZoomAndPanCurveViewController {
|
||||||
public:
|
public:
|
||||||
PlotController(PlotStore * store, MicroPython::ExecutionEnvironment * executiveEnvironment) : Shared::ZoomAndPanCurveViewController(nullptr), ExecutionViewControllerHelper(executiveEnvironment), m_store(store), m_view(m_store) {}
|
PlotController(PlotStore * store) : Shared::ZoomAndPanCurveViewController(nullptr), m_store(store), m_view(m_store) {}
|
||||||
|
|
||||||
void viewWillAppear() override;
|
void viewWillAppear() override;
|
||||||
void viewDidDisappear() override;
|
void viewDidDisappear() override;
|
||||||
|
|||||||
@@ -95,23 +95,6 @@ void MicroPython::ExecutionEnvironment::interrupt() {
|
|||||||
mp_keyboard_interrupt();
|
mp_keyboard_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicroPython::ExecutionEnvironment::viewControllerDidDisappear(ViewController * vc) {
|
|
||||||
if (vc == sandbox()) {
|
|
||||||
modturtle_view_did_disappear();
|
|
||||||
}
|
|
||||||
m_displayedViewController = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MicroPython::ExecutionViewControllerHelper::viewWillAppear(ViewController * vc) {
|
|
||||||
assert(m_executionEnvironment != nullptr);
|
|
||||||
m_executionEnvironment->viewControllerWillAppear(vc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MicroPython::ExecutionViewControllerHelper::viewDidDisappear(ViewController * vc) {
|
|
||||||
assert(m_executionEnvironment != nullptr);
|
|
||||||
m_executionEnvironment->viewControllerDidDisappear(vc);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern const void * _stack_start;
|
extern const void * _stack_start;
|
||||||
extern const void * _stack_end;
|
extern const void * _stack_end;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public:
|
|||||||
|
|
||||||
class ExecutionEnvironment {
|
class ExecutionEnvironment {
|
||||||
public:
|
public:
|
||||||
ExecutionEnvironment() : m_displayedViewController(nullptr) {}
|
ExecutionEnvironment() {}
|
||||||
static ExecutionEnvironment * currentExecutionEnvironment();
|
static ExecutionEnvironment * currentExecutionEnvironment();
|
||||||
void runCode(const char * );
|
void runCode(const char * );
|
||||||
virtual const char * inputText(const char * prompt) { return nullptr; }
|
virtual const char * inputText(const char * prompt) { return nullptr; }
|
||||||
@@ -28,24 +28,10 @@ public:
|
|||||||
// Generic View Controller
|
// Generic View Controller
|
||||||
virtual void displayViewController(ViewController * controller) {}
|
virtual void displayViewController(ViewController * controller) {}
|
||||||
virtual void hideAnyDisplayedViewController() {}
|
virtual void hideAnyDisplayedViewController() {}
|
||||||
void viewControllerWillAppear(ViewController * vc) { m_displayedViewController = vc; }
|
|
||||||
void viewControllerDidDisappear(ViewController * vc);
|
|
||||||
|
|
||||||
virtual void printText(const char * text, size_t length) {}
|
virtual void printText(const char * text, size_t length) {}
|
||||||
virtual void refreshPrintOutput() {}
|
virtual void refreshPrintOutput() {}
|
||||||
void interrupt();
|
void interrupt();
|
||||||
protected:
|
|
||||||
bool viewControllerIsDisplayed(ViewController * vc) const { return m_displayedViewController == vc; }
|
|
||||||
ViewController * m_displayedViewController;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExecutionViewControllerHelper {
|
|
||||||
public:
|
|
||||||
ExecutionViewControllerHelper(ExecutionEnvironment * executionEnvironment) : m_executionEnvironment(executionEnvironment) {}
|
|
||||||
void viewWillAppear(ViewController * vc);
|
|
||||||
void viewDidDisappear(ViewController * vc);
|
|
||||||
private:
|
|
||||||
ExecutionEnvironment * m_executionEnvironment;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void init(void * heapStart, void * heapEnd);
|
void init(void * heapStart, void * heapEnd);
|
||||||
|
|||||||
Reference in New Issue
Block a user