1 19 20 package org.netbeans.modules.ruby.rubyproject.ui.wizards; 21 22 23 import java.awt.Color ; 24 import java.awt.Component ; 25 import java.beans.PropertyChangeListener ; 26 import java.io.File ; 27 import java.text.MessageFormat ; 28 import java.util.Arrays ; 29 import java.util.Collections ; 30 import java.util.HashSet ; 31 import java.util.Set ; 32 import javax.swing.DefaultListModel ; 33 import javax.swing.DefaultListCellRenderer ; 34 import javax.swing.Icon ; 35 import javax.swing.JFileChooser ; 36 import javax.swing.JList ; 37 import javax.swing.event.ListSelectionListener ; 38 import javax.swing.event.ListSelectionEvent ; 39 import org.netbeans.modules.ruby.rubyproject.RubyProject; 40 import org.netbeans.api.project.SourceGroup; 41 import org.netbeans.api.project.Sources; 42 import org.netbeans.modules.ruby.rubyproject.ui.customizer.RubySourceRootsUi; 43 import org.openide.filesystems.FileObject; 44 import org.openide.filesystems.FileUtil; 45 import org.openide.util.NbBundle; 46 import org.netbeans.api.project.FileOwnerQuery; 47 import org.netbeans.api.project.Project; 48 import org.netbeans.api.project.ProjectInformation; 49 import org.netbeans.modules.ruby.rubyproject.ui.FoldersListSettings; 50 51 52 56 public final class FolderList extends javax.swing.JPanel { 57 58 public static final String PROP_FILES = "files"; public static final String PROP_LAST_USED_DIR = "lastUsedDir"; 61 private String fcMessage; 62 private File projectFolder; 63 private File lastUsedFolder; 64 private FolderList relatedFolderList; 65 66 67 public FolderList (String label, char mnemonic, String accessibleDesc, String fcMessage, 68 char addButtonMnemonic, String addButtonAccessibleDesc, 69 char removeButtonMnemonic,String removeButtonAccessibleDesc) { 70 this.fcMessage = fcMessage; 71 initComponents(); 72 this.jLabel1.setText(label); 73 this.jLabel1.setDisplayedMnemonic(mnemonic); 74 this.roots.getAccessibleContext().setAccessibleDescription(accessibleDesc); 75 this.roots.setCellRenderer(new Renderer ()); 76 this.roots.setModel (new DefaultListModel ()); 77 this.roots.addListSelectionListener(new ListSelectionListener () { 78 public void valueChanged(ListSelectionEvent e) { 79 if (!e.getValueIsAdjusting()) { 80 removeButton.setEnabled(roots.getSelectedIndices().length != 0); 81 } 82 } 83 }); 84 this.addButton.getAccessibleContext().setAccessibleDescription(addButtonAccessibleDesc); 85 this.addButton.setMnemonic (addButtonMnemonic); 86 this.removeButton.getAccessibleContext().setAccessibleDescription(removeButtonAccessibleDesc); 87 this.removeButton.setMnemonic (removeButtonMnemonic); 88 this.removeButton.setEnabled(false); 89 } 90 91 public void setProjectFolder (File projectFolder) { 92 this.projectFolder = projectFolder; 93 } 94 95 public void setRelatedFolderList (FolderList relatedFolderList) { 96 this.relatedFolderList = relatedFolderList; 97 } 98 99 public File [] getFiles () { 100 Object [] files = ((DefaultListModel )this.roots.getModel()).toArray(); 101 File [] result = new File [files.length]; 102 System.arraycopy(files, 0, result, 0, files.length); 103 return result; 104 } 105 106 public void setFiles (File [] files) { 107 DefaultListModel model = ((DefaultListModel )this.roots.getModel()); 108 model.clear(); 109 for (int i=0; i<files.length; i++) { 110 model.addElement (files[i]); 111 } 112 if (files.length>0) { 113 this.roots.setSelectedIndex(0); 114 } 115 } 116 117 public void setLastUsedDir (File lastUsedDir) { 118 if (this.lastUsedFolder == null ? lastUsedDir != null : !this.lastUsedFolder.equals(lastUsedDir)) { 119 File oldValue = this.lastUsedFolder; 120 this.lastUsedFolder = lastUsedDir; 121 this.firePropertyChange(PROP_LAST_USED_DIR, oldValue, this.lastUsedFolder); 122 } 123 } 124 125 public File getLastUsedDir () { 126 return this.lastUsedFolder; 127 } 128 129 134 private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; 136 137 jLabel1 = new javax.swing.JLabel (); 138 jScrollPane1 = new javax.swing.JScrollPane (); 139 roots = new javax.swing.JList (); 140 addButton = new javax.swing.JButton (); 141 removeButton = new javax.swing.JButton (); 142 143 setLayout(new java.awt.GridBagLayout ()); 144 145 jLabel1.setLabelFor(roots); 146 jLabel1.setText("jLabel1"); 147 gridBagConstraints = new java.awt.GridBagConstraints (); 148 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 149 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 150 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 151 gridBagConstraints.weightx = 1.0; 152 gridBagConstraints.insets = new java.awt.Insets (0, 0, 6, 0); 153 add(jLabel1, gridBagConstraints); 154 155 jScrollPane1.setViewportView(roots); 156 157 gridBagConstraints = new java.awt.GridBagConstraints (); 158 gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; 159 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 160 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 161 gridBagConstraints.weightx = 1.0; 162 gridBagConstraints.weighty = 1.0; 163 gridBagConstraints.insets = new java.awt.Insets (0, 0, 0, 12); 164 add(jScrollPane1, gridBagConstraints); 165 166 addButton.setText(java.util.ResourceBundle.getBundle("org/netbeans/modules/ruby/rubyproject/ui/wizards/Bundle").getString("CTL_AddFolder")); 167 addButton.addActionListener(new java.awt.event.ActionListener () { 168 public void actionPerformed(java.awt.event.ActionEvent evt) { 169 addButtonActionPerformed(evt); 170 } 171 }); 172 173 gridBagConstraints = new java.awt.GridBagConstraints (); 174 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 175 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 176 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 177 add(addButton, gridBagConstraints); 178 179 removeButton.setText(java.util.ResourceBundle.getBundle("org/netbeans/modules/ruby/rubyproject/ui/wizards/Bundle").getString("CTL_RemoveFolder")); 180 removeButton.addActionListener(new java.awt.event.ActionListener () { 181 public void actionPerformed(java.awt.event.ActionEvent evt) { 182 removeButtonActionPerformed(evt); 183 } 184 }); 185 186 gridBagConstraints = new java.awt.GridBagConstraints (); 187 gridBagConstraints.gridx = 1; 188 gridBagConstraints.gridy = 2; 189 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 190 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 191 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 192 gridBagConstraints.insets = new java.awt.Insets (12, 0, 0, 0); 193 add(removeButton, gridBagConstraints); 194 195 } 197 private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) { Object [] selection = this.roots.getSelectedValues (); 199 for (int i=0; i<selection.length; i++) { 200 ((DefaultListModel )this.roots.getModel()).removeElement (selection[i]); 201 } 202 this.firePropertyChange(PROP_FILES, null, null); 203 } 205 private void addButtonActionPerformed(java.awt.event.ActionEvent evt) { JFileChooser chooser = new JFileChooser (); 207 FileUtil.preventFileChooserSymlinkTraversal(chooser, null); 208 chooser.setDialogTitle(this.fcMessage); 209 chooser.setFileSelectionMode (JFileChooser.DIRECTORIES_ONLY); 210 chooser.setMultiSelectionEnabled(true); 211 if (this.lastUsedFolder != null && this.lastUsedFolder.isDirectory()) { 212 chooser.setCurrentDirectory (this.lastUsedFolder); 213 } 214 else if (this.projectFolder != null && this.projectFolder.isDirectory()) { 215 chooser.setCurrentDirectory (this.projectFolder); 216 } 217 if (chooser.showOpenDialog(this)== JFileChooser.APPROVE_OPTION) { 218 File [] files = chooser.getSelectedFiles(); 219 int[] indecesToSelect = new int[files.length]; 220 DefaultListModel model = (DefaultListModel )this.roots.getModel(); 221 Set invalidRoots = new HashSet (); 222 File [] relatedFolders = this.relatedFolderList == null ? 223 new File [0] : this.relatedFolderList.getFiles(); 224 for (int i=0, index=model.size(); i<files.length; i++, index++) { 225 File normalizedFile = FileUtil.normalizeFile(files[i]); 226 if (!isValidRoot(normalizedFile, relatedFolders, this.projectFolder)) { 227 invalidRoots.add (normalizedFile); 228 } 229 else { 230 int pos = model.indexOf (normalizedFile); 231 if (pos == -1) { 232 model.addElement (normalizedFile); 233 indecesToSelect[i] = index; 234 } 235 else { 236 indecesToSelect[i] = pos; 237 } 238 } 239 } 240 this.roots.setSelectedIndices(indecesToSelect); 241 this.firePropertyChange(PROP_FILES, null, null); 242 File cd = chooser.getCurrentDirectory(); 243 if (cd != null) { 244 this.setLastUsedDir(FileUtil.normalizeFile(cd)); 245 } 246 if (invalidRoots.size()>0) { 247 RubySourceRootsUi.showIllegalRootsDialog(invalidRoots); 248 } 249 } 250 } 252 253 static boolean isValidRoot (File file, File [] relatedRoots, File projectFolder) { 254 Project p; 255 if ((p = FileOwnerQuery.getOwner(file.toURI()))!=null 256 && !file.getAbsolutePath().startsWith(projectFolder.getAbsolutePath()+File.separatorChar)) { 257 final Sources sources = (Sources) p.getLookup().lookup(Sources.class); 258 if (sources == null) { 259 return false; 260 } 261 final SourceGroup[] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC); 262 final SourceGroup[] javaGroups = sources.getSourceGroups(RubyProject.SOURCES_TYPE_RUBY); 263 final SourceGroup[] groups = new SourceGroup [sourceGroups.length + javaGroups.length]; 264 System.arraycopy(sourceGroups,0,groups,0,sourceGroups.length); 265 System.arraycopy(javaGroups,0,groups,sourceGroups.length,javaGroups.length); 266 final FileObject projectDirectory = p.getProjectDirectory(); 267 final FileObject fileObject = FileUtil.toFileObject(file); 268 if (projectDirectory == null || fileObject == null) { 269 return false; 270 } 271 for (int i = 0; i< groups.length; i++) { 272 final FileObject sgRoot = groups[i].getRootFolder(); 273 if (fileObject.equals(sgRoot)) { 274 return false; 275 } 276 if (!projectDirectory.equals(sgRoot) && FileUtil.isParentOf(sgRoot, fileObject)) { 277 return false; 278 } 279 } 280 return true; 281 } 282 else if (contains (file, relatedRoots)) { 283 return false; 284 } 285 return true; 286 } 287 288 private static boolean contains (File folder, File [] roots) { 289 String path = folder.getAbsolutePath (); 290 for (int i=0; i<roots.length; i++) { 291 String rootPath = roots[i].getAbsolutePath(); 292 if (rootPath.equals (path) || path.startsWith (rootPath + File.separatorChar)) { 293 return true; 294 } 295 } 296 return false; 297 } 298 299 private static class Renderer extends DefaultListCellRenderer { 300 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 301 File f = (File ) value; 302 Project p = FileOwnerQuery.getOwner(f.toURI()); 303 String message = f.getAbsolutePath(); 304 Component result = super.getListCellRendererComponent(list, message, index, isSelected, cellHasFocus); 305 return result; 306 } 307 308 } 309 310 private javax.swing.JButton addButton; 312 private javax.swing.JLabel jLabel1; 313 private javax.swing.JScrollPane jScrollPane1; 314 private javax.swing.JButton removeButton; 315 private javax.swing.JList roots; 316 318 } 319 | Popular Tags |