mirror of https://github.com/espruino/BangleApps
Merge branch 'master' into icon-notifs
commit
e1481981da
|
@ -256,6 +256,7 @@ and which gives information about the app for the Launcher.
|
|||
// 'clock' - a clock - required for clocks to automatically start
|
||||
// 'widget' - a widget
|
||||
// 'bootloader' - an app that at startup (app.boot.js) but doesn't have a launcher entry for 'app.js'
|
||||
// 'settings' - apps that appear in Settings->Apps (with appname.settings.js) but that have no 'app.js'
|
||||
// 'RAM' - code that runs and doesn't upload anything to storage
|
||||
// 'launch' - replacement 'Launcher'
|
||||
// 'textinput' - provides a 'textinput' library that allows text to be input on the Bangle
|
||||
|
|
|
@ -28,3 +28,4 @@
|
|||
0.26: Add support for Monday as first day of the week (#1780)
|
||||
0.27: New UI!
|
||||
0.28: Fix bug with alarms not firing when configured to fire only once
|
||||
0.29: Fix wrong 'dow' handling in new timer if first day of week is Monday
|
||||
|
|
|
@ -37,8 +37,8 @@ function handleFirstDayOfWeek(dow) {
|
|||
return dow;
|
||||
}
|
||||
|
||||
// Check the first day of week and update the dow field accordingly.
|
||||
alarms.forEach(alarm => alarm.dow = handleFirstDayOfWeek(alarm.dow));
|
||||
// Check the first day of week and update the dow field accordingly (alarms only!)
|
||||
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
||||
|
||||
function showMainMenu() {
|
||||
const menu = {
|
||||
|
@ -158,14 +158,14 @@ function saveAlarm(alarm, alarmIndex, time) {
|
|||
}
|
||||
|
||||
function saveAndReload() {
|
||||
// Before saving revert the dow to the standard format
|
||||
alarms.forEach(a => a.dow = handleFirstDayOfWeek(a.dow, firstDayOfWeek));
|
||||
// Before saving revert the dow to the standard format (alarms only!)
|
||||
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
||||
|
||||
require("sched").setAlarms(alarms);
|
||||
require("sched").reload();
|
||||
|
||||
// Fix after save
|
||||
alarms.forEach(a => a.dow = handleFirstDayOfWeek(a.dow, firstDayOfWeek));
|
||||
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
||||
}
|
||||
|
||||
function decodeDOW(alarm) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "alarm",
|
||||
"name": "Alarms & Timers",
|
||||
"shortName": "Alarms",
|
||||
"version": "0.28",
|
||||
"version": "0.29",
|
||||
"description": "Set alarms and timers on your Bangle",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,alarm,widget",
|
||||
|
|
|
@ -11,6 +11,8 @@ const speedUnits = { // how many kph per X?
|
|||
"kmh": 1,
|
||||
"kph": 1,
|
||||
"km/h": 1,
|
||||
"kmt": 1,
|
||||
"km/tim": 1,
|
||||
"mph": 1.60934,
|
||||
"kts": 1.852
|
||||
};
|
||||
|
|
|
@ -67,13 +67,6 @@ function saveMessages() {
|
|||
require("Storage").writeJSON("messages.json",MESSAGES)
|
||||
}
|
||||
|
||||
function getPosImage() {
|
||||
return atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA==");
|
||||
}
|
||||
function getNegImage() {
|
||||
return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA=");
|
||||
}
|
||||
|
||||
function showMapMessage(msg) {
|
||||
active = "map";
|
||||
var m;
|
||||
|
@ -300,7 +293,7 @@ function showMessage(msgid) {
|
|||
var buttons = [
|
||||
];
|
||||
if (msg.positive) {
|
||||
buttons.push({type:"btn", src:getPosImage(), cb:()=>{
|
||||
buttons.push({type:"btn", src:atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA=="), cb:()=>{
|
||||
msg.new = false; saveMessages();
|
||||
cancelReloadTimeout(); // don't auto-reload to clock now
|
||||
Bangle.messageResponse(msg,true);
|
||||
|
@ -309,7 +302,7 @@ function showMessage(msgid) {
|
|||
}
|
||||
if (msg.negative) {
|
||||
if (buttons.length) buttons.push({width:32}); // nasty hack...
|
||||
buttons.push({type:"btn", src:getNegImage(), cb:()=>{
|
||||
buttons.push({type:"btn", src:atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA="), cb:()=>{
|
||||
msg.new = false; saveMessages();
|
||||
cancelReloadTimeout(); // don't auto-reload to clock now
|
||||
Bangle.messageResponse(msg,false);
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
0.04: Fixed issue selecting Frankfurt not saved
|
||||
0.05: Fixed issue with back option
|
||||
0.06: renamed source files to match standard
|
||||
0.07: Move mylocation app into 'Settings -> Apps'
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
*Sets and stores GPS lat and lon of your preferred city*
|
||||
|
||||
To access, go to `Settings -> Apps -> My Location`
|
||||
|
||||
* Select one of the preset Cities or setup through the GPS
|
||||
* Other Apps can read this information to do calculations based on location
|
||||
* When the City shows ??? it means the location has been set through the GPS
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
require("heatshrink").decompress(atob("mEw4UA///gH4AYPO/QPDgNVqtADY/1BYNfBQ0PBQIAB+ALFmoLDrgLF6oLDq4KEgYKDBYPABYcNBYlVuAuIGAwuEAANUBYYKFHgg6Bq4ZCr4DBHgQLBvWq2te1WlBYZGBBYOr1Wq1qSDBYNqBIILDKgQLLgoLHqBqDBfJHLBZBrOgKPCBYiPCU4NaBYe1WYrABBQLCCfgYGCrwVBa4kAirvKNgIAErgLDKgIAEKQQ8EAAY6DBZhIDIww8GHQg8GHQgwGFwowEFwx5EOog8GHQ0AlWpBYNq1AKFWIILBAYOgBYbICytWAgQKCgTgDcwYXGAAgvGAAY8EEgYWGBgoVEA=="))
|
|
@ -2,16 +2,15 @@
|
|||
"name": "My Location",
|
||||
"shortName":"My Location",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
"type": "settings",
|
||||
"screenshots": [{"url":"screenshot_1.png"}],
|
||||
"version":"0.06",
|
||||
"version":"0.07",
|
||||
"description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README",
|
||||
"readme": "README.md",
|
||||
"tags": "tool,utility",
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"mylocation.app.js","url":"app.js"},
|
||||
{"name":"mylocation.img","url":"icon.js","evaluate": true }
|
||||
{"name":"mylocation.settings.js","url":"settings.js"}
|
||||
],
|
||||
"data": [
|
||||
{"name":"mylocation.json"}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
(function(back) {
|
||||
|
||||
const SETTINGS_FILE = "mylocation.json";
|
||||
let settings;
|
||||
|
@ -18,7 +17,7 @@ function loadSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
function save() {
|
||||
function saveSettings() {
|
||||
settings = s;
|
||||
require('Storage').write(SETTINGS_FILE, settings);
|
||||
}
|
||||
|
@ -34,29 +33,29 @@ function setFromGPS() {
|
|||
//console.log("fix from GPS");
|
||||
s = {'lat': gps.lat, 'lon': gps.lon, 'location': '???' };
|
||||
Bangle.buzz(1500); // buzz on first position
|
||||
Bangle.setGPSPower(0);
|
||||
save();
|
||||
Bangle.setGPSPower(0, "mylocation");
|
||||
saveSettings();
|
||||
|
||||
Bangle.setUI("updown", ()=>{ load(); });
|
||||
E.showPrompt("Location has been saved from the GPS fix",{
|
||||
title:"Location Saved",
|
||||
buttons : {"OK":1}
|
||||
E.showPrompt(/*LANG*/"Location has been saved from the GPS fix",{
|
||||
title:/*LANG*/"Location Saved",
|
||||
buttons : {/*LANG*/"OK":1}
|
||||
}).then(function(v) {
|
||||
load(); // load default clock
|
||||
});
|
||||
});
|
||||
|
||||
Bangle.setGPSPower(1);
|
||||
E.showMessage("Waiting for GPS fix. Place watch in the open. Could take 10 minutes. Long press to abort", "GPS Running");
|
||||
Bangle.setGPSPower(1, "mylocation");
|
||||
E.showMessage(/*LANG*/"Waiting for GPS fix. Place watch in the open. Could take 10 minutes. Long press to abort", "GPS Running");
|
||||
Bangle.setUI("updown", undefined);
|
||||
}
|
||||
|
||||
function showMainMenu() {
|
||||
//console.log("showMainMenu");
|
||||
const mainmenu = {
|
||||
'': { 'title': 'My Location' },
|
||||
'< Back': ()=>{ load(); },
|
||||
'City': {
|
||||
'': { 'title': /*LANG*/'My Location' },
|
||||
'< Back': ()=>{ back(); },
|
||||
/*LANG*/'City': {
|
||||
value: 0 | locations.indexOf(s.location),
|
||||
min: 0, max: locations.length - 1,
|
||||
format: v => locations[v],
|
||||
|
@ -65,14 +64,15 @@ function showMainMenu() {
|
|||
s.location = locations[v];
|
||||
s.lat = lats[v];
|
||||
s.lon = lons[v];
|
||||
save();
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
},
|
||||
'Set From GPS': ()=>{ setFromGPS(); }
|
||||
/*LANG*/'Set From GPS': ()=>{ setFromGPS(); }
|
||||
};
|
||||
return E.showMenu(mainmenu);
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
showMainMenu();
|
||||
})
|
|
@ -4,6 +4,7 @@
|
|||
"version":"0.01",
|
||||
"description": "A clock with R2D2's shiny metal face on it. :)",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"icon": "rndmclk.png",
|
||||
"type": "widget",
|
||||
"tags": "widget,clock",
|
||||
"supports": ["BANGLEJS"],
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"rndmclk.wid.js","url":"widget.js"}
|
||||
|
|
|
@ -49,3 +49,4 @@
|
|||
0.44: Add "Start Week On X" option (#1780)
|
||||
UI improvements to Locale and Date & Time menu
|
||||
0.45: Add calibrate battery option
|
||||
0.46: Fix regression after making 'calibrate battery' only for Bangle.js 2
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "setting",
|
||||
"name": "Settings",
|
||||
"version": "0.45",
|
||||
"version": "0.46",
|
||||
"description": "A menu for setting up Bangle.js",
|
||||
"icon": "settings.png",
|
||||
"tags": "tool,system",
|
||||
|
|
|
@ -545,8 +545,10 @@ function showUtilMenu() {
|
|||
setInterval(function() {
|
||||
var i=1000;while (i--);
|
||||
}, 1);
|
||||
},
|
||||
/*LANG*/'Calibrate Battery': () => {
|
||||
}
|
||||
};
|
||||
if (BANGLEJS2)
|
||||
menu[/*LANG*/'Calibrate Battery'] = () => {
|
||||
E.showPrompt(/*LANG*/"Is the battery fully charged?",{title:/*LANG*/"Calibrate"}).then(ok => {
|
||||
if (ok) {
|
||||
var s=require("Storage").readJSON("setting.json");
|
||||
|
@ -557,8 +559,8 @@ function showUtilMenu() {
|
|||
E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("settings.app.js"));
|
||||
}
|
||||
});
|
||||
},
|
||||
/*LANG*/'Reset Settings': () => {
|
||||
};
|
||||
menu[/*LANG*/'Reset Settings'] = () => {
|
||||
E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings"}).then((v) => {
|
||||
if (v) {
|
||||
E.showMessage('Resetting');
|
||||
|
@ -566,9 +568,9 @@ function showUtilMenu() {
|
|||
setTimeout(showMainMenu, 50);
|
||||
} else showUtilMenu();
|
||||
});
|
||||
},
|
||||
/*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() }
|
||||
};
|
||||
};
|
||||
menu[/*LANG*/'Turn Off'] = ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() };
|
||||
|
||||
if (Bangle.factoryReset) {
|
||||
menu[/*LANG*/'Factory Reset'] = ()=>{
|
||||
E.showPrompt(/*LANG*/'This will remove everything!',{title:/*LANG*/"Factory Reset"}).then((v) => {
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
0.03: Add Banglejs 1 compatibility
|
||||
0.04: Fix settings bug
|
||||
0.05: Add altitude display (only Bangle.js 2)
|
||||
0.06: Add power related settings to control the HR and pressure(altitude) sensor from the watchface
|
||||
|
|
|
@ -8,3 +8,8 @@ It can display :
|
|||
- hrm
|
||||
- motion
|
||||
- steps
|
||||
|
||||
|
||||
"Power saving" setting control the HR and pressure (altitude) sensors.
|
||||
If "Off" they will always be on.
|
||||
If "On" the sensors will be turned on every "Power on interval" minutes for 45 secondes
|
||||
|
|
|
@ -3,15 +3,14 @@ var fontColor = g.theme.dark ? "#0f0" : "#000";
|
|||
var heartRate = 0;
|
||||
var altitude = -9001;
|
||||
|
||||
// handling the differents versions of the Banglejs smartwatch
|
||||
// handling the differents versions of the Banglejs smartwatch screen sizes
|
||||
if (process.env.HWVERSION == 1){
|
||||
var paddingY = 3;
|
||||
var font6x8At4Size = 48;
|
||||
var font6x8At2Size = 27;
|
||||
var font6x8FirstTextSize = 6;
|
||||
var font6x8DefaultTextSize = 3;
|
||||
}
|
||||
else{
|
||||
} else{
|
||||
var paddingY = 2;
|
||||
var font6x8At4Size = 32;
|
||||
var font6x8At2Size = 18;
|
||||
|
@ -66,7 +65,7 @@ function drawDate(now, pos){
|
|||
drawLine(locale_date, pos);
|
||||
}
|
||||
|
||||
function drawInput(now, pos){
|
||||
function drawInput(pos){
|
||||
clearField(pos);
|
||||
drawLine(">", pos);
|
||||
}
|
||||
|
@ -129,16 +128,52 @@ function draw(){
|
|||
drawStepCount(curPos);
|
||||
curPos++;
|
||||
}
|
||||
drawInput(now, curPos);
|
||||
drawInput(curPos);
|
||||
}
|
||||
|
||||
function turnOnServices(){
|
||||
if(settings.showHRM){
|
||||
Bangle.setHRMPower(true, "terminalclock");
|
||||
}
|
||||
if(settings.showAltitude && process.env.HWVERSION != 1){
|
||||
Bangle.setBarometerPower(true, "terminalclock");
|
||||
}
|
||||
if(settings.powerSaving){
|
||||
setTimeout(function () {
|
||||
turnOffServices();
|
||||
}, 45000);
|
||||
}
|
||||
}
|
||||
|
||||
function turnOffServices(){
|
||||
if(settings.showHRM){
|
||||
Bangle.setHRMPower(false, "terminalclock");
|
||||
}
|
||||
if(settings.showAltitude && process.env.HWVERSION != 1){
|
||||
Bangle.setBarometerPower(false, "terminalclock");
|
||||
}
|
||||
}
|
||||
|
||||
var unlockDrawIntervalID = -1;
|
||||
Bangle.on('lock', function(on){
|
||||
if(!on){ // unclock
|
||||
if(settings.powerSaving){
|
||||
turnOnServices();
|
||||
}
|
||||
unlockDrawIntervalID = setInterval(draw, 1000); // every second
|
||||
}
|
||||
if(on && unlockDrawIntervalID != -1){ // lock
|
||||
clearInterval(unlockDrawIntervalID);
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.on('HRM',function(hrmInfo) {
|
||||
if(hrmInfo.confidence >= settings.HRMinConfidence)
|
||||
heartRate = hrmInfo.bpm;
|
||||
});
|
||||
|
||||
var MEDIANLENGTH = 20;
|
||||
var avr = [], median;
|
||||
var MEDIANLENGTH = 20; // technical
|
||||
var avr = [], median; // technical
|
||||
Bangle.on('pressure', function(e) {
|
||||
while (avr.length>MEDIANLENGTH) avr.pop();
|
||||
avr.unshift(e.altitude);
|
||||
|
@ -161,18 +196,20 @@ var settings = Object.assign({
|
|||
showActivity: true,
|
||||
showStepCount: true,
|
||||
showAltitude: process.env.HWVERSION != 1 ? true : false,
|
||||
powerSaving: true,
|
||||
PowerOnInterval: 15,
|
||||
}, require('Storage').readJSON("terminalclock.json", true) || {});
|
||||
|
||||
if(settings.showAltitude && process.env.HWVERSION != 1){
|
||||
Bangle.setBarometerPower(true, "app");
|
||||
// turn the services before drawing anything
|
||||
turnOnServices();
|
||||
if(settings.powerSaving){
|
||||
setInterval(turnOnServices, settings.PowerOnInterval*60000); // every PowerOnInterval min
|
||||
}
|
||||
|
||||
// Show launcher when middle button pressed
|
||||
Bangle.setUI("clock");
|
||||
// Load widgets
|
||||
// Load and draw widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
// draw immediately at first
|
||||
draw();
|
||||
|
||||
var secondInterval = setInterval(draw, 10000);
|
||||
setInterval(draw, 10000); // every 10 seconds
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Terminal Clock",
|
||||
"shortName":"Terminal Clock",
|
||||
"description": "A terminal cli like clock displaying multiple sensor data",
|
||||
"version":"0.05",
|
||||
"version":"0.06",
|
||||
"icon": "app.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
showHRM: true,
|
||||
showActivity: true,
|
||||
showStepCount: true,
|
||||
powerSaving: true,
|
||||
PowerOnInterval: 15,
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
|
@ -65,10 +67,29 @@
|
|||
settings.showStepCount = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Power saving': {
|
||||
value: settings.powerSaving,
|
||||
format: v => v?"On":"Off",
|
||||
onchange: v => {
|
||||
settings.powerSaving = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Power on interval': {
|
||||
value: settings.PowerOnInterval,
|
||||
min: 3, max: 60,
|
||||
onchange: v => {
|
||||
settings.PowerOnInterval = v;
|
||||
writeSettings();
|
||||
},
|
||||
format: x => {
|
||||
return x + " min";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (process.env.HWVERSION == 1) {
|
||||
delete menu['Show Altitude']
|
||||
}
|
||||
E.showMenu(menu);
|
||||
})
|
||||
})
|
|
@ -65,7 +65,7 @@ const APP_KEYS = [
|
|||
const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports'];
|
||||
const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate'];
|
||||
const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports'
|
||||
const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","textinput","scheduler","notify","locale"]; // values allowed for "type" field
|
||||
const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","textinput","scheduler","notify","locale","settings"]; // values allowed for "type" field
|
||||
const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info
|
||||
const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ];
|
||||
const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"];
|
||||
|
@ -140,7 +140,7 @@ apps.forEach((app,appIdx) => {
|
|||
ERROR(`App ${app.id} 'dependencies' must all be tagged 'type' or 'app' right now`);
|
||||
if (app.dependencies[dependency]=="type" && !METADATA_TYPES.includes(dependency))
|
||||
ERROR(`App ${app.id} 'type' dependency must be one of `+METADATA_TYPES);
|
||||
|
||||
|
||||
});
|
||||
} else
|
||||
ERROR(`App ${app.id} 'dependencies' must be an object`);
|
||||
|
|
2
core
2
core
|
@ -1 +1 @@
|
|||
Subproject commit 404e981834f2e8df9c505a8fab12ae12fe3bd562
|
||||
Subproject commit 2054537a9958f9812ae2cad908b6597ff01e449d
|
|
@ -1,74 +1,6 @@
|
|||
/* Copyright (c) 2022 Bangle.js contributors. See the file LICENSE for copying permission. */
|
||||
/*
|
||||
Take a look at README.md for hints on developing with this library.
|
||||
Usage:
|
||||
```
|
||||
var Layout = require("Layout");
|
||||
var layout = new Layout( layoutObject, options )
|
||||
layout.render(optionalObject);
|
||||
```
|
||||
For example:
|
||||
```
|
||||
var Layout = require("Layout");
|
||||
var layout = new Layout( {
|
||||
type:"v", c: [
|
||||
{type:"txt", font:"20%", label:"12:00" },
|
||||
{type:"txt", font:"6x8", label:"The Date" }
|
||||
]
|
||||
});
|
||||
g.clear();
|
||||
layout.render();
|
||||
```
|
||||
layoutObject has:
|
||||
* A `type` field of:
|
||||
* `undefined` - blank, can be used for padding
|
||||
* `"txt"` - a text label, with value `label`. 'font' is required
|
||||
* `"btn"` - a button, with value `label` and callback `cb`
|
||||
optional `src` specifies an image (like img) in which case label is ignored
|
||||
Default font is `6x8`, scale 2. This can be overridden with the `font` or `scale` fields.
|
||||
* `"img"` - an image where `src` is an image, or a function which is called to return an image to draw.
|
||||
* `"custom"` - a custom block where `render(layoutObj)` is called to render
|
||||
* `"h"` - Horizontal layout, `c` is an array of more `layoutObject`
|
||||
* `"v"` - Vertical layout, `c` is an array of more `layoutObject`
|
||||
* A `id` field. If specified the object is added with this name to the
|
||||
returned `layout` object, so can be referenced as `layout.foo`
|
||||
* A `font` field, eg `6x8` or `30%` to use a percentage of screen height. Set scale with :, e.g. `6x8:2`.
|
||||
* A `scale` field, eg `2` to set scale of an image
|
||||
* A `r` field to set rotation of text or images (0: 0°, 1: 90°, 2: 180°, 3: 270°).
|
||||
* A `wrap` field to enable line wrapping. Requires some combination of `width`/`height`
|
||||
and `fillx`/`filly` to be set. Not compatible with text rotation.
|
||||
* A `col` field, eg `#f00` for red
|
||||
* A `bgCol` field for background color (will automatically fill on render)
|
||||
* A `halign` field to set horizontal alignment WITHIN a `v` container. `-1`=left, `1`=right, `0`=center
|
||||
* A `valign` field to set vertical alignment WITHIN a `h` container. `-1`=top, `1`=bottom, `0`=center
|
||||
* A `pad` integer field to set pixels padding
|
||||
* A `fillx` int to choose if the object should fill available space in x. 0=no, 1=yes, 2=2x more space
|
||||
* A `filly` int to choose if the object should fill available space in y. 0=no, 1=yes, 2=2x more space
|
||||
* `width` and `height` fields to optionally specify minimum size
|
||||
options is an object containing:
|
||||
* `lazy` - a boolean specifying whether to enable automatic lazy rendering
|
||||
* `btns` - array of objects containing:
|
||||
* `label` - the text on the button
|
||||
* `cb` - a callback function
|
||||
* `cbl` - a callback function for long presses
|
||||
* `back` - a callback function, passed as `back` into Bangle.setUI (which usually adds an icon in the top left)
|
||||
|
||||
If automatic lazy rendering is enabled, calls to `layout.render()` will attempt to automatically
|
||||
determine what objects have changed or moved, clear their previous locations, and re-render just those objects.
|
||||
Once `layout.update()` is called, the following fields are added
|
||||
to each object:
|
||||
* `x` and `y` for the top left position
|
||||
* `w` and `h` for the width and height
|
||||
* `_w` and `_h` for the **minimum** width and height
|
||||
Other functions:
|
||||
* `layout.update()` - update positions of everything if contents have changed
|
||||
* `layout.debug(obj)` - draw outlines for objects on screen
|
||||
* `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render)
|
||||
* `layout.forgetLazyState()` - if lazy rendering is enabled, makes the next call to `render()` perform a full re-render
|
||||
* `layout.setUI()` - (called when module initialised) This sets up input (buttons, touch, etc) with Bangle._setUI
|
||||
This can be useful if you called E.showMenu/showPrompt/etc and those grabbed input away from layour
|
||||
*/
|
||||
|
||||
// See Layout.md for documentation
|
||||
|
||||
function Layout(layout, options) {
|
||||
this._l = this.l = layout;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
Bangle.js Layout Library
|
||||
========================
|
||||
|
||||
> Take a look at README.md for hints on developing with this library.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```JS
|
||||
var Layout = require("Layout");
|
||||
var layout = new Layout(layoutObject, options)
|
||||
|
||||
layout.render(optionalObject);
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```JS
|
||||
var Layout = require("Layout");
|
||||
var layout = new Layout({
|
||||
type:"v",
|
||||
c: [
|
||||
{ type: "txt", font: "20%", label: "12:00" },
|
||||
{ type: "txt", font: "6x8", label: "The Date" }
|
||||
]
|
||||
});
|
||||
|
||||
g.clear();
|
||||
|
||||
layout.render();
|
||||
```
|
||||
|
||||
`layoutObject` has:
|
||||
|
||||
- A `type` field of:
|
||||
- `undefined` - blank, can be used for padding
|
||||
- `"txt"` - a text label, with value `label`. `font` is required
|
||||
- `"btn"` - a button, with value `label` and callback `cb`. Optional `src` specifies an image (like img) in which case label is ignored. Default font is `6x8`, scale 2. This can be overridden with the `font` or `scale` fields.
|
||||
- `"img"` - an image where `src` is an image, or a function which is called to return an image to draw
|
||||
- `"custom"` - a custom block where `render(layoutObj)` is called to render
|
||||
- `"h"` - Horizontal layout, `c` is an array of more `layoutObject`
|
||||
- `"v"` - Vertical layout, `c` is an array of more `layoutObject`
|
||||
- A `id` field. If specified the object is added with this name to the returned `layout` object, so can be referenced as `layout.foo`
|
||||
- A `font` field, eg `6x8` or `30%` to use a percentage of screen height. Set scale with :, e.g. `6x8:2`.
|
||||
- A `scale` field, eg `2` to set scale of an image
|
||||
- A `r` field to set rotation of text or images (0: 0°, 1: 90°, 2: 180°, 3: 270°).
|
||||
- A `wrap` field to enable line wrapping. Requires some combination of `width`/`height` and `fillx`/`filly` to be set. Not compatible with text rotation.
|
||||
- A `col` field, eg `#f00` for red
|
||||
- A `bgCol` field for background color (will automatically fill on render)
|
||||
- A `halign` field to set horizontal alignment WITHIN a `v` container. `-1`=left, `1`=right, `0`=center
|
||||
- A `valign` field to set vertical alignment WITHIN a `h` container. `-1`=top, `1`=bottom, `0`=center
|
||||
- A `pad` integer field to set pixels padding
|
||||
- A `fillx` int to choose if the object should fill available space in x. 0=no, 1=yes, 2=2x more space
|
||||
- A `filly` int to choose if the object should fill available space in y. 0=no, 1=yes, 2=2x more space
|
||||
- `width` and `height` fields to optionally specify minimum size options is an object containing:
|
||||
- `lazy` - a boolean specifying whether to enable automatic lazy rendering
|
||||
- `btns` - array of objects containing:
|
||||
- `label` - the text on the button
|
||||
- `cb` - a callback function
|
||||
- `cbl` - a callback function for long presses
|
||||
- `back` - a callback function, passed as `back` into Bangle.setUI (which usually adds an icon in the top left)
|
||||
|
||||
If automatic lazy rendering is enabled, calls to `layout.render()` will attempt to automatically determine what objects have changed or moved, clear their previous locations, and re-render just those objects.
|
||||
|
||||
Once `layout.update()` is called, the following fields are added to each object:
|
||||
|
||||
- `x` and `y` for the top left position
|
||||
- `w` and `h` for the width and height
|
||||
- `_w` and `_h` for the **minimum** width and height
|
||||
|
||||
Other functions:
|
||||
|
||||
- `layout.update()` - update positions of everything if contents have changed
|
||||
- `layout.debug(obj)` - draw outlines for objects on screen
|
||||
- `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render)
|
||||
- `layout.forgetLazyState()` - if lazy rendering is enabled, makes the next call to `render()` perform a full re-render
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- [Official tutorial](https://www.espruino.com/Bangle.js+Layout)
|
Loading…
Reference in New Issue