layout: text alignment not working?

Posted on
  • Is there any possibility to align some text within its cell when using the layout library? halign and valign don't seem to be respected as you can see yourself by running the following example:

      let ScreenWidth  = g.getWidth(),  ColumnWidth = ScreenWidth/3;    // 3 columns
      let ScreenHeight = g.getHeight(), RowHeight   = ScreenHeight/3;  // and 3 rows
    
      g.clear(true);
    
      let Layout = require('Layout');
      let Display = new Layout({
        type:'v', c:[
          { type:'h', c:[
            { type:'txt', font:'12x20', label:'Test', valign:-1, halign:-1, width:ColumnWidth, height:RowHeight },
            { type:'txt', font:'12x20', label:'Test', valign:0,  halign:-1, width:ColumnWidth, height:RowHeight },
            { type:'txt', font:'12x20', label:'Test', valign:1,  halign:-1, width:ColumnWidth, height:RowHeight },
          ] },
          { type:'h', c:[
            { type:'txt', font:'12x20', label:'Test', valign:-1, halign:0, width:ColumnWidth, height:RowHeight },
            { type:'txt', font:'12x20', label:'Test', valign:0,  halign:0, width:ColumnWidth, height:RowHeight },
            { type:'txt', font:'12x20', label:'Test', valign:1,  halign:0, width:ColumnWidth, height:RowHeight },
          ] },
          { type:'h', c:[
            { type:'txt', font:'12x20', label:'Test', valign:-1, halign:1, width:ColumnWidth, height:RowHeight },
            { type:'txt', font:'12x20', label:'Test', valign:0,  halign:1, width:ColumnWidth, height:RowHeight },
            { type:'txt', font:'12x20', label:'Test', valign:1,  halign:1, width:ColumnWidth, height:RowHeight },
          ] },
        ]
      });
      Display.render();
    

    1 Attachment

    • TextAlignment.png
  • The attached screenshot illustrates what I expected - but I reached that state with a custom renderer only:

    /**** Label ****/
    
      function Label (Text, Options) {
        function renderLabel (Details) {
          let halfWidth  = Details.w/2, xAlignment = Details.halign || 0;
          let halfHeight = Details.h/2, yAlignment = Details.valign || 0;
          let Padding = Details.pad || 0;
    
          g.setColor(Details.col || g.theme.fg || '#000000');
    
          if (Details.font != null) { g.setFont(Details.font); }
          g.setFontAlign(xAlignment,yAlignment);
    
          g.drawString(Details.label,
            Details.x + halfWidth  + xAlignment*(halfWidth+Padding),
            Details.y + halfHeight + yAlignment*(halfHeight+Padding)
          );
        }
    
        let Result = Object.assign({}, Options || {}, {
          type:'custom', render:renderLabel, label:Text || ''
        });
          let TextMetrics
          if (! Options.width || ! Options.height) {
            if (Options.font != null) { g.setFont(Options.font); }
            TextMetrics = g.stringMetrics(Result.label);
          }
    
          Result.width  = Options.width  || TextMetrics.width  + 2*(Options.pad || 0);
          Result.height = Options.height || TextMetrics.height + 2*(Options.pad || 0);
        return Result;
      }
    

    Here is a simple "smoke test" for the above "component":

      let ScreenWidth  = g.getWidth(),  ColumnWidth = ScreenWidth/3;    // 3 columns
      let ScreenHeight = g.getHeight(), RowHeight   = ScreenHeight/3;  // and 3 rows
    
      g.clear(true);
    
    /**** Label ****/
    
      function Label (Text, Options) {
        function renderLabel (Details) {
          let halfWidth  = Details.w/2, xAlignment = Details.halign || 0;
          let halfHeight = Details.h/2, yAlignment = Details.valign || 0;
          let Padding = Details.pad || 0;
    
          g.setColor(Details.col || g.theme.fg || '#000000');
    
          if (Details.font != null) { g.setFont(Details.font); }
          g.setFontAlign(xAlignment,yAlignment);
    
          g.drawString(Details.label,
            Details.x + halfWidth  + xAlignment*(halfWidth+Padding),
            Details.y + halfHeight + yAlignment*(halfHeight+Padding)
          );
        }
    
        let Result = Object.assign({}, Options || {}, {
          type:'custom', render:renderLabel, label:Text || ''
        });
          let TextMetrics
          if (! Options.width || ! Options.height) {
            if (Options.font != null) { g.setFont(Options.font); }
            TextMetrics = g.stringMetrics(Result.label);
          }
    
          Result.width  = Options.width  || TextMetrics.width  + 2*(Options.pad || 0);
          Result.height = Options.height || TextMetrics.height + 2*(Options.pad || 0);
        return Result;
      }
    
    
      g.setFont12x20();                  // does not seem to be respected in layout!
    
      let Layout = require('Layout');
      let Display = new Layout({
        type:'v', c:[
          { type:'h', c:[
            Label('Test',{ valign:-1, halign:-1, font:'12x20', width:ColumnWidth, height:RowHeight }),
            Label('Test',{ valign:0,  halign:-1, font:'12x20', width:ColumnWidth, height:RowHeight }),
            Label('Test',{ valign:1,  halign:-1, font:'12x20', width:ColumnWidth, height:RowHeight }),
          ] },
          { type:'h', c:[
            Label('Test',{ valign:-1, halign:0, font:'12x20', width:ColumnWidth, height:RowHeight }),
            Label('Test',{ valign:0,  halign:0, font:'12x20', width:ColumnWidth, height:RowHeight }),
            Label('Test',{ valign:1,  halign:0, font:'12x20', width:ColumnWidth, height:RowHeight }),
          ] },
          { type:'h', c:[
            Label('Test',{ valign:-1, halign:1, font:'12x20', width:ColumnWidth, height:RowHeight }),
            Label('Test',{ valign:0,  halign:1, font:'12x20', width:ColumnWidth, height:RowHeight }),
            Label('Test',{ valign:1,  halign:1, font:'12x20', width:ColumnWidth, height:RowHeight }),
          ] },
        ]
      });
      Display.render();
    

    (the "Label" component is part of my Bangle.js 2 activities as documented on GitHub)


    1 Attachment

    • TextAlignment.png
  • I've just added a bold option to the "Label" component - see GitHub for details


    1 Attachment

    • LabelDemo.png
  • The issue is you don't have fillx:1,filly:1 I think.

    Without it the element is sized to fit the text exactly, so then aligning within that box has no effect.

  • No, all cells have a fixed width and height (namely 1/3 of the full screen width/height) and texts should have been aligned within these cells...

  • Ok, just checked and the issue is documentation - but maybe the label renderer should be smarter too.

    halign/valign do align the element within its container. As a result, halign only works for v layouts, and valign only works for h.

    But if you specify a size for the element that fills the container there is no room for alignment, so there is no effect. Once you have the element size set, the label is just rendered in the middle of that element, regardless of alignment requested

  • I see.

    On the other hand, I usually preset the (minimum) size of a control (e.g., in order to keep them equal across rows/columns) and then want the text to be properly aligned within its cell. Thats what my "Label" control (and all the others) do.

    Thus, don't worry right now (perhaps update docs, at least) - I already have a "workaround"

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

layout: text alignment not working?

Posted by Avatar for Andreas_Rozek @Andreas_Rozek

Actions