Big refactor #2 - variable width widgets
parent
a772280871
commit
e0d29c81f2
26
README.md
26
README.md
|
|
@ -120,7 +120,7 @@ Apps are listed in the Bangle.js menu, accessible from a clock app via the middl
|
||||||
|
|
||||||
#### `app-icon.js`
|
#### `app-icon.js`
|
||||||
|
|
||||||
The icon image and short description is used in the menu entry as selection possibility.
|
The icon image and short description is used in Bangle.js's launcher.
|
||||||
|
|
||||||
Use the Espruino [image converter](https://www.espruino.com/Image+Converter) and upload your `app.png` file.
|
Use the Espruino [image converter](https://www.espruino.com/Image+Converter) and upload your `app.png` file.
|
||||||
|
|
||||||
|
|
@ -136,11 +136,14 @@ Follow this steps to create a readable icon as image string.
|
||||||
Replace this line with the image converter output:
|
Replace this line with the image converter output:
|
||||||
|
|
||||||
```
|
```
|
||||||
require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA=="));
|
require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA=="))
|
||||||
```
|
```
|
||||||
|
|
||||||
Keep in mind to use this converter for creating images you like to draw with `g.drawImage()` with your app.
|
You can also use this converter for creating images you like to draw with `g.drawImage()` with your app.
|
||||||
|
|
||||||
|
Apps that need widgets can call `Bangle.loadWidgets()` **once** at startup to load
|
||||||
|
them, and then `Bangle.drawWidgets()` to draw them onto the screen whenever the app
|
||||||
|
has call to completely clear the screen. Widgets themselves will update as and when needed.
|
||||||
|
|
||||||
### Widget Example
|
### Widget Example
|
||||||
|
|
||||||
|
|
@ -149,6 +152,23 @@ The widget example is available in [`apps/_example_widget`](apps/_example_widget
|
||||||
* `add_to_apps.json` - insert into `apps.json`, describes the widget to bootloader and loader
|
* `add_to_apps.json` - insert into `apps.json`, describes the widget to bootloader and loader
|
||||||
* `widget.js` - widget code
|
* `widget.js` - widget code
|
||||||
|
|
||||||
|
Widgets are just small bits of code that run whenever an app that supports them
|
||||||
|
calls `Bangle.loadWidgets()`. If they want to display something in the 24px high
|
||||||
|
widget bars at the top and bottom of the screen they can add themselves to
|
||||||
|
the global `WIDGETS` array with:
|
||||||
|
|
||||||
|
```
|
||||||
|
WIDGETS["mywidget"]={
|
||||||
|
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
|
||||||
|
width: 24, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout
|
||||||
|
draw:draw // called to draw the widget
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
When the widget is to be drawn, `x` and `y` values are set up in `WIDGETS["mywidget"]`
|
||||||
|
and `draw` can then use `this.x` and `this.y` to figure out where it needs to draw to.
|
||||||
|
|
||||||
|
|
||||||
### `app.info` format
|
### `app.info` format
|
||||||
|
|
||||||
This is the file that's **auto-generated** and loaded onto Bangle.js by the App Loader,
|
This is the file that's **auto-generated** and loaded onto Bangle.js by the App Loader,
|
||||||
|
|
|
||||||
25
apps.json
25
apps.json
|
|
@ -66,7 +66,7 @@
|
||||||
{ "id": "gbridge",
|
{ "id": "gbridge",
|
||||||
"name": "Gadgetbridge",
|
"name": "Gadgetbridge",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.03",
|
"version":"0.04",
|
||||||
"description": "The default notification handler for Gadgetbridge notifications from Android",
|
"description": "The default notification handler for Gadgetbridge notifications from Android",
|
||||||
"tags": "tool,system,android,widget",
|
"tags": "tool,system,android,widget",
|
||||||
"storage": [
|
"storage": [
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
"name": "Default Alarm",
|
"name": "Default Alarm",
|
||||||
"shortName":"Alarms",
|
"shortName":"Alarms",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.03",
|
"version":"0.04",
|
||||||
"description": "Set and respond to alarms",
|
"description": "Set and respond to alarms",
|
||||||
"tags": "tool,alarm,widget",
|
"tags": "tool,alarm,widget",
|
||||||
"storage": [
|
"storage": [
|
||||||
|
|
@ -249,7 +249,7 @@
|
||||||
{ "id": "gpsrec",
|
{ "id": "gpsrec",
|
||||||
"name": "GPS Recorder",
|
"name": "GPS Recorder",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.04",
|
"version":"0.05",
|
||||||
"interface": "interface.html",
|
"interface": "interface.html",
|
||||||
"description": "Application that allows you to record a GPS track. Can run in background",
|
"description": "Application that allows you to record a GPS track. Can run in background",
|
||||||
"tags": "tool,outdoors,gps,widget",
|
"tags": "tool,outdoors,gps,widget",
|
||||||
|
|
@ -285,7 +285,7 @@
|
||||||
{ "id": "widbat",
|
{ "id": "widbat",
|
||||||
"name": "Battery Level Widget",
|
"name": "Battery Level Widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.02",
|
"version":"0.03",
|
||||||
"description": "Show the current battery level and charging status in the top right of the clock",
|
"description": "Show the current battery level and charging status in the top right of the clock",
|
||||||
"tags": "widget,battery",
|
"tags": "widget,battery",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
@ -296,7 +296,7 @@
|
||||||
{ "id": "widbt",
|
{ "id": "widbt",
|
||||||
"name": "Bluetooth Widget",
|
"name": "Bluetooth Widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.01",
|
"version":"0.02",
|
||||||
"description": "Show the current Bluetooth connection status in the top right of the clock",
|
"description": "Show the current Bluetooth connection status in the top right of the clock",
|
||||||
"tags": "widget,bluetooth",
|
"tags": "widget,bluetooth",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
@ -318,7 +318,7 @@
|
||||||
{ "id": "widhrm",
|
{ "id": "widhrm",
|
||||||
"name": "Simple Heart Rate widget",
|
"name": "Simple Heart Rate widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.01",
|
"version":"0.02",
|
||||||
"description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.",
|
"description": "When the screen is on, the widget turns on the heart rate monitor and displays the current heart rate (or last known in grey). For this to work well you'll need at least a 15 second LCD Timeout.",
|
||||||
"tags": "health,widget",
|
"tags": "health,widget",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
@ -329,7 +329,7 @@
|
||||||
{ "id": "stetho",
|
{ "id": "stetho",
|
||||||
"name": "Stethoscope",
|
"name": "Stethoscope",
|
||||||
"icon": "stetho.png",
|
"icon": "stetho.png",
|
||||||
"version":"0.0198",
|
"version":"0.01",
|
||||||
"description": "Hear your heart rate",
|
"description": "Hear your heart rate",
|
||||||
"tags": "health",
|
"tags": "health",
|
||||||
"storage": [
|
"storage": [
|
||||||
|
|
@ -472,7 +472,7 @@
|
||||||
{ "id": "widnceu",
|
{ "id": "widnceu",
|
||||||
"name": "NCEU Logo Widget",
|
"name": "NCEU Logo Widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.01",
|
"version":"0.02",
|
||||||
"description": "Show the NodeConf EU logo in the top left",
|
"description": "Show the NodeConf EU logo in the top left",
|
||||||
"tags": "widget",
|
"tags": "widget",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
@ -480,9 +480,6 @@
|
||||||
{"name":"widnceu.wid.js","url":"widget.js"}
|
{"name":"widnceu.wid.js","url":"widget.js"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ "id": "sclock",
|
{ "id": "sclock",
|
||||||
"name": "Simple Clock",
|
"name": "Simple Clock",
|
||||||
"icon": "clock-simple.png",
|
"icon": "clock-simple.png",
|
||||||
|
|
@ -704,7 +701,7 @@
|
||||||
{ "id": "widclk",
|
{ "id": "widclk",
|
||||||
"name": "Digital clock widget",
|
"name": "Digital clock widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.01",
|
"version":"0.02",
|
||||||
"description": "A simple digital clock widget",
|
"description": "A simple digital clock widget",
|
||||||
"tags": "widget,clock",
|
"tags": "widget,clock",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
@ -715,7 +712,7 @@
|
||||||
{ "id": "widpedom",
|
{ "id": "widpedom",
|
||||||
"name": "Pedometer widget",
|
"name": "Pedometer widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.06",
|
"version":"0.07",
|
||||||
"description": "Daily pedometer widget",
|
"description": "Daily pedometer widget",
|
||||||
"tags": "widget",
|
"tags": "widget",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
@ -804,7 +801,7 @@
|
||||||
{ "id": "widid",
|
{ "id": "widid",
|
||||||
"name": "Bluetooth ID Widget",
|
"name": "Bluetooth ID Widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.01",
|
"version":"0.02",
|
||||||
"description": "Display the last two tuple of your Bangle.js address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!",
|
"description": "Display the last two tuple of your Bangle.js address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!",
|
||||||
"tags": "widget",
|
"tags": "widget",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
/* run widgets in their own function scope so they don't interfere with
|
/* run widgets in their own function scope so they don't interfere with
|
||||||
currently-running apps */
|
currently-running apps */
|
||||||
(() => {
|
(() => {
|
||||||
// add the width
|
|
||||||
var xpos = WIDGETPOS.tr-24;/*<the widget width>*/;
|
|
||||||
WIDGETPOS.tr-= 28;/* the widget width plus some extra pixel to keep distance to others */;
|
|
||||||
|
|
||||||
// draw your widget at xpos
|
|
||||||
function draw() {
|
function draw() {
|
||||||
g.reset(); // reset the graphics context to defaults (color/font/etc)
|
g.reset(); // reset the graphics context to defaults (color/font/etc)
|
||||||
// add your code
|
// add your code
|
||||||
|
g.drawString("X", this.x, this.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add your widget
|
// add your widget
|
||||||
WIDGETS["mywidget"]={draw:draw};
|
WIDGETS["mywidget"]={
|
||||||
|
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
|
||||||
|
width: 28, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout
|
||||||
|
draw:draw // called to draw the widget
|
||||||
|
};
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Fix issues with alarm scheduling
|
0.02: Fix issues with alarm scheduling
|
||||||
0.03: More alarm scheduling issues
|
0.03: More alarm scheduling issues
|
||||||
|
0.04: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
(() => {
|
(() => {
|
||||||
var alarms = require('Storage').readJSON('alarm.json',1)||[];
|
var alarms = require('Storage').readJSON('alarm.json',1)||[];
|
||||||
alarms = alarms.filter(alarm=>alarm.on);
|
alarms = alarms.filter(alarm=>alarm.on);
|
||||||
if (!alarms.length) return;
|
if (!alarms.length) return; // no alarms, no widget!
|
||||||
delete alarms;
|
delete alarms;
|
||||||
// add the width
|
|
||||||
var xpos = WIDGETPOS.tl;
|
|
||||||
WIDGETPOS.tl += 24;/* the widget width plus some extra pixel to keep distance to others */;
|
|
||||||
|
|
||||||
// draw your widget at xpos
|
|
||||||
|
|
||||||
// add the widget
|
// add the widget
|
||||||
WIDGETS["alarm"]={draw:function() {
|
WIDGETS["alarm"]={area:"tl",width:24,draw:function() {
|
||||||
g.setColor(-1);
|
g.setColor(-1);
|
||||||
g.drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),xpos,0);
|
g.drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
||||||
}};
|
}};
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: Initial version
|
0.01: Initial version
|
||||||
0.02: Increase contrast (darker notification background, white text)
|
0.02: Increase contrast (darker notification background, white text)
|
||||||
0.03: Gadgetbridge widget now shows connection state
|
0.03: Gadgetbridge widget now shows connection state
|
||||||
|
0.04: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
0.01: Initial version
|
||||||
|
0.02: Increase contrast (darker notification background, white text)
|
||||||
|
0.03: Gadgetbridge widget now shows connection state
|
||||||
|
0.04: Tweaks for variable size widget system
|
||||||
|
|
@ -109,19 +109,17 @@
|
||||||
function draw() {
|
function draw() {
|
||||||
g.setColor(-1);
|
g.setColor(-1);
|
||||||
if (NRF.getSecurityStatus().connected)
|
if (NRF.getSecurityStatus().connected)
|
||||||
g.drawImage(require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")),xpos+1,1);
|
g.drawImage(require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")),this.x+1,this.y+1);
|
||||||
else
|
else
|
||||||
g.drawImage(require("heatshrink").decompress(atob("i0WwQFC1WgAgYFDAgIFClQFCwEK1W/AoIPB1f+CAMq1f7/WqwQPB/fq1Gq1/+/4dC/2/CAIaB/YbBAAO///qAoX/B4QbBDQQ7BDQQrBAAWoIIIACIIIVC0ECB4cACAZiBAoRtCAoIDBA")),xpos+1,1);
|
g.drawImage(require("heatshrink").decompress(atob("i0WwQFC1WgAgYFDAgIFClQFCwEK1W/AoIPB1f+CAMq1f7/WqwQPB/fq1Gq1/+/4dC/2/CAIaB/YbBAAO///qAoX/B4QbBDQQ7BDQQrBAAWoIIIACIIIVC0ECB4cACAZiBAoRtCAoIDBA")),this.x+1,this.y+1);
|
||||||
}
|
}
|
||||||
function changed() {
|
function changed() {
|
||||||
draw();
|
WIDGETS["gbridgew"].draw();
|
||||||
g.flip();// turns screen on
|
g.flip();// turns screen on
|
||||||
}
|
}
|
||||||
NRF.on('connected',changed);
|
NRF.on('connected',changed);
|
||||||
NRF.on('disconnected',changed);
|
NRF.on('disconnected',changed);
|
||||||
|
|
||||||
var xpos = WIDGETPOS.tl;
|
WIDGETS["gbridgew"]={area:"tl",width:24,draw:draw};
|
||||||
WIDGETPOS.tl+=24;
|
|
||||||
WIDGETS["gbridgew"]={draw:draw};
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
0.02: Fix GPS time logging
|
0.02: Fix GPS time logging
|
||||||
0.03: Fix GPS time display in gpsrec app
|
0.03: Fix GPS time display in gpsrec app
|
||||||
0.04: Properly Fix GPS time display in gpsrec app
|
0.04: Properly Fix GPS time display in gpsrec app
|
||||||
|
0.05: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,29 @@
|
||||||
(() => {
|
(() => {
|
||||||
// add the width
|
|
||||||
var xpos = WIDGETPOS.tl;
|
|
||||||
WIDGETPOS.tl += 24;/* the widget width plus some extra pixel to keep distance to others */;
|
|
||||||
var settings = {};
|
var settings = {};
|
||||||
var hasFix = false;
|
var hasFix = false;
|
||||||
var fixToggle = false; // toggles once for each reading
|
var fixToggle = false; // toggles once for each reading
|
||||||
var gpsTrack; // file for GPS track
|
var gpsTrack; // file for GPS track
|
||||||
var periodCtr = 0;
|
var periodCtr = 0;
|
||||||
|
|
||||||
// draw your widget at xpos
|
// draw your widget
|
||||||
function draw() {
|
function draw() {
|
||||||
|
if (!settings.recording) return;
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setFont("4x6");
|
g.setFont("4x6");
|
||||||
g.setFontAlign(0,0);
|
g.setFontAlign(0,0);
|
||||||
g.clearRect(xpos,0,xpos+23,23);
|
g.clearRect(this.x,this.y,this.x+23,this.y+23);
|
||||||
|
g.setColor("#ff0000");
|
||||||
if (!settings.recording) {
|
if (hasFix) {
|
||||||
g.setColor("#606060");
|
if (fixToggle) {
|
||||||
|
g.fillCircle(this.x+11,this.y+11,9);
|
||||||
|
g.setColor("#000000");
|
||||||
|
} else
|
||||||
|
g.drawCircle(this.x+11,this.y+11,9);
|
||||||
} else {
|
} else {
|
||||||
g.setColor("#ff0000");
|
g.drawString("NO",this.x+12,this.y+5);
|
||||||
if (hasFix) {
|
g.drawString("FIX",this.x+12,this.y+19);
|
||||||
if (fixToggle) {
|
|
||||||
g.fillCircle(xpos+11,11,9);
|
|
||||||
g.setColor("#000000");
|
|
||||||
} else
|
|
||||||
g.drawCircle(xpos+11,11,9);
|
|
||||||
} else {
|
|
||||||
g.setColor(fixToggle ? "#ff0000" : "#7f0000");
|
|
||||||
g.drawString("NO",xpos+12,5);
|
|
||||||
g.drawString("FIX",xpos+12,19);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g.drawString("GPS",xpos+12,12);
|
g.drawString("GPS",this.x+12,this.y+12);
|
||||||
g.setColor(-1); // change color back to be nice to other apps
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGPS(fix) {
|
function onGPS(fix) {
|
||||||
|
|
@ -53,7 +44,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the GPS app to reload settings and decide what's
|
// Called by the GPS app to reload settings and decide what to do
|
||||||
function reload() {
|
function reload() {
|
||||||
settings = require("Storage").readJSON("gpsrec.json",1)||{};
|
settings = require("Storage").readJSON("gpsrec.json",1)||{};
|
||||||
settings.period = settings.period||1;
|
settings.period = settings.period||1;
|
||||||
|
|
@ -61,17 +52,22 @@
|
||||||
|
|
||||||
Bangle.removeListener('GPS',onGPS);
|
Bangle.removeListener('GPS',onGPS);
|
||||||
if (settings.recording) {
|
if (settings.recording) {
|
||||||
|
WIDGETS["gpsrec"].width = 24;
|
||||||
Bangle.on('GPS',onGPS);
|
Bangle.on('GPS',onGPS);
|
||||||
Bangle.setGPSPower(1);
|
Bangle.setGPSPower(1);
|
||||||
var n = settings.file.toString(36);
|
var n = settings.file.toString(36);
|
||||||
gpsTrack = require("Storage").open(".gpsrc"+n,"a");
|
gpsTrack = require("Storage").open(".gpsrc"+n,"a");
|
||||||
} else {
|
} else {
|
||||||
|
WIDGETS["gpsrec"].width = 0;
|
||||||
Bangle.setGPSPower(0);
|
Bangle.setGPSPower(0);
|
||||||
gpsTrack = undefined;
|
gpsTrack = undefined;
|
||||||
}
|
}
|
||||||
draw();
|
|
||||||
}
|
}
|
||||||
reload();
|
|
||||||
// add the widget
|
// add the widget
|
||||||
WIDGETS["gpsrec"]={draw:draw,reload:reload};
|
WIDGETS["gpsrec"]={area:"tl",width:24,draw:draw,reload:function() {
|
||||||
|
reload();
|
||||||
|
Bangle.drawWidgets(); // relayout all widgets
|
||||||
|
}};
|
||||||
|
// load settings, set correct widget width
|
||||||
|
reload();
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ var clickTimes = [];
|
||||||
var CLICK_COUNT = 4; // number of taps
|
var CLICK_COUNT = 4; // number of taps
|
||||||
var CLICK_PERIOD = 1; // second
|
var CLICK_PERIOD = 1; // second
|
||||||
|
|
||||||
|
// we don't actually create/draw a widget here at all...
|
||||||
|
|
||||||
Bangle.on("lcdPower",function(on) {
|
Bangle.on("lcdPower",function(on) {
|
||||||
// First click (that turns LCD on) isn't given to
|
// First click (that turns LCD on) isn't given to
|
||||||
// setWatch, so handle it here
|
// setWatch, so handle it here
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
0.02: Now refresh battery monitor every minute if LCD on
|
0.02: Now refresh battery monitor every minute if LCD on
|
||||||
|
0.03: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
(function(){
|
(function(){
|
||||||
var img_charge = E.toArrayBuffer(atob("DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"));
|
|
||||||
var CHARGING = 0x07E0;
|
var CHARGING = 0x07E0;
|
||||||
var xpos = WIDGETPOS.tr-64;
|
|
||||||
WIDGETPOS.tr-=68;
|
|
||||||
|
|
||||||
|
function setWidth() {
|
||||||
|
WIDGETS["bat"].width = 40 + (Bangle.isCharging()?16:0);
|
||||||
|
}
|
||||||
function draw() {
|
function draw() {
|
||||||
var s = 63;
|
var s = 39;
|
||||||
var x = xpos, y = 0;
|
var x = this.x, y = this.y;
|
||||||
g.clearRect(x,y,x+s,y+23);
|
|
||||||
if (Bangle.isCharging()) {
|
if (Bangle.isCharging()) {
|
||||||
g.setColor(CHARGING).drawImage(img_charge,x,y);
|
g.setColor(CHARGING).drawImage(atob("DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y);
|
||||||
x+=16;
|
x+=16;
|
||||||
s-=16;
|
|
||||||
}
|
}
|
||||||
g.setColor(-1);
|
g.setColor(-1);
|
||||||
g.fillRect(x,y+2,x+s-4,y+21);
|
g.fillRect(x,y+2,x+s-4,y+21);
|
||||||
|
|
@ -20,7 +18,12 @@ function draw() {
|
||||||
g.setColor(CHARGING).fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);
|
g.setColor(CHARGING).fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);
|
||||||
g.setColor(-1);
|
g.setColor(-1);
|
||||||
}
|
}
|
||||||
Bangle.on('charging',function(charging) { draw(); g.flip(); if(charging)Bangle.buzz(); });
|
Bangle.on('charging',function(charging) {
|
||||||
|
if(charging) Bangle.buzz();
|
||||||
|
setWidth();
|
||||||
|
Bangle.drawWidgets(); // relayout widgets
|
||||||
|
g.flip();
|
||||||
|
});
|
||||||
var batteryInterval;
|
var batteryInterval;
|
||||||
Bangle.on('lcdPower', function(on) {
|
Bangle.on('lcdPower', function(on) {
|
||||||
if (on) {
|
if (on) {
|
||||||
|
|
@ -35,5 +38,6 @@ Bangle.on('lcdPower', function(on) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
WIDGETS["battery"]={draw:draw};
|
WIDGETS["bat"]={area:"tr",width:40,draw:draw};
|
||||||
|
setWidth();
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.02: Tweaks for variable size widget system
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
(function(){
|
(function(){
|
||||||
var img_bt = E.toArrayBuffer(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="));
|
var img_bt = E.toArrayBuffer(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="));
|
||||||
var xpos = WIDGETPOS.tr-24;
|
|
||||||
WIDGETPOS.tr-=24;
|
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
var x = xpos, y = 0;
|
g.reset();
|
||||||
if (NRF.getSecurityStatus().connected)
|
if (NRF.getSecurityStatus().connected)
|
||||||
g.setColor(0,0.5,1);
|
g.setColor(0,0.5,1);
|
||||||
else
|
else
|
||||||
g.setColor(0.3,0.3,0.3);
|
g.setColor(0.3,0.3,0.3);
|
||||||
g.drawImage(img_bt,10+x,2+y);
|
g.drawImage(img_bt,10+this.x,2+this.y);
|
||||||
g.setColor(1,1,1);
|
|
||||||
}
|
}
|
||||||
function changed() {
|
function changed() {
|
||||||
draw();
|
draw();
|
||||||
|
|
@ -18,5 +15,5 @@ function changed() {
|
||||||
}
|
}
|
||||||
NRF.on('connected',changed);
|
NRF.on('connected',changed);
|
||||||
NRF.on('disconnected',changed);
|
NRF.on('disconnected',changed);
|
||||||
WIDGETS["bluetooth"]={draw:draw};
|
WIDGETS["bluetooth"]={area:"tr",width:24,draw:draw};
|
||||||
})()
|
})()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.02: Now refresh battery monitor every minute if LCD on
|
||||||
|
|
@ -1,39 +1,27 @@
|
||||||
(() => {
|
(() => {
|
||||||
let intervalRef = null;
|
let intervalRef = null;
|
||||||
var width = 5 * 6*2
|
var width = 5 * 6*2
|
||||||
var xpos = WIDGETPOS.tr - width;
|
|
||||||
WIDGETPOS.tr -= (width + 2);
|
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
// Widget (0,0,239,23)
|
g.reset().setFont("6x8", 2).setFontAlign(-1, 0);
|
||||||
let date = new Date();
|
var time = require("locale").time(new Date(),1);
|
||||||
var dateArray = date.toString().split(" ");
|
g.drawString(time, this.x, this.y+11, true); // 5 * 6*2 = 60
|
||||||
g.setColor(1,1,1);
|
|
||||||
g.setFont("6x8", 2);
|
|
||||||
g.setFontAlign(-1, 0);
|
|
||||||
g.drawString(dateArray[4].substr(0, 5), xpos, 11, true); // 5 * 6*2 = 60
|
|
||||||
g.flip();
|
|
||||||
}
|
}
|
||||||
function clearTimers(){
|
function clearTimers(){
|
||||||
if(intervalRef) {
|
if(intervalRef) {
|
||||||
clearInterval(intervalRef);
|
clearInterval(intervalRef);
|
||||||
intervalRef = null;
|
intervalRef = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function startTimers(){
|
function startTimers(){
|
||||||
if(intervalRef) clearTimers();
|
intervalRef = setInterval(draw, 60*1000);
|
||||||
intervalRef = setInterval(draw, 60*1000);
|
draw();
|
||||||
draw();
|
|
||||||
}
|
}
|
||||||
Bangle.on('lcdPower', (on) => {
|
Bangle.on('lcdPower', (on) => {
|
||||||
if (on) {
|
clearTimers();
|
||||||
// startTimers(); // comment out as it is called by app anyway
|
if (on) startTimers();
|
||||||
} else {
|
|
||||||
clearTimers();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// add your widget
|
WIDGETS["wdclk"]={area:"tr",width:width,draw:draw};
|
||||||
WIDGETS["wdclk"]={draw:startTimers};
|
if (Bangle.isLCDOn) intervalRef = setInterval(draw, 60*1000);
|
||||||
|
|
||||||
})()
|
})()
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
0.01: New Widget!
|
0.01: New Widget!
|
||||||
|
0.02: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
(() => {
|
(() => {
|
||||||
var xpos = WIDGETPOS.tl;
|
|
||||||
var width = 24;
|
|
||||||
WIDGETPOS.tl += width+2;
|
|
||||||
var currentBPM = undefined;
|
var currentBPM = undefined;
|
||||||
var lastBPM = undefined;
|
var lastBPM = undefined;
|
||||||
var firstBPM = true; // first reading since sensor turned on
|
var firstBPM = true; // first reading since sensor turned on
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
|
var width = 24;
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setFont("6x8", 1);
|
g.setFont("6x8", 1);
|
||||||
g.setFontAlign(0, 0);
|
g.setFontAlign(0, 0);
|
||||||
g.clearRect(xpos,15,xpos+width,24); // erase background
|
g.clearRect(this.x,this.y+15,this.x+width,this.y+23); // erase background
|
||||||
var bpm = currentBPM, isCurrent = true;
|
var bpm = currentBPM, isCurrent = true;
|
||||||
if (bpm===undefined) {
|
if (bpm===undefined) {
|
||||||
bpm = lastBPM;
|
bpm = lastBPM;
|
||||||
|
|
@ -19,9 +17,9 @@
|
||||||
if (bpm===undefined)
|
if (bpm===undefined)
|
||||||
bpm = "--";
|
bpm = "--";
|
||||||
g.setColor(isCurrent ? "#ffffff" : "#808080");
|
g.setColor(isCurrent ? "#ffffff" : "#808080");
|
||||||
g.drawString(bpm, xpos+width/2, 19);
|
g.drawString(bpm, this.x+width/2, this.y+19);
|
||||||
g.setColor(isCurrent ? "#ff0033" : "#808080");
|
g.setColor(isCurrent ? "#ff0033" : "#808080");
|
||||||
g.drawImage(atob("CgoCAAABpaQ//9v//r//5//9L//A/+AC+AAFAA=="),xpos+(width-10)/2,1);
|
g.drawImage(atob("CgoCAAABpaQ//9v//r//5//9L//A/+AC+AAFAA=="),this.x+(width-10)/2,this.y+1);
|
||||||
g.setColor(-1);
|
g.setColor(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,5 +47,5 @@
|
||||||
Bangle.setHRMPower(Bangle.isLCDOn());
|
Bangle.setHRMPower(Bangle.isLCDOn());
|
||||||
|
|
||||||
// add your widget
|
// add your widget
|
||||||
WIDGETS["hrm"]={draw:draw};
|
WIDGETS["hrm"]={area:"tl",width:24,draw:draw};
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
0.01: New Widget!
|
0.01: New Widget!
|
||||||
|
0.02: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
/* jshint esversion: 6 */
|
/* jshint esversion: 6 */
|
||||||
(() => {
|
(() => {
|
||||||
var xpos = WIDGETPOS.tr - 16;
|
var id = NRF.getAddress().substr().substr(12).split(":");
|
||||||
WIDGETPOS.tr -= 16;
|
|
||||||
id = NRF.getAddress().split(":");
|
|
||||||
|
|
||||||
// draw your widget at xpos
|
// draw your widget at xpos
|
||||||
function draw() {
|
function draw() {
|
||||||
var x = xpos,
|
|
||||||
y = 0;
|
|
||||||
g.reset().setColor(0, 0.5, 1).setFont("6x8", 1);
|
g.reset().setColor(0, 0.5, 1).setFont("6x8", 1);
|
||||||
g.drawString(id[4], x, 0, true);
|
g.drawString(id[0], this.x+2, this.y+4, true);
|
||||||
g.drawString(id[5], x, 10, true);
|
g.drawString(id[1], this.x+2, this.y+14, true);
|
||||||
}
|
}
|
||||||
WIDGETS["widid"] = { draw: draw };
|
WIDGETS["widid"] = { area:"tr", width:16, draw: draw };
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
0.01: New Widget!
|
||||||
|
0.02: Tweaks for variable size widget system
|
||||||
|
|
@ -1,13 +1,5 @@
|
||||||
(function(){
|
WIDGETS["nceu"]={area:"tl",width:75,draw:function(){
|
||||||
var img = E.toArrayBuffer(atob("SxgCAAAAAAAAAAAAAAAAAAAAAAAAALwDwH/gD/0B//Af+AAD4C8f/wL8Dwf/8H//C//C//AAD9C8f/wL9Dw//+H//i4AD0AH8D/C8fAAL/Dz///H//y8ALgAf/D/i8fAALrzz///H//2//PAAv/Dz28f/gLz7z///H//29VPQAv/Dx+8fqQLw/y///H//y4ALwAP/Dwv8fAALwfw//9H//i+qD8FC0DwP8fAALwPwP/4H/+C//A//AADwD8fAAAAAAC/QD+gAAAAL4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGqooBkD+AP0fgvgAAAAAAAAAAL/88C4NBw0NBjQcAAAAAAAAAALQA8C4AAyQDBjAJAAAAAAAAAALQA8C4AAzACBjAKAAAAAAAAAAL/88C4ABTACRjQbAAAAAAAAAAL/48C4AHDACRgvjAAAAAAAAAALQA8C4AcDACBgACAAAAAAAAAALQA+D0BwCQDBgANAAAAAAAAAAL/8P/wHAA0NBgAoAAAAAAAAAAGqoC+AP/0HgAQuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
|
g.reset().setColor(0.17,0.2,0.5);
|
||||||
var xpos = WIDGETPOS.tl;
|
g.drawImage(atob("SxgCAAAAAAAAAAAAAAAAAAAAAAAAALwDwH/gD/0B//Af+AAD4C8f/wL8Dwf/8H//C//C//AAD9C8f/wL9Dw//+H//i4AD0AH8D/C8fAAL/Dz///H//y8ALgAf/D/i8fAALrzz///H//2//PAAv/Dz28f/gLz7z///H//29VPQAv/Dx+8fqQLw/y///H//y4ALwAP/Dwv8fAALwfw//9H//i+qD8FC0DwP8fAALwPwP/4H/+C//A//AADwD8fAAAAAAC/QD+gAAAAL4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGqooBkD+AP0fgvgAAAAAAAAAAL/88C4NBw0NBjQcAAAAAAAAAALQA8C4AAyQDBjAJAAAAAAAAAALQA8C4AAzACBjAKAAAAAAAAAAL/88C4ABTACRjQbAAAAAAAAAAL/48C4AHDACRgvjAAAAAAAAAALQA8C4AcDACBgACAAAAAAAAAALQA+D0BwCQDBgANAAAAAAAAAAL/8P/wHAA0NBgAoAAAAAAAAAAGqoC+AP/0HgAQuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),this.x,this.y);
|
||||||
WIDGETPOS.tl+=75;
|
|
||||||
|
|
||||||
|
|
||||||
WIDGETS["nceu"]={draw:()=>{
|
|
||||||
var x = xpos, y = 0;
|
|
||||||
g.setColor(0.17,0.2,0.5);
|
|
||||||
g.drawImage(img,x,y);
|
|
||||||
g.setColor(1,1,1);
|
g.setColor(1,1,1);
|
||||||
}};
|
}};
|
||||||
})()
|
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@
|
||||||
0.04: Fix pedometer reload when going back to clock app
|
0.04: Fix pedometer reload when going back to clock app
|
||||||
0.05: Add foot icon, use tidier font, and move to the left of the screen
|
0.05: Add foot icon, use tidier font, and move to the left of the screen
|
||||||
0.06: Fix widget position increment
|
0.06: Fix widget position increment
|
||||||
|
0.07: Tweaks for variable size widget system
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
(() => {
|
(() => {
|
||||||
const PEDOMFILE = "wpedom.json";
|
const PEDOMFILE = "wpedom.json";
|
||||||
// add the width
|
|
||||||
// WIDGETPOS.tr is originally 208 without any widgets
|
|
||||||
var xpos = WIDGETPOS.tl;
|
|
||||||
var width = 24;
|
|
||||||
WIDGETPOS.tl += (width + 2);
|
|
||||||
|
|
||||||
let lastUpdate = new Date();
|
let lastUpdate = new Date();
|
||||||
let stp_today = 0;
|
let stp_today = 0;
|
||||||
|
|
||||||
// draw your widget at xpos
|
// draw your widget
|
||||||
function draw() {
|
function draw() {
|
||||||
// Widget (0,0,239,23)
|
var width = 24;
|
||||||
if (stp_today > 99999){
|
if (stp_today > 99999){
|
||||||
stp_today = stp_today % 100000; // cap to five digits + comma = 6 characters
|
stp_today = stp_today % 100000; // cap to five digits + comma = 6 characters
|
||||||
}
|
}
|
||||||
|
|
@ -24,9 +18,9 @@
|
||||||
g.setFont("6x8", 1);
|
g.setFont("6x8", 1);
|
||||||
}
|
}
|
||||||
g.setFontAlign(0, 0); // align to x: center, y: center
|
g.setFontAlign(0, 0); // align to x: center, y: center
|
||||||
g.clearRect(xpos,15,xpos+width,24); // erase background
|
g.clearRect(this.x,this.y+15,this.x+width,this.y+23); // erase background
|
||||||
g.drawString(stps, xpos+width/2, 19);
|
g.drawString(stps, this.x+width/2, this.y+19);
|
||||||
g.drawImage(atob("CgoCLguH9f2/7+v6/79f56CtAAAD9fw/n8Hx9A=="),xpos+(width-10)/2,2);
|
g.drawImage(atob("CgoCLguH9f2/7+v6/79f56CtAAAD9fw/n8Hx9A=="),this.x+(width-10)/2,this.y+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bangle.on('step', (up) => {
|
Bangle.on('step', (up) => {
|
||||||
|
|
@ -55,7 +49,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
// add your widget
|
// add your widget
|
||||||
WIDGETS["wpedom"]={draw:draw};
|
WIDGETS["wpedom"]={area:"tl",width:26,draw:draw};
|
||||||
// Load data at startup
|
// Load data at startup
|
||||||
let pedomData = require("Storage").readJSON(PEDOMFILE,1);
|
let pedomData = require("Storage").readJSON(PEDOMFILE,1);
|
||||||
if (pedomData) {
|
if (pedomData) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue