/*
* Copyright 2000-2014 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.ide.customize;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.tree.TreeUtil;
import consulo.ide.customize.CustomizeSelectTemplateStepPanel;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep {
private final MultiMap<String, IdeaPluginDescriptor> myPluginDescriptors;
private final CustomizeSelectTemplateStepPanel myTemplateStepPanel;
private final CheckedTreeNode myRoot;
public CustomizePluginsStepPanel(MultiMap<String, IdeaPluginDescriptor> pluginDescriptors, @Nullable CustomizeSelectTemplateStepPanel templateStepPanel) {
myPluginDescriptors = pluginDescriptors;
myTemplateStepPanel = templateStepPanel;
setLayout(new BorderLayout());
myRoot = new CheckedTreeNode(null);
for (Map.Entry<String, Collection<IdeaPluginDescriptor>> entry : pluginDescriptors.entrySet()) {
String key = entry.getKey();
Collection<IdeaPluginDescriptor> value = entry.getValue();
DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(key);
for (IdeaPluginDescriptor ideaPluginDescriptor : value) {
CheckedTreeNode newChild = new CheckedTreeNode(ideaPluginDescriptor);
newChild.setChecked(false);
groupNode.add(newChild);
}
myRoot.add(groupNode);
}
CheckboxTree checkboxTree = new CheckboxTree(new CheckboxTree.CheckboxTreeCellRenderer() {
@Override
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
String valueOfNode = getValueOfNode(value);
if (valueOfNode != null) {
getTextRenderer().append(valueOfNode);
}
}
}, myRoot) {
@Override
protected void onNodeStateChanged(CheckedTreeNode node) {
boolean state = node.isChecked();
Object userObject = node.getUserObject();
if(userObject instanceof IdeaPluginDescriptor) {
Set<String> deepDependencies = new THashSet<String>();
collectDeepDependencies(deepDependencies, (IdeaPluginDescriptor)userObject);
setupChecked(myRoot, deepDependencies, state);
}
repaint();
}
};
TreeUtil.sort(myRoot, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
String stringValue1 = getValueOfNode(o1);
String stringValue2 = getValueOfNode(o2);
if (stringValue1 != null && stringValue2 != null) {
return stringValue1.compareToIgnoreCase(stringValue2);
}
return 0;
}
});
checkboxTree.setRootVisible(false);
TreeUtil.expandAll(checkboxTree);
add(ScrollPaneFactory.createScrollPane(checkboxTree, true), BorderLayout.CENTER);
}
private void collectDeepDependencies(Set<String> deepDependencies, IdeaPluginDescriptor ideaPluginDescriptor) {
for (PluginId depPluginId : ideaPluginDescriptor.getDependentPluginIds()) {
String idString = depPluginId.getIdString();
deepDependencies.add(idString);
for (IdeaPluginDescriptor pluginDescriptor : myPluginDescriptors.values()) {
if(pluginDescriptor.getPluginId().equals(depPluginId)) {
collectDeepDependencies(deepDependencies, pluginDescriptor);
}
}
}
}
private static String getValueOfNode(Object value) {
if (value instanceof CheckedTreeNode) {
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if (!(userObject instanceof IdeaPluginDescriptor)) {
return null;
}
return ((IdeaPluginDescriptor)userObject).getName();
}
else if (value instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if (!(userObject instanceof String)) {
return null;
}
return (String)userObject;
}
return null;
}
@Override
public boolean beforeShown(boolean forward) {
if (myTemplateStepPanel == null) {
return false;
}
Set<String> enablePluginSet = myTemplateStepPanel.getEnablePluginSet();
setupChecked(myRoot, enablePluginSet, null);
return false;
}
private static void setupChecked(DefaultMutableTreeNode treeNode, Set<String> set, Boolean state) {
Object userObject = treeNode.getUserObject();
if (userObject instanceof IdeaPluginDescriptor) {
String id = ((IdeaPluginDescriptor)userObject).getPluginId().getIdString();
boolean contains = set.contains(id);
if(state == null) {
((CheckedTreeNode)treeNode).setChecked(contains);
}
else if(contains) {
((CheckedTreeNode)treeNode).setChecked(state);
}
}
int childCount = treeNode.getChildCount();
for (int i = 0; i < childCount; i++) {
DefaultMutableTreeNode childAt = (DefaultMutableTreeNode)treeNode.getChildAt(i);
setupChecked(childAt, set, state);
}
}
@NotNull
public Set<IdeaPluginDescriptor> getPluginsForDownload() {
Set<IdeaPluginDescriptor> set = new THashSet<IdeaPluginDescriptor>();
collect(myRoot, set);
return set;
}
private static void collect(DefaultMutableTreeNode treeNode, Set<IdeaPluginDescriptor> set) {
Object userObject = treeNode.getUserObject();
if (userObject instanceof IdeaPluginDescriptor) {
CheckedTreeNode checkedTreeNode = (CheckedTreeNode)treeNode;
if (checkedTreeNode.isChecked()) {
set.add(((IdeaPluginDescriptor)userObject));
}
}
int childCount = treeNode.getChildCount();
for (int i = 0; i < childCount; i++) {
DefaultMutableTreeNode childAt = (DefaultMutableTreeNode)treeNode.getChildAt(i);
collect(childAt, set);
}
}
@Override
public String getTitle() {
return "Plugins";
}
@Override
public String getHTMLHeader() {
return "<html><body><h2>Select Plugins For Download</h2></body></html>";
}
@Override
public String getHTMLFooter() {
return null;
}
}