-
• #2
2 of n posts
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 capabilities, still a very small foot print...
...and this is the actual code:
Tip for best display of code sections without line wrapping : change browser window to the sweet spot where no line wrapping happens.
// ----- 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.
The
onInit()
invocation - last line in the code - 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 on power-cycling but without actually having to save the code and do a 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 do therefore 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 required entries to precede the Espruino code to run it in an plain html document in a Web browser:
<script src="_emulationConfig.js"></script> <script>function _eeLoad(eComponentName) { document.writeln(['<scri','pt src="',_eEmulationPath,eComponentName,'.js"></scri','pt>'].join("")); } </script> <script>_eeLoad("_eEspruinoJsShim");</script> <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 ecosystem 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...
-
• #3
Have you posted the module somewhere accessible?
Thanks,
-
• #4
...got a bit stuck in doc and work... will show in public in a bit...
-
• #5
@user54159 , check your forum messages...
-
• #6
@allObjects Thanks!!!!
-
• #7
uiReadMe.txt
Hi,
The modular and extensible ui framework for Espruino from allObjects - is now ready for use 'as is' (finishing touches still ongoing).
6 folders - _sbx (an espruino sandbox ready to be used), _ecomponents, uidev, edev, uidoc and uixsrcmaterial - and this post as text in ui.zip file fort download below.
Unzip them into any directory. Make _sbx the sandbox folder in Espruino Web IDE. Upload the (example) projects to run them on your Espruino board.
Not the right hardware (yet) at hand? or: Not much time either for a sneak peek? - No problem:
Look at and play around with the very same examples in your Browser...
To run / develop the same modules and projects in emulation / cross development mode in Browser: open .html files - uiExample.html - in uidev folder and click link all.
uxscrmaterial folder contains many useful examples and older, simpler versions of the ui, most of them still working. Some of them will migrate over time into the actual modules and projects folders.
Goal is to harden the modules, grow the example pool, add examples for various hardware, also hardware without touch screen support, and make it all available on the Espruino site - as modules and as tutorial(s).
best js hacks - @allObjects
Attached: shot showing zip file content, ui_20190927.zip (zipped ui folder w/ all you need for ui). - ui_20191119.zip - newer version (still in work)
3 Attachments
-
• #8
----- ui_ ------------------------- 20190927 - intro
*** modular and extensible (graphical) ui framework - regular version.
The framework consists of a bases module which provides the infrastructure
for individual out of box and custom ui elements and utility extensions.
Out of box ui elements include (for now):- plain button
- check box
- radio button
- slider
- input field
- keyboard (soft keyboard / touch keyboard)
An out of box extension provides utility and convenience functions and
is required for more complex ui elements - for now - for - out of box -
radio button, and is also useful for the application to easy access
ui elements.Creating and integrating custom ui elements and extensions as needed
is easy based on the architecture and available documentation and
ready to run examples. Examples can be run on actual Espruino and
display with and - soon also - without touch screen. Most of the
examples run also emulated in cross development environment in any browser
as html sharing the Espruino JavaScript files - that's how and where
the ui framework and ui elements are developed and maintained for most
of their functionality.All ui elements handled by ui framework have roughly 12 (13) common
properties in same and similar structure(s):- flags - hidden/displayed, touch active, read/display-only, in focus,...
- clazz - btn-Button, chk-Checkbox, rad-Radiobutton, sli-Slider, inp-Inputfield,...
- id of ui element - enabling sharing callbacks and other nifty things,
such as keeping additional, application specific state and behavior
the ui framework does not cater for (yet) or will never do or can... - x and y position - left-top of ui elements bounding box
- width and height
- border and fill colors
- a value (object) enabling sharing callbacks and other nifty things
- a preferred callback - fired on untouch after touch down on same ui element
- some label object(s) - plain, static text but also as renders (functions)
- (optional, NON-preferred, experimental callback called on all touch events)
Only the 1st 9 of the 12 (13) properties are really mandatory. Same
values in same structures have lead to an implementation of the ui
elements as light weight, lean 'array objects' in order to save memory
/ variables.Details about the ui element specific properties for construction and
runtime are documented for each ui element separately.The ui communicates input (and other) events through callbacks. The
callback arguments include all pertinent information to allow a straight
forward, from simple to sophisticated use in the application and keep the
code terse in order to save memory / variables:- id of ui element
- value (object) of ui element
- ui singleton (module) for accessing all statuses / ui elements / ui aspects
- ui element subject to touch event (for optional query/change by application)
- touch event object (touch/untouch and position on display / ui element, flags)
Attached shot: ui start up w/ all ui element types and keyboard (in emulation).
1 Attachment
- plain button
-
• #9
----- ui_ ------------------------- 20190919 - intro
*** ui framework - base module - intro
The
ui
base module takes care of most of the plumbing, logic and data
flow between touch screen (or physical buttons) and display as input and
output components and controling application.--- Implementation approach
The
ui
base module is currently implemented as singleton, literally constructed
when loaded (required). At runtime it does not only hold on to its own code and
data but also the mixed in code for the various ui element 'types' as
needed (as loaded on demand byrequire()
) and the data of the
created ui elements. The ui elements are implemented a light weight array
objects: just data and - where needed - some format function(s).--- Memory / Variable usage
Below some (ballpark) figures on various usage, categorized as U
for unminified vs. M for minified and I for individual vs C for cumulated.// vars (Idividual|Cumulated) IU / IM - CU - CM B (Un|Minified) var ui = require("ui") // 314 / 282 - 361 - 302 20 (-Base) .add(require("uiExt")) // 237 / 214 - 598 - 515 .add(require("uiRad")) // 190 / 168 - 788 - 683 ; var ui = require("ui") // 314 / 282 - 361 - 302 20 .add(require("uiBtn")) .add(require("uiChk")) .add(require("uiExt")) // 237 / 214 - 598 - 515 .add(require("uiRad")) // 190 / 168 - 788 - 683 ;
Minification setting in Espruino Web IDE: Esprima (offline) for both code
in Editor window and from modules.*** Basic Application of ui base and - as example - use of uiBtn (Button) element
Get ui base and ui elements and build ui - like a DOM - by ui definitions in
level 0. The build is executed on upload to Espruino.save()
will save
the built ui. TheonInit()
function will start the already built ui
on power up, after save() or - while under development - manually by
invocation in console or automatically in asetTimeout()
(see below).--- Require ui components
Get ui base and ui elements to the extent as needed into the system,
such as uiBtn, uiSli(der), etc.var ui = require("ui") // getting ui base code (w/ 8 default colors) .add(require("uiBtn")) // add / mixin btn ui elt support into ui ;
----- Define UI and add elements
Definition of UI(s) - creation of 'DOM'(s) - best happen (with Espruino)
on code upload and is/are as such then saved on save(), but not displayed
(rendered) yet. Creating it dynamically is possible as well. Example UI
below defines ui with two (2) buttons -b1
andb2
- which on
release (untouch, tap) will call the example callbackcb
. Button ui
element definition includes just data and requires out of box no format
functions. For more details see uiBtn module (unminified code) and related
documentation.// 0 1 2 3 4 5 6 7 8 9 10 11 // flas clazz id x y w h bc fc valObj cb, l (label array obj) // btn ->x2->y2 fv tc x y text ui.c( 3,"btn","b1" , 5, 40, 65, 35, 4, 4, "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"]); // bc/fc/tc: border/fill/text colors; cb=callback(id, v, ui, e, t): id: button id, // such as "b1"; v, ui, e, t provide btn value, ui, elt and touch event runtime // data; colors: 3-bit depth coded: 0b### ###=rgb (0=black, 7=white, 4=red,...)
--- Define application stuff
The application acts on ui events that are communicated thru callbacks.
This sample callbackcb
- for simplicity reason - just logs the
buttons' id and value (object) in the console.function cb(id,v,_,e,t) { console.log(id+": "+v); } // sample callback
--- Do devices stuff
Device stuff happens on upload - once - and defines the display and the
touch instance and module variables and sets latter accordingly.The
ILI9341
display controller used in the examples is a 240 x 320
pixel, max 16-bit color, TFT display controller. Other controller can be
used as well with adjusted width and height values and color definitions.If the touch screen has a controller, use its module - like
XPT2046
for resistive touch screen (XPT2046 works also for theADS7843
controller); otherwise use the module that can handle a resistive touch
screen directly (TouchRD - from: Touchscreen, Resistive, where membrane
edge traces are Directly connected to Espruino pins and controlled and
sensed by Espruino).// instance and module variables: // var dsp, dspMod = require("ILI9341"); // display var touch,touchMod = require("XPT2046"); // touch screen controller // or: var touch,touchMod = require("TouchRD"); // touch screen w/o controller
--- Define the onInit() function
Function
onInit() {...}
gets everything initialized, connected and
started. The code below shows touch screen controller module for touch
screen connection (XPT2046
can also be used for equally
specifiedADS7843
). Pins used are related to PICO.function onInit() { // on power on/save() setting up all from scratch // setup and connect display, then ui and input (touch | phys btns) SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 1000000}); // display dsp = dspMod.connect(SPI2, B10, B1, A4, function() { // using... // ...spi, dc, cs, rst, callback dsp.clear(); A1.set(); // display clear and turn back light on ui.connect(dsp) // connect ui to dsp and display it .w(0,0,dspW-1,dspH-1) // wipe screen (rect) w/ default / bg color .d() // display all elements .di = true; // set display changes to immediate SPI1.setup({sck:A5, miso:A6, mosi:A7, baud: 1000000}); // touch inp touch = touchMod.connect(SPI1, A3, A2, function(x,y){ ui.evt(x,y);} // ...spi, cs, irq, callback, /. calibrated... , function(yr, xr, d) { // ...function, maps touch to x/y of dsp return [ Math.round(xr / -121.44 + 259.70685111989) , Math.round(yr / 88.90357142857 + -19.78130398103) ]; } ).listen(); // for XPT2046 module (ADS7843: not needed/supported) } ); } // /onInit()
--- Start the code after uploadis
After uploading the code, enter
onInit()
in the Espruino IDE console
to get the code started. For convenience you can add the following line as
last line in the code, which gets the code automatically going after
upload has successfully completed. Note though to remove or comment this
line on the last upload before saving the code withsave()
:setTimeout(onInit,999); // for dev; remove before upload for save()
*** Description of (graphical) ui base module and touch controller interface
--- Functions / methods of ui base module
The
ui
base module provides also convenience functions/methods to be
used in application to deal with ui elements as well as plain graphics. Due to
ui's extensibility, you can add easily your own ui element or plain function
extensions as desired (with.add(module);
)..evt(x,y)
- main entry point for touch and touch emulating functions (tap
function in uiExt module). A tap starts with invocation of .evt(x,y)
with x and y values; subsequent invocations with x and y values
indicate dragging, and invocation without x and y indicate an un-touch,
which completes a tap or touch. ui base module keeps track of the
changes and makes them available to the application thru callbacks
with the ui singleton - variableui
/_
- and touch event
objectt
with detailed flagst.f
. Any other 'entries' can
be used but keeping the states consistent become the burden of the
application and is not recommended..iib(x,y,e)
- returns true when x and y (of touch) lay in bounding box of
ui element e.foc(e)
- set focus to element e (and takes it away from element that had
it so far).blr(e)
- blur/unfocus element e (if .blr(), element currently in focus is
blurred).w(x,y,w,h,c)
- wipe rectangular area at x/y and w(idth)/h(eight) of
display w/ optional color c; default color is background color (.bc)..c(arguments)
generic, single point entry for creating ui elements. Uses
first arguments[1] as class or type name and concatenates it with "C"
for specific create entry. To create a custom ui element and
integrate it (with .add(require("customUiElementModule")) is
discussed in a separate publication..d(e)
- (re) draw element e, and when just .d(), redraw the whole ui (all ui
elements). In general, a ui is built on upload without displaying it
to save variables and displayed on demand or in onInit() to
re-display on every re-power up or reset. Note ui elements with
custom (label) renderers / formatters that use ui () or touch
event states / flags (.te.f, t.f), these states / flags in their
logic, such as the optional value renderer / formatter of the slider,
this logic needs adjustment, or, the state(s) / flag(s) need to be
set accordingly, latter though without interfering with their overall\
life cycle or their dependents (ui components' logic)..clr(c,i)
- set color according this.clrs{0](c,i) (customizable) function.
Default is set for bit coded value for 3-bit (rgb) color depth and
provides 8 colors: b&000=0=black, b&111=7=white, b&100=4=red, etc.
this.clrs[0]() can be customized to support any color depth - coded,
table looked up, or literal. For details see Colors and color
definitions section below..fnt(fv)
- set fontVector (size) ...currently w/ no frills, as opposed to
.clr(). More font options will be implemented at a later time..ld(x,y,l(abelInfoArray))
- label draw function; label info array:
l[0]
: fontVector (size)l[1]
: color (see Colors sectionl[2]
: xOffset to x - left of bounding box of label (.drawString(...))l[3]
: yOffset to y - top of bounding box of label (.drawString(...))l[4]
: label text (used in .drawString(...))
Note: the reason for x and xOffset - and y and yOffset - is because
.ld() is used in conjunction with a ui element that has a bounding
box that provides x and y - usually left-top corner and xOffset
and yOffset are used to place the label relative to the ui
element's corner coordinates. For plain, direct use with absolute
coordinates, either xOffset and yOffset have to be set to 0. For
reuse of label at same position, it is better to set both x and
y to 0.
.add(module,keep)
- extend ui module with ui element and other extensions
to support modularity. After module code is merged into ui base code,
module is removed from cache to save variables. For that purpose, the
module has to know its name in module name property mn. For example,
for a module onOff.js for switching back light on/off on pin
B2,exports = { mn:"onOff"
, on: function(on) { digitalWrite(B2, on || on===undefined); }
defines the module code,ui.add(require("onOff"))
adds it to the
ui.js base code in order to be used asui.on();
. Without building
a file, modules can also be put into cache directly on upload in level
0 (and served with require() with module name provided as variable to
escape regular module detection and pre-upload from modules
sources):Modules.addCached(mName,'{ mn:"onOff",on: function(on) {'
+ digitalWrite(B2, on || on===undefined); }');
, and added
withui.add("onOff");
.
--- UI (touch) event object (passed in callbacks)is
The touch event object
t
and other objects, such as theui
/_
and the ui elemente
themselves, are passed around for easy
access in the ui base and ui element implementation as well as in the
application. The touch event object has this structure:t = // (touch) event { x: x // current or last touched x coordinate , y: y // current or last touched y coordinate , t: t // touching: (truey), not touching (anymore): falsey , f: f // touch event flags (experimental) }
Touch event flags
t.f
- some experimental - are:0000 0000 0000 0 unexpected (invalid?) 0000 0000 0001 1 untouch 0000 0000 0010 2 touching 0000 0000 0100 4 touch down 0000 0000 1000 8 'untouch' focused element while not in focus - _.lf 0000 0001 0000 16 untouched focused elt while in focus (typical untouch) 0000 0010 0000 32 moved out of focused element (touched down element) 0000 0100 0000 64 touching in focused elt (touched down elt) - _.ef / _.lf 0000 1000 0000 128 touching / focused 1st time or re-focused - _.ef / _.lf 0001 0000 0000 256 untouch on dragged over non-touched-down, alt elt - _.af 0010 0000 0000 512 moved out of non-touched-down, alternate focused elt 0100 0000 0000 1024 touching in non-touched-down, alternate focused element 1000 0000 0000 2048 touching 1st time in non-touched-down, alt. focused elt
Re-focusing happens when having touched down, dragged out of the element
and now draging back 'into' the initially focused element (touched down
element (_.ef / _.lf).In preferred callback, a typical untouch - touch down on a ui element and
untouch on same ui element - set these flags:
conditions:0000 0001 0001 7 = 16 untouched focused element while in focus (simple, + 1 untouch event
Untouching after moving / dragging out of the bounding box of the touched
down ui element sets these flags:0000 0001 1001 25 = 16 untouched focused element while in focus (simple, regular untouch event) + 8 'untouch' focused element while not in focus (_.lf) - last registered focused element, now not in focus anymore (_.fe), but may need cleanup or reset when element has been modified on other events using alternative callback + 1 untouch event
In the preferred callback fired on ontouch only - touch started with
touch down and ended with untouch on same ui element - requires usually
no or only rarely interpretation of touch event flags.The alternative callback fires on every kind of touch event and demands
significant interpretation of the flags from the application and ui
status items - passed as well in the callback - in order to take
appropriate action(s) in the application. The multitude of flags
allows to determine - next to untouch - touch down, dragging within,
leaving and re-entering bounding box of touched down ui element as well
as same events of the alternate - not touched down - element (and can
be used to implement drag and drop).--- Colors and Color Definitions
ui base module includes a default color converter that supports 3-bit
color depth - 1 bit each per red, green and blue base color - coded as
single RGB integer value, yielding 8 colors:2^1^3 = 8
colors (3 LSB -
Least Significant Bits of an integer). The color converter is a
function and is first element - index [0] - of an array which is set
and stored asui.clrs[]
array property:ui.clrs = [ function(c,i){ var v=(i)?c^7:c; return [v>>2&1,v>>1&1,v&1]; }.bind(exports) ]
The default color converter accepts for c a value from 0..7 for the basic
8 colors and returns them as triplets of 0s and 1s (array of three (3)
elements of values 0 and 1). It accepts an optional second parameter to
invert the color when truey. The inverted, complementary color contrasts
the non-inverted color and is defined by the color specified by the
1-complement of color c. For example, for a the 3-bit color depth defined
color with value4
,[1r,0g,0b]
orred
, the inverted,
contrasting complementary color value is3
,[0r,1g,1b]
oraqua
.The color converter is is invoked by ui's color setting method
ui.clr(c,i)
with same arguments. Any color converter delivers - has to deliver -
the normalized values 0..1 for each of the RGB colors as
[r, g, b] triplet, because hat values triplet is parameter for setting the
color by invoking the set-color method.setColor(r, g, b)
of the
Espruino Graphics object. The display module knows how to pass the color
onto the display's controller to make the display show the proper color.--- Enhanced Color Converter
With the enhanced color converter as below, colors can be specified in
three ways:- bit-coded as single positive value
- (negative) index into palette of [r,g,b] triplets
- literal [r,g,b] triplet
The n custom colors of the custom color palette are stored in the same
array as the color converter as 2nd to n-th + 1 element - index 1..n. The
color converter has to be built to accept 'negative' color values -1 .. -n
to pick a color from the custom palette: it takes the negative value as
positive index into theui.clrs[]
array property tp pick a color
from the custom color palette and return it as value-normalized
[0..1r,0..1g,0..1b] triplet. The way the custom colors of the custom color
palette are specified determines the implementation of the converter.ui.clrs = // 'imply' color depth and populate table w/ converter and define // user colors / palette (colors accessed w/ negative index) [function(c,i) { // converts 'custom color info / spec' to [r,g,b]... var v, s=isNaN(c); // ...@ idx 0; internally called: _.clrs[0](...) if (s || c<0) { // c<0 (looked up [R,G,B]) or c=[R,G,B] return ( ((s) ? c : this.clrs[-c]).map( // convert 0..255->0.0..1.0 function(v){ return ((i)?v^255:v)/256; } ) ); } else { // c>=0 bit coded rgb color (0b001,010,011,100,...111 v = (i) ? c^7 : c; // (default 3-bit color depth w/ 2^1^3=8 colors) return [v>>2&1,v>>1&1,v&1]; } }.bind(ui) // custom color palette (converter knows to convert spec) ,[216,216,216] // user color -1: light grey // keyboard special keys ,[192,192,192] // user color -2: medium light grey ,[128,128,128] // user color -3: medium gray ,[192,128,192] // user color -4: light purple ,[0 ,160, 64] // user color -5: kind of a 'darker' green ]; ui.bc = 0; // ui (screen) background color (override default w/ other value) ui.tc = 7; // ui (screen) touch / focus color (override default w/ oth. val)
For [r,g,b] specification, Espruino Graphics modules accepts for each
r,g,b base color the normalized value 0.0 .. 1.0. Under the hood and with
help of the module for the display, this normalized color specification is
transformed - most of the time - into a bit coded color again, but in a
different, more elaborate / complicated encoding, especially when
different number of bits are used for each of the base r, g and b colors,
for example, (display specific) 5, 6, 5 bits for r, g, b. The module also
handles the conversion the sequence of the r, g and b colors when needed,
for example, [r,g,b] to [r,b,g].Normalized color specification value is mapped to actual color based on
color depth specified for or implied by the display (module) used in
conjunction with the Espruino's Graphics object. The ui base module
already includes a default color converter from bit coded rgb value to
Espruino's normalized [r,g,b] values triplet. Passing the normalized
values triplets makes bit coded colors in the ui independent from the
display's version of bit coding.The n custom colors of the custom color palette are stored in the same
array as the color converter as 2nd to n-th + 1 element - index 1..n.
The color converter has to be built to accept 'negative' color values
in range of -1 .. -n to pick a color from the custom palette: it takes
the negative value as positive index into theui.clrs[]
array to
properly pick a color from the custom color palette and return it
converted to value-normalized [0.0..1.0r, 0.0..1.0g, 0.0..1.0b] triplet.
The way the custom colors of the custom color palette are specified
determines the implementation of the converter.--- Custom ui elements and extensions
In order to not collide with future development of the ui components
out of the box and for easy distinction, choose for custom ui elements
clazz names of 5 characters or more, use for mixed in properties -
variables and methods - names with 6 or more characters. Also, add a
custom parallel array object or real js object rather than adding
elements to the existing array object.--- More...
The unminified sources and examples have in-line documentation - same
as this - and in-line comments. Latter is useful when reading the code
to grok 'what is going on'. Feedback - in general and in particular -
and (improving) contributions are welcome (@ allObjects).--- ui - base code into which elements and custom code are mixed in
exports = // ui base / 'DOM'/ui e(lement) data & code holder, singleton, for mixins) { dsp: null // display (Espruino Graphics object) , mn: "ui" // reserved, used temporary , bc: 0 // dsp background color >=0: r*g*b* bit coded; <0: looked up [...,[R,G,B],...] , tc: 7 // touch / focus color; >=0: r*g*b* bit coded; <0: looked up [...,[R,G,B],...] , di: false // display instantly on create/change (not defer until after save()) , es: [] // ui elements , ef: null // (primary ui) element (in visual) focus (by touch down / hovering) , lf: null // (primary ui element) last (in visual) focus (by touch down / not hovering) , af: null // alternate (ui element in non-visual) focus (by drag over / hovering) , it: false // (display) is touched , td: false // is touch down (event) , tt: 0 // touch down time , lx: 0 // last x (touched) , ly: 0 // last y (touched) , dx: -1 // (last) x (touch) down , dy: -1 // (last) y (touch) down , te: {f:0} // (last) touch event , clrs: // default - bit coded color of 3-bit color-depth - 2^1^3(rgb) = 8 colors // .... // ... public methods - documented above // ... private methods // ... }
Attached shot: Button b1 and then button b2 'tapped'.
1 Attachment
-
• #10
----- uiBtn ------------------------- 20190927
*** ui button module
The ui button module extends ui base with button ui element.
Implementation note: vs3 overlaps/is duplicates of uiExt module and
will overwrite each other. Therefore - on changes - changes have to
be applied to both of them to maintain consistent outcome. It is
duplicated in the ui checkbox so that ui extensions does not need to
be loaded when not used. It saves memory / vars with simple UIs.--- Enable ui base with uiBtn and create a button with callback on untouch:
var ui = require("ui") // load ui base module .add(require("uiBtn")) // add module into base and remove from cache ;
--- Create - specify - plain buttons
// flgs clazz id x y w h b f value object /. callback on 'untouch' ui.c( 3,"btn","b1",10,20,50,30,4,7,"B_1" ,function() { (LED1.read()) ? LED1.reset() : LED1.set() } ,[20,0,5,15,"RED"]); // fv t x y label text
Creates, adds to ui, conditionally displays and returns an active(2),
visible(1) =(3) button ("btn") with id "b01". Button is positioned at
10 @ 20 (left @ top, x @ y) and is sized 50 x 30 (width x height), has
4(red) / 7(white) border / fill colors, has value object string "B_1",
has (arguments ignoring) callback that toggles red LED1, and is labeled
"RED" on top of it in fontVector (size) 20, text (font) color 0 (black
on white button fill color) and x / y-offset of 5 / 15 from left top
corner of button's bounding box.Colors are bit-coded with 3-bit color-depth according ui.clrs=[...] setup.
Callback cb is called on untouch with
id, v, ui, e, t
as arguments:args[] sym description 0 id : button id ("b1") 1 v : value object ("B_1" - can be any object) 2 ui : ui (THE ui object) 3 e : uiBtn element (btn 'object' (runtime data structure)) 4 t : touch info x, y,... (where last touched) { x : x coordinate , y : y coordinate , t : touched (truey) / untouched (falsey) , f : flags }
For ui base, color, label, and callback details see (also) ui base module.
For detailed ui setup, including color depth and custom colors, connecting
to display and touch screen, soft key board or buttons, see ui module and
example material (in the ui.zip file and sources with comments). Take a
look at the example that shows all ui elements on one single
display -uiExampleAll.js
- project file in the _sbx Espruino sandbox projects
folder. Make it the Espruino Web IDE sandbox folder and run the ready-made
examples on your Espruino board. Espruino forum has several entries about
the modules and hardware. Search in (google) for:Espruino Forum allObjects touch screen display modular ui framework
No board or display with touch screen yet? No Problem: Open
uiExample.html
in uidev folder in Web browser to run the same example in the Cross
Development / Emulation environment (where modules are developed and
maintained).--- Some more details
A button with border and fill colors equal to display background
color (ui.bc) creates a tap-able area that is useful to make anything,
such as a displayed image, to act like a button...uiBtn can be changed within callback: for example in example above, the
label can be changed to indicate whether tapping will turn the LED on or
off. In order to make the ui framework redraw the button and make the
label change visible, the callback has to return truey ('JS true'). The
button / callback definition for label changing button looks like this:// flgs clazz id x y w h b f value object /. callback on 'untouch' ui.c(3,"btn","b01",10,20,50,30,4,7,"B_1" ,function(id, v, ui, e, t) { // on untouch event if (LED1.read()) { LED1.reset(); e[11][4] = "RED on"; // label text } else { LED1.set(); e[11][4] = "RED off"; // label text } return true; // truey forces button to be re-drawn } ,[20,0,5,15,"RED on"]); // fv t x y label text
The same callback shared by multiple uiBtns can produce button specific
results when callback takes into account the each buttone's unique id or
value (object) as passed to the callback as 2nd argument. Example code for
label change above shows that callback parameters include the value object
of the button (as well as the button element itself). This allows to use
the same callback with different outcome based on button value object (or
button's fill color). Multiple, different colored buttons can be used to
light up an RGB LED (string) in the button's colors as defined by the
value object (and/or fill a rectangle somewhere on the display with the
same color as the button's color using one and the same callback to keep
the code terse and save space (variables).Note: The preferred touch event to invoke the callback is on untouch,
because it has these advantages:- UI behavior is simple in sequence and behavior.
- Enables cancel of touchdown: releasing / untouch AFTER 'moving /
dragging the touch' out of the bounding box of the initially touched
button (touched on touch down) will not invoke the untouch callback
that otherwise would be the inevitable consequence on touchdown on
the button. - Implementation of callback is simpler because it is time-wise less
critical for delivering a UX behavior with timely, intuitive (visual)
feedback to user and no delay on execution of the callback.
To use the (experimental) alternative callback called on all touch events,
the 11th ([10]) argument value for the preferred callback 11in the
constructor -ui.c(...);
- has to be a falsey value best is
undefined) and the 13th [12] has to be the callback function. The
alternative callback is called with the same arguments as the preferred
one. The touch event objectt
has 12 bit coded flags -t.f
,
for example, for the untouch event is0b000000011001
or25
-
which describe the touch event in detail. For details see ui base module.Using a synchronous implementation for callback on touch down may delay
the visual feedback to the user about the accepted touch down when it
takes noticeable time to complete. Therefore, the callback should invoke
the heavy lifting code in asetTimeout(function(...){...},10,...);
function as the last thing in the (otherwise 'empty') callback. The 10
millisecond timeout is a value to start with. If it is not working, find
the best value empirically by working thru the application varying the
value.If the button has to change to give additional visual feedback to the user
that the callback is in execution, then that change has to be coded
BEFORE* thesetTimeout()
and the callback has to return truey in
order to trigger the redrawing of the button in the ui base module.
Changing the button again after completion of the heavy lifting
of the callback, it has to happen as last thing IN
thesetTimeout(function(...){...; e[#]=...; ... _.d(e); },10,...);
(with_
being theui
singleton (ui base module) object, passed
as the 3rd argument to the callback).To prevent additional touch down events on the button to prevent
triggering the callback again before its completion, disabling of the
button has to happen beforesetTimeout()
as well
withe[1]=e|1]|2-2;
. Re-enabling as absolutely last item IN
thesetTimeout(){...; e[1]=|2; }
code, even after the redraw (see
above). A more radical approach is to control the touch listener if it
supports the methodtouch.listen(false)
(and the opposite,
touch.listen(), which is the same as touch.listen(true)... or 0 and 1
for false and true argument values, respective). Doing latter though,
you loose the ability to issue a cancel of a long running callback
(which of course has to yield once in a while to the touch controller
module using chained setTimeout()s until done.Example of a button with both untouch and touchdown event callback:
// flgs clazz id x y w h b f value object ui.c(3,"btn","b01",10,20,50,30,4,7,"B_1" ,undefined ,[20,0,5,15,"RED"] // fv t x y label text ,function(id,v,_,e,t){ console.log(id+" "+t.f); } );
If you use both callbacks and put 'the (heavy) work' of the touch down
callback into asetTimeout(function(...){...},10,...);
, you may
consider to put 'the work' of both callbacks into asetTimeout();
(with equal timeout value) to ensure proper sequence (to prevent touchdown
callback being triggered first...). Having 'the work' of the untouch in
asetTimout();
, it is recommended to implement button changes the same
way as it has to be done in the touchdown callback by invoking the redraw
in the callback with_.d(e);
and let the callback return nothing
(which is the same as falsey).--- btn ui element constructor arguments (a[]) and runtime data structure (e[]) are:
arg runtime 'object' instance of 'clazz' ` btn` (button) a[] e[] 0 [0] f - flags focus(4), active(2), visible(1) . . 0bxx1 visible &1 visible . . 0bx1x active &2 active / senses touches vs read/display-only . . 0b1xx focus &4 focus by touch down, drag w/in bounding box 1 [1] c - clazz "btn" 2 [2] i - id eg "b01", short, at least 2..3 chars, ui globally unique. Single letter ui element ids are 'reserved' (for keyboard(s)). 3 [3] x - x ((left ) of focus / touch bounding box) 4 [4] y - y ((top ) of focus / touch bounding box) 5 w - width (of focus / touch box) [5] x2 - x ((right) of focus / touch bounding box: x - w + 1) 6 h - height (of focus / touch box,... [6] y2 - y ((bot ) of focus / touch bounding box: y - h + 1) 7 [7] bc - border color 8 [8] fc - fill color 9 [9] v - value - any object, from simple string to number to complex { } object (returned when button pressed) 10 [10] cb - simple, preferred callback on untouch after touchdown 11 [11] l - label (info), array with: l[0] fv - fontVector (size) l[1] tc - (label) text color l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] tx - label text to display (using .drawString()) 12 [12] ca - NON-preferred, experimental callback on any touch event
Attached shot: uiBtn - button - example (in emulation) - touching down on b1, dragging over b2 and back to b1 and then untouch b1 = tapping b1.
1 Attachment
- UI behavior is simple in sequence and behavior.
-
• #11
----- uiChk ------------------------- 20190927
*** ui checkbox module
The ui checkbox module extends ui base with checkbox ui element.
Implementation note: vs2 overlaps/is duplicates of uiExt module and
uwill overwrite each other. Therefore - on changes - changes have to
be applied to both of them to maintain consistent outcome. It is
duplicated in the ui checkbox so that ui extensions does not need to
be loaded when not used. It saves memory / vars with simple UIs.--- Enable ui base with uiChk and create a checkbox with callback on untouch:
var ui = require("ui") // load ui base module .add(require("uiChk")) // add module into base and remove from cache ;
--- Create - specify - check box
// flgs clazz id x y w s b f value object /. callback on 'untouch' ui.c( 3,"chk","c1",140,45,25,0,2,7,"H" ,function(id,v){ (v) ? LED2.set() : LED2.reset() } ,[12,7,3,5,"On"]); // fv t x y label text
Creates, adds to ui, conditionally displays and returns an active(2),
visible(1) =(3) checkbox ("chk") with id "c01". Checkbox is positioned
at 145 @ 40 (left @ top, x @ y) and sized 25 square (both width and
height), has 2(blue) / 7(white) border / fill colors, is initially
unchecked (0, but any falsey works), has value object "H" (when checked
and undefined when unchecked), has callback that sets and resets green
LED2 accordingly, and is labeled "On" right next to it in fontVector
(size) 12, text (font) color 7(white) on black screen background color
and x / y-offset of 3 / 5 from left top corner of checkbox's bounding box.Colors are bit-coded with 3-bit color-depth according ui.clrs=[...] setup.
For ui base, color, label, and callback details see (also) ui base module.
Callback cb is called on untouch with
id, v, ui, e, t
as arguments:args[] sym description 0 id : button id ("c1") 1 v : value object ("H" - can be any object); NOTE: is undefined when check box is unchecked 2 ui : ui (THE ui object) 3 e : uiChk element (chk 'object' (runtime data structure)) 4 t : touch info x, y,... (where last touched) { x : x coordinate , y : y coordinate , t : touched (truey) / untouched (falsey) , f : flags }
For detailed ui setup, including color depth and custom colors, connecting
to display and touch screen, soft key board or buttons, see ui module and
example material (in the ui.zip file and sources with comments). Take a
look at the example that shows all ui elements on one single display -folder. Make it the Espruino Web IDE sandbox folder and run the ready-made examples on your Espruino board. Espruino forum has several entries about the modules and hardware. Search in (google) for:
Espruino Forum allObjects touch screen display modular ui framework```
No board or display with touch screen yet? No Problem: Open
uiExample.html
in uidev folder in Web browser to run the same example in the Cross
Development / Emulation environment (where modules are developed and
maintained).For helpful details to use the ui base and ui element APIs, take a look
at documentation in ui base and uiBtn modules.--- chk ui element constructor arguments (a[]) and runtime data structure (e[]) are:
arg runtime 'object' instance of 'clazz' chk (chkbox) a[] e[] 0 [0] f - flags focus(4), active(2), visible(1) . . 0bxx1 visible &1 visible . . 0bx1x active &2 active / senses touches vs read/display-only . . 0b1xx focus &4 focus by touch down, drag w/in bounding box 1 [1] c - clazz "chk" 2 [2] i - id eg "c01", short, at least 2..3 chars, ui globally unique. Single letter ui element ids are 'reserved' (for keyboard(s)). 3 [3] x - x ((left ) of focus / touch bounding box) 4 [4] y - y ((top ) of focus / touch bounding box) 5 w - width and height (of focus / touch bounding box) [5] x2 - x ((right) of focus / touch bounding box: x - w + 1) 6 s - initial checked(truey/1)/unchecked(falsy/0) state used with [9] value info [6] y2 - y ((bot ) of focus / touch bounding box: y - h + 1) 7 [7] bc - border color 8 [8] fc - fill color 9 v - value (returned value when checked) [9] vi - value info array w/ state and value [0] - truey/falsey for checked/unchecked state of checkbox [1] - value object (returned when checkbox is checked) 10 [10] cb - simple, preferred callback on untouch after touchdown 11 [11] l - label (info), array with: l[0] fv - fontVector (size) l[1] tc - (label) text color l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] tx - label text to display (using .drawString()) 12 [12] ca - NON-preferred, experimental callback on any touch event
Attached shot: Check box c1 and then check box c2 'tapped'.
1 Attachment
-
• #12
----- uiExt ------------------------- 20190927
The
ui extension
extends ui base with service and convenience functions for
ui frame work as well applicationui extension is currently required by:
- uiRad - Radio button ui element
- uiKb3x10B - Soft / touch keyboard / keypad
- uiEBC - extension for button controlled ui
--- Brief documentation of the methods / functions available
.ff(a,f,s,_)
- find and return first element in arraya
starting
with start indexs
(if absent, s=0 assumed) that makes function
f(element, _auxiliaryVar)
return truey; if not found,
returnundefined
. Argument_
(_auxiliaryVar) is also
passed to the function and can be any value the application needs. If
application has no use for it, it is just left away in the call and
function..fx(a,f,s,_)
- find and return index of first element in arraya
that makes functionf(element)
return truey; if not found,
return-1
. Argument_
(_auxiliaryVar) is also
passed to the function and can be any value the application needs. If
application has no use for it, it is just left away in the call and
function..e(iie)
- return ui element by idx, id or elt. If by id and not found,
undefined is returned..g(iie)
- get element value (obj) - runtime e[9] - by idx, id or elt..u(iie,p)
- update value object by element idx or id with or without
propagation (calling callback). Be aware how the value (object) is
defined creation of the ui element..t(iie,ud)
- tap on ui element by idx or id or ui element. If element is
found, x and y coordinates of center are passed to ui and processing
happens as if the element would be touched on a touch screen and then
un-touched - with the default or overwritten untouch delay.ud
.
Providing proper un-touch delays yields full control over touch-time
sensitive ui elements, such as key board keys, where, for example,
long touch of keys with numbers inuiKbc3x10B
module will return
the number character instead of the alpha character..cb(iie)
and.cb(iie,cb,ca)
- getter and setter of callback; getter is
with both cb and ca being undefined by value or absence of value.
--- ext - ui extension properties - variables and methods - mixed into ui base
exports = // ui (generic) ext(ension/utils: vertices(circle,...) find elt/idx in arr,...) { mn: "uiExt" // module 'clazz' name - globally unique (used to remove code from cache) , ud: 100 // default tap duration defined as u-ntouch d-elay / timeout , cg1: [2,-5,4,-4,5,-2,6,0,5,2,4,4,2,5,0,6,-2,5,-4,4,-5,2,-6,0,-5,-2,-4,-4,-2,-5] // .... // ... public methods - documented above // ... private methods // ... }
Attached shot: shows the browser developer / debug view with the browser console log, to which the ui framework is logging to by injected functions.
1 Attachment
- uiRad - Radio button ui element
-
• #13
----- uiRad ------------------------- 201909227
*** ui radio button module
The ui radio button module extends ui base with radio button ui element.
Note: It requires the uiExt - ui extension module - to be loaded.
--- Enable ui base with uiRad element functions:
Note: requires uiExt(ension) module (see uiExt.js module)
var ui = require("ui") // load ui base module .add(require("iuExt")) // add uiExt module into base and remove from cache .add(require("uiRad")) // add uiRad module into base and remove from cache ;
--- Create - specify - radio buttons
// flgs clazz id x y w s b f value callback on 'untouch' ui.c( 3,"rad","r1.a", 5,80,37,0,6,2,"L", cb, [12,7,5,10,"Large"]); ui.c( 3,"rad","r1.b", 95,85,27,1,3,1,"M", 0 , [12,7,5, 7,"Med" ]); ui.c( 3,"rad","r1.c",170,90,17,1,5,2,"S", 0 , [12,7,5, 2,"Small"]); // fv t x y label text
Crates and add to ui three active(2), visible(1) =(3) radio buttons at
x/y (left/top: 5/80, 95/85 and 170/90) of different sizes/widths/diameters
(37, 27 and 17) with size related values ("L", "M" and "S") and labels
("Large", "Medium" and "Small"), with group name "r1." (dot is part of
group name). Medium sized radio button is set/checked (first set/checked
radio button wins... therefore small one is not set/checked even though
specified as such). Border colors (6, 3 and 5) and fill colors (2,1 and 2)
are all different (by choice). Unset/unchecked radiobuttons show ui
display background color (ui.bc). Label array definitions include
fontVector (size), font color, x/y offset from right/top (x2/y) corner of
touch sensitive bounding box, and text.Colors are bit-coded with 3-bit color-depth according ui.clrs=[...] setup.
Callback cb is called on untouch with
id, v, ui, e, t
as arguments:args[] sym description 0 id : button id ("r1.a") 1 v : value object ("L"|"M"|"S" - can be any object) NOTE: is undefined when check box is unchecked 2 ui : ui (THE ui object) 3 e : uiRad element (rad 'object' (runtime data structure) just untouched) 4 t : touch info x, y,... (where last touched) { x : x coordinate , y : y coordinate , t : touched (truey) / untouched (falsey) , f : flags }
For detailed ui setup, including color depth and custom colors, connecting
to display and touch screen, soft key board or buttons, see ui module and
example material (in the ui.zip file and sources with comments). Take a
look at the example that shows all ui elements on one single display -
uiExampleAll.js
- project file in the _sbx Espruino sandbox projects
folder. Make it the Espruino Web IDE sandbox folder and run the ready-made
examples on your Espruino board. Espruino forum has several entries about
the modules and hardware. Search in (google) for:
Espruino Forum allObjects touch screen display modular ui framework
No board or display with touch screen yet? No Problem: Open
uiExample.html
in uidev folder in Web browser to run the same example in the Cross
Development / Emulation environment (where modules are developed and
maintained).For helpful details to use the ui base and ui element APIs, take a look
at documentation in ui base and uiBtn modules.--- rad ui element constructor arguments (a[]) and runtime data structure (e[]) are:
arg runtime 'object' instance of 'clazz' chk (chkbox) a[] e[] 0 [0] f - flags focus(4), active(2), visible(1) . . 0bxx1 visible &1 visible . . 0bx1x active &2 active / senses touches vs read/display-only . . 0b1xx focus &4 focus by touch down, drag w/in bounding box 1 [1] c - clazz - "rad" 2 [2] i - id - eg "r01.a","r01.b","r01.c",.. short, at least 2 or 3 chars for radio button group id, and globally unique. Single letter ui element ids are 'reserved' (for keyboard(s)). Radio button id consist of two elements: - Radio button group id - the part *before* the dot. - Radio button individual id - the part *after* the dot. Radio button group id is used to make the buttons in the group behave like radio buttons: any 'pressed' button 'releases' all others, or in other words, only one radio button can be 'pressed' - or on - at one time. 3 [3] x - x ((left ) of focus / touch bounding box) 4 [4] y - y ((top ) of focus / touch bounding box) 5 w - width and hight (of focus / touch box,... [5] x2 - x ((right) of focus / touch bounding box: x - w + 1) 6 s - initial checked(truey/1)/unchecked(falsey/0) state used w/ [9] value info; note that only one radio button can be set / checked / on at one time [6] y2 - y ((bot ) of focus / touch bounding box: y - h + 1) 7 [7] bc - border color 8 [8] fc - fill color 9 v - value (returned value when checked) [9] vi - value info array w/ state and value object [0] - truey / falsey indicating state checked/unchecked [1] - value object (returned when radio button is checked) 10 cb - simple, preferred callback on untouch after touchdown; [10] g - radio button group management array object [0] - radio button group id, eg. "r1." (incl. dot) [1] - preferred callback (1st encountered truey cb) [2] - alternate callback (1st encountered truey ca) [3] - checked radio button ui element (or null / falsey) [4...] - group radio button ui elements Note that first encountered truey callback - cb or ca wins and cb wins over ca. Therefore only one needs to be specified per group cb over ca priority. The others can be left undefined, they are ignored anyway. 11 [11] l - label (info), array with: l[0] fv - fontVector (size) l[1] tc - (label) text color (index) l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] tx - label text to display (using .drawString()) 12 [12] ca - NON-preferred, experimental callback on any touch event
Attached shot: Tabbed thru uiRad - radio buttons.
1 Attachment
-
• #14
----- uiSli ------------------------- 20190927
*** ui slider module
ui slider module extends ui base with slider ui element.
--- Enable ui base with uiSli and create a slider with callback on untouch:
var ui = require("ui") // load ui base module .add(require("uiSli")) // add uiSli module into base and remove from cache ;
--- Create - specify - a slider
var s2 = // hold on to "s2" slider ui element for direct access app later on. // 0 1 2 3 4 5 6 7 8 9 10 11 // flgs clazz id x y w h bc fs valObj cb, ls (arr of label ([[...],..])) // sli ->x2->y2 [0] fv tc x y min max s flgs ui.c( 3,"sli","s2" , 30,175,180, 26, -4,[-4,0],{v:33},cb, [[12, 6, 70, 6, 0,100,3,168 // [0][8] format (function) ,function(v,_){ // (val, ui) var s="", f=_.te.f; return (!(f==0 || f&184)) ? s : ((v<1)?"0":"") // 128+32+16+8 +(s=Math.round(v*10)+"%").substr(0,s.length-2)+"."+s.substr(-2); } ] // val // [>0] fv tc x y label text ,[12, 7, -25, 6, "%:0"] // frnt ,[12, 7, 182, 6, "100"] // back ]);
Creates, adds to ui, conditionally displays and returns and stores in
global variable s2 a 0..100% slider of 3 pixel change value touch
sensitivity with bit coded callback activation flags, custom colored
(-4) border and same colored 'left' filling, black (0) 'right'filling,
shows % range from min 0% to max 100% as text labels left and right of
of it and current value as label in center on it by custom formatter
function.Custom formatter has dual purpose:
- render more than just the bare value
- avoid slowing down sliding by rendering (if needed)
Because rendering - drawing strings on a display - can be slow, rendering
the actual value while sliding has to be kept to a minimum to keep sliding
snappy. Providing the formatter function that returns an non-empty string
only on desired conditions and an empty one else does the trick: rendering
an empty string is not noticeably slowing down sliding; ui element value
(v), ui and touch event states / flags (_, _.te.f) can be used to form
the desired condition to return empty or not empty string.Colors are bit-coded with 3-bit color-depth according ui.clrs=[...] setup.
Since slider has two (2) areas to fill - left and right side of slider -
fill colors - fs - are specified as array:- fs[0] is fill color for the 'left' / 'filled' side of the slider.
- fs[1] is fill color for the 'right' / 'empty' side of the slider.
Since slider has drag aspects callback and should also be able to deliver
values to the application while sliding, callback conditions can be
specified by flags as defined for the ui event flags. These flags also
control whether the new changed value is set and custom formatter function
is invoked or not. On untouch though, the new value is and formatter is
invoked no matter whether the untouch flag(s) is(are) set or not.Callback is called with
id, v, ui, e, t
as arguments:args[] sym description 0 id : button id ("c01") 1 v : value object (usually a number) 2 ui : ui (THE ui object) 3 e : uiSli element (sli 'object' (runtime data structure)) 4 t : touch info x, y,... (where last touched) { x : x coordinate , y : y coordinate , t : touched (truey) / untouched (falsey) , f : flags }
For detailed ui setup, including color depth and custom colors, connecting
to display and touch screen, soft key board or buttons, see ui module and
example material (in the ui.zip file and sources with comments). Take a
look at the example that shows all ui elements on one single display -
uiExampleAll.js
- project file in the _sbx Espruino sandbox projects
folder. Make it the Espruino Web IDE sandbox folder and run the ready-made
examples on your Espruino board. Espruino forum has several entries about
the modules and hardware. Search in (google) for:
Espruino Forum allObjects touch screen display modular ui framework
No board or display with touch screen yet? No Problem: Open
uiExample.html
in uidev folder in Web browser to run the same example in the Cross
Development / Emulation environment (where modules are developed and
maintained).For helpful details to use the ui base and ui element APIs, take a look
at documentation in ui base and uiBtn modules.--- sli ui element constructor arguments (a[]) and runtime data structure (e[]) are:
arg runtime 'object' instance of 'clazz' slider a[] e[] 0 [0] f - flags focus(4), active(2), visible(1) . . 0bxx1 visible &1 visible . . 0bx1x active &2 active / senses touches vs read/display-only . . 0b1xx focus &4 focus by touch down, drag w/in bounding box 1 [1] c - clazz - "rad" 2 [2] id - eg "s02", short, at least 3 chars, and ui globally unique Single letter ui element ids are 'reserved' (for keyboard(s)). 3 [3] x - x ((left ) of focus / touch bounding box) 4 [4] y - y ((top ) of focus / touch bounding box) 5 w - width (of focus / touch box,... [5] x2 - x ((right) of focus / touch bounding box: x - w + 1) 6 h - height (of focus / touch box,... [6] y2 - y ((bot ) of focus / touch bounding box: y - h + 1) 7 [7] bc - border color 8 [8] fs - fill colors array fs[0] fill color for 'left side' of slider fs[1] fill color for 'right side' of slider 9 [9] v - value - a number 10 [10] cb - callback on touch, value change, untouch 11 [11] ls - labels - array of labels of which first one is value related ls[0] label (info) for value related info, array with: l[0] fv - fontVector (size) l[1] tc - (label) text color (index) l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] mn - minimum value ( at left border ) l[5] mx - maximum value ( at right border ) l[6] s - sensitivity (in pixels to detect change and redraw) l[7] fm - optional format function to format value label ls[1,2,3,...] any number of additional labels, but mostly just two... l[0] fv - fontVector (size) ...for min and max l[1] tc - (label) text color (index) l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] tx - label text to display (using .drawString())
Attached shot: Slider s1 and slider s2 moved / 'dragged'.
1 Attachment
- render more than just the bare value
-
• #15
----- uiInp ------------------------- 20190927
*** ui input field module
ui input module extends ui base module with input field ui element.
Note: requires uiExt(ension) module (see uiExt.js module)
--- Enable ui with uiInp element functions:
var ui = require("ui") // load ui base module .add(require("iuExt")) // add module into base and remove from cache .add(require("uiInp")) // add module into base and remove from cache ;
--- Create and add to ui an active(2), visible(1) =(3) input field at x/y
(left/top: 45/7) of size width/height (195/28), turkis border color (3),
white. Callback clears content when tap lasted longer than 550ms and there
is content. Not checking for content runs into stack overflow, because.u(e,"")
triggers again a callback because it is a change of value...Colors are bit-coded with 3-bit color-depth according ui.clrs=[...] setup.
// 0 1 2 3 4 5 6 7 8 9 10 11 // flgs clazz id x y w h bc fc valObj cb ls (arr of label ([[..],..])) // btn ->x2->y2 callback clears on tap > 550ms ui.c( 3,"inp","i1" , 45, 7,195, 28, 3, 7,"modular UI" ,function(i,v,_,e){ if (getTime()-_.tt>0.55 // [0] fv tc x y mxLen typ fmt && v.length) _.u(e,""); } // [1] fv tc x y label text ,[[13, 0, 5, 6, 16, 0, 0] ,[13, 7,-233, 6, "Field" ] ]);
Callback cb is called on release (untouch) and change and
providesid, v, ui, e, t
as arguments:args[] sym description 0 id : button id ("x") 1 v : value (object) - type dependent (for now just string) 2 ui : ui (THE ui object) 3 e : uiInp element (inp 'object' (runtime data structure)) 4 t : touch info x, y,... (where last touched) { x : x coordinate , y : y coordinate , t : touched (truey) / untouched (falsey) , f : flags }
For detailed ui setup, including color depth and custom colors, connecting
to display and touch screen, soft key board or buttons, see ui module and
example material (in the ui.zip file and sources with comments). Take a
look at the example that shows all ui elements on one single
display -uiExampleAll.js
- project file in the _sbx Espruino sandbox projects
folder. Make it the Espruino Web IDE sandbox folder and run the ready-made
examples on your Espruino board. Espruino forum has several entries about
the modules and hardware. Search in (google) for:Espruino Forum allObjects touch screen display modular ui framework
.No board or display with touch screen yet? No Problem: Open
uiExample.html
in uidev folder in Web browser to run the same example in the Cross
Development / Emulation environment (where modules are developed and
maintained).For helpful details to use the ui base and ui element APIs, take a look
at documentation in ui base and uiBtn modules.--- inp ui element constructor arguments (a[]) and runtime data structure (e[]) are:
arg runtime 'object' instance of 'clazz' inp - input field a[] e[] 0 [0] f - flags focus(4), active(2), visible(1) . . 0bxx1 visible &1 visible . . 0bx1x active &2 active / senses touches vs read/display-only . . 0b1xx focus &4 focus by touch down, drag w/in bounding box 1 [1] c - clazz "inp" 2 [2] i - id eg "i01", short, at least 2..3 chars, ui globally unique. Single letter ui element ids are 'reserved' (for keyboard(s)). 3 [3] x - x ((left ) of focus / touch bounding box) 4 [4] y - y ((top ) of focus / touch bounding box) 5 w - width (of focus / touch box,... [5] x2 - x ((right) of focus / touch bounding box: x - w + 1) 6 h - height (of focus / touch box,... [6] y2 - y ((bot ) of focus / touch bounding box: y - h + 1) 7 [7] bc - border color 8 [8] fc - fill color 9 [9] v - value - (string) value to start with 10 [10] cb - simple, preferred callback on untouch after touchdown 11 [11] ls - labels - array of labels of which 1st is also value related ls[0] label (info) for value related info, array with: l[0] fv - fontVector (size) l[1] tc - (label) text color (index) l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] mxLen - maximum length l[5] type - opt type (absent & 0:plain string, only type for now) l[6] frmt - opt format function to use to format value for label ls[1,2,3,...] any number of additional labels, but mostly just two... l[0] fv - fontVector (size) ...for min and max l[1] tc - (label) text color (index) l[2] x - x offset from focus box x ( bounding box left ) l[3] y - y offset from focus box y ( bounding box top ) l[4] tx - label text to display (using .drawString())
Attached shot: 'cleared' entry field tapping x in top right corner; 'typed' on keyboard by tapping: 1 x shift (one shot shift sh1 ^^) - Key K - 3 x shift or long tap (num lock #^) - key 3 - 1 x shift (back to no shift sh0 ^) - y key, 2 x shift (shift lock sh2 ^^^) - Keys B O A R D - 2 x shift (back to no shift sh0 ^) - key x - long tap bottom right button - back space / bs - removes last keyed x.
1 Attachment
-
• #16
----- keyboard/keypad - 3 x 10 Btns ------------------------- 20190927
*** uiKbd3x10B - ui keyboard module w/ 3 rows x 10 columns of uiBtn ui elements.
Note: uiKbd3x10B IS NOT part of the ui singleton. It is a standalone
input ui element similar to the touch modules: connected to ui and ui
elements, but not mixed into the ui element and managed by the ui (yet
or ever).--- Key assugnments and mappings
For Keyboards with buttons, key ids are the button ids, and button ids are
SINGLE character ids (thus reserved for the ui modules and not available
to application ui elements). The id of a key is the 1st char on the key
(btn), for examples:- "a" for key (btn) "a@" , returning the values "a" , "A", and "@". - "<" for key (btn) "<' \", returning the values "cr/lf", "'", and "\". - "." for key (btn) "
Keyboard key handler calls cb callback w/ values v, k, u, e, and t parameters:
v - key value - single character representing the printable key; special values: "sh0".."sh3" for shift key, "bs" for BacksSpace, "cr/lf" for CR/LF k - keyboard object (this) u - ui core singleton e - event source (key btn) t - touch object
e is the key board button that has just been untouched (k: keyboard, u: ui
core and t: touch event object).Key value depends on short TAP / LONG TOUCH and shift key mode.
The ^-shift key cycles w/ short taps through ^ m=0, ^^ m=1, ^^^ m=2,
^# m=3 its displays and modes; long touch always goes directly to
^# m=3 shift mode (number and special characters - NUM-LOCK).For REGULAR keys, shift key modes and returned chars with regular - SHORT
TAP - are:shift shift key mode display impact (and for mode 1 only also state change) ^ 0: lowercase - key id/1st char in lowercase ^^ 1: 1 uppercase - key id/1st char in uppercase, falls back to mode 0. ^^^ 2: all uppercase, key id/1st char in uppercase (SHIFT LOCK) ^# 3: all number and special chars - 2nd char on key (NUM LOCK)
LONG TOUCH return number for key with numbers - top row - and for other
keys with three (3) characters this third character (except cr/lf key),
otherwise none (cr/lf key is double special: special 'special key').The ^-shift key itself returns key values: "sh"+mode: "sh0", "sh1", "sh2"
and "sh3".Special keys with shift mode 0..3 returns (listed by key, mode and short
tap or long touch):special key w/ [chars on key] - location on keyboard 1st chr on shift shft key displ mod returns (comment) --- ----- --- -------- --------------------------------------------------- ^ (shift)[^],[^^],[^^^],[#^] - 1st key in bottom row ... w/ short tap: ^ 0: sh1 (when sh0 / ^ no-shift, cycles to sh1, single shot) ^^ 1: sh2 (when sh1 / ^^ single shot cycles to sh2) ^^^ 2: sh3 (when sh2 / ^^^ shift lock, cycles to sh3) #^ 3: sh0 (when sh3 / #^ NumLock, cycles back to sh0) ... w/ long touch: N/C *: sh3 (ALWAYS jumps to mode 3 / "sh3" string for NumLock) < (=cr/lf) [<'\] - last key in 2nd to bottom row: ... w/ short tap: ^ 0: cr/lf ("cr/lf" string) ^^ 1: ' (single quote) and back to shift mode 0 ^^^ 2: \ (back slash) #^ 3: cr/lf ("cr/lf" string) ... w/ long touch: . (dot) [.?..] - second to last key in bottom row: ... w/ short tap: ^ 0: . (dot) ^^ 1: ? (question mark) and back to shift mode 0 ^^^ 2: . (dot) #^ 3: . (dot) ... w/ long touch: ^ 0: . (dot) ^^ 1: ? (question mark) and back to shift mode 0 ^^^ 2: . (dot) #^ 3: . (dot) b/blank [ "_] - last key in bottom row: ... w/ short tap: ^ 0: b/blank (space 'bar') ^^ 1: " (double quotes) and back to shift mode 0 ^^^ 2: _ (underscore) #^ 3: b/blank (space 'bar') ... w/ long touch: N/A *: bs (ALWAYS "bs" string for BackSpace)
In other words - basically:
- When no-shift (^): first char on key prints.
- Tap shift once (^^) prints next char in uppercase or 2nd special key on special key.
- Tap shift twice goes into SHIFT-LOCK (^^^) and twice again goes back to no-shift.
- When in SHIFT-LOCK (^^^): char key prints uppercase and special key 3rd char.
- Touch shift long goes always into NUM-LOCK.
- When in NUM-LOCK (#^): key with number prints number, special key.
- Touch long key with number or 3rd, special char prints number and special char, resp.
- Tapping shift cycles from no-shift to single-shot shift, SHIFT-LOCK,
NUM-LOCK and back to no-shift.
--- Usage example
get the keyboard and 'connect' it to entry field "i1" - as part of UI definition:
Note: this keyboard modules requires ui base and uiBtn modules to be
loaded. It creates for each key a button with the id being the first char
displayed on the key, for example, a,b,c,..., ^ for shift, < for enter /
return, blank (" ") for blank/backspace,... Therefore, (practically) all
single letter ui element id's are taken and therefore 'reserved'.var ui = require("ui") // load ui base module .add(require("uiBtn")) // add module into base and remove from cache ; var kbd = require("uiKbd3x10B") .connect(ui,0,215,24,24, 7, 7,-2, 1, 1,10 ,0, 2, 4, // ui,x, y, w, h,bc,fc,sc,mx,my,fs,tc,tx,ty,cb function(v) { var s = ui.g("i1"); // is uiInp(ut field) ui element if (v.length === 1) { 'normal' key - append ui.s("i1",s + "" + v); } else if (v === "bs") { BS/BackSpace key - remove last char if (s.length > 0) { ui.s("i1",s.substr(0,s.length - 1)); } } } );
--- Module .connect(arguments)
0 ui ui core 1 x top of bounding box border 2 y left of bounding box border 3 w width of bounding box 4 h height of bounding box 5 bc key border color 6 fc key fill color for regular keys 7 sc key fill color for special keys (shift, return, special chars,... 8 mx x margin of key bounding box ...only, blank, backspace) 9 my y margin of key bounding box 10 fv key fontVector (size) 11 tc key text color 12 tx key text x offset (within key/btn bounding box) 13 ty key text y offset (within key/btn bounding box) 14 cb callback function to accept following parameters: 0 v key: a single printable char, string for non-printables: "bs" for backspace, "cr/lf", "sh0".."sh4" for shift key 1 k keyboard (this sigleton) 1 u ui core singleton (see ui module) 2 e key btn that was just released (see uiBtn module) 3 t touch object (see ui module)
--- uiKbd3x10B - soft keyboard properties - variables and methods - mixed into ui base:
exports = // uiKbd3x10B { mn: "uiKbd3x10B" , kc: 30 // key count , fi: -1 // idx 1st key in ui.es ui elts; adjust when insert/remove before , fk: null // first key ("q") , lt: 0.14 // short touch maximum / medium ('long') touch min time in seconds , tt: 0 // touch time in secs , sm: 0 // shift mode (0="^", 1="^^", 2="^#", 3="^^^") , sk: null // shift key , cb: null // callback , st: ["^","^^","^^^","#^"] // for shift key status display // .... // ... public methods - documented above // ... private methods // ... }
- When no-shift (^): first char on key prints.
-
• #17
----- uiEBC ------------------------- 20190927
The ui Extension for Button Controlled ui vs touch screen controlled ui.
ui EBC extension requires uiExt module.
The uiEBC extension works already well with plain buttons, check boxes and
radio buttons with just watched buttons. Even though it works also with
the uiKbd3x10B soft keyboard and uiInp input field module when choosing
and passing the proper un-touch delay(s). Better support is under
construction.The uiExampleAll shows in emulation how to use 1 to three buttons to
navigate and 'tap' / 'touch' a ui with buttons, check boxes, and radio
buttons.The extension supports select next ui element, select previous ui element
and 'tap' selected ui element. By default, select next and previous cycle
thru all active and visible buttons (flags: 0b0011 = 3) with wrap around.
Optional first and last index values can be supplied to stay within a
a range of ui elements, such as a keyboard or keypad when in an input
field. Wrap around can be controlled was well.The uiEBC extension is added to the base ui the same way as the uiExt
extension module. uiEBC extension requires iuExt extension to be loaded
in order to work.var ui = require("ui") ,add(require("uiBtn")) .add(require("uiExt")) ,add(require("uiEBC")) ;
There can be only one ui element selected at one time. The visual cue is
left and top borders of a rectangle in touch color.--- Brief documentation of the methods / functions available:
- .sd - delay for re-drawing the selection cue after ui element has been
tapped / (un)touched - which concludes with a blur. Application
can control / overwrite select redraw delay as well as the (un)touch
delay by passing values to tap/touch selected ui element mimicking
tap / touch duration :.st(sd,ud)
. Passing a value fordu
will
override the default value specified inui
base module. - .sx - property holds index of selected element in ui element array
.es.
Value-1
indicates that no ui element is selected. - .sn(w,f,l) - method selects the next qualifying ui element. If there is
none (anymore, if not wrapped), undefined is returned. If there is
only exactly one, then that one is returned every time. If none is
currently selected, the first one is returned. - .st(sd,ud) - method taps / touches the selected ui element and delays the
untouch by specified time overriding the.ud
default as defined
in theuiExt
module, where the tap / touch function.t(iie,ud)
is defined.
Select next and previous will be constrained in the future by a bit map
in addition to the range to proved more flexibility over non-contiguous
ranges of qualifying and application desired ui elements.--- EBC - ui extension for push button controlled ui - properties - variables
and methods - mixed into ui base:exports = // ui ctrl w/ btns vs touch ext, used by ui3|4|5|6BC modules { mn: "uiEBC" // module 'clazz' name - globally unique (used to rem frm cache) , sd: 100 // ms default select delay , sx: -1 // idx elt selected w/ ui ctrl w/ phys push btns, no touch // .... // ... public methods - documented above // ... private methods // ... }
Attached shots: 3, 2 and 1 physical push button example added. With small change in keyboard and input field, the ui can be driven by as little as 1 button. Of course, more buttons increase efficiency. The visual cue that a ui element is selected are the bright horizontal and vertical lines above and left of the ui element.
2 Attachments
- .sd - delay for re-drawing the selection cue after ui element has been
-
• #18
----- ui on Pixl.js ------------------------- 20190927 - *** PREVIEW ***
First of all: Espruino Pixl.js is just cool... - I guess you know that... so:
I created and example for Pixl... worked right out of box... with proper color converter as soon as I understood Pixl's color philosophy and designing the ui in black&white. Vector fonts do not work out that great in the desired (small) size.... and with that some changes arose. The solution approach for fonts is the same ways as custom colors: fonts are added into an array and referenced with 'negative font vector (sizes): -1 as font means: pick the font that has been added as the first one. The changes made so far have not been back-ported and tested yet for non-Pixl displays, but they will... and they will enhance actually the overall framework. Because Pixl is a bit shorter on memory than PICO and I wanted still to work on the un-minified sources, I produced _U - uncommented versions.... and so far, these include the changes needed for Pixl.
So that you can start to play with the ui framework on Pixle, I added the sandbox _sbx that holds all what you need for this example - foremost the _U versions.
Below code of the
uiExamplePixl.js
project file that produces the UI shown in attached screenshot. I chose three (3) buttons to control the ui:BTN1
(left top) andBTN2
(right top) jump between ui elements -previous
andnext
- undBTN3
(right bottom) is the enter /touch
button. In attached screenshot, you see the first - unchecked -checkbox ui element selected. PressingBTN3
will check the checkbox and fire the callback.// uiExamplePixl.js - pixl - example // 20190930 - allObjects - variables: ~ / ~ // ----- 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) - (..._U = uncommented) var ui = require("ui_U") // basic module _U(ncommented) .adx(require("uiExt_U"),-1,"uiExt_U") // basic extension .adx(require("uiEBC_U"),-1,"uiEBC_U") // button controlled ui extension .adx(require("uiBtn_U"),-1,"uiBtn_U") // ui button element .adx(require("uiChk_U"),-1,"uiChk_U") // ui checkbox element .adx(require("Font6x8"),-2,"Font6x8") // pixl suitable bitmap font ; // define Pixl Button 'clazz' var uiPBt = function(btn,downCb,upCb,debounce) { var t=0; setWatch( function(e){ if (! t) { t=Math.round(e.time*1000); if (downCb) downCb(t); }} , btn, {edge:"rising" ,repeat:true, debounce:debounce} ); setWatch( function(e){ if ( t) { upCb(Math.round(e.time*1000)-t); t=0; }} , btn, {edge:"falling",repeat:true,debounce:debounce} ); }; // ------- uiPBt ----------------------------------- // ----- 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 fv tc x y label txt ca ui.c( 3,"btn","b1" , 0, 20, 30, 19, 0, 0, "B_1", cb, [-1, 7, 7, 6, "RED" ]); ui.c( 3,"btn","b2" , 29, 20, 41, 19, 0, 7, {v:1}, ca , [-1, 0, 7, 6, "Y-w-B"], ca); // ---------- Checkbox examples ---------- // 0 1 2 3 4 5 6 7 8 9 10 11 12 // flgs clazz id x y w s bc fc valObj cb, l (label array obj) // chk ->x2+>y2~------->[s,vOjb] fv tc x y label txt ui.c( 3,"chk","c1" , 69, 20, 19, 0, 0, 7, "H", cb, [-1, 0, 1, 6, "On" ]); ui.c( 3,"chk","c2" , 99, 20, 19, 1, 0, 0, "X", u , [-1, 0, 1, 6, "Up" ], ca); //----- Pixl sepcifics var dsp = g, dspW=128, dspH=64 // ...to keep var names as usual ; ui.bc=7; // set ui background color to white ui.tc=0; // set ui touch color to black ui.clrs= // set white to pixl color [function(c,i){ var v=(i)?c^7:c; return [(v&&4)?0:1]; }.bind(ui) ]; var flp; // ----- run UI function onInit() { dsp.clear(); LED.set(); // display clear and turn back light on setTimeout(function(){ // connect ui to dsp and display it ui.connect(dsp) .w(0,0,dspW-1,dspH-1) // wipe screen (rect) w/ default / bg color .d() // display all elements .di = true // set display changes to immediate ; flp = function(){ dsp.flip(); }; flp(); new uiPBt(BTN1,0,function(t){console.log(1);ui.sp();flp();}); // sel prev on BTN1 new uiPBt(BTN2,0,function(t){console.log(2);ui.sn();flp();}); // sel next on BTN2 new uiPBt(BTN3,0,function(t){console.log(3);ui.st(t+70,t);setTimeout(flp,t+140);}); },1000); } setTimeout(onInit,999); // for dev only, remove before save()
Remaining ui elements will be adjusted to work also on Pixl and changes will be back ported, examples updated, documentation adjusted... and emulation will follow thereafter. This all will take 'a few' days. In the mean time:
- happy Pixl-ing @ allObjects - w/ attached sandbox.
Attached: _sbx - Sandbox folder with all what Pixl needs... and a screenshot (related to chosen font size... can go smaller or larger... all a simple matter of the UI definitions...).
2 Attachments
- happy Pixl-ing @ allObjects - w/ attached sandbox.
-
• #19
ui on other displays - tbp
-
• #20
ui experimental all touch events callback - drag and drop - tbp
-
• #21
----- varia ----------- DisplayUiEltWithCumstomFormatter.js
*** Varia: Display ui element with custom formatter
Custom renderers / formatters may take ui and touch states / flags into
account in their logic. This can cause interference issues when using
ui's display function on element:ui.d(e)
. Issue is that sometimes
the renderer / formatter works, and sometimes not.There are three (3) options for a solution:
--- Setup
The
ui
singleton (framework)var ui = require("ui") // UI singleton holding slider s2 (below) // ...
slider "s2" kept held onto with variable
s2
:var s2 = ui.c( 3,"sli","s2",... // slider - uiSli - w/ custom formatter taking ui / touch event // states / flags into consideration in logic // function(v,_) { if (_t.te.f... ) { ...
For more details see instructions in
ui
,uiBtn
anduiSli
modules.--- Options
option 1
// option 1 - where no touch event is ongoing and flags f has to keep state: // set touch event flags all to 0 before invoking display of ui element ui.te.f = 0; ui.d(s2); // display value label of slider
option 2
// option 2 - where touch event is ongoing but flags f have to keep state: // backup flags, set all to 0 or as desired, invoke display AND restore var fs = ui.te.f; ui.te.f=0; ui.d(s2).te.f=fs;
option 3
// option 3 - use additional control flag // introduce a flag yourself 'outside' / global or on ui which works as // a one-shot trigger in the render / formatter function - or as in // the example code below: stick it as property to the ```ui``` object // (just use property name 6 or more chars). function(v,_) { if (_.myOverrideFlag || !_.te.t) { _.myOverrideFlag=0; // ...the other stuff } } // ui.myOverrideFlag=1; ui.d(s2);
option 4
// option 4 - extend ui with .dWrapped(e) wrapping of .d(e) and // using option 2 for implementation ui.dWrapped(e) = function (){var fs=this.te.f; this.d(e).te.f=fs; return this;}; // ... ui.dWrapped(e);
-
• #22
ui varia 2 - tbp
-
• #23
ui varia 3 - tbp
-
• #24
----- 2019-09-24 Update -----
Finally some rework and review round trip completed to share things that had its design in 2015, some rework in 2016 and 2017 and just now.
Updated zip file is to be found in --->post #7 .
Reviewing and getting code and some doc ready for pub did not go without some enhancements and adding a few vars to the foot print.
Event categorization with flags and handling got a significant lift to give more control to the user and application. Also the slider got a technical as well as a face lift. Some issues got resolved, such as ui elements changing unintended their values by just dragging over them.
Input field is still a bit bare bones and kept as such... last but not least because of slowness of (communication to) most displays. Have to come up w/ some enhanced version... being a different ui element 'clazz' though to keep the simple version with small foot print.
The general idea of publishing in this conversation is to get it out and get feedback. Over time these posts will change including the zip file uploaded in post #8 with all the code - modules, examples and cross development components (on functional changes). Old versions will be kept there as long as possible.
After a while things will move into regular site's modules folder and into module and tutorial pages.
Cu after reading up from ---> post #7 on.
-
• #25
----- 2019-09-27 Update -----
As new extension module has been added: support for control with watched push buttons rather than with touch screen - see ---> post #17 . Same time, the keyboard, the input fields and the uiExt extension got some enhancements, last but not least to support watched buttons to drive the ui. So far all but the sliders can be used - with three (3) buttons it is very comfortable: two (2) buttons to cycle forward and backward thru he ui elements and the third - 'Enter' / Tap - button is for tapping. Timing the tapping - how long the push button has been pressed and passing it when calling the tap selected ui element -
.ts(...)
- gives access to also the timed functions:- short tap / touch / press the button: < 140 ms
- medium tap / touch / press the button: 140..450 ms
- long tap / touch / press the button: >450 ms
The input field has a callback that checks tap time, and when it is more than 550 ms, the input field is cleared. The delete x in the top right corner of the input field is part of the ui element and not one of its own, so it cannot be reached with cycling through the ui elements. Having separate buttons for navigation / 'moving' the selection and the action tapping makes operation safe. Increasing the time for clearing the input field to make it distinctive from cycling backwards with a long press.
Other, non-functional changes is the renaming of the example: replacing the DspTouch infix in the names with just Example provides room the examples to also include button operation vs touch operation. Both can be used simultaneously... (with one caveat: touchscreen tapping does not preserve the visual cue what ui element is selected at times.
Updated zip file is to be found in --->post #7 .
- short tap / touch / press the button: < 140 ms
1 of n posts
Tip for best display of code sections without line wrapping : change browser window to the sweet spot where no line wrapping happens.
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