Solved

Item Renderer and Tree control creating havoc!!!

Posted on 2009-05-14
5
1,526 Views
Last Modified: 2012-06-27
We are facing a weird problem while using Tree control with Item Renderer.

http://202.131.103.236/Problem/SampleTree.html

With both nodes collapsed, access them one after another, every time closing the previous one. They will both reflect the same values.. actually they have separate values. But since, every time expansion / collapse happens, it re-generates the item renderer and thus mis matches the whole stuff.

Same way, inside any node, select a child and hit F2 to rename. After renaming, click outside to apply change. Now, collapse the node and re-expand it. The position of changed child would have changed and will do so every time it is expanded.

We are really stuck at this and need a solution to get through.

Any help is greatly appreciated.

Warm Regards.
0
Comment
Question by:shardul_bartwal
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 10

Expert Comment

by:mplord
ID: 24390765
Can you allow View Source on that demo?
0
 

Author Comment

by:shardul_bartwal
ID: 24392558
Hi Mplord,

Thanks for reverting back.

I have updated the link: http://202.131.103.236/Problem/SampleTree.html

with View Source enabled.

Looking forward for your inputs.

Warm Regards.
0
 
LVL 10

Expert Comment

by:mplord
ID: 24394060
I think the key point is that you're forgetting that only a small number of itemRenderers are used to render *every* node of the tree, you don't get one itemRenderer per node. itemRenderers are reused to improve display performance of the tree.

That means you can't store data in the itemRenderer (e.g. disBox, disImage, spacer, treeListData, labelEdit) and assume that it won't been clobbered by rendering of other nodes.
            
Don't store data locally in the itemRenderer, and you'll need to figure out a way to 'data-drive' the visuals so that each time an itemRenderer does something, it can figure out either from the data or dynamic interrogation what state it should be in.
0
 
LVL 10

Accepted Solution

by:
mplord earned 250 total points
ID: 24394423
Looking more closely, the key is really about the 'flag' variable, which will never be set back to true once the itemRenderer has been created, so as soon as it is used for other nodes (e.g. collapse one folder, expand another) the data is not overwritten with the new details.

I've modified your TreeRenderer code in a few places to take this into account.
When data is set for the renderer, this will usually be when the itemRenderer is used for a different node, so we've got to set the flag back to true.
However in createChildren, you might already have created the renderer controls, so check if they're null first before creating.
In onFinishEdit, you need to remember to invalidateDisplayList.

Finally a small change in LabelEditor - when losing focus the FinishEdit event wasn't fired - I changed the event name to match FinishEdit to make sure it's fired.

No change to the main application MXML.

###### TreeRenderer.as
 
package renderer
{
	import flash.events.Event;
	import flash.filters.DropShadowFilter;
	
	import mx.containers.Box;
	import mx.containers.HBox;
	import mx.controls.Spacer;
	import mx.controls.Tree;
	import mx.controls.treeClasses.TreeItemRenderer;
	import mx.controls.treeClasses.TreeListData;
	import mx.core.IDataRenderer;
	import mx.events.FlexEvent;
	
	public class TreeRenderer extends TreeItemRenderer implements IDataRenderer 
	{
		public var disBox:HBox;
		public var disImage:Box;
		public var spacer:Spacer;
		public var treeListData:TreeListData;
		public var labelEdit:LabelEditor;
		
		public var flag:Boolean = true; 
		
		public function TreeRenderer()
		{
			super();
		}
 
		override public function set data(value:Object):void
		{
			flag = true;
			super.data = value
		}
		
		
		override protected function createChildren():void
		{
			super.createChildren();
 
			if(flag)
			{
				for(var i:int=0; i<numChildren; i++)
				super.removeChildAt(i);
				
				if (disBox == null)
				{
					disBox = new HBox();
					spacer = new Spacer();
					labelEdit = new LabelEditor();
					disImage = new Box();
					
					disBox.addChild(labelEdit);
					disBox.addChild(spacer);
					disBox.addChild(disImage);
					this.addChild(disBox);
	
					labelEdit.addEventListener("StartEdit",onStartEdit);
					labelEdit.addEventListener("FinishEdit",onFinishEdit);
				}
			}
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth,unscaledHeight);
			
			if(flag)
			{
				treeListData = TreeListData(listData);
				if(treeListData != null)
				{
					if(super.data)
	            	{
						var xml:XML = treeListData.item as XML;
						label.visible = false;
						icon.visible = true;
						
						labelEdit.text = xml.@Name;
						
						disBox.height = height;
						disBox.width = width - ( icon.width + icon.x );
						disBox.x = icon.width + icon.x;
						disBox.visible = true;
						
						disImage.width = 40;
						disImage.height = height;
						
						spacer.percentWidth = 100;
						
						disImage.filters = [ new DropShadowFilter() ];
						flag = false;
	            	}
				}
				if(treeListData.hasChildren)
				{
					disImage.setStyle("backgroundColor",0xFF0000);
				}
				else
				{
					disImage.setStyle("backgroundColor",0xFFFF00); 
				}
			}
			
		}
		
		private function onFinishEdit ( event : Event ):void
		{
			var newStr : String = ( event.currentTarget as LabelEditor )._updatedText;
			
			( treeListData.item as XML ).@Name = newStr;
			( owner as Tree ).dispatchEvent( new Event("UpdateTree",true) );
			
			this.invalidateDisplayList();
		}
		
		private function onStartEdit ( event : Event ):void
		{
		}
	}
}
 
 
 
###### Change to LabelEditor.as
 
protected function onFocusOut(event:FocusEvent):void
{
	_updatedText = text;
	
	if(_updatedText != _originalText){
		dispatchEvent(new Event("FinishEdit"));
	}
	
	setEditable(false);
}

Open in new window

0
 

Author Closing Comment

by:shardul_bartwal
ID: 31581550
Hey mplord,

Thanks a lot buddy. It has worked out like a charm. Will let you know if there are any further problems. Much appreciated...
0

Featured Post

Optimize your web performance

What's in the eBook?
- Full list of reasons for poor performance
- Ultimate measures to speed things up
- Primary web monitoring types
- KPIs you should be monitoring in order to increase your ROI

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

First things first - Preparation We need all the part for this install and it's much nicer to have them all on hand when you need them so here's what's required. Download Eclipse 3.5 32 bit (I like the Classic flavour) from here. (http://www.e…
There are times when I have encountered the need to decompress a response from a PHP request. This is how it's done, but you must have control of the request and you can set the Accept-Encoding header.
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…

617 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question