## Positioning controls in windows

### Setting the initial position of a control

When you create a control on a window, you normally set its position using the `where` property. This defines the initial position of the control relative to the top left of the window, in units set by the `scale` property of the parent. This example creates a window with a multi-line text-edit box taking up most of the window, and an OK button in the right-hand corner:

            Win1„'Œ' ŒNEW 'Window' ª Win1.where„4 4 14 28
            Win1.Ed.New 'Edit' ª Win1.Ed.where„1 1 8 25 ª Win1.Ed.style„8196
            Win1.But.New 'Button' ª Win1.But.where„10 16 ª Win1.But.caption„'OK'

Caution: For compatibility with other APL systems, the `scale` property defaults to 1, 'character' units, which is not necessarily the most convenient scale to use. You can change this to 5 (pixels) for more precise positioning, or to values expressed in physical units such as points or millimetres. The `scale` property for a given object is inherited from its parent when you create it, so it is often best to set the `scale` of the System object (which is the ultimate parent of all objects) at the beginning of your program. See the description of the `scale` property for more details.

If you want to query or change the size of a control but not its position, you can use the `size` or `extent` properties. These are the same, except that `size` is expressed in the object's own `scale`, whereas `extent` is in the `scale` of its parent.

### Handling re-sizing

If the window or dialog can be re-sized by the user, you need to consider what should happen to the control positions and sizes as the window size changes. The default is for the controls to remain at their initial positions, and to stay the same size. For some controls, that may be what you want. In many cases, however, you will want controls such as text-edit fields to get larger or smaller as the window changes size. You may also want controls such as buttons to move so that they remain anchored to the right or bottom-right of the window. In our example above, we want the OK button to remain at the bottom-right of the window, and we want the edit field to grow or shrink with the window.

One way of achieving this is to write an `onResize` callback, i.e. an APL function which gets called when the window is resized. Your APL function can then read the new window size, and move the controls around as necessary.

However, a much easier way is to use the `anchors` property. This defines which edges of the window the control is anchored to. It comprises a vector of four boolean values, which govern whether the control is anchored to the top, left, bottom and right of the window respectively. The default is 1 1 0 0, meaning that the control is anchored to the top and left of the window. As the window is resized, the position of the control remains fixed relative to the top left.

If you set the `anchors` property to 0 0 1 1, the control will be anchored to the bottom and right of the window. This means that, as the window is resized, the control will remain at a constant distance from the bottom right corner of the window (its `where` property will change accordingly). This is exactly what we want for our OK button in the above example:

            Win1.But.anchors„0 0 1 1

If a control is anchored to both the left and the right, then as the window is re-sized, the left edge of the control will remain at a fixed distance (as initially set by the `where` property) from the left edge of the window, and the right edge of the control will remain at a fixed distance from the right edge of the window. Thus the control will grow or shrink horizontally with the window. Similarly, if the control is anchored to both the top and the bottom, it will grow or shrink vertically with the window. This is what we want for our text-edit field in the above example:

            Win1.Ed.anchors„1 1 1 1

### Forcing a control to align with an edge of its parent

Another way of managing control positions and sizes is to use the `align` property. This is somewhat like the `anchors` property, in that it governs the position of a control by reference to the edge of the parent. However, unlike the `anchors` property, it overrides the `where` property, and forces the control to be positioned hard against the edge. It also forces it to expand or contract to be the same height or width as the parent. You can set it to one of five values:

         0  No alignment (default)
         1  The control is aligned along the top edge of its parent
         2  The control is aligned along the left edge of its parent
         3  The control is aligned along the bottom edge of its parent
         4  The control is aligned along the right edge of its parent
         ¯1 The control fills the whole client area of its parent

If, instead of the above example, you wanted the text edit control to fill the whole window, you could write:

            Win1„'Œ' ŒNEW 'Window' ª Win1.where„4 4 14 28
            Win1.Ed.New 'Edit' ª Win1.Ed.align„¯1 ª Win1.Ed.style„8196

### Using Splitter controls

A special case arises with the Splitter control. This is a vertical or horizontal line control, which allows the user to change the relative sizes of the controls on a window. For example, you might have a list box and a text edit, and use a Splitter to allow the user to move the boundary between them.

To do this, you first set up the leftmost (or topmost) control or controls, using the `align` property to align to the left (or top). You then create the Splitter, defining its position with the `where` property. Then you create the rightmost (or bottom) control, setting its `align` property to fill the remaining client area of the parent:

          DEMO„'Œ' ŒNEW 'Window'
          DEMO.title„'Splitter Example' ª DEMO.scale„5
          DEMO.List1.New 'List'
          DEMO.List1.align„2 ª DEMO.List1.size„50 20 ª DEMO.List1.list„ŒM
          DEMO.MySplitter.New 'Splitter' ª DEMO.MySplitter.where„0 22
          DEMO.Edit1.New 'Edit' ª DEMO.Edit1.style„36 ª DEMO.Edit1.align„¯1

### Setting constraints on the maximum and minimum window size

Often, you may want to put limits on the maximum or minimum height and width of a window, so that the user cannot make it so small that it becomes unusable, or so large that it wastes screen space. The `maxsize` and `minsize` properties allow you to specify the maximum and minimum sizes respectively.

### Automatic adjustment of control sizes for MacOS Aqua

The new look-and-feel (known as 'Aqua') which Apple introduced in MacOS X can sometimes require controls to be slightly larger than they were in the 'classic' MacOS environment. For example, Buttons have a more rounded look, which for some dialogs can mean that text which used to fit in the button is now partially obscured. If you have code designed for the 'classic' MacOS which you now want to run under MacOS X, the sizes therefore may need adjustment. Obviously, you can go through your code and adjust the sizes of the controls on each dialog, but this can be very time-consuming. APLX provides a quick method of reducing the conversion effort. If you set the `aquaadjust` property for the System object, all subsequent Buttons, Radio buttons and Checkboxes which are created will be adjusted in size slightly (although some additional manual adjustment may still be needed). This property is inherited by window objects, as well as the individual controls, so you can set it on or off individually for particular dialogs or controls. The property is ignored under Windows and Linux.

Topic: APLX Help : System Classes : Positioning controls in windows

[ Previous | Next | Contents | Index ]