package fr.adrienbrault.idea.symfony2plugin.action.ui;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class ServiceArgumentSelectionDialog extends JDialog {
private final Project project;
private final Map<String, Set<String>> arguments;
private final Callback callback;
private JPanel panel1;
private JButton generateButton;
private JButton closeButton;
private JPanel mainPanel;
private TableView<ServiceParameter> tableView;
private ListTableModel<ServiceParameter> modelList;
public ServiceArgumentSelectionDialog(Project project, Map<String, Set<String>> arguments, Callback callback) {
this.project = project;
this.arguments = arguments;
this.callback = callback;
}
public void init() {
setContentPane(panel1);
setModal(true);
generateButton.addActionListener(e -> {
setEnabled(false);
java.util.List<String> items = new ArrayList<>();
for (ServiceParameter serviceParameter : modelList.getItems()) {
items.add(serviceParameter.getCurrentService());
}
callback.onOk(items);
dispose();
});
generateButton.requestFocusInWindow();
this.getRootPane().setDefaultButton(generateButton);
this.closeButton.addActionListener(e -> onCancel());
this.getRootPane().registerKeyboardAction(e ->
onCancel(),
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
);
}
private void onCancel() {
setEnabled(false);
dispose();
}
private void createUIComponents() {
mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(0, 1));
this.modelList = new ListTableModel<>(
new IconColumn(),
new NamespaceColumn(),
new ServiceColumn()
);
for (Map.Entry<String, Set<String>> entry : this.arguments.entrySet()) {
this.modelList.addRow(new ServiceParameter(entry.getKey(), entry.getValue()));
}
this.tableView = new TableView<>();
this.tableView.setModelAndUpdateColumns(this.modelList);
mainPanel.add(ToolbarDecorator.createDecorator(this.tableView)
.disableAddAction()
.disableDownAction()
.disableRemoveAction()
.disableUpDownActions()
.createPanel()
);
}
private static class ServiceParameter {
private final String classFqn;
private final Set<String> possibleServices;
private String currentService;
public ServiceParameter(String classFqn, Set<String> possibleServices) {
this.classFqn = classFqn;
this.possibleServices = possibleServices;
if(possibleServices.size() > 0) {
currentService = possibleServices.iterator().next();
}
}
public String getClassFqn() {
return classFqn;
}
public Set<String> getPossibleServices() {
return possibleServices;
}
public String getCurrentService() {
return currentService;
}
public void setCurrentService(String currentService) {
if (StringUtils.isBlank(currentService)) {
this.currentService = null;
return;
}
this.currentService = currentService;
}
}
private class NamespaceColumn extends ColumnInfo<ServiceParameter, String> {
public NamespaceColumn() {
super("Class");
}
@Nullable
@Override
public String valueOf(ServiceParameter modelParameter) {
String classFqn = modelParameter.getClassFqn();
if(StringUtils.isBlank(classFqn)) {
return "unknown";
}
if(classFqn.startsWith("\\")) {
classFqn = classFqn.substring(1);
}
int i = classFqn.lastIndexOf("\\");
if(i > 0) {
String ns = classFqn.substring(0, i);
String clazz = classFqn.substring(i + 1, classFqn.length());
classFqn = String.format("%s [%s]", clazz, ns);
}
return classFqn;
}
}
private class ServiceColumn extends ColumnInfo<ServiceParameter, String> {
public ServiceColumn() {
super("Service");
}
@Nullable
@Override
public String valueOf(ServiceParameter modelParameter) {
return modelParameter.getCurrentService();
}
public void setValue(ServiceParameter modelParameter, String value){
modelParameter.setCurrentService(value);
tableView.getListTableModel().fireTableDataChanged();
}
@Override
public boolean isCellEditable(ServiceParameter modelParameter) {
return true;
}
@Nullable
@Override
public TableCellEditor getEditor(ServiceParameter modelParameter) {
Set<String> sorted = modelParameter.getPossibleServices();
ComboBox comboBox = new ComboBox(sorted.toArray(new String[sorted.size()] ), 200);
comboBox.setEditable(true);
return new DefaultCellEditor(comboBox);
}
}
private class IconColumn extends ColumnInfo<ServiceParameter, Icon> {
public IconColumn() {
super("");
}
@Nullable
@Override
public Icon valueOf(ServiceParameter modelParameter) {
PhpClass classInterface = PhpElementsUtil.getClassInterface(project, modelParameter.getClassFqn());
return classInterface != null ? classInterface.getIcon() : null;
}
public java.lang.Class getColumnClass() {
return ImageIcon.class;
}
@Override
public int getWidth(JTable table) {
return 32;
}
}
public interface Callback {
void onOk(java.util.List<String> items);
}
public static ServiceArgumentSelectionDialog createDialog(Project project, Map<String, Set<String>> arguments, Callback callback) {
ServiceArgumentSelectionDialog dialog = new ServiceArgumentSelectionDialog(project, arguments, callback);
dialog.pack();
dialog.init();
dialog.setMinimumSize(new Dimension(620, 300));
dialog.setTitle("Symfony: Add Argument");
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
return dialog;
}
}