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