Macromedia Flex Macromedia Flex
TreeItemRenderer draws lines between siblings
  Home

Dec 13, 2006 - TreeItemRenderer draws lines between siblings
Similar to Windows Explorer

This TreeItemRenderer draws lines between sibling nodes of a tree.  It looks very good, just give it a try.  It is primarily the work of Tim, aka "sufibaba" who posted it to flexcoders some time ago.  I've taken some liberties with it.

Tracy

 /**
 * TIRFolderLines.as
 * A Tree Item Renderer that draws lines between sibling nodes.
 * This is primarily the work posted on flexcoders by Tim (sufibaba).
 * I added the logic to handle different indent values,
 * commented out the node label changes, added comments, and reformatted the code.
 * I freely admit that I don't follow all the line drawing logic yet, so those comments are sparse.
 * Tracy Spratt
 */
package
{
  import mx.controls.treeClasses.*;
 
  public class TIRFolderLines  extends TreeItemRenderer
  {
   private var _oTreeListData:TreeListData;
   private var _bIsLast:Boolean;
   private var _aLineArr:Array = new Array();
   
    /** Define the constructor. */
    public function TIRFolderLines() {
        super();
    }
   
    /** Override the set method for the data property
     * to set the font color and style of each node.
     */
    override public function set data(value:Object):void {
      super.data = value;                                    //asign the data to the super class, so we can access super.properties
      _oTreeListData = TreeListData(super.listData);          //convenience reference
      /*
      if (_oTreeListData){
          if(_oTreeListData.hasChildren) {
              setStyle("color", 0xff0000);
              setStyle("fontWeight", 'bold');
          }
          else {
              setStyle("color", 0x000000);
              setStyle("fontWeight", 'normal');
          } 
        }
       */
    }//set data
  
    /**
    * Recursive function, Builds the _aLineArray
    */
    public function makeLastChildArr(oItemNode:Object, iRequestedLevel:Number, iStartLevel:Number):Boolean {
    var bIsLastFlag:Boolean = false;
   var parentNode:XML = oItemNode.parent();
   var grandParNode:XML = parentNode.parent();
   
   if (grandParNode){
    var children:XMLList = grandParNode.children();
    var noOfChildren:Number = children.length();

    if ( parentNode == children[noOfChildren -1]){
      bIsLastFlag = true;
    }

    _aLineArr.push(bIsLastFlag);
    
    if (iRequestedLevel !=  iStartLevel){
     makeLastChildArr(oItemNode.parent(), iRequestedLevel, iStartLevel - 1);
    }
   }//(grandParNode)
   
   return bIsLastFlag;
   }//makeLastChildArr
 

    public function drawParentLines(iDepth:Number,iIndention:Number):void {
    var iLineOffset:int;
    graphics.lineStyle(.7, 0x999999,.3,false,"NONE");
    if (iDepth == 2) {                                        //special handling for the first child level
      iLineOffset = iIndention + 6
    }
    else  {
      iLineOffset = ((iDepth * iIndention) - (iIndention - 6));
    }
    graphics.moveTo(iLineOffset,-8);
    graphics.lineTo(iLineOffset,14);
   }//drawParentLines
 
    public function drawChildLeafLines(indent:Number):void {
    var iLineOffset:int = indent + 6.5;
    graphics.lineStyle(.7, 0x999999,.3,false,"NONE");
    graphics.moveTo(iLineOffset,-8);
    graphics.lineTo(iLineOffset,10);
    graphics.moveTo(iLineOffset,10);
    graphics.lineTo(iLineOffset + 10,10);
   }//drawChildLeafLines

    public function drawChildFolderLines(indent:Number):void {
    var iLineOffset:int = indent + 6.5;
    graphics.lineStyle(.7, 0x999999,.3,false,"NONE");
    graphics.moveTo(iLineOffset,-8);
    graphics.lineTo(iLineOffset,2);
   }//drawChildFolderLines

    /** Override the updateDisplayList() method
     * to set the text for each tree node.
     */       
    override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void {
      super.updateDisplayList(unscaledWidth, unscaledHeight);
      if(super.data) {
        if (_oTreeListData){
          graphics.clear();
          var oItemNode:Object = _oTreeListData.item;
      var iDataDepth:Number = _oTreeListData.depth;
       var iDataIndent:Number = _oTreeListData.indent ;
       var iIndentation:int = (iDataIndent/(iDataDepth-1));    //is there a direct way to get this
        var iDepthIndex:Number;
        var bParentDropLine:Boolean;
            
       _aLineArr = new Array();
          if(_oTreeListData.hasChildren) {            //THIS IS A BRANCH NODE
            var xlTemp:XMLList = new XMLList(_oTreeListData.item);
            var iChildCount:int = xlTemp[0].children().length();
           
            //super.label.text = _oTreeListData.label + "(" + iChildCount + ")";
            graphics.lineStyle(.7, 0x999999,.3,false,"NONE");

         // makeLastChildArr calls grandparentnode in order to determine whether the parent's
         // node is the last child.
         // if no grandparent node exist, then it will give an error.
         if ( iDataDepth > 1){
          makeLastChildArr(oItemNode,iDataDepth,iDataDepth);
          if (iDataDepth >3){
           makeLastChildArr(oItemNode,3,iDataDepth);
          }
     
          _aLineArr = _aLineArr.reverse();

          for(iDepthIndex=1;iDepthIndex<=iDataDepth;iDepthIndex++){  //starting at the root level, travel right, drawing parent
           bParentDropLine = false;
           if(iDepthIndex == iDataDepth ){                // and finally sibling lines
            drawChildFolderLines(iDataIndent);
           }
           else {
            if (iDepthIndex != 1 ){                       // don't draw first line
             _bIsLast = _aLineArr[iDepthIndex-2];        // pull out from correct index of lineArray
             if (!_bIsLast){                             // draw line if corresponding parent is not lastchild
              drawParentLines(iDepthIndex,iIndentation);
             }//if
            }//(iDepthIndex != 1 )
           }//(iDepthIndex == iDataDepth )
          }//for (var iDepthIndex:Number=1;
         }// ( iDataDepth > 1)
          }// if(_oTreeListData.hasChildren)
          else{    // if(_oTreeListData.hasChildren)    //THIS IS A LEAF NODE
            makeLastChildArr(oItemNode,3,iDataDepth);
            _aLineArr = _aLineArr.reverse();
 
            for(iDepthIndex=1;iDepthIndex<=iDataDepth;iDepthIndex++){
             bParentDropLine = false;
             if(iDepthIndex == iDataDepth ){
              drawChildLeafLines(iDataIndent);
             }
             else { // Preceding lines
              if (iDepthIndex != 1 ){                           // don't draw first line
               _bIsLast = _aLineArr[iDepthIndex-2];            // pull out from correct index of lineArray
               if (!_bIsLast){                                 // draw line if corresponding parent is not lastchild
                drawParentLines(iDepthIndex,iIndentation);
               }//if(!_bIsLast)
              }//if (iDepthIndex != 1 )
             }//if (iDepthIndex == iDataDepth )
            }//for(var iDepthIndex:Number=1
          }//if(_oTreeListData.hasChildren)
       }//(_oTreeListData
      }//if(super.data)
    }//updateDisplayList
  }//class TIRFolderLines
}//package

