package com.intellij.lang.javascript.flex.projectStructure.ui; import com.intellij.lang.javascript.flex.FlexUtils; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.AnActionButton; import com.intellij.ui.AnActionButtonRunnable; import com.intellij.ui.TableUtil; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.table.JBTable; import com.intellij.util.ui.AbstractTableCellEditor; import com.intellij.util.ui.CellEditorComponentWithBrowseButton; import com.intellij.util.ui.JBUI; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static com.intellij.lang.javascript.flex.projectStructure.model.AirPackagingOptions.FilePathAndPathInPackage; public class FilesToPackageForm { private JPanel myMainPanel; private JBTable myFilesToPackageTable; private final Project myProject; private List<FilePathAndPathInPackage> myFilesToPackage = new ArrayList<>(); private enum Column { Path("Path to file or folder", String.class) { Object getValue(final FilePathAndPathInPackage row) { return FileUtil.toSystemDependentName(row.FILE_PATH); } void setValue(final List<FilePathAndPathInPackage> myFilesToPackage, final int row, final Object value) { myFilesToPackage.get(row).FILE_PATH = FileUtil.toSystemIndependentName(((String)value).trim()); } }, RelativePath("Its relative path in package", String.class) { Object getValue(final FilePathAndPathInPackage row) { return FileUtil.toSystemDependentName(row.PATH_IN_PACKAGE); } void setValue(final List<FilePathAndPathInPackage> myFilePathsToPackage, final int row, final Object value) { myFilePathsToPackage.get(row).PATH_IN_PACKAGE = FileUtil.toSystemIndependentName(((String)value).trim()); } }; private final String myColumnName; private final Class myColumnClass; private Column(final String columnName, final Class columnClass) { myColumnName = columnName; myColumnClass = columnClass; } public String getColumnName() { return myColumnName; } private Class getColumnClass() { return myColumnClass; } abstract Object getValue(FilePathAndPathInPackage row); abstract void setValue(List<FilePathAndPathInPackage> myFilesToPackage, int row, Object value); } public FilesToPackageForm(final Project project) { myProject = project; initTable(); initTableButtons(); } private void initTable() { myFilesToPackageTable = new JBTable(); myFilesToPackageTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); // otherwise model is not in sync with view myFilesToPackageTable.setPreferredScrollableViewportSize(JBUI.size(400, 150)); myFilesToPackageTable.setRowHeight(new JTextField("Fake").getPreferredSize().height + myFilesToPackageTable.getRowMargin()); myFilesToPackageTable.setModel(new DefaultTableModel() { public int getColumnCount() { return Column.values().length; } public int getRowCount() { return myFilesToPackage.size(); } public String getColumnName(int column) { return Column.values()[column].getColumnName(); } public Class<?> getColumnClass(int column) { return Column.values()[column].getColumnClass(); } public Object getValueAt(int row, int column) { return Column.values()[column].getValue(myFilesToPackage.get(row)); } public void setValueAt(Object aValue, int row, int column) { Column.values()[column].setValue(myFilesToPackage, row, aValue); } }); myFilesToPackageTable.getColumnModel().getColumn(0).setCellEditor(new AbstractTableCellEditor() { private CellEditorComponentWithBrowseButton<JTextField> myComponent; public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, int row, int column) { final ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent e) { FileChooserDescriptor d = new FileChooserDescriptor(true, true, false, true, false, false); VirtualFile initialFile = LocalFileSystem.getInstance().findFileByPath((String)getCellEditorValue()); VirtualFile file = FileChooser.chooseFile(d, myProject, initialFile); if (file != null) { myComponent.getChildComponent().setText(file.getPresentableUrl()); } } }; myComponent = new CellEditorComponentWithBrowseButton<>(new TextFieldWithBrowseButton(listener), this); myComponent.getChildComponent().setText((String)value); return myComponent; } public Object getCellEditorValue() { return myComponent.getChildComponent().getText(); } }); } private void initTableButtons() { ToolbarDecorator d = ToolbarDecorator.createDecorator(myFilesToPackageTable); d.setAddAction(new AnActionButtonRunnable() { public void run(AnActionButton button) { final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, false, true, false, true); final VirtualFile[] files = FileChooser.chooseFiles(descriptor, myProject, null); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); for (final VirtualFile file : files) { final VirtualFile sourceRoot = fileIndex.getSourceRootForFile(file); String relativePath = sourceRoot == null ? null : sourceRoot.equals(file) ? "." : VfsUtilCore.getRelativePath(file, sourceRoot, '/'); myFilesToPackage.add(new FilePathAndPathInPackage(file.getPath(), StringUtil.notNullize(relativePath, file.getName()))); } if (files.length > 0) { fireDataChanged(); IdeFocusManager.getInstance(myProject).requestFocus(myFilesToPackageTable, true); final int rowCount = myFilesToPackageTable.getRowCount(); myFilesToPackageTable.setRowSelectionInterval(rowCount - files.length, rowCount - 1); } } }); d.setRemoveAction(new AnActionButtonRunnable() { public void run(AnActionButton anActionButton) { TableUtil.stopEditing(myFilesToPackageTable); final int[] selectedRows = myFilesToPackageTable.getSelectedRows(); Arrays.sort(selectedRows); for (int i = selectedRows.length - 1; i >= 0; i--) { myFilesToPackage.remove(selectedRows[i]); } fireDataChanged(); } }); myMainPanel.add(d.createPanel(), BorderLayout.CENTER); } public void fireDataChanged() { ((AbstractTableModel)myFilesToPackageTable.getModel()).fireTableDataChanged(); } public List<FilePathAndPathInPackage> getFilesToPackage() { TableUtil.stopEditing(myFilesToPackageTable); return myFilesToPackage; } public void resetFrom(final List<FilePathAndPathInPackage> filesToPackage) { myFilesToPackage.clear(); myFilesToPackage.addAll(filesToPackage); fireDataChanged(); } public boolean isModified(final List<FilePathAndPathInPackage> filesToPackage) { return !FlexUtils.equalLists(filesToPackage, myFilesToPackage); } public ActionCallback navigateTo(final AirPackagingConfigurableBase.Location location) { if (location == AirPackagingConfigurableBase.Location.FilesToPackage) { return IdeFocusManager.findInstance().requestFocus(myFilesToPackageTable, true); } return ActionCallback.DONE; } }