From 0682d21a3262b6d1ae4e76d356e75d7c7de1e794 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 30 Jan 2018 13:11:23 +0100 Subject: [PATCH] [python] Implement ExecutionEnvironment::input By using a re-entrant RunLoop call --- apps/apps_container.cpp | 5 +++++ apps/apps_container.h | 1 + apps/code/console_controller.cpp | 35 ++++++++++++++++++++++++++++++-- apps/code/console_controller.h | 3 +++ apps/code/console_edit_cell.h | 1 + escher/include/escher/run_loop.h | 2 +- 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index a8ae4db8e..13bc02e13 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -136,6 +136,11 @@ void AppsContainer::run() { switchTo(nullptr); } +void AppsContainer::runWhile(bool (*callback)(void * ctx), void * ctx) { + while (callback(ctx) && RunLoop::step()) { + } +} + bool AppsContainer::updateBatteryState() { if (m_window.updateBatteryLevel() || m_window.updateIsChargingState() || diff --git a/apps/apps_container.h b/apps/apps_container.h index 89126897f..d7a7b7a56 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -39,6 +39,7 @@ public: virtual bool dispatchEvent(Ion::Events::Event event) override; void switchTo(App::Snapshot * snapshot) override; void run() override; + void runWhile(bool (*callback)(void * ctx), void * ctx); bool updateBatteryState(); void refreshPreferences(); void displayExamModePopUp(bool activate); diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 8ba7ba65f..92ffbd2ea 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "../apps_container.h" extern "C" { #include @@ -80,7 +81,23 @@ void ConsoleController::runAndPrintForCommand(const char * command) { } const char * ConsoleController::input() { - return "1+1"; + AppsContainer * a = (AppsContainer *)(app()->container()); + m_inputRunLoopActive = true; + + m_selectableTableView.reloadData(); + m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines()); + m_editCell.setText("???"); + + a->redrawWindow(); + a->runWhile([](void * a){ + ConsoleController * c = static_cast(a); + return c->inputRunLoopActive(); + }, this); + + flushOutputAccumulationBufferToStore(); + m_consoleStore.deleteLastLineIfEmpty(); + + return m_editCell.text(); } void ConsoleController::removeExtensionIfAny(char * name) { @@ -111,6 +128,12 @@ void ConsoleController::didBecomeFirstResponder() { } bool ConsoleController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Home && inputRunLoopActive()) { + askInputRunLoopTermination(); + // We need to return true here because we want to actually exit from the + // input run loop, which requires ending a dispatchEvent cycle. + return true; + } if (event == Ion::Events::Up) { if (m_consoleStore.numberOfLines() > 0 && m_selectableTableView.selectedRow() == m_consoleStore.numberOfLines()) { m_editCell.setEditing(false); @@ -245,6 +268,10 @@ bool ConsoleController::textFieldDidReceiveEvent(TextField * textField, Ion::Eve } bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { + if (inputRunLoopActive()) { + askInputRunLoopTermination(); + return false; + } runAndPrintForCommand(text); if (m_sandboxIsDisplayed) { return true; @@ -257,7 +284,11 @@ bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const c } bool ConsoleController::textFieldDidAbortEditing(TextField * textField, const char * text) { - stackViewController()->pop(); + if (inputRunLoopActive()) { + askInputRunLoopTermination(); + } else { + stackViewController()->pop(); + } return true; } diff --git a/apps/code/console_controller.h b/apps/code/console_controller.h index a8f7e0944..55db61f28 100644 --- a/apps/code/console_controller.h +++ b/apps/code/console_controller.h @@ -65,6 +65,8 @@ public: const char * input() override; private: + bool inputRunLoopActive() { return m_inputRunLoopActive; } + void askInputRunLoopTermination() { m_inputRunLoopActive = false; } static constexpr int LineCellType = 0; static constexpr int EditCellType = 1; static constexpr int k_numberOfLineCells = 15; // May change depending on the screen height @@ -91,6 +93,7 @@ private: * ConsoleLine in the ConsoleStore and empty m_outputAccumulationBuffer. */ ScriptStore * m_scriptStore; SandboxController m_sandboxController; + bool m_inputRunLoopActive; }; } diff --git a/apps/code/console_edit_cell.h b/apps/code/console_edit_cell.h index bf151274a..6121800cb 100644 --- a/apps/code/console_edit_cell.h +++ b/apps/code/console_edit_cell.h @@ -28,6 +28,7 @@ public: // Edit cell void setEditing(bool isEditing, bool reinitDraftBuffer = false); + const char * text() const { return m_textField.text(); } void setText(const char * text); bool insertText(const char * text); diff --git a/escher/include/escher/run_loop.h b/escher/include/escher/run_loop.h index 83f9396d6..2788fb2f8 100644 --- a/escher/include/escher/run_loop.h +++ b/escher/include/escher/run_loop.h @@ -12,8 +12,8 @@ protected: virtual bool dispatchEvent(Ion::Events::Event e) = 0; virtual int numberOfTimers(); virtual Timer * timerAtIndex(int i); -private: bool step(); +private: int m_time; };