Menu

Spark Basic Layout

SourceForge Editorial Staff

Spark Basic Layout - Functional and Design Specification


Summary and Background


In the Spark architecture, the containers and the layouts are separate objects. With Spark, we are providing generic containers, extensible/custom layouts as well as a few stock layouts with functionality that is parallel to the most-commonly used Halo layout containers.

This spec describes the BasicLayout, which is the Spark counterpart of the Canvas absolute layout, but without the advanced constraints support (no support for constraintRows and constraintColumns).

Goals:

  • BasicLayout should provide adequate absolute positioning and constraints support similar to the Halo Canvas container.
  • Lightweight enough to be the default GroupBase layout.
  • Takes advantage of the ILayoutElement interface to support 2D xforms on the elements
  • Reasonable scrolling support.
  • Layout calculations place elements on pixel boundaries provided that the input is in integer numbers.

Non-goals:

  • Preserve the absolutely exact behavior of the Halo Canvas container.
  • BasicLayout does not support virtual layout.

Usage Scenarios


  • Use absolute positioning by specifying x, y, width, height.
  • Use constraints left, right, top, bottom, horizontalCenter, verticalCenter, baseline.
  • Use percentWidth and percentHeight constraints
  • Use any combination of the above to arrange elements in skins, renderers; components in applications, etc.

Detailed Description


The BasicLayout extends LayoutBase. It is the default layout of a GroupBase.

Order of Precedence to Determine Element's Size

  • Percent width/height - the element's width/height is calculated as percentage of parent's width/height minus any left/right/top/bottom constraints. Element's minimum width, height are respected.
  • left & right determine width (element width = parent width - left - right), top & bottom determine height (element height = parent height - top - bottom). Element's minimum width, height are respected.
  • preferred element size (explicit or measured width/height).

Order of Precedence to Determine Element's Position

  • horizontalCenter, verticalCenter - offsets element's center from the parent's center (element's x = (parent width - element's width) / 2).
  • baseline - aligns the element's baselinePosition with the baseline constraint (element's y = baseline - baselinePosition).
  • left, top
  • right, bottom
  • x, y

Order of Precedence to Determine Default Extents for an Element

  • Both 'left' and 'right' or 'top' and 'bottom' are set - the extents are big enough to fit the element at its preferredSize.
  • horizontalCenter/verticalCenter - the extents are big enough to fit the element as offset from the center of the parent at the parent's default size and element's preferred size (extX = 0, extWidth = horizontalCenter * 2 + preferredWidth);
  • baseline - the extents are big enough to fit the element as offset from the baseline (extY = 0, extHeight = element.baseline + element.preferredHeight - element.baselinePosition).
  • left/right/top/bottom - the extents are big enough to fit the element plus any of the constraints.

Order of Precedence to Determine Minimum Default Extents for an Element

The minimum default extents are calculated the same way as the default extents. The only difference is that we take the element's minimum size instead of the preferred size in those cases where the element's size is constrained to the parent size (both left & right set or %width set, both top & bottom set or %height set).

Calculating the Default Size - measure()

  • measuredWidth, measuredHeight, measuredMinWidth, measuredMinHeight initially set to zero
  • For each element that is included in the layout calculate the element default extents and default minimum extents as outlined above.
  • Set the measuredWidth, measuredHeight to the Maximum of the bottom-right corners of the default extents. measuredWidth, measuredHeight are at least zero.
  • Set the measuredMinWidth, measuredMinHeight to the Maximums of the bottom-right corners of the default minimum extents.

Note that we don't take into account the %width, %height to calculate the default size.

Size and Arrange Elements - updateDisplayList(width, height)

  • For each element that is included in the layout:
    • Apply the constraints to determine the element's size as described above.
    • Using the element's size, apply the constraints to determine the element's position as described above.
  • container.contentWidth = Max(childX + childWidth)
  • container.contentHeight = Max(childY + childHeight)

Note that because of the way the constraints are defined, there are several meaningful ways to combine them. Let's take a look at a Group with size (100,100):

  • left=10, right=20, percentWidth=50 - when sized, the element's width will be 50% of 100 - 10 - 20 = 35 pixels. Element's x will always be 10 as per its left constraint.
  • left=10, right=20, percentWidth=50, horizontalCenter=0 - same as above the element will be 35 pixels wide, however it will be positioned in the center of the group. (x = 17.5, 18 after rounding).

Scrolling support

