| /* | 
 |  * Copyright 2000-2011 JetBrains s.r.o. | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  * http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 | package com.intellij.cvsSupport2.cvsoperations.cvsAdd.ui; | 
 |  | 
 | import com.intellij.CvsBundle; | 
 | import com.intellij.cvsSupport2.CvsActionPlaces; | 
 | import com.intellij.cvsSupport2.cvsoperations.cvsAdd.AddedFileInfo; | 
 | import com.intellij.cvsSupport2.keywordSubstitution.KeywordSubstitutionWrapper; | 
 | import com.intellij.cvsSupport2.ui.Options; | 
 | import com.intellij.icons.AllIcons; | 
 | import com.intellij.openapi.actionSystem.ActionManager; | 
 | import com.intellij.openapi.actionSystem.AnAction; | 
 | import com.intellij.openapi.actionSystem.AnActionEvent; | 
 | import com.intellij.openapi.actionSystem.DefaultActionGroup; | 
 | import com.intellij.openapi.project.Project; | 
 | import com.intellij.ui.ScrollPaneFactory; | 
 | import com.intellij.ui.dualView.TreeTableView; | 
 | import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns; | 
 | import com.intellij.ui.treeStructure.treetable.TreeTable; | 
 | import com.intellij.ui.treeStructure.treetable.TreeTableModel; | 
 | import com.intellij.ui.treeStructure.treetable.TreeTableTree; | 
 | import com.intellij.util.ui.ColumnInfo; | 
 | import com.intellij.util.ui.ComboBoxTableCellRenderer; | 
 | import com.intellij.util.ui.table.ComboBoxTableCellEditor; | 
 | import com.intellij.util.ui.tree.TreeUtil; | 
 | import org.netbeans.lib.cvsclient.command.KeywordSubstitution; | 
 |  | 
 | import javax.swing.*; | 
 | import javax.swing.table.JTableHeader; | 
 | import javax.swing.table.TableCellEditor; | 
 | import javax.swing.table.TableCellRenderer; | 
 | import javax.swing.tree.DefaultMutableTreeNode; | 
 | import java.awt.*; | 
 | import java.awt.event.KeyAdapter; | 
 | import java.awt.event.KeyEvent; | 
 | import java.util.ArrayList; | 
 | import java.util.Collection; | 
 | import java.util.Observable; | 
 | import java.util.Observer; | 
 |  | 
 | /** | 
 |  * author: lesya | 
 |  */ | 
 | public class AddMultipleFilesOptionsDialog extends AbstractAddOptionsDialog { | 
 |   private final Collection<AddedFileInfo> myRoots; | 
 |   private final static JCheckBox CHECKBOX = new JCheckBox(); | 
 |  | 
 |   private final ColumnInfo INCLUDED = new ColumnInfo("") { | 
 |  | 
 |     public Object valueOf(Object object) { | 
 |       return Boolean.valueOf(((AddedFileInfo)object).included()); | 
 |     } | 
 |  | 
 |     public Class getColumnClass() { | 
 |       return Boolean.class; | 
 |     } | 
 |  | 
 |     public boolean isCellEditable(Object o) { | 
 |       return true; | 
 |     } | 
 |  | 
 |     public void setValue(Object o, Object aValue) { | 
 |       final AddedFileInfo node = (AddedFileInfo)o; | 
 |       node.setIncluded(((Boolean)aValue).booleanValue()); | 
 |       myModel.nodeChanged(node); | 
 |     } | 
 |  | 
 |     public int getWidth(JTable table) { | 
 |       return CHECKBOX.getPreferredSize().width + 4; | 
 |     } | 
 |   }; | 
 |  | 
 |  | 
 |   private static final ColumnInfo<AddedFileInfo, AddedFileInfo> FILE = | 
 |     new ColumnInfo<AddedFileInfo, AddedFileInfo>(CvsBundle.message("add.multiple.files.file.column.name")) { | 
 |       public AddedFileInfo valueOf(AddedFileInfo object) { | 
 |         return object; | 
 |       } | 
 |  | 
 |       public Class getColumnClass() { | 
 |         return TreeTableModel.class; | 
 |       } | 
 |  | 
 |       public boolean isCellEditable(AddedFileInfo o) { | 
 |         return true; | 
 |       } | 
 |     }; | 
 |  | 
 |   private static final ColumnInfo KEYWORD_SUBSTITUTION = new ColumnInfo( | 
 |     CvsBundle.message("add.multiple.files.keyword.substitution.column.name")) { | 
 |     public Object valueOf(Object object) { | 
 |       return ((AddedFileInfo)object).getKeywordSubstitutionsWithSelection(); | 
 |     } | 
 |  | 
 |     public boolean isCellEditable(Object o) { | 
 |       AddedFileInfo addedFileInfo = (AddedFileInfo)o; | 
 |       if (addedFileInfo.getFile().isDirectory()) return false; | 
 |       return addedFileInfo.included(); | 
 |     } | 
 |  | 
 |     public void setValue(Object o, Object aValue) { | 
 |       final AddedFileInfo fileInfo = (AddedFileInfo)o; | 
 |       final KeywordSubstitutionWrapper substitutionWrapper = (KeywordSubstitutionWrapper)aValue; | 
 |       final KeywordSubstitution substitution = substitutionWrapper.getSubstitution(); | 
 |       fileInfo.setKeywordSubstitution(substitution); | 
 |     } | 
 |  | 
 |     public TableCellRenderer getRenderer(Object o) { | 
 |       AddedFileInfo addedFileInfo = (AddedFileInfo)o; | 
 |       if (addedFileInfo.getFile().isDirectory()) return TABLE_CELL_RENDERER; | 
 |       return ComboBoxTableCellRenderer.INSTANCE; | 
 |     } | 
 |  | 
 |     public TableCellEditor getEditor(Object item) { | 
 |       return ComboBoxTableCellEditor.INSTANCE; | 
 |     } | 
 |  | 
 |     public int getWidth(JTable table) { | 
 |       return table.getFontMetrics(table.getFont()).stringWidth(getName()) + 10; | 
 |     } | 
 |   }; | 
 |  | 
 |   private final ColumnInfo[] COLUMNS = new ColumnInfo[]{INCLUDED, FILE, KEYWORD_SUBSTITUTION}; | 
 |  | 
 |   private TreeTable myTreeTable; | 
 |   private ListTreeTableModelOnColumns myModel; | 
 |   private static final JPanel J_PANEL = new JPanel(); | 
 |   private static final TableCellRenderer TABLE_CELL_RENDERER = new TableCellRenderer() { | 
 |     public Component getTableCellRendererComponent(JTable table, | 
 |                                                    Object value, | 
 |                                                    boolean isSelected, | 
 |                                                    boolean hasFocus, | 
 |                                                    int row, | 
 |                                                    int column) { | 
 |       J_PANEL.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); | 
 |       return J_PANEL; | 
 |     } | 
 |   }; | 
 |   private final Observer myObserver; | 
 |  | 
 |  | 
 |   public AddMultipleFilesOptionsDialog(Project project, Collection<AddedFileInfo> roots, Options options) { | 
 |     super(project, options); | 
 |  | 
 |     myRoots = roots; | 
 |     myObserver = new Observer() { | 
 |           public void update(Observable o, Object arg) { | 
 |             setOKButtonEnabling(); | 
 |           } | 
 |         }; | 
 |  | 
 |     for (AddedFileInfo myRoot : myRoots) { | 
 |       myRoot.addIncludedObserver(myObserver); | 
 |     } | 
 |  | 
 |     setTitle(CvsBundle.message("dialog.title.add.files.to.cvs")); | 
 |     createTree(); | 
 |     expandAll(); | 
 |  | 
 |     init(); | 
 |     setOKButtonEnabling(); | 
 |   } | 
 |  | 
 |   private void setOKButtonEnabling() { | 
 |     setOKActionEnabled(hasIncludedNodes()); | 
 |   } | 
 |  | 
 |   private boolean hasIncludedNodes() { | 
 |     for (AddedFileInfo addedFileInfo : myRoots) { | 
 |       if (addedFileInfo.hasIncludedNodes()) return true; | 
 |     } | 
 |     return false; | 
 |   } | 
 |  | 
 |   public void dispose() { | 
 |     super.dispose(); | 
 |     for (AddedFileInfo myRoot : myRoots) { | 
 |       myRoot.removeIncludedObserver(myObserver); | 
 |     } | 
 |   } | 
 |  | 
 |   private void expandAll() { | 
 |     int row = 0; | 
 |     JTree tree = myTreeTable.getTree(); | 
 |     while (row < tree.getRowCount()) { | 
 |       tree.expandRow(row); | 
 |       row++; | 
 |     } | 
 |   } | 
 |  | 
 |   private void createTree() { | 
 |     DefaultMutableTreeNode root = new DefaultMutableTreeNode(); | 
 |  | 
 |     for (AddedFileInfo myRoot : myRoots) { | 
 |       root.add(myRoot); | 
 |     } | 
 |  | 
 |     myModel = new ListTreeTableModelOnColumns(root, COLUMNS); | 
 |     myTreeTable = new TreeTableView(myModel); | 
 |  | 
 |     int comboHeight = new JComboBox().getPreferredSize().height; | 
 |     int checkBoxHeight = new JCheckBox().getPreferredSize().height; | 
 |     myTreeTable.setMinRowHeight(Math.max(comboHeight, checkBoxHeight) + 2); | 
 |     myTreeTable.setRootVisible(false); | 
 |     final JTableHeader tableHeader = myTreeTable.getTableHeader(); | 
 |     tableHeader.setReorderingAllowed(false); | 
 |     tableHeader.setResizingAllowed(false); | 
 |     final TreeTableTree tree = myTreeTable.getTree(); | 
 |     myTreeTable.addKeyListener(new KeyAdapter() { | 
 |       @Override | 
 |       public void keyPressed(KeyEvent e) { | 
 |         final int keyCode = e.getKeyCode(); | 
 |         if (keyCode == KeyEvent.VK_SPACE) { | 
 |           final int selectedColumn = myTreeTable.getSelectedColumn(); | 
 |           if (selectedColumn == 0) { | 
 |             return; | 
 |           } | 
 |           final int[] selectedRows = myTreeTable.getSelectedRows(); | 
 |           if (selectedRows.length == 0) { | 
 |             return; | 
 |           } | 
 |           final boolean included = !((AddedFileInfo)myTreeTable.getValueAt(selectedRows[0], 1)).included(); | 
 |           for (int selectedRow : selectedRows) { | 
 |             final AddedFileInfo addedFileInfo = (AddedFileInfo)myTreeTable.getValueAt(selectedRow, 1); | 
 |             addedFileInfo.setIncluded(included); | 
 |             myModel.nodeChanged(addedFileInfo); | 
 |           } | 
 |         } | 
 |       } | 
 |     }); | 
 |     tree.setCellRenderer(new AddedFileCellRenderer()); | 
 |     TreeUtil.installActions(tree); | 
 |   } | 
 |  | 
 |   protected JComponent createCenterPanel() { | 
 |     JPanel result = new JPanel(new BorderLayout()); | 
 |     JComponent toolbar = createToolbar(); | 
 |     result.add(toolbar, BorderLayout.NORTH); | 
 |     result.add(ScrollPaneFactory.createScrollPane(myTreeTable), BorderLayout.CENTER); | 
 |     return result; | 
 |   } | 
 |  | 
 |   private JComponent createToolbar() { | 
 |     ActionManager actionManager = ActionManager.getInstance(); | 
 |     DefaultActionGroup group = new DefaultActionGroup(); | 
 |     group.add(new SelectAllAction()); | 
 |     group.add(new UnselectAllAction()); | 
 |     return actionManager.createActionToolbar(CvsActionPlaces.ADD_FILES_TOOLBAR, group, true).getComponent(); | 
 |   } | 
 |  | 
 |   private abstract class SelectUnselectAllAction extends AnAction { | 
 |     protected SelectUnselectAllAction(String text, Icon icon) { | 
 |       super(text, null, icon); | 
 |     } | 
 |  | 
 |     public void actionPerformed(AnActionEvent e) { | 
 |       for (AddedFileInfo addedFileInfo : getAllFileInfos()) { | 
 |         addedFileInfo.setIncluded(includedValue()); | 
 |       } | 
 |       AddMultipleFilesOptionsDialog.this.myTreeTable.repaint(); | 
 |     } | 
 |  | 
 |     private Collection<AddedFileInfo> getAllFileInfos() { | 
 |       ArrayList<AddedFileInfo> result = new ArrayList(); | 
 |       for (AddedFileInfo myRoot : myRoots) { | 
 |         addChildrenTo(result, myRoot); | 
 |       } | 
 |       return result; | 
 |     } | 
 |  | 
 |     private void addChildrenTo(ArrayList<AddedFileInfo> result, AddedFileInfo addedFileInfo) { | 
 |       result.add(addedFileInfo); | 
 |       for (int i = 0; i < addedFileInfo.getChildCount(); i++) { | 
 |         addChildrenTo(result, (AddedFileInfo)addedFileInfo.getChildAt(i)); | 
 |       } | 
 |     } | 
 |  | 
 |     protected abstract boolean includedValue(); | 
 |   } | 
 |  | 
 |   private class SelectAllAction extends SelectUnselectAllAction { | 
 |  | 
 |     public SelectAllAction() { | 
 |       super(CvsBundle.message("action.name.select.all"), AllIcons.Actions.Selectall); | 
 |     } | 
 |  | 
 |     protected boolean includedValue() { | 
 |       return true; | 
 |     } | 
 |   } | 
 |  | 
 |   private class UnselectAllAction extends SelectUnselectAllAction { | 
 |     public UnselectAllAction() { | 
 |       super(CvsBundle.message("action.name.unselect.all"), AllIcons.Actions.Unselectall); | 
 |     } | 
 |  | 
 |     protected boolean includedValue() { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 | } |