Discussion

Links vs. Buttons

[1/13/09 - sparent <at> adobe <dot> com]
The current description of a link in this document refers to the "chain link" indicator in the Ps Image Size dialog. The term link however has come to be used more commonly to refer to a hyper text link. I propose we change that name and add a hyper text link widget. From here forward in the discussion when I refer to a link I mean a hyper text link.

A link widget is similar in nature to a button except the semantics of the action are constrained to "go to location" where a location could be a dialog, sheet, document page, panel, anchor within a document page, or other 'visual' location. Traditionally in dialogs a button with an ellipses, i.e. (Auto...), implied a link to a dialog (later extended to a sheet). The ellipses also implied "more information needed" - however that distinction is not being consistently applied. The ellipses is also used in menu items with the same implication. A link widget should take a URI as an argument and we should settle on a standard URI format to link to application UI constructs (mostly dialogs).

I would like to see our UI designers weigh in with a rule set for when to use a link vs. a button with an ellipsis so we can gain some consistency (perhaps we could simply drop this use case for buttons). If the distinction cannot be made programmatically, then I propose we have an attribute on the link widget gives the button/ellipse appearance without the need to embed the ellipse in the string (giving greater flexibility to the UI designers in the future).

As we are building more of our own UI, some thought might be given to using a link representation in menus as well.

A good display_text widget would allow for embedded links (possibly using an xhtml representation for the display text).

Subordinate Groups

[1/13/09 - sparent <at> adobe <dot> com]
A recent question arose regarding adding the ability to add any widget into the header of a group widget. There are cases within our UI where we have a checkbox and a popup and the idea was to generalize this to any widget. However, upon reflection the implied semantics of a widget in the header of a group are that the items within the group are subordinates to the item in the header. The only widgets for which I can envision such a subordinate relationship are those that select from a fixed set of values, specifically, checkbox, radio_button, and popup.

For a checkbox, the implication is that the subordinate items only apply when the checkbox is in it's positive state (and would be disabled otherwise). For a radio_button, the implication is that the subordinate items only apply when the state associated with the radio button is selected. For a popup, the implication is that there are multiple panels of subordinate items and the items on non-visible panels will be disabled (with the items on the current panel being enabled for the current popup selection). This distinguishes the popup group case from the tab panel case where there is no implication that the tabs are making any "choice" other than selecting which view to display.

My proposed solution is that we allow checkbox, radio_button and popup to be used as containers:

checkbox(name: "Use File Size:") {
edit_number();
}

(The proper enabled/disabled behavior would still fall out of the property model - this just allows for a visual clustering). A smart implementation may choose to display such a group that only contains a single element as a row instead of a group box.

CEL Primer

Values expressed in this document are specified using the Common Expression Language (CEL). For a more thorough introduction to the common expression language please visit the CEL expression reference documentation. Here is a quick overview of the types available in the CEL and how they are formatted:

array

dictionary

Stored as an adobe::dictionary_t. A collection of associated key-value pairs wrapped in brackets. The keys are always of type Identifier (adobe::name_t), though they are not prepended with the '@' (it is implied).

Other Types

The type system for CEL is open. Values are stored in an adobe::any_regular_t which can hold any regular type. Client functions can be introduced that return values of types other than those listed and other functions may process those value.

Predefined Constants

There are a number of predefined constants in the layout library - unless otherwise specified the value of the constant is not defined:

align_left

align_right

align_center

place_row

place_column

place_overview

The following constants should be defined with values based upon their context within a layout. For example, the value of space_normal should be less inside of a palette or message box then inside of a dialog.

space_grouped

space_normal

space_unrelated

The value of space_grouped should match the spacing defined within the widget set between a widget label and field. For example:

[ The space_ variables are not currently defined in the Begin application. ]

Associated Structures

These data structures are used by some of the widgets described below. They are available as utility structures to any widget that would like to use them. Note that a widget is not required to use all portions of a structure; it may use just what it requires.

unit_t

unit_t stores attributes pertaining to a specific numerical unit. An example of a numerical unit may be inches or degrees Celsius. Each of the values in this dictionary can be interpreted by the implementation of a widget as the widget sees fit. unit_t is described in CEL as a dictionary, and can have the following keys:

Attributes

