Components

Freestyle components are objects that have a graphical representation, and can use that representation to interact with the user. Examples of components are buttons, checkboxes, and icons.

Structure

Internally, components are discreet bundles of visual information packaged with logic to define how that visual information reacts to user input. The logic is specified with java code, or some other programming language, while the visual information, or view, is specified with HTML/CSS.

All of the following are valid views:

<div>This is a view.</div>
<ul>May I introduce
  <li>Thing one</li>
  <li>Thing two</li>
</ul>
<span style="border: 2px solid black;">Hello</span>
Every Freestyle component has a view. The default view looks like this:
<div/>

For an advanced treatment of styling and laying out components with CSS, see the section on Style.

Note: Freestyle specifically does not use any code-based solutions such as "layout managers" to arrange and render components. HTML and CSS are flexible, standard and familiar technologies which are particularly suited to this task.

Composition

A core feature of components is that they may be composed of other components. That is to say: their appearance and behavior may include the appearance and behavior of other components. For example, a combo-box is composed from a text-field, a button, and a list. While a form for collecting credit-card information might be composed from combo-boxes, text-fields, and check-boxes.

The sub-components which form a component are called that component's children. Stated another way, a component is said to contain its children. Naturally, the component which contains a child is called that childs parent. The entire tree of components in an application, starting with the top-most component and including all of its children, and its children's children, etc... is called the component hierarchy.

Component hierarchies are assembled by adding and removing children from other components just as you might manage any hiearchical structure such as a DOM. This is accomplished with calls to the addChild() and removeChild() methods..

The manner in which components are arranged into a hiearchy is used not only to control how events are handled, but also how the component appears when it is rendered

View Composition

When one component contains other components, its view will also contain the views of all its children. That is to say, the html of the child's view is incorporated into the html of its parent. By default, the html is composed in the order the children were added to the parent component. For example, suppose you have a component and two children whose views look like the following:

<!--container view -->
<div>
  <span class="title">Component One<span>
</div>
<!--child 1 view -->
<span>Hello</span>
<!-- child 2 view -->
<table><tr><td>Prokaryote</td></tr></table>

adding child 1 and child 2 to container in that order, will result in the following composed view for container

<div>
  <span>Component One</span>
  <ul/>    <!-- included from child 1 -->
  <table><tr><td>Prokaryote</td></tr></table> <!-- included from child2 -->
</div>

Child Slots

What happens if we do not want the child component's html to be included at the end of its parent's but somewhere else entirely? For these cases, a component can specify where in its view it wishes a particular child's view to be included. It does this by using roles for its children. Consider the following, more complex component view:

<!-- a panel view -->
<table>
<tr><td>${instructions}</td><td>${detonator}</td></tr>
</table>

The above view has two slots named "instructions" and "detonator." These slots will be filled by component's views which are added with a role of the same name. For example:

panel.addChild("instructions", new Label("Click Here -->"));
panel.addChild("detonator", new Button("Self Destruct"));

Roles

When a component is contained by another component, it will always have a role associated with it. A role is nothing more than a single string of meta-data indicating which part a child plays in the functioning of its parent. If a role is not stated explicitly, it will always have the implicit role anonymous.

We have already seen roles in action when composing views; a child's role is used to find out where to include that child's view in its parent's view. Role's are also used by selectors when styling components.

Pro Tip: There is no limit to the number of components that can be added with a given role, and no limit to the number of views that can be included in a given slot.