package fr.adrienbrault.idea.symfony2plugin.translation.form;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
import fr.adrienbrault.idea.symfony2plugin.action.comparator.PsiWeightListComparator;
import fr.adrienbrault.idea.symfony2plugin.action.dict.TranslationFileModel;
import fr.adrienbrault.idea.symfony2plugin.translation.dict.TranslationUtil;
import fr.adrienbrault.idea.symfony2plugin.util.SymfonyBundleUtil;
import fr.adrienbrault.idea.symfony2plugin.util.dict.SymfonyBundle;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.yaml.psi.YAMLFile;
import javax.swing.*;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class TranslatorKeyExtractorDialog extends JDialog {
private JPanel contentPane;
private JButton buttonOK;
private JButton buttonCancel;
private JTextField textTranslationKey;
private JPanel panelTableView;
private JComboBox comboBox1;
private JCheckBox checkNavigateTo;
private final ListTableModel<TranslationFileModel> listTableModel;
private final OnOkCallback okCallback;
private final Project project;
private final PsiFile fileContext;
public TranslatorKeyExtractorDialog(@NotNull Project project, @NotNull PsiFile fileContext, @NotNull Collection<String> domains, @Nullable String defaultKey, @NotNull String defaultDomain, @NotNull OnOkCallback okCallback) {
this.project = project;
this.fileContext = fileContext;
this.okCallback = okCallback;
for(String domain: domains) {
comboBox1.addItem(domain);
}
if(defaultKey != null) {
textTranslationKey.setText(defaultKey);
}
setContentPane(contentPane);
setModal(true);
getRootPane().setDefaultButton(buttonOK);
buttonOK.addActionListener(e -> onOK());
buttonCancel.addActionListener(e -> onCancel());
comboBox1.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
Object item = e.getItem();
if(item instanceof String) {
filterList((String) item);
}
}
});
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
});
contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
listTableModel = new ListTableModel<>(
new IconColumn(),
new PathNameColumn(),
new FileNameColumn(),
new BooleanColumn("Create")
);
comboBox1.setSelectedItem(defaultDomain);
filterList(defaultDomain);
TableView<TranslationFileModel> tableView = new TableView<>();
tableView.setModelAndUpdateColumns(listTableModel);
panelTableView.add(ToolbarDecorator.createDecorator(tableView)
.disableAddAction()
.disableDownAction()
.disableRemoveAction()
.disableUpDownActions()
.createPanel()
);
}
private void filterList(String domainName) {
// clear list no all*() method?
while(this.listTableModel.getRowCount() > 0) {
this.listTableModel.removeRow(0);
}
// we only support yaml files right now
// filter on PsiFile instance
Collection<PsiFile> domainPsiFilesYaml = TranslationUtil.getDomainPsiFiles(this.project, domainName).stream()
.filter(domainPsiFile -> domainPsiFile instanceof YAMLFile || TranslationUtil.isSupportedXlfFile(domainPsiFile))
.collect(Collectors.toCollection(ArrayList::new));
this.listTableModel.addRows(this.getFormattedFileModelList(domainPsiFilesYaml));
// only one domain; fine preselect it
if(this.listTableModel.getRowCount() == 1) {
this.listTableModel.getItem(0).setEnabled(true);
}
}
private void onOK() {
String text = textTranslationKey.getText();
if(StringUtils.isNotBlank(text)) {
List<TranslationFileModel> psiFiles = new ArrayList<>();
for(TranslationFileModel translationFileModel: listTableModel.getItems()) {
if(translationFileModel.isEnabled()) {
psiFiles.add(translationFileModel);
}
}
if(psiFiles.size() > 0) {
okCallback.onClick(psiFiles, text, (String) comboBox1.getSelectedItem(), checkNavigateTo.isSelected());
dispose();
return;
}
}
dispose();
}
private void onCancel() {
dispose();
}
private class FileNameColumn extends ColumnInfo<TranslationFileModel, String> {
public FileNameColumn() {
super("Name");
}
@Nullable
@Override
public String valueOf(TranslationFileModel domainModel) {
return domainModel.getPsiFile().getName();
}
public int getWidth(JTable table) {
return 190;
}
}
private class PathNameColumn extends ColumnInfo<TranslationFileModel, String> {
public PathNameColumn() {
super("Path");
}
@Nullable
@Override
public String valueOf(TranslationFileModel domainModel) {
if(domainModel.getSymfonyBundle() != null) {
return domainModel.getSymfonyBundle().getName();
}
String relative = domainModel.getRelativePath();
if(relative != null) {
return relative;
}
return domainModel.getPsiFile().getName();
}
}
private static class BooleanColumn extends ColumnInfo<TranslationFileModel, Boolean>
{
public BooleanColumn(String name) {
super(name);
}
@Nullable
@Override
public Boolean valueOf(TranslationFileModel domainModel) {
return domainModel.isEnabled();
}
public boolean isCellEditable(TranslationFileModel groupItem)
{
return true;
}
public void setValue(TranslationFileModel domainModel, Boolean value){
domainModel.setEnabled(value);
}
public Class getColumnClass()
{
return Boolean.class;
}
public int getWidth(JTable table) {
return 50;
}
}
private class IconColumn extends ColumnInfo<TranslationFileModel, Icon> {
public IconColumn() {
super("");
}
@Nullable
@Override
public Icon valueOf(TranslationFileModel modelParameter) {
if(modelParameter.isBoldness()) {
return Symfony2Icons.BUNDLE;
}
return modelParameter.getPsiFile().getIcon(0);
}
public java.lang.Class getColumnClass() {
return ImageIcon.class;
}
@Override
public int getWidth(JTable table) {
return 32;
}
}
private List<TranslationFileModel> getFormattedFileModelList(Collection<PsiFile> psiFiles) {
SymfonyBundleUtil symfonyBundleUtil = new SymfonyBundleUtil(this.project);
final SymfonyBundle symfonyBundle = symfonyBundleUtil.getContainingBundle(fileContext);
List<TranslationFileModel> psiFilesSorted = new ArrayList<>();
for(PsiFile psiFile: psiFiles) {
TranslationFileModel psiWeightList = new TranslationFileModel(psiFile);
if(symfonyBundle != null && symfonyBundle.isInBundle(psiFile)) {
psiWeightList.setSymfonyBundle(symfonyBundle);
psiWeightList.setBoldness(true);
psiWeightList.addWeight(2);
} else {
psiWeightList.setSymfonyBundle(symfonyBundleUtil.getContainingBundle(psiFile));
}
String relativePath = psiWeightList.getRelativePath();
if(relativePath != null && (relativePath.startsWith("src") || relativePath.startsWith("app"))) {
psiWeightList.addWeight(1);
}
psiFilesSorted.add(psiWeightList);
}
psiFilesSorted.sort(new PsiWeightListComparator());
return psiFilesSorted;
}
public interface OnOkCallback {
void onClick(List<TranslationFileModel> files, String keyName, String domain, boolean navigateTo);
}
}