User Interface for Constraints
Two main parts of SCWM's interface to the Cassowary constraint solver exist: a toolbar for adding constraints, and an investigator for managing and visualizing existing constraints.
Applying Constraints Using the Toolbar
Constraints are applied to windows using a toolbar. Each constraint class in the system is represented by a button on the toolbar (see Figure 2). The user creates a constraint by clicking a button and then selecting the windows to be constrained. Alternatively, the user can first highlight the windows to be constrained, and then click the appropriate button. Icons and tooltips with descriptive text assist the user in understanding what each constraint does.
Figure 2. Toolbar and buttons
We provide the following constraint classes in our system. Most of the interesting relationships are either present or they can be created by combining classes in the list.
Constant Height/Width Sum—Keep the total of the height/width of two windows constant.
Horizontal/Vertical Separation—Keep one window always to the left of or above another.
Strict Relative Position—Maintain the relative positions of two windows.
Vertical/Horizontal Maximum Size—Keep the height/width of a window below a threshold.
Vertical/Horizontal Minimum Size—Keep the height/width of a window above a threshold.
Vertical/Horizontal Relative Size—Keep the change in heights/widths of two windows constant (that is, resize them by the same amount together).
Vertical/Horizontal Alignment—Align the edge or center of one window along a vertical/horizontal line with the edge or center of another window.
Anchor—Keep a window in place.
Some of these constraint types can constrain windows in several different ways. For example, the Vertical Alignment constraint can align the left edge of one window with the right edge of another, or the right edge of one window with the middle of another. Users specify the parameters of the relationship by using window nonants, the ninefold analogue of quadrants (see Figure 3). The nonant in which the user clicks dictates the part of the window to which the constraint relates. For example, if the user selects the Vertical Alignment constraint and then chooses the first window by clicking in any of the east nonants, and the second window by clicking on any of its west nonants, the resulting constraint holds the right edge of the first window in line with the left edge of the second. This technique makes some constraint classes—such as those handling alignment—more generally useful. It also decreases the number of buttons on the toolbar, which could otherwise become unwieldy with many narrowly applicable constraint classes.
Figure 3. A nonant
Because it is impossible to predict every possible relationship that a user might desire, SCWM has a simple programming-by-demonstration facility that allows users to create new constraint class buttons. The leftmost button of the buttonbar starts a macro recorder that remembers the actions that are applied until a stop button is clicked. The intervening actions define a new relationship, and SCWM adds a new button to the buttonbar in order to make it easier to constrain other windows in the same way.
When a constraint is applied, the user must still be able to manage it. Users may wish to disable the constraint temporarily or remove it entirely. They may also encounter an odd behavior while they are moving or resizing a window, and they may want to discover which constraint(s) caused the unexpected result. They may simply be curious to know what constraints are applied to a given window and how that window will interact with other windows. Our constraint investigation interface allows for all of these interactions.
The primary means of inspecting constraints is through visual representations that are superimposed directly on the windows to which the constraint applies. In Figure 4, XTerm A is constrained to be to the left of XTerm B and above XTerm C. In addition, XTerm C is required to have a minimum width, and the XEmacs window's southeast corner is anchored at its current location. The constraint investigator, which allows users to manage the constraints instances, appears in the bottom left of the screen shot.
Figure 4. An example of constraints
When the mouse pointer hovers over a constraint in the investigator, the representation of that constraint is drawn. This hint makes it easy for the user to make the correct associations between windows and constraints. Each constraint class also defines its own visual representation, which closely matches the icon in the toolbar in most cases.
The constraint investigation window also allows the user to enable and disable one or all constraints via a checkbox, and to remove a constraint via a delete button. The constraint investigator can be kept onscreen at all times and can be dynamically updated as constraints are applied and removed. Together with the visual representation system, the investigation window makes it easy to manipulate constraints.