Starling FoxholeControls LayoutHelper

Super quick post… I’ve created a simple LayoutHelper for Josh Tynjala’s FoxholeControls.

This will help simple containers lay out their components without having to do a ton of custom property/member inspection for each child you want to lay out!

First up, some super handy links!

 
And now the code!

package com.killerspaz.flash.starling.foxhole.helpers
{
    import flash.geom.Point;
    
    import org.josht.starling.foxhole.core.FoxholeControl;
    
    import starling.display.DisplayObject;

    public class LayoutHelper
    {
        public static const DIRECTION_VERITCAL:String   = "DIRECTION_VERITCAL";
        public static const DIRECTION_HORIZONTAL:String = "DIRECTION_HORIZONTAL";
        
        private var _layoutTarget:FoxholeControl;
        private var _direction:String   = DIRECTION_HORIZONTAL;
        private var _allowFlow:Boolean  = true;
        private var _gap:Number         = 5;
        private var _padding:Number     = 10;
        
        public function LayoutHelper(layoutTarget:FoxholeControl):void
        {
            this._layoutTarget = layoutTarget;
        }

        public function get allowFlow():Boolean
        {
            return this._allowFlow;
        }

        public function set allowFlow(value:Boolean):void
        {
            this._allowFlow = value;
            this.invalidate();
        }

        public function get direction():String
        {
            return this._direction;
        }

        public function set direction(value:String):void
        {
            this._direction = value;
            this.invalidate();
        }

        public function get padding():Number
        {
            return this._padding;
        }

        public function set padding(value:Number):void
        {
            this._padding = value;
            this.invalidate();
        }

        public function get gap():Number
        {
            return this._gap;
        }

        public function set gap(value:Number):void
        {
            this._gap = value;
            this.invalidate();
        }

        public function get layoutTarget():FoxholeControl
        {
            return this._layoutTarget;
        }

        public function set layoutTarget(value:FoxholeControl):void
        {
            this._layoutTarget = value;
            this.invalidate();
        }
        
        public function invalidate():void
        {
            if (null !== this._layoutTarget) {
                this._layoutTarget.invalidate();
            }
        }
        
        public function layout():void
        {
            var numChildren:int = this._layoutTarget.numChildren;
            
            var childIdx:int;
            var currChild:DisplayObject;
            var layoutPoint:Point = new Point(this._padding, this._padding);

            var maxBoundaries:Point = new Point();
            var rowBoundaries:Point = new Point();
            
            //Calculate w/h, excluding the padding top/bottom or left/right
            maxBoundaries.x         = this._layoutTarget.width  - (this._padding * 2);
            maxBoundaries.y         = this._layoutTarget.height - (this._padding * 2);
            
            //Iterate over children, and layout accordingly
            for (childIdx = 0; childIdx < numChildren; childIdx++) {
                currChild = this._layoutTarget.getChildAt(childIdx);
                
                if (currChild is FoxholeControl) {
                    FoxholeControl(currChild).validate();
                }
                
                //Position Child!
                currChild.x = layoutPoint.x;
                currChild.y = layoutPoint.y;
                
                //Layout based on direction
                if (DIRECTION_HORIZONTAL === this._direction) {
                    layoutPoint.x   += currChild.width + this._gap;  //Increase layout sizes (except if first child)
                    rowBoundaries.y = Math.max(rowBoundaries.y, currChild.height);          //Determine the actual row/column boundary to avoid overlapping rows/columns
                    
                    //If allowed to "flow," carry on to next row...
                    if (this._allowFlow && layoutPoint.x >= maxBoundaries.x) {
                        layoutPoint.x   = this._padding;
                        layoutPoint.y   += this._gap + rowBoundaries.y;
                        rowBoundaries.y = 0;
                    }
                } else { //Same as above, but inverted for VERITCAL layout
                    layoutPoint.y   += currChild.height + this._gap;
                    rowBoundaries.x = Math.max(rowBoundaries.x, currChild.width);
                    
                    if (this._allowFlow && layoutPoint.y >= maxBoundaries.y) {
                        layoutPoint.x   += this._gap + rowBoundaries.x;
                        layoutPoint.y   = this._padding;
                        rowBoundaries.x = 0;
                    }
                }
                
                //trace ("Child " + (childIdx + 1) + " of " + numChildren + " " + currChild + " -- " + layoutPoint);
            }
        }

    }
}

Keep in mind, it’s simple, but supports the following:

  • Global container padding
  • Gapsize
  • Horizontal and Vertical “Layout”
  • Flow – whether to create a new row/column or just infinitely lay out a single direction (default = true)

Usage is simple…

1. In a FoxholeControl::initialize(), create a new instance and pass self into it:

        override protected function initialize():void
        {
            super.initialize();

            this._layoutHelper                  = new LayoutHelper(this);
            this._layoutHelper.direction        = LayoutHelper.DIRECTION_VERITCAL;
            //this._layoutHelper.allowFlow        = false;
  ...

2. In FoxholeControl::draw(), simply put:

        override protected function draw():void
        {
            super.draw();

            this._layoutHelper.layout();
        }

That’s it! Super simple!

Advertisements

About killerspaz

I'm a developer that loves to tinker with cutting edge technology. I have recently been playing with the Flash Platform (AS3/Flex), Android (custom roms, replacement apps, scripting), and looking at opportunities in the mobile markets.

Posted on 04.02.2012, in Flash, Starling and tagged , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: