TreeNode.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ArmarX::Gui::TreeNode
17 * @author Kai Welke ( welke at kit dot edu)
18 * @date
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 #include "TreeNode.h"
24 
25 #include <cfloat>
26 
27 namespace armarx
28 {
30  const QSize TreeNode::DefaultNodeVerticalSeparator(0, 50);
31  const QSize TreeNode::DefaultNodeSize(30, 30);
32 
33  //----------------------------------------------------------------------
34  // construction
35  //----------------------------------------------------------------------
36  TreeNode::TreeNode(QGraphicsScene* scene, QSize nodeSize)
37  {
38  this->size = nodeSize;
39 
40  nodeItem = new QGraphicsEllipseItem();
41  scene->addItem(nodeItem);
42  nodeItem->hide();
43  edgeItem = new QGraphicsLineItem();
44  scene->addItem(edgeItem);
45  edgeItem->hide();
46  }
47 
48  //----------------------------------------------------------------------
49  // tree structure
50  //----------------------------------------------------------------------
51  void
52  TreeNode::setParent(TreeNodeWeakPtr parent)
53  {
54  this->parent = parent;
55  // maybe set parent of QGraphicsItems in order to allow transformations
56  }
57 
58  void
60  {
61  child->setParent(TreeNodeWeakPtr(shared_from_this()));
62  childs.push_back(child);
63  }
64 
65  //----------------------------------------------------------------------
66  // layout handling
67  //----------------------------------------------------------------------
68  void
69  TreeNode::update(QPointF positionLeftTop)
70  {
71  // assure root node
72  if (parent.lock())
73  {
74  return;
75  }
76 
77  // recalculate size recursively
78  calculateSubTreeSize();
79 
80  // update layout recursively
81  updateLayout(positionLeftTop);
82  }
83 
84  std::vector<TreeNodePtr>
86  {
87  return childs;
88  }
89 
90  //----------------------------------------------------------------------
91  // helper methods
92  //----------------------------------------------------------------------
93  void
94  TreeNode::updateLayout(QPointF leftTop)
95  {
96  // update of childs if necessary
97  if (childs.size() > 0)
98  {
99  // init left top position of childs
100  QPointF childLeftTop = leftTop;
101  childLeftTop.ry() +=
102  TreeNode::DefaultNodeVerticalSeparator.height() + getSize().height();
103 
104  std::vector<TreeNodePtr>::iterator iter = childs.begin();
105 
106  while (iter != childs.end())
107  {
108  // set layout of children
109  (*iter)->updateLayout(childLeftTop);
110 
111  // move to next left position
112  QSize childSubTreeSize = (*iter)->getSubTreeSize();
113  QPointF inc(
114  childSubTreeSize.width() + TreeNode::DefaultNodeHorizontalSeparator.width(), 0);
115  childLeftTop += inc;
116 
117  iter++;
118  }
119  }
120 
121  // calculate position of node and draw
122  if (childs.size() == 0) // put node in center
123  {
124  // set geometry of node
125  boundingBox =
126  QRectF(leftTop.x() + getSubTreeSize().width() / 2.0f - getSize().width() / 2.0f,
127  leftTop.y(),
128  getSize().width(),
129  getSize().height());
130  drawNode(boundingBox);
131  }
132  else
133  {
134  // center nodes with respect to next layer
135  QRectF childsBB = calculateChildsBoundingBox();
136 
137  // set geometry of node
138  boundingBox = QRectF(childsBB.center().x() - getSize().width() / 2.0f,
139  leftTop.y(),
140  getSize().width(),
141  getSize().height());
142  drawNode(boundingBox);
143  }
144 
145  // draw edge
146  drawEdges();
147  }
148 
149  QSize
150  TreeNode::calculateSubTreeSize()
151  {
152  std::vector<TreeNodePtr>::iterator iter = childs.begin();
153 
154  // size of childs
155  int width = 0;
156  int height = 0;
157 
158  while (iter != childs.end())
159  {
160  // width of children is the sum
161  QSize childSize = (*iter)->calculateSubTreeSize();
162  width += childSize.width() + TreeNode::DefaultNodeHorizontalSeparator.width();
163 
164  // height is the maximum
165  if (childSize.height() > height)
166  {
167  height = childSize.height();
168  }
169 
170  iter++;
171  }
172 
173  // adapt wize
174  if (childs.size() > 0)
175  {
177  height += TreeNode::DefaultNodeVerticalSeparator.height();
178  }
179  else
180  {
181  width = getSize().width();
182  }
183 
184  // adapt size in height
185  height += getSize().height();
186 
187  this->subTreeSize = QSize(width, height);
188 
189  return subTreeSize;
190  }
191 
192  QRectF
193  TreeNode::calculateChildsBoundingBox()
194  {
195  // calculate boundingbox of childs
196  float minX = FLT_MAX;
197  float maxX = 0;
198 
199  float minY = FLT_MAX;
200  float maxY = 0;
201 
202  std::vector<TreeNodePtr>::iterator iter = childs.begin();
203 
204  while (iter != childs.end())
205  {
206  QRectF childBB = (*iter)->getBoundingBox();
207 
208  if (childBB.left() < minX)
209  {
210  minX = childBB.left();
211  }
212 
213  if (childBB.right() > maxX)
214  {
215  maxX = childBB.right();
216  }
217 
218  if (childBB.top() < minY)
219  {
220  minY = childBB.top();
221  }
222 
223  if (childBB.bottom() > maxY)
224  {
225  maxY = childBB.bottom();
226  }
227 
228  iter++;
229  }
230 
231  QRectF result(minX, minY, maxX - minX, maxY - minY);
232  return result;
233  }
234 
235  void
236  TreeNode::drawEdges()
237  {
238  std::vector<TreeNodePtr>::iterator iter = childs.begin();
239 
240  while (iter != childs.end())
241  {
242  QPointF lineStart =
243  (getBoundingBox().bottomLeft() + getBoundingBox().bottomRight()) / 2.0f;
244  QPointF lineEnd =
245  ((*iter)->getBoundingBox().topLeft() + (*iter)->getBoundingBox().topRight()) / 2.0f;
246  QLineF line(lineStart, lineEnd);
247 
248  (*iter)->drawEdge(line);
249 
250  iter++;
251  }
252  }
253 
254  void
255  TreeNode::drawEdge(QLineF line)
256  {
257  edgeItem->setLine(line);
258  edgeItem->show();
259  }
260 
261  void
262  TreeNode::drawNode(QRectF boundingBox)
263  {
264  nodeItem->setRect(boundingBox);
265  nodeItem->show();
266  }
267 } // namespace armarx
armarx::TreeNode::DefaultNodeVerticalSeparator
static const QSize DefaultNodeVerticalSeparator
Definition: TreeNode.h:48
armarx::TreeNode::getChildren
std::vector< TreeNodePtr > getChildren() const
Definition: TreeNode.cpp:85
armarx::TreeNodePtr
std::shared_ptr< TreeNode > TreeNodePtr
Definition: TreeNode.h:40
armarx::TreeNode::TreeNode
TreeNode(QGraphicsScene *scene, QSize nodeSize=TreeNode::DefaultNodeSize)
Constructs a tree node as part of a Qt visualizable tree.
Definition: TreeNode.cpp:36
armarx::TreeNode::DefaultNodeHorizontalSeparator
static const QSize DefaultNodeHorizontalSeparator
Definition: TreeNode.h:47
TreeNode.h
armarx::TreeNode::DefaultNodeSize
static const QSize DefaultNodeSize
Definition: TreeNode.h:49
armarx::TreeNode::getSubTreeSize
QSize getSubTreeSize()
Retrieve size of the complete subtree where the current node is root.
Definition: TreeNode.h:99
armarx::TreeNode::update
void update(QPointF positionLeftTop=QPointF(0, 0))
Updates the layout of the tree.
Definition: TreeNode.cpp:69
armarx::TreeNode::drawNode
virtual void drawNode(QRectF boundingBox)
Draws the node.
Definition: TreeNode.cpp:262
armarx::TreeNodeWeakPtr
std::weak_ptr< TreeNode > TreeNodeWeakPtr
Definition: TreeNode.h:41
armarx::TreeNode::getBoundingBox
QRectF getBoundingBox()
Retrieve boundingbox of the node.
Definition: TreeNode.h:88
armarx::TreeNode::addChild
void addChild(TreeNodePtr child)
Adds a child to the node in the tree structure.
Definition: TreeNode.cpp:59
armarx::TreeNode::drawEdge
virtual void drawEdge(QLineF line)
Draws an edge to this node.
Definition: TreeNode.cpp:255
armarx::TreeNode::getSize
QSize getSize()
Retrieve size of the node.
Definition: TreeNode.h:76
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27