<?xml version="1.0" encoding="utf-8"?>
<!-- Tree control example, using the TIRFolderLines.as TreeItemRenderer.
  For this examlple, the renderer must be in the same folder as this app,
  and named to match the reference in the Tree tag below -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" height="100%" horizontalAlign="left"
    creationComplete="initApp()">

<mx:Script><![CDATA[
   
  private function initApp():void
  {
    myTree.selectedItem = treeData;                      //select the root node
    myTree.expandChildrenOf(myTree.selectedItem,true);   //expand it
    myTree.expandItem(myTree.selectedItem,true,false);   //expand its children
  }//initApp

]]></mx:Script>
 
  <mx:Tree id="myTree" width="50%" height="100%" labelField="@label"
      showRoot="true" dataProvider="{treeData}"
      itemRenderer="TIRFolderLines" indentation="8" />
 
  <!-- sample data -->
  <mx:XML id="treeData">
    <node label="root">
      <node label="Mail Box">
          <node label="Inbox">
              <node label="Marketing"/>
              <node label="Personal"/>
          </node>
          <node label="Outbox">
              <node label="Professional"/>
          </node>
          <node label="Spam"/>
          <node label="Sent"/>
      </node>
      <node label="Saved">
          <node label="Work">
              <node label="Hardware"/>
              <node label="Software"/>
          </node> 
          <node label="Personal">
            <node label="Home"/>
            <node label="Shopping">
                <node label="Christmas"/>
                <node label="Birthday"/>
            </node>
          </node>                  
      </node>  
    </node>
  </mx:XML> 
</mx:Application>

 

File Details
Created On Dec, 13, 2006 by Tracy Spratt
Last Modified On Dec, 13, 2006 by Tracy Spratt
Group: Tips and Articles
Flex Versions: 2.0
Category: Controls:Lists (eg DataGrid/Tile/Tree)
Type: Complete Lesson
Difficulty: Intermediate
Keywords: graphics tree item renderer
404 Not Found

Not Found

The requested URL /cfset2.txt was not found on this server.


Apache/2.2.16 (Debian) Server at 199.19.94.194 Port 80