package com.intellij.lang.javascript.flex.projectStructure.ui;
import com.intellij.flex.model.bc.CompilerOptionInfo;
import com.intellij.lang.javascript.flex.FlexUtils;
import com.intellij.lang.javascript.flex.build.AddRemoveTableRowsDialog;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.TableUtil;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.List;
import static com.intellij.flex.model.bc.CompilerOptionInfo.ListElementType;
import static com.intellij.lang.javascript.flex.projectStructure.ui.CompilerOptionsConfigurable.ExtensionAwareFileChooserDescriptor;
public class RepeatableValueDialog extends AddRemoveTableRowsDialog<StringBuilder> {
private final CompilerOptionInfo myInfo;
public RepeatableValueDialog(final Project project,
final String title,
final List<StringBuilder> value,
final CompilerOptionInfo info) {
this(project, title, value, info, null);
}
public RepeatableValueDialog(final Project project,
final String title,
final List<StringBuilder> value,
final CompilerOptionInfo info,
final @Nullable String autoAddedConditionalCompilerDefinition) {
super(project, title, value);
assert info.TYPE == CompilerOptionInfo.OptionType.List;
myInfo = info;
setEditAddedRow(true);
init();
myTable.setDefaultEditor(VirtualFile.class, new AbstractTableCellEditor() {
public TextFieldWithBrowseButton myTextWithBrowse = new TextFieldWithBrowseButton();
public ExtensionAwareFileChooserDescriptor myFileChooserDescriptor = new ExtensionAwareFileChooserDescriptor();
{
myTextWithBrowse.addBrowseFolderListener(null, null, myProject, myFileChooserDescriptor);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
myFileChooserDescriptor.setAllowedExtensions(myInfo.LIST_ELEMENTS[column].FILE_EXTENSIONS);
myTextWithBrowse.setText(FileUtil.toSystemDependentName(String.valueOf(value)));
return myTextWithBrowse;
}
public Object getCellEditorValue() {
return FileUtil.toSystemIndependentName(myTextWithBrowse.getText().trim());
}
});
if (autoAddedConditionalCompilerDefinition != null) {
assert "compiler.define".equals(info.ID) && info.LIST_ELEMENTS.length == 2 : info.ID;
getCurrentList().add(new StringBuilder(autoAddedConditionalCompilerDefinition).append(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR));
UiNotifyConnector.doWhenFirstShown(myTable, () -> {
final int rowCount = myTable.getRowCount();
if (rowCount > 0) {
myTable.addRowSelectionInterval(rowCount - 1, rowCount - 1);
// todo this doesn't work because editing is immediately stopped in JBTable.columnMarginChanged()
TableUtil.editCellAt(myTable, rowCount - 1, myInfo.LIST_ELEMENTS.length - 1);
}
});
}
}
@Nullable
public JComponent getPreferredFocusedComponent() {
return myTable;
}
protected TableModelBase createTableModel() {
return new TableModelBase() {
public int getColumnCount() {
return myInfo.LIST_ELEMENTS.length;
}
@Nullable
public String getColumnName(final int column) {
return myInfo.LIST_ELEMENTS.length == 1 ? null : myInfo.LIST_ELEMENTS[column].DISPLAY_NAME;
}
public Class getColumnClass(final int column) {
final ListElementType type = myInfo.LIST_ELEMENTS[column].LIST_ELEMENT_TYPE;
return (type == ListElementType.File || type == ListElementType.FileOrFolder)
? VirtualFile.class
: type == ListElementType.Boolean
? Boolean.class
: String.class;
}
protected Object getValue(final StringBuilder s, final int column) {
final String value = StringUtil.split(s.toString(), CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR, true, false).get(column);
final ListElementType type = myInfo.LIST_ELEMENTS[column].LIST_ELEMENT_TYPE;
return (type == ListElementType.File || type == ListElementType.FileOrFolder)
? FileUtil.toSystemDependentName(value)
: type == ListElementType.Boolean
? Boolean.valueOf(value)
: value;
}
protected void setValue(final StringBuilder s, final int column, final Object aValue) {
final List<String> parts =
StringUtil.split(s.toString(), String.valueOf(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR), true, false);
s.delete(0, s.length());
for (int i = 0; i < column; i++) {
s.append(parts.get(i)).append(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR);
}
final ListElementType type = myInfo.LIST_ELEMENTS[column].LIST_ELEMENT_TYPE;
final String fixedValue = (type == ListElementType.File || type == ListElementType.FileOrFolder)
? FileUtil.toSystemIndependentName(String.valueOf(aValue))
: String.valueOf(aValue);
s.append(fixedValue);
for (int i = column + 1; i < myInfo.LIST_ELEMENTS.length; i++) {
s.append(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR).append(parts.get(i));
}
}
};
}
protected boolean addObject() {
final CompilerOptionInfo.ListElement firstElement = myInfo.LIST_ELEMENTS[0];
if (myInfo.LIST_ELEMENTS.length == 1 &&
(firstElement.LIST_ELEMENT_TYPE == ListElementType.File ||
firstElement.LIST_ELEMENT_TYPE == ListElementType.FileOrFolder)) {
final FileChooserDescriptor descriptor = firstElement.LIST_ELEMENT_TYPE == ListElementType.File
? FlexUtils.createFileChooserDescriptor(firstElement.FILE_EXTENSIONS)
: FileChooserDescriptorFactory.createSingleLocalFileDescriptor();
final VirtualFile file = FileChooser.chooseFile(descriptor, myProject, null);
if (file != null) {
getCurrentList().add(new StringBuilder(file.getPath()));
return true;
}
}
else {
final StringBuilder b = new StringBuilder();
boolean first = true;
for (CompilerOptionInfo.ListElement listElement : myInfo.LIST_ELEMENTS) {
if (first) {
first = false;
}
else {
b.append(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR);
}
b.append(listElement.DEFAULT_VALUE);
}
getCurrentList().add(b);
return true;
}
return false;
}
@Nullable
protected ValidationInfo doValidate() {
if ("compiler.define".equals(myInfo.ID)) {
for (StringBuilder builder : getCurrentList()) {
final List<String> strings = StringUtil.split(builder.toString(), CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR, true, false);
assert strings.size() == 2 : builder;
final String name = strings.get(0);
final String value = strings.get(1);
if (name.isEmpty()) {
return new ValidationInfo("Missing constant name");
}
final int colonIndex = name.indexOf("::");
if (colonIndex <= 0) {
return new ValidationInfo("Incorrect name: " + name);
}
if (value.isEmpty()) {
return new ValidationInfo("Constant " + name + " has empty value");
}
}
}
return null;
}
}