Making the Window the Right Size

Make the window the right size for the message:

     | ?- win(Window),
             text_extents(Window, 'Hello, world!!', L, R, W,
                     Ascent, Descent),
             Width is W+4,
             Height is Ascent+Descent+4,
             put_window_attributes(Window, [size(Width,Height)]),
             TextLeft is L+2,
             TextBase is Ascent+2.
     Window = window(2376568),
     L = 0,
     R = 145,
     W = 146,
     Ascent = 17,
     Descent = 3,
     Width = 150,
     Height = 24,
     TextLeft = 2,
     TextBase = 19

First we retrieve our window. The second line, the call to text_extents/7, computes how big the message is when printed in the window. The first argument to text_extents/7 is a specification of the font we are using. Here, since we've already specified the font to use for drawing into this window, the window uniquely determines the font. So ProXL accepts the window in place of the font argument.

This unique determination of argument types is an important concept. ProXL tries to infer the right object from the object you give it. In this case, it wants a font, but it accepts a window. Previously, we associated a font with this window, so ProXL knows which font we mean. The table in pxl-bas-inf spells out which entities are predictable.

Returning to our example, the remaining arguments to text_extents/7 are:

the string whose size we're trying to find
left bearing: the number of pixels this string will occupy left of the origin
right bearing: the number of pixels this string will occupy right of the origin
total width
the number of pixels above the origin
the number of pixels below the origin

The next two goals compute the width and height of the window. We allow 2 pixels of blank space all around the string, yielding the 4 pixels we add in to determine both width and height. Note that the height of a string is its ascent plus it descent.

In the fifth line, we specify the new size for the window as we did before, only now with a more precise size.

The last two lines compute the origin point for drawing into the window. TextLeft allows 2 pixels to the left of the string, and TextBase leaves 2 pixels above. For this tutorial, we'll just remember these results and use them when needed. In an actual program, we would pass them as arguments to the program doing the drawing.

Notice that resizing the window erases our Hello, world!! message. This points up an important aspect of X: it is always the responsibility of the application to refresh its windows. Later we'll worry about making that work automatically; for now, just manually refresh the window:

     | ?- win(Window),
          draw_string(Window, 2, 19, 'Hello, world!!').
     Window = window(2376568)

There shouldn't be any surprises here. The position (2,19) simply the TextLeft and TextBase we computed earlier.