Modular and extensible UI framework and ui elements.

Posted on
  • 1 of n

    A while ago I played around with touch screen displays that resulted in a quite terse, resource frugal UI implementation: UI Module w/ Buttons, Checkboxes,... for Display w/ Touchscreen.

    Recently I picked up where left of and completed what I was originally going for. Several serious refactoring cycles lead to the 'thing' I'd like to share, to contribute as generally available Espruino modules, and also to provide some tutorials to introduce the rich options... last but not least an introduction how to build and integrate your own ui element extensions.

    Already too many words, therefore a picture right away... actually more than one... See image attachments showing Buttons, Check Boxes, Radio Buttons, Sliders and even a soft '101'-Key keyboard, all on a touchscreen LCD (...which you get for a few bucks).

    More out of a need or constraint than intentionally, I developed a simple cross development environment in the Web browser - after all, it is with display, and the browser has what is needed: display AND JavaScript. The browser gets the modules from the same sand box folder as the Espruino Web IDE and thus validation in the real environment is just an upload click away... (...is as close as an upload click... on the same screen, just in different window). I'll share crosses development as well. At this point it is developed to the point to support this particular ui framework development work, but it has the core ingredients - such as the cache - that allows to add emulating modules for many hard ware modules to run complete applications.


    3 Attachments

    • ui_displayR.jpg
    • ui_espruinoCrossDevRuntie.png
    • ui_displayWithBoardR.jpg
  • 2 of n

    To provide a first glimps into the components, here some code facts:

    • ui.js uses 247 variables for code and data.
    • uiBtn.js uses 90 variables for code, and about 25 variables for each instance.

    The numbers for the slider ui element have not exactly settled yet, but are around the double of a plain button... considering the capabilites, still a very small foot print...

    ...and some code:

    // ----- pull in dispaly and touchscreen
    var dsp, dMod = require("ILI9341"),
        touch, tMod = require("XPT2046");
    
    // ----- pull in ui base and ui element
    var ui = require("ui")
          .add(require("uiBtn"))
          ;
    
    // ----- define callbacks (to log ui element id and value)
    var cb = function(id,v) { console.log(id + ": " + v); };
     
    // ----- define UI (in level 0, so it does not use memory for source)
    
    //   0  1     2       3  4     5    6    7   8
    // flgs clazz id      x  y     w    h   bc  fc
    //      btn                 ->x2 ->y2         
    ui.c(3,"btn","b1"  ,  5, 40,  65,  35,  4,   4
    
    //                    9       10  11 
    //                    valObj  cb,  l (label array obj)
    //                                 fv tc    x  y  label text
                       , "B_1",   cb,  [15, 7,  13, 9, "RED"  ]);
                       
    ui.c(3,"btn","b2"  , 70, 40,  65,  35,  5,   6
                       , {v:1},   cb,  [15, 0,   9, 9, "Y-w-B"]);
    
    // ----- run UI
    function onInit() {
      SPI1.setup({sck:B3, miso:B4, mosi:B5, baud: 1000000});
                       // spi, dc, cs, rst, callback
      dsp = dMod.connect(SPI1, B7, B6, A8, function() {
          dsp.clear(); A5.set(); // display clear and back light on
          // connect ui to dsp and display it
          ui.connect(dsp)
            .w(0,0,239,319) // wipe screen w/ background color
            .d() // display all elements
            .di=true; // set display changes to immediate
          // setup touchscreen and connect it to ui
          SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 2000000});
          touch = tMod.connect(
              // spi, cs, irq, callback, calc (calibration calc function)
              SPI2, B10, B1, function(x,y) { ui.evt(x,y);
              }, function(yr, xr, d) {
                return [ Math.round(xr / -121.44          + 259.70685111989) 
                       , Math.round(yr /   88.90357142857 + -19.78130398103)
                       ];
          });
          if (touch._eRegisterCanvas) { // only in emulation and before listen
              touch._eRegisterCanvas("dspCanvas", 10, 10); }
      });
      if (dsp._eRegisterCanvas) { // only in emulation dev and before drawing
          dsp._eRegisterCanvas("dspCanvas", 240, 320); }
    }
    
    onInit(); // development convenience only... not part of final, saved application code.
    

    onInit() invocation does not really belong to the application code... but while developing, it is is very convenient, because the system behaves the same way as with saved code and power-cycling but without actually having to save the code and power-cycling... ;-)

    To understand touch screen related lines 45..47, take a look at recent Touchscreen conversation.

    Lines 49..50 and 52..53 are cross development environment related and were a quick (and dirty) compromise to keep the emulating modules application independent... These lines do not belong into Espruino, and that's why they are conditioned and therefore do no harm...

    As in above paragraph, emulation shows... but really marginal... and with some smart thinking - or (with some not so beloved) conventions - emulation can become completely transparent.

    The code shows how the Espruino code is prefixed in order to run in cross development. Below few javascript lines are the only entries required to precede the Espruino code to run it in an html document:

    <script src="_emulationConfig.js"></script>
    
    <script>function _eeLoad(eComponentName) {
      document.writeln(['<scri','pt src="',_eEmulationPath,eComponentName,'.­js"></scri','pt>'].join("")); }
    </script>            
    
    <script>_eeLoad("_eEspruinoJsShim");</sc­ript>
    <script>_eeLoad("_eEspruinoPicoShim");</­script>
    
    <script> // (pre) load emulating modules - emulating code upload to board
    _eeLoad("ILI9341"   );
    _eeLoad("TouchRD");
    </script>
    
    <script> // (pre) load (non emulating) modules - emulating code upload to board
    _emLoad("ui");    // ui base (code and runtime data holder)
    _emLoad("uiBtn"); // uiBtn (Button)      element
    </script>
    
    

    As obvious, a plain html file is used. To avoid a Web server, it is all pulled with just file:// protocol from directories which are configured in line 1 - pulled in as well from a java script fragment while the page is loaded... same concept as files are uploaded into Espruino, they get evaluated... and so does the html with embedded code when pulled in by the browser.

    Lines 3..5 show this loader that adds javascript on the go, as you see in lines

    • 7..8: Espruino ecology with emulated board
    • 11..12: Emulated display and touchscreen modules
    • 16..17: ui base and uiBtn ui element modules

    I was surprised how well the UI behaves regarding speed - even though the communication with the display is serial... Text (drawString()) still drags its feet - understandably - but all other things are extremely snappy, such as visual touch feedback. I guess it is thanks to @JumJum who recently made some speed enhancement when using the Graphics objects - the 'inner' implementing of the LCD displays...

  • Have you posted the module somewhere accessible?

    Thanks,

  • ...got a bit stuck in doc and work... will show in public in a bit...

  • @user54159 , check your forum messages...

  • @allObjects Thanks!!!!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Modular and extensible UI framework and ui elements.

Posted by Avatar for allObjects @allObjects

Actions