Home | History | Annotate | Download | only in device
      1 /*
      2  * Copyright (C) 2008 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.device;
     18 
     19 import org.eclipse.swt.graphics.Image;
     20 
     21 import java.util.ArrayList;
     22 import java.util.Collections;
     23 import java.util.Comparator;
     24 import java.util.HashMap;
     25 import java.util.List;
     26 import java.util.Map;
     27 import java.util.Set;
     28 import java.util.TreeSet;
     29 
     30 public class ViewNode {
     31 
     32     public static enum ProfileRating {
     33         RED, YELLOW, GREEN, NONE
     34     };
     35 
     36     private static final double RED_THRESHOLD = 0.8;
     37 
     38     private static final double YELLOW_THRESHOLD = 0.5;
     39 
     40     public static final String MISCELLANIOUS = "miscellaneous";
     41 
     42     public String id;
     43 
     44     public String name;
     45 
     46     public String hashCode;
     47 
     48     public List<Property> properties = new ArrayList<Property>();
     49 
     50     public Map<String, Property> namedProperties = new HashMap<String, Property>();
     51 
     52     public ViewNode parent;
     53 
     54     public List<ViewNode> children = new ArrayList<ViewNode>();
     55 
     56     public int left;
     57 
     58     public int top;
     59 
     60     public int width;
     61 
     62     public int height;
     63 
     64     public int scrollX;
     65 
     66     public int scrollY;
     67 
     68     public int paddingLeft;
     69 
     70     public int paddingRight;
     71 
     72     public int paddingTop;
     73 
     74     public int paddingBottom;
     75 
     76     public int marginLeft;
     77 
     78     public int marginRight;
     79 
     80     public int marginTop;
     81 
     82     public int marginBottom;
     83 
     84     public int baseline;
     85 
     86     public boolean willNotDraw;
     87 
     88     public boolean hasMargins;
     89 
     90     public boolean hasFocus;
     91 
     92     public int index;
     93 
     94     public double measureTime;
     95 
     96     public double layoutTime;
     97 
     98     public double drawTime;
     99 
    100     public ProfileRating measureRating = ProfileRating.NONE;
    101 
    102     public ProfileRating layoutRating = ProfileRating.NONE;
    103 
    104     public ProfileRating drawRating = ProfileRating.NONE;
    105 
    106     public Set<String> categories = new TreeSet<String>();
    107 
    108     public Window window;
    109 
    110     public Image image;
    111 
    112     public int imageReferences = 1;
    113 
    114     public int viewCount;
    115 
    116     public boolean filtered;
    117 
    118     public int protocolVersion;
    119 
    120     public ViewNode(Window window, ViewNode parent, String data) {
    121         this.window = window;
    122         this.parent = parent;
    123         index = this.parent == null ? 0 : this.parent.children.size();
    124         if (this.parent != null) {
    125             this.parent.children.add(this);
    126         }
    127         int delimIndex = data.indexOf('@');
    128         name = data.substring(0, delimIndex);
    129         data = data.substring(delimIndex + 1);
    130         delimIndex = data.indexOf(' ');
    131         hashCode = data.substring(0, delimIndex);
    132         loadProperties(data.substring(delimIndex + 1).trim());
    133 
    134         measureTime = -1;
    135         layoutTime = -1;
    136         drawTime = -1;
    137     }
    138 
    139     public void dispose() {
    140         final int N = children.size();
    141         for (int i = 0; i < N; i++) {
    142             children.get(i).dispose();
    143         }
    144         dereferenceImage();
    145     }
    146 
    147     public void referenceImage() {
    148         imageReferences++;
    149     }
    150 
    151     public void dereferenceImage() {
    152         imageReferences--;
    153         if (image != null && imageReferences == 0) {
    154             image.dispose();
    155         }
    156     }
    157 
    158     private void loadProperties(String data) {
    159         int start = 0;
    160         boolean stop;
    161         do {
    162             int index = data.indexOf('=', start);
    163             ViewNode.Property property = new ViewNode.Property();
    164             property.name = data.substring(start, index);
    165 
    166             int index2 = data.indexOf(',', index + 1);
    167             int length = Integer.parseInt(data.substring(index + 1, index2));
    168             start = index2 + 1 + length;
    169             property.value = data.substring(index2 + 1, index2 + 1 + length);
    170 
    171             properties.add(property);
    172             namedProperties.put(property.name, property);
    173 
    174             stop = start >= data.length();
    175             if (!stop) {
    176                 start += 1;
    177             }
    178         } while (!stop);
    179 
    180         Collections.sort(properties, new Comparator<ViewNode.Property>() {
    181             public int compare(ViewNode.Property source, ViewNode.Property destination) {
    182                 return source.name.compareTo(destination.name);
    183             }
    184         });
    185 
    186         id = namedProperties.get("mID").value; //$NON-NLS-1$
    187 
    188         left =
    189  namedProperties.containsKey("mLeft") ? getInt("mLeft", 0) : getInt("layout:mLeft", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    190                         0);
    191         top = namedProperties.containsKey("mTop") ? getInt("mTop", 0) : getInt("layout:mTop", 0); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    192         width =
    193                 namedProperties.containsKey("getWidth()") ? getInt("getWidth()", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    194                         "layout:getWidth()", 0); //$NON-NLS-1$
    195         height =
    196                 namedProperties.containsKey("getHeight()") ? getInt("getHeight()", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    197                         "layout:getHeight()", 0); //$NON-NLS-1$
    198         scrollX =
    199                 namedProperties.containsKey("mScrollX") ? getInt("mScrollX", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    200                         "scrolling:mScrollX", 0); //$NON-NLS-1$
    201         scrollY =
    202                 namedProperties.containsKey("mScrollY") ? getInt("mScrollY", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    203                         "scrolling:mScrollY", 0); //$NON-NLS-1$
    204         paddingLeft =
    205                 namedProperties.containsKey("mPaddingLeft") ? getInt("mPaddingLeft", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    206                         "padding:mPaddingLeft", 0); //$NON-NLS-1$
    207         paddingRight =
    208                 namedProperties.containsKey("mPaddingRight") ? getInt("mPaddingRight", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    209                         "padding:mPaddingRight", 0); //$NON-NLS-1$
    210         paddingTop =
    211                 namedProperties.containsKey("mPaddingTop") ? getInt("mPaddingTop", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    212                         "padding:mPaddingTop", 0); //$NON-NLS-1$
    213         paddingBottom =
    214                 namedProperties.containsKey("mPaddingBottom") ? getInt("mPaddingBottom", 0) //$NON-NLS-1$ //$NON-NLS-2$
    215                         : getInt("padding:mPaddingBottom", 0); //$NON-NLS-1$
    216         marginLeft =
    217                 namedProperties.containsKey("layout_leftMargin") ? getInt("layout_leftMargin", //$NON-NLS-1$ //$NON-NLS-2$
    218                         Integer.MIN_VALUE) : getInt("layout:layout_leftMargin", Integer.MIN_VALUE); //$NON-NLS-1$
    219         marginRight =
    220                 namedProperties.containsKey("layout_rightMargin") ? getInt("layout_rightMargin", //$NON-NLS-1$ //$NON-NLS-2$
    221                         Integer.MIN_VALUE) : getInt("layout:layout_rightMargin", Integer.MIN_VALUE); //$NON-NLS-1$
    222         marginTop =
    223                 namedProperties.containsKey("layout_topMargin") ? getInt("layout_topMargin", //$NON-NLS-1$ //$NON-NLS-2$
    224                         Integer.MIN_VALUE) : getInt("layout:layout_topMargin", Integer.MIN_VALUE); //$NON-NLS-1$
    225         marginBottom =
    226                 namedProperties.containsKey("layout_bottomMargin") ? getInt("layout_bottomMargin", //$NON-NLS-1$ //$NON-NLS-2$
    227                         Integer.MIN_VALUE)
    228                         : getInt("layout:layout_bottomMargin", Integer.MIN_VALUE); //$NON-NLS-1$
    229         baseline =
    230                 namedProperties.containsKey("getBaseline()") ? getInt("getBaseline()", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
    231                         "layout:getBaseline()", 0); //$NON-NLS-1$
    232         willNotDraw =
    233                 namedProperties.containsKey("willNotDraw()") ? getBoolean("willNotDraw()", false) //$NON-NLS-1$ //$NON-NLS-2$
    234                         : getBoolean("drawing:willNotDraw()", false); //$NON-NLS-1$
    235         hasFocus =
    236                 namedProperties.containsKey("hasFocus()") ? getBoolean("hasFocus()", false) //$NON-NLS-1$ //$NON-NLS-2$
    237                         : getBoolean("focus:hasFocus()", false); //$NON-NLS-1$
    238 
    239         hasMargins =
    240                 marginLeft != Integer.MIN_VALUE && marginRight != Integer.MIN_VALUE
    241                         && marginTop != Integer.MIN_VALUE && marginBottom != Integer.MIN_VALUE;
    242 
    243         for (String name : namedProperties.keySet()) {
    244             int index = name.indexOf(':');
    245             if (index != -1) {
    246                 categories.add(name.substring(0, index));
    247             }
    248         }
    249         if (categories.size() != 0) {
    250             categories.add(MISCELLANIOUS);
    251         }
    252     }
    253 
    254     public void setProfileRatings() {
    255         final int N = children.size();
    256         if (N > 1) {
    257             double totalMeasure = 0;
    258             double totalLayout = 0;
    259             double totalDraw = 0;
    260             for (int i = 0; i < N; i++) {
    261                 ViewNode child = children.get(i);
    262                 totalMeasure += child.measureTime;
    263                 totalLayout += child.layoutTime;
    264                 totalDraw += child.drawTime;
    265             }
    266             for (int i = 0; i < N; i++) {
    267                 ViewNode child = children.get(i);
    268                 if (child.measureTime / totalMeasure >= RED_THRESHOLD) {
    269                     child.measureRating = ProfileRating.RED;
    270                 } else if (child.measureTime / totalMeasure >= YELLOW_THRESHOLD) {
    271                     child.measureRating = ProfileRating.YELLOW;
    272                 } else {
    273                     child.measureRating = ProfileRating.GREEN;
    274                 }
    275                 if (child.layoutTime / totalLayout >= RED_THRESHOLD) {
    276                     child.layoutRating = ProfileRating.RED;
    277                 } else if (child.layoutTime / totalLayout >= YELLOW_THRESHOLD) {
    278                     child.layoutRating = ProfileRating.YELLOW;
    279                 } else {
    280                     child.layoutRating = ProfileRating.GREEN;
    281                 }
    282                 if (child.drawTime / totalDraw >= RED_THRESHOLD) {
    283                     child.drawRating = ProfileRating.RED;
    284                 } else if (child.drawTime / totalDraw >= YELLOW_THRESHOLD) {
    285                     child.drawRating = ProfileRating.YELLOW;
    286                 } else {
    287                     child.drawRating = ProfileRating.GREEN;
    288                 }
    289             }
    290         }
    291         for (int i = 0; i < N; i++) {
    292             children.get(i).setProfileRatings();
    293         }
    294     }
    295 
    296     public void setViewCount() {
    297         viewCount = 1;
    298         final int N = children.size();
    299         for (int i = 0; i < N; i++) {
    300             ViewNode child = children.get(i);
    301             child.setViewCount();
    302             viewCount += child.viewCount;
    303         }
    304     }
    305 
    306     public void filter(String text) {
    307         int dotIndex = name.lastIndexOf('.');
    308         String shortName = (dotIndex == -1) ? name : name.substring(dotIndex + 1);
    309         filtered =
    310                 !text.equals("") //$NON-NLS-1$
    311                         && (shortName.toLowerCase().contains(text.toLowerCase()) || (!id
    312                                 .equals("NO_ID") && id.toLowerCase().contains(text.toLowerCase()))); //$NON-NLS-1$
    313         final int N = children.size();
    314         for (int i = 0; i < N; i++) {
    315             children.get(i).filter(text);
    316         }
    317     }
    318 
    319     private boolean getBoolean(String name, boolean defaultValue) {
    320         Property p = namedProperties.get(name);
    321         if (p != null) {
    322             try {
    323                 return Boolean.parseBoolean(p.value);
    324             } catch (NumberFormatException e) {
    325                 return defaultValue;
    326             }
    327         }
    328         return defaultValue;
    329     }
    330 
    331     private int getInt(String name, int defaultValue) {
    332         Property p = namedProperties.get(name);
    333         if (p != null) {
    334             try {
    335                 return Integer.parseInt(p.value);
    336             } catch (NumberFormatException e) {
    337                 return defaultValue;
    338             }
    339         }
    340         return defaultValue;
    341     }
    342 
    343     @Override
    344     public String toString() {
    345         return name + "@" + hashCode; //$NON-NLS-1$
    346     }
    347 
    348     public static class Property {
    349         public String name;
    350 
    351         public String value;
    352 
    353         @Override
    354         public String toString() {
    355             return name + '=' + value;
    356         }
    357     }
    358 }
    359