Distinguishes the common underlying unit for this unit. An example of this would be lengths displayed in inches, centimeters, mm, picas, etc. Though they are different units they all, by linear transformation (see scale, below), devolve to a base unit which the user can choose. This identifier is used to group different units together that have the same base unit. This allows for a single collection of units to describe values in different bases (For example, bases of unit length and unit percent.)

This is the linear transformation used to go from this-unit to the base-unit. The first number is the slope of the linear transformation (m). The second number is the y-intercept of the transformation (b). A default of [ 1, 0 ] results in an identity transformation for the unit values.

value_range_format_t

This is a simple filter for limiting a value to one within a range of values. The general notion of a filter should describe a set of valid values (potentially infinite - such as all positive numbers).

Attributes

Specifies the increment/decrement count to get between first and last. In ASL widget implementations if this value is omitted it will default to last - first (which is actually pretty useless).

Examples in CEL

format: { first: 0, last: 100, interval_count: 50 }

General Layout Attributes

The layout engine ("Eve") does not know the difference between a widget destined to be a container (e.g., a window or a panel) versus one that is a leaf node (e.g., a button or a label). To the layout engine everything is a "box" with various attributes. In theory, then, all of the general attributes below could pertain to all of the widgets. Of course, this is nonsensical in some cases (e.g., spacing for a label), but the layout engine does not care, because it does not know that a "label" is a leaf widget any more than it knows a "group" is not (though it actually may be if it has no children). From an implementation standpoint, all nodes in the layout hierarchy have all these attributes, even if some are never used (or make no sense).

Default values in this section are suggestions of sorts. It is possible (and entirely likely) that the layout semantics of various widgets will require a different default for an attribute. For example, the default horizontal alignment of a container is align_default, but that value is changed to align_fill in the case of a panel widget. Overrides of this nature are explicitly iterated in the section on #Widget-Specific Layout Attributes under "Layout Attribute Defaults".

Code for the layout attributes can be found in <adobe/layout_attributes.hpp>.

Code for the extents can be found in <adobe/extents.hpp>.

Layout Attributes

indent

create

Determines whether or not this node actually creates a widget using a platform widget implementation. Examples of noncreating containers are row, column, and overlay. This attribute is not settable from within the layout description.

spacing

The amount of space to be put between multiple children of the container. This value can also contain an array, which will be iterated in turn to determine the spacing between two child widgets. Example: spacing: [ 5, 10, 15 ] will yield a container with 5 pixels between child widget 1 and 2, 10 pixels between child widget 2 and 3, and so forth.

placement

Align the children in an overlay. An overlay will cause all children to have horizontal and vertical alignments of align_fill. Each child will share the same layout real estate with its siblings. The idea for an container placing its children using place_overlay is so that only one will be visible at a time.

question : What does place_leaf do?

margin

margin is the amount of space from the frame of the container to the children within. The margins of a container can only be encroached upon by the outset of a child widget. A child widget's outset is not allowed to be larger than its container's margin (implying the outset of the child would extend into and possibly beyond the frame of the container.) If the container has no margin, then the outset of the child widgets will propagate to become the outsets of the parent container. If this attribute is specified using a single value (e.g., margin: 20) it implies the value should be used for all the container's margins.

size

Widget Extents

Generally the widget extents are not settable through a layout description - but instead are obtained by a call to the widget with the attributes supplied by the description. The terminology is documented here so that in cases where it does make sense to expose through a layout description it is done so consistently.

guide_set

width

height

Widget-Specific Layout Attributes

Containers

A container is a widget-context term: as previously mentioned, it really has no meaning as far as the layout engine is concerned. That being said, it is very helpful as a user interface designer to separate those widgets intending to contain child widgets from those that are meant to be leaf nodes. No container should be required to have any children, though for some of them it would be a poor UI decision to do so (e.g., a tab_group with no child panels would not be much of a tab group.)

When the bound cell to the tab group is set to this value, this particular tab becomes selected. Note that this does not hide/show the children of the tab group explicitly. Rather, in order to hide/show children properly, they must be contained within a panel bound to the same cell, and revealing itself by the same regular value.

Examples in CEL

Non-Creating Containers

Non-creating containers are unique from regular containers in that they produce no platform-specific widget upon time of creation. They are legitimate nodes in the layout engine tree, and can contain other nodes and be contained themselves. However, when the time comes to create the widgets within the layout, these elements propagate information up and down the layout, but do nothing in and of themselves.

