Solved

Item Renderer and Tree control creating havoc!!!

Posted on 2009-05-14
5
1,507 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
  • 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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

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…
We have come a long way with backup and data protection — from backing up to floppies, external drives, CDs, Blu-ray, flash drives, SSD drives, and now to the cloud.
This video discusses moving either the default database or any database to a new volume.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

757 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now