/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.hierarchyviewer.scene; import java.awt.Color; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Point2D; import org.netbeans.api.visual.action.ActionFactory; import org.netbeans.api.visual.action.WidgetAction; import org.netbeans.api.visual.anchor.AnchorFactory; import org.netbeans.api.visual.border.BorderFactory; import org.netbeans.api.visual.graph.GraphScene; import org.netbeans.api.visual.layout.LayoutFactory; import org.netbeans.api.visual.model.ObjectState; import org.netbeans.api.visual.widget.ConnectionWidget; import org.netbeans.api.visual.widget.LabelWidget; import org.netbeans.api.visual.widget.LayerWidget; import org.netbeans.api.visual.widget.Widget; public class ViewHierarchyScene extends GraphScene<ViewNode, String> { private ViewNode root; private LayerWidget widgetLayer; private LayerWidget connectionLayer; private WidgetAction moveAction = ActionFactory.createMoveAction(); public ViewHierarchyScene() { widgetLayer = new LayerWidget(this); connectionLayer = new LayerWidget(this); addChild(widgetLayer); addChild(connectionLayer); } public ViewNode getRoot() { return root; } void setRoot(ViewNode root) { this.root = root; } @Override protected Widget attachNodeWidget(ViewNode node) { Widget widget = createBox(node, node.name, node.id); widget.getActions().addAction(createSelectAction()); widget.getActions().addAction(moveAction); widgetLayer.addChild(widget); return widget; } private Widget createBox(ViewNode node, String nodeName, String id) { final String shortName = getShortName(nodeName); node.setShortName(shortName); GradientWidget box = new GradientWidget(this, node); box.setLayout(LayoutFactory.createVerticalFlowLayout()); box.setBorder(BorderFactory.createLineBorder(2, Color.BLACK)); box.setOpaque(true); LabelWidget label = new LabelWidget(this); label.setFont(getDefaultFont().deriveFont(Font.PLAIN, 12.0f)); label.setLabel(shortName); label.setBorder(BorderFactory.createEmptyBorder(6, 6, 0, 6)); label.setAlignment(LabelWidget.Alignment.CENTER); box.addChild(label); label = new LabelWidget(this); label.setFont(getDefaultFont().deriveFont(Font.PLAIN, 10.0f)); label.setLabel(getAddress(nodeName)); label.setBorder(BorderFactory.createEmptyBorder(3, 6, 0, 6)); label.setAlignment(LabelWidget.Alignment.CENTER); box.addressWidget = label; box.addChild(label); label = new LabelWidget(this); label.setFont(getDefaultFont().deriveFont(Font.PLAIN, 10.0f)); label.setLabel(id); label.setBorder(BorderFactory.createEmptyBorder(3, 6, 6, 6)); label.setAlignment(LabelWidget.Alignment.CENTER); box.addChild(label); return box; } private static String getAddress(String name) { String[] nameAndHashcode = name.split("@"); return "@" + nameAndHashcode[1]; } private static String getShortName(String name) { String[] nameAndHashcode = name.split("@"); String[] packages = nameAndHashcode[0].split("\\."); return packages[packages.length - 1]; } @Override protected Widget attachEdgeWidget(String edge) { ConnectionWidget connectionWidget = new ConnectionWidget(this); connectionLayer.addChild(connectionWidget); return connectionWidget; } @Override protected void attachEdgeSourceAnchor(String edge, ViewNode oldSourceNode, ViewNode sourceNode) { final ConnectionWidget connection = (ConnectionWidget) findWidget(edge); final Widget source = findWidget(sourceNode); connection.bringToBack(); source.bringToFront(); connection.setSourceAnchor(AnchorFactory.createRectangularAnchor(source)); } @Override protected void attachEdgeTargetAnchor(String edge, ViewNode oldTargetNode, ViewNode targetNode) { final ConnectionWidget connection = (ConnectionWidget) findWidget(edge); final Widget target = findWidget(targetNode); connection.bringToBack(); target.bringToFront(); connection.setTargetAnchor(AnchorFactory.createRectangularAnchor(target)); } private static class GradientWidget extends Widget implements ViewNode.StateListener { public static final GradientPaint BLUE_EXPERIENCE = new GradientPaint( new Point2D.Double(0, 0), new Color(168, 204, 241), new Point2D.Double(0, 1), new Color(44, 61, 146)); public static final GradientPaint MAC_OSX_SELECTED = new GradientPaint( new Point2D.Double(0, 0), new Color(81, 141, 236), new Point2D.Double(0, 1), new Color(36, 96, 192)); public static final GradientPaint MAC_OSX = new GradientPaint( new Point2D.Double(0, 0), new Color(167, 210, 250), new Point2D.Double(0, 1), new Color(99, 147, 206)); public static final GradientPaint AERITH = new GradientPaint( new Point2D.Double(0, 0), Color.WHITE, new Point2D.Double(0, 1), new Color(64, 110, 161)); public static final GradientPaint GRAY = new GradientPaint( new Point2D.Double(0, 0), new Color(226, 226, 226), new Point2D.Double(0, 1), new Color(250, 248, 248)); public static final GradientPaint RED_XP = new GradientPaint( new Point2D.Double(0, 0), new Color(236, 81, 81), new Point2D.Double(0, 1), new Color(192, 36, 36)); public static final GradientPaint NIGHT_GRAY = new GradientPaint( new Point2D.Double(0, 0), new Color(102, 111, 127), new Point2D.Double(0, 1), new Color(38, 45, 61)); public static final GradientPaint NIGHT_GRAY_LIGHT = new GradientPaint( new Point2D.Double(0, 0), new Color(129, 138, 155), new Point2D.Double(0, 1), new Color(58, 66, 82)); public static final GradientPaint NIGHT_GRAY_VERY_LIGHT = new GradientPaint( new Point2D.Double(0, 0), new Color(129, 138, 155, 60), new Point2D.Double(0, 1), new Color(58, 66, 82, 60)); private static Color UNSELECTED = Color.BLACK; private static Color SELECTED = Color.WHITE; private final ViewNode node; private LabelWidget addressWidget; private boolean isSelected = false; private final GradientPaint selectedGradient = MAC_OSX_SELECTED; private final GradientPaint filteredGradient = RED_XP; private final GradientPaint focusGradient = NIGHT_GRAY_VERY_LIGHT; public GradientWidget(ViewHierarchyScene scene, ViewNode node) { super(scene); this.node = node; node.setStateListener(this); } @Override protected void notifyStateChanged(ObjectState previous, ObjectState state) { super.notifyStateChanged(previous, state); isSelected = state.isSelected() || state.isFocused() || state.isWidgetFocused(); pickChildrenColor(); } private void pickChildrenColor() { for (Widget child : getChildren()) { child.setForeground(isSelected || node.filtered ? SELECTED : UNSELECTED); } repaint(); } @Override protected void paintBackground() { super.paintBackground(); Graphics2D g2 = getGraphics(); Rectangle bounds = getBounds(); if (!isSelected) { if (!node.filtered) { if (!node.hasFocus) { g2.setColor(Color.WHITE); } else { g2.setPaint(new GradientPaint(bounds.x, bounds.y, focusGradient.getColor1(), bounds.x, bounds.x + bounds.height, focusGradient.getColor2())); } } else { g2.setPaint(new GradientPaint(bounds.x, bounds.y, filteredGradient.getColor1(), bounds.x, bounds.x + bounds.height, filteredGradient.getColor2())); } } else { g2.setPaint(new GradientPaint(bounds.x, bounds.y, selectedGradient.getColor1(), bounds.x, bounds.x + bounds.height, selectedGradient.getColor2())); } g2.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); } public void nodeStateChanged(ViewNode node) { pickChildrenColor(); } public void nodeIndexChanged(ViewNode node) { if (addressWidget != null) { addressWidget.setLabel("#" + node.index + addressWidget.getLabel()); } } } }