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 + diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index 0550692477..ab99fb8ca3 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -332,6 +332,10 @@ exports.addInteractive = function(menu, options) { redraw = false; if (redraw) options.redraw(); }; + // 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; @@ -344,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/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", 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" }], diff --git a/apps/widclkinfo/widget.js b/apps/widclkinfo/widget.js index d51f0563fb..cfc19db4b7 100644 --- a/apps/widclkinfo/widget.js +++ b/apps/widclkinfo/widget.js @@ -1,50 +1,93 @@ -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", - // 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, - // 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; - if (WIDGETS["clkinfo"]) - WIDGETS["clkinfo"].draw(WIDGETS["clkinfo"]); - } - }); - let clockInfoInfo; // when clockInfoMenu.draw is called we set this up +(() => { + if (!require("clock_info").loadCount) { // don't load if a clock_info was already loaded + const clock_info = require("clock_info"); - // The actual widget we're displaying WIDGETS["clkinfo"] = { - area:"tl", - width: clockInfoMenu.w, - draw:function(e) { - clockInfoMenu.x = e.x; - clockInfoMenu.y = e.y; - var o = clockInfoMenu; - // Clear the background + 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: 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) => { + // 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"]); + } + } + }), + draw: function(e) { + this.clockInfoMenu.x = e.x; + var o = this.clockInfoMenu; g.reset(); - // indicate focus - make background reddish - //if (clockInfoMenu.focus) g.setBgColor(g.blendColor(g.theme.bg, "#f00", 0.25)); - if (clockInfoMenu.focus) g.setColor("#f00"); - g.clearRect(o.x, o.y, o.x+o.w-1, o.y+o.h-1); - if (clockInfoInfo) { + // 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 (clockInfoInfo.img) { - g.drawImage(clockInfoInfo.img, x,o.y); // draw the image - x+=24; + if (this.clockInfoInfo.img) { + g.drawImage(this.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) + 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(clockInfoInfo.text, x+2,o.y+12); // draw the text + g.drawString(this.clockInfoInfo.text, x + 2, o.y + 12); // draw the text } } - }; -} \ No newline at end of file + }.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) { + wi.clockInfoMenu.y = 0; + wi.draw(wi); + } + }); + + Bangle.on("widgets-shown", () => { + var wi = WIDGETS["clkinfo"]; + if (wi) { + wi.clockInfoMenu.y = 0; + wi.draw(wi); + } + }); + + Bangle.on("widgets-start-hide", () => { + var wi = WIDGETS["clkinfo"]; + if (wi) { + wi.clockInfoMenu.ensure_blur(); // let user see defocus cue before hiding + wi.clockInfoMenu.y = -24; + wi.draw(wi); + } + }); + + Bangle.on("widgets-hidden", () => { + var wi = WIDGETS["clkinfo"]; + if (wi) { + wi.clockInfoMenu.ensure_blur(); + wi.clockInfoMenu.y = -24; + wi.draw(wi); + } + }); +}})() diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 376c2ceba1..e9423c417f 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); } + Bangle.emit("widgets-hidden"); }; /// Show any hidden widgets @@ -25,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 @@ -129,19 +131,41 @@ 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; - if (dir>0 && exports.offset>=0) { // fully down - stop = true; - exports.offset = 0; - } else if (dir<0 && exports.offset<-23) { // fully up - stop = true; - exports.offset = -24; + if (dir > 0) { + if (exports.offset >= -dir) { + // nearly shown + stop = true; + exports.offset = 0; // clamp + Bangle.emit("widgets-shown"); + } else if (exports.offset < -23 + dir) { + Bangle.emit("widgets-start-show"); + } else { + Bangle.emit("widgets-anim-step"); + } + } else if (dir < 0) { + if (exports.offset > dir) { + Bangle.emit("widgets-start-hide"); + } else if (exports.offset < -23 - dir) { + // nearly hidden + stop = true; + exports.offset = -24; // clamp + Bangle.emit("widgets-hidden"); + } else { + Bangle.emit("widgets-anim-step"); + } } if (stop) { clearInterval(exports.animInterval); delete exports.animInterval; - if (callback) callback(); + if (callback) { + callback(); + } + } else { + exports.offset += dir; } queueDraw(); }, 50);