include "draw.m"; include "prefab.m"; prefab:= load Prefab Prefab->PATH; # types of Elements EIcon: con 0; EText: con 1; ETitle: con 2; EHorizontal:con 3; EVertical: con 4; ESeparator: con 5; # first arg to Element.adjust: size of elements Adjpack: con 10; # leave alone, pack tightly Adjequal: con 11; # make equal Adjfill: con 12; # make equal, filling available space # second arg: position of element within space Adjleft: con 20; Adjup: con 20; Adjcenter: con 21; Adjright: con 22; Adjdown: con 22; Layout: adt { font: ref Draw->Font; color: ref Draw->Image; text: string; icon: ref Draw->Image; mask: ref Draw->Image; tag: string; }; Element: adt { kind: int; r: Draw->Rect; environ:ref Environ; tag: string; # different fields defined for different kinds of Elements kids: cyclic list of ref Element; # children of elists str: string; # text in an EText element mask: ref Draw->Image; # part of Eicon, ESeparator image: ref Draw->Image; # part of Eicon, ESeparator,
EText, Etitle font: ref Draw->Font; # part of EText, Etitle icon: fn(env: ref Environ, r: Draw->Rect, icon, mask: ref Draw->Image) :ref Element; text: fn(env: ref Environ, text: string, r: Draw->Rect, kind: int):ref Element; layout: fn(env: ref Environ, lay: list of Layout, r: Draw->Rect, kind: int):ref Element; elist: fn(env: ref Environ, elem: ref Element, kind: int) :ref Element; separator:fn(env:ref Environ, r: Draw->Rect, icon, mask: ref Draw->Image):ref Element; append: fn(elist:self ref Element, elem: ref Element): int; adjust: fn(elem:self ref Element, equal: int, dir: int); clip: fn(elem:self ref Element, r: Draw->Rect); scroll: fn(elem:self ref Element, d: Draw->Point); translate: fn(elem:self ref Element, d: Draw->Point); show: fn(elist:self ref Element, elem: ref Element): int; };
icon: fn(env: ref Environ, r: Draw->Rect,Build one EIcon element to be drawn with the icon and mask. The rectangle, r, gives the element's position and size.
icon, mask: ref Draw->Image): ref Element;
text: fn(env: ref Environ, text: string,Build a textual element or a list of textual elements. The kind parameter may be EText or ETitle, determining the style of the drawn text. The resulting Element object may be a single element or an EVertical list of the appropriate kind, if the text occupies more than one line. The text is folded as necessary to accommodate the available horizontal space; newlines in the text cause line breaks. The width of the text is determined by r, but if r has no width, it will be set by the text itself. The height of the Element is also determined by r. If the height of r is zero, the Element will be made as tall as necessary. If r is not tall enough, the rest of the text may be made visible by calls to Element.scroll. Thus one may choose a specific size or let the text determine the size by setting r suitably.
r: Draw->Rect, kind: int): ref Element;
layout: fn(env: ref Environ, lay: list of Layout,Like Element.text but builds a structure using the contents of the list of Layout adts. The Layout adt allows construction of a more general form of textual display by providing fine control over the font and color in which to display text and the inclusion of images as textual elements. It also allows setting of the tag for each component of the resulting element or list of elements. If the Layout has a non-nil image field, it is taken as a description of a picture to be incorporated in the text as an EIcon element (and the text field is ignored); otherwise the text field specifies the text to be drawn in the indicated font and color. As with Element.text, Element.layout does all the geometry management, including text line breaking and folding.
r: Draw->Rect, kind: int): ref Element;
elist: fn(env: ref Environ, elem: ref Element,Start a list of Element objects. The kind may be EHorizontal or EVertical, specifying the orientation of the list. Parameter elem will be the first element of the list. It may be nil, which creates an empty list of the requested orientation. Subsequent Element.append calls build the list.
kind: int): ref Element;
separator: fn(env: ref Environ, r: Draw->Rect,Build one ESeparator element to be drawn with the icon and mask. The rectangle, r, gives the element's position and size.
icon, mask: ref Draw->Image): ref Element;
append:fn(elist: self ref Element, elem: ref Element): int;Append one Element, elem, to an existing list, elist. The new element will appear after those already there, either to the right for EHorizontal or below for EVertical lists.
adjust: fn(elem: self ref Element, equal: int, dir: int);Format the list so its elements abut. The list-building functions such as append attempt to build a sensible geometry. Alternatively, one can build a list using degenerate geometry and then let adjust compute the geometry for the whole list. For example, one could place all the elements at (0, 0) and then call adjust to decide where the elements belong.
clip: fn(elem: self ref Element, r: Draw->Rect);The drawing model for Element objects is that they occupy some space in the plane, which may be larger or smaller than the space occupied by its constituent text, icons, sub-elements, and so on. The clip function sets the rectangle of elem to r, without changing its internal geometry. Any space made newly visible by this will be filled in by the list's Style.elemcolor. For example, if e is an icon element just large enough to display its image, e.clip(e.r.inset(-2)) will make a two-pixel-wide border around the icon when it is drawn. As another example, lists are scrolled by leaving their clip rectangle intact while translating the list elements' coordinates.
scroll: fn(elem: self ref Element, d: Draw->Point);Argument d is a Point, representing a vector; elem is an Element to be scrolled. The scroll function leaves the element's r alone and translates all the constituent pieces of the list by d, causing a different portion of elem to be visible in its rectangle.
translate: fn(elem: self ref Element, d: Draw->Point);Like elem.scroll(d), but moves r too, thus translating the entire Element rather than just the visible part within a fixed rectangle.
show: fn(elist: self ref Element, elem: ref Element): int;The show function does nothing if elist is not a list. If it is a list, the list is scrolled so elem, which must be a member of the list, is visible through
elist.r.
The geometry of elements and the membership of lists may be modified only through the provided functions. The Limbo-visible structure is intended to be read-only. Tags, text, and images may be modified freely by the application. There is no way to recalculate the geometry if the components of a textual or image icon change size.
Element objects are not drawn explicitly, and they are not drawn after any Element operation. They are made visible only by calls to Compound.draw, described in compound - windows for ITV toolkit.