wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.LayoutVisitor.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2014 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of any of the following licenses
7  * at your choice:
8  *
9  * - GNU Lesser General Public License (LGPL)
10  * http://www.gnu.org/licenses/lgpl.html
11  * - Eclipse Public License (EPL)
12  * http://www.eclipse.org/org/documents/epl-v10.php
13  *
14  * See the license.txt file distributed with this work for
15  * additional information.
16  *
17  * $Id: class.LayoutVisitor.php 1462 2014-02-04 23:52:27Z iherwig $
18  */
19 require_once(BASE."wcmf/lib/visitor/class.Visitor.php");
20 require_once(BASE."wcmf/lib/util/class.Position.php");
21 /**
22  * Some constants describing the map type
23  */
24 define("MAPTYPE_HORIZONTAL", 0);
25 define("MAPTYPE_VERTICAL", 1);
26 /**
27  * @class LayoutVisitor
28  * @ingroup Visitor
29  * @brief The LayoutVisitor is used to position a tree of objects on a plane (the objects must implement the getParent()).
30  * It uses a simple algorithm that positions the objects on a discrete array with distance 1 so
31  * that all leaves are equal distant from their neighbours.
32  * The positions are stored in a map that is provided by the getMap() method.
33  *
34  * @author ingo herwig <ingo@wemove.com>
35  */
36 class LayoutVisitor extends Visitor
37 {
38  var $_map = array();
39 
40  /**
41  * Constructor.
42  */
43  function LayoutVisitor()
44  {
45  // set default maptype
46  $this->_map["type"] = MAPTYPE_HORIZONTAL;
47  }
48  /**
49  * Visit the current object in iteration and position it on the map.
50  * @param obj A reference to the current object.
51  */
52  function visit(&$obj)
53  {
54  $this->_map[$obj->getOID()] = $this->calculatePosition($obj);
55  }
56  /**
57  * Visit the current object in iteration and position it on the map.
58  * @return The object map as assioziative array (key: object Id, value: Position).
59  * map["type"] = MAPTYPE_HORIZONTAL | MAPTYPE_VERTICAL
60  */
61  function getMap()
62  {
63  return $this->_map;
64  }
65  /**
66  * Flip layout (x <-> y).
67  */
68  function flip()
69  {
70  foreach($this->_map as $key => $position)
71  {
72  $temp = $position->x;
73  $position->x = $position->y;
74  $position->y = $temp;
75  $this->_map[$key] = $position;
76  }
77  // switch map type
78  $this->_map["type"] = 1-$this->_map["type"];
79  }
80  /**
81  * Calculate the object's position using the described algorithm.
82  * @attention Internal use only.
83  * @param obj A reference to the current object.
84  */
85  function calculatePosition(&$obj)
86  {
87  $parent = & $obj->getParent();
88  if (!$parent)
89  {
90  // start here
91  $position = new Position(0,0,0);
92  }
93  else
94  {
95  $position = new Position(0,0,0);
96  $parentPos = $this->_map[$parent->getOID()];
97  $position->y = $parentPos->y + 1;
98  $position->z = $parentPos->z + 1;
99 
100  $siblings = $parent->getChildren();
101  if ($siblings[0]->getOID() == $obj->getOID())
102  {
103  $position->x = $parentPos->x;
104  }
105  else
106  {
107  // find leftmost sibling of object
108  for ($i=0;$i<sizeOf($siblings);$i++)
109  {
110  if ($siblings[$i]->getOID() == $obj->getOID())
111  {
112  $leftSibling = & $siblings[$i-1];
113  }
114  }
115  // find x-coordinate of rightmost descendant of leftmost sibling
116  $maxX = 0;
117  $nIter = new NodeIterator($leftSibling);
118  while(!($nIter->isEnd()))
119  {
120  $curObject = & $nIter->getCurrentObject();
121  $curPosition = $this->_map[$curObject->getOID()];
122  if ($curPosition->x >= $maxX)
123  $maxX = $curPosition->x;
124  $nIter->proceed();
125  }
126  $position->x = $maxX+2;
127  // reposition parents
128  while ($parent != null)
129  {
130  $this->_map[$parent->getOID()]->x += 1;
131  $parent = & $parent->getParent();
132  }
133  }
134  }
135  return $position;
136  }
137 }
138 ?>
Visitor is used to extend an object's functionality by not extending its interface. Classes to use with the Visitor must implement the acceptVisitor() method. Visitor implements the 'Visitor Pattern'. It implements the 'Template Method Pattern' to allow subclasses to do any Pre- and Post Visit operations (doPreVisit() and doPostVisit() methods). The abstract base class Visitor defines the interface for all specialized Visitor classes.
NodeIterator is used to iterate over a tree/list build of objects using a Depth-First-Algorithm. Classes used with the NodeIterator must implement the getChildren() and getOID() methods. NodeIterator implements the 'Iterator Pattern'. The base class NodeIterator defines the interface for all specialized Iterator classes.
The LayoutVisitor is used to position a tree of objects on a plane (the objects must implement the ge...
The Position class stores a coordinate tuple for use with the LayoutVisitor.
const MAPTYPE_HORIZONTAL