blob: 9bc7204ea7c2d0d1dbd6a0ab6e7c6cec36135471 [file] [log] [blame]
/*
* Copyright (C) 2015 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.tools.idea.editors.gfxtrace.controllers;
import com.android.tools.idea.editors.gfxtrace.controllers.modeldata.AtomNode;
import com.android.tools.idea.editors.gfxtrace.controllers.modeldata.EnumInfoCache;
import com.android.tools.idea.editors.gfxtrace.controllers.modeldata.HierarchyNode;
import com.android.tools.idea.editors.gfxtrace.renderers.AtomTreeRenderer;
import com.android.tools.idea.editors.gfxtrace.renderers.styles.TreeUtil;
import com.android.tools.idea.editors.gfxtrace.rpc.AtomGroup;
import com.android.tools.idea.editors.gfxtrace.rpc.Hierarchy;
import com.android.tools.idea.editors.gfxtrace.schema.AtomReader;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.ui.components.JBLoadingPanel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.util.ui.StatusText;
import org.jetbrains.annotations.NotNull;
import javax.swing.tree.*;
import java.awt.*;
import java.util.Enumeration;
public class AtomController implements GfxController {
@NotNull private final JBLoadingPanel myLoadingPanel;
@NotNull private final SimpleTree myTree;
@NotNull private final AtomTreeRenderer myAtomTreeRenderer;
private TreeNode myAtomTreeRoot;
private EnumInfoCache myEnumInfoCache;
public AtomController(@NotNull Project project, @NotNull JBScrollPane scrollPane) {
scrollPane.getHorizontalScrollBar().setUnitIncrement(20);
scrollPane.getVerticalScrollBar().setUnitIncrement(20);
myTree = new SimpleTree();
myTree.setRowHeight(TreeUtil.TREE_ROW_HEIGHT);
myTree.setRootVisible(false);
myTree.setLineStyleAngled();
myTree.getEmptyText().setText(SELECT_CAPTURE);
myLoadingPanel = new JBLoadingPanel(new BorderLayout(), project);
myLoadingPanel.add(myTree);
scrollPane.setViewportView(myLoadingPanel);
myAtomTreeRenderer = new AtomTreeRenderer();
}
@NotNull
public static TreeNode prepareData(@NotNull Hierarchy hierarchy) {
assert (!ApplicationManager.getApplication().isDispatchThread());
return generateAtomTree(hierarchy.getRoot());
}
@NotNull
private static MutableTreeNode generateAtomTree(@NotNull AtomGroup atomGroup) {
assert (atomGroup.getRange().getCount() > 0);
DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode();
currentNode.setUserObject(new HierarchyNode(atomGroup));
long lastGroupIndex = atomGroup.getRange().getFirst();
for (AtomGroup subGroup : atomGroup.getSubGroups()) {
long subGroupFirst = subGroup.getRange().getFirst();
assert (subGroupFirst >= lastGroupIndex);
if (subGroupFirst > lastGroupIndex) {
addLeafNodes(currentNode, subGroupFirst, subGroupFirst - lastGroupIndex);
}
currentNode.add(generateAtomTree(subGroup));
lastGroupIndex = subGroup.getRange().getFirst() + subGroup.getRange().getCount();
}
long nextSiblingStartIndex = atomGroup.getRange().getFirst() + atomGroup.getRange().getCount();
if (nextSiblingStartIndex > lastGroupIndex) {
addLeafNodes(currentNode, lastGroupIndex, nextSiblingStartIndex - lastGroupIndex);
}
return currentNode;
}
private static void addLeafNodes(@NotNull DefaultMutableTreeNode parentNode, long start, long count) {
for (long i = 0, index = start; i < count; ++i, ++index) {
AtomNode atomNode = new AtomNode(index);
parentNode.add(new DefaultMutableTreeNode(atomNode, false));
}
}
@NotNull
public SimpleTree getTree() {
return myTree;
}
@Override
public void startLoad() {
myTree.getEmptyText().setText("");
myLoadingPanel.startLoading();
}
@Override
public void commitData(@NotNull GfxContextChangeState state) {
myEnumInfoCache = state.myEnumInfoCache;
myAtomTreeRoot = state.myTreeRoot;
}
public void populateUi(@NotNull AtomReader atomReader) {
ApplicationManager.getApplication().assertIsDispatchThread();
assert (myAtomTreeRoot != null);
myAtomTreeRenderer.init(myEnumInfoCache, atomReader);
myTree.setModel(new DefaultTreeModel(myAtomTreeRoot));
myTree.setLargeModel(true); // Set some performance optimizations for large models.
myTree.setRowHeight(TreeUtil.TREE_ROW_HEIGHT); // Make sure our rows are constant height.
myTree.setCellRenderer(myAtomTreeRenderer);
if (myAtomTreeRoot.getChildCount() == 0) {
myTree.getEmptyText().setText(StatusText.DEFAULT_EMPTY_TEXT);
}
myLoadingPanel.stopLoading();
myLoadingPanel.revalidate();
}
public void selectFrame(@NotNull AtomGroup group) {
// Search through the list for now.
for (Enumeration it = myAtomTreeRoot.children(); it.hasMoreElements(); ) {
TreeNode node = (TreeNode)it.nextElement();
assert (node instanceof DefaultMutableTreeNode);
Object userObject = ((DefaultMutableTreeNode)node).getUserObject();
if (!(userObject instanceof HierarchyNode)) {
continue;
}
if (((HierarchyNode)userObject).isProxyFor(group)) {
TreePath path = new TreePath(new Object[]{myAtomTreeRoot, node});
select(path);
break;
}
}
}
@Override
public void clear() {
myTree.setModel(null);
myAtomTreeRenderer.clearState();
myAtomTreeRoot = null;
myEnumInfoCache = null;
}
@Override
public void clearCache() {
myTree.clearSelection();
}
private void select(@NotNull TreePath path) {
myTree.setSelectionPath(path);
myTree.scrollPathToVisible(path);
}
}