BasicLayout doesn't override any of the inherited scrolling APIs from LayoutBase.
The default LayoutBase implementation maps

  • ScrollBar steps to single pixel scrolling (ScrollUnit.LEFT scrolls a pixel in the left direction) * ScrollBar pages to the width/height of the scrollRect (ScrollUnit.PAGE_LEFT will scroll left by the width of the scrollRect).

Refer to the LayoutBase spec for details on the scrolling APIs.

Pixel Boundaries and Rounding

The BasicLayout takes care to perform rounding for any computation that may yield fractional numbers, assuming that the inputs are always integer numbers:

  • childWidth from width and percentWidth is rounded
  • childHeight from height and percentHeight is rounded
  • childX from width and horizontalCenter is rounded
  • childY from height and verticalCenter is rounded

API Description


The BasicLayout extends LayoutBase. There are no additional public APIs beyond that.

Examples and Usage


Align the text to y=40:

<Group>
    <layout>
        <BasicLayout/>
    </layout>
    <Label text="blah" baseline="40"/>
</Group>

Left and Right constraints, we don't need to specify the layout as basic, as this is the default

<Group>
    <Label text="blah" left="40" right="10" verticalCenter="0"/>
</Group>

Example from the Spark Panel skin, default Skin layout is basic as well:

<SparkSkin xmlns="http://ns.adobe.com/mxml/2009" alpha.disabled="0.5">

.....

    <states>
        <State name="normal" />
        <State name="disabled" />
    </states>

    <!-- drop shadow -->
    <Rect left="0" top="0" right="0" bottom="0">
        <filters>
            <DropShadowFilter blurX="20" blurY="20" alpha="0.32" distance="11" angle="90" knockout="true" />
        </filters>
        <fill>
            <SolidColor color="0" />
        </fill>
    </Rect>

    <!-- layer 1: border -->
    <Rect left="0" right="0" top="0" bottom="0">
        <stroke>
            <SolidColorStroke color="0" alpha="0.50" weight="1" />
        </stroke>
    </Rect>

    <!-- layer 2: background fill -->
    <Rect id="background" left="1" top="1" right="1" bottom="1">
        <fill>
            <SolidColor color="0xFFFFFF" id="bgFill" />
        </fill>
    </Rect>

    <!-- layer 3: title bar fill -->
    <Rect left="1" right="1" top="1" height="30">
       <fill>
            <LinearGradient rotation="90">
                <GradientEntry color="0xE2E2E2" />
                <GradientEntry color="0xD9D9D9" />
            </LinearGradient>
       </fill>
    </Rect>

    <!-- layer 4: title bar highlight -->
    <Rect left="1" right="1" top="1" height="30">
       <stroke>
            <LinearGradientStroke rotation="90" weight="1">
                <GradientEntry color="0xEAEAEA" />
                <GradientEntry color="0xBEBEBE" />
            </LinearGradientStroke>
       </stroke>
    </Rect>

    <!-- layer 5: text -->
    <TextBox id="titleField"
             left="10" right="4" top="2" height="30"
             verticalAlign="middle" fontWeight="bold">
    </TextBox>

    <Group id="contentGroup" left="1" right="1" top="32" bottom="1">
    </Group>

</SparkSkin>

Additional Implementation Details


Enter implementation/design details for the feature here. This section may be updated after the spec signs off.

Prototype Work


BasicLayout exists and is in a fairly complete state in the trunk.

Compiler Work


No.

Web Tier Compiler Impact


No.

Flex Feature Dependencies


Dependencies on other Flex features.

Backwards Compatibility


No.

Accessibility


Describe any accessibility considerations.

Performance


Possible optimizations

  • Don't calculate contentWidth, contnetHeight unless scrolling and clipping is in effect
  • If an element is not constrained, the BasicLayout doesn't need to specify its position again.

Globalization


No issues.

Localization


Compiler Features

No command-line params, warnings, errors, etc.

Framework Features

No RTE messages.

No UI text, images, skins, sounds.

Issues and Recommendations


Currently there's an issue with performing accurate measurement in cases where some child properties depend on the child's size. We have two such cases presently:

  • Child's bounds top-left position may depend on the child's size (e.g. child is rotated, or child is a path). This leads to incorrect measurement anytime updateDisplayList resizes the child, most notably during init time. This is a more-limited problem affecting only the BasicLayout from all stock Spark layouts.
  • Child's baselinePosition depends on the child's size. This problem will affect any layout that relies on baselinePosition during measure if the child is resized in updateDisplayList.

Recommendation:

Documentation


Describe any documentation issues or any tips for the doc team.

QA


If there are testing tips for QA, note them here, include a link to the test plan document.



Related

Wiki: Flex 4
Wiki: Gumbo Component Architecture

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.