Home | History | Annotate | Download | only in scene
      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.scene;
     18 
     19 import java.awt.Color;
     20 import java.awt.Font;
     21 import java.awt.GradientPaint;
     22 import java.awt.Graphics2D;
     23 import java.awt.Rectangle;
     24 import java.awt.geom.Point2D;
     25 
     26 import org.netbeans.api.visual.action.ActionFactory;
     27 import org.netbeans.api.visual.action.WidgetAction;
     28 import org.netbeans.api.visual.anchor.AnchorFactory;
     29 import org.netbeans.api.visual.border.BorderFactory;
     30 import org.netbeans.api.visual.graph.GraphScene;
     31 import org.netbeans.api.visual.layout.LayoutFactory;
     32 import org.netbeans.api.visual.model.ObjectState;
     33 import org.netbeans.api.visual.widget.ConnectionWidget;
     34 import org.netbeans.api.visual.widget.LabelWidget;
     35 import org.netbeans.api.visual.widget.LayerWidget;
     36 import org.netbeans.api.visual.widget.Widget;
     37 
     38 public class ViewHierarchyScene extends GraphScene<ViewNode, String> {
     39     private ViewNode root;
     40     private LayerWidget widgetLayer;
     41     private LayerWidget connectionLayer;
     42 
     43     private WidgetAction moveAction = ActionFactory.createMoveAction();
     44 
     45     public ViewHierarchyScene() {
     46         widgetLayer = new LayerWidget(this);
     47         connectionLayer = new LayerWidget(this);
     48 
     49         addChild(widgetLayer);
     50         addChild(connectionLayer);
     51     }
     52 
     53     public ViewNode getRoot() {
     54         return root;
     55     }
     56 
     57     void setRoot(ViewNode root) {
     58         this.root = root;
     59     }
     60 
     61     @Override
     62     protected Widget attachNodeWidget(ViewNode node) {
     63         Widget widget = createBox(node, node.name, node.id);
     64         widget.getActions().addAction(createSelectAction());
     65         widget.getActions().addAction(moveAction);
     66         widgetLayer.addChild(widget);
     67         return widget;
     68     }
     69 
     70     private Widget createBox(ViewNode node, String nodeName, String id) {
     71         final String shortName = getShortName(nodeName);
     72         node.setShortName(shortName);
     73 
     74         GradientWidget box = new GradientWidget(this, node);
     75         box.setLayout(LayoutFactory.createVerticalFlowLayout());
     76         box.setBorder(BorderFactory.createLineBorder(2, Color.BLACK));
     77         box.setOpaque(true);
     78 
     79         LabelWidget label = new LabelWidget(this);
     80         label.setFont(getDefaultFont().deriveFont(Font.PLAIN, 12.0f));
     81         label.setLabel(shortName);
     82         label.setBorder(BorderFactory.createEmptyBorder(6, 6, 0, 6));
     83         label.setAlignment(LabelWidget.Alignment.CENTER);
     84 
     85         box.addChild(label);
     86 
     87         label = new LabelWidget(this);
     88         label.setFont(getDefaultFont().deriveFont(Font.PLAIN, 10.0f));
     89         label.setLabel(getAddress(nodeName));
     90         label.setBorder(BorderFactory.createEmptyBorder(3, 6, 0, 6));
     91         label.setAlignment(LabelWidget.Alignment.CENTER);
     92 
     93         box.addressWidget = label;
     94 
     95         box.addChild(label);
     96 
     97         label = new LabelWidget(this);
     98         label.setFont(getDefaultFont().deriveFont(Font.PLAIN, 10.0f));
     99         label.setLabel(id);
    100         label.setBorder(BorderFactory.createEmptyBorder(3, 6, 6, 6));
    101         label.setAlignment(LabelWidget.Alignment.CENTER);
    102 
    103         box.addChild(label);
    104 
    105         return box;
    106     }
    107 
    108     private static String getAddress(String name) {
    109         String[] nameAndHashcode = name.split("@");
    110         return "@" + nameAndHashcode[1];
    111     }
    112 
    113     private static String getShortName(String name) {
    114         String[] nameAndHashcode = name.split("@");
    115         String[] packages = nameAndHashcode[0].split("\\.");
    116         return packages[packages.length - 1];
    117     }
    118 
    119     @Override
    120     protected Widget attachEdgeWidget(String edge) {
    121         ConnectionWidget connectionWidget = new ConnectionWidget(this);
    122         connectionLayer.addChild(connectionWidget);
    123         return connectionWidget;
    124     }
    125 
    126     @Override
    127     protected void attachEdgeSourceAnchor(String edge, ViewNode oldSourceNode, ViewNode sourceNode) {
    128         final ConnectionWidget connection = (ConnectionWidget) findWidget(edge);
    129         final Widget source = findWidget(sourceNode);
    130         connection.bringToBack();
    131         source.bringToFront();
    132         connection.setSourceAnchor(AnchorFactory.createRectangularAnchor(source));
    133     }
    134 
    135     @Override
    136     protected void attachEdgeTargetAnchor(String edge, ViewNode oldTargetNode, ViewNode targetNode) {
    137         final ConnectionWidget connection = (ConnectionWidget) findWidget(edge);
    138         final Widget target = findWidget(targetNode);
    139         connection.bringToBack();
    140         target.bringToFront();
    141         connection.setTargetAnchor(AnchorFactory.createRectangularAnchor(target));
    142     }
    143 
    144     private static class GradientWidget extends Widget implements ViewNode.StateListener {
    145         public static final GradientPaint BLUE_EXPERIENCE = new GradientPaint(
    146                 new Point2D.Double(0, 0),
    147                 new Color(168, 204, 241),
    148                 new Point2D.Double(0, 1),
    149                 new Color(44, 61, 146));
    150         public static final GradientPaint MAC_OSX_SELECTED = new GradientPaint(
    151                 new Point2D.Double(0, 0),
    152                 new Color(81, 141, 236),
    153                 new Point2D.Double(0, 1),
    154                 new Color(36, 96, 192));
    155         public static final GradientPaint MAC_OSX = new GradientPaint(
    156                 new Point2D.Double(0, 0),
    157                 new Color(167, 210, 250),
    158                 new Point2D.Double(0, 1),
    159                 new Color(99, 147, 206));
    160         public static final GradientPaint AERITH = new GradientPaint(
    161                 new Point2D.Double(0, 0),
    162                 Color.WHITE,
    163                 new Point2D.Double(0, 1),
    164                 new Color(64, 110, 161));
    165         public static final GradientPaint GRAY = new GradientPaint(
    166                 new Point2D.Double(0, 0),
    167                 new Color(226, 226, 226),
    168                 new Point2D.Double(0, 1),
    169                 new Color(250, 248, 248));
    170         public static final GradientPaint RED_XP = new GradientPaint(
    171                 new Point2D.Double(0, 0),
    172                 new Color(236, 81, 81),
    173                 new Point2D.Double(0, 1),
    174                 new Color(192, 36, 36));
    175         public static final GradientPaint NIGHT_GRAY = new GradientPaint(
    176                 new Point2D.Double(0, 0),
    177                 new Color(102, 111, 127),
    178                 new Point2D.Double(0, 1),
    179                 new Color(38, 45, 61));
    180         public static final GradientPaint NIGHT_GRAY_LIGHT = new GradientPaint(
    181                 new Point2D.Double(0, 0),
    182                 new Color(129, 138, 155),
    183                 new Point2D.Double(0, 1),
    184                 new Color(58, 66, 82));
    185         public static final GradientPaint NIGHT_GRAY_VERY_LIGHT = new GradientPaint(
    186                 new Point2D.Double(0, 0),
    187                 new Color(129, 138, 155, 60),
    188                 new Point2D.Double(0, 1),
    189                 new Color(58, 66, 82, 60));
    190 
    191         private static Color UNSELECTED = Color.BLACK;
    192         private static Color SELECTED = Color.WHITE;
    193 
    194         private final ViewNode node;
    195 
    196         private LabelWidget addressWidget;
    197 
    198         private boolean isSelected = false;
    199         private final GradientPaint selectedGradient = MAC_OSX_SELECTED;
    200         private final GradientPaint filteredGradient = RED_XP;
    201         private final GradientPaint focusGradient = NIGHT_GRAY_VERY_LIGHT;
    202 
    203         public GradientWidget(ViewHierarchyScene scene, ViewNode node) {
    204             super(scene);
    205             this.node = node;
    206             node.setStateListener(this);
    207         }
    208 
    209         @Override
    210         protected void notifyStateChanged(ObjectState previous, ObjectState state) {
    211             super.notifyStateChanged(previous, state);
    212             isSelected = state.isSelected() || state.isFocused() || state.isWidgetFocused();
    213 
    214             pickChildrenColor();
    215         }
    216 
    217         private void pickChildrenColor() {
    218             for (Widget child : getChildren()) {
    219                 child.setForeground(isSelected || node.filtered ? SELECTED : UNSELECTED);
    220             }
    221 
    222             repaint();
    223         }
    224 
    225         @Override
    226         protected void paintBackground() {
    227             super.paintBackground();
    228 
    229             Graphics2D g2 = getGraphics();
    230             Rectangle bounds = getBounds();
    231 
    232             if (!isSelected) {
    233                 if (!node.filtered) {
    234                     if (!node.hasFocus) {
    235                         g2.setColor(Color.WHITE);
    236                     } else {
    237                         g2.setPaint(new GradientPaint(bounds.x, bounds.y,
    238                                 focusGradient.getColor1(), bounds.x, bounds.x + bounds.height,
    239                                 focusGradient.getColor2()));
    240                     }
    241                 } else {
    242                     g2.setPaint(new GradientPaint(bounds.x, bounds.y, filteredGradient.getColor1(),
    243                         bounds.x, bounds.x + bounds.height, filteredGradient.getColor2()));
    244                 }
    245             } else {
    246                 g2.setPaint(new GradientPaint(bounds.x, bounds.y, selectedGradient.getColor1(),
    247                         bounds.x, bounds.x + bounds.height, selectedGradient.getColor2()));
    248             }
    249             g2.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
    250         }
    251 
    252         public void nodeStateChanged(ViewNode node) {
    253             pickChildrenColor();
    254         }
    255 
    256         public void nodeIndexChanged(ViewNode node) {
    257             if (addressWidget != null) {
    258                 addressWidget.setLabel("#" + node.index + addressWidget.getLabel());
    259             }
    260         }
    261     }
    262 }
    263