From a9f4da92c0cad506562fe50cb8379020c3dd6e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 20 Nov 2017 11:14:08 +0100 Subject: [PATCH] [code/python] Fixed the Kandinsky module in Python. User can draw on the 320*220 drawing screen. Change-Id: I25034b05f21aacc35608358fdb7a4d9924dd22e8 --- apps/apps_window.cpp | 3 ++- apps/apps_window.h | 1 - apps/code/console_controller.cpp | 22 ++++++++++++++++++- apps/code/console_controller.h | 20 ++++++++++++++++- apps/code/script_store.cpp | 1 + apps/code/script_template.cpp | 4 ++-- escher/include/escher/metric.h | 1 + python/port/modkandinsky.c | 1 - python/port/modkandinsky_impl.cpp | 11 +++++++--- python/port/port.cpp | 36 +++++++++++++++++++++++++++---- python/port/port.h | 7 ++++++ 11 files changed, 93 insertions(+), 14 deletions(-) diff --git a/apps/apps_window.cpp b/apps/apps_window.cpp index 74aa44f1e..47cef825b 100644 --- a/apps/apps_window.cpp +++ b/apps/apps_window.cpp @@ -1,4 +1,5 @@ #include "apps_window.h" +#include extern "C" { #include } @@ -54,7 +55,7 @@ View * AppsWindow::subviewAtIndex(int index) { } void AppsWindow::layoutSubviews() { - KDCoordinate titleHeight = m_hideTitleBarView ? 0 : k_titleBarHeight; + KDCoordinate titleHeight = m_hideTitleBarView ? 0 : Metric::TitleBarHeight; m_titleBarView.setFrame(KDRect(0, 0, bounds().width(), titleHeight)); if (m_contentView != nullptr) { m_contentView->setFrame(KDRect(0, titleHeight, bounds().width(), bounds().height()-titleHeight)); diff --git a/apps/apps_window.h b/apps/apps_window.h index e6f9a61e7..b3625c7c2 100644 --- a/apps/apps_window.h +++ b/apps/apps_window.h @@ -15,7 +15,6 @@ public: bool updateAlphaLock(); void hideTitleBarView(bool hide); private: - constexpr static KDCoordinate k_titleBarHeight = 18; int numberOfSubviews() const override; void layoutSubviews() override; View * subviewAtIndex(int index) override; diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index bc0a5001c..7d80be5e5 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -11,15 +11,31 @@ extern "C" { namespace Code { + +ConsoleController::ContentView::ContentView(SelectableTableView * selectabletableView) : + m_selectableTableView(selectabletableView) +{ +} + +void ConsoleController::ContentView::layoutSubviews() { + m_selectableTableView->setFrame(bounds()); +} + +void ConsoleController::ContentView::markAsDirty() { + markRectAsDirty(bounds()); +} + ConsoleController::ConsoleController(Responder * parentResponder, ScriptStore * scriptStore) : ViewController(parentResponder), SelectableTableViewDataSource(), TextFieldDelegate(), + MicroPython::ExecutionEnvironment(), m_rowHeight(KDText::charSize(k_fontSize).height()), m_selectableTableView(this, this, 0, 1, 0, Metric::CommonRightMargin, 0, Metric::TitleBarExternHorizontalMargin, this, this, true, true, KDColorWhite), m_editCell(this, this), m_pythonHeap(nullptr), - m_scriptStore(scriptStore) + m_scriptStore(scriptStore), + m_view(&m_selectableTableView) { for (int i = 0; i < k_numberOfLineCells; i++) { m_cells[i].setParentResponder(&m_selectableTableView); @@ -254,6 +270,10 @@ void ConsoleController::printText(const char * text, size_t length) { } } +void ConsoleController::redraw() { + m_view.markAsDirty(); +} + void ConsoleController::autoImportScriptAtIndex(int index) { const char * importCommand1 = "from "; const char * importCommand2 = " import *"; diff --git a/apps/code/console_controller.h b/apps/code/console_controller.h index 78960fb6e..f3bf258ab 100644 --- a/apps/code/console_controller.h +++ b/apps/code/console_controller.h @@ -32,7 +32,7 @@ public: void removeExtensionIfAny(char * name); // ViewController - View * view() override { return &m_selectableTableView; } + View * view() override { return &m_view; } void viewWillAppear() override; void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; @@ -57,8 +57,25 @@ public: bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; bool textFieldDidAbortEditing(TextField * textField, const char * text) override; ::Toolbox * toolboxForTextField(TextField * textField) override; + // MicroPython::ExecutionEnvironment void printText(const char * text, size_t length) override; + void redraw() override; + + // ConsoleController::ContentView + class ContentView : public View { + public: + ContentView(SelectableTableView * selectabletableView); + void markAsDirty(); + private: + int numberOfSubviews() const override { return 1; } + View * subviewAtIndex(int index) override { + assert(index == 0); + return m_selectableTableView; + } + void layoutSubviews() override; + SelectableTableView * m_selectableTableView; + }; private: static constexpr int LineCellType = 0; @@ -85,6 +102,7 @@ private: * happens, or when m_outputAccumulationBuffer is full, we create a new * ConsoleLine in the ConsoleStore and empty m_outputAccumulationBuffer. */ ScriptStore * m_scriptStore; + ContentView m_view; }; } diff --git a/apps/code/script_store.cpp b/apps/code/script_store.cpp index 4a8ed46e3..affdc8ca6 100644 --- a/apps/code/script_store.cpp +++ b/apps/code/script_store.cpp @@ -12,6 +12,7 @@ ScriptStore::ScriptStore() : { addScriptFromTemplate(ScriptTemplate::Factorial()); addScriptFromTemplate(ScriptTemplate::Fibonacci()); + addScriptFromTemplate(ScriptTemplate::Mandelbrot()); } const Script ScriptStore::scriptAtIndex(int index, EditableZone zone) { diff --git a/apps/code/script_template.cpp b/apps/code/script_template.cpp index 02183ba3e..8bbcf1d34 100644 --- a/apps/code/script_template.cpp +++ b/apps/code/script_template.cpp @@ -31,9 +31,9 @@ constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", R"(# This scr # N_iteration: degree of precision import kandinsky N_iteration = 10 -def drawMandelbrot(): +def drawMandlebrot(): for x in range(320): - for y in range(240): + for y in range(222): # Compute the mandelbrot sequence for the point c = (c_r, c_i) with start value z = (z_r, z_i) z_r = 0 z_i = 0 diff --git a/escher/include/escher/metric.h b/escher/include/escher/metric.h index 920be7e23..888904cb6 100644 --- a/escher/include/escher/metric.h +++ b/escher/include/escher/metric.h @@ -11,6 +11,7 @@ public: constexpr static KDCoordinate CommonBottomMargin = 15; constexpr static KDCoordinate HistoryHorizontalMargin = 10; constexpr static KDCoordinate TitleBarExternHorizontalMargin = 5; + constexpr static KDCoordinate TitleBarHeight = 18; constexpr static KDCoordinate ParameterCellHeight = 35; constexpr static KDCoordinate ModalTopMargin = 5; constexpr static KDCoordinate ModalBottomMargin = 18; diff --git a/python/port/modkandinsky.c b/python/port/modkandinsky.c index fd68a29d4..b24064436 100644 --- a/python/port/modkandinsky.c +++ b/python/port/modkandinsky.c @@ -21,4 +21,3 @@ const mp_obj_module_t kandinsky_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&kandinsky_module_globals, }; - diff --git a/python/port/modkandinsky_impl.cpp b/python/port/modkandinsky_impl.cpp index 74ff8a83a..abc19ab29 100644 --- a/python/port/modkandinsky_impl.cpp +++ b/python/port/modkandinsky_impl.cpp @@ -1,7 +1,9 @@ extern "C" { #include "modkandinsky.h" } +#include #include +#include "port.h" mp_obj_t kandinsky_color(mp_obj_t red, mp_obj_t green, mp_obj_t blue) { return @@ -16,22 +18,25 @@ mp_obj_t kandinsky_color(mp_obj_t red, mp_obj_t green, mp_obj_t blue) { mp_obj_t kandinsky_get_pixel(mp_obj_t x, mp_obj_t y) { KDColor c = KDIonContext::sharedContext()->getPixel( - KDPoint(mp_obj_get_int(x), mp_obj_get_int(y)) + KDPoint(mp_obj_get_int(x), mp_obj_get_int(y) + Metric::TitleBarHeight) ); return MP_OBJ_NEW_SMALL_INT(c); } mp_obj_t kandinsky_set_pixel(mp_obj_t x, mp_obj_t y, mp_obj_t color) { KDIonContext::sharedContext()->setPixel( - KDPoint(mp_obj_get_int(x), mp_obj_get_int(y)), + KDPoint(mp_obj_get_int(x), mp_obj_get_int(y) + Metric::TitleBarHeight), KDColor::RGB16(mp_obj_get_int(color)) ); + MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->didModifyFramebuffer(); return mp_const_none; } mp_obj_t kandinsky_draw_string(mp_obj_t text, mp_obj_t x, mp_obj_t y) { KDIonContext::sharedContext()->drawString( mp_obj_str_get_str(text), - KDPoint(mp_obj_get_int(x), mp_obj_get_int(y)) + KDPoint(mp_obj_get_int(x), mp_obj_get_int(y) + Metric::TitleBarHeight) ); + MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->didModifyFramebuffer(); return mp_const_none; } + diff --git a/python/port/port.cpp b/python/port/port.cpp index d065acebf..2e65242db 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -1,3 +1,10 @@ +#include +#include +#include +#include +#include +#include "port.h" + #include #include #include @@ -16,19 +23,31 @@ extern "C" { #include "py/stackctrl.h" } -#include -#include -#include "port.h" - static char * python_stack_top = NULL; static MicroPython::ScriptProvider * sScriptProvider = nullptr; static MicroPython::ExecutionEnvironment * sCurrentExecutionEnvironment = nullptr; +MicroPython::ExecutionEnvironment::ExecutionEnvironment() : + m_framebufferHasBeenModified(false) +{ +} + +MicroPython::ExecutionEnvironment * MicroPython::ExecutionEnvironment::currentExecutionEnvironment() { + return sCurrentExecutionEnvironment; +} + +void MicroPython::ExecutionEnvironment::didModifyFramebuffer() { + m_framebufferHasBeenModified = true; +} + void MicroPython::ExecutionEnvironment::runCode(const char * str) { assert(sCurrentExecutionEnvironment == nullptr); sCurrentExecutionEnvironment = this; + KDIonContext::sharedContext()->setOrigin(KDPointZero); + KDIonContext::sharedContext()->setClippingRect(KDRect(0, Metric::TitleBarHeight, Ion::Display::Width, Ion::Display::Height - Metric::TitleBarHeight)); + nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(0, str, strlen(str), false); @@ -74,6 +93,15 @@ void MicroPython::ExecutionEnvironment::runCode(const char * str) { /* End of mp_obj_print_exception. */ } + while (m_framebufferHasBeenModified) { + int timeout = 3000; + Ion::Events::Event event = Ion::Events::getEvent(&timeout); + if (event == Ion::Events::OK || event == Ion::Events::Back) { + m_framebufferHasBeenModified = false; + redraw(); + } + } + assert(sCurrentExecutionEnvironment == this); sCurrentExecutionEnvironment = nullptr; } diff --git a/python/port/port.h b/python/port/port.h index 5f42743b6..612ac2571 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -10,9 +10,16 @@ public: class ExecutionEnvironment { public: + ExecutionEnvironment(); + static ExecutionEnvironment * currentExecutionEnvironment(); + void didModifyFramebuffer(); void runCode(const char * ); virtual void printText(const char * text, size_t length) { } + virtual void redraw() { + } +private: + bool m_framebufferHasBeenModified; }; void init(void * heapStart, void * heapEnd);