Last active
August 29, 2015 13:56
-
-
Save nicholasdunbar/8797771 to your computer and use it in GitHub Desktop.
Example of how to use and customize the Yahoo! Astra tree menu for ActionScript 3.0 (AS3)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Astra depends on some component libraries. | |
//For instructions on how to set up go to the following URL | |
//http://www.actionscript-flash-guru.com/blog/19-tree-menu-with-actionscript-as3.php | |
//set up the tree | |
import TreeCustom;var mytree:TreeCustom = new TreeCustom(); | |
mytree.setSize(500,200); | |
this.addChild(my tree); | |
mytree.init(); | |
//multi purpose add a node to the tree function | |
//param 1 - this is main text of the tree node | |
//param 2 - this is the class name of the symbol in the library to use as an icon _iconFunctionCustom in CustomTree is what determines the icon for the list element in the Tree if you use nothing it resumes to default operation | |
//param 3 - an array of lines that you might want to include under the item | |
//param 4 - text that right justifies its self to the end of the tree item it is a clickable link and will trigger the link in the following: | |
//textFieldRight.htmlText = "<a href='test.html'> "+_data.data.endText+" </a> "; | |
//in TreeCellRenderCustom.as | |
mytree.addCustomItem( "This is example 1 of an item in the list","ThisIsASymbolInTheLibrary",["this is sub node 1","this is sub node 2"],"this is text on the end"); | |
//this creates a closed parent node or branch node that | |
//encapsulates any subsequent nodes added under this | |
node.mytree.group("click to open group"); | |
//this adds a leaf node or a node with | |
leafsmytree.addCustomItem("This is example 2 of an item in the list","",["this is sub node 1","this is sub node 2"]); | |
//this close up the node "click to open group" and any subsequent | |
//additions are added at the same level as the parent node "click to open group" | |
mytree.groupEnd(); | |
mytree.addCustomItem("This is example 3 of an item in the list", "", ["this is sub node 1","this is sub node 2"]); | |
mytree.addLeaf("new item",""); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 { | |
import com.yahoo.astra.fl.controls.Tree; | |
import com.yahoo.astra.fl.controls.treeClasses.TreeDataProvider; | |
import com.yahoo.astra.fl.controls.treeClasses.TNode; | |
import com.yahoo.astra.fl.controls.treeClasses.LeafNode; | |
import com.yahoo.astra.fl.controls.treeClasses.BranchNode; | |
import com.yahoo.astra.fl.controls.treeClasses.RootNode; | |
import fl.controls.ButtonLabelPlacement; | |
import fl.controls.listClasses.ListData; | |
import fl.controls.listClasses.ICellRenderer; | |
//import com.yahoo.astra.fl.controls.treeClasses.LabelButton; | |
import fl.controls.LabelButton; | |
import fl.events.ComponentEvent; | |
import fl.core.UIComponent; | |
import flash.events.Event; | |
import flash.events.MouseEvent; | |
import flash.events.TextEvent; | |
import flash.text.TextField; | |
import flash.text.TextFieldType; | |
import flash.text.TextFieldAutoSize; | |
import flash.text.TextFormat; | |
import flash.text.StyleSheet; | |
import fl.core.InvalidationType; | |
import flash.display.Sprite; | |
import flash.display.DisplayObject; | |
import flash.display.MovieClip; | |
//-------------------------------------- | |
// Styles | |
//-------------------------------------- | |
/** | |
* Name of the class to use as the skin for the icon associated | |
* with a closed branch of the tree. | |
* | |
* @default TreeCellRenderer_closedBranchIcon | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="closedBranchIcon", type="Class")] | |
/** | |
* Name of the class to use as the skin for the icon associated | |
* with an open branch of the tree. | |
* | |
* @default TreeCellRenderer_openBranchIcon | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="openBranchIcon", type="Class")] | |
/** | |
* Name of the class to use as the skin for the icon associated | |
* with a leaf node of the tree. | |
* | |
* @default TreeCellRenderer_leafIcon | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="leafIcon", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:upSkin | |
* | |
* @default CellRenderer_upSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="upSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:downSkin | |
* | |
* @default CellRenderer_downSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="downSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:overSkin | |
* | |
* @default CellRenderer_overSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="overSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:disabledSkin | |
* | |
* @default CellRenderer_disabledSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="disabledSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:selectedDisabledSkin | |
* | |
* @default CellRenderer_selectedDisabledSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="selectedDisabledSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:selectedUpSkin | |
* | |
* @default CellRenderer_selectedUpSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="selectedUpSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:selectedDownSkin | |
* | |
* @default CellRenderer_selectedDownSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="selectedDownSkin", type="Class")] | |
/** | |
* @copy fl.controls.LabelButton#style:selectedOverSkin | |
* | |
* @default CellRenderer_selectedOverSkin | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="selectedOverSkin", type="Class")] | |
/** | |
* @copy fl.core.UIComponent#style:textFormat | |
* | |
* @default null | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="textFormat", type="flash.text.TextFormat")] | |
/** | |
* @copy fl.core.UIComponent#style:disabledTextFormat | |
* | |
* @default null | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="disabledTextFormat", type="flash.text.TextFormat")] | |
/** | |
* @copy fl.controls.LabelButton#style:textPadding | |
* | |
* @default 5 | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="textPadding", type="Number", format="Length")] | |
/** | |
* Number of pixels to use as offset when rendering nested tree nodes. | |
* | |
* @default 5 | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="nodeIndent", type="Number", format="Length")] | |
/** | |
* Left margin width in pixels | |
* | |
* @default 5 | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
[Style(name="leftMargin", type="Number", format="Length")] | |
//-------------------------------------- | |
// Class description | |
//-------------------------------------- | |
/** | |
* The TreeCellRenderer class defines methods and properties for | |
* Tree component to manipulate and display custom | |
* cell content in each of its rows. TreeCellRenderer relies on | |
* properties contained in the TreeDataProvider objects to set | |
* appropriate icons and offsets for individual cells. | |
* The TreeCellRenderer implements ICellRenderer and extends | |
* the LabelButton. | |
* | |
* @see com.yahoo.astra.fl.controls.treeClasses.TreeDataProvider | |
* @see ICellRenderer | |
* @see fl.controls.LabelButton | |
* | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public class TreeCellRendererCustom extends LabelButton implements ICellRenderer { | |
/** | |
* @private (protected) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
protected var _listData:ListData; | |
/** | |
* @private (protected) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
protected var _data:Object; | |
/** | |
* @private (protected) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
protected static var _widthOverride:Number = 0; | |
/** | |
* @private (protected) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
protected static var _heightOverride:Number = 0; | |
protected var textFieldRight:TextField; | |
public static const NODE_INDENT:uint = 20; | |
/** | |
* Creates a new TreeCellRenderer instance. | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public function TreeCellRendererCustom():void { | |
super(); | |
toggle = true; | |
focusEnabled = false; | |
this.addEventListener(MouseEvent.CLICK, handleClickEvent, false, 0, true); | |
} | |
/*public function get iconGet():DisplayObject{ | |
return icon; | |
}*/ | |
public function destroy():void{ | |
if (this.hasEventListener(MouseEvent.CLICK)){ | |
this.removeEventListener(MouseEvent.CLICK, handleClickEvent); | |
} else { | |
trace("yo it don have da listener"); | |
} | |
} | |
private function handleClickEvent(evt:MouseEvent) : void { | |
var currentNode:TNode = data as TNode; | |
if (this.icon != null && currentNode is BranchNode && | |
this.icon.x <= this.mouseX && | |
this.mouseX <= (this.icon.x + this.icon.width) && | |
this.icon.y <= this.mouseY && | |
this.mouseY <= (this.icon.y + this.icon.height)) { | |
evt.stopImmediatePropagation(); | |
if (currentNode.isOpen()) { | |
currentNode.closeNode(); | |
} else { | |
currentNode.openNode(); | |
} | |
} else if (this.mouseX >= (width-textFieldRight.width-30) && | |
0 <= this.mouseY && | |
this.mouseY <= (0 + this.height) && | |
this._data.data.endText != null && | |
this._data.data.endText.length > 0){ | |
trace("you clicked on "+this._data.data.endText); | |
evt.stopImmediatePropagation(); | |
} | |
} | |
/** | |
* @private | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
private static var defaultStyles:Object = {upSkin:"TreeCellRenderer_upSkin",downSkin:"TreeCellRenderer_downSkin",overSkin:"TreeCellRenderer_overSkin", | |
disabledSkin:"TreeCellRenderer_disabledSkin", | |
selectedDisabledSkin:"TreeCellRenderer_selectedDisabledSkin", | |
selectedUpSkin:"TreeCellRenderer_selectedUpSkin",selectedDownSkin:"TreeCellRenderer_selectedDownSkin",selectedOverSkin:"TreeCellRenderer_selectedOverSkin", | |
closedBranchIcon:"TreeCellRenderer_closedBranchIcon", | |
openBranchIcon:"TreeCellRenderer_openBranchIcon", | |
leafIcon:"TreeCellRenderer_leafIcon", | |
textFormat:null, | |
disabledTextFormat:null, | |
embedFonts:null, | |
textPadding:5, | |
nodeIndent:5, | |
leftMargin:5}; | |
/** | |
* @copy fl.core.UIComponent#getStyleDefinition() | |
* | |
* @includeExample ../../core/examples/UIComponent.getStyleDefinition.1.as -noswf | |
* | |
* @see fl.core.UIComponent#getStyle() | |
* @see fl.core.UIComponent#setStyle() | |
* @see fl.managers.StyleManager | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public static function getStyleDefinition():Object { | |
return mergeStyles(defaultStyles, LabelButton.getStyleDefinition()); | |
} | |
public static function setOverrideSize(width:Number, height:Number):void { | |
_widthOverride = width; | |
_heightOverride = height; | |
} | |
/** | |
* Specifies the dimensions at which the data should be rendered. | |
* These dimensions affect both the data and the cell that contains it; | |
* the cell renderer uses them to ensure that the data fits the cell and | |
* does not bleed into adjacent cells. | |
* | |
* @param width The width of the object, in pixels. | |
* | |
* @param height The height of the object, in pixels. | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
override public function setSize(width:Number, height:Number):void { | |
if (_widthOverride != 0){ | |
width = _widthOverride; | |
} | |
if (_heightOverride != 0){ | |
height = _heightOverride; | |
} | |
super.setSize(width, height); | |
} | |
/** | |
* @copy fl.controls.listClasses.ICellRenderer#listData | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public function get listData():ListData { | |
return _listData; | |
} | |
/** | |
* @private (setter) | |
* When listData is set, we determine the appropriate icon to use | |
* with the particular type of Tree node (open branch, closed branch, | |
* or leaf). | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public function set listData(value:ListData):void { | |
_listData = value; | |
label = _listData.label; | |
var parentTree:Tree = _listData.owner as Tree; | |
if (data.nodeType == TreeDataProvider.BRANCH_NODE) { | |
if (data.nodeState == TreeDataProvider.OPEN_NODE) { | |
if (parentTree.iconFunction != null) { | |
setStyle("icon", parentTree.iconFunction(data)); | |
} else if (parentTree.openBranchIconField != null && data[parentTree.openBranchIconField] != null) { | |
setStyle("icon", data[parentTree.openBranchIconField]); | |
} else { | |
setStyle("icon", getStyleValue("openBranchIcon")); | |
} | |
} else { | |
if (parentTree.iconFunction != null) { | |
setStyle("icon", parentTree.iconFunction(data)); | |
} else if (parentTree.closedBranchIconField != null && data[parentTree.closedBranchIconField] != null) { | |
setStyle("icon", data[parentTree.closedBranchIconField]); | |
} else { | |
setStyle("icon", getStyleValue("closedBranchIcon")); | |
} | |
} | |
} | |
else { | |
if (parentTree.iconFunction != null) { | |
setStyle("icon", parentTree.iconFunction(data)); | |
} else if (parentTree.openBranchIconField != null && data[parentTree.leafIconField] != null) { | |
setStyle("icon", data[parentTree.leafIconField]); | |
} else { | |
setStyle("icon", getStyleValue("leafIcon")); | |
} | |
} | |
} | |
override protected function drawIcon():void { | |
var oldIcon:DisplayObject = icon; | |
var styleName:String = (enabled) ? mouseState : "disabled"; | |
if (selected) { | |
styleName = "selected"+styleName.substr(0,1).toUpperCase()+styleName.substr(1); | |
} | |
styleName += "Icon"; | |
var iconStyle:Object = getStyleValue(styleName); | |
if (iconStyle == null) { | |
// try the default icon: | |
iconStyle = getStyleValue("icon"); | |
} | |
if (iconStyle != null) { | |
icon = getDisplayObjectInstance(iconStyle); | |
} | |
if (icon != null) { | |
addChildAt(icon,1); | |
} | |
if (oldIcon != null && oldIcon != icon) { | |
removeChild(oldIcon); | |
} | |
} | |
override protected function draw():void { | |
if (textField.htmlText != _label) { | |
label = _label; | |
} | |
if (isInvalid(InvalidationType.STYLES,InvalidationType.STATE)) { | |
drawBackground(); | |
drawIcon(); | |
drawTextFormat(); | |
invalidate(InvalidationType.SIZE,false); | |
} | |
if (isInvalid(InvalidationType.SIZE)) { | |
drawLayout(); | |
} | |
if (isInvalid(InvalidationType.SIZE,InvalidationType.STYLES)) { | |
if (isFocused && focusManager.showFocusIndicator) { drawFocus(true); } | |
} | |
validate(); // because we're not calling super.draw | |
} | |
override protected function drawBackground():void { | |
var styleName:String = (enabled) ? mouseState : "disabled"; | |
var bgParentMc:TreeCellRendererCustom; | |
if (selected) { styleName = "selected"+styleName.substr(0,1).toUpperCase()+styleName.substr(1); } | |
styleName += "Skin"; | |
var bg:DisplayObject = background; | |
background = getDisplayObjectInstance(getStyleValue(styleName)); | |
addChildAt(background, 0); | |
if (bg != null && bg != background) { | |
bgParentMc = bg.parent as TreeCellRendererCustom; | |
bgParentMc.graphics.clear(); | |
removeChild(bg); | |
} | |
} | |
override public function set label(value:String):void { | |
_label = value; | |
if (textField.htmlText != _label) { | |
textField.htmlText = _label; | |
dispatchEvent(new ComponentEvent(ComponentEvent.LABEL_CHANGE)); | |
} | |
invalidate(InvalidationType.SIZE); | |
invalidate(InvalidationType.STYLES); | |
} | |
override protected function configUI():void { | |
super.configUI(); | |
//WHERE YOU LEFT OFF: add a text field to the far right | |
textFieldRight = new TextField(); | |
textFieldRight.autoSize = TextFieldAutoSize.RIGHT; | |
textFieldRight.type = TextFieldType.DYNAMIC; | |
textFieldRight.selectable = true; | |
var style:StyleSheet = new StyleSheet(); | |
var hover:Object = new Object(); | |
//hover.fontWeight = "bold"; | |
hover.color = "#0000FF"; | |
var link:Object = new Object(); | |
link.textDecoration= "underline"; | |
link.color = "#FF0000"; | |
var active:Object = new Object(); | |
//active.fontWeight = "bold"; | |
active.color = "#FF0000"; | |
var visited:Object = new Object(); | |
visited.color = "#cc0099"; | |
visited.textDecoration= "underline"; | |
style.setStyle("a:link", link); | |
style.setStyle("a:hover", hover); | |
style.setStyle("a:active", active); | |
style.setStyle(".visited", visited); | |
textFieldRight.styleSheet = style; | |
addChild(textFieldRight); | |
// | |
textField.styleSheet = new StyleSheet(); | |
textField.autoSize = TextFieldAutoSize.LEFT; | |
} | |
override protected function drawTextFormat():void { | |
// Apply a default textformat | |
/* | |
var uiStyles:Object = UIComponent.getStyleDefinition(); | |
var defaultTF:TextFormat = enabled ? uiStyles.defaultTextFormat as TextFormat : uiStyles.defaultDisabledTextFormat as TextFormat; | |
//textField.setTextFormat(defaultTF); | |
var tf:TextFormat = getStyleValue(enabled?"textFormat":"disabledTextFormat") as TextFormat; | |
if (tf != null) { | |
//textField.setTextFormat(tf); | |
} else { | |
tf = defaultTF; | |
} | |
//textField.defaultTextFormat = tf; | |
setEmbedFont(); | |
*/ | |
} | |
/** | |
* @copy fl.controls.listClasses.ICellRenderer#data | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public function get data():Object { | |
return _data; | |
} | |
/** | |
* @private (setter) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
public function set data(value:Object):void { | |
_data = value; | |
} | |
/** | |
* @copy fl.controls.listClasses.ICellRenderer#selected | |
* | |
* @default false | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
override public function get selected():Boolean { | |
return super.selected; | |
} | |
/** | |
* @private (setter) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
override public function set selected(value:Boolean):void { | |
super.selected = value; | |
} | |
/** | |
* @private (protected) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
override protected function toggleSelected(event:MouseEvent):void { | |
// don't set selected or dispatch change event. | |
} | |
/** | |
* @private (protected) | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
override protected function drawLayout():void { | |
var textPadding:Number = Number(getStyleValue("textPadding")); | |
var nodeIndent:Number = Number(getStyleValue("nodeIndent")); | |
var leftMargin:Number = Number(getStyleValue("leftMargin")); | |
var indentation:int = (_data.nodeLevel*NODE_INDENT); | |
var textFieldX:Number = 0; | |
var renderBoxesLimit:int = 0; | |
var bgMc:MovieClip; | |
var bgParentMc:TreeCellRendererCustom; | |
// Align icon and add the indent derived from node's level | |
if (icon != null) { | |
if (_data.data.type == "MoreInfo" || _data.data.type == "MoreDoneInfo"){ | |
icon.x = (leftMargin + data.nodeLevel * nodeIndent)-NODE_INDENT; | |
icon.visible = false; | |
} else { | |
icon.x = leftMargin + data.nodeLevel * nodeIndent; | |
} | |
icon.y = Math.round( (height-icon.height)>>1 ); | |
textFieldX = icon.x + icon.width + textPadding; | |
} | |
// Align text and add the indent derived from node's level | |
if (label.length > 0) { | |
textField.visible = true; | |
var textWidth:Number = Math.max(0, width - textFieldX - textPadding*2); | |
textField.width = textWidth; | |
textField.height = textField.textHeight + 4; | |
textField.x = textFieldX; | |
textField.y = Math.round((height-textField.height)>>1); | |
} else { | |
textField.visible = false; | |
} | |
//set background state | |
bgMc = background as MovieClip; | |
bgParentMc = bgMc.parent as TreeCellRendererCustom; | |
if (_data.data.type == "Group" && _data.nodeType == TreeDataProvider.BRANCH_NODE){ | |
bgMc.gotoAndStop("branch"); | |
} | |
if (_data.data.type == "Done"){ | |
textField.x = indentation-NODE_INDENT+5; | |
background.width = width-indentation+NODE_INDENT; | |
background.x = indentation-NODE_INDENT; | |
bgMc.visible = false; | |
bgParentMc.graphics.lineStyle(1, 0xD7D7D7); | |
bgParentMc.graphics.moveTo(background.x, 0); ///This is where we start drawing | |
bgParentMc.graphics.lineTo(background.x, height); | |
bgParentMc.graphics.lineTo(width, height); | |
renderBoxesLimit = 1; | |
} else if (_data.data.type == "DoneInfo"){ | |
bgParentMc.graphics.lineStyle(1, 0xD7D7D7); | |
bgParentMc.graphics.moveTo(indentation-NODE_INDENT, 0); ///This is where we start drawing | |
bgParentMc.graphics.lineTo(indentation-NODE_INDENT, height); | |
bgParentMc.graphics.lineTo(width, height); | |
textField.selectable = true; | |
if (_data.nodeType == TreeDataProvider.LEAF_NODE){ | |
background.visible = false; | |
if (_data.nodeLevel == 1){ | |
renderBoxesLimit = 1; | |
} | |
} | |
} else if (_data.data.type == "MoreDoneInfo"){ | |
bgParentMc.graphics.lineStyle(1, 0xD7D7D7); | |
bgParentMc.graphics.moveTo(indentation, 0); ///This is where we start drawing | |
bgParentMc.graphics.lineTo(indentation, height); | |
bgParentMc.graphics.lineTo(width, height); | |
textField.selectable = true; | |
if (_data.nodeType == TreeDataProvider.LEAF_NODE){ | |
background.visible = false; | |
if (_data.nodeLevel == 1){ | |
renderBoxesLimit = 1; | |
} | |
} | |
} else if (_data.data.type == "MoreInfo"){ | |
bgParentMc.graphics.lineStyle(1, 0xD7D7D7); | |
bgParentMc.graphics.moveTo(indentation, 0); ///This is where we start drawing | |
bgParentMc.graphics.lineTo(indentation, height); | |
textField.selectable = true; | |
//bgParentMc.graphics.lineTo(width, height); | |
if (_data.nodeType == TreeDataProvider.LEAF_NODE){ | |
background.visible = false; | |
if (_data.nodeLevel == 1){ | |
renderBoxesLimit = 1; | |
} | |
} | |
} else if (_data.data.type == "SquareNoClick"){ | |
bgParentMc.graphics.lineStyle(1, 0xD7D7D7); | |
bgParentMc.graphics.moveTo(indentation, 0); ///This is where we start drawing | |
bgParentMc.graphics.lineTo(indentation, height); | |
bgParentMc.graphics.lineTo(width, height); | |
bgParentMc.graphics.lineTo(width, 0); | |
bgParentMc.graphics.lineTo(indentation, 0); | |
textField.selectable = true; | |
//bgParentMc.graphics.lineTo(width, height); | |
if (_data.nodeType == TreeDataProvider.LEAF_NODE){ | |
background.visible = false; | |
if (_data.nodeLevel == 1){ | |
renderBoxesLimit = 1; | |
} | |
} | |
} else { | |
// Size background | |
//background.width = textField.width+textFieldX+leftMargin+( data.nodeLevel * nodeIndent); | |
background.width = width-indentation; | |
background.x = indentation; | |
if (_data.nodeType == TreeDataProvider.LEAF_NODE){ | |
background.visible = false; | |
if (_data.nodeLevel == 1){ | |
renderBoxesLimit = 1; | |
} | |
} | |
} | |
background.height = height; | |
//draw box lines | |
if (_data.nodeLevel > 0 && _data.data.type != "Empty"){ | |
bgParentMc.graphics.lineStyle(1, 0xD7D7D7); | |
//TEST: uncomment when you want to see what the lines that make the boxes look like | |
//bgParentMc.graphics.lineStyle(1, 0x000000); | |
for (var j:int = 0; j < _data.nodeLevel-renderBoxesLimit; j++){ | |
if (_data.label == "line0" && _data.nodeLevel == 1){ | |
var yourmom:int = 30; | |
} | |
bgParentMc.graphics.moveTo(j*NODE_INDENT,0); ///This is where we start drawing | |
bgParentMc.graphics.lineTo(j*NODE_INDENT, height); | |
} | |
} | |
if (_data.data.endText != null && _data.data.endText.length > 0){ | |
textFieldRight.visible = true; | |
textFieldRight.htmlText = "<a href='test.html'>"+_data.data.endText+"</a>"; | |
textFieldRight.x = width-textFieldRight.width-20; | |
} else { | |
textFieldRight.visible = false; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package { | |
//astra yahoo libs | |
import TreeCellRendererCustom; | |
import com.yahoo.astra.fl.controls.treeClasses.TreeDataProvider; | |
import com.yahoo.astra.fl.controls.Tree; | |
import com.yahoo.astra.fl.controls.treeClasses.TNode; | |
import com.yahoo.astra.fl.controls.treeClasses.LeafNode; | |
import com.yahoo.astra.fl.controls.treeClasses.BranchNode; | |
import com.yahoo.astra.fl.controls.treeClasses.RootNode; | |
//adobe libs | |
import fl.core.InvalidationType; | |
import fl.controls.ScrollPolicy; | |
import fl.data.DataProvider; | |
import fl.controls.listClasses.CellRenderer; | |
import fl.controls.listClasses.ICellRenderer; | |
import fl.controls.listClasses.ListData; | |
import fl.controls.ScrollPolicy; | |
import fl.controls.SelectableList; | |
import fl.core.InvalidationType; | |
import fl.core.UIComponent; | |
import fl.managers.IFocusManagerComponent; | |
import fl.events.DataChangeType; | |
import fl.events.DataChangeEvent; | |
import fl.events.ListEvent; | |
import fl.events.ScrollEvent; | |
//native libs | |
import flash.xml.XMLNode; | |
import flash.xml.XMLNodeType; | |
import flash.text.TextFormat; | |
import flash.text.TextField; | |
import flash.text.TextLineMetrics; | |
import flash.text.TextFieldAutoSize; | |
import flash.text.StyleSheet; | |
import flash.display.DisplayObject; | |
import flash.display.Sprite; | |
import flash.events.Event; | |
import flash.events.KeyboardEvent; | |
import flash.events.MouseEvent; | |
import flash.ui.Keyboard; | |
import flash.utils.Dictionary; | |
import flash.utils.describeType; | |
import flash.utils.getQualifiedClassName; | |
import flash.geom.Rectangle; | |
import flash.external.ExternalInterface; | |
public class TreeCustom extends Tree { | |
private var _isScrollSizeChanged:Boolean; | |
private var _scrollMaxWidthSize:Number; | |
private var _currentNumberOfGroups:uint; | |
private var _lastGroupNodeList:Array = new Array(); | |
private var _placeHolderNode:LeafNode; | |
private var _placeHolderNode1:LeafNode; | |
private var _cellRendererList:Array = new Array(); | |
public var isScrollToBottom:Boolean = true; | |
private static const NO_DATA:String = "no data"; | |
public function TreeCustom() { | |
//starting structure for the data provider | |
var dp:XML = <node label="Root node"></node>; | |
super(); | |
//uncomment this if you want to use calculate content width | |
this.useFixedHorizontalScrolling = false; | |
//use custom cell renderer | |
this.setStyle('cellRenderer', TreeCellRendererCustom); | |
this.setRendererStyle("nodeIndent", TreeCellRendererCustom.NODE_INDENT); | |
//this.setRendererStyle("nodeIndent", 20); | |
this.setRendererStyle("textPadding", 5); | |
this.enabled = true; | |
this.horizontalScrollPolicy = ScrollPolicy.AUTO; | |
this.horizontalLineScrollSize = 5; | |
this.allowMultipleSelection = true; | |
this.iconFunction = _iconFunctionCustom; | |
this.labelFunction = _labelFunctionCustom; | |
this.maxHorizontalScrollPosition = 0; | |
_scrollMaxWidthSize = 0; | |
this.dataProvider = new TreeDataProvider(dp); | |
} | |
public function init():void{ | |
var parentDp:TreeDataProvider = this.dataProvider as TreeDataProvider; | |
var rn:RootNode; | |
rn = parentDp.rootNode as RootNode; | |
_placeHolderNode1 = new LeafNode(parentDp); | |
_placeHolderNode1.label = "-"; | |
_placeHolderNode1.data = {type:"Empty"}; | |
rn.addChildNodeAt(_placeHolderNode1, rn.children.length); | |
_placeHolderNode = new LeafNode(parentDp); | |
_placeHolderNode.label = ""; | |
_placeHolderNode.data = {type:"Empty"}; | |
rn.addChildNodeAt(_placeHolderNode,rn.children.length); | |
} | |
public function addCustomItem(item:String, type:String, lines:Array = null, endTextStr:String = "", endLink:Object = null):void{ | |
var parentDp:TreeDataProvider = this.dataProvider as TreeDataProvider; | |
var parentGroupNode:BranchNode; | |
var bn:BranchNode = new BranchNode(parentDp); | |
var rn:RootNode; | |
var ln:LeafNode; | |
var i:uint; | |
var j:uint; | |
if (lines == null){ | |
lines = []; | |
} | |
var linesLength:uint; | |
var linesLength2:uint; | |
var linesArray:Array = limitStringLength(item); | |
//addChildNode | |
bn.label = linesArray.shift() as String; | |
if (endTextStr == NO_DATA+"."+NO_DATA){ | |
bn.data = {type:type}; | |
} else { | |
bn.data = {type:type, endText:endTextStr}; | |
} | |
if (_currentNumberOfGroups == 0){ | |
rn = parentDp.rootNode as RootNode; | |
rn.addChildNodeAt(bn, rn.children.length-2); | |
//rn.addChildNode(bn); | |
} else { | |
rn = parentDp.rootNode as RootNode; | |
parentGroupNode = _lastGroupNodeList[_lastGroupNodeList.length-1] as BranchNode; | |
//parentGroupNode.addChildNodeAt(bn, rn.children.length-2); | |
parentGroupNode.addChildNode(bn); | |
} | |
//bn.openNode(); | |
linesLength = linesArray.length; | |
for (i = 0; i < linesLength; i++){ | |
ln = new LeafNode(parentDp); | |
ln.label = linesArray[i]; | |
if (i == linesLength-1){ | |
ln.data = {type:"MoreDoneInfo"}; | |
} else { | |
ln.data = {type:"MoreInfo"}; | |
} | |
bn.addChildNode(ln); | |
} | |
linesLength = lines.length; | |
for (i = 0; i < linesLength; i++){ | |
ln = new LeafNode(parentDp); | |
linesArray = limitStringLength(lines[i]); | |
ln.label = linesArray.shift(); | |
linesLength2 = linesArray.length; | |
ln.data = {type:"SquareNoClick"}; | |
bn.addChildNode(ln); | |
for (j = 0; j<linesLength2; j++){ | |
ln = new LeafNode(parentDp); | |
ln.label = " "+linesArray[j]; | |
if (j == linesLength2-1){ | |
ln.data = {type:"MoreDoneInfo"}; | |
} else { | |
ln.data = {type:"MoreInfo"}; | |
} | |
bn.addChildNode(ln); | |
} | |
} | |
if (dataProvider != null && isScrollToBottom){ | |
scrollToIndex(dataProvider.length); | |
} | |
} | |
override public function removeAll():void{ | |
super.removeAll(); | |
this.dataProvider.removeAll(); | |
//starting structure for the data provider | |
var dp:XML = <node label="Root node"></node>; | |
this.dataProvider = new TreeDataProvider(dp); | |
var parentDp:TreeDataProvider = this.dataProvider as TreeDataProvider; | |
var rn:RootNode; | |
rn = parentDp.rootNode as RootNode; | |
_placeHolderNode1 = new LeafNode(parentDp); | |
_placeHolderNode1.label = "-"; | |
_placeHolderNode1.data = {type:"Empty"}; | |
rn.addChildNodeAt(_placeHolderNode1, rn.children.length); | |
_placeHolderNode = new LeafNode(parentDp); | |
_placeHolderNode.label = ""; | |
_placeHolderNode.data = {type:"Empty"}; | |
rn.addChildNodeAt(_placeHolderNode,rn.children.length); | |
} | |
public function group(groupTitle:String):void{ | |
var parentDp:TreeDataProvider = this.dataProvider as TreeDataProvider; | |
var bn:BranchNode = new BranchNode(parentDp); | |
var parentGroupNode:BranchNode; | |
var rn:RootNode; | |
bn.label = groupTitle; | |
bn.data = {type:"Group"}; | |
if (_currentNumberOfGroups == 0){ | |
rn = parentDp.rootNode as RootNode; | |
rn.addChildNodeAt(bn, rn.children.length-2); | |
//rn.addChildNode(bn); | |
} else { | |
parentGroupNode = _lastGroupNodeList[_lastGroupNodeList.length-1] as BranchNode; | |
parentGroupNode.addChildNode(bn); | |
} | |
_currentNumberOfGroups++; | |
_lastGroupNodeList.push(bn); | |
} | |
public function groupEnd():void{ | |
var parentDp:TreeDataProvider = this.dataProvider as TreeDataProvider; | |
var bn:BranchNode; | |
var ln:LeafNode; | |
if (_currentNumberOfGroups != 0){ | |
_currentNumberOfGroups--; | |
bn = _lastGroupNodeList.pop() as BranchNode; | |
ln = new LeafNode(parentDp); | |
ln.label = "done"; | |
ln.data = {type:"Done"}; | |
bn.addChildNode(ln); | |
} | |
} | |
function limitStringLength(s:String):Array{ | |
var textString:String = s; | |
var dummyTxt:TextField = new TextField(); | |
var linesOnEachArray:Array = new Array(); | |
dummyTxt.styleSheet = new StyleSheet(); | |
dummyTxt.autoSize = TextFieldAutoSize.NONE; | |
dummyTxt.width = 800; | |
dummyTxt.multiline = true; | |
dummyTxt.wordWrap = true; | |
dummyTxt.htmlText = textString; | |
for (var i:uint; i < dummyTxt.numLines; i++){ | |
linesOnEachArray.push( dummyTxt.getLineText(i) ); | |
} | |
return linesOnEachArray; | |
} | |
public function addLeaf(item:String, type:String):void{ | |
var parentDp:TreeDataProvider = this.dataProvider as TreeDataProvider; | |
var parentGroupNode:BranchNode; | |
var rn:RootNode; | |
var ln:LeafNode = new LeafNode(parentDp); | |
var i:uint = 0; | |
ln.label = item; | |
ln.data = {type:""+type}; | |
if (_currentNumberOfGroups == 0){ | |
rn = parentDp.rootNode as RootNode; | |
rn.addChildNodeAt(ln, rn.children.length-2); | |
} else { | |
rn = parentDp.rootNode as RootNode; | |
parentGroupNode = _lastGroupNodeList[_lastGroupNodeList.length-1] as BranchNode; | |
parentGroupNode.addChildNode(ln); | |
} | |
} | |
private function _iconFunctionCustom(data:Object):String { | |
if (data.data.type == "ThisIsASymbolInTheLibrary") { | |
return ("ThisIsASymbolInTheLibrary"); | |
} if (data.data.type == "Empty") { | |
return ""; | |
} else if (data.data.type == "Done") { | |
return ""; | |
}else if (data.nodeType == TreeDataProvider.LEAF_NODE) { | |
return ("TreeCellRenderer_leafIcon"); | |
} else if (data.nodeType == TreeDataProvider.BRANCH_NODE) { | |
if (data.nodeState == TreeDataProvider.OPEN_NODE) { | |
return "TreeCellRenderer_openBranchIcon"; | |
} | |
else { | |
return "TreeCellRenderer_closedBranchIcon"; | |
} | |
} | |
return ""; | |
} | |
private function _labelFunctionCustom(data:Object):String{ | |
var textString:String = data.label; | |
var maxHorizontalPixles:Number; | |
var textMetrics:TextLineMetrics; | |
var dummyTxt:TextField = new TextField(); | |
dummyTxt.styleSheet = new StyleSheet(); | |
dummyTxt.htmlText = ""; | |
dummyTxt.htmlText = textString; | |
textMetrics = dummyTxt.getLineMetrics(0); | |
maxHorizontalPixles = textMetrics.width+(TreeCellRendererCustom.NODE_INDENT*data.nodeLevel)+60; | |
if (data.data.endText != null){ | |
dummyTxt.htmlText = ""; | |
dummyTxt.htmlText = data.data.endText; | |
textMetrics = dummyTxt.getLineMetrics(0); | |
maxHorizontalPixles += textMetrics.width; | |
} | |
if (_scrollMaxWidthSize < maxHorizontalPixles){ | |
_isScrollSizeChanged = true; | |
_scrollMaxWidthSize = maxHorizontalPixles; | |
} | |
return textString; | |
} | |
override protected function validate():void { | |
var i:int = 40; | |
super.validate(); | |
if (_isScrollSizeChanged){ | |
drawLayout(); | |
//drawList(); | |
//updateChildren(); | |
} | |
_isScrollSizeChanged = false; | |
} | |
override protected function calculateContentWidth():void { | |
var textString:String; | |
var maxHorizontalPixles:Number; | |
var textMetrics:TextLineMetrics; | |
var dummyTxt:TextField; | |
var item:Object; | |
if (_isScrollSizeChanged){ | |
contentWidth = _scrollMaxWidthSize; | |
if (width < contentWidth){ | |
TreeCellRendererCustom.setOverrideSize(contentWidth, 0); | |
super.setSize(width, height); | |
} else { | |
TreeCellRendererCustom.setOverrideSize(width, 0); | |
super.setSize(width, height); | |
} | |
//_scrollMaxWidthSize = 0; | |
} else { | |
// figure out what we have to check: | |
var startIndex:uint = Math.floor(this._verticalScrollPosition/this.rowHeight); | |
var endIndex:uint = Math.min(this.length,startIndex + this.rowCount+1); | |
for (var i:uint = startIndex; i<endIndex; i++) { | |
item = _dataProvider.getItemAt(i); | |
textString = item.label; | |
dummyTxt = new TextField(); | |
dummyTxt.styleSheet = new StyleSheet(); | |
dummyTxt.htmlText = ""; | |
dummyTxt.htmlText = textString; | |
textMetrics = dummyTxt.getLineMetrics(0); | |
maxHorizontalPixles = textMetrics.width+60; | |
if (item.data.endText != null){ | |
dummyTxt.htmlText = ""; | |
dummyTxt.htmlText = item.data.endText; | |
textMetrics = dummyTxt.getLineMetrics(0); | |
maxHorizontalPixles += textMetrics.width; | |
} | |
if (contentWidth < maxHorizontalPixles){ | |
//_isScrollSizeChanged = true; | |
contentWidth = maxHorizontalPixles; | |
if (width < contentWidth){ | |
TreeCellRendererCustom.setOverrideSize(contentWidth, 0); | |
super.setSize(width, height); | |
} else { | |
TreeCellRendererCustom.setOverrideSize(width, 0); | |
super.setSize(width, height); | |
} | |
trace("contentWidth : "+contentWidth); | |
} | |
} | |
} | |
} | |
override protected function drawList():void { | |
// List is very environmentally friendly, it reuses existing | |
// renderers for old data, and recycles old renderers for new data. | |
// set horizontal scroll: | |
listHolder.x = listHolder.y = contentPadding; | |
//var rect:Rectangle = listHolder.scrollRect; | |
//rect.x = _horizontalScrollPosition; | |
// set pixel scroll: | |
//rect.y = Math.floor(_verticalScrollPosition)%rowHeight; | |
//listHolder.scrollRect = rect; | |
listHolder.cacheAsBitmap = useBitmapScrolling; | |
// figure out what we have to render: | |
var startIndex:uint = Math.floor(_verticalScrollPosition/rowHeight); | |
var endIndex:uint = Math.min(length,startIndex + rowCount+1); | |
// these vars get reused in different loops: | |
var i:uint; | |
var item:Object; | |
var renderer:ICellRenderer; | |
// create a dictionary for looking up the new "displayed" items: | |
var itemHash:Dictionary = renderedItems = new Dictionary(true); | |
for (i=startIndex; i<endIndex; i++) { | |
itemHash[_dataProvider.getItemAt(i)] = true; | |
} | |
// find cell renderers that are still active, and make those that aren't active available: | |
var itemToRendererHash:Dictionary = new Dictionary(true); | |
while (activeCellRenderers.length > 0) { | |
renderer = activeCellRenderers.pop() as ICellRenderer; | |
item = renderer.data; | |
if (itemHash[item] == null || invalidItems[item] == true) { | |
availableCellRenderers.push(renderer); | |
} else { | |
itemToRendererHash[item] = renderer; | |
// prevent problems with duplicate objects: | |
invalidItems[item] = true; | |
} | |
list.removeChild(renderer as DisplayObject); | |
} | |
invalidItems = new Dictionary(true); | |
// draw cell renderers: | |
for (i=startIndex; i<endIndex; i++) { | |
var reused:Boolean = false; | |
item = _dataProvider.getItemAt(i); | |
if (itemToRendererHash[item] != null) { | |
// existing renderer for this item we can reuse: | |
reused = true; | |
renderer = itemToRendererHash[item]; | |
delete(itemToRendererHash[item]); | |
} else if (availableCellRenderers.length > 0) { | |
// recycle an old renderer: | |
renderer = availableCellRenderers.pop() as ICellRenderer; | |
} else { | |
// out of renderers, create a new one: | |
renderer = getDisplayObjectInstance(getStyleValue("cellRenderer")) as ICellRenderer; | |
var rendererSprite:Sprite = renderer as Sprite; | |
if (rendererSprite != null) { | |
rendererSprite.addEventListener(MouseEvent.CLICK,handleCellRendererClick,false,0,true); | |
_cellRendererList.push({obj:rendererSprite, eventStr: MouseEvent.CLICK, func:handleCellRendererClick}); | |
rendererSprite.addEventListener(MouseEvent.ROLL_OVER,handleCellRendererMouseEvent,false,0,true); | |
_cellRendererList.push({obj:rendererSprite, eventStr: MouseEvent.ROLL_OVER, func:handleCellRendererMouseEvent}); | |
rendererSprite.addEventListener(MouseEvent.ROLL_OUT,handleCellRendererMouseEvent,false,0,true); | |
_cellRendererList.push({obj:rendererSprite, eventStr: MouseEvent.ROLL_OUT, func:handleCellRendererMouseEvent}); | |
rendererSprite.addEventListener(Event.CHANGE,handleCellRendererChange,false,0,true); | |
_cellRendererList.push({obj:rendererSprite, eventStr: Event.CHANGE, func:handleCellRendererChange}); | |
rendererSprite.doubleClickEnabled = true; | |
rendererSprite.addEventListener(MouseEvent.DOUBLE_CLICK, handleCellRendererDoubleClick, false, 0, true); | |
_cellRendererList.push({obj:rendererSprite, eventStr: MouseEvent.DOUBLE_CLICK, func:handleCellRendererDoubleClick}); | |
//rendererSprite = renderer as Sprite; | |
if (rendererSprite != null && rendererSprite["setStyle"] != null) { | |
for (var n:String in rendererStyles) { | |
rendererSprite["setStyle"](n, rendererStyles[n]) | |
} | |
} | |
} | |
} | |
list.addChild(renderer as Sprite); | |
activeCellRenderers.push(renderer); | |
renderer.y = rowHeight*(i-startIndex); | |
//renderer.setSize(availableWidth+_maxHorizontalScrollPosition,rowHeight); | |
if (width < contentWidth){ | |
renderer.setSize(contentWidth, rowHeight); | |
} else { | |
renderer.setSize(width, rowHeight); | |
} | |
var label:String = itemToLabel(item); | |
var icon:Object = null; | |
if (_iconFunction != null) { | |
icon = _iconFunction(item); | |
} else if (_iconField != null) { | |
icon = item[_iconField]; | |
} | |
if (!reused) { | |
renderer.data = item; | |
} | |
renderer.listData = new ListData(label,icon,this,i,i,0); | |
renderer.selected = (_selectedIndices.indexOf(i) != -1); | |
// force an immediate draw (because render event will not be called on the renderer): | |
if (renderer is UIComponent) { | |
(renderer as UIComponent).drawNow(); | |
} | |
} | |
} | |
/** | |
* Sets the component to the specified width and height. | |
* | |
* @param width The width of the component, in pixels. | |
* | |
* @param height The height of the component, in pixels. | |
* | |
* @langversion 3.0 | |
* @playerversion Flash 9.0.28.0 | |
*/ | |
override public function setSize(width:Number, height:Number):void { | |
super.setSize(width, height); | |
if (width < contentWidth){ | |
TreeCellRendererCustom.setOverrideSize(contentWidth, 0); | |
super.setSize(width, height); | |
} else { | |
TreeCellRendererCustom.setOverrideSize(width, 0); | |
super.setSize(width, height); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment