Modular and extensible UI framework and ui elements.

Posted on
Page
of 2
Prev
/ 2
  • Sat 2019.09.28

    What a fantastic contribution @allObjects

    I'm sure you are proud of the final result, now with the finish line in sight!!

    Had a hunch there would be a fair amount of updating content when I recognized the dozen of link earmarked entries a week ago.

    Although I won't have immediate time to delve into your accomplishment right now, will set aside some time this winter.

    Well done. Congrats!
    Robin


    EDIT: (ten minutes later)
    Curiosity got the better of me:

    Love the immediate run/launch with the Html pages. Just tried the button press uiExample.html and it works without configuration in Chrome on Windows10, just launch and go. Simple, intuitive, impressive. BRAVO!

  • ----- 2019-09-30 Update -----

    Espruino Pixl makes its debut the ui framework... see the Preview in ---> post #18.

    From #post 18, download, unzip the attached zip file with the _sbx Sandbox folder, make Espruino Web IDE point to this sandbox folder and load the uiExamplePixl.js project file.

  • New update - with work in progress - that includes Emulations for Pixle.js and even Bangle.js... some work is still going on, especially for handling the non-touch and limited touch screens. Navigation from element to element in the ui works, 'clicking' on (regular) buttons, checkboxes and radio buttons work. Clicking on horizontal and vertical slider are setting their values so far - matter fact of touch emulation in the center - to the middle value. More to come there. Since all is JavaScript you can write code to practically emulate what ever you think of... You would just not emulate on the very low level hardware, but on the module level, add value input fileds and buttons to the html view to bring the module to life and let your application handle it properly in the emulation. This way even coding and emulating of time sensitive / ui dynamic applications are possible. The code already includes Pins and Buttons - specified in the board includes - and setWatch/clearWatch for buttons in the emulator HTML view. If you miss a behavior or item, just extend existing item or add a new one.

    Updated zip file is to be found in --->post #7 .


    3 Attachments

    • uiLCDTFTXDev2.jpg
    • uiSlidersTFF.png
    • bangle_emulationFirstShot.png
  • Have you tried your UI with the Bangle Emulator?

  • Yes I did and I like it very much... I know that - for some - an emulator may take a bit the push away to get a real board... on the other hand it makes development of logic so much easier, especially since the upload over BLE 'snails'.

  • @allObjects

    [ ] How to use firmware included touch screens with ui?

    Bangle2 Emulator

    >Bangle.on('touch', function(zone,e) {print(zone,e);})
    =undefined
    1 { "x": 33, "y": 36, "type": 0 }
    2 { "x": 121, "y": 36, "type": 0 }
    ... 
    

    ESP32 CYD

    E.on('touch',(e)=>{print(e);});
    =undefined
    // b = 1 : touch, b = 0 : released
    { "x": 197, "y": 116, "b": 1 }
    { "x": 197, "y": 116, "b": 0 }
    ...
    

    [ ] How to use build in fonts with ui?

    // Bangle2 Emulator
    >g.getFonts()
    =[
      "4x6",
      "6x8",
      "12x20",
      "6x15",
      "Vector"
     ]
    > 
    
    // ESP32 CYD
    >g.getFonts()
    =[
      "4x6",
      "6x8",
      "Vector"
     ]
    
    

    check for setFontXXXXX functions show that setFont6x8 is missing because it is different included than 6x15.

    g.setF
    setFont             setFont12x20
    setFont6x15         setFontAlign
    setFontBitmap       setFontCustom
    setFontPBF          setFontVector
    

    Solution: Including "6x8" directly into the ui.fnts array and make sure it can set via g.setFont6x8

    // add included Font
    ui.fnts.push('setFont6x8');
    g.setFont6x8 = function(){g.setFont("6x8");};
    

    [ ] Any plans to include uiG(auge) as module?

  • @MaBe,

    looks like that these are you questions:

    a. [ ] How to use firmware included touch screens with ui?
    b. [ ] How to use built-in fonts with ui?
    c. [ ] Any plans to include uiG(auge) as module?

    Generally speaking: starting out with a (custom named and referenced) wrapper that is housing the built-in things - touch / font - is good to start with. The reason for that is that when the UI was built, bangles weren't around yet... But it should then be easy to modify the code to drop the wrapper and use the built-in appliances directly. All is pulled in as modules, so changes can happen gradually.

    Since displays have quite some variations, take a look at how colors and fonts are referenced in the ui definition and how the respective support mapes it into the hw context. Modules are also pulled by name dynamically, so control can happen in a single place w/ a config-like object, which then can be made dependent on the context / hw ID.

    ttyl.

    ao

  • Yes and have one more for now.

    d. [ ] Can ui switch to Anti-Aliasing functions if available?

  • It could affect some functionality if the font goes too close to the borders. I show a frame around an active field and clear it w/ the back ground color and if the anti-aliasing goes 'too close' to it, you may notice the interference. In the context where and for what the UI was done, memory is on short supply... so no layering... layering would have been the answer to many things.

  • Since the UI framework was conceived, a lot has changed in Espruino world. The most impacting change is that Bangle2 has a built in touch screen and firmware functions way superior to the touch modules ever existed.

    Basic touch modules deliver two (2) types of events:

    1. touch w/ x and y populated in the callback (as 1st touch down event and subsequent events on dragging
    2. untouch w/ x and y *** NOT *** populated in the callback (undefined)

    That is the reason that the ui.evt(x,y) is passed no information wether it is a touch or untouch, because an even with x or/and y being undefined provides the touch or untouch distinction. Since the untouch has no coordinates, the ui module kept track of what the last x and y was.

    Rewriting of ui.evt(x,y) is an option, but before going there, using event Bangle.drag logically by emulating the simple touch with x, y and untouch without x, y will do the job, and lets ui module keep the handling of x and y on untouch...

    Two (2) sections the introductory page at espruino.com/ui - UI Framework for microcontrollers are affected:

    1. Devices - is to be skipped, since for Bangle2 all is there already.
    2. Define the onInit() function - looks much simpler:

      function onInit() {
      // connect ui to dsp and display it
      ui.connect(g)
      .w(0,0,176-1,176-1) // wipe screen (rect) w/ default / bg color
      .d()                // display all elements
      .di = true;         // set display changes to immediate
      // connect touch sreen to ui
      Bangle.on("drag",(t)=>{ if (t.b) ui.evt(t.x,t.y); else ui.evt(); }); 
      } // /onInit()
      

    Take a look at the complete code - same example as documented at https://www.espruino.com/uiExampleBtn:

    // ----- setup lon and log() (considering emulating _eConsole)
    var lon = true // logging is on / off
      , log = function() { if (lon) { var lgr;(lgr=(typeof _eConsole
           =="object")?_eConsole:console).log.apply(lgr,arguments);}};
    
    // ----- pull in ui base and ui element(s)
    var ui = require("ui")
        .adx(require("uiExt")) // only when push button control is required / no touch
        .adx(require("uiEBC")) // only when push button control is required / no touch
        .adx(require("uiBtn")) // ui plain button element
        .adx(require("Font8x16"),-2,"Font8x16") // fs: -1 - custom bitmap font
        ;
    
    // ----- define callback(s): preferred (untouch) / generic (all) touch event(s)
    var cb = function(id, v, _, e, t) { log( "id:",id,"val:",v
            ,(t)?((t.t)?"":"un")+"touch focused":t); }
      , ca = ( (typeof ca === "undefined")
             ? function(id, v, _, e, t) { var s=(t.f|65536).toString(2); // log flags
                 log("c:",e[1],"c:",e[1],"id:",id,"v:",v,"f:",[s.substr(5,4),s.substr(9,4),s.substr(13,4)].join(" "),t.f); }
             : ca )
      , u; // for space / memory / var saving value of * undefined *
    
    // ----- define UI (in level 0 - built to be saved)
    
    //---------- Button examples ----------
    //
    //    0  1     2       3   4   5   6   7   8  9       10  11                         12
    // flgs  clazz id      x   y   w   h  bc  fc  valObj  cb,  l (label array obj)
    //       btn                ->x2->y2                        fs tc    x  y label txt  ca
    ui.c( 3,"btn","b1"  ,  5, 40, 65, 35,  4,  4, "B_1",  cb,  [15, 7,  19,12, "RED"  ]);
    ui.c( 3,"btn","b2"  , 70, 40, 65, 35,  5,  6, {v:1},  u ,  [-1, 0,  10,10, "BonYbg"],ca);
    
    // ----- run UI
    function onInit() {
      // connect ui to dsp and display it
      ui.connect(g)
        .w(0,0,176-1,176-1) // wipe screen (rect) w/ default / bg color
        .d()                // display all elements
        .di = true;         // set display changes to immediate
      // connect touch sreen to ui
      Bangle.on("drag",(t)=>{ if (t.b) ui.evt(t.x,t.y); else ui.evt(); }); 
    } // /onInit()
    
    setTimeout(onInit,999); // for dev only, remove before upload for save()
    

    Since dealing with (vector) fonts is always a bit a lottery, the position of the RED button label needed some adjustment.... Interestingly, the label in the second button did just fine...

    @MaBe pointed out that there are some other things that need minor changes... one is related to how (default) fonts are loaded and set in current Espruino Graphics object. More about that from @Gordon or me, later on.

    As a closing icing on the cake, I'd like to introduce - re-introduced - a more elaborate callback for the RED button:

    1. RED Button turns (emulated) red LED on and off - see attached screenshot!
    2. RED Button shows in label what pressing the button will do: turn the LED off or on.


    1st change:

    ...
    var redLED = false // defines the red LED1 (initial) state
      , cb = function(id, v, _, e, t) { digitalWrite(LED1, redLED = !redLED); } // toggles the red LED1
    ...
    

    2nd change:

    ...
    var redLED = false
      , cb = function(id, v, _, e, t) {
                 digitalWrite(LED1, redLED = !redLED);
                 e[11][4] = "RED " + (redLED) ? "off" : "on"; // Set (just) the label text
                 // e is the ui element, [11]th property is label, and [4]th is the text
                 console.log(e); // dump ui element e in console to show its state
                 return true; // make the button to be redrawn
             }
    ...
    

    The 2nd change needs also some layout changes because of the longer button label text (widening the RED button by 5 px (w+5) to 70 and moving the 2nd button 5 pixel (x+5) to the right to 70):

    //---------- Button examples ----------
    //
    //    0  1     2       3   4   5   6   7   8  9       10  11                         12
    // flgs  clazz id      x   y   w   h  bc  fc  valObj  cb,  l (label array obj)
    //       btn                ->x2->y2                        fs tc    x  y label txt  ca
    ui.c( 3,"btn","b1"  ,  5, 40, 70, 35,  4,  4, "B_1",  cb,  [15, 7,   8,11, "RED on"]);
    ui.c( 3,"btn","b2"  , 75, 40, 65, 35,  5,  6, {v:1},  u ,  [-1, 0,  10,10, "BonYbg"],ca);
    

    Running the second change (after all those years) became a surprise:

    Unfortunately, something has changed in the Espruino js interpreter when it comes to address an array literally with a 0 as the console points out:

    [ 7,
      "btn",
      "b1",
      5, 40, 74, 74, 4, 4,
      "B_1",
      function (id,v,_,e,t) {
      digitalWrite(LED1, redLED = !redLED);
                 e[11][4] = "RED " + (redLED) ? "off" : "on"; // Set (just) the label text
                 // e is the ui element, [11]th property is label, and [4]th is the text
                 console.log(e);
                 return true;
    },
      [ 15, 7, 8, 11,
        "off"
       ],
      undefined ]
    Uncaught Error: Field or method "0" does not already exist, and can't create it on Number
     at line 1 col 7
    if(e[0]&1)_[e[1]+"D"].apply(_,e)
          ^
    in function called from line 1 col 84
    ...1)_[e[1]+"D"].apply(_,e)},_);if(f)f(_,e);return _
                                  ^
    in function "d" called from line 1 col 54
    if(c=c&&(c=e[10])?c:e[12])if(c(e[2],e[9],_,e,t))_.d(e)
                                                         ^
    in function "btn" called from line 2 col 422
    ...t.f|=16;if(!_[e[1]](_,e,t,1))_.blr(e)}[_.lf,o=_.af].forEach(...
                                  ^
    in function "evt" called from line 1 col 39
    if (t.b) ui.evt(t.x,t.y); else ui.evt();
                                          ^
    in function called from system
    > 
    

    Something weird... because when duping the element in the console, it shows value 7 - 4 flags set - in its array (state members of the ui element)... even when dumping it after the error happened...

    Weird, because when accessing the value in console's REPL, it can do so:

    =[ 7,
      "btn",
      "b1",
      5, 40, 74, 74, 4, 4,
      "B_1",
      function (id,v,_,e,t) { ... },
      [ 15, 7, 8, 11,
        "off"
       ],
      undefined ]
    >ui.es[0][0] // accessing 1st property of 1st ui element (directly)
    =7
    >var e = ui.es[0]; // ...indirectly... via variable...
    =[ 7,
      "btn",
      "b1",
      5, 40, 74, 74, 4, 4,
      "B_1",
      function (id,v,_,e,t) { ... },
      [ 15, 7, 8, 11,
        "off"
       ],>ui.es[0]
    =[ 7,
      "btn",
      "b1",
      5, 40, 74, 74, 4, 4,
      "B_1",
      function (id,v,_,e,t) { ... },
      [ 15, 7, 8, 11,
        "off"
       ],
      undefined ]
    >ui.es[0][0]
    =7
    >var e = ui.es[0];
    =[ 7,
      "btn",
      "b1",
      5, 40, 74, 74, 4, 4,
      "B_1",
      function (id,v,_,e,t) { ... },
      [ 15, 7, 8, 11,
        "off"
       ],
      undefined ]
    >e[0]
    =7  undefined ]
    >e[0] // ...accessing via variable...
    =7
    

    Looking at the ui.js module code - .d(e,f){...} display function - it shows the following construct:

    , d: function(e,f) { // display / redraw ui element e, redraw all if e falsy,
                         // and if f, call f w/ ui,e f for extra 'drawings' or action
        var _=_||this
             , es = (e) // if ui element e is passed, build array w/ e as its only item
                  ? [e]
                  : _.es.slice(_.b,_.n);
        es.forEach(function(e){ // iterate over array - all ui elements in the array
          if (e[0]&1) // if visible flag is set...   <<<<<===== interpreter issue???
               _[e[1]+"D"].apply(_,e); // ... call element's Display method
        });
        if (f) f(_,e); // do the extra things...
        return _;
      }
    

    From looking at the code and its syntax, the error message makes no sense what so ever... The literal integer number 0 should be recognized by the interpreter as such and used as the index... and not as a not defined variable / symbol...

    (Yes, the construct re-uses the variable e in the iterators function as local parameter... but it has its own scope... does it?)


    1 Attachment

    • uiButtonsInBangle2.png
  • 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