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