Ask Reuben

Spacer vs Space

Why is there no “space” when I use a “spacer” ?

How can I force a gap between adjacent widgets?

This question came from a developer who was trying to use a spacer to force a gap between two adjacent widgets.

For those who have not come across a spacer before, it is something you can use with HBox-tags.

A spacer is an invisible element that automatically expands. It can be used to align elements left, right or center in the hbox.

So despite the name, a spacer does not necessarily add a space, its purpose is alignment.   I like to think of it as a spring that is forcing apart adjacent widgets so that they align without being resized.  That spring can be compressed so that it does not take up any space and that is where the confusion may arise.

If you want to force a space between adjacent fields, then you need to do something to ensure that the width of the grid columns between the two fields is greater than zero.  That can be achieved by adding a LABEL between the two adjacent widgets that has a non-empty TEXT attribute, the simplest case being a single space.  This has the desired effect of making the grid column between the adjacent widgets have the minimum width necessary to display a space in the current font.

I have put the code example for the screenshots at the end of the article so you can copy and paste.  The next 3 images show …

  • the code in the .per and where the spacer and space is in use
  • a screenshot of the spacer compressed to its minimum
  • a screenshot of the spacer expanding as the window is resized

… you should note that the LABEL, TEXT=” ” remains the same size and puts a gap between the adjacent fields, whilst the SPACER compresses and expands, and can compress so that it does not take up any space.

#! spacer.4gl
MAIN
    CALL ui.Interface.loadStyles("spacer")
    OPEN WINDOW w WITH FORM "spacer"
    MENU ""
        ON ACTION accept 
            EXIT MENU
        ON ACTION close
            EXIT MENU
    END MENU
END MAIN
#!spacer.per 
LAYOUT (TEXT="Spacer v Space")
HBOX
GROUP (TEXT="SPACER - No Stretchable Element")
GRID
{
[f01        : :f02        ]
}
END
END
GROUP (TEXT="SPACER - Stretchable Element")
GRID
{
[f11        : :f12        ]
[i11                      ]
}
END
END
GROUP (TEXT="LABEL - SPACE")
GRID
{
[f21        :x:f22        ]
[i21                      ]
}
END
END
END
ATTRIBUTES

f01 = formonly.f01;
f02 = formonly.f02;

f11 = formonly.f11;
f12 = formonly.f12;
IMAGE i11 = formonly.dummy1, STRETCH=BOTH, STYLE="noborder";

f21 = formonly.f21;
f22 = formonly.f22;
IMAGE i21 = formonly.dummy2, STRETCH=BOTH, STYLE="noborder";
LABEL x: TEXT=" ";
#! spacer.4st -- delete this line so it is valid .4st
<?xml version="1.0" encoding="ANSI_X3.4-1968"?>
<StyleList>
  <Style name="Window">
     <StyleAttribute name="windowType" value="normal" />
  </Style>
  <Style name="Image.noborder">
     <StyleAttribute name="border" value="none" />
  </Style>
</StyleList>

You may recognise that this is the same concept as an earlier Ask-Reuben article about adding a blank line in a grid only instead of ensuring a grid row has some space allocated, in this instance a grid column has some space allocated.