Next: User-Defined Layout Schemes Up: No Title Previous: Introduction
One important requirement in the design of user interfaces is the ability for specifying the layout of dialog windows. These windows usually consist of several elements implemented as graphical objects. Therefore, window layout can be expressed as spatial relationships between window elements. Within our framework layout is specified by an abstract notation. The underlying concept of this notation is based on the ``box-and-glue'' metaphor of the TeX text formatting language .
Boxes describe layout of rectangular regions of screen space. They have a type and are hierarchically organized. Boxes consist of window elements, (variable) white space (referred to as fillers ), and other boxes. It is important to mention that our system implements layout boxes and fillers as virtual objects , i.e. not as special windows. Having virtual layout objects is advantageous in window systems where no lightweight windows are directly supported (e.g. on a Macintosh). Strategies for laying out and positioning box elements are defined by various box types. Our system offers a set of predefined box types implementing basic layout algorithms. Box types supporting more general layout algorithms are discussed in Section 3.
Our basic building blocks for layout specifications are horizontal and vertical boxes. Elements of these boxes are laid out horizontally and vertically, respectively. A box specification consists of a keyword indicating the box type, a size specification which might be empty, and a list of box elements. A horizontal or vertical box (<box-type> either :hbox or :vbox) is specified by the Lisp form (<box-type> (:width h :height v) box-item-1 ). The size of a box can be specified as a fixed or variable distance (filler) in either direction. In case of an empty size specification, the width and height of a box are set to a filler with default constraints (see below) and determined by its surrounding box. If elements require more space than available to their surrounding box, they are allowed to extend beyond the boundaries of their box. Boxes may also overlap one another.
It is also possible to define the size of a box with respect to its elements. Then, the size of this box is set to the result achieved by laying out its elements and shrinking fillers to their lower limit. Thus, the box has a minimal size satisfying all lower bound constraints.
In general the layout algorithm keeps the size of box elements unchanged. But this behavior is not always desired. Therefore, we introduced a frame-box (:fbox) which constrains (i.e. modifies) the size of its element in order to match exactly the size of the frame-box. A frame-box may contain only one box element: (:fbox (:width h :height v) box-item).
Fillers specify distances in either horizontal or vertical direction. They may be used as box elements denoting white space and gluing together other elements. They are also used in size specifications of boxes.
Fillers can be specified as fixed (e.g. size in pixel) or variable. Variable fillers depend on the space available to their enclosing box. We distinguish relative and constrained
fillers. A relative filler is expressed as a fixed ratio to the size of its superior box. Constrained fillers can shrink (stretch) to a given lower (upper) limit. Their default constraints are zero as lower and box size as upper bound. Several fillers as elements of the same box work together like springs. They share the available space and in general every filler claims the same amount of space, which is only constrained by its lower and upper limit.
The complete form specifying a constrained filler is (:filler :min m :max n), :min and :max are optional. We defined :filler as short-form of (:filler :min 0 :max <box-size>).
Figure 1: A DAG graph of a standard class hierarchy.
The first example demonstrates a simple dialog window. The three basic box types defined above are combined and applied to specify the layout of a window. This window (see Figure 1) shows a simple CLOS class browser displaying a class hierarchy. The right table contains all direct subclasses of the class listed in the left table. The contents of the tables can be replaced by direct super- or subclasses, i.e. they can be shifted (and scrolled) to focus on ``interesting'' classes. The lower part of the window displays a graph of the selected class hierarchy. The dialog window results from the following (schematic) layout specification (given as Lisp code). The layout facility is implemented by a class -mixin that provides methods for interpreting an initial layout description and updating a layout accordingly when the size of a corresponding dialog (or view) has been changed.
(defclass graph-view-scroller (layout-mixin scroller) ; inheritance of scroller makes a display area scrollable () (:documentation "Combines scrollable views and the layout facility")) (defclass class-browser-dialog (layout-mixin dialog) () (:documentation "Defines dialog windows with layout")) (let ((left-table (make-instance 'sequence-dialog-item \codedots)) (right-table (make-instance 'sequence-dialog-item \codedots)) (graph-view (make-instance 'graph-view-scroller \codedots))) (make-instance 'class-browser-dialog :layout (:vbox (:width :filler :height :filler) ; main vertical box (:hbox (:height 1/4 :width :filler) ; top row (:fbox () left-table) (:fbox () right-table)) (:fbox () graph-view))) ; bottom row (setf (layout graph-view) ...))
Figure 2: CLOS class inspector window (default size).
Figure 3: CLOS class inspector window (vertically and horizontally enlarged).
The browser dialog is specified as a vertical box with :filler as width and height. Its first item is a horizontal box whose height is set to of the vertical box. The horizontal box contains two scrollable tables which are enclosed by frame-boxes. The height of these frame-boxes is constrained by their surrounding horizontal box. Their width is not explicitly specified, therefore the default value :filler is chosen and half of the width of the horizontal box is assigned to each frame-box (and its inferior table). The second item of the vertical box is a frame-box surrounding the box element -view which generates the class graph. A layout form which is similar to that defining -view is shown in Figure 4.
The second example is part of a user interface of a CLOS inspector. It demonstrates the use of fillers with minimum and maximum length specifications. The inspector displays a window consisting of tabular subwindows. Figure 2 shows information about a class . It displays the class precedence list, direct super and subclasses, slot information, and direct (locally defined) methods. If necessary, tables may be scrolled provided the space available to a table is not sufficient for displaying all table elements.
The corresponding layout specification is composed of several parts, we only explain its general outline. The upper rows are specified as horizontal boxes containing three frame-boxes which represent tables. The width and height of the frame-boxes are defined by constrained fillers. All fillers compete for the horizontal space available to them, which, in fact, is constrained by their surrounding horizontal box. Therefore, after a relaxation process each filler acquires one third of the available space. Roughly, the horizontal boxes compete for the vertical space in a similar manner. Minimal and maximal constraints guarantee that sparse tables have a visually appealing uniform shape.
Our notion of constrained fillers is important for describing a flexible window layout. For instance, Figure 3 shows the same window as in Figure 2 except that the vertical and horizontal space available to the window has been enlarged. The table displaying the direct methods of class adapted to the new space constraint. The additional vertical space was completely consumed by this table since it is the only element with a filler constraint whose upper bound has not yet been reached.1
Our current layout scheme provides no support for specifying dependencies between box items which are not elements of the same box. For instance, the height of box elements cannot depend on the width of arbitrary other elements. This restriction could be relaxed by introducing local variables in layout forms. These variables could represent box attributes such as the actual width and height of a box. The variables could serve as constants within the scope of a form. The following example shows a useful application of this feature.
(let ((item-1 (make-dialog-item ...)) ; create two window elements (item-2 (make-dialog-item ...))) (:vbox (:width (:filler :bind ?total-width)) ; ?total-width is local variable :filler ; vertical centering (:hbox () 20 ; left border (in pixel) (:fbox (:height (truncate (/ ?total-width 2))) item-1) ; use local variable :filler ; align frame-boxes to left and right (:fbox (:height (truncate (/ ?total-width 2))) item-2) ; use local variable 20) ; right border (in pixel) :filler)) ; vertical centering
One interpretation of this specification might be as follows. The evaluation of the form :bind ?total-width depends on its lexical context. In this case the value of ?total-width is set to the actual width of the vertical box, which is constrained by the width of the surrounding window. Then, this value is used to determine the height of item-1 and item-2. Therefore, the height of item-1 and item-2 depends on the total width of their outermost vertical box.
Next: User-Defined Layout Schemes Up: No Title Previous: Introduction