2ebbc075c768177f65053857b37e8e60bc334f1f
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / compiler / GroovyCompilerConfigurable.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.jetbrains.plugins.groovy.compiler;
18
19 import com.intellij.compiler.options.JavaCompilersTab;
20 import com.intellij.compiler.server.BuildManager;
21 import com.intellij.ide.DataManager;
22 import com.intellij.openapi.compiler.options.ExcludedEntriesConfigurable;
23 import com.intellij.openapi.compiler.options.ExcludesConfiguration;
24 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
25 import com.intellij.openapi.module.Module;
26 import com.intellij.openapi.module.ModuleManager;
27 import com.intellij.openapi.options.Configurable;
28 import com.intellij.openapi.options.ConfigurationException;
29 import com.intellij.openapi.options.SearchableConfigurable;
30 import com.intellij.openapi.options.ex.Settings;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.roots.ModuleRootManager;
33 import com.intellij.openapi.roots.ProjectFileIndex;
34 import com.intellij.openapi.roots.ProjectRootManager;
35 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
36 import com.intellij.openapi.util.Comparing;
37 import com.intellij.openapi.util.io.FileUtil;
38 import com.intellij.openapi.vfs.VirtualFile;
39 import com.intellij.ui.ColorUtil;
40 import com.intellij.ui.IdeBorderFactory;
41 import com.intellij.ui.components.JBCheckBox;
42 import com.intellij.util.containers.ContainerUtil;
43 import com.intellij.util.ui.GridBag;
44 import com.intellij.util.ui.JBUI;
45 import com.intellij.util.ui.UI;
46 import com.intellij.util.ui.UIUtil;
47 import org.jetbrains.annotations.Nls;
48 import org.jetbrains.annotations.NotNull;
49 import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
50
51 import javax.swing.*;
52 import javax.swing.event.HyperlinkEvent;
53 import javax.swing.text.DefaultCaret;
54 import javax.swing.text.EditorKit;
55 import javax.swing.text.html.HTMLEditorKit;
56 import javax.swing.text.html.StyleSheet;
57 import java.awt.*;
58 import java.util.List;
59
60 /**
61  * @author peter
62  */
63 public class GroovyCompilerConfigurable implements SearchableConfigurable, Configurable.NoScroll {
64   private final Project myProject;
65   private JPanel myMainPanel;
66   private JPanel myExcludesPanel;
67   private JBCheckBox myInvokeDynamicSupportCB;
68   private TextFieldWithBrowseButton myConfigScriptPath;
69   private JPanel myPathPanel;
70
71   private final ExcludedEntriesConfigurable myExcludes;
72   private final GroovyCompilerConfiguration myConfig;
73
74   public GroovyCompilerConfigurable(Project project) {
75     myProject = project;
76     myConfig = GroovyCompilerConfiguration.getInstance(project);
77     myExcludes = createExcludedConfigurable(project);
78
79     myExcludesPanel.setBorder(IdeBorderFactory.createTitledBorder("Exclude from stub generation:", false, JBUI.insetsTop(8)).setShowLine(false));
80   }
81
82   public ExcludedEntriesConfigurable getExcludes() {
83     return myExcludes;
84   }
85
86   private ExcludedEntriesConfigurable createExcludedConfigurable(final Project project) {
87     final ExcludesConfiguration configuration = myConfig.getExcludeFromStubGeneration();
88     final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
89     final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, false, false, false, true) {
90       @Override
91       public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
92         return super.isFileVisible(file, showHiddenFiles) && !index.isExcluded(file);
93       }
94     };
95     descriptor.setRoots(ContainerUtil.concat(ContainerUtil.<Module, List<VirtualFile>>map(ModuleManager.getInstance(project).getModules(),
96                                                     module -> ModuleRootManager.getInstance(module)
97                                                       .getSourceRoots(JavaModuleSourceRootTypes.SOURCES))));
98     return new ExcludedEntriesConfigurable(project, descriptor, configuration);
99   }
100
101
102   @Override
103   @NotNull
104   public String getId() {
105     return "Groovy compiler";
106   }
107
108   @Override
109   @Nls
110   public String getDisplayName() {
111     return "Groovy Compiler";
112   }
113
114   @Override
115   public String getHelpTopic() {
116     return "reference.projectsettings.compiler.groovy";
117   }
118
119   @Override
120   public JComponent createComponent() {
121     myExcludesPanel.add(myExcludes.createComponent());
122     return myMainPanel;
123   }
124
125   @Override
126   public boolean isModified() {
127     return !Comparing.equal(myConfig.getConfigScript(), getExternalizableConfigScript()) ||
128            myInvokeDynamicSupportCB.isSelected() != myConfig.isInvokeDynamic() ||
129            myExcludes.isModified();
130   }
131
132   @Override
133   public void apply() throws ConfigurationException {
134     myExcludes.apply();
135     myConfig.setInvokeDynamic(myInvokeDynamicSupportCB.isSelected());
136     myConfig.setConfigScript(getExternalizableConfigScript());
137     BuildManager.getInstance().clearState(myProject);
138   }
139
140   @Override
141   public void reset() {
142     myConfigScriptPath.setText(FileUtil.toSystemDependentName(myConfig.getConfigScript()));
143     myInvokeDynamicSupportCB.setSelected(myConfig.isInvokeDynamic());
144     myExcludes.reset();
145   }
146
147   @Override
148   public void disposeUIResources() {
149     myExcludes.disposeUIResources();
150   }
151
152   @NotNull
153   private String getExternalizableConfigScript() {
154     return FileUtil.toSystemIndependentName(myConfigScriptPath.getText());
155   }
156
157   private void createUIComponents() {
158     myPathPanel = new JPanel(new GridBagLayout());
159     GridBag gb = new GridBag().setDefaultWeightX(1.0).
160       setDefaultAnchor(GridBagConstraints.LINE_START).
161       setDefaultFill(GridBagConstraints.HORIZONTAL);
162
163     FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false);
164     myConfigScriptPath = new TextFieldWithBrowseButton();
165     myConfigScriptPath.addBrowseFolderListener(null, "Select path to Groovy compiler configscript", null, descriptor);
166
167     myPathPanel.add(createTopLabel(), gb.nextLine());
168     myPathPanel.add(UI.PanelFactory.panel(myConfigScriptPath).withLabel("Path to &configscript:").createPanel(), gb.nextLine().insetTop(13));
169
170     String cbText = "Invoke &dynamic support";
171     myInvokeDynamicSupportCB = new JBCheckBox(UIUtil.removeMnemonic(cbText));
172     myInvokeDynamicSupportCB.setDisplayedMnemonicIndex(UIUtil.getDisplayMnemonicIndex(cbText));
173     myPathPanel.add(myInvokeDynamicSupportCB, gb.nextLine().insetTop(8));
174   }
175
176   private static JComponent createTopLabel() {
177     JEditorPane tipComponent = new JEditorPane();
178     tipComponent.setContentType("text/html");
179     tipComponent.setEditable(false);
180     tipComponent.setEditorKit(UIUtil.getHTMLEditorKit());
181
182     EditorKit kit = tipComponent.getEditorKit();
183     if (kit instanceof HTMLEditorKit) {
184       StyleSheet css = ((HTMLEditorKit)kit).getStyleSheet();
185
186       css.addRule("a, a:link {color:#" + ColorUtil.toHex(JBUI.CurrentTheme.Link.linkColor()) + ";}");
187       css.addRule("a:visited {color:#" + ColorUtil.toHex(JBUI.CurrentTheme.Link.linkVisitedColor()) + ";}");
188       css.addRule("a:hover {color:#" + ColorUtil.toHex(JBUI.CurrentTheme.Link.linkHoverColor()) + ";}");
189       css.addRule("a:active {color:#" + ColorUtil.toHex(JBUI.CurrentTheme.Link.linkPressedColor()) + ";}");
190       //css.addRule("body {background-color:#" + ColorUtil.toHex(info.warning ? warningBackgroundColor() : errorBackgroundColor()) + ";}");
191     }
192
193     if (tipComponent.getCaret() instanceof DefaultCaret) {
194       ((DefaultCaret)tipComponent.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
195     }
196
197     tipComponent.setCaretPosition(0);
198     tipComponent.setText("Alternatively, you can specify Groovy-Eclipse compiler at <a href=\"#\">Java Compiler page</a>");
199     tipComponent.addHyperlinkListener(e -> {
200       if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
201         Settings allSettings = Settings.KEY.getData(DataManager.getInstance().getDataContext(tipComponent));
202         if (allSettings != null) {
203           Configurable javacConfigurable = allSettings.find(JavaCompilersTab.class);
204           if (javacConfigurable != null) {
205             allSettings.select(javacConfigurable);
206           }
207         }
208       }
209     });
210
211     tipComponent.setBorder(null);
212     tipComponent.setOpaque(false);
213
214     return tipComponent;
215   }
216 }