Home | History | Annotate | Download | only in ui
      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.hierarchyviewer.ui;
     18 
     19 import com.android.hierarchyviewer.scene.ViewHierarchyScene;
     20 import com.android.hierarchyviewer.scene.ViewNode;
     21 
     22 import javax.swing.JComponent;
     23 import javax.swing.BorderFactory;
     24 import java.awt.Color;
     25 import java.awt.Dimension;
     26 import java.awt.Graphics;
     27 import java.awt.Insets;
     28 import java.awt.event.MouseAdapter;
     29 import java.awt.event.MouseEvent;
     30 import java.util.Set;
     31 
     32 class LayoutRenderer extends JComponent {
     33     private static final int EMULATED_SCREEN_WIDTH = 320;
     34     private static final int EMULATED_SCREEN_HEIGHT = 480;
     35     private static final int SCREEN_MARGIN = 24;
     36 
     37     private boolean showExtras;
     38     private ViewHierarchyScene scene;
     39     private JComponent sceneView;
     40 
     41     LayoutRenderer(ViewHierarchyScene scene, JComponent sceneView) {
     42         this.scene = scene;
     43         this.sceneView = sceneView;
     44 
     45         setOpaque(true);
     46         setBorder(BorderFactory.createEmptyBorder(0, 0, 12, 0));
     47         setBackground(Color.BLACK);
     48         setForeground(Color.WHITE);
     49 
     50         addMouseListener(new MouseAdapter() {
     51             @Override
     52             public void mousePressed(MouseEvent event) {
     53                 selectChild(event.getX(), event.getY());
     54             }
     55         });
     56     }
     57 
     58     @Override
     59     public Dimension getPreferredSize() {
     60         return new Dimension(EMULATED_SCREEN_WIDTH + SCREEN_MARGIN,
     61                 EMULATED_SCREEN_HEIGHT + SCREEN_MARGIN);
     62     }
     63 
     64     @Override
     65     protected void paintComponent(Graphics g) {
     66         g.setColor(getBackground());
     67         g.fillRect(0, 0, getWidth(), getHeight());
     68 
     69         Insets insets = getInsets();
     70         g.clipRect(insets.left, insets.top,
     71                 getWidth() - insets.left - insets.right,
     72                 getHeight() - insets.top - insets.bottom);
     73 
     74         if (scene == null) {
     75             return;
     76         }
     77 
     78         ViewNode root = scene.getRoot();
     79         if (root == null) {
     80             return;
     81         }
     82 
     83         int x = (getWidth() - insets.left - insets.right - root.width) / 2;
     84         int y = (getHeight() - insets.top - insets.bottom - root.height) / 2;
     85         g.translate(insets.left + x, insets.top + y);
     86 
     87         g.setColor(getForeground());
     88         g.drawRect(root.left, root.top, root.width - 1, root.height - 1);
     89         g.clipRect(root.left - 1, root.top - 1, root.width + 1, root.height + 1);
     90         drawChildren(g, root, -root.scrollX, -root.scrollY);
     91 
     92         Set<?> selection = scene.getSelectedObjects();
     93         if (selection.size() > 0) {
     94             ViewNode node = (ViewNode) selection.iterator().next();
     95             g.setColor(Color.RED);
     96             Graphics s = g.create();
     97             ViewNode p = node.parent;
     98             while (p != null) {
     99                 s.translate(p.left - p.scrollX, p.top - p.scrollY);
    100                 p = p.parent;
    101             }
    102             if (showExtras && node.image != null) {
    103                 s.drawImage(node.image, node.left, node.top, null);
    104             }
    105             s.drawRect(node.left, node.top, node.width - 1, node.height - 1);
    106             s.dispose();
    107         }
    108 
    109         g.translate(-insets.left - x, -insets.top - y);
    110     }
    111 
    112     private void drawChildren(Graphics g, ViewNode root, int x, int y) {
    113         g.translate(x, y);
    114         for (ViewNode node : root.children) {
    115             if (!node.willNotDraw) {
    116                 g.drawRect(node.left, node.top, node.width - 1, node.height - 1);
    117             }
    118 
    119             if (node.children.size() > 0) {
    120                 drawChildren(g, node,
    121                         node.left - node.parent.scrollX,
    122                         node.top - node.parent.scrollY);
    123             }
    124         }
    125         g.translate(-x, -y);
    126     }
    127 
    128     public void setShowExtras(boolean showExtras) {
    129         this.showExtras = showExtras;
    130         repaint();
    131     }
    132 
    133     private void selectChild(int x, int y) {
    134 
    135         if (scene == null) {
    136             return;
    137         }
    138 
    139         ViewNode root = scene.getRoot();
    140         if (root == null) {
    141             return;
    142         }
    143 
    144         Insets insets = getInsets();
    145 
    146         int xoffset = (getWidth() - insets.left - insets.right - root.width) / 2 + insets.left + 1;
    147         int yoffset = (getHeight() - insets.top - insets.bottom - root.height) / 2 + insets.top + 1;
    148 
    149         x -= xoffset;
    150         y -= yoffset;
    151         if (x >= 0 && x < EMULATED_SCREEN_WIDTH && y >= 0 && y < EMULATED_SCREEN_HEIGHT) {
    152             ViewNode hit = findChild(root, root, x, y);
    153             scene.setFocusedObject(hit);
    154             sceneView.repaint();
    155         }
    156     }
    157 
    158     private ViewNode findChild(ViewNode root, ViewNode besthit, int x, int y) {
    159         ViewNode hit = besthit;
    160         for (ViewNode node : root.children) {
    161 
    162             if (node.left <= x && x < node.left + node.width &&
    163                 node.top <= y && y < node.top + node.height) {
    164                 if (node.width <= hit.width && node.height <= hit.height) {
    165                     hit = node;
    166                 }
    167             }
    168 
    169             if (node.children.size() > 0) {
    170                 hit = findChild(node, hit,
    171                         x - (node.left - node.parent.scrollX),
    172                         y - (node.top - node.parent.scrollY));
    173             }
    174         }
    175         return hit;
    176     }
    177 }
    178