/*
* Copyright 2003-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 jetbrains.mps.intentions;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.Configurable.Composite;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckboxTree.CheckboxTreeCellRenderer;
import com.intellij.ui.CheckboxTreeBase.CheckPolicy;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.util.ui.tree.TreeUtil;
import jetbrains.mps.openapi.intentions.IntentionDescriptor;
import jetbrains.mps.openapi.intentions.IntentionFactory;
import jetbrains.mps.smodel.language.LanguageRuntime;
import jetbrains.mps.util.StringUtil;
import org.jetbrains.annotations.Nls;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTree;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class IntentionSettingsConfigurable implements Configurable, Composite {
private IntentionsManager myIntentionsManager;
private CheckboxTree myTree;
private Map<String, LanguageTreeNode> myLanguageTreeNodes = new HashMap<String, LanguageTreeNode>();
public IntentionSettingsConfigurable(IntentionsManager intentionsManager) {
myIntentionsManager = intentionsManager;
}
@Nls
@Override
public String getDisplayName() {
return "Intentions";
}
@Override
public String getHelpTopic() {
// MPS-13404
return "preferences.intentionPowerPack";
}
@Override
public JComponent createComponent() {
initCheckBoxes();
CheckedTreeNode rootNode = new CheckedTreeNode(null);
for (LanguageTreeNode languageTreeNode : myLanguageTreeNodes.values()) {
rootNode.add(languageTreeNode);
}
myTree = new CheckboxTree(getCheckboxTreeCellRenderer(), rootNode, new CheckPolicy(true, true, true, false));
myTree.setRootVisible(false);
TreeUtil.expandAll(myTree);
JPanel mainPanel = new JPanel(new GridLayoutManager(1, 1));
mainPanel.add(ScrollPaneFactory.createScrollPane(myTree), new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_BOTH,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
null, null, null));
return mainPanel;
}
private void initCheckBoxes() {
Map<LanguageRuntime, Collection<IntentionFactory>> allIntentionFactories = myIntentionsManager.getAllIntentionFactories();
List<LanguageRuntime> runtimes = new ArrayList<>(allIntentionFactories.keySet());
runtimes.sort((LanguageRuntime l1, LanguageRuntime l2) -> StringUtil.compare(l1.getNamespace(), l2.getNamespace()));
for (LanguageRuntime runtime : runtimes) {
List<IntentionDescriptor> intentions = new ArrayList<>(allIntentionFactories.get(runtime));
intentions.sort(
(IntentionDescriptor i1, IntentionDescriptor i2) -> StringUtil.compare(i1.getPresentation().toLowerCase(), i2.getPresentation().toLowerCase()));
for (IntentionDescriptor descriptor : intentions) {
LanguageTreeNode langTreeNode = myLanguageTreeNodes.computeIfAbsent(runtime.getNamespace(), k -> new LanguageTreeNode(runtime.getNamespace()));
langTreeNode.add(new IntentionTreeNode(descriptor));
}
}
}
@Override
public boolean isModified() {
for (LanguageTreeNode languageTreeNode : myLanguageTreeNodes.values()) {
Enumeration<IntentionTreeNode> intentionTreeNode = languageTreeNode.children();
while (intentionTreeNode.hasMoreElements()) {
if (intentionTreeNode.nextElement().isModified()) {
return true;
}
}
}
return false;
}
@Override
public void apply() throws ConfigurationException {
for (LanguageTreeNode languageTreeNode : myLanguageTreeNodes.values()) {
Enumeration<IntentionTreeNode> intentionTreeNode = languageTreeNode.children();
while (intentionTreeNode.hasMoreElements()) {
intentionTreeNode.nextElement().apply();
}
}
}
@Override
public void reset() {
for (LanguageTreeNode languageTreeNode : myLanguageTreeNodes.values()) {
Enumeration<IntentionTreeNode> intentionTreeNode = languageTreeNode.children();
while (intentionTreeNode.hasMoreElements()) {
intentionTreeNode.nextElement().reset();
}
}
}
@Override
public void disposeUIResources() {
myTree = null;
}
@Override
public Configurable[] getConfigurables() {
return new Configurable[0];
}
private class LanguageTreeNode extends CheckedTreeNode {
public LanguageTreeNode(final String languageFqName) {
super(languageFqName);
}
@Override
public String getUserObject() {
return (String) super.getUserObject();
}
}
private class IntentionTreeNode extends CheckedTreeNode {
private final String myPersistentStateKey;
public IntentionTreeNode(final IntentionDescriptor intentionDescriptor) {
super(intentionDescriptor);
myPersistentStateKey = intentionDescriptor.getPersistentStateKey();
}
@Override
public IntentionDescriptor getUserObject() {
return (IntentionDescriptor) super.getUserObject();
}
private boolean isModified() {
return myIntentionsManager.isIntentionDisabled(myPersistentStateKey) == isChecked();
}
private void apply() {
myIntentionsManager.setIntentionState(myPersistentStateKey, !isChecked());
}
private void reset() {
setChecked(!myIntentionsManager.isIntentionDisabled(myPersistentStateKey));
}
}
private static CheckboxTreeCellRenderer getCheckboxTreeCellRenderer() {
return new CheckboxTreeCellRenderer() {
@Override
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.customizeRenderer(tree, value, selected, expanded, leaf, row, hasFocus);
ColoredTreeCellRenderer renderer = getTextRenderer();
JCheckBox checkBox = getCheckbox();
if (value instanceof IntentionTreeNode) {
IntentionTreeNode intentionTreeNode = (IntentionTreeNode) value;
renderer.append(intentionTreeNode.getUserObject().getPresentation());
checkBox.setSelected(intentionTreeNode.isChecked());
} else if (value instanceof LanguageTreeNode) {
LanguageTreeNode languageTreeNode = (LanguageTreeNode) value;
renderer.append(languageTreeNode.getUserObject());
checkBox.setSelected(languageTreeNode.isChecked());
}
}
};
}
}