Cleanup: NotNull/Nullable
[idea/community.git] / java / compiler / impl / src / com / intellij / compiler / actions / GenerateAntBuildDialog.java
1 // Copyright 2000-2018 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 package com.intellij.compiler.actions;
3
4 import com.intellij.compiler.HelpID;
5 import com.intellij.compiler.ModuleCompilerUtil;
6 import com.intellij.compiler.ant.BuildProperties;
7 import com.intellij.ide.util.PropertiesComponent;
8 import com.intellij.openapi.compiler.CompilerBundle;
9 import com.intellij.openapi.module.Module;
10 import com.intellij.openapi.module.ModuleManager;
11 import com.intellij.openapi.project.Project;
12 import com.intellij.openapi.ui.DialogWrapper;
13 import com.intellij.openapi.ui.MultiLineLabelUI;
14 import com.intellij.openapi.util.Pair;
15 import com.intellij.openapi.util.text.StringUtil;
16 import com.intellij.ui.IdeBorderFactory;
17 import com.intellij.ui.ScrollPaneFactory;
18 import com.intellij.util.ArrayUtil;
19 import com.intellij.util.Chunk;
20 import com.intellij.util.ListWithSelection;
21 import com.intellij.util.ui.JBUI;
22 import com.intellij.util.ui.Table;
23 import com.intellij.util.ui.table.ComboBoxTableCellEditor;
24 import org.jetbrains.annotations.NonNls;
25
26 import javax.swing.*;
27 import javax.swing.table.AbstractTableModel;
28 import javax.swing.table.DefaultTableCellRenderer;
29 import javax.swing.table.TableCellEditor;
30 import javax.swing.table.TableColumn;
31 import java.awt.*;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Iterator;
35 import java.util.List;
36
37 /**
38  * @author Eugene Zhuravlev
39  */
40 public class GenerateAntBuildDialog extends DialogWrapper {
41   private JPanel myPanel;
42   private JRadioButton myRbGenerateSingleFileBuild;
43   private JRadioButton myRbGenerateMultipleFilesBuild;
44   private JCheckBox myCbEnableUIFormsCompilation;
45   private JRadioButton myRbBackupFiles;
46   private JRadioButton myRbOverwriteFiles;
47   private JCheckBox myCbForceTargetJdk;
48   private JCheckBox myCbInlineRuntimeClasspath;
49   private JPanel myChunksPanel;
50   private JCheckBox myGenerateIdeaHomeProperty;
51   private JTextField myOutputFileNameField;
52   private final Project myProject;
53   @NonNls private static final String SINGLE_FILE_PROPERTY = "GenerateAntBuildDialog.generateSingleFile";
54   @NonNls private static final String UI_FORM_PROPERTY = "GenerateAntBuildDialog.enableUiFormCompile";
55   @NonNls private static final String FORCE_TARGET_JDK_PROPERTY = "GenerateAntBuildDialog.forceTargetJdk";
56   @NonNls private static final String BACKUP_FILES_PROPERTY = "GenerateAntBuildDialog.backupFiles";
57   @NonNls private static final String INLINE_RUNTIME_CLASSPATH_PROPERTY = "GenerateAntBuildDialog.inclineRuntiemClasspath";
58   @NonNls private static final String GENERATE_IDEA_HOME_PROPERTY = "GenerateAntBuildDialog.generateIdeaHomeProperty";
59   @NonNls private static final String OUTPUT_FILE_NAME_PROPERTY = "GenerateAntBuildDialog.outputFileNameProperty";
60   private MyTableModel myTableModel;
61   private Table myTable;
62
63   public GenerateAntBuildDialog(Project project) {
64     super(project, false);
65     myProject = project;
66     setTitle(CompilerBundle.message("generate.ant.build.title"));
67     init();
68     loadSettings();
69   }
70
71   private List<Chunk<Module>> getCycleChunks() {
72     List<Chunk<Module>> chunks =
73       ModuleCompilerUtil.getSortedModuleChunks(myProject, Arrays.asList(ModuleManager.getInstance(myProject).getModules()));
74     for (Iterator<Chunk<Module>> it = chunks.iterator(); it.hasNext();) {
75       final Chunk<Module> chunk = it.next();
76       if (chunk.getNodes().size() == 1) {
77         it.remove();
78       }
79     }
80     return chunks;
81   }
82
83   private void loadSettings() {
84     final PropertiesComponent properties = PropertiesComponent.getInstance(myProject);
85     if (properties.isValueSet(SINGLE_FILE_PROPERTY)) {
86       final boolean singleFile = properties.isTrueValue(SINGLE_FILE_PROPERTY);
87       myRbGenerateSingleFileBuild.setSelected(singleFile);
88       myRbGenerateMultipleFilesBuild.setSelected(!singleFile);
89     }
90     if (properties.isValueSet(UI_FORM_PROPERTY)) {
91       myCbEnableUIFormsCompilation.setSelected(properties.isTrueValue(UI_FORM_PROPERTY));
92     }
93     if (properties.isValueSet(FORCE_TARGET_JDK_PROPERTY)) {
94       myCbForceTargetJdk.setSelected(properties.isTrueValue(FORCE_TARGET_JDK_PROPERTY));
95     }
96     if (properties.isValueSet(BACKUP_FILES_PROPERTY)) {
97       final boolean backup = properties.isTrueValue(BACKUP_FILES_PROPERTY);
98       myRbBackupFiles.setSelected(backup);
99       myRbOverwriteFiles.setSelected(!backup);
100     }
101     if (properties.isValueSet(INLINE_RUNTIME_CLASSPATH_PROPERTY)) {
102       myCbInlineRuntimeClasspath.setSelected(properties.isTrueValue(INLINE_RUNTIME_CLASSPATH_PROPERTY));
103     }
104     if (properties.isValueSet(GENERATE_IDEA_HOME_PROPERTY)) {
105       myGenerateIdeaHomeProperty.setSelected(properties.isTrueValue(GENERATE_IDEA_HOME_PROPERTY));
106     }
107     if (properties.isValueSet(OUTPUT_FILE_NAME_PROPERTY)) {
108       myOutputFileNameField.setText(properties.getValue(OUTPUT_FILE_NAME_PROPERTY));
109     }
110     else {
111       myOutputFileNameField.setText(BuildProperties.getProjectBuildFileName(myProject));
112     }
113   }
114
115   private void saveSettings() {
116     final PropertiesComponent properties = PropertiesComponent.getInstance(myProject);
117     properties.setValue(SINGLE_FILE_PROPERTY, myRbGenerateSingleFileBuild.isSelected());
118     properties.setValue(UI_FORM_PROPERTY, myCbEnableUIFormsCompilation.isSelected());
119     properties.setValue(FORCE_TARGET_JDK_PROPERTY, myCbForceTargetJdk.isSelected());
120     properties.setValue(BACKUP_FILES_PROPERTY, myRbBackupFiles.isSelected());
121     properties.setValue(INLINE_RUNTIME_CLASSPATH_PROPERTY, myCbInlineRuntimeClasspath.isSelected());
122     properties.setValue(GENERATE_IDEA_HOME_PROPERTY, myGenerateIdeaHomeProperty.isSelected());
123     properties.setValue(OUTPUT_FILE_NAME_PROPERTY, StringUtil.nullize(getOutputFileName()));
124   }
125
126   @Override
127   public void dispose() {
128     saveSettings();
129     super.dispose();
130   }
131
132   @Override
133   protected JComponent createCenterPanel() {
134     final ButtonGroup group = new ButtonGroup();
135     group.add(myRbGenerateMultipleFilesBuild);
136     group.add(myRbGenerateSingleFileBuild);
137
138     final ButtonGroup group1 = new ButtonGroup();
139     group1.add(myRbBackupFiles);
140     group1.add(myRbOverwriteFiles);
141
142     myRbGenerateMultipleFilesBuild.setSelected(true);
143     myRbBackupFiles.setSelected(true);
144     myCbEnableUIFormsCompilation.setSelected(true);
145     myCbForceTargetJdk.setSelected(true);
146     myCbInlineRuntimeClasspath.setSelected(false);
147
148     initChunksPanel();
149
150     return myPanel;
151   }
152
153   private void initChunksPanel() {
154     List<Chunk<Module>> chunks = getCycleChunks();
155     if (chunks.isEmpty()) {
156       return;
157     }
158     myChunksPanel.setLayout(new BorderLayout());
159     myChunksPanel.setBorder(
160       IdeBorderFactory.createTitledBorder(CompilerBundle.message("generate.ant.build.dialog.cyclic.modules.table.title"),
161                                           true));
162     JLabel textLabel = new JLabel(CompilerBundle.message("generate.ant.build.dialog.cyclic.modules.table.description"));
163     textLabel.setUI(new MultiLineLabelUI());
164     textLabel.setBorder(JBUI.Borders.empty(4, 4, 6, 4));
165     myChunksPanel.add(textLabel, BorderLayout.NORTH);
166
167     myTableModel = new MyTableModel(chunks);
168     myTable = new Table(myTableModel);
169     final MyTableCellRenderer cellRenderer = new MyTableCellRenderer();
170     final TableColumn nameColumn = myTable.getColumnModel().getColumn(MyTableModel.NAME_COLUMN);
171     nameColumn.setCellEditor(ComboBoxTableCellEditor.INSTANCE);
172     nameColumn.setCellRenderer(cellRenderer);
173     final TableColumn labelColumn = myTable.getColumnModel().getColumn(MyTableModel.NUMBER_COLUMN);
174     labelColumn.setCellRenderer(cellRenderer);
175
176     final Dimension preferredSize = new Dimension(myTable.getPreferredSize());
177     preferredSize.height = (myTableModel.getRowCount() + 2) * myTable.getRowHeight() + myTable.getTableHeader().getHeight();
178
179     final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable);
180     scrollPane.setPreferredSize(preferredSize);
181     myChunksPanel.add(scrollPane, BorderLayout.CENTER);
182   }
183
184   @Override
185   protected void doOKAction() {
186     if (myTable != null) {
187       TableCellEditor cellEditor = myTable.getCellEditor();
188       if (cellEditor != null) {
189         cellEditor.stopCellEditing();
190       }
191     }
192     super.doOKAction();
193   }
194
195   public boolean isGenerateSingleFileBuild() {
196     return myRbGenerateSingleFileBuild.isSelected();
197   }
198
199   public boolean isFormsCompilationEnabled() {
200     return myCbEnableUIFormsCompilation.isSelected();
201   }
202
203   public boolean isForceTargetJdk() {
204     return myCbForceTargetJdk.isSelected();
205   }
206
207   public boolean isBackupFiles() {
208     return myRbBackupFiles.isSelected();
209   }
210
211   public boolean isRuntimeClasspathInlined() {
212     return myCbInlineRuntimeClasspath.isSelected();
213   }
214
215   public String[] getRepresentativeModuleNames() {
216     return myTableModel != null ? myTableModel.getModuleRepresentatives() : ArrayUtil.EMPTY_STRING_ARRAY;
217   }
218
219   /**
220    * @return true if user has selected to generate IDEA_HOME property
221    */
222   public boolean isIdeaHomeGenerated() {
223     return myGenerateIdeaHomeProperty.isSelected();
224   }
225
226   public String getOutputFileName() {
227     return myOutputFileNameField.getText().trim();
228   }
229
230   private static class MyTableModel extends AbstractTableModel {
231     private static final int NUMBER_COLUMN = 0;
232     private static final int NAME_COLUMN = 1;
233
234     private final List<Pair<String, ListWithSelection>> myItems = new ArrayList<>();
235
236     private MyTableModel(List<? extends Chunk<Module>> chunks) {
237       for (final Chunk<Module> chunk : chunks) {
238         final ListWithSelection<String> item = new ListWithSelection<>();
239         for (final Module module : chunk.getNodes()) {
240           item.add(module.getName());
241         }
242         item.selectFirst();
243         myItems.add(new Pair<>(createCycleName(chunk), item));
244       }
245     }
246
247     private static String createCycleName(Chunk<? extends Module> chunk) {
248       final StringBuilder buf = new StringBuilder();
249       for (Module module : chunk.getNodes()) {
250         if (buf.length() > 0) {
251           buf.append(", ");
252         }
253         buf.append(module.getName());
254       }
255       buf.insert(0, "[");
256       buf.append("]");
257       return buf.toString();
258     }
259
260     public String[] getModuleRepresentatives() {
261       final String[] names = new String[myItems.size()];
262       int index = 0;
263       for (final Pair<String, ListWithSelection> pair : myItems) {
264         names[index++] = (String)pair.getSecond().getSelection();
265       }
266       return names;
267     }
268
269     @Override
270     public int getColumnCount() {
271       return 2;
272     }
273
274     @Override
275     public int getRowCount() {
276       return myItems.size();
277     }
278
279     @Override
280     public boolean isCellEditable(int rowIndex, int columnIndex) {
281       return columnIndex == 1;
282     }
283
284     @Override
285     public Class getColumnClass(int columnIndex) {
286       switch (columnIndex) {
287         case NUMBER_COLUMN:
288           return String.class;
289         case NAME_COLUMN:
290           return ListWithSelection.class;
291         default:
292           return super.getColumnClass(columnIndex);
293       }
294     }
295
296     @Override
297     public Object getValueAt(int rowIndex, int columnIndex) {
298       switch (columnIndex) {
299         case NUMBER_COLUMN:
300           return myItems.get(rowIndex).getFirst();
301         case NAME_COLUMN:
302           return myItems.get(rowIndex).getSecond();
303         default:
304           return null;
305       }
306     }
307
308     @Override
309     public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
310       if (columnIndex == NAME_COLUMN) {
311         myItems.get(rowIndex).getSecond().select(aValue);
312       }
313     }
314
315     @Override
316     public String getColumnName(int columnIndex) {
317       switch (columnIndex) {
318         case NUMBER_COLUMN:
319           return CompilerBundle.message("generate.ant.build.dialog.cyclic.modules.table.number.column.header");
320         case NAME_COLUMN:
321           return CompilerBundle.message("generate.ant.build.dialog.cyclic.modules.table.name.column.header");
322       }
323       return super.getColumnName(columnIndex);
324     }
325   }
326
327   private static class MyTableCellRenderer extends DefaultTableCellRenderer {
328     @Override
329     public Component getTableCellRendererComponent(JTable table,
330                                                    Object value,
331                                                    boolean isSelected,
332                                                    boolean hasFocus,
333                                                    int row,
334                                                    int column) {
335       if (value instanceof ListWithSelection) {
336         value = ((ListWithSelection)value).getSelection();
337       }
338       final JLabel component = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
339       component.setHorizontalAlignment(SwingConstants.CENTER);
340       return component;
341     }
342   }
343
344   @Override
345   protected String getHelpId() {
346     return HelpID.GENERATE_ANT_BUILD;
347   }
348 }