PDA

View Full Version : <tree> recursion not working when tree is dynamically created, OL4.3 / SWF9.


falcor781
07-01-2009, 10:11 AM
Hi folks --

I'm trying to create a view that will show all of my XML at once so I can more easily debug when nodes are created / destroyed / modified. What I've found is that when making a tree, my dataset will correctly be recursively created with a tree only if I use a static tag. If it's done dynamically (i.e. with 'new') for some reason the recursion will go only one level deep if there are more than 1 children at that tree level of depth.

Below, I have an example dataset and my implementation of the XML viewer.

<canvas debug="true">

<dataset name="toolkit">
<problemspec>
</problemspec>
<problemstates>
<problemstate name="toplevel">
<parameter name="currentTrial" value="1"/>
</problemstate>
<problemstate name="simulation">
<objectstate name="ramp1">
<parameters>
<parameter name="leftRampAngle" value="0.34906"/>
<parameter name="ballStartPercent" value="0.5"/>
<parameter name="frictionColor" value="green"/>
<parameter name="ballMass" value="1"/>
<parameter name="ballRadius" value="10"/>
<parameter name="leftRampLength" value="300"/>
<parameter name="rightRampLength" value="200"/>
<parameter name="rightRampFriction" value=".33"/>
<parameter name="leftRampFriction" value=".1"/>
<parameter name="ballColor" value="blue"/>
</parameters>
</objectstate>
</problemstate>
<problemstate name="hypothesis"/>
<problemstate name="trials"/>
<problemstate name="table"/>
<problemstate name="graph"/>
</problemstates>
<actions>

</actions>
<history>

</history>

</dataset>

<!-- Recursively build a tree that shows all the nodes in the dataset -->
<class name="debugtreeview" extends="view">
<tree datapath="." text="$path{'./name(.)'}">
<tree datapath="*">
<handler name="ondata">
var node = datapath.xpathQuery('.');
var attrs = datapath.xpathQuery('@*');
var str = node.nodeName + " -- "
for(att in attrs)
{
str += "(" + att + ": " + attrs[att] + "), ";
}
this.setAttribute('text', str);
</handler>
</tree>
</tree>
</class>

<!-- A view for the debug tree for testing purposes -->
<class name="testview" extends="view">
<debugtreeview datapath="."/>
<handler name="ondata">
this.addSubview(new lz.debugtreeview(this, {datapath: '.'})); // Doesn't work where as the debugtreeview tag above does work.
</handler>
<simplelayout axis="y"/>
</class>

<testview datapath="toolkit:/"/>
</canvas>


I've looked into the issue a little by throwing some debug statements inside basetree.lzx within the createChildTrees() method. What I've found is that on dynamic creation, it's claiming that some of the datapointers in the XML structure are null (INFO: getNodeName: p is null in Datapath for tree) even though they clearly aren't since it works fine in the nondynamic case.

Anyone have any idea what's going on?

Thanks!!

falcor781
07-06-2009, 08:58 PM
Since creating children is done in the init method, the datapath may not be finished initializing when creating a new tree via 'new' for some reason. The following changes to basetree.lzx fix the problem and works for tag-created and dynamically created trees.

Basically, I moved the createChildren() call to an ondata handler. Works when I reset the datapath via setAttribute as well. Will be posting a JIRA on this shortly.

<method name="init">
<![CDATA[

super.init();

if ( this._children == null ) {
this._children = this.searchSubnodes( "name" , this.defaultplacement );
}

if (this.isRoot()) {

var focusItem = this.item;
if ( ! this.showroot ) {
this.item.destroy();
this.item = null;
this.setAttribute("open", true);
this.children.setAttribute("x", 0);
this.children.setAttribute("y", 0);
var sv = this.children.subviews;
if (sv && (sv[0]) instanceof lz.basetree) {
focusItem = sv[0].item;
}
}

this._selector = new lz.treeselector(this,
{ multiselect: this.multiselect,
toggle: this.toggleselected });

// Call this only after selector is created
this.changeFocus(focusItem.parent);
}

// Make sure selector knows about me being selected
if (this.selected) this._setSelected(true);


]]>
</method>

<handler name="ondata">
if (this.datapath) {
createChildTrees();
}
</handler>


Enjoy!!