blob: cd1372ab83e5b45fe382ecea5d154f2dd055df5c [file] [log] [blame]
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* 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.intellij.framework.detection.impl.ui;
import com.intellij.framework.FrameworkType;
import com.intellij.framework.detection.DetectedFrameworkDescription;
import com.intellij.framework.detection.FrameworkDetectionContext;
import com.intellij.framework.detection.impl.FrameworkDetectionUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.util.Consumer;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import java.util.*;
/**
* @author nik
*/
public class DetectedFrameworksTree extends CheckboxTree {
private List<? extends DetectedFrameworkDescription> myDetectedFrameworks;
private final FrameworkDetectionContext myContext;
private DetectedFrameworksComponent.GroupByOption myGroupByOption;
public DetectedFrameworksTree(final FrameworkDetectionContext context, DetectedFrameworksComponent.GroupByOption groupByOption) {
super(new DetectedFrameworksTreeRenderer(), new CheckedTreeNode(null), new CheckPolicy(true, true, true, false));
myContext = context;
myGroupByOption = groupByOption;
setShowsRootHandles(false);
setRootVisible(false);
}
private void createNodesGroupedByDirectory(CheckedTreeNode root, final List<? extends DetectedFrameworkDescription> frameworks) {
Map<VirtualFile, FrameworkDirectoryNode> nodes = new HashMap<VirtualFile, FrameworkDirectoryNode>();
List<DetectedFrameworkNode> externalNodes = new ArrayList<DetectedFrameworkNode>();
for (DetectedFrameworkDescription framework : frameworks) {
VirtualFile parent = VfsUtil.getCommonAncestor(framework.getRelatedFiles());
if (parent != null && !parent.isDirectory()) {
parent = parent.getParent();
}
final DetectedFrameworkNode frameworkNode = new DetectedFrameworkNode(framework, myContext);
if (parent != null) {
createDirectoryNodes(parent, nodes).add(frameworkNode);
}
else {
externalNodes.add(frameworkNode);
}
}
List<FrameworkDirectoryNode> rootDirs = new ArrayList<FrameworkDirectoryNode>();
for (FrameworkDirectoryNode directoryNode : nodes.values()) {
if (directoryNode.getParent() == null) {
rootDirs.add(directoryNode);
}
}
for (FrameworkDirectoryNode dir : rootDirs) {
root.add(collapseDirectoryNode(dir));
}
for (DetectedFrameworkNode node : externalNodes) {
root.add(node);
}
}
public void processUncheckedNodes(@NotNull final Consumer<DetectedFrameworkTreeNodeBase> consumer) {
TreeUtil.traverse(getRoot(), new TreeUtil.Traverse() {
@Override
public boolean accept(Object node) {
if (node instanceof DetectedFrameworkTreeNodeBase) {
final DetectedFrameworkTreeNodeBase frameworkNode = (DetectedFrameworkTreeNodeBase)node;
if (!frameworkNode.isChecked()) {
consumer.consume(frameworkNode);
}
}
return true;
}
});
}
@Override
protected void onNodeStateChanged(CheckedTreeNode node) {
final List<DetectedFrameworkDescription> checked = Arrays.asList(getCheckedNodes(DetectedFrameworkDescription.class, null));
final List<DetectedFrameworkDescription> disabled = FrameworkDetectionUtil.getDisabledDescriptions(checked, Collections.<DetectedFrameworkDescription>emptyList());
for (DetectedFrameworkDescription description : disabled) {
final DefaultMutableTreeNode treeNode = TreeUtil.findNodeWithObject(getRoot(), description);
if (treeNode instanceof CheckedTreeNode) {
((CheckedTreeNode)treeNode).setChecked(false);
}
}
}
private static FrameworkDirectoryNode collapseDirectoryNode(FrameworkDirectoryNode node) {
if (node.getChildCount() == 1) {
final TreeNode child = node.getChildAt(0);
if (child instanceof FrameworkDirectoryNode) {
return collapseDirectoryNode((FrameworkDirectoryNode)child);
}
}
for (int i = 0; i < node.getChildCount(); i++) {
TreeNode child = node.getChildAt(i);
if (child instanceof FrameworkDirectoryNode) {
final FrameworkDirectoryNode collapsed = collapseDirectoryNode((FrameworkDirectoryNode)child);
if (collapsed != child) {
node.remove(i);
node.insert(collapsed, i);
}
}
}
return node;
}
@NotNull
private static FrameworkDirectoryNode createDirectoryNodes(@NotNull VirtualFile dir, @NotNull Map<VirtualFile, FrameworkDirectoryNode> nodes) {
final FrameworkDirectoryNode node = nodes.get(dir);
if (node != null) {
return node;
}
final FrameworkDirectoryNode newNode = new FrameworkDirectoryNode(dir);
nodes.put(dir, newNode);
final VirtualFile parent = dir.getParent();
if (parent != null) {
createDirectoryNodes(parent, nodes).add(newNode);
}
return newNode;
}
private void createNodesGroupedByType(CheckedTreeNode root, final List<? extends DetectedFrameworkDescription> frameworks) {
Map<FrameworkType, FrameworkTypeNode> groupNodes = new HashMap<FrameworkType, FrameworkTypeNode>();
for (DetectedFrameworkDescription framework : frameworks) {
final FrameworkType type = framework.getDetector().getFrameworkType();
FrameworkTypeNode group = groupNodes.get(type);
if (group == null) {
group = new FrameworkTypeNode(type);
groupNodes.put(type, group);
root.add(group);
}
group.add(new DetectedFrameworkNode(framework, myContext));
}
}
private CheckedTreeNode getRoot() {
return ((CheckedTreeNode)getModel().getRoot());
}
public void changeGroupBy(DetectedFrameworksComponent.GroupByOption option) {
if (myGroupByOption.equals(option)) return;
myGroupByOption = option;
if (myDetectedFrameworks != null) {
rebuildTree(myDetectedFrameworks);
}
}
public void rebuildTree(final List<? extends DetectedFrameworkDescription> frameworks) {
final CheckedTreeNode root = getRoot();
root.removeAllChildren();
if (myGroupByOption == DetectedFrameworksComponent.GroupByOption.TYPE) {
createNodesGroupedByType(root, frameworks);
}
else {
createNodesGroupedByDirectory(root, frameworks);
}
((DefaultTreeModel)getModel()).nodeStructureChanged(root);
TreeUtil.expandAll(this);
myDetectedFrameworks = frameworks;
}
private static class DetectedFrameworksTreeRenderer extends CheckboxTreeCellRenderer {
private DetectedFrameworksTreeRenderer() {
super(true, false);
}
@Override
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (value instanceof DetectedFrameworkTreeNodeBase) {
((DetectedFrameworkTreeNodeBase)value).renderNode(getTextRenderer());
}
}
}
}