1 19 20 package org.netbeans.modules.apisupport.project.ui; 21 22 import java.awt.Dialog ; 23 import java.awt.Image ; 24 import java.awt.event.ActionEvent ; 25 import java.awt.event.ActionListener ; 26 import java.io.File ; 27 import java.io.IOException ; 28 import java.net.URL ; 29 import java.util.ArrayList ; 30 import java.util.Arrays ; 31 import java.util.Collections ; 32 import java.util.List ; 33 import java.util.SortedSet ; 34 import java.util.TreeSet ; 35 import javax.swing.AbstractAction ; 36 import javax.swing.Action ; 37 import javax.swing.Icon ; 38 import javax.swing.ImageIcon ; 39 import org.netbeans.api.project.Project; 40 import org.netbeans.api.project.ProjectManager; 41 import org.netbeans.api.project.ui.OpenProjects; 42 import org.netbeans.modules.apisupport.project.NbModuleProject; 43 import org.netbeans.modules.apisupport.project.spi.NbModuleProvider; 44 import org.netbeans.modules.apisupport.project.ProjectXMLManager; 45 import org.netbeans.modules.apisupport.project.Util; 46 import org.netbeans.modules.apisupport.project.ui.ModulesNodeFactory.AddNewLibraryWrapperAction; 47 import org.netbeans.modules.apisupport.project.ui.customizer.AddModulePanel; 48 import org.netbeans.modules.apisupport.project.ui.customizer.EditDependencyPanel; 49 import org.netbeans.modules.apisupport.project.ui.customizer.ModuleDependency; 50 import org.netbeans.modules.apisupport.project.ui.customizer.SingleModuleProperties; 51 import org.netbeans.modules.apisupport.project.universe.ModuleEntry; 52 import org.netbeans.modules.apisupport.project.universe.NbPlatform; 53 import org.netbeans.modules.apisupport.project.universe.TestModuleDependency; 54 import org.netbeans.spi.java.project.support.ui.PackageView; 55 import org.netbeans.spi.project.support.ant.AntProjectEvent; 56 import org.netbeans.spi.project.support.ant.AntProjectHelper; 57 import org.netbeans.spi.project.support.ant.AntProjectListener; 58 import org.openide.DialogDescriptor; 59 import org.openide.DialogDisplayer; 60 import org.openide.ErrorManager; 61 import org.openide.actions.DeleteAction; 62 import org.openide.actions.FindAction; 63 import org.openide.awt.HtmlBrowser; 64 import org.openide.awt.StatusDisplayer; 65 import org.openide.filesystems.FileObject; 66 import org.openide.filesystems.FileUtil; 67 import org.openide.filesystems.URLMapper; 68 import org.openide.nodes.AbstractNode; 69 import org.openide.nodes.Children; 70 import org.openide.nodes.FilterNode; 71 import org.openide.nodes.Node; 72 import org.openide.util.HelpCtx; 73 import org.openide.util.Mutex; 74 import org.openide.util.MutexException; 75 import org.openide.util.NbBundle; 76 import org.openide.util.RequestProcessor; 77 import org.openide.util.Utilities; 78 import org.openide.util.actions.CookieAction; 79 import org.openide.util.actions.SystemAction; 80 import org.openide.util.lookup.Lookups; 81 import org.openide.util.lookup.ProxyLookup; 82 83 86 final class LibrariesNode extends AbstractNode { 87 88 static final String LIBRARIES_NAME = "libraries"; 90 private static final String DISPLAY_NAME = getMessage("LBL_libraries"); 91 92 93 static final RequestProcessor RP = new RequestProcessor(); 94 95 private final Action [] actions; 96 97 public LibrariesNode(final NbModuleProject project) { 98 super(new LibrariesChildren(project)); 99 setName(LIBRARIES_NAME); 100 setDisplayName(DISPLAY_NAME); 101 if (Util.getModuleType(project) == NbModuleProvider.SUITE_COMPONENT) { 102 actions = new Action [] { 103 new AddModuleDependencyAction(project), 104 new AddNewLibraryWrapperAction(project, project) 105 }; 106 } else { 107 actions = new Action [] { 108 new AddModuleDependencyAction(project), 109 }; 110 } 111 } 112 113 public Image getIcon(int type) { 114 return getIcon(false); 115 } 116 117 public Image getOpenedIcon(int type) { 118 return getIcon(true); 119 } 120 121 private Image getIcon(boolean opened) { 122 Image badge = Utilities.loadImage("org/netbeans/modules/apisupport/project/ui/resources/libraries-badge.png", true); 123 return Utilities.mergeImages(UIUtil.getTreeFolderIcon(opened), badge, 8, 8); 124 } 125 126 public Action [] getActions(boolean context) { 127 return actions; 128 } 129 130 private static String createHtmlDescription(final ModuleDependency dep) { 131 StringBuffer shortDesc = new StringBuffer ("<html><u>" + dep.getModuleEntry().getCodeNameBase() + "</u><br>"); if (dep.hasImplementationDepedendency()) { 134 shortDesc.append("<br><font color=\"red\">" + getMessage("CTL_ImplementationDependency") + "</font>"); 135 } 136 if (dep.hasCompileDependency()) { 137 shortDesc.append("<br>").append(getMessage("CTL_NeededToCompile")); 138 } 139 if (dep.getReleaseVersion() != null) { 140 shortDesc.append("<br>").append(NbBundle.getMessage(LibrariesNode.class, "CTL_MajorReleaseVersion", 141 dep.getReleaseVersion())); 142 } 143 if (dep.getSpecificationVersion() != null) { 144 shortDesc.append("<br>").append(NbBundle.getMessage(LibrariesNode.class, "CTL_SpecificationVersion", 145 dep.getSpecificationVersion())); 146 } 147 shortDesc.append("</html>"); return shortDesc.toString(); 149 } 150 151 private static String getMessage(String bundleKey) { 152 return NbBundle.getMessage(LibrariesNode.class, bundleKey); 153 } 154 155 private static final class LibrariesChildren extends Children.Keys<Object > implements AntProjectListener { 156 157 private static final String JDK_PLATFORM_NAME = "jdkPlatform"; 159 private static final String LIBRARIES_ICON = 160 "org/netbeans/modules/apisupport/project/ui/resources/libraries.gif"; 162 private final NbModuleProject project; 163 164 private ImageIcon librariesIcon; 165 166 LibrariesChildren(final NbModuleProject project) { 167 this.project = project; 168 } 169 170 protected void addNotify() { 171 super.addNotify(); 172 project.getHelper().addAntProjectListener(this); 173 refreshKeys(); 174 } 175 176 protected void removeNotify() { 177 setKeys(Collections.emptySet()); 178 project.getHelper().removeAntProjectListener(this); 179 super.removeNotify(); 180 } 181 182 private void refreshKeys() { 183 RP.post(new Runnable () { 189 public void run() { 190 try { 191 ProjectManager.mutex().readAccess(new Mutex.ExceptionAction<Void >() { 192 public Void run() throws Exception { 193 ProjectXMLManager pxm = new ProjectXMLManager(project); 194 final List <Object > keys = new ArrayList <Object >(); 195 keys.add(JDK_PLATFORM_NAME); 196 SortedSet <ModuleDependency> deps = new TreeSet <ModuleDependency>(ModuleDependency.LOCALIZED_NAME_COMPARATOR); 197 deps.addAll(pxm.getDirectDependencies()); 198 keys.addAll(deps); 199 RP.post(new Runnable () { 203 public void run() { 204 setKeys(Collections.unmodifiableList(keys)); 205 } 206 }); 207 return null; 208 } 209 }); 210 } catch (MutexException e) { 211 assert false : e.getException(); 212 } 213 } 214 }); 215 } 216 217 protected Node[] createNodes(Object key) { 218 Node node; 219 if (key == JDK_PLATFORM_NAME) { 220 node = PlatformNode.create(project.evaluator(), "nbjdk.home"); } else { 222 ModuleDependency dep = (ModuleDependency) key; 223 File srcF = dep.getModuleEntry().getSourceLocation(); 224 if (srcF == null) { 225 File jarF = dep.getModuleEntry().getJarLocation(); 226 URL jarRootURL = Util.urlForJar(jarF); 227 assert jarRootURL != null; 228 FileObject root = URLMapper.findFileObject(jarRootURL); 229 ModuleEntry me = dep.getModuleEntry(); 230 String name = me.getLocalizedName() + " - " + me.getCodeNameBase(); Icon icon = getLibrariesIcon(); 232 Node pvNode = ActionFilterNode.create( 233 PackageView.createPackageView(new LibrariesSourceGroup(root, name, icon, icon))); 234 node = new LibraryDependencyNode(dep, project, pvNode); 235 } else { 236 node = new ProjectDependencyNode(dep, project); 237 } 238 } 239 assert node != null; 240 return new Node[] { node }; 241 } 242 243 public void configurationXmlChanged(AntProjectEvent ev) { 244 if (project.getHelper().resolveFileObject(AntProjectHelper.PROJECT_XML_PATH) != null) { 247 refreshKeys(); 248 } 249 } 250 251 public void propertiesChanged(AntProjectEvent ev) { 252 } 254 255 274 275 private Icon getLibrariesIcon() { 276 if (librariesIcon == null) { 277 librariesIcon = new ImageIcon (Utilities.loadImage(LIBRARIES_ICON, true)); 278 } 279 return librariesIcon; 280 } 281 282 } 283 284 private static final class ProjectDependencyNode extends AbstractNode { 285 286 private final ModuleDependency dep; 287 private final NbModuleProject project; 288 289 ProjectDependencyNode(final ModuleDependency dep, final NbModuleProject project) { 290 super(Children.LEAF, Lookups.fixed(dep, project, dep.getModuleEntry())); 291 this.dep = dep; 292 this.project = project; 293 ModuleEntry me = dep.getModuleEntry(); 294 setIconBaseWithExtension(NbModuleProject.NB_PROJECT_ICON_PATH); 295 setDisplayName(me.getLocalizedName()); 296 setShortDescription(LibrariesNode.createHtmlDescription(dep)); 297 } 298 299 public Action [] getActions(boolean context) { 300 return new Action [] { 301 SystemAction.get(OpenProjectAction.class), 302 new EditDependencyAction(dep, project), 303 new ShowJavadocAction(dep, project), 304 SystemAction.get(RemoveAction.class), 305 }; 306 } 307 308 public Action getPreferredAction() { 309 return getActions(false)[0]; } 311 312 public boolean canDestroy() { 313 return true; 314 } 315 316 public void destroy() throws IOException { 317 removeDependency(project, dep); 318 } 319 320 } 321 322 private static final class LibraryDependencyNode extends FilterNode { 323 324 private final ModuleDependency dep; 325 private final NbModuleProject project; 326 327 LibraryDependencyNode(final ModuleDependency dep, 328 final NbModuleProject project, final Node original) { 329 super(original, null, new ProxyLookup(original.getLookup(), Lookups.fixed(dep, project))); 330 this.dep = dep; 331 this.project = project; 332 setShortDescription(LibrariesNode.createHtmlDescription(dep)); 333 } 334 335 public Action [] getActions(boolean context) { 336 return new Action [] { 337 new EditDependencyAction(dep, project), 338 SystemAction.get(FindAction.class), 339 new ShowJavadocAction(dep, project), 340 SystemAction.get(RemoveAction.class), 341 }; 342 } 343 344 public Action getPreferredAction() { 345 return new EditDependencyAction(dep, project); 346 } 347 348 public boolean canDestroy() { 349 return true; 350 } 351 352 public void destroy() throws IOException { 353 removeDependency(project, dep); 354 } 355 356 } 357 358 private static void removeDependency(NbModuleProject project, ModuleDependency dep) throws IOException { 359 new ProjectXMLManager(project).removeDependencies(Collections.singleton(dep)); 360 ProjectManager.getDefault().saveProject(project); 361 } 362 363 private static final class AddModuleDependencyAction extends AbstractAction { 364 365 private final NbModuleProject project; 366 367 AddModuleDependencyAction(final NbModuleProject project) { 368 super(getMessage("CTL_AddModuleDependency")); 369 this.project = project; 370 } 371 372 public void actionPerformed(ActionEvent ev) { 373 SingleModuleProperties props = SingleModuleProperties.getInstance(project); 375 final AddModulePanel addPanel = new AddModulePanel(props); 376 final DialogDescriptor descriptor = new DialogDescriptor(addPanel, 377 getMessage("CTL_AddModuleDependencyTitle")); 378 descriptor.setHelpCtx(new HelpCtx(AddModulePanel.class)); 379 descriptor.setClosingOptions(new Object [0]); 380 final Dialog d = DialogDisplayer.getDefault().createDialog(descriptor); 381 descriptor.setButtonListener(new ActionListener () { 382 public void actionPerformed(ActionEvent e) { 383 if (DialogDescriptor.OK_OPTION.equals(e.getSource()) && 384 addPanel.getSelectedDependencies().length == 0) { 385 return; 386 } 387 d.setVisible(false); 388 d.dispose(); 389 } 390 }); 391 d.setVisible(true); 392 if (descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) { 393 ModuleDependency[] newDeps = addPanel.getSelectedDependencies(); 394 ProjectXMLManager pxm = new ProjectXMLManager(project); 395 try { 396 for (ModuleDependency dep : newDeps) { 397 pxm.addDependency(dep); 398 } 399 ProjectManager.getDefault().saveProject(project); 400 } catch (IOException e) { 401 ErrorManager.getDefault().annotate(e, "Cannot add selected dependencies: " + Arrays.asList(newDeps)); ErrorManager.getDefault().notify(e); 403 } 404 } 405 d.dispose(); 406 } 407 408 } 409 410 private static final class EditDependencyAction extends AbstractAction { 411 412 private final ModuleDependency dep; 413 private final NbModuleProject project; 414 415 EditDependencyAction(final ModuleDependency dep, final NbModuleProject project) { 416 super(getMessage("CTL_EditDependency")); 417 this.dep = dep; 418 this.project = project; 419 } 420 421 public void actionPerformed(ActionEvent ev) { 422 EditDependencyPanel editPanel = new EditDependencyPanel(dep, 424 NbPlatform.getPlatformByDestDir(dep.getModuleEntry().getDestDir())); 425 DialogDescriptor descriptor = new DialogDescriptor(editPanel, 426 NbBundle.getMessage(LibrariesNode.class, "CTL_EditModuleDependencyTitle", 427 dep.getModuleEntry().getLocalizedName())); 428 descriptor.setHelpCtx(new HelpCtx(EditDependencyPanel.class)); 429 Dialog d = DialogDisplayer.getDefault().createDialog(descriptor); 430 d.setVisible(true); 431 if (descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) { 432 ModuleDependency editedDep = editPanel.getEditedDependency(); 433 try { 434 ProjectXMLManager pxm = new ProjectXMLManager(project); 435 SortedSet <ModuleDependency> deps = new TreeSet <ModuleDependency>(pxm.getDirectDependencies()); 436 deps.remove(dep); 437 deps.add(editedDep); 438 pxm.replaceDependencies(deps); 439 ProjectManager.getDefault().saveProject(project); 440 } catch (IOException e) { 441 ErrorManager.getDefault().annotate(e, "Cannot store dependency: " + editedDep); ErrorManager.getDefault().notify(e); 443 } 444 } 445 d.dispose(); 446 } 447 448 } 449 450 private static final class ShowJavadocAction extends AbstractAction { 451 452 private final ModuleDependency dep; 453 private final NbModuleProject project; 454 455 private URL currectJavadoc; 456 457 ShowJavadocAction(final ModuleDependency dep, final NbModuleProject project) { 458 super(getMessage("CTL_ShowJavadoc")); 459 this.dep = dep; 460 this.project = project; 461 } 462 463 public void actionPerformed(ActionEvent ev) { 464 HtmlBrowser.URLDisplayer.getDefault().showURL(currectJavadoc); 465 } 466 467 public boolean isEnabled() { 468 if (Util.getModuleType(project) == NbModuleProvider.NETBEANS_ORG) { 469 currectJavadoc = Util.findJavadocForNetBeansOrgModules(dep); 470 } else { 471 currectJavadoc = Util.findJavadoc(dep, project.getPlatform(true)); 472 } 473 return currectJavadoc != null; 474 } 475 476 } 477 478 static final class OpenProjectAction extends CookieAction { 479 480 protected void performAction(Node[] activatedNodes) { 481 try { 482 final Project[] projects = new Project[activatedNodes.length]; 483 for (int i = 0; i < activatedNodes.length; i++) { 484 ModuleEntry me = activatedNodes[i].getLookup().lookup(ModuleEntry.class); 485 assert me != null; 486 File prjDir = me.getSourceLocation(); 487 assert prjDir != null; 488 Project project = ProjectManager.getDefault().findProject(FileUtil.toFileObject(prjDir)); 489 assert project != null; 490 projects[i] = project; 491 } 492 RequestProcessor.getDefault().post(new Runnable () { 493 public void run() { 494 StatusDisplayer.getDefault().setStatusText( 495 getMessage("MSG_OpeningProjects")); 496 OpenProjects.getDefault().open(projects, false); 497 } 498 }); 499 } catch (IOException e) { 500 assert false : e; 501 } 502 } 503 504 public boolean isEnabled() { 505 return true; 506 } 507 508 public String getName() { 509 return getMessage("CTL_Open"); 510 } 511 512 public HelpCtx getHelpCtx() { 513 return HelpCtx.DEFAULT_HELP; 514 } 515 516 protected boolean asynchronous() { 517 return false; 518 } 519 520 protected int mode() { 521 return CookieAction.MODE_ALL; 522 } 523 524 protected Class [] cookieClasses() { 525 return new Class [] { ModuleDependency.class, TestModuleDependency.class }; 526 } 527 528 } 529 530 private static final class RemoveAction extends DeleteAction { 531 532 public String getName() { 533 return getMessage("CTL_RemoveDependency"); 534 } 535 536 protected void initialize() { 537 super.initialize(); 538 putValue(Action.ACCELERATOR_KEY, SystemAction.get(DeleteAction.class).getValue(Action.ACCELERATOR_KEY)); 539 } 540 541 } 542 543 } 544 | Popular Tags |