1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage;
14 import java.util.ArrayList;
15 import java.util.List;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.events.DisposeEvent;
19 import org.eclipse.swt.events.DisposeListener;
20 import org.eclipse.swt.graphics.Color;
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Display;
25 import org.eclipse.swt.widgets.Menu;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.core.resources.IFile;
32 import org.eclipse.core.resources.IFolder;
33 import org.eclipse.core.resources.IResource;
34 import org.eclipse.core.resources.IWorkspace;
35 import org.eclipse.core.resources.IWorkspaceRunnable;
36 import org.eclipse.core.resources.ResourcesPlugin;
38 import org.eclipse.jface.action.IMenuListener;
39 import org.eclipse.jface.action.IMenuManager;
40 import org.eclipse.jface.action.MenuManager;
41 import org.eclipse.jface.viewers.DoubleClickEvent;
42 import org.eclipse.jface.viewers.IDoubleClickListener;
43 import org.eclipse.jface.viewers.IPostSelectionProvider;
44 import org.eclipse.jface.viewers.ISelection;
45 import org.eclipse.jface.viewers.ISelectionChangedListener;
46 import org.eclipse.jface.viewers.IStructuredSelection;
47 import org.eclipse.jface.viewers.StructuredSelection;
48 import org.eclipse.jface.viewers.TreeViewer;
49 import org.eclipse.jface.viewers.Viewer;
51 import org.eclipse.ui.part.ISetSelectionTarget;
53 import org.eclipse.jdt.core.IClasspathEntry;
54 import org.eclipse.jdt.core.IJavaProject;
55 import org.eclipse.jdt.core.IPackageFragment;
56 import org.eclipse.jdt.core.IPackageFragmentRoot;
57 import org.eclipse.jdt.core.JavaModelException;
59 import org.eclipse.jdt.internal.corext.buildpath.ClasspathModifier;
60 import org.eclipse.jdt.internal.corext.util.Messages;
62 import org.eclipse.jdt.ui.JavaElementComparator;
63 import org.eclipse.jdt.ui.JavaElementLabels;
65 import org.eclipse.jdt.internal.ui.JavaPlugin;
66 import org.eclipse.jdt.internal.ui.filters.LibraryFilter;
67 import org.eclipse.jdt.internal.ui.filters.OutputFolderFilter;
68 import org.eclipse.jdt.internal.ui.packageview.PackageExplorerContentProvider;
69 import org.eclipse.jdt.internal.ui.packageview.PackageFragmentRootContainer;
70 import org.eclipse.jdt.internal.ui.viewsupport.AppearanceAwareLabelProvider;
71 import org.eclipse.jdt.internal.ui.viewsupport.DecoratingJavaLabelProvider;
72 import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
73 import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
74 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
75 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
76 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
77 import org.eclipse.jdt.internal.ui.workingsets.WorkingSetModel;
80 * A package explorer widget that can be used in dialogs. It uses its own
81 * content provider, label provider, element sorter and filter to display
82 * elements that are not shown usually in the package explorer of the
85 public class DialogPackageExplorer implements IMenuListener, IPostSelectionProvider, ISetSelectionTarget {
87 * A extended content provider for the package explorer which can additionally display
88 * an output folder item.
90 private final class PackageContentProvider extends PackageExplorerContentProvider {
91 public PackageContentProvider() {
96 * Get the elements of the current project
98 * @param element the element to get the children from, will
99 * not be used, instead the project children are returned directly
100 * @return returns the children of the project
103 public Object[] getElements(Object element) {
104 if (fCurrJProject == null || !fCurrJProject.exists())
105 return new Object[0];
106 return new Object[] {fCurrJProject};
110 * Get the children of the current <code>element</code>. If the
111 * element is of type <code>IPackageFragmentRoot</code> and
112 * displaying the output folders is selected, then an icon for
113 * the output folder is created and displayed additionally.
115 * @param element the current element to get the children from
116 * @return an array of children
119 public Object[] getChildren(Object element) {
120 Object[] children= super.getChildren(element);
121 if (((element instanceof IPackageFragmentRoot && !ClasspathModifier.isInExternalOrArchive((IPackageFragmentRoot) element)) ||
122 (element instanceof IJavaProject && fCurrJProject.isOnClasspath(fCurrJProject))) && fShowOutputFolders) {
124 IClasspathEntry entry;
125 if (element instanceof IPackageFragmentRoot)
126 entry= ((IPackageFragmentRoot) element).getRawClasspathEntry();
128 entry= ClasspathModifier.getClasspathEntryFor(fCurrJProject.getPath(), fCurrJProject, IClasspathEntry.CPE_SOURCE);
129 CPListElement parent= CPListElement.createFromExisting(entry, fCurrJProject);
130 CPListElementAttribute outputFolder= new CPListElementAttribute(parent, CPListElement.OUTPUT,
131 parent.getAttribute(CPListElement.OUTPUT), true);
132 Object[] extendedChildren= new Object[children.length + 1];
133 System.arraycopy(children, 0, extendedChildren, 1, children.length);
134 extendedChildren[0]= outputFolder;
135 return extendedChildren;
136 } catch (JavaModelException e) {
147 * A extended label provider for the package explorer which can additionally display
148 * an output folder item.
150 private final class PackageLabelProvider extends AppearanceAwareLabelProvider {
151 private CPListLabelProvider outputFolderLabel;
153 public PackageLabelProvider(long textFlags, int imageFlags) {
154 super(textFlags, imageFlags);
155 outputFolderLabel= new CPListLabelProvider();
159 public String getText(Object element) {
160 if (element instanceof CPListElementAttribute)
161 return outputFolderLabel.getText(element);
162 String text= super.getText(element);
164 if (element instanceof IPackageFragmentRoot) {
165 IPackageFragmentRoot root= (IPackageFragmentRoot)element;
166 if (root.exists() && ClasspathModifier.filtersSet(root)) {
167 IClasspathEntry entry= root.getRawClasspathEntry();
168 int excluded= entry.getExclusionPatterns().length;
170 return Messages.format(NewWizardMessages.DialogPackageExplorer_LabelProvider_SingleExcluded, text);
171 else if (excluded > 1)
172 return Messages.format(NewWizardMessages.DialogPackageExplorer_LabelProvider_MultiExcluded, new Object[] {text, new Integer(excluded)});
175 if (element instanceof IJavaProject) {
176 IJavaProject project= (IJavaProject)element;
177 if (project.exists() && project.isOnClasspath(project)) {
178 IPackageFragmentRoot root= project.findPackageFragmentRoot(project.getPath());
179 if (ClasspathModifier.filtersSet(root)) {
180 IClasspathEntry entry= root.getRawClasspathEntry();
181 int excluded= entry.getExclusionPatterns().length;
183 return Messages.format(NewWizardMessages.DialogPackageExplorer_LabelProvider_SingleExcluded, text);
184 else if (excluded > 1)
185 return Messages.format(NewWizardMessages.DialogPackageExplorer_LabelProvider_MultiExcluded, new Object[] {text, new Integer(excluded)});
189 if (element instanceof IFile || element instanceof IFolder) {
190 IResource resource= (IResource)element;
191 if (resource.exists() && ClasspathModifier.isExcluded(resource, fCurrJProject))
192 return Messages.format(NewWizardMessages.DialogPackageExplorer_LabelProvider_Excluded, text);
194 } catch (JavaModelException e) {
201 * @see org.eclipse.jdt.internal.ui.viewsupport.JavaUILabelProvider#getForeground(java.lang.Object)
204 public Color getForeground(Object element) {
206 if (element instanceof IPackageFragmentRoot) {
207 IPackageFragmentRoot root= (IPackageFragmentRoot)element;
208 if (root.exists() && ClasspathModifier.filtersSet(root))
209 return getBlueColor();
211 if (element instanceof IJavaProject) {
212 IJavaProject project= (IJavaProject)element;
213 if (project.exists() && project.isOnClasspath(project)) {
214 IPackageFragmentRoot root= project.findPackageFragmentRoot(project.getPath());
215 if (root != null && ClasspathModifier.filtersSet(root))
216 return getBlueColor();
219 if (element instanceof IFile || element instanceof IFolder) {
220 IResource resource= (IResource)element;
221 if (resource.exists() && ClasspathModifier.isExcluded(resource, fCurrJProject))
222 return getBlueColor();
224 } catch (JavaModelException e) {
230 private Color getBlueColor() {
231 return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
235 public Image getImage(Object element) {
236 if (element instanceof CPListElementAttribute)
237 return outputFolderLabel.getImage(element);
238 return super.getImage(element);
242 public void dispose() {
243 outputFolderLabel.dispose();
249 * A extended element sorter for the package explorer which displays the output
250 * folder (if any) as first child of a source folder. The other java elements
251 * are sorted in the normal way.
253 private final class ExtendedJavaElementSorter extends JavaElementComparator {
254 public ExtendedJavaElementSorter() {
259 public int compare(Viewer viewer, Object e1, Object e2) {
260 if (e1 instanceof CPListElementAttribute)
262 if (e2 instanceof CPListElementAttribute)
264 return super.compare(viewer, e1, e2);
269 * An extended filter for the package explorer which filters
271 * files named ".classpath" or ".project",
272 * the default package, and
275 private final class PackageFilter extends LibraryFilter {
276 private OutputFolderFilter fOutputFolderFilter= new OutputFolderFilter();
278 public boolean select(Viewer viewer, Object parentElement, Object element) {
280 if (element instanceof IFile) {
281 IFile file= (IFile) element;
282 if (file.getName().equals(".classpath") || file.getName().equals(".project")) //$NON-NLS-1$//$NON-NLS-2$
284 } else if (element instanceof IPackageFragmentRoot) {
285 IClasspathEntry cpe= ((IPackageFragmentRoot)element).getRawClasspathEntry();
286 if (cpe == null || cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER || cpe.getEntryKind() == IClasspathEntry.CPE_LIBRARY || cpe.getEntryKind() == IClasspathEntry.CPE_VARIABLE)
288 } else if (element instanceof PackageFragmentRootContainer) {
290 } else if (element instanceof IPackageFragment) {
291 IPackageFragment fragment= (IPackageFragment)element;
292 if (fragment.isDefaultPackage() && !fragment.hasChildren())
294 } else if (element instanceof IFolder) {
295 IFolder folder= (IFolder)element;
296 if (folder.getName().startsWith(".")) //$NON-NLS-1$
299 } catch (JavaModelException e) {
302 /*if (element instanceof IPackageFragmentRoot) {
303 IPackageFragmentRoot root= (IPackageFragmentRoot)element;
304 if (root.getElementName().endsWith(".jar") || root.getElementName().endsWith(".zip")) //$NON-NLS-1$ //$NON-NLS-2$
307 return /*super.select(viewer, parentElement, element) &&*/ fOutputFolderFilter.select(viewer, parentElement, element);
311 /** The tree showing the project like in the package explorer */
312 private TreeViewer fPackageViewer;
313 /** The tree's context menu */
314 private Menu fContextMenu;
315 /** The action group which is used to fill the context menu. The action group
316 * is also called if the selection on the tree changes */
317 private DialogPackageExplorerActionGroup fActionGroup;
319 * Flag to indicate whether output folders
320 * can be created or not. This is used to
321 * set the content correctly in the case
322 * that a IPackageFragmentRoot is selected.
324 * @see #showOutputFolders(boolean)
326 private boolean fShowOutputFolders= false;
328 /** Stores the current selection in the tree
329 * @see #getSelection()
331 private IStructuredSelection fCurrentSelection;
333 /** The current java project
334 * @see #setInput(IJavaProject)
336 private IJavaProject fCurrJProject;
337 private PackageContentProvider fContentProvider;
339 public DialogPackageExplorer() {
342 fCurrentSelection= new StructuredSelection();
345 public Control createControl(Composite parent) {
346 fPackageViewer= new TreeViewer(parent, SWT.MULTI);
347 fPackageViewer.setComparer(WorkingSetModel.COMPARER);
348 fPackageViewer.addFilter(new PackageFilter());
349 fPackageViewer.setComparator(new ExtendedJavaElementSorter());
350 fPackageViewer.addDoubleClickListener(new IDoubleClickListener() {
351 public void doubleClick(DoubleClickEvent event) {
352 Object element= ((IStructuredSelection)event.getSelection()).getFirstElement();
353 if (fPackageViewer.isExpandable(element)) {
354 fPackageViewer.setExpandedState(element, !fPackageViewer.getExpandedState(element));
356 if (element instanceof CPListElementAttribute) {
357 CPListElementAttribute attribute= (CPListElementAttribute)element;
358 if (attribute.getKey().equals(CPListElement.OUTPUT)) {
359 fActionGroup.getEditOutputFolderAction().run();
366 MenuManager menuMgr= new MenuManager("#PopupMenu"); //$NON-NLS-1$
367 menuMgr.setRemoveAllWhenShown(true);
368 menuMgr.addMenuListener(this);
369 fContextMenu= menuMgr.createContextMenu(fPackageViewer.getTree());
370 fPackageViewer.getTree().setMenu(fContextMenu);
371 parent.addDisposeListener(new DisposeListener() {
372 public void widgetDisposed(DisposeEvent e) {
373 fContextMenu.dispose();
377 return fPackageViewer.getControl();
381 * Sets the action group for the package explorer.
382 * The action group is necessary to populate the
383 * context menu with available actions. If no
384 * context menu is needed, then this method does not
387 * Should only be called once.
389 * @param actionGroup the action group to be used for
392 public void setActionGroup(final DialogPackageExplorerActionGroup actionGroup) {
393 fActionGroup= actionGroup;
397 * Populate the context menu with the necessary actions.
399 * @see org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
401 public void menuAboutToShow(IMenuManager manager) {
402 if (fActionGroup == null) // no context menu
404 JavaPlugin.createStandardGroups(manager);
405 fActionGroup.fillContextMenu(manager);
409 * Set the content and label provider of the
410 * <code>fPackageViewer</code>
412 public void setContentProvider() {
413 if (fContentProvider != null) {
414 fContentProvider.dispose();
416 fContentProvider= new PackageContentProvider();
417 fContentProvider.setIsFlatLayout(true);
418 PackageLabelProvider labelProvider= new PackageLabelProvider(AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS | JavaElementLabels.P_COMPRESSED,
419 AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS | JavaElementImageProvider.SMALL_ICONS);
420 fPackageViewer.setContentProvider(fContentProvider);
421 fPackageViewer.setLabelProvider(new DecoratingJavaLabelProvider(labelProvider, false));
425 * Set the input for the package explorer.
427 * @param project the project to be displayed
429 public void setInput(IJavaProject project) {
430 IJavaProject oldProject= fCurrJProject;
431 fCurrJProject= project;
432 if (fContentProvider != null)
433 fContentProvider.inputChanged(fPackageViewer, oldProject, fCurrJProject);
434 fPackageViewer.setInput(new Object[0]);
436 List<IJavaProject> selectedElements= new ArrayList<IJavaProject>();
437 selectedElements.add(fCurrJProject);
438 setSelection(selectedElements);
441 public void dispose() {
442 if (fContentProvider != null) {
443 fContentProvider.dispose();
444 fContentProvider= null;
446 if (fActionGroup != null) {
447 fActionGroup.dispose();
450 fPackageViewer= null;
454 * Set the selection and focus to the list of elements
455 * @param elements the object to be selected and displayed
457 public void setSelection(final List<?> elements) {
458 if (elements == null || elements.size() == 0)
461 ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
462 public void run(IProgressMonitor monitor) throws CoreException {
463 fPackageViewer.refresh();
464 IStructuredSelection selection= new StructuredSelection(elements);
465 fPackageViewer.setSelection(selection, true);
466 fPackageViewer.getTree().setFocus();
468 if (elements.size() == 1 && elements.get(0) instanceof IJavaProject)
469 fPackageViewer.expandToLevel(elements.get(0), 1);
471 }, ResourcesPlugin.getWorkspace().getRoot(), IWorkspace.AVOID_UPDATE, new NullProgressMonitor());
472 } catch (CoreException e) {
478 * The current list of selected elements. The
479 * list may be empty if no element is selected.
481 * @return the current selection
483 public ISelection getSelection() {
484 return fCurrentSelection;
488 * Get the viewer's control
490 * @return the viewers control
492 public Control getViewerControl() {
493 return fPackageViewer.getControl();
497 * Method that is called whenever setting of
498 * output folders is allowed or forbidden (for example
499 * on changing a checkbox with this setting):
501 * @param showOutputFolders <code>true</code> if output
502 * folders should be shown, <code>false</code> otherwise.
504 public void showOutputFolders(boolean showOutputFolders) {
505 fShowOutputFolders= showOutputFolders;
506 fActionGroup.getEditOutputFolderAction().showOutputFolders(showOutputFolders);
507 fPackageViewer.refresh();
513 public void addSelectionChangedListener(ISelectionChangedListener listener) {
514 fPackageViewer.addSelectionChangedListener(listener);
520 public void removeSelectionChangedListener(ISelectionChangedListener listener) {
521 fPackageViewer.removeSelectionChangedListener(listener);
527 public void setSelection(ISelection selection) {
528 setSelection(((StructuredSelection)selection).toList());
534 public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
535 fPackageViewer.addPostSelectionChangedListener(listener);
541 public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
542 fPackageViewer.removePostSelectionChangedListener(listener);
548 public void selectReveal(ISelection selection) {
549 setSelection(selection);