452 lines
11 KiB
ActionScript
Executable File
452 lines
11 KiB
ActionScript
Executable File
/*
|
||
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
|
||
The copyrights embodied in the content of this file are licensed under the BSD (revised) open source license
|
||
*/
|
||
package com.yahoo.astra.fl.controls.containerClasses
|
||
{
|
||
import com.yahoo.astra.fl.controls.containerClasses.AutoSizeButton;
|
||
import fl.events.ComponentEvent;
|
||
import flash.events.MouseEvent;
|
||
import fl.core.UIComponent;
|
||
import flash.events.KeyboardEvent;
|
||
import flash.events.FocusEvent;
|
||
import flash.ui.Keyboard;
|
||
import flash.text.TextFormat;
|
||
import com.yahoo.astra.utils.InstanceFactory;
|
||
import com.yahoo.astra.fl.utils.UIComponentUtil;
|
||
|
||
//--------------------------------------
|
||
// Class description
|
||
//--------------------------------------
|
||
|
||
/**
|
||
* ButtonBar extends UIComponent and builds one or multiple rows of AutoSizeButton
|
||
* instances depending on the dimensions of its parent container and the size of the
|
||
* buttons
|
||
*
|
||
* @see fl.core.UIComponent
|
||
* @see com.yahoo.astra.fl.controls.containerClasses.AutoSizeButton
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
* @author Dwight Bridges
|
||
*/
|
||
public class ButtonBar extends UIComponent
|
||
{
|
||
|
||
//--------------------------------------
|
||
// Constructor
|
||
//--------------------------------------
|
||
|
||
/**
|
||
* Constructor
|
||
*/
|
||
public function ButtonBar()
|
||
{
|
||
super();
|
||
this.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
|
||
this.addEventListener(KeyboardEvent.KEY_DOWN, navigationKeyDownHandler);
|
||
tabChildren = false;
|
||
}
|
||
|
||
//--------------------------------------
|
||
// Properties
|
||
//--------------------------------------
|
||
|
||
/**
|
||
* @private (setter)
|
||
*/
|
||
override public function set height(ht:Number):void {_height = ht;}
|
||
|
||
/**
|
||
* Gets or sets the width
|
||
*/
|
||
override public function get width():Number {return _width;}
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//Contains an object for each button. The object contains the button and an
|
||
//array of listeners attached to the button
|
||
public var _buttons:Array = [];
|
||
|
||
/**
|
||
* @private
|
||
*/
|
||
//array containing buttons that can be used when the drawButtons method is called
|
||
private var _cachedButtons:Array = [];
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//Used to determine the x coordinate of buttons
|
||
protected var _left:Number = 0;
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//holds index of the object to have focus
|
||
protected var _focusIndex:int;
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//the button that currently has focus
|
||
protected var _focusButton:AutoSizeButton;
|
||
|
||
/**
|
||
* The amount of padding between buttons
|
||
*/
|
||
public var spacing:int;
|
||
|
||
/**
|
||
* The amount of padding between rows
|
||
*/
|
||
public var rowSpacing:int;
|
||
|
||
/**
|
||
* The maximum width of the component. Used to determine how many rows
|
||
* of buttons are necessary.
|
||
*/
|
||
public var maxWidth:int;
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//Number of buttons to be drawn.
|
||
protected var _length:uint;
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//Number of buttons loaded
|
||
protected var _buttonsLoaded:uint;
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//Array containing index for each row of buttons
|
||
protected var _rows:Array;
|
||
|
||
/**
|
||
* @private (protected)
|
||
*/
|
||
//Current index for the button rows
|
||
protected var _currentRow:uint;
|
||
|
||
/**
|
||
* Gets or sets the index of the button that has focus.
|
||
*/
|
||
public function get focusIndex():int
|
||
{
|
||
return _focusIndex;
|
||
}
|
||
|
||
/**
|
||
* @private (setter)
|
||
*/
|
||
public function set focusIndex(value:int):void
|
||
{
|
||
_focusIndex = value;
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
*/
|
||
private var defaultButtonStyles:Object = {};
|
||
|
||
//--------------------------------------
|
||
// Public Methods
|
||
//--------------------------------------
|
||
|
||
/**
|
||
* Draws and arranges buttons
|
||
*
|
||
* @param labels - an array of strings to be used as the text for the buttons
|
||
* @param listeners - an array of handler functions to be called on a button click
|
||
*/
|
||
public function drawButtons(labels:Array, listeners:Array):void
|
||
{
|
||
_currentRow = _buttonsLoaded = _left = _width = 0;
|
||
_rows = [];
|
||
_rows[_currentRow] = {};
|
||
_rows[_currentRow].buttons = [];
|
||
_rows[_currentRow].width = 0;
|
||
|
||
this.removeChildren();
|
||
this.setFocus();
|
||
_focusIndex = 0;
|
||
var cachedLen:Number = _cachedButtons.length;
|
||
var len:uint = _length = labels.length;
|
||
for(var i:uint = 0; i < len; i++)
|
||
{
|
||
var newButton:AutoSizeButton;
|
||
var label:String = labels[i];
|
||
if(i < cachedLen)
|
||
{
|
||
newButton = _cachedButtons[i];
|
||
newButton.textField.text = "";
|
||
newButton.visible = true;
|
||
newButton.label = newButton.name = label;
|
||
}
|
||
else
|
||
{
|
||
newButton = new AutoSizeButton();
|
||
newButton.height = _height;
|
||
this.addChild(newButton);
|
||
newButton.addEventListener(ComponentEvent.LABEL_CHANGE, buttonChangeHandler);
|
||
newButton.label = newButton.name = label;
|
||
newButton.useHandCursor = true;
|
||
_cachedButtons.push(newButton);
|
||
}
|
||
|
||
var listlen:uint = listeners.length;
|
||
for(var j:uint = 0; j < listlen; j++)
|
||
{
|
||
newButton.addEventListener(MouseEvent.CLICK, listeners[j]);
|
||
}
|
||
|
||
newButton.drawNow();
|
||
newButton.tabIndex = i+1;
|
||
_buttons.push({button:newButton, listeners:listeners});
|
||
|
||
}
|
||
this.setFocusButton();
|
||
this.setButtonStyles();
|
||
}
|
||
|
||
|
||
/**
|
||
* Removes buttons
|
||
*/
|
||
public function removeChildren():void
|
||
{
|
||
_buttons.forEach(disableButtons);
|
||
_buttons = [];
|
||
}
|
||
|
||
/**
|
||
* Positions each button after it has been resized. Creates multiple rows if a
|
||
* single row of buttons will exceed the maximum width.
|
||
*
|
||
* @param evnt - event fired from buttons after it has been redrawn
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
public function buttonChangeHandler(evnt:ComponentEvent):void
|
||
{
|
||
var thisButton:AutoSizeButton = evnt.target as AutoSizeButton;
|
||
if(_left + thisButton.width <= maxWidth)
|
||
{
|
||
thisButton.x = _left;
|
||
_left += thisButton.width + spacing;
|
||
_rows[_currentRow].width = _left - spacing;
|
||
_rows[_currentRow].buttons.push(thisButton);
|
||
_width = Math.max(_width, _rows[_currentRow].width);
|
||
thisButton.y = (thisButton.height * _currentRow) + (rowSpacing * _currentRow);
|
||
}
|
||
else
|
||
{
|
||
_left = thisButton.x = 0;
|
||
_currentRow++;
|
||
_rows[_currentRow] = {};
|
||
_rows[_currentRow].buttons = [];
|
||
_rows[_currentRow].width = thisButton.width;
|
||
_rows[_currentRow].buttons.push(thisButton);
|
||
thisButton.y = (thisButton.height * _currentRow) + (rowSpacing * _currentRow);
|
||
_width = Math.max(thisButton.width, _width);
|
||
_left += thisButton.width + spacing;
|
||
}
|
||
_buttonsLoaded++;
|
||
if(_buttonsLoaded == _length)
|
||
{
|
||
var len:uint = _rows.length;
|
||
if(len > 1)
|
||
{
|
||
_rows.forEach(centerButtonRow);
|
||
_height = thisButton.y + thisButton.height;
|
||
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
|
||
}
|
||
else
|
||
{
|
||
this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Sets the focus for the correct button.
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
public function setFocusButton():void
|
||
{
|
||
_focusButton = _buttons[_focusIndex].button;
|
||
_focusButton.setFocus();
|
||
_focusButton.drawFocus(true);
|
||
}
|
||
|
||
/*
|
||
* Set the index to have focus and call the <code>setFocusButton</code> function
|
||
*
|
||
* @param decrem indicates whether to increase or decrease the focus index
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
public function setFocusIndex(decrem:Boolean):void
|
||
{
|
||
var len:int = _buttons.length - 1;
|
||
if(decrem)
|
||
{
|
||
if(_focusIndex == 0)
|
||
{
|
||
_focusIndex = len;
|
||
}
|
||
else
|
||
{
|
||
_focusIndex--;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(_focusIndex == len)
|
||
{
|
||
_focusIndex = 0;
|
||
}
|
||
else
|
||
{
|
||
_focusIndex++;
|
||
}
|
||
}
|
||
setFocusButton();
|
||
}
|
||
|
||
/**
|
||
* Sets the styles of the buttons
|
||
*/
|
||
public function setButtonStyle(name:String, style:Object):void
|
||
{
|
||
defaultButtonStyles[name] = style;
|
||
if(_buttons != null && _buttons.length > 0)
|
||
{
|
||
for(var i:int = 0; i < _buttons.length; i++)
|
||
{
|
||
(_buttons[i].button as UIComponent).setStyle(name, style);
|
||
}
|
||
}
|
||
}
|
||
|
||
//--------------------------------------
|
||
// Protected Methods
|
||
//--------------------------------------
|
||
|
||
/**
|
||
* @private (protected)
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
//Adjusts the x coordinate for each button in a row
|
||
//Called when there are multiple rows so that the buttons will be centered
|
||
protected function centerButtonRow(element:*, index:Number, arr:Array):void
|
||
{
|
||
var wid:uint = element.width;
|
||
var buttons:Array = element.buttons;
|
||
for(var i:uint = 0; i < buttons.length;i++)
|
||
{
|
||
buttons[i].x += Math.round((_width - wid)/2);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @private (protected)
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
//Remove event listeners from each button
|
||
//Set visibility to false for each button
|
||
protected function disableButtons(element:*, index:Number, arr:Array):void
|
||
{
|
||
var button:AutoSizeButton = element.button;
|
||
var listeners:Array = element.listeners;
|
||
var len:uint = listeners.length;
|
||
for(var i:uint = 0; i < len; i++)
|
||
{
|
||
button.removeEventListener(MouseEvent.CLICK, listeners[i]);
|
||
}
|
||
button.visible = false;
|
||
}
|
||
|
||
/**
|
||
* @private (protected)
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
//If the right arrow is pressed, pass a value of false to the setFocusIndex function
|
||
//If the left arrow is pressed, pass a value of true to the setFocusIndex function
|
||
//If the enter key is pressed, dispatch a click event from the _focusButton
|
||
protected function navigationKeyDownHandler(evnt:KeyboardEvent):void
|
||
{
|
||
switch(evnt.keyCode)
|
||
{
|
||
case Keyboard.RIGHT :
|
||
setFocusIndex(false);
|
||
break;
|
||
case Keyboard.LEFT :
|
||
setFocusIndex(true);
|
||
break;
|
||
|
||
case Keyboard.ENTER :
|
||
_focusButton.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* @private (protected)
|
||
*
|
||
* @langversion 3.0
|
||
* @playerversion Flash 9.0.28.0
|
||
*/
|
||
//On the keyFocusChange event, prevent the default handling of the tab key
|
||
protected function keyFocusChangeHandler(evnt:FocusEvent):void
|
||
{
|
||
if(evnt.keyCode == Keyboard.TAB)
|
||
{
|
||
evnt.preventDefault();
|
||
setFocusIndex(evnt.shiftKey)
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
* Copies button styles to a button
|
||
*/
|
||
private function setButtonStyles():void
|
||
{
|
||
var len:int = _buttons.length;
|
||
for(var i:int = 0; i < len; i++)
|
||
{
|
||
for(var n:String in defaultButtonStyles)
|
||
{
|
||
(_buttons[i].button as UIComponent).setStyle(n, defaultButtonStyles[n]);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
*/
|
||
override protected function draw():void
|
||
{
|
||
setButtonStyles();
|
||
}
|
||
|
||
}
|
||
} |