//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package mx.collections { import flash.events.EventDispatcher; import mx.events.CollectionEvent; import mx.events.CollectionEventKind; /** * Hierarchical data is data already in a structure of parent and child data items. * The HierarchicalData class provides a default implementation for * accessing and manipulating data for use in controls such as the AdvancedDataGrid control. * To configure the AdvancedDataGrid control to display hierarchical data, * you pass to the dataProvider property an instance of the HierarchicalData class. * * This implementation handles E4X, XML, and Object nodes in similar but different * ways. See each method description for details on how the method * accesses values in nodes of various types. * * @see mx.controls.AdvancedDataGrid * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class HierarchicalData extends EventDispatcher implements IHierarchicalData { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @param value The data used to populate the HierarchicalData instance. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function HierarchicalData(value:Object = null) { super(); source = value; } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // childrenField //-------------------------------------------------------------------------- /** * @private * The field name to be used to detect children field. */ private var _childrenField:String = "children"; /** * Indicates the field name to be used to detect children objects in * a data item. * By default, all subnodes are considered as children for * XML data, and the children property is used for the Object data type. * * This is helpful in adapting to a data format that uses custom data fields * to represent children. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get childrenField():String { return _childrenField; } /** * @private */ public function set childrenField(value:String):void { _childrenField = value; } //-------------------------------------------------------------------------- // source //-------------------------------------------------------------------------- /** * @private * The source collection. */ private var _source:Object; /** * The source collection. * The collection should implement the IList interface * to facilitate operation like the addition and removal of items. * * @see mx.collections.IList * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get source():Object { return _source; } /** * @private */ public function set source(value:Object):void { _source = value; var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE); event.kind = CollectionEventKind.RESET; dispatchEvent(event); } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function canHaveChildren(node:Object):Boolean { if (node == null) return false; var branch:Boolean = false; if (node is XML) { var childList:XMLList = childrenField == "children" ? node.children() : node.child(childrenField).children(); //accessing non-required e4x attributes is quirky //but we know we'll at least get an XMLList var branchFlag:XMLList = node.@isBranch; //check to see if a flag has been set if (branchFlag.length() == 1) { //check flag and return (this flag overrides termination status) if (branchFlag[0] == "true") branch = true; } //since no flags, we'll check to see if there are children else if (childList.length() != 0) { branch = true; } } else if (node is Object) { try { if (node[childrenField] != undefined) { branch = true; } } catch (e:Error) { } } return branch; } /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getChildren(node:Object):Object { if (node == null) return null; var children:*; //first get the children based on the type of node. if (node is XML) { children = childrenField == "children" ? node.* : node.child(childrenField).*; } else if (node is Object) { //we'll try the default children property try { children = node[childrenField]; } catch (e:Error) { } } //no children exist for this node if(children === undefined) return null; return children; } /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function hasChildren(node:Object):Boolean { if (node == null) return false; //This default impl can't optimize this call to getChildren //since we can't make any assumptions by type. Custom impl's //can probably avoid this call and reduce the number of calls to //getChildren if need be. var children:Object = getChildren(node); try { if(children is XMLList || children is XML) { if (children.length() > 0) return true; } if (children.length > 0) return true; } catch (e:Error) { } return false; } /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getData(node:Object):Object { return Object(node); } /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getRoot():Object { return source; } } }