By implication, calling adobe::measure and adobe::place for these "widgets" are no-ops.

Examples in CEL

checkbox

(Note: move this to the semantics doc) Checkboxes are not boolean (flag) widgets. There is a third, undetermined state for a checkbox, which is commonly seen as a dash running through the middle of the checkbox itself. When the value of the cell to which the checkbox is bound matches neither value_on or value_off, the checkbox should be seen in this third, undetermined state.

Examples in CEL

display_number

Note: There is a design flaw with the display_number implementation. It would be nice if the user were not required to specify a unit array for the display_number, but a problem arises in that the one and only unit thus created will use the name parameter for the display_number as the unit's name. This will cause a duplication of the name of the widget as the unit's label itself, for example: Inches: 5 Inches:

Describes the units to be used when formatting the number coming in from the property model. This array should contain a collection of unit_t dictionaries; please see the #unit_t documentation for parameter information. Note that display_number collects defaults for all unit values from the parameter set for the widget itself. For example, if format is defined as a parameter to this widget and is not otherwise specified by a unit, the unit will use the value found in the format parameter as its format value. This avoids unnecessary description duplication.

Describes the units to be used when formatting the number coming in from the property model. This array should contain a collection of unit_t dictionaries; please see the #unit_t documentation for parameter information. Note that edit_number collects defaults for all unit values from the parameter set for the widget itself. For example, if format is defined as a parameter to this widget and is not otherwise specified by a unit, the unit will use the value found in the format parameter as its format value. This avoids unnecessary description duplication.

Layout Attribute Defaults

Additional Attributes

Specifies the maximum width of the label (in approximate characters). When the label's content exceeds this width, the label will wrap, automatically increasing its height, so the entire label's contents are visible.

Examples in CEL

static_text(name: "Unfortunately, something drastic has happened. If you would like we can try to
continue with the operation, but there is a chance you will blow up your computer. Would
you like to try?", characters: 25);

Examples in CEL

popup

The custom meta-item is never explicitly selectable by the user. The only way it can be shown is if the user modifies the value bound to the popup by some other means for which the popup has no corresponding menu item.

Layout Attribute Defaults

no changes.

Additional Attributes

When the value to which this popup is bound does not match any of the possible values in the popup, the 'Custom' meta-item is shown. This string is the actual text used in the display of the custom meta-item.

Describes the items to be listed in the popup. If a name is specified then the popup items are bound to an output of the data model. The value bound to should contain an array of dictionaries as described here. [Note: binding items is currently not implemented in the APL widget set.] Each dictionary in the array has the following keys:

presets

Note: This is one nasty widget. The reason it is so is because it does not follow the conventions of a widget (typically) being a single view/controller into the model. In the case of a preset widget, it is a view/controller into an arbitrary number of values in the property model. As such, extra levels of setup and hook points are required.

The domain of the widget, typically the name of the application in which this preset widget resides. Note that this name is never seen visually; rather, it is used as the directory that will contain all the preset widget data files for this application.

Sometimes the client application will want to add runtime 'presets' that are not really presets but give the user the ability to copy state already present within the application. Examples of this may be a current list of the open documents and their dimensions. Each item is described using a dictionary with the following keys:

Describes the actual values contained within the preset. The keys in the preset's value must have a one-to-one correspondence to keys found in the current property model. The value associated with those keys are the values to be imbued upon the property model at the time this preset is selected by the user.

Specifies the feedback cell to go from the property model to the preset. This cell should contain an aggregation of property model cell names and their values as key/value pairs of a dictionary. When a value changes in the model and the preset widget wants to know about the change, the cell named here should have an updated dictionary with the new value for the modified cell.

One of the functions available through the preset widget is the ability to add new presets. When this is done a dialog is presented to the user where they can specify a name for the preset. The user, in that dialog, will also be able to specify exactly which of the property model values they would like to have included in the preset. This parameter allows for the specification of which property model values are allowed in a preset. Specifying an array of identifiers under a single label allows for related values to be added/omitted as a group from the preset.

Please see the CEL example for an example of how this parameter is specified.

The preset widget has subdialogs of its own. In order to allow for the client application to override the string values within these widgets, this dictionary can be supplied to the widget. There are a set number of keys for which strings are expected; if the key/value pair is not supplied in the dictionary, a default (English) string will be used.

Please see the CEL example for a list of keys (and possible string values).