Есть такая замечательная библиотека для программирования с применением Adobe Flex, под названием flexlib. Разумеется, к ней есть документация, которую можно найти на страничке проекта.
Но я хотел бы написать об использовании конкретного класса FlowBox, и о совместимости его с недавно вышедшим Flex 3. (В продолжении статьи). А вот - полный список компонентов, входящих во FlexLib.
FlowBox - это такой Box, в который объекты добавляются и размещаются в нем в зависимости от их размеров. Например, в первой строчке может быть 10 узких объектов, а во второй - 1 широкий. Этот объект используется для допзоны в Берсерк-Онлайн. Зачем это надо? Если мы точно знаем, что ширина контейнера 200, а ширина всех его детей по 100, - мы конечно можем использовать Box, указав, что в каждой строчке нужно размещать по 2 объекта. Но если мы не знаем ни ширину контейнера, ни ширину детей - FlowBox нас спасет.
Но - самое большое разочарование постигает нас неожиданно. Дело в том, что если скин (borderSkin) задает собственные EdgeMetrics, то они учитываются. Что в контексте Flex 3 - может быть некорректно (если borderSkin объекта является наследником RectangularBorder) - так как поддержка RectangularBorder есть внутри самого Flex (геттер borderMetrics класса Container), но возможно корректно в контексте Flex 2.
Однако, если исключить из FlowLayout.as все упоминания про viewMetrics и borderMetrics, все становится нормально. Вот подкорректированный мной метод doLayout (не будет корректно работать с бордерами на основе IBorder (а не IRectangularBorder) и во Flex 2, так что на решение проблемы я не претендую).
[geshi lang=Actionscript]
private function doLayout(unscaledWidth:Number, moveChildren:Boolean):void
{
var vm:EdgeMetrics = target.viewMetricsAndPadding;
var hAlign:Number = getHorizontalAlignValue();
var vAlign:Number = getVerticalAlignValue();
var hGap:Number = target.getStyle( "horizontalGap" );
var vGap:Number = target.getStyle( "verticalGap" );
var len:Number = target.numChildren;
var currentRowChildren:Array = new Array;
var currentRowHeight:Number = 0;
var currentRowY:Number = 0; // dirty hack by baron
var currentRowLastX:Number = 0; // dirty hack by baron
var child:IFlexDisplayObject;
var tmpChild:IFlexDisplayObject;
var rowExcessSpace:Number;
var top:Number;
var maxX:Number;
var maxY:Number;
var paddingRight:Number = target.getStyle("paddingRight"); // dirty hack by baron
var paddingLeft:Number = target.getStyle("paddingLeft"); // dirty hack by baron
for ( var i:int = 0; i < len; i++ )
{
child = IFlexDisplayObject( target.getChildAt( i ) );
if(child is UIComponent && !UIComponent(child).includeInLayout) {
continue;
}
// If the child can't be placed in the current row....
if ( currentRowLastX + child.width > unscaledWidth - paddingRight )
{
currentRowLastX -= hGap;
rowExcessSpace = unscaledWidth - paddingRight - currentRowLastX;
rowExcessSpace *= hAlign;
currentRowLastX = rowExcessSpace == 0 ? paddingLeft : rowExcessSpace;
// Go back through the row and adjust the children for
// their vertical and horizontal align values
for ( var j:int = 0; j < currentRowChildren.length; j++ )
{
tmpChild = currentRowChildren[ j ];
top = ( currentRowHeight - tmpChild.height ) * vAlign;
if(moveChildren) {
tmpChild.move( Math.floor( currentRowLastX ), currentRowY + Math.floor( top ) );
}
currentRowLastX += tmpChild.width + hGap;
}
// Start a new row
currentRowY += currentRowHeight + vGap;
currentRowLastX = paddingLeft;
currentRowHeight = 0;
currentRowChildren = [];
}
// Don't actually move the child yet because that'd done when we
// "finish" a row
//child.move( currentRowLastX, currentRowY );
// Move on to the next x location in the row
currentRowLastX += child.width + hGap;
// Add the child to the current row so we can adjust the
// coordinates based on vAlign and hAlign
currentRowChildren.push( child );
// The largest child height in the row is the height for the
// entire row
currentRowHeight = Math.max( child.height, currentRowHeight );
}
// Done laying out the children, finish up the children that
// are in the last row -- adjust the children for
// their vertical and horizontal align values
//remove the single extra padding we have
currentRowLastX -= hGap;
rowExcessSpace = unscaledWidth - paddingRight - currentRowLastX;
rowExcessSpace *= hAlign;
currentRowLastX = rowExcessSpace == 0 ? paddingLeft : rowExcessSpace;
for ( j = 0; j < currentRowChildren.length; j++ )
{
tmpChild = currentRowChildren[ j ];
top = ( currentRowHeight - tmpChild.height ) * vAlign;
if(moveChildren) {
tmpChild.move( Math.floor( currentRowLastX ), currentRowY + Math.floor( top ) );
}
currentRowLastX += hGap + tmpChild.width;
}
if(!moveChildren) {
target.measuredHeight = currentRowY + currentRowHeight + vm.bottom + vm.top;
}
}[/geshi]