IDEA-257029 IntelliJ IDEA 2020.3 GUI: Configuration Window textfield does not scale...
[idea/community.git] / platform / execution-impl / src / com / intellij / execution / ui / CommonParameterFragments.java
1 // Copyright 2000-2020 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.execution.ui;
3
4 import com.intellij.execution.CommonProgramRunConfigurationParameters;
5 import com.intellij.execution.ExecutionBundle;
6 import com.intellij.execution.InputRedirectAware;
7 import com.intellij.execution.configuration.EnvironmentVariablesComponent;
8 import com.intellij.ide.macro.MacrosDialog;
9 import com.intellij.openapi.editor.ex.util.EditorUtil;
10 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
11 import com.intellij.openapi.project.Project;
12 import com.intellij.openapi.ui.ComponentWithBrowseButton;
13 import com.intellij.openapi.ui.LabeledComponent;
14 import com.intellij.openapi.ui.TextComponentAccessor;
15 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
16 import com.intellij.openapi.util.Computable;
17 import com.intellij.openapi.util.io.FileUtil;
18 import com.intellij.openapi.vfs.LocalFileSystem;
19 import com.intellij.openapi.vfs.VirtualFile;
20 import com.intellij.ui.RawCommandLineEditor;
21 import com.intellij.ui.components.fields.ExtendableTextField;
22 import com.intellij.util.ui.JBUI;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
25
26 import javax.swing.*;
27 import java.awt.*;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31
32 import static com.intellij.openapi.util.text.StringUtil.*;
33
34 public class CommonParameterFragments<Settings extends CommonProgramRunConfigurationParameters> {
35
36   private final List<SettingsEditorFragment<Settings, ?>> myFragments = new ArrayList<>();
37   private final SettingsEditorFragment<Settings, LabeledComponent<TextFieldWithBrowseButton>> myWorkingDirectory;
38   private final Computable<Boolean> myHasModule;
39
40   public CommonParameterFragments(@NotNull Project project, Computable<Boolean> hasModule) {
41     myHasModule = hasModule;
42     TextFieldWithBrowseButton workingDirectoryField = new TextFieldWithBrowseButton();
43     workingDirectoryField.addBrowseFolderListener(ExecutionBundle.message("select.working.directory.message"), null,
44                                                     project,
45                                                     FileChooserDescriptorFactory.createSingleFolderDescriptor(),
46                                                     TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT);
47     MacrosDialog.addMacroSupport((ExtendableTextField)workingDirectoryField.getTextField(), MacrosDialog.Filters.DIRECTORY_PATH, hasModule);
48     LabeledComponent<TextFieldWithBrowseButton> field = LabeledComponent.create(workingDirectoryField, ExecutionBundle.message(
49                                                                                        "run.configuration.working.directory.label"));
50     field.setLabelLocation(BorderLayout.WEST);
51     myWorkingDirectory = new SettingsEditorFragment<>("workingDirectory", null, null, field,
52                                                       (settings, component) -> component.getComponent()
53                                                         .setText(settings.getWorkingDirectory()),
54                                                       (settings, component) -> settings
55                                                         .setWorkingDirectory(component.getComponent().getText()),
56                                                       settings -> isNotEmpty(settings.getWorkingDirectory()));
57     myFragments.add(myWorkingDirectory);
58     myFragments.add(createEnvParameters());
59   }
60
61   @NotNull
62   public SettingsEditorFragment<Settings, RawCommandLineEditor> programArguments() {
63     RawCommandLineEditor programArguments = new RawCommandLineEditor();
64     CommandLinePanel.setMinimumWidth(programArguments, 400);
65     String message = ExecutionBundle.message("run.configuration.program.parameters.placeholder");
66     programArguments.getEditorField().getEmptyText().setText(message);
67     programArguments.getEditorField().getAccessibleContext().setAccessibleName(message);
68     FragmentedSettingsUtil.setupPlaceholderVisibility(programArguments.getEditorField());
69     setMonospaced(programArguments.getTextField());
70     MacrosDialog.addMacroSupport(programArguments.getEditorField(), MacrosDialog.Filters.ALL, myHasModule);
71     SettingsEditorFragment<Settings, RawCommandLineEditor> parameters =
72       new SettingsEditorFragment<>("commandLineParameters", ExecutionBundle.message("run.configuration.program.parameters.name"), null, programArguments,
73                                    100,
74                                    (settings, component) -> component.setText(settings.getProgramParameters()),
75                                    (settings, component) -> settings.setProgramParameters(component.getText()),
76                                    settings -> true);
77     parameters.setRemovable(false);
78     parameters.setEditorGetter(editor -> editor.getEditorField());
79     parameters.setHint(ExecutionBundle.message("run.configuration.program.parameters.hint"));
80     return parameters;
81   }
82
83   public List<SettingsEditorFragment<Settings, ?>> getFragments() {
84     return myFragments;
85   }
86
87   public <S extends InputRedirectAware> SettingsEditorFragment<S, ?> createRedirectFragment() {
88     TextFieldWithBrowseButton inputFile = new TextFieldWithBrowseButton();
89     inputFile.addActionListener(new ComponentWithBrowseButton.BrowseFolderActionListener<>(null, null, inputFile, null,
90                                                                                            FileChooserDescriptorFactory
91                                                                                              .createSingleFileDescriptor(),
92                                                                                            TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
93       @Override
94       protected @Nullable VirtualFile getInitialFile() {
95         VirtualFile initialFile = super.getInitialFile();
96         if (initialFile != null) {
97           return initialFile;
98         }
99         String text = myWorkingDirectory.component().getComponent().getText();
100         return LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(text));
101       }
102     });
103
104     MacrosDialog.addMacroSupport((ExtendableTextField)inputFile.getTextField(), MacrosDialog.Filters.ALL, myHasModule);
105     LabeledComponent<TextFieldWithBrowseButton> labeledComponent =
106       LabeledComponent.create(inputFile, ExecutionBundle.message("redirect.input.from"));
107     labeledComponent.setLabelLocation(BorderLayout.WEST);
108     SettingsEditorFragment<S, LabeledComponent<TextFieldWithBrowseButton>> redirectInput =
109       new SettingsEditorFragment<>("redirectInput", ExecutionBundle.message("redirect.input.from.name"),
110                                    ExecutionBundle.message("group.operating.system"), labeledComponent,
111                                    (settings, component) -> component.getComponent().setText(
112                                      FileUtil.toSystemDependentName(notNullize(settings.getInputRedirectOptions().getRedirectInputPath()))),
113                                    (settings, component) -> {
114                                      String filePath = component.getComponent().getText();
115                                      settings.getInputRedirectOptions().setRedirectInput(component.isVisible() && isNotEmpty(filePath));
116                                      settings.getInputRedirectOptions().setRedirectInputPath(
117                                        isEmpty(filePath) ? null : FileUtil.toSystemIndependentName(filePath));
118                                    },
119                                    settings -> isNotEmpty(settings.getInputRedirectOptions().getRedirectInputPath()));
120     redirectInput.setActionHint(ExecutionBundle.message("read.input.from.the.specified.file"));
121     return redirectInput;
122   }
123
124   public static <S extends CommonProgramRunConfigurationParameters> SettingsEditorFragment<S, ?> createEnvParameters() {
125     EnvironmentVariablesComponent env = new EnvironmentVariablesComponent();
126     env.setLabelLocation(BorderLayout.WEST);
127     setMonospaced(env.getComponent().getTextField());
128     SettingsEditorFragment<S, JComponent> fragment =
129       new SettingsEditorFragment<>("environmentVariables", ExecutionBundle.message("environment.variables.fragment.name"),
130                                    ExecutionBundle.message("group.operating.system"), env,
131                                    (settings, c) -> env.reset(settings),
132                                    (settings, c) -> {
133                                      if (!env.isVisible()) {
134                                        settings.setEnvs(Collections.emptyMap());
135                                        settings.setPassParentEnvs(true);
136                                      }
137                                      else
138                                        env.apply(settings);
139                                    },
140                                    s -> true);
141     fragment.setCanBeHidden(true);
142     fragment.setHint(ExecutionBundle.message("environment.variables.fragment.hint"));
143     fragment.setActionHint(ExecutionBundle.message("set.custom.environment.variables.for.the.process"));
144     return fragment;
145   }
146
147   public static void setMonospaced(Component field) {
148     field.setFont(EditorUtil.getEditorFont().deriveFont(Font.PLAIN, JBUI.Fonts.label().getSize()));
149   }
150 }