Есть такая замечательная библиотека для программирования с применением 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]