• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.hierarchyviewerlib.ui.util;
18 
19 import com.android.hierarchyviewerlib.device.ViewNode;
20 
21 import java.util.ArrayList;
22 
23 public class DrawableViewNode {
24     public ViewNode viewNode;
25 
26     public final ArrayList<DrawableViewNode> children = new ArrayList<DrawableViewNode>();
27 
28     public final static int NODE_HEIGHT = 100;
29 
30     public final static int NODE_WIDTH = 180;
31 
32     public final static int CONTENT_LEFT_RIGHT_PADDING = 9;
33 
34     public final static int CONTENT_TOP_BOTTOM_PADDING = 8;
35 
36     public final static int CONTENT_INTER_PADDING = 3;
37 
38     public final static int INDEX_PADDING = 7;
39 
40     public final static int LEAF_NODE_SPACING = 9;
41 
42     public final static int NON_LEAF_NODE_SPACING = 15;
43 
44     public final static int PARENT_CHILD_SPACING = 50;
45 
46     public final static int PADDING = 30;
47 
48     public int treeHeight;
49 
50     public int treeWidth;
51 
52     public boolean leaf;
53 
54     public DrawableViewNode parent;
55 
56     public int left;
57 
58     public double top;
59 
60     public int topSpacing;
61 
62     public int bottomSpacing;
63 
64     public boolean treeDrawn;
65 
66     public static class Rectangle {
67         public double x, y, width, height;
68 
Rectangle()69         public Rectangle() {
70 
71         }
72 
Rectangle(Rectangle other)73         public Rectangle(Rectangle other) {
74             this.x = other.x;
75             this.y = other.y;
76             this.width = other.width;
77             this.height = other.height;
78         }
79 
Rectangle(double x, double y, double width, double height)80         public Rectangle(double x, double y, double width, double height) {
81             this.x = x;
82             this.y = y;
83             this.width = width;
84             this.height = height;
85         }
86 
87         @Override
toString()88         public String toString() {
89             return "{" + x + ", " + y + ", " + width + ", " + height + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
90         }
91 
92     }
93 
94     public static class Point {
95         public double x, y;
96 
Point()97         public Point() {
98         }
99 
Point(double x, double y)100         public Point(double x, double y) {
101             this.x = x;
102             this.y = y;
103         }
104 
105         @Override
toString()106         public String toString() {
107             return "(" + x + ", " + y + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
108         }
109     }
110 
111     public Rectangle bounds = new Rectangle();
112 
DrawableViewNode(ViewNode viewNode)113     public DrawableViewNode(ViewNode viewNode) {
114         this.viewNode = viewNode;
115         treeDrawn = !viewNode.willNotDraw;
116         if (viewNode.children.size() == 0) {
117             treeHeight = NODE_HEIGHT;
118             treeWidth = NODE_WIDTH;
119             leaf = true;
120         } else {
121             leaf = false;
122             int N = viewNode.children.size();
123             treeHeight = 0;
124             treeWidth = 0;
125             for (int i = 0; i < N; i++) {
126                 DrawableViewNode child = new DrawableViewNode(viewNode.children.get(i));
127                 children.add(child);
128                 child.parent = this;
129                 treeHeight += child.treeHeight;
130                 treeWidth = Math.max(treeWidth, child.treeWidth);
131                 if (i != 0) {
132                     DrawableViewNode prevChild = children.get(i - 1);
133                     if (prevChild.leaf && child.leaf) {
134                         treeHeight += LEAF_NODE_SPACING;
135                         prevChild.bottomSpacing = LEAF_NODE_SPACING;
136                         child.topSpacing = LEAF_NODE_SPACING;
137                     } else {
138                         treeHeight += NON_LEAF_NODE_SPACING;
139                         prevChild.bottomSpacing = NON_LEAF_NODE_SPACING;
140                         child.topSpacing = NON_LEAF_NODE_SPACING;
141                     }
142                 }
143                 treeDrawn |= child.treeDrawn;
144             }
145             treeWidth += NODE_WIDTH + PARENT_CHILD_SPACING;
146         }
147     }
148 
setLeft()149     public void setLeft() {
150         if (parent == null) {
151             left = PADDING;
152             bounds.x = 0;
153             bounds.width = treeWidth + 2 * PADDING;
154         } else {
155             left = parent.left + NODE_WIDTH + PARENT_CHILD_SPACING;
156         }
157         int N = children.size();
158         for (int i = 0; i < N; i++) {
159             children.get(i).setLeft();
160         }
161     }
162 
placeRoot()163     public void placeRoot() {
164         top = PADDING + (treeHeight - NODE_HEIGHT) / 2.0;
165         double currentTop = PADDING;
166         int N = children.size();
167         for (int i = 0; i < N; i++) {
168             DrawableViewNode child = children.get(i);
169             child.place(currentTop, top - currentTop);
170             currentTop += child.treeHeight + child.bottomSpacing;
171         }
172         bounds.y = 0;
173         bounds.height = treeHeight + 2 * PADDING;
174     }
175 
place(double treeTop, double rootDistance)176     private void place(double treeTop, double rootDistance) {
177         if (treeHeight <= rootDistance) {
178             top = treeTop + treeHeight - NODE_HEIGHT;
179         } else if (rootDistance <= -NODE_HEIGHT) {
180             top = treeTop;
181         } else {
182             if (children.size() == 0) {
183                 top = treeTop;
184             } else {
185                 top =
186                         rootDistance + treeTop - NODE_HEIGHT + (2.0 * NODE_HEIGHT)
187                                 / (treeHeight + NODE_HEIGHT) * (treeHeight - rootDistance);
188             }
189         }
190         int N = children.size();
191         double currentTop = treeTop;
192         for (int i = 0; i < N; i++) {
193             DrawableViewNode child = children.get(i);
194             child.place(currentTop, rootDistance);
195             currentTop += child.treeHeight + child.bottomSpacing;
196             rootDistance -= child.treeHeight + child.bottomSpacing;
197         }
198     }
199 
getSelected(double x, double y)200     public DrawableViewNode getSelected(double x, double y) {
201         if (x >= left && x < left + NODE_WIDTH && y >= top && y <= top + NODE_HEIGHT) {
202             return this;
203         }
204         int N = children.size();
205         for (int i = 0; i < N; i++) {
206             DrawableViewNode selected = children.get(i).getSelected(x, y);
207             if (selected != null) {
208                 return selected;
209             }
210         }
211         return null;
212     }
213 
214     /*
215      * Moves the node the specified distance up.
216      */
move(double distance)217     public void move(double distance) {
218         top -= distance;
219 
220         // Get the root
221         DrawableViewNode root = this;
222         while (root.parent != null) {
223             root = root.parent;
224         }
225 
226         // Figure out the new tree top.
227         double treeTop;
228         if (top + NODE_HEIGHT <= root.top) {
229             treeTop = top + NODE_HEIGHT - treeHeight;
230         } else if (top >= root.top + NODE_HEIGHT) {
231             treeTop = top;
232         } else {
233             if (leaf) {
234                 treeTop = top;
235             } else {
236                 double distanceRatio = 1 - (root.top + NODE_HEIGHT - top) / (2.0 * NODE_HEIGHT);
237                 treeTop = root.top - treeHeight + distanceRatio * (treeHeight + NODE_HEIGHT);
238             }
239         }
240         // Go up the tree and figure out the tree top.
241         DrawableViewNode node = this;
242         while (node.parent != null) {
243             int index = node.viewNode.index;
244             for (int i = 0; i < index; i++) {
245                 DrawableViewNode sibling = node.parent.children.get(i);
246                 treeTop -= sibling.treeHeight + sibling.bottomSpacing;
247             }
248             node = node.parent;
249         }
250 
251         // Update the bounds.
252         root.bounds.y = Math.min(root.top - PADDING, treeTop - PADDING);
253         root.bounds.height =
254                 Math.max(treeTop + root.treeHeight + PADDING, root.top + NODE_HEIGHT + PADDING)
255                         - root.bounds.y;
256         // Place all the children of the root
257         double currentTop = treeTop;
258         int N = root.children.size();
259         for (int i = 0; i < N; i++) {
260             DrawableViewNode child = root.children.get(i);
261             child.place(currentTop, root.top - currentTop);
262             currentTop += child.treeHeight + child.bottomSpacing;
263         }
264 
265     }
266 }
267