<html> <script src=“https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js”></script> <script src=“https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js”></script> <script src=“https://embeddedt.github.io/lv_micropython/ports/javascript/lvgl_mp.js”></script>
<link rel=“stylesheet” href=“https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/xterm.min.css” integrity=“sha512-iLYuqv+v/P4u9erpk+KM83Ioe/l7SEmr7wB6g+Kg1qmEit8EShDKnKtLHlv2QXUp7GGJhmqDI+1PhJYLTsfb8w==” crossorigin=“anonymous” /> <script src=“https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/xterm.min.js” integrity=“sha512-2PRgAav8Os8vLcOAh1gSaDoNLe1fAyq8/G3QSdyjFFD+OqNjLeHE/8q4+S4MEZgPsuo+itHopj+hJvqS8XUQ8A==” crossorigin=“anonymous”></script> <script src=“https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/addons/fit/fit.min.js” integrity=“sha512-+wh8VA1djpWk3Dj9/IJDu6Ufi4vVQ0zxLv9Vmfo70AbmYFJm0z3NLnV98vdRKBdPDV4Kwpi7EZdr8mDY9L8JIA==” crossorigin=“anonymous”></script>
<table> <tbody> <tr><td> <textarea name=“my-python-editor” id=“my-python-editor” data-editor=“python” data-gutter=“1” rows=“50” cols=“90”> import imp, sys sys.path.append('https://raw.githubusercontent.com/littlevgl/lv_binding_micropython/master/lib') import display_driver import lvgl as lv
# lvgl must be initialized before any lvgl function is called or object/struct is constructed!
lv.init()
############################################################################## # Styles ##############################################################################
class ColorStyle(lv.style_t):
def __init__(self, color): super().__init__() self.set_bg_opa(lv.STATE.DEFAULT, lv.OPA.COVER); self.set_bg_color(lv.STATE.DEFAULT, lv.color_hex3(color)) self.set_bg_grad_color(lv.STATE.DEFAULT, lv.color_hex3(0xFFF)); self.set_bg_grad_dir(lv.STATE.DEFAULT, lv.GRAD_DIR.VER); # self.set_bg_main_stop(lv.STATE.DEFAULT, 0); # self.set_bg_grad_stop(lv.STATE.DEFAULT, 128);
class ChartPaddingStyle(lv.style_t):
def __init__(self): super().__init__() self.set_pad_left(lv.STATE.DEFAULT, 10); self.set_pad_right(lv.STATE.DEFAULT, 10); self.set_pad_bottom(lv.STATE.DEFAULT, 10); self.set_pad_top(lv.STATE.DEFAULT, 10);
class ShadowStyle(lv.style_t):
def __init__(self): super().__init__() self.set_shadow_opa(lv.STATE.DEFAULT, lv.OPA.COVER); self.set_shadow_width(lv.STATE.DEFAULT, 3); self.set_shadow_color(lv.STATE.DEFAULT, lv.color_hex3(0xAAA)); self.set_shadow_ofs_x(lv.STATE.DEFAULT, 5); self.set_shadow_ofs_y(lv.STATE.DEFAULT, 3); self.set_shadow_spread(lv.STATE.DEFAULT, 0);
class ContainerStyle(lv.style_t):
def __init__(self): super().__init__() self.set_value_align(lv.STATE.DEFAULT, lv.ALIGN.OUT_TOP_LEFT) self.set_value_ofs_y(lv.STATE.DEFAULT, -10) self.set_margin_top(lv.STATE.DEFAULT, 30)
# lv_style_set_value_ofs_y(&style_box, LV_STATE_DEFAULT, - LV_DPX(10)); # lv_style_set_margin_top(&style_box, LV_STATE_DEFAULT, LV_DPX(30));
# A square button with a shadow when not pressed class ButtonStyle(lv.style_t):
def __init__(self): super().__init__() self.set_radius(lv.STATE.DEFAULT, lv.dpx(8)) self.set_shadow_opa(lv.STATE.DEFAULT, lv.OPA.COVER); self.set_shadow_width(lv.STATE.DEFAULT, lv.dpx(10)); self.set_shadow_color(lv.STATE.DEFAULT, lv.color_hex3(0xAAA)); self.set_shadow_ofs_x(lv.STATE.DEFAULT, lv.dpx(10)); self.set_shadow_ofs_y(lv.STATE.DEFAULT, lv.dpx(10)); self.set_shadow_spread(lv.STATE.DEFAULT, 0);
self.set_shadow_ofs_x(lv.STATE.PRESSED, lv.dpx(0)); self.set_shadow_ofs_y(lv.STATE.PRESSED, lv.dpx(0));
############################################################################## # Themes ##############################################################################
class AdvancedDemoTheme(lv.theme_t):
def __init__(self): super().__init__() self.button_style = ButtonStyle()
# This theme is based on active theme (material) base_theme = lv.theme_get_act() self.copy(base_theme)
# This theme will be applied only after base theme is applied self.set_base(base_theme)
# Set the "apply" callback of this theme to our custom callback self.set_apply_cb(self.apply)
# Activate this theme self.set_act() def apply(self, theme, obj, name): if name == lv.THEME.BTN: obj.add_style(obj.PART.MAIN, self.button_style)
##############################################################################
def get_member_name(obj, value):
for member in dir(obj): if getattr(obj, member) == value: return member
class SymbolButton(lv.btn):
def __init__(self, parent, symbol, text): super().__init__(parent) self.symbol = lv.label(self) self.symbol.set_text(symbol) self.label = lv.label(self) self.label.set_text(text)
class Page_Buttons:
def __init__(self, app, page): self.app = app self.page = page
self.btn1 = SymbolButton(page, lv.SYMBOL.PLAY, "Play") self.btn1.set_size(80, 80) self.btn1.align(page, lv.ALIGN.IN_TOP_LEFT, 30, 30)
self.btn2 = SymbolButton(page, lv.SYMBOL.PAUSE, "Pause") self.btn2.set_size(80, 80) self.btn2.align(page, lv.ALIGN.IN_TOP_RIGHT, -30, 30)
self.label = lv.label(page) self.label.align(page, lv.ALIGN.IN_BOTTOM_LEFT, 30, -30)
for btn, name in [(self.btn1, 'Play'), (self.btn2, 'Pause')]: btn.set_event_cb(lambda obj=None, event=-1, name=name: self.label.set_text('%s %s' % (name, get_member_name(lv.EVENT, event))))
class Page_Simple:
def __init__(self, app, page): self.app = app self.page = page
# slider self.slider = lv.slider(page) self.slider.set_width(160) self.slider.align(page, lv.ALIGN.IN_TOP_LEFT, 20, 20) self.slider_label = lv.label(page) self.slider_label.align(self.slider, lv.ALIGN.OUT_RIGHT_MID, 15, 0) self.slider.set_event_cb(self.on_slider_changed) self.on_slider_changed(None)
# style selector self.styles = [('Gray', ColorStyle(0xCCC)), ('Red', ColorStyle(0xF00)), ('Green',ColorStyle(0x0F0)), ('Blue', ColorStyle(0x00F))] self.style_selector = lv.dropdown(page) self.style_selector.add_style(self.style_selector.PART.MAIN, ShadowStyle()) self.style_selector.align(self.slider, lv.ALIGN.OUT_BOTTOM_LEFT, 0, 40) self.style_selector.set_options('\n'.join(x[0] for x in self.styles)) self.style_selector.set_event_cb(self.on_style_selector_changed)
# counter button self.counter_btn = lv.btn(page) self.counter_btn.set_size(80,80) self.counter_btn.align(self.page, lv.ALIGN.IN_BOTTOM_MID, 0, -20) self.counter_label = lv.label(self.counter_btn) self.counter_label.set_text("Count") self.counter_btn.set_event_cb(self.on_counter_btn) self.counter = 0
def on_slider_changed(self, obj=None, event=-1): self.slider_label.set_text(str(self.slider.get_value()))
def on_style_selector_changed(self, obj=None, event=-1): selected = self.style_selector.get_selected() tabview = self.app.screen_main.tabview if hasattr(self, 'selected_style'): tabview.remove_style(tabview.PART.BG, self.selected_style) self.selected_style = self.styles[selected][1] tabview.add_style(tabview.PART.BG, self.selected_style)
def on_counter_btn(self, obj, event): if event == lv.EVENT.CLICKED: self.counter += 1 self.counter_label.set_text(str(self.counter))
class Anim(lv.anim_t):
def __init__(self, obj, val, size, exec_cb, path_cb, time=500, playback=False, ready_cb=None): super().__init__() self.init() self.set_time(time) self.set_values(val, val + size) if callable(exec_cb): self.set_custom_exec_cb(exec_cb) else: self.set_exec_cb(obj, exec_cb) path = lv.anim_path_t({'cb': path_cb}) self.set_path(path) if playback: self.set_playback(0) if ready_cb: self.set_ready_cb(ready_cb) self.start()
class AnimatedChart(lv.chart):
def __init__(self, parent, val, size): super().__init__(parent) self.val = val self.size = size self.max = 2000 self.min = 500 self.factor = 100 self.anim_phase1()
def anim_phase1(self): self.phase1 = Anim( self, self.val, self.size, lambda a, val: self.set_y_range(self.AXIS.PRIMARY_Y,0, val), lv.anim_path_t.ease_in, ready_cb=lambda a:self.anim_phase2(), time=(self.max * self.factor) // 100, )
def anim_phase2(self): self.phase2 = Anim( self, self.val + self.size, -self.size, lambda a, val: self.set_y_range(self.AXIS.PRIMARY_Y, 0, val), lv.anim_path_t.ease_out, ready_cb=lambda a:self.anim_phase1(), time=(self.min * self.factor) // 100, )
class Page_Chart:
def __init__(self, app, page): self.app = app self.page = page self.chart = AnimatedChart(page, 100, 1000) self.chart.set_width(page.get_width() - 80) self.series1 = self.chart.add_series(lv.color_hex(0xFF0000)) self.chart.set_type(self.chart.TYPE.LINE) self.chart.set_style_local_line_width(self.chart.PART.SERIES, lv.STATE.DEFAULT, 3) self.chart.add_style(self.chart.PART.SERIES, ColorStyle(0x055)) self.chart.add_style(self.chart.PART.BG, ChartPaddingStyle()) self.chart.set_y_range(self.chart.AXIS.PRIMARY_Y, 0,100) self.chart.init_points(self.series1, 10) self.chart.set_points(self.series1, [10, 20, 30, 20, 10, 40, 50, 90, 95, 90]) self.chart.set_x_tick_texts("a\nb\nc\nd\ne", 2, lv.chart.AXIS.DRAW_LAST_TICK) self.chart.set_x_tick_length(10, 5) self.chart.set_y_tick_texts("1\n2\n3\n4\n5", 2, lv.chart.AXIS.DRAW_LAST_TICK) self.chart.set_y_tick_length(10, 5) self.chart.set_div_line_count(3, 3) self.chart.set_height(self.page.get_height() - 60) self.chart.align(page, lv.ALIGN.CENTER, 0, 0)
# Create a slider that controls the chart animation speed
def on_slider_changed(obj=None, event=-1): self.chart.factor = self.slider.get_value()
self.slider = lv.slider(page) self.slider.align(self.chart, lv.ALIGN.OUT_RIGHT_TOP, 10, 0) self.slider.set_width(10) self.slider.set_height(self.chart.get_height()) self.slider.set_range(10, 200) self.slider.set_value(self.chart.factor, 0) self.slider.set_event_cb(on_slider_changed)
class Page_Controls:
def __init__(self, app, page): self.app = app self.page = page # self.page.set_scrl_layout(lv.LAYOUT.PRETTY_TOP)
# not know how does msgbox works # self.mbox = lv.msgbox(lv.scr_act()) # self.mbox.set_text("A message box with two buttons.") # self.mbox.add_btns({"Cancel", "Ok"}) # self.mbox.set_width(200) # self.mbox.align(Null, lv.ALIGN.CENTER, 0, 0)
CtrlBasicContainer = lv.cont(page) CtrlBasicContainer.set_layout(lv.LAYOUT.PRETTY_MID) CtrlBasicContainer.add_style(lv.cont.PART.MAIN, ContainerStyle()) CtrlBasicContainer.set_drag_parent(True) CtrlBasicContainer.align(page, lv.ALIGN.IN_TOP_LEFT, 10, 30)
CtrlBasicContainer.set_style_local_value_str(lv.cont.PART.MAIN, lv.STATE.DEFAULT, "Basics") CtrlBasicContainer.set_fit2(lv.FIT.NONE, lv.FIT.TIGHT) CtrlBasicContainer.set_width( page.get_width_grid(2, 1) );
btn1 = lv.btn(CtrlBasicContainer) btn1.set_fit2(lv.FIT.NONE, lv.FIT.TIGHT) lbl1 = lv.label(btn1) lbl1.set_text("Button1")
btn2 = lv.btn(CtrlBasicContainer) btn2.toggle() lbl2 = lv.label(btn2) lbl2.set_text("Button2")
sw1 = lv.switch(CtrlBasicContainer)
CtrlTextContainer = lv.cont(page) CtrlTextContainer.set_layout(lv.LAYOUT.PRETTY_MID) CtrlTextContainer.add_style(lv.cont.PART.MAIN, ContainerStyle()) CtrlTextContainer.set_drag_parent(True) CtrlTextContainer.align(page, lv.ALIGN.IN_TOP_RIGHT, -1 * CtrlTextContainer.get_width() - 60, 30)
CtrlTextContainer.set_style_local_value_str(lv.cont.PART.MAIN, lv.STATE.DEFAULT, "Text Input") CtrlTextContainer.set_fit2(lv.FIT.NONE, lv.FIT.TIGHT) CtrlTextContainer.set_width( page.get_width_grid(2, 1) );
btn1z = lv.btn(CtrlTextContainer) btn1z.set_fit2(lv.FIT.NONE, lv.FIT.TIGHT) lbl1z = lv.label(btn1z) lbl1z.set_text("Button1")
btn2z = lv.btn(CtrlTextContainer) btn2z.toggle() lbl2z = lv.label(btn2z); lbl2z.set_text("Button2");
class Screen_Main(lv.obj):
def color_chg_event_cb(self, obj, evt): if evt == lv.EVENT.VALUE_CHANGED: flag = lv.THEME_MATERIAL_FLAG.LIGHT; if obj.get_state(): flag = lv.THEME_MATERIAL_FLAG.DARK; # LV_THEME_DEFAULT_INIT(lv_theme_get_color_primary(), lv_theme_get_color_secondary(), # flag, # lv_theme_get_font_small(), lv_theme_get_font_normal(), lv_theme_get_font_subtitle(), lv_theme_get_font_title()); print("TODO: Pasikei2ia templeitas ", flag, )
def __init__(self, app, *args, **kwds): self.app = app super().__init__(*args, **kwds) self.theme = AdvancedDemoTheme()
self.tabview = lv.tabview(self) self.tabview.set_style_local_pad_left(lv.tabview.PART.TAB_BG, lv.STATE.DEFAULT, 120) self.tabview.set_btns_pos(lv.tabview.TAB_POS.TOP)
self.sw=lv.switch(self) self.sw.set_pos(5, 11) self.sw.set_style_local_value_str(lv.switch.PART.BG, lv.STATE.DEFAULT, "Dark") self.sw.set_style_local_value_align(lv.switch.PART.BG, lv.STATE.DEFAULT, lv.ALIGN.OUT_RIGHT_MID) self.sw.set_style_local_value_ofs_x(lv.switch.PART.BG, lv.STATE.DEFAULT, 3) self.sw.set_event_cb(self.color_chg_event_cb)
self.page_simple = Page_Simple(self.app, self.tabview.add_tab("Simple")) self.page_controls = Page_Controls(self.app, self.tabview.add_tab("Controls")) # self.page_buttons = Page_Buttons(self.app, self.tabview.add_tab("Buttons")) # self.page_chart = Page_Chart(self.app, self.tabview.add_tab("Chart"))
# def bandymas(obj, evt): # print('bandymas', obj, evt)
# self.tabview.set_event_cb(bandymas)
lv.scr_load(Screen_Main(lv))
</textarea> </td> <td>
<canvas id=“canvas” width=“480” height=“320” oncontextmenu=“event.preventDefault()” tabindex=“-1”></canvas>
</td> </tr> </tbody> </table>
<script type=“text/javascript”> Hook up ACE editor to all textareas with data-editor attribute jQuery(function() { jQuery('textarea[data-editor]').each(function() { var textarea = $(this); var mode = textarea.data('editor'); var editDiv = $('<div>', { position: 'absolute', width: textarea.width(), height: textarea.height(), 'class': textarea.attr('class') }).insertBefore(textarea); textarea.css('display', 'none'); var editor = ace.edit(editDiv[0]); editor.renderer.setShowGutter(textarea.data('gutter')); editor.getSession().setValue(textarea.val()); editor.getSession().setMode(“ace/mode/” + mode); editor.setTheme(“ace/theme/tomorrow”); copy back to textarea on form submit…
textarea.closest('form').submit(function() { textarea.val(editor.getSession().getValue()); }) });
});
/*Write text to the terminal */ function sendText(text) { var print = new Event('print'); print.data = text; mp_js_stdout.dispatchEvent(print); } function processScriptArg(url){ // read text from URL location var request = new XMLHttpRequest(); request.open('GET', url, true); request.send(null); request.onreadystatechange = function () { if (request.readyState === 4 && request.status === 200) { var type = request.getResponseHeader('Content-Type'); if (type.indexOf("text") !== 1) { mp_js_do_str(request.responseText); } } } } Module.canvas = (function() { var canvas = document.getElementById('canvas'); return canvas; })(); var lines = [ "import lvgl as lv", "lv.init()", "import SDL", "SDL.init()", /* Register SDL display driver. */ "disp_drv = lv.disp_drv_t()", "lv.disp_drv_init(disp_drv)", "disp_drv.disp_flush = SDL.monitor_flush", "disp_drv.disp_fill = SDL.monitor_fill", "disp_drv.disp_map = SDL.monitor_map", "lv.disp_drv_register(disp_drv)", /*Regsiter SDL mouse driver*/ "indev_drv = lv.indev_drv_t()", "lv.indev_drv_init(indev_drv)", "indev_drv.type = lv.INDEV_TYPE.POINTER;", "indev_drv.read = SDL.mouse_read;", "lv.indev_drv_register(indev_drv);", /* Create a screen with a button and a label */ "scr = lv.obj()", "btn = lv.btn(scr)", "btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)", "label = lv.label(btn)", "label.set_text('Button')", /* Load the screen */ "lv.scr_load(scr)" ]; /*Initialization function*/ window.onload = function() {
Terminal.applyAddon(fit); term = new Terminal(); mp_js_stdout = document.getElementById('terminal'); mp_js_stdout.value = ""; term.open(mp_js_stdout); term.fit(); /*Initialize MicroPython itself*/ mp_js_init(1 * 1024 * 1024); /*Setup printing event handler*/ mp_js_stdout.addEventListener('print', function(e) { text = e.data; term.write(text); }, false); /*Setup key input handler */ term.on('data', function(key, e) { console.log(key); for(var i = 0; i < key.length; i++) { mp_js_process_char(key.charCodeAt(i)); } }); /* Run init script */ for(var i = 0;i < lines.length;i++){ mp_js_do_str(lines[i]); }
/* Run custom script if passed */ var custom = undefined; try { custom = new URL(window.location.href).searchParams.get("script"); } catch (e) { console.log(e + ": URL seems to be unsupported"); } console.log("Custom script: " + custom); if(custom !== undefined && custom !== null) processScriptArg(custom);
/*Setup lv_task_handler loop*/
var the_mp_handle_pending = Module.cwrap('mp_handle_pending', null); function handle_pending() { the_mp_handle_pending(); setTimeout(handle_pending, 20); // should call lv_task_handler() } /*Initialize the REPL.*/ mp_js_init_repl(); /*Start the main loop, asynchronously.*/ handle_pending(); }
</script>
</html>