00001 <?php
00002
00045 class TKTree extends TKContainer {
00046 protected $listIds = array();
00047 protected $bulletIds = array();
00048
00049 protected $curParent = null;
00050 private $root = array('c');
00051
00055 public function __construct() {
00056 parent::__construct();
00057
00058 $this->addProperty('item_class', self::PROP_CLASS);
00059 $this->addProperty('item_style', self::PROP_STYLE);
00060 $this->addProperty('inner_class', self::PROP_CLASS);
00061 $this->addProperty('inner_style', self::PROP_STYLE);
00062 $this->addProperty('bullet_none_class', self::PROP_CLASS);
00063 $this->addProperty('bullet_collapse_class', self::PROP_CLASS);
00064 $this->addProperty('bullet_expand_class', self::PROP_CLASS);
00065
00066 $this->addProperty('node_state', self::PROP_ARRAY);
00067 $this->addProperty('node_children', self::PROP_ARRAY);
00068
00069 $this->set('node_children', array(0 => array()));
00070 }
00071
00079 public function addItemsTo($parent) {
00080 if($parent != null && !isset($this->children['main'][$parent->getId()])) {
00081 $this->setError("Parent object with id '" . $parent->getId() . "' does not exist in this tree.");
00082 return false;
00083 }
00084 $this->curParent = $parent;
00085 }
00086
00091 public function getParentNode() {
00092 return $this->curParent;
00093 }
00094
00104 public function setItemState($item, $collapsed, $rec = false) {
00105 if(isset($this->children['main'][$item->getId()])) {
00106 $nodeState = $this->get('node_state');
00107 $nodeState[$item->getId()] = ($collapsed?'e':'c');
00108 $this->set('node_state', $nodeState);
00109 if($rec) {
00110 $children = $this->get('node_children');
00111 foreach($children[$item->getId()] as $child) {
00112 $this->setItemState($child, $collapsed, true);
00113 }
00114 }
00115 return true;
00116 }
00117 else {
00118 $this->setError("No such object in tree: " . $item->getId());
00119 return false;
00120 }
00121 }
00122
00124 protected function onAdd(&$component, &$slot, &$params, $id) {
00125 if(isset($params['collapsed'])) {
00126 $col = $params['collapsed'] == true ? 'e' : 'c';
00127 }
00128 else {
00129 $col = 'e';
00130 }
00131 $this->append('node_state', array($id => $col));
00132
00133 $parent = isset($params['parent']) ? $params['parent'] : $this->curParent;
00134 $parentInfo = $this->get('node_children');
00135 if($parent === false || $parent == null) {
00136 $parent = null;
00137 array_push($parentInfo[0], $id);
00138 }
00139 else {
00140 array_push($parentInfo[$parent->getId()], $id);
00141 }
00142 $parentInfo[$id] = array();
00143 $this->set('node_children', $parentInfo);
00144 $keepParent = isset($params['keep']) ? $params['keep'] : false;
00145
00146
00147 $params = array();
00148 $params[0] = $col;
00149
00150 if($keepParent)
00151 $this->curParent = $parent;
00152 return true;
00153 }
00154
00156 private static function rec_create($obj, $node) {
00157 $curParent = null;
00158 foreach($node['children'] as $child) {
00159 if($child['tag'] == 'subtree') {
00160 if($curParent == null) {
00161 self::setStaticError("Cannot add a subtree with no parent!");
00162 return false;
00163 }
00164 if(isset($child['attrs']['collapse'])) {
00165 $collapsed = $child['attrs']['collapse'] == 'true' ? true : false;
00166 switch($child['attrs']['collapse']) {
00167 case 'self:true':
00168 $collapsed = true;
00169 $rec = false;
00170 break;
00171 case 'self:false':
00172 $collapsed = false;
00173 $rec = false;
00174 break;
00175 case 'children:true':
00176 $collapsed = true;
00177 $rec = true;
00178 break;
00179 case 'children:false':
00180 $collapsed = false;
00181 $rec = true;
00182 break;
00183 }
00184 }
00185 else {
00186 $collapsed = true;
00187 $rec = false;
00188 }
00189 unset($child['attrs']['collapse']);
00190 $oldParent = $obj->getParentNode();
00191 $obj->addItemsTo($curParent);
00192 $obj->setItemState($curParent, $collapsed, $rec);
00193 self::rec_create($obj, $child);
00194 $obj->addItemsTo($oldParent);
00195
00196 }
00197 else if(substr($child['tag'], 0, 2) == 'TK') {
00198
00199 $nobj = self::convertChild($child);
00200 if($nobj !== null)
00201 $obj->add($nobj);
00202 $curParent = $nobj;
00203 }
00204
00205 }
00206 return true;
00207 }
00208
00210 public static function createFromXML($attrs, $contents, $node) {
00211 $obj = new TKTree();
00212 self::convertStdAttributes($obj, $attrs);
00213 self::convertStdEvents($obj, $node);
00214 if(!self::rec_create($obj, $node))
00215 return null;
00216 return $obj;
00217 }
00218
00219 private $nodesSoFar = 0;
00220
00222 protected function renderContainer($class, $style, $events, $id) {
00223 $bcClass = join(" ", $this->get('bullet_collapse_class'));
00224 $beClass = join(" ", $this->get('bullet_expand_class'));
00225 $bnClass = join(" ", $this->get('bullet_none_class'));
00226
00227 $collect = "<ul $id$class[0]$style[0]$events>\n";
00228 $children = $this->get('node_children');
00229 $children = $children[0];
00230 $collect .= $this->renderSubtree($children, $class, $style, $bcClass, $beClass, $bnClass);
00231 $collect .= "</ul>\n";
00232
00233 $myId = $this->getId();
00234 $js = "Toolkit.\$treeListIds['$myId'] = ['" . implode("','", $this->listIds) . "'];\n";
00235 $js .= "Toolkit.\$treeBulletIds['$myId'] = ['" . implode("','", $this->bulletIds) . "'];\n";
00236 $js .= "Toolkit.\$treeDisabledNodes['$myId'] = [];\n";
00237 $this->addExtraJS('tkv_tree_' . $this->getId(), $js);
00238
00239 return $collect;
00240 }
00241
00243 protected function renderSubtree($children, $class, $style, $bcClass, $beClass, $bnClass) {
00244 if(count($children) == 0)
00245 return "";
00246 $collect = "";
00247
00248 $cinfo = $this->get('node_state');
00249 $innerchildren = $this->get('node_children');
00250 foreach($children as $id) {
00251 $c = $this->getChild('main', $id);
00252
00253 $inner = $innerchildren[$id];
00254 if(count($inner) > 0) {
00255 $lid = "list_$id";
00256 $bid = "bullet_$id";
00257 array_push($this->listIds, $lid);
00258 array_push($this->bulletIds, $bid);
00259 if($cinfo[$id] == 'c') {
00260 $bullet = $class['bullet_collapse'];
00261 $hidden = "";
00262 }
00263 else {
00264 $bullet = $class['bullet_expand'];
00265 $hidden = "display:none";
00266 }
00267 $this->nodesSoFar++;
00268 $innerC = $this->renderSubtree($inner, $class, $style, $bcClass, $beClass, $bnClass);
00269 $collect .= $this->renderNode($c, $innerC, $class, $style, $bcClass, $beClass, $bullet, $lid, $bid, $hidden);
00270 }
00271 else {
00272 $this->nodesSoFar++;
00273 $collect .= $this->renderLeafNode($c, $class, $style);
00274 }
00275 }
00276 return $collect;
00277 }
00278
00280 protected function renderNode($node, $inner, $class, $style, $bcClass, $beClass, $bullet, $lid, $bid, $hidden) {
00281 $onclick = " onclick=\"Toolkit.toggleDisplay('$lid', '$bid', '$bcClass', '$beClass');false\"";
00282 $html = is_object($node) ? $node->render() : $node;
00283 $collect = "<li$class[item]$style[item]><span id=\"$bid\"$bullet$onclick> </span>$html" ;
00284 $innerStyle = rtrim($style['inner'], '"') . ";$hidden\"";
00285 $collect .= "\n<ul id=\"$lid\"$class[inner] style=\"$innerStyle\">\n";
00286 $collect .= $inner
00287 . "</ul></li>\n";
00288 return $collect;
00289 }
00290
00292 protected function renderLeafNode($node, $class, $style) {
00293 $html = is_object($node) ? $node->render() : $node;
00294 $collect = "<li$class[item]$style[item]><span$class[bullet_none]> </span>$html</li>\n";
00295 return $collect;
00296 }
00297 }
00298
00299 ?>