From 0ab04e422dea9d41b270ccacf3dda351f9eebfc3 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 1 Dec 2024 15:13:21 -0500 Subject: [PATCH 01/25] clock_info: Expose internal blur function as force_blur ...so an external action like hiding widgets with widclkinfo can unfocus the clock info. This always decrements Bangle.CLKINFO_FOCUS, so in the future we should only call force_blur if we know the Clock Info is focused. We could provide a different function ensure_blur. --- apps/clock_info/lib.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index 0550692477..3e5393cf4d 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -326,12 +326,15 @@ exports.addInteractive = function(menu, options) { const blur = () => { options.focus=false; Bangle.CLKINFO_FOCUS--; + // if (Bangle.CLKINFO_FOCUS < 0) Bangle.CLKINFO_FOCUS = 0; const itm = menu[options.menuA].items[options.menuB]; let redraw = true; if (itm.blur && itm.blur(options) === false) redraw = false; if (redraw) options.redraw(); }; + // better to only call blur when we know it's focused. Maybe we can rename force_blur to ensure_blur. + options.force_blur = blur; const focus = () => { let redraw = true; Bangle.CLKINFO_FOCUS = (0 | Bangle.CLKINFO_FOCUS) + 1; From e86fca804e7f29e30b4d291088e8fcf1eb72e7cb Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 1 Dec 2024 15:13:42 -0500 Subject: [PATCH 02/25] widget_utils: Add shown and hidden events This can help widgets, such as widclkinfo, know when they are on screen. --- modules/widget_utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 376c2ceba1..3d69bd9809 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -134,9 +134,11 @@ exports.swipeOn = function(autohide) { if (dir>0 && exports.offset>=0) { // fully down stop = true; exports.offset = 0; + exports.emit("shown"); } else if (dir<0 && exports.offset<-23) { // fully up stop = true; exports.offset = -24; + exports.emit("hidden"); } if (stop) { clearInterval(exports.animInterval); From e9850560b2cc502d1bad84e476a49bc4e2b5538e Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 1 Dec 2024 15:14:25 -0500 Subject: [PATCH 03/25] widclkinfo: work in progress: Be aware of widget_utils.swipeOn TODO: disable these changes when widget_utils are not being used. Use new (prototype) widget_utils events to blur and set offscreen the clock info when the widgets are hidden. This prevents activating or further interacting with the widclkinfo. --- apps/widclkinfo/widget.js | 49 ++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index d51f0563fb..ff0d233e7c 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -1,20 +1,30 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was already loaded // Load the clock infos - let clockInfoItems = require("clock_info").load(); - // Add the - let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { - app : "widclkinfo", + let clockInfoItems = clock_info.load(); + + // TODO only do checks if widget_utils.swipeOn is being used + let wuo = widget_utils.offset; + + let clockInfoMenu = clock_info.addInteractive(clockInfoItems, { + app: "widclkinfo", // Add the dimensions we're rendering to here - these are used to detect taps on the clock info area - x : 0, y: 0, w: 72, h:24, + x: 0, + y: 0, // maybe set offset to initial offset + w: 72, + h: 24, // You can add other information here you want to be passed into 'options' in 'draw' // This function draws the info - draw : (itm, info, options) => { + draw: (itm, info, options) => { // itm: the item containing name/hasRange/etc // info: data returned from itm.get() containing text/img/etc // options: options passed into addInteractive clockInfoInfo = info; - if (WIDGETS["clkinfo"]) + wuo = 0 | widget_utils.offset; + clockInfoMenu.y = options.y + wuo; + if (WIDGETS["clkinfo"]) { WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + console.log("Clock Info was updated, thus drawing widget."); + } } }); let clockInfoInfo; // when clockInfoMenu.draw is called we set this up @@ -25,12 +35,12 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread width: clockInfoMenu.w, draw:function(e) { clockInfoMenu.x = e.x; - clockInfoMenu.y = e.y; + wuo = 0 | widget_utils.offset; + clockInfoMenu.y = e.y + wuo; var o = clockInfoMenu; // Clear the background g.reset(); - // indicate focus - make background reddish - //if (clockInfoMenu.focus) g.setBgColor(g.blendColor(g.theme.bg, "#f00", 0.25)); + // indicate focus if (clockInfoMenu.focus) g.setColor("#f00"); g.clearRect(o.x, o.y, o.x+o.w-1, o.y+o.h-1); if (clockInfoInfo) { @@ -47,4 +57,21 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread } } }; -} \ No newline at end of file + + widget_utils.on("hidden", () => { + console.log("hidden"); + clockInfoMenu.y = -24; + clockInfoMenu.force_blur(); // needs to be here so it doesn't stay the focused color + if (clockInfoMenu.focus) { + //clockInfoMenu.force_blur(); + console.log("Forced blur bc hidden"); + } + }); + + widget_utils.on("shown", () => { + clockInfoMenu.y = 0; + console.log("shown"); + if (WIDGETS["clkinfo"]) { + WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + } + }); From 413b33f769058156500d516a6b92658a091d1c62 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 1 Dec 2024 18:47:03 -0500 Subject: [PATCH 04/25] Suggestions from review: emit events from Bangle and moving force_blur calls --- apps/widclkinfo/widget.js | 3 +-- modules/widget_utils.js | 15 +++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index ff0d233e7c..7771617c48 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -61,9 +61,8 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread widget_utils.on("hidden", () => { console.log("hidden"); clockInfoMenu.y = -24; - clockInfoMenu.force_blur(); // needs to be here so it doesn't stay the focused color if (clockInfoMenu.focus) { - //clockInfoMenu.force_blur(); + clockInfoMenu.force_blur(); console.log("Forced blur bc hidden"); } }); diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 3d69bd9809..bedb357978 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -11,6 +11,7 @@ exports.hide = function() { w.area = ""; if (w.x!=undefined) g.clearRect(w.x,w.y,w.x+w.width-1,w.y+23); } + // TODO: do we need to emit event here too? }; /// Show any hidden widgets @@ -134,11 +135,11 @@ exports.swipeOn = function(autohide) { if (dir>0 && exports.offset>=0) { // fully down stop = true; exports.offset = 0; - exports.emit("shown"); + Bangle.emit("widgets-shown"); } else if (dir<0 && exports.offset<-23) { // fully up stop = true; exports.offset = -24; - exports.emit("hidden"); + Bangle.emit("widgets-hidden"); } if (stop) { clearInterval(exports.animInterval); @@ -160,8 +161,14 @@ exports.swipeOn = function(autohide) { anim(-4); }, exports.autohide); }; - if (ud>0 && exports.offset<0) anim(4, cb); - if (ud<0 && exports.offset>-24) anim(-4); + if (ud>0 && exports.offset<0) { + Bangle.emit("widgets-start-show"); + anim(4, cb); + } + if (ud<0 && exports.offset>-24) { + Bangle.emit("widgets-start-hide"); + anim(-4); + } }; Bangle.on("swipe", exports.swipeHandler); Bangle.drawWidgets(); From 9bd9344da823464fc113972025b4c07f47dc1a92 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 1 Dec 2024 23:23:49 -0500 Subject: [PATCH 05/25] Also emit event when autohiding --- modules/widget_utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index bedb357978..811788f64e 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -158,6 +158,7 @@ exports.swipeOn = function(autohide) { let cb; if (exports.autohide > 0) cb = function() { exports.hideTimeout = setTimeout(function() { + Bangle.emit("widgets-start-hide"); anim(-4); }, exports.autohide); }; From b5ffb5abe2fae8d315fa54428dc674ad9cbc23ae Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 1 Dec 2024 23:37:12 -0500 Subject: [PATCH 06/25] Listen for widget events from Bangle --- apps/widclkinfo/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 7771617c48..0d025d21ed 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -58,7 +58,7 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread } }; - widget_utils.on("hidden", () => { + Bangle.on("hidden", () => { console.log("hidden"); clockInfoMenu.y = -24; if (clockInfoMenu.focus) { @@ -67,7 +67,7 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread } }); - widget_utils.on("shown", () => { + Bangle.on("shown", () => { clockInfoMenu.y = 0; console.log("shown"); if (WIDGETS["clkinfo"]) { From 3a0de9045dfae12e87bc61efaad6cc07cc3fe02e Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Fri, 13 Dec 2024 00:18:32 -0500 Subject: [PATCH 07/25] widget_utils: Emit shown and hidden events on show and hide functions --- modules/widget_utils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 811788f64e..250cd3d34b 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -11,7 +11,7 @@ exports.hide = function() { w.area = ""; if (w.x!=undefined) g.clearRect(w.x,w.y,w.x+w.width-1,w.y+23); } - // TODO: do we need to emit event here too? + Bangle.emit("widgets-hidden"); }; /// Show any hidden widgets @@ -26,6 +26,7 @@ exports.show = function() { delete w._area; w.draw(w); } + Bangle.emit("widgets-shown"); }; /// Remove anything not needed if the overlay was removed From 40059b7715076ddc5275da94a85d65ace1e963b5 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Fri, 13 Dec 2024 00:20:22 -0500 Subject: [PATCH 08/25] widclkinfo: Remove references to widget_utils --- apps/widclkinfo/widget.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 0d025d21ed..25323a3d84 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -2,9 +2,6 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread // Load the clock infos let clockInfoItems = clock_info.load(); - // TODO only do checks if widget_utils.swipeOn is being used - let wuo = widget_utils.offset; - let clockInfoMenu = clock_info.addInteractive(clockInfoItems, { app: "widclkinfo", // Add the dimensions we're rendering to here - these are used to detect taps on the clock info area @@ -19,9 +16,8 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread // info: data returned from itm.get() containing text/img/etc // options: options passed into addInteractive clockInfoInfo = info; - wuo = 0 | widget_utils.offset; - clockInfoMenu.y = options.y + wuo; if (WIDGETS["clkinfo"]) { + clockInfoMenu.y = options.y; WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); console.log("Clock Info was updated, thus drawing widget."); } @@ -35,8 +31,7 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread width: clockInfoMenu.w, draw:function(e) { clockInfoMenu.x = e.x; - wuo = 0 | widget_utils.offset; - clockInfoMenu.y = e.y + wuo; + clockInfoMenu.y = e.y; var o = clockInfoMenu; // Clear the background g.reset(); From b44fc1865d06b0ed9a9528d1065aeb577f1a7040 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Fri, 13 Dec 2024 00:24:23 -0500 Subject: [PATCH 09/25] widclkinfo: cleanup event listeners --- apps/widclkinfo/widget.js | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 25323a3d84..299e598f2d 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -53,19 +53,37 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread } }; - Bangle.on("hidden", () => { - console.log("hidden"); + Bangle.on("widgets-start-show", () => { + clockInfoMenu.y = 0; + if (WIDGETS["clkinfo"]) { + WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + } + }) + + Bangle.on("widgets-shown", () => { + clockInfoMenu.y = 0; + if (WIDGETS["clkinfo"]) { + WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + } + }); + + Bangle.on("widgets-start-hide", () => { clockInfoMenu.y = -24; + if (WIDGETS["clkinfo"]) { + WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + } if (clockInfoMenu.focus) { - clockInfoMenu.force_blur(); - console.log("Forced blur bc hidden"); + clockInfoMenu.blur(); } }); - Bangle.on("shown", () => { - clockInfoMenu.y = 0; - console.log("shown"); + Bangle.on("widgets-hidden", () => { + clockInfoMenu.y = -24; if (WIDGETS["clkinfo"]) { WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); } + // check here too in case widget_utils.hide() is called + if (clockInfoMenu.focus) { + clockInfoMenu.blur(); + } }); From 45843303b3a54fac8ac774b6482c2ace5976dc7e Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Fri, 13 Dec 2024 00:25:03 -0500 Subject: [PATCH 10/25] widclkinfo: move draw function definition. Key change to function: not setting `clockInfoMenu.y = e.y` --- apps/widclkinfo/widget.js | 49 +++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 299e598f2d..6c05212d33 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -24,33 +24,36 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread } }); let clockInfoInfo; // when clockInfoMenu.draw is called we set this up + let draw = function(e) { + clockInfoMenu.x = e.x; + var o = clockInfoMenu; + // Clear the background + g.reset(); + // indicate focus + if (clockInfoMenu.focus) { + g.setColor("#f00"); + } + g.clearRect(o.x, o.y, o.x + o.w - 1, o.y + o.h - 1); + + if (clockInfoInfo) { + var x = o.x; + if (clockInfoInfo.img) { + g.drawImage(clockInfoInfo.img, x, o.y); // draw the image + x += 24; + } + var availableWidth = o.x + clockInfoMenu.w - (x + 2); + g.setFont("6x8:2").setFontAlign(-1, 0); + if (g.stringWidth(clockInfoInfo.text) > availableWidth) + g.setFont("6x8:1x2"); + g.drawString(clockInfoInfo.text, x + 2, o.y + 12); // draw the text + } + }; // The actual widget we're displaying WIDGETS["clkinfo"] = { - area:"tl", + area: "tl", width: clockInfoMenu.w, - draw:function(e) { - clockInfoMenu.x = e.x; - clockInfoMenu.y = e.y; - var o = clockInfoMenu; - // Clear the background - g.reset(); - // indicate focus - if (clockInfoMenu.focus) g.setColor("#f00"); - g.clearRect(o.x, o.y, o.x+o.w-1, o.y+o.h-1); - if (clockInfoInfo) { - var x = o.x; - if (clockInfoInfo.img) { - g.drawImage(clockInfoInfo.img, x,o.y); // draw the image - x+=24; - } - var availableWidth = o.x+clockInfoMenu.w - (x+2); - g.setFont("6x8:2").setFontAlign(-1,0); - if (g.stringWidth(clockInfoInfo.text) > availableWidth) - g.setFont("6x8:1x2"); - g.drawString(clockInfoInfo.text, x+2,o.y+12); // draw the text - } - } + draw: draw }; Bangle.on("widgets-start-show", () => { From de845be76f3fb653a837e9540ef6d7adbe0e84e4 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Fri, 13 Dec 2024 00:28:05 -0500 Subject: [PATCH 11/25] widclkinfo: Don't redraw widget if its clock_info is off screen I think it's okay to not update the clock_info in this case because they are designed to be on screen. --- apps/widclkinfo/widget.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 6c05212d33..ece03aa91b 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -6,7 +6,7 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread app: "widclkinfo", // Add the dimensions we're rendering to here - these are used to detect taps on the clock info area x: 0, - y: 0, // maybe set offset to initial offset + y: -24, // TODO how know if offscreen to start? w: 72, h: 24, // You can add other information here you want to be passed into 'options' in 'draw' @@ -16,13 +16,13 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread // info: data returned from itm.get() containing text/img/etc // options: options passed into addInteractive clockInfoInfo = info; - if (WIDGETS["clkinfo"]) { clockInfoMenu.y = options.y; + if (WIDGETS["clkinfo"] && clockInfoMenu.y > -24) { WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); - console.log("Clock Info was updated, thus drawing widget."); } } }); + let clockInfoInfo; // when clockInfoMenu.draw is called we set this up let draw = function(e) { clockInfoMenu.x = e.x; From 72a6b1db2f83133728195283bb284f900e52e095 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Fri, 13 Dec 2024 00:32:09 -0500 Subject: [PATCH 12/25] widclkinfo: balance brackets --- apps/widclkinfo/widget.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index ece03aa91b..23d73783e3 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -90,3 +90,4 @@ if (!require("clock_info").loadCount) { // don't load if a clock_info was alread clockInfoMenu.blur(); } }); +} From ba5d98a8c24a111e79a8c858c512874a07b107c7 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 5 Jan 2025 14:46:18 -0500 Subject: [PATCH 13/25] widclkinfo: Make clockInfoMenu part of the widget --- apps/widclkinfo/widget.js | 156 ++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 74 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 23d73783e3..3fece174c2 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -1,93 +1,101 @@ -if (!require("clock_info").loadCount) { // don't load if a clock_info was already loaded - // Load the clock infos - let clockInfoItems = clock_info.load(); +(() => { + if (!require("clock_info").loadCount) { // don't load if a clock_info was already loaded + //WIDGETS = {}; + const clock_info = require("clock_info"); - let clockInfoMenu = clock_info.addInteractive(clockInfoItems, { - app: "widclkinfo", - // Add the dimensions we're rendering to here - these are used to detect taps on the clock info area - x: 0, - y: -24, // TODO how know if offscreen to start? - w: 72, - h: 24, - // You can add other information here you want to be passed into 'options' in 'draw' - // This function draws the info - draw: (itm, info, options) => { - // itm: the item containing name/hasRange/etc - // info: data returned from itm.get() containing text/img/etc - // options: options passed into addInteractive - clockInfoInfo = info; - clockInfoMenu.y = options.y; - if (WIDGETS["clkinfo"] && clockInfoMenu.y > -24) { - WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + WIDGETS["clkinfo"] = { + area: "tl", + width: 0, //this.clockInfoMenu.w, + init: function() { + this.width = this.clockInfoMenu.w; + delete this.init; + return this; + }, + clockInfoInfo: undefined, // defined during clockInfoMenu.draw() + clockInfoMenu: clock_info.addInteractive(clock_info.load(), { + app: "widclkinfo", + // Add the dimensions we're rendering to here - these are used to detect taps on the clock info area + x: 0, + y: 0, // TODO how know if offscreen to start? + w: 72, + h: 24, + // You can add other information here you want to be passed into 'options' in 'draw' + // This function draws the info + draw: (itm, info, options) => { + // itm: the item containing name/hasRange/etc + // info: data returned from itm.get() containing text/img/etc + // options: options passed into addInteractive + var wi = WIDGETS["clkinfo"]; + wi.clockInfoInfo = info; + wi.clockInfoMenu.y = options.y; + if (WIDGETS["clkinfo"] && wi.clockInfoMenu.y > -24) { + WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + } } - } - }); - - let clockInfoInfo; // when clockInfoMenu.draw is called we set this up - let draw = function(e) { - clockInfoMenu.x = e.x; - var o = clockInfoMenu; - // Clear the background - g.reset(); - // indicate focus - if (clockInfoMenu.focus) { - g.setColor("#f00"); - } - g.clearRect(o.x, o.y, o.x + o.w - 1, o.y + o.h - 1); - - if (clockInfoInfo) { - var x = o.x; - if (clockInfoInfo.img) { - g.drawImage(clockInfoInfo.img, x, o.y); // draw the image - x += 24; + }), + draw: function(e) { + this.clockInfoMenu.x = e.x; + var o = this.clockInfoMenu; + g.reset(); + // indicate focus + if (this.clockInfoMenu.focus) { + g.setColor("#f00"); + } + g.clearRect(o.x, o.y, o.x + o.w - 1, o.y + o.h - 1); + if (this.clockInfoInfo) { + var x = o.x; + if (this.clockInfoInfo.img) { + g.drawImage(this.clockInfoInfo.img, x, o.y); // draw the image + x += 24; + } + var availableWidth = o.x + this.clockInfoMenu.w - (x + 2); + g.setFont("6x8:2").setFontAlign(-1, 0); + if (g.stringWidth(this.clockInfoInfo.text) > availableWidth) + g.setFont("6x8:1x2"); + g.drawString(this.clockInfoInfo.text, x + 2, o.y + 12); // draw the text } - var availableWidth = o.x + clockInfoMenu.w - (x + 2); - g.setFont("6x8:2").setFontAlign(-1, 0); - if (g.stringWidth(clockInfoInfo.text) > availableWidth) - g.setFont("6x8:1x2"); - g.drawString(clockInfoInfo.text, x + 2, o.y + 12); // draw the text } - }; - - // The actual widget we're displaying - WIDGETS["clkinfo"] = { - area: "tl", - width: clockInfoMenu.w, - draw: draw - }; + }.init(); Bangle.on("widgets-start-show", () => { - clockInfoMenu.y = 0; - if (WIDGETS["clkinfo"]) { - WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + var wi = WIDGETS["clkinfo"]; + if (wi) { + wi.clockInfoMenu.y = 0; + wi.draw(wi); } - }) + }); Bangle.on("widgets-shown", () => { - clockInfoMenu.y = 0; - if (WIDGETS["clkinfo"]) { - WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); + var wi = WIDGETS["clkinfo"]; + if (wi) { + wi.clockInfoMenu.y = 0; + wi.draw(wi); } }); Bangle.on("widgets-start-hide", () => { - clockInfoMenu.y = -24; - if (WIDGETS["clkinfo"]) { - WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); - } - if (clockInfoMenu.focus) { - clockInfoMenu.blur(); + var wi = WIDGETS["clkinfo"]; + if (wi) { + if (wi.clockInfoMenu.focus) wi.clockInfoMenu.blur(); + wi.clockInfoMenu.y = -24; + wi.draw(wi); } }); Bangle.on("widgets-hidden", () => { - clockInfoMenu.y = -24; - if (WIDGETS["clkinfo"]) { - WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); - } - // check here too in case widget_utils.hide() is called - if (clockInfoMenu.focus) { - clockInfoMenu.blur(); + var wi = WIDGETS["clkinfo"]; + if (wi) { + if (wi.clockInfoMenu.focus) wi.clockInfoMenu.blur(); + wi.clockInfoMenu.y = -24; + wi.draw(wi); } }); -} +}})() + +/* +const widget_utils = require("widget_utils"); +g.clear(); +Bangle.loadWidgets(); +widget_utils.swipeOn(); +Bangle.drawWidgets(); +*/ From 302e48b6fa9cee89c2897ac29ad17a29aeab2f26 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Wed, 18 Jun 2025 08:57:55 -0400 Subject: [PATCH 14/25] widget_utils: Move events to anim function --- modules/widget_utils.js | 49 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 250cd3d34b..67a69a6e29 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -132,16 +132,34 @@ exports.swipeOn = function(autohide) { if (exports.animInterval) clearInterval(exports.animInterval); exports.animInterval = setInterval(function() { exports.offset += dir; - let stop = false; - if (dir>0 && exports.offset>=0) { // fully down - stop = true; - exports.offset = 0; - Bangle.emit("widgets-shown"); - } else if (dir<0 && exports.offset<-23) { // fully up - stop = true; - exports.offset = -24; - Bangle.emit("widgets-hidden"); - } + let stop = false; +// exports.offset >=0 <0 <-23 +// dir >0 shown, so stop. in process of showing start show +// <0 start hide in process of hiding hidden, so stop + if (dir > 0) { + if (exports.offset >= 0) { + stop = true; + exports.offset = 0; + Bangle.emit("widgets-shown"); + } else if (exports.offset <= -23) { + Bangle.emit("widgets-start-show"); + } else { + Bangle.emit("widget-anim-step"); + } + } else if (dir < 0) { + if (exports.offset>=0) { + Bangle.emit("widget-start-hide"); + } else if (exports.offset <= -23) { + stop = true; + exports.offset = -24; + Bangle.emit("widgets-hidden"); + } else { + Bangle.emit("widget-anim-step"); + } + } + else { + // dir == 0?? + } if (stop) { clearInterval(exports.animInterval); delete exports.animInterval; @@ -159,18 +177,11 @@ exports.swipeOn = function(autohide) { let cb; if (exports.autohide > 0) cb = function() { exports.hideTimeout = setTimeout(function() { - Bangle.emit("widgets-start-hide"); anim(-4); }, exports.autohide); }; - if (ud>0 && exports.offset<0) { - Bangle.emit("widgets-start-show"); - anim(4, cb); - } - if (ud<0 && exports.offset>-24) { - Bangle.emit("widgets-start-hide"); - anim(-4); - } + if (ud>0 && exports.offset<0) anim(4, cb); + if (ud<0 && exports.offset>-24) anim(-4); }; Bangle.on("swipe", exports.swipeHandler); Bangle.drawWidgets(); From 86e6f8628857b9923907159e769b014b5564a154 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Wed, 18 Jun 2025 09:00:51 -0400 Subject: [PATCH 15/25] widget_utils: format indentation --- modules/widget_utils.js | 51 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 67a69a6e29..6d38d60417 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -132,34 +132,33 @@ exports.swipeOn = function(autohide) { if (exports.animInterval) clearInterval(exports.animInterval); exports.animInterval = setInterval(function() { exports.offset += dir; - let stop = false; -// exports.offset >=0 <0 <-23 -// dir >0 shown, so stop. in process of showing start show -// <0 start hide in process of hiding hidden, so stop - if (dir > 0) { - if (exports.offset >= 0) { - stop = true; - exports.offset = 0; - Bangle.emit("widgets-shown"); - } else if (exports.offset <= -23) { - Bangle.emit("widgets-start-show"); - } else { - Bangle.emit("widget-anim-step"); - } - } else if (dir < 0) { - if (exports.offset>=0) { - Bangle.emit("widget-start-hide"); - } else if (exports.offset <= -23) { - stop = true; - exports.offset = -24; - Bangle.emit("widgets-hidden"); - } else { - Bangle.emit("widget-anim-step"); - } + let stop = false; + // exports.offset >=0 <0 <-23 + // dir >0 shown, so stop. in process of showing start show + // <0 start hide in process of hiding hidden, so stop + if (dir > 0) { + if (exports.offset >= 0) { + stop = true; + exports.offset = 0; + Bangle.emit("widgets-shown"); + } else if (exports.offset <= -23) { + Bangle.emit("widgets-start-show"); + } else { + Bangle.emit("widget-anim-step"); } - else { - // dir == 0?? + } else if (dir < 0) { + if (exports.offset >= 0) { + Bangle.emit("widget-start-hide"); + } else if (exports.offset <= -23) { + stop = true; + exports.offset = -24; + Bangle.emit("widgets-hidden"); + } else { + Bangle.emit("widget-anim-step"); } + } else { + // dir == 0?? + } if (stop) { clearInterval(exports.animInterval); delete exports.animInterval; From b99bc3e90dba3aee839630c8d6969d143fb1918a Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sat, 16 Aug 2025 19:41:50 -0400 Subject: [PATCH 16/25] clock_info: Use ensure_blur as public function in options --- apps/clock_info/lib.js | 7 ++++--- apps/widclkinfo/widget.js | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index 3e5393cf4d..e4d2f5da24 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -326,15 +326,16 @@ exports.addInteractive = function(menu, options) { const blur = () => { options.focus=false; Bangle.CLKINFO_FOCUS--; - // if (Bangle.CLKINFO_FOCUS < 0) Bangle.CLKINFO_FOCUS = 0; const itm = menu[options.menuA].items[options.menuB]; let redraw = true; if (itm.blur && itm.blur(options) === false) redraw = false; if (redraw) options.redraw(); }; - // better to only call blur when we know it's focused. Maybe we can rename force_blur to ensure_blur. - options.force_blur = blur; + // better to only call blur when we know it's focused. Could reuse this logic in this file + options.ensure_blur = () => { + if (options.focus) blur() + } const focus = () => { let redraw = true; Bangle.CLKINFO_FOCUS = (0 | Bangle.CLKINFO_FOCUS) + 1; diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 3fece174c2..c7b3895e62 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -57,6 +57,7 @@ } }.init(); + // We make clock info touch area active on the start of the animation Bangle.on("widgets-start-show", () => { var wi = WIDGETS["clkinfo"]; if (wi) { @@ -76,7 +77,7 @@ Bangle.on("widgets-start-hide", () => { var wi = WIDGETS["clkinfo"]; if (wi) { - if (wi.clockInfoMenu.focus) wi.clockInfoMenu.blur(); + wi.clockInfoMenu.ensure_blur(); // let user see defocus cue before hiding wi.clockInfoMenu.y = -24; wi.draw(wi); } @@ -85,7 +86,7 @@ Bangle.on("widgets-hidden", () => { var wi = WIDGETS["clkinfo"]; if (wi) { - if (wi.clockInfoMenu.focus) wi.clockInfoMenu.blur(); + wi.clockInfoMenu.ensure_blur(); wi.clockInfoMenu.y = -24; wi.draw(wi); } From f1b8749a906c57d729229c44d995e3fb2096df40 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sat, 16 Aug 2025 19:46:49 -0400 Subject: [PATCH 17/25] widclkinfo: update version and changelog --- apps/widclkinfo/ChangeLog | 3 ++- apps/widclkinfo/metadata.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/widclkinfo/ChangeLog b/apps/widclkinfo/ChangeLog index d621e012af..9609b16e90 100644 --- a/apps/widclkinfo/ChangeLog +++ b/apps/widclkinfo/ChangeLog @@ -1,4 +1,5 @@ 0.01: New Widget! 0.02: Now use an app ID (to avoid conflicts with clocks that also use ClockInfo) 0.03: Fix widget clearing too far down -0.04: If a small font is needed, use 6x8 but twice as high \ No newline at end of file +0.04: If a small font is needed, use 6x8 but twice as high +0.05: Defocus the clock_info if widget_utils is used to move widgets off screen diff --git a/apps/widclkinfo/metadata.json b/apps/widclkinfo/metadata.json index 628388f55a..117879e20b 100644 --- a/apps/widclkinfo/metadata.json +++ b/apps/widclkinfo/metadata.json @@ -1,6 +1,6 @@ { "id": "widclkinfo", "name": "Clock Info Widget", - "version":"0.04", + "version":"0.05", "description": "Use 'Clock Info' in the Widget bar. Tap on the widget to select, then drag up/down/left/right to choose what information is displayed.", "icon": "widget.png", "screenshots" : [ { "url":"screenshot.png" }], From dd5fcd4f369ed0c03d646bfbd14a46e9f7a63da9 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sat, 16 Aug 2025 19:55:38 -0400 Subject: [PATCH 18/25] clock_info: update changelog --- apps/clock_info/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/clock_info/ChangeLog b/apps/clock_info/ChangeLog index 18439d3a29..605ad23ec2 100644 --- a/apps/clock_info/ChangeLog +++ b/apps/clock_info/ChangeLog @@ -20,3 +20,5 @@ 0.19: Fix Altitude ClockInfo after BLE added Tapping Altitude now updates the reading 0.20: Altitude ClockInfo now uses the distance units set in locale. +0.21: Expose ensure_blur function + From c7d7c8b93b35522ed2d7a267821a54dbada89a35 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sat, 16 Aug 2025 20:23:13 -0400 Subject: [PATCH 19/25] clock_info: bump version --- apps/clock_info/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/clock_info/metadata.json b/apps/clock_info/metadata.json index bfc0083989..cabe6313d5 100644 --- a/apps/clock_info/metadata.json +++ b/apps/clock_info/metadata.json @@ -1,7 +1,7 @@ { "id": "clock_info", "name": "Clock Info Module", "shortName": "Clock Info", - "version":"0.20", + "version":"0.21", "description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)", "icon": "app.png", "type": "module", From 89fb705a8fdde36555b42aad8a752a70b1f5af66 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sat, 16 Aug 2025 20:27:23 -0400 Subject: [PATCH 20/25] Remove test code comment --- apps/widclkinfo/widget.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index c7b3895e62..7edf030bb4 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -92,11 +92,3 @@ } }); }})() - -/* -const widget_utils = require("widget_utils"); -g.clear(); -Bangle.loadWidgets(); -widget_utils.swipeOn(); -Bangle.drawWidgets(); -*/ From dbdf1a56aa205597763b686e0984ffaf39bb67a2 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 17 Aug 2025 10:04:10 -0400 Subject: [PATCH 21/25] Note possible off by one error in detecting taps on clock_info --- apps/clock_info/lib.js | 7 ++++++- apps/widclkinfo/widget.js | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index e4d2f5da24..ab99fb8ca3 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -348,10 +348,15 @@ exports.addInteractive = function(menu, options) { if (redraw) options.redraw(); }; let touchHandler, lockHandler; +// debug touch handler next if (options.x!==undefined && options.y!==undefined && options.w && options.h) { touchHandler = function(_,e) { if (e.x(options.x+options.w) || e.y>(options.y+options.h)) { + e.x>(options.x+options.w-1) || e.y>(options.y+options.h-1)) { +// touch at y=0 focuses when widclkinfo is off screen +// may have off by one error here +// options.y is -24 +// options.h is 24 if (options.focus) blur(); return; // outside area diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index 7edf030bb4..c2bbfcef20 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -18,7 +18,7 @@ x: 0, y: 0, // TODO how know if offscreen to start? w: 72, - h: 24, + h: 23, // workaround off by one error in clock_info // You can add other information here you want to be passed into 'options' in 'draw' // This function draws the info draw: (itm, info, options) => { From 2c16883725a70772f678e323b367ae64f6eaafa9 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 17 Aug 2025 13:44:05 -0400 Subject: [PATCH 22/25] widget_utils: Work to fix logic error in animation state handling 1) Run exports.offset+=dir only in animation steps using the existing stop variable. We check if near animation boundary instead of doing the addition and seeing if we overstepped the animation boundary. The logic table now has absolute values that mean "nearly done with animation". This should mean that, eg, if the user swipes up in the last frame of the show animation, the widgets-start-hide event will still be triggered. 2) Also, standardize event name to widgets-* --- modules/widget_utils.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 6d38d60417..cfd3b066d4 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -131,39 +131,40 @@ exports.swipeOn = function(autohide) { function anim(dir, callback) { if (exports.animInterval) clearInterval(exports.animInterval); exports.animInterval = setInterval(function() { - exports.offset += dir; +// exports.offset < -23 + |dir| > -|dir| otherwise +// dir >0 start showing shown this step showing +// <0 hidden this step start hiding hiding let stop = false; - // exports.offset >=0 <0 <-23 - // dir >0 shown, so stop. in process of showing start show - // <0 start hide in process of hiding hidden, so stop if (dir > 0) { - if (exports.offset >= 0) { + if (exports.offset >= -dir) { + // nearly shown stop = true; - exports.offset = 0; + exports.offset = 0; // clamp Bangle.emit("widgets-shown"); - } else if (exports.offset <= -23) { + } else if (exports.offset < -23 + dir) { Bangle.emit("widgets-start-show"); } else { - Bangle.emit("widget-anim-step"); + Bangle.emit("widgets-anim-step"); } } else if (dir < 0) { - if (exports.offset >= 0) { - Bangle.emit("widget-start-hide"); - } else if (exports.offset <= -23) { + if (exports.offset > dir) { + Bangle.emit("widgets-start-hide"); + } else if (exports.offset < -23 - dir) { + // nearly hidden stop = true; - exports.offset = -24; + exports.offset = -24; // clamp Bangle.emit("widgets-hidden"); } else { - Bangle.emit("widget-anim-step"); + Bangle.emit("widgets-anim-step"); } - } else { - // dir == 0?? - } if (stop) { clearInterval(exports.animInterval); delete exports.animInterval; if (callback) callback(); } + else { + exports.offset += dir; + } queueDraw(); }, 50); } From 403ee4e8af4dd0ee1a73af8be4c242de56f19469 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 17 Aug 2025 14:03:57 -0400 Subject: [PATCH 23/25] widclkinfo: Remove debug line --- apps/widclkinfo/widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index c2bbfcef20..cfc19db4b7 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -1,6 +1,5 @@ (() => { if (!require("clock_info").loadCount) { // don't load if a clock_info was already loaded - //WIDGETS = {}; const clock_info = require("clock_info"); WIDGETS["clkinfo"] = { From 1358c99fa77375067d2d518781095ccb468800bd Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 17 Aug 2025 14:09:33 -0400 Subject: [PATCH 24/25] widget_utils: fix missing bracket --- modules/widget_utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index cfd3b066d4..14d57b9919 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -157,6 +157,7 @@ exports.swipeOn = function(autohide) { } else { Bangle.emit("widgets-anim-step"); } + } if (stop) { clearInterval(exports.animInterval); delete exports.animInterval; From 71a98acb1f0f57a721535339d5a67a9315017520 Mon Sep 17 00:00:00 2001 From: Corwin Kerr Date: Sun, 17 Aug 2025 15:27:37 -0400 Subject: [PATCH 25/25] widget_utils: Fix ambiguous if else --- modules/widget_utils.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 14d57b9919..e9423c417f 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -161,9 +161,10 @@ exports.swipeOn = function(autohide) { if (stop) { clearInterval(exports.animInterval); delete exports.animInterval; - if (callback) callback(); - } - else { + if (callback) { + callback(); + } + } else { exports.offset += dir; } queueDraw();