package com.google.jstestdriver.idea.execution.settings.ui;
import com.intellij.javascript.testFramework.TestFileStructureManager;
import com.intellij.javascript.testFramework.TestFileStructurePack;
import com.google.jstestdriver.idea.execution.settings.JstdRunSettings;
import com.google.jstestdriver.idea.util.SwingUtils;
import com.google.jstestdriver.idea.util.TextChangeListener;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
public class TestCaseRunSettingsSection extends AbstractRunSettingsSection {
private final JsFileRunSettingsSection myJsFileRunSettingsSection;
private final JComboBox myTestCaseNameComboBox;
private final JBLabel myLabel;
private final TestMethodRunSettingsSection myTestMethodSettingsSection;
TestCaseRunSettingsSection() {
this(null);
}
TestCaseRunSettingsSection(@Nullable TestMethodRunSettingsSection testMethodSettingsSection) {
myTestMethodSettingsSection = testMethodSettingsSection;
myJsFileRunSettingsSection = new JsFileRunSettingsSection();
myTestCaseNameComboBox = createComboBox();
myLabel = new JBLabel("Case:");
setAnchor(SwingUtils.getWiderComponent(myLabel, myJsFileRunSettingsSection));
}
private void trackJsTestFilePathChanges(@NotNull final Project project) {
SwingUtils.addTextChangeListener(
myJsFileRunSettingsSection.getJsTestFileTextField(),
new TextChangeListener() {
@Override
public void textChanged(String oldJsTestFilePath, @NotNull String newJsTestFilePath) {
String oldValue = getTestCaseName();
try {
updateTestCaseVariants(project, newJsTestFilePath);
fireStateChanged(project);
}
finally {
myTestCaseNameComboBox.setSelectedItem(oldValue);
}
}
}
);
myTestCaseNameComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
fireStateChanged(project);
}
});
}
private void fireStateChanged(@NotNull Project project) {
String jsTestFilePath = myJsFileRunSettingsSection.getJsTestFileTextField().getText();
String testCaseName = getTestCaseName();
if (myTestMethodSettingsSection != null) {
myTestMethodSettingsSection.stateChanged(project, jsTestFilePath, testCaseName);
}
}
private void updateTestCaseVariants(@NotNull Project project, @NotNull String jsTestFilePath) {
myTestCaseNameComboBox.removeAllItems();
VirtualFile jsTestVirtualFile = VfsUtil.findFileByIoFile(new File(jsTestFilePath), false);
if (jsTestVirtualFile == null) {
return;
}
JSFile jsFile = ObjectUtils.tryCast(PsiManager.getInstance(project).findFile(jsTestVirtualFile), JSFile.class);
if (jsFile == null) {
return;
}
TestFileStructurePack pack = TestFileStructureManager.fetchTestFileStructurePackByJsFile(jsFile);
if (pack != null) {
for (Object topLevel : pack.getTopLevelElements()) {
myTestCaseNameComboBox.addItem(topLevel);
}
}
}
private String getTestCaseName() {
Object value = myTestCaseNameComboBox.getSelectedItem();
return value == null ? "" : value.toString();
}
private static JComboBox createComboBox() {
JComboBox comboBox = new JComboBox();
comboBox.setRenderer(new ListCellRendererWrapper<String>() {
@Override
public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
setText(value);
}
});
comboBox.setEditable(true);
return comboBox;
}
@Override
public void resetFrom(@NotNull JstdRunSettings runSettings) {
myJsFileRunSettingsSection.resetFrom(runSettings);
myTestCaseNameComboBox.setSelectedItem(runSettings.getTestCaseName());
}
@Override
public void applyTo(@NotNull JstdRunSettings.Builder runSettingsBuilder) {
myJsFileRunSettingsSection.applyTo(runSettingsBuilder);
String testCaseName = getTestCaseName();
runSettingsBuilder.setTestCaseName(testCaseName);
}
@NotNull
@Override
protected JComponent createComponent(@NotNull CreationContext creationContext) {
JPanel panel = new JPanel(new GridBagLayout());
{
GridBagConstraints c = new GridBagConstraints(
0, 0,
2, 1,
1.0, 0.0,
GridBagConstraints.NORTHWEST,
GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0),
0, 0
);
JComponent jsFileComponent = myJsFileRunSettingsSection.getComponent(creationContext);
panel.add(jsFileComponent, c);
}
{
myLabel.setDisplayedMnemonic('e');
myLabel.setHorizontalAlignment(SwingConstants.RIGHT);
GridBagConstraints c = new GridBagConstraints(
0, 1,
1, 1,
0.0, 0.0,
GridBagConstraints.EAST,
GridBagConstraints.NONE,
new Insets(UIUtil.DEFAULT_VGAP, 0, 0, UIUtil.DEFAULT_HGAP),
0, 0
);
panel.add(myLabel, c);
}
{
GridBagConstraints c = new GridBagConstraints(
1, 1,
1, 1,
1.0, 0.0,
GridBagConstraints.WEST,
GridBagConstraints.HORIZONTAL,
new Insets(UIUtil.DEFAULT_VGAP, 0, 0, 0),
0, 0
);
panel.add(myTestCaseNameComboBox, c);
myLabel.setLabelFor(myTestCaseNameComboBox);
}
SwingUtils.addGreedyBottomRow(panel);
trackJsTestFilePathChanges(creationContext.getProject());
return panel;
}
@Override
public void setAnchor(@Nullable JComponent anchor) {
super.setAnchor(anchor);
myLabel.setAnchor(anchor);
myJsFileRunSettingsSection.setAnchor(anchor);
}
}