As it comes, Bangle.js provides several utility functions that other apps use to provide more functionality.
For example:
E.showMessage
shows a messageE.showAlert
shows a message with an 'ok' buttonE.showPrompt
shows a message with multiple buttonsE.showMenu
shows a menu where items can be selected and tweakedBangle.setUI
provides easy access to Bangle.js buttons/touchscreenFor usage info on these, see the reference
These functions are built in and work a certain way, but they can be changed if you don't like the look of them, for instance with the Small Menus App.
You might want to change the positioning, font size, or even the way you interact with the menus completely!
So how does this work?
For this example, we'll look at E.showMessage
as it's nice and simple.
In most cases, the implementation of the function will be in JavaScript in the Espruino Repository, but it's worth checking.
⇒
arrow next to it.For E.showMessage
you're taken to the Pixl.js implementation (there can be more than one implementation) which looks
like this:
/*JSON{
"type" : "staticmethod",
"class" : "E",
"name" : "showMessage",
"generate_js" : "libs/js/pixljs/E_showMessage.min.js",
"params" : [
["message","JsVar","A message to display. Can include newlines"],
["title","JsVar","(optional) a title for the message"]
],
"ifdef" : "PIXLJS"
}
...
*/
So here you can see it's loading up libs/js/pixljs/E_showMessage.min.js
.
We can guess where the Bangle.js one is... libs/js/banglejs/E_showMessage.js
Note: sometimes there will be multiple versions of a file, like _Q3
(Bangle.js 2)
and _F18
(Bangle.js 1)
Bear in mind these functions are generally written for execution speed and not readability!
Now you have your file, copy it into the IDE with E.showMessage =
before
it (or whatever function you're trying to replace) and copy out one of the
usage examples from the documentation to right below it - like this:
E.showMessage = function(msg,options) {
if ("string" == typeof options)
options = { title : options };
options = options||{};
g.clear(1); // clear screen
Bangle.drawWidgets(); // redraw widgets
g.reset().setFont("6x8",(g.getWidth()>128)?2:1).setFontAlign(0,-1);
var Y = global.WIDGETS ? 24 : 0;
var W = g.getWidth(), H = g.getHeight()-Y, FH=g.getFontHeight();
var titleLines = g.wrapString(options.title, W-2);
var msgLines = g.wrapString(msg||"", W-2);
var y = Y + (H + (titleLines.length - msgLines.length)*FH )/2;
if (options.img) {
var im = g.imageMetrics(options.img);
g.drawImage(options.img,(W-im.width)/2,y - im.height/2);
y += 4+im.height/2;
}
g.drawString(msgLines.join("\n"),W/2,y);
if (options.title)
g.setColor(g.theme.fgH).setBgColor(g.theme.bgH).
clearRect(0,Y,W-1,Y+4+titleLines.length*FH).
drawString(titleLines.join("\n"),W/2,Y+2);
Bangle.setLCDPower(1); // ensure screen is on
};
E.showMessage("Lots of text will wrap automatically",{
title:"Warning",
img:atob("FBQBAfgAf+Af/4P//D+fx/n+f5/v+f//n//5//+f//n////3//5/n+P//D//wf/4B/4AH4A=")
})
You can now run it - make sure you upload to RAM
:
You may also want to test it with widgets, in which case you can add these lines right before your test call:
Bangle.loadWidgets();
Bangle.drawWidgets();
Ok, now you can tweak the function - let's say we want to put a rounded border around the edge:
E.showMessage = function(msg,options) {
if ("string" == typeof options)
options = { title : options };
options = options||{};
g.clear(1); // clear screen
Bangle.drawWidgets(); // redraw widgets
g.reset().setFont("6x8",(g.getWidth()>128)?2:1).setFontAlign(0,-1);
var Y = global.WIDGETS ? 24 : 0;
var W = g.getWidth(), H = g.getHeight()-Y, FH=g.getFontHeight();
var titleLines = g.wrapString(options.title, W-2);
var msgLines = g.wrapString(msg||"", W-2);
var y = Y + (H + (titleLines.length - msgLines.length)*FH )/2;
var yt = Y + titleLines.length*FH;
// colour everything
g.setColor(g.theme.bgH).fillRect(0,Y,W-1,g.getHeight());
// add a white inner with rounded borders
g.setColor(g.theme.bg).
fillRect(8,yt+16,W-8,g.getHeight()-16).
fillRect(16,yt+8,W-17,g.getHeight()-8).
fillCircle(16,yt+16,8).
fillCircle(W-16,yt+16,8).
fillCircle(16,g.getHeight()-16,8).
fillCircle(W-16,g.getHeight()-16,8).
setColor(g.theme.fg);
// draw image
if (options.img) {
var im = g.imageMetrics(options.img);
g.drawImage(options.img,(W-im.width)/2,y - im.height/2);
y += 4+im.height/2;
}
// message body
g.drawString(msgLines.join("\n"),W/2,y);
// title
if (options.title)
g.setColor(g.theme.fgH).setBgColor(g.theme.bgH).
drawString(titleLines.join("\n"),W/2,Y+2);
Bangle.setLCDPower(1); // ensure screen is on
};
E.showMessage("Lots of text will wrap automatically",{
title:"Warning",
img:atob("FBQBAfgAf+Af/4P//D+fx/n+f5/v+f//n//5//+f//n////3//5/n+P//D//wf/4B/4AH4A=")
})
This is really easy - simply delete all your test code, so you're left with just something like:
E.showMessage = function(msg,options) {
// ...
};
Now:
Storage
, New File
mytweaks.boot.js
as the nameUpload
buttonNothing will happen immediately, but now try typing E.showMessage("Boo!")
in the left
hand side of the IDE - you'll get the new message box.
Your watch will now be usable as it was before, but all apps will have your updated menu.
Note: The next time you upload, the saved version of your code will
not update because Bangle.js caches the boot files. You will need to
type load("bootupdate.js")
into the left-hand side of the IDE.
Now everything is working, you can turn this into an app.
mytweaks
BangleApps/apps/mytweaks
E.showMessage
implementation as boot.js
app.png
metadata.json
, remembering
to change mytweaks
to whatever app ID you decided to use:{
"id": "mytweaks",
"name": "Rounded showMessage",
"version": "0.01",
"description": "Replace built in E.showMessage",
"icon": "app.png",
"type": "boot",
"tags": "system",
"supports": ["BANGLEJS2"],
"storage": [
{"name":"mytweaks.boot.js","url":"boot.js"}
]
}
And now you're done! You can either use it on your own personal app loader, or can submit it to the main Bangle.js app loader!
This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.