Adding Bangle.getAppRect? Widget bar size...

Posted on
  • Hi!

    If you've been writing Bangle.js apps, one thing you might have noticed is the need to hard-code a 24px gap at the top of the screen for the widget bar (there's also potentially 24px at the bottom for widgets but few things use this).

    This has been annoying me, because I'm pretty sure some people would like the ability to have a bigger (or smaller) widget bar (or even to relocate it completely) - and that'd be perfectly easy to do by installing something that replaced Bangle.drawWidgets.

    It's just that apps have no way of knowing what area they're expected to draw in.

    So I'm thinking something like:

    >print(Bangle.getAppRect())
    ={x:0,y:24,w:176,h:152}
    

    Would make a lot of sense?

    Any thoughts? What about a name? Part of me thinks it should be as short as possible - like Bangle.appRect

  • Since I'm currently working on a 2FA app, I've been thinking about exactly this (along with wondering if there is some sort of theme API for default colours).

    Should it be the app getting the available space from the system? Should there be some way for the app to control how much space is available for widgets? Top only? Bottom only? Both? More or less than 24px?

    Maybe the API should be:

    1. Bangle.getDefaultWidgetHeight() - returns 24 - this could be device dependant?
    2. Bangle.setWidgetHeight(top, btm) - set height of top and/or bottom widget space
    3. Bangle.getWidgetRect() - get effective screen area left after widgets - not necessary? - the app should be able to calculate this?

    Then widgets need a new API to determine how much space is available to them! :-)

    Also, I think that 24px top + 24px bottom (48px total) out of 176px height available on the Bangle 2 is more than 25% of the total screen height! IMO, that's too much.

  • One of the use cases that I see happening would be:

    var dim = Bangle.getAppRect();
    g.clearRect(dim.x, dim.y, dim.w, dim.h); // wrong
    g.clearRect(dim.x, dim.y, dim.w, dim.h + dim.y); // correct
    

    Bangle.getWidgetHeight() is also a nice addition

  • Maybe...

    >print(Bangle.getAppRect())
    ={x1:0,y1:24,x2:176,y2:176}
    

    This is your space to play with.

  • Something like that would be very nice!
    Some thoughts:

    • Does it have to be a function? Could maybe just be Bangle.APP, as we already have Bangle.WIDGETS?
    • When would it be allowed to change? I'm thinking only when calling Bangle.loadWidgets().
    • x,y,w,h looks nice, but if something is called *Rect I would expect x1,y1,x2,y2, like g.fillRect().
    • Also: x,y,w,h feels neater, but will make apps calculate a lot of x+w-1, whereas x2 wouldn't have the off-by-one problems, from the above example:

      var dim = Bangle.getAppRect();
      g.clearRect(dim.x, dim.y, dim.w, dim.h); // wrong
      g.clearRect(dim.x, dim.y, dim.w, dim.h + dim.y); // also wrong :-(
      g.clearRect(dim.x, dim.y, dim.x + dim.w - 1, dim.h + dim.y -1 ); // correct
      // vs
      g.clearRect(dim.x1, dim.y1, dim.x2, dim.y2);
      

      Same goes for

      var app = Bangle.getAppRect();
      g.setFontAlign(1, 1); // right,bottom
      g.drawString('bottom right', app.x+app.w-1, app.y+app.h-1);
      // vs
      g.drawString('bottom right', app.x2, app.y2);
      
  • You are write.... should be 175 (dam 0 index) 🤣🤣🤣

  • I like x1/y1/x2/y2.

    After thinking a bit, my phone has widget-like things - but they're only across the top. Perhaps support for bottom widgets should be dropped, and just support "l" and "r" areas ("tl"="bl"="l", "tr"="br"="r"). You've said that few things use bottom widgets. The Bangle 2 could be a good time for a new policy?

    I had also been thinking that perhaps the application clipping rectangle could be used (if g.getClipRect() existed and the clipping rectangle was forced to be the non-widget area), but then I thought some apps might like to draw to the entire screen and somehow have the widgets 'float' on top. That would require the application having the responsibility for drawing the background of the widget area, and for the widgets to only draw what they have to without erasing their background. It would also mean that widgets should NOT be calling Bangle.drawWidgets(), but should instead be sending an event to the host application, telling it that the widgets need to be drawn, and allowing it to update the background and then it calls Bangle.drawWidgets().

    It also occurs to me that widgets could be dynamic - they could come and go as required, which could mean the entire reserved widget area could also come and go.

    For me, the bottom line is this: the host application needs to be able to control where widgets can be displayed and know (if not control) how much space they take up. Widgets also need to know how much space (height) they have. If that is decided to be a fixed 24px height, then I'd be happy with that. If the application knows which widget areas it has enabled, then it can precalculate its draw area at launch - no need for a getAppRect(), but perhaps a need for a getWidgetHeight().

  • along with wondering if there is some sort of theme API for default colours

    Yes - g.theme / g.setTheme:)

    Should there be some way for the app to control how much space is available for widgets?

    Yes and no. I think usually we want apps just to be able to find out easily. But as hinted at, an app will be able to change Bangle.drawWidgets to allow widgets to be drawn wherever it wants.

    I can imagine a case where mostly you want the widgets in the normal place, but a clock may want to relocate them somewhere fancy.

    clearRect -x2/y2

    yes, it's a good point - and very common. I feel like some things may expect width and height but it's not a big deal for me to have x,y,w,h,x2,y2 in there?

    bottom widget bar

    Yes, it's a point that not much stuff uses (or supports!) it. It might be worth removing. What does everyone think?

    setWidgetHeight / precalculate its draw area

    My concern with this is I can see cases where someone might want to do something a bit different - maybe moving all widgets to the bottom, to left of the screen, or even putting some in the middle and making them bigger.

  • Just a note that I'm implementing this as a variable as @rigrig suggested, and I modified clearRect/etc so they can take an object as well as numbers.

    So now it's as easy as:

    g.clearRect(Bangle.appRect);
    
  • I modified clearRect/etc so they can take an object as well as numbers.

    Awesome, I'm sure this will come in handy in other places too.

  • Super

  • Yes - g.theme / g.setTheme:)

    Thanks - I knew I'd seen something somewhere, but couldn't remember. g.setTheme is not documented?

    BTW, the example data structure for g.theme repeats fg/bg instead of referring to fg2/bg2/fgH/bgH.

    I can see cases where someone might want to do something a bit different

    I know it's tempting to try to be as flexible as possible, but there is also value in enforcing consistency. In this case, using my phone as an example, status widgets have only ever appeared at the top, and I've never felt they needed to appear anywhere else :)

    I also don't think there is a good reason to have variable-sized widgets. What if some authors can't be bothered to implement support for variable sizes? If they do, will they need to supply multiple-sized images if they use images? What if there's a mix of variable and fixed-size? It seems overly complicated to me. I say - put your foot down and set the size at 24! ;-)

  • Think down the line and into the future where you get a Bangle.js 3 with a screen size of 524 x 524... maybe 24 pixel height is very small and unreadable.

  • @andrewg_oz thanks - i'll change those g.theme docs.

    I guess one thing I'm imagining (and I may implement this at some point) is that a 'large widgets' app could replace Bangle.loadWidgets and then wrap every widget's draw call in a function that drew it to an offscreen buffer and then doubled the size. It wouldn't be a hard thing to do and I think for some users it might be valuable.

    But yes, asking widget developers to handle different sizes would increase a lot of bloat and extra effort needed. I'm not sure it's a sensible thing to do either.

  • Hi
    I am working with Layout. It already relies on this Bangle.appRect.
    Which is great.
    However, the Bangle.appRect does not honour if bottom widgets are there.
    And in my case they are. My app will work with GPS, showing it on app screen and writing messages to Storage. I've already created widgets for GPS(tr), Storage(bl), digital clock with seconds(br), going to create recording widget may be. So, all widget real estate top and bottom is occupied.
    Please do not desupport bottom widget area.

    Again. My current problem. the Bangle.appRect does not honour if bottom widgets are there. It still shows

    >Bangle.appRect
    ={ x: 0, y: 24, w: 176, h: 152,
      x2: 175, y2: 175 }
    

    It causes app and bottom widgets override each other drawings. Mess.
    I tried to assign new h and y2 to Bangle.appRect, but it does not change.
    Gordon, could you fix it?
    Oh, I see in change log it is fixed already in 2v11!
    I need to upgrade.

    Just confirming that Layout works correctly after the upgrade to 2v11.

    Thanks!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Adding Bangle.getAppRect? Widget bar size...

Posted by Avatar for Gordon @Gordon

Actions