1 19 20 package org.netbeans.modules.java.j2seproject.ui.customizer; 21 22 import java.awt.*; 23 import java.awt.event.ActionEvent ; 24 import java.awt.event.ActionListener ; 25 import java.io.File ; 26 import java.net.URI ; 27 import java.net.URL ; 28 import java.util.ArrayList ; 29 import java.util.Iterator ; 30 import java.util.HashSet ; 31 import java.util.Set ; 32 import java.util.Vector ; 33 import java.text.MessageFormat ; 34 import javax.swing.*; 35 import javax.swing.JButton ; 36 import javax.swing.event.ListSelectionEvent ; 37 import javax.swing.event.ListSelectionListener ; 38 import javax.swing.event.CellEditorListener ; 39 import javax.swing.event.ChangeEvent ; 40 import javax.swing.table.DefaultTableCellRenderer ; 41 import javax.swing.table.DefaultTableModel ; 42 import org.netbeans.api.java.project.JavaProjectConstants; 43 import org.netbeans.api.project.ProjectUtils; 44 import org.netbeans.api.project.SourceGroup; 45 import org.netbeans.api.project.Sources; 46 import org.netbeans.modules.java.j2seproject.J2SEProject; 47 import org.netbeans.modules.java.j2seproject.ui.FoldersListSettings; 48 import org.netbeans.api.project.FileOwnerQuery; 49 import org.netbeans.api.project.Project; 50 import org.netbeans.api.project.ProjectInformation; 51 import org.netbeans.modules.java.j2seproject.SourceRoots; 52 import org.openide.DialogDisplayer; 53 import org.openide.DialogDescriptor; 54 import org.openide.NotifyDescriptor; 55 import org.openide.filesystems.FileObject; 56 import org.openide.filesystems.FileUtil; 57 import org.openide.util.NbBundle; 58 import org.openide.util.HelpCtx; 59 60 64 public final class J2SESourceRootsUi { 65 66 public static DefaultTableModel createModel( SourceRoots roots ) { 67 68 String [] rootLabels = roots.getRootNames(); 69 String [] rootProps = roots.getRootProperties(); 70 URL [] rootURLs = roots.getRootURLs(); 71 Object [][] data = new Object [rootURLs.length] [2]; 72 for (int i=0; i< rootURLs.length; i++) { 73 data[i][0] = new File (URI.create (rootURLs[i].toExternalForm())); 74 data[i][1] = roots.getRootDisplayName(rootLabels[i], rootProps[i]); 75 } 76 return new SourceRootsModel(data); 77 78 } 79 80 public static EditMediator registerEditMediator( J2SEProject master, 81 SourceRoots sourceRoots, 82 JTable rootsList, 83 JButton addFolderButton, 84 JButton removeButton, 85 JButton upButton, 86 JButton downButton) { 87 88 EditMediator em = new EditMediator( master, 89 sourceRoots, 90 rootsList, 91 addFolderButton, 92 removeButton, 93 upButton, 94 downButton); 95 96 addFolderButton.addActionListener( em ); 99 removeButton.addActionListener( em ); 100 upButton.addActionListener( em ); 101 downButton.addActionListener( em ); 102 rootsList.getSelectionModel().addListSelectionListener( em ); 104 DefaultCellEditor editor = new DefaultCellEditor(new JTextField()); 105 editor.addCellEditorListener (em); 106 rootsList.setDefaultRenderer( File .class, new FileRenderer (FileUtil.toFile(master.getProjectDirectory()))); 107 rootsList.setDefaultEditor(String .class, editor); 108 em.valueChanged( null ); 110 111 DefaultTableModel model = (DefaultTableModel )rootsList.getModel(); 112 String [] columnNames = new String [2]; 113 columnNames[0] = NbBundle.getMessage( J2SESourceRootsUi.class,"CTL_PackageFolders"); 114 columnNames[1] = NbBundle.getMessage( J2SESourceRootsUi.class,"CTL_PackageLabels"); 115 model.setColumnIdentifiers(columnNames); 116 rootsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 117 118 return em; 119 } 120 121 125 public static void showIllegalRootsDialog (Set roots) { 126 JButton closeOption = new JButton (NbBundle.getMessage(J2SESourceRootsUi.class,"CTL_J2SESourceRootsUi_Close")); 127 closeOption.getAccessibleContext ().setAccessibleDescription (NbBundle.getMessage(J2SESourceRootsUi.class,"AD_J2SESourceRootsUi_Close")); 128 JPanel warning = new WarningDlg (roots); 129 String message = NbBundle.getMessage(J2SESourceRootsUi.class,"MSG_InvalidRoot"); 130 JOptionPane optionPane = new JOptionPane (new Object [] {message, warning}, 131 JOptionPane.WARNING_MESSAGE, 132 0, 133 null, 134 new Object [0], 135 null); 136 optionPane.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(J2SESourceRootsUi.class,"AD_InvalidRootDlg")); 137 DialogDescriptor dd = new DialogDescriptor (optionPane, 138 NbBundle.getMessage(J2SESourceRootsUi.class,"TITLE_InvalidRoot"), 139 true, 140 new Object [] { 141 closeOption, 142 }, 143 closeOption, 144 DialogDescriptor.DEFAULT_ALIGN, 145 null, 146 null); 147 DialogDisplayer.getDefault().notify(dd); 148 } 149 150 152 public static class EditMediator implements ActionListener , ListSelectionListener , CellEditorListener { 153 154 155 final JTable rootsList; 156 final JButton addFolderButton; 157 final JButton removeButton; 158 final JButton upButton; 159 final JButton downButton; 160 private final Project project; 161 private final SourceRoots sourceRoots; 162 private final Set ownedFolders; 163 private DefaultTableModel rootsModel; 164 private EditMediator relatedEditMediator; 165 private File lastUsedDir; 167 168 public EditMediator( J2SEProject master, 169 SourceRoots sourceRoots, 170 JTable rootsList, 171 JButton addFolderButton, 172 JButton removeButton, 173 JButton upButton, 174 JButton downButton) { 175 176 if ( !( rootsList.getModel() instanceof DefaultTableModel ) ) { 177 throw new IllegalArgumentException ( "Jtable's model has to be of class DefaultTableModel" ); } 179 180 this.rootsList = rootsList; 181 this.addFolderButton = addFolderButton; 182 this.removeButton = removeButton; 183 this.upButton = upButton; 184 this.downButton = downButton; 185 this.ownedFolders = new HashSet (); 186 187 this.project = master; 188 this.sourceRoots = sourceRoots; 189 190 this.ownedFolders.clear(); 191 this.rootsModel = (DefaultTableModel )rootsList.getModel(); 192 Vector data = rootsModel.getDataVector(); 193 for (Iterator it = data.iterator(); it.hasNext();) { 194 Vector row = (Vector ) it.next (); 195 File f = (File ) row.elementAt(0); 196 this.ownedFolders.add (f); 197 } 198 } 199 200 public void setRelatedEditMediator(EditMediator rem) { 201 this.relatedEditMediator = rem; 202 } 203 204 206 208 public void actionPerformed( ActionEvent e ) { 209 210 Object source = e.getSource(); 211 212 if ( source == addFolderButton ) { 213 214 JFileChooser chooser = new JFileChooser(); 216 FileUtil.preventFileChooserSymlinkTraversal(chooser, null); 217 chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY ); 218 chooser.setMultiSelectionEnabled( true ); 219 if (this.sourceRoots.isTest()) { 220 chooser.setDialogTitle( NbBundle.getMessage( J2SESourceRootsUi.class, "LBL_TestFolder_DialogTitle" )); } 222 else { 223 chooser.setDialogTitle( NbBundle.getMessage( J2SESourceRootsUi.class, "LBL_SourceFolder_DialogTitle" )); } 225 File curDir = this.lastUsedDir; 226 if (curDir == null) { 227 curDir = FileUtil.toFile(this.project.getProjectDirectory()); 228 } 229 if (curDir != null) { 230 chooser.setCurrentDirectory (curDir); 231 } 232 int option = chooser.showOpenDialog( SwingUtilities.getWindowAncestor( addFolderButton ) ); 234 if ( option == JFileChooser.APPROVE_OPTION ) { 235 curDir = chooser.getCurrentDirectory(); 236 if (curDir != null) { 237 this.lastUsedDir = curDir; 238 if (this.relatedEditMediator != null) { 239 this.relatedEditMediator.lastUsedDir = curDir; 240 } 241 } 242 File files[] = chooser.getSelectedFiles(); 243 addFolders( files ); 244 } 245 246 } 247 else if ( source == removeButton ) { 248 removeElements(); 249 } 250 else if ( source == upButton ) { 251 moveUp(); 252 } 253 else if ( source == downButton ) { 254 moveDown(); 255 } 256 } 257 258 260 262 public void valueChanged( ListSelectionEvent e ) { 263 264 int[] si = rootsList.getSelectedRows(); 265 266 268 270 272 boolean edit = si != null && si.length > 0; 274 275 boolean remove = si != null && si.length > 0; 277 279 boolean up = si != null && si.length > 0 && si[0] != 0; 282 283 boolean down = si != null && si.length > 0 && si[si.length-1] !=rootsList.getRowCount() - 1; 286 287 removeButton.setEnabled( remove ); 288 upButton.setEnabled( up ); 289 downButton.setEnabled( down ); 290 291 293 } 294 295 public void editingCanceled(ChangeEvent e) { 296 297 } 298 299 public void editingStopped(ChangeEvent e) { 300 } 302 303 private void addFolders( File files[] ) { 304 int[] si = rootsList.getSelectedRows(); 305 int lastIndex = si == null || si.length == 0 ? -1 : si[si.length - 1]; 306 ListSelectionModel selectionModel = this.rootsList.getSelectionModel(); 307 selectionModel.clearSelection(); 308 Set rootsFromOtherProjects = new HashSet (); 309 Set rootsFromRelatedSourceRoots = new HashSet (); 310 out: for( int i = 0; i < files.length; i++ ) { 311 File normalizedFile = FileUtil.normalizeFile(files[i]); 312 Project p; 313 if (ownedFolders.contains(normalizedFile)) { 314 Vector dataVector = rootsModel.getDataVector(); 315 for (int j=0; j<dataVector.size();j++) { 316 File f = (File )((Vector )dataVector.elementAt(j)).elementAt(0); 318 if (f.equals(normalizedFile)) { 319 selectionModel.addSelectionInterval(j,j); 320 } 321 } 322 } 323 else if (this.relatedEditMediator != null && this.relatedEditMediator.ownedFolders.contains(normalizedFile)) { 324 rootsFromRelatedSourceRoots.add (normalizedFile); 325 continue; 326 } 327 if ((p=FileOwnerQuery.getOwner(normalizedFile.toURI()))!=null && !p.getProjectDirectory().equals(project.getProjectDirectory())) { 328 final Sources sources = (Sources) p.getLookup().lookup (Sources.class); 329 if (sources == null) { 330 rootsFromOtherProjects.add (normalizedFile); 331 continue; 332 } 333 final SourceGroup[] sourceGroups = sources.getSourceGroups(Sources.TYPE_GENERIC); 334 final SourceGroup[] javaGroups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); 335 final SourceGroup[] groups = new SourceGroup [sourceGroups.length + javaGroups.length]; 336 System.arraycopy(sourceGroups,0,groups,0,sourceGroups.length); 337 System.arraycopy(javaGroups,0,groups,sourceGroups.length,javaGroups.length); 338 final FileObject projectDirectory = p.getProjectDirectory(); 339 final FileObject fileObject = FileUtil.toFileObject(normalizedFile); 340 if (projectDirectory == null || fileObject == null) { 341 rootsFromOtherProjects.add (normalizedFile); 342 continue; 343 } 344 for (int j=0; j<groups.length; j++) { 345 final FileObject sgRoot = groups[j].getRootFolder(); 346 if (fileObject.equals(sgRoot)) { 347 rootsFromOtherProjects.add (normalizedFile); 348 continue out; 349 } 350 if (!projectDirectory.equals(sgRoot) && FileUtil.isParentOf(sgRoot, fileObject)) { 351 rootsFromOtherProjects.add (normalizedFile); 352 continue out; 353 } 354 } 355 } 356 int current = lastIndex + 1 + i; 357 rootsModel.insertRow( current, new Object [] {normalizedFile, sourceRoots.createInitialDisplayName(normalizedFile)}); selectionModel.addSelectionInterval(current,current); 359 this.ownedFolders.add (normalizedFile); 360 } 361 if (rootsFromOtherProjects.size() > 0 || rootsFromRelatedSourceRoots.size() > 0) { 362 rootsFromOtherProjects.addAll(rootsFromRelatedSourceRoots); 363 showIllegalRootsDialog (rootsFromOtherProjects); 364 } 365 } 367 368 private void removeElements() { 369 370 int[] si = rootsList.getSelectedRows(); 371 372 if( si == null || si.length == 0 ) { 373 assert false : "Remove button should be disabled"; } 375 376 for( int i = si.length - 1 ; i >= 0 ; i-- ) { 378 this.ownedFolders.remove(((Vector )rootsModel.getDataVector().elementAt(si[i])).elementAt(0)); 379 rootsModel.removeRow( si[i] ); 380 } 381 382 383 if ( rootsModel.getRowCount() != 0) { 384 int selectedIndex = si[si.length - 1] - si.length + 1; 386 if ( selectedIndex > rootsModel.getRowCount() - 1) { 387 selectedIndex = rootsModel.getRowCount() - 1; 388 } 389 rootsList.setRowSelectionInterval( selectedIndex, selectedIndex ); 390 } 391 392 394 } 395 396 private void moveUp() { 397 398 int[] si = rootsList.getSelectedRows(); 399 400 if( si == null || si.length == 0 ) { 401 assert false : "MoveUp button should be disabled"; } 403 404 ListSelectionModel selectionModel = this.rootsList.getSelectionModel(); 406 selectionModel.clearSelection(); 407 for( int i = 0; i < si.length; i++ ) { 408 Vector item = (Vector ) rootsModel.getDataVector().elementAt(si[i]); 409 int newIndex = si[i]-1; 410 rootsModel.removeRow( si[i] ); 411 rootsModel.insertRow( newIndex, item ); 412 selectionModel.addSelectionInterval(newIndex,newIndex); 413 } 414 } 416 417 private void moveDown() { 418 419 int[] si = rootsList.getSelectedRows(); 420 421 if( si == null || si.length == 0 ) { 422 assert false : "MoveDown button should be disabled"; } 424 425 ListSelectionModel selectionModel = this.rootsList.getSelectionModel(); 427 selectionModel.clearSelection(); 428 for( int i = si.length -1 ; i >= 0 ; i-- ) { 429 Vector item = (Vector ) rootsModel.getDataVector().elementAt(si[i]); 430 int newIndex = si[i] + 1; 431 rootsModel.removeRow( si[i] ); 432 rootsModel.insertRow( newIndex, item ); 433 selectionModel.addSelectionInterval(newIndex,newIndex); 434 } 435 } 437 438 439 } 440 441 private static class SourceRootsModel extends DefaultTableModel { 442 443 public SourceRootsModel (Object [][] data) { 444 super (data,new Object []{"location","label"}); } 446 447 public boolean isCellEditable(int row, int column) { 448 return column == 1; 449 } 450 451 public Class getColumnClass(int columnIndex) { 452 switch (columnIndex) { 453 case 0: 454 return File .class; 455 case 1: 456 return String .class; 457 default: 458 return super.getColumnClass (columnIndex); 459 } 460 } 461 } 462 463 private static class FileRenderer extends DefaultTableCellRenderer { 464 465 private File projectFolder; 466 467 public FileRenderer (File projectFolder) { 468 this.projectFolder = projectFolder; 469 } 470 471 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row, int column) { 472 String displayName; 473 if (value instanceof File ) { 474 File root = (File ) value; 475 String pfPath = projectFolder.getAbsolutePath() + File.separatorChar; 476 String srPath = root.getAbsolutePath(); 477 if (srPath.startsWith(pfPath)) { 478 displayName = srPath.substring(pfPath.length()); 479 } 480 else { 481 displayName = srPath; 482 } 483 } 484 else { 485 displayName = null; 486 } 487 Component c = super.getTableCellRendererComponent(table, displayName, isSelected, hasFocus, row, column); 488 if (c instanceof JComponent) { 489 ((JComponent) c).setToolTipText (displayName); 490 } 491 return c; 492 } 493 494 } 495 496 private static class WarningDlg extends JPanel { 497 498 public WarningDlg (Set invalidRoots) { 499 this.initGui (invalidRoots); 500 } 501 502 private void initGui (Set invalidRoots) { 503 setLayout( new GridBagLayout ()); 504 JLabel label = new JLabel (); 505 label.setText (NbBundle.getMessage(J2SESourceRootsUi.class,"LBL_InvalidRoot")); 506 label.setDisplayedMnemonic(NbBundle.getMessage(J2SESourceRootsUi.class,"MNE_InvalidRoot").charAt(0)); 507 GridBagConstraints c = new GridBagConstraints(); 508 c.gridx = GridBagConstraints.RELATIVE; 509 c.gridy = GridBagConstraints.RELATIVE; 510 c.gridwidth = GridBagConstraints.REMAINDER; 511 c.fill = GridBagConstraints.HORIZONTAL; 512 c.anchor = GridBagConstraints.NORTHWEST; 513 c.weightx = 1.0; 514 c.insets = new Insets (12,0,6,0); 515 ((GridBagLayout)this.getLayout()).setConstraints(label,c); 516 this.add (label); 517 JList roots = new JList (invalidRoots.toArray()); 518 roots.setCellRenderer (new InvalidRootRenderer(true)); 519 JScrollPane p = new JScrollPane (roots); 520 c = new GridBagConstraints(); 521 c.gridx = GridBagConstraints.RELATIVE; 522 c.gridy = GridBagConstraints.RELATIVE; 523 c.gridwidth = GridBagConstraints.REMAINDER; 524 c.fill = GridBagConstraints.BOTH; 525 c.anchor = GridBagConstraints.NORTHWEST; 526 c.weightx = c.weighty = 1.0; 527 c.insets = new Insets (0,0,12,0); 528 ((GridBagLayout)this.getLayout()).setConstraints(p,c); 529 this.add (p); 530 label.setLabelFor(roots); 531 roots.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(J2SESourceRootsUi.class,"AD_InvalidRoot")); 532 JLabel label2 = new JLabel (); 533 label2.setText (NbBundle.getMessage(J2SESourceRootsUi.class,"MSG_InvalidRoot2")); 534 c = new GridBagConstraints(); 535 c.gridx = GridBagConstraints.RELATIVE; 536 c.gridy = GridBagConstraints.RELATIVE; 537 c.gridwidth = GridBagConstraints.REMAINDER; 538 c.fill = GridBagConstraints.HORIZONTAL; 539 c.anchor = GridBagConstraints.NORTHWEST; 540 c.weightx = 1.0; 541 c.insets = new Insets (0,0,0,0); 542 ((GridBagLayout)this.getLayout()).setConstraints(label2,c); 543 this.add (label2); 544 } 545 546 private static class InvalidRootRenderer extends DefaultListCellRenderer { 547 548 private boolean projectConflict; 549 550 public InvalidRootRenderer (boolean projectConflict) { 551 this.projectConflict = projectConflict; 552 } 553 554 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 555 File f = (File ) value; 556 String message = f.getAbsolutePath(); 557 if (projectConflict) { 558 Project p = FileOwnerQuery.getOwner(f.toURI()); 559 if (p!=null) { 560 ProjectInformation pi = ProjectUtils.getInformation(p); 561 String projectName = pi.getDisplayName(); 562 message = MessageFormat.format (NbBundle.getMessage(J2SESourceRootsUi.class,"TXT_RootOwnedByProject"), new Object [] { 563 message, 564 projectName}); 565 } 566 } 567 return super.getListCellRendererComponent(list, message, index, isSelected, cellHasFocus); 568 } 569 } 570 } 571 572 } 573 | Popular Tags |