project:lvgl-simulator:start

<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>

  • project/lvgl-simulator/start.txt
  • Last modified: 2020/10/08 23:38
  • (external edit)