diff options
| author | Christian Pontesegger | 2012-10-16 18:43:47 +0000 |
|---|---|---|
| committer | Curtis Windatt | 2012-10-16 18:43:47 +0000 |
| commit | 54f28d1df708c084068cfe9dfec61c9a30ef0fcb (patch) | |
| tree | ee0d8367338826fef6de93c1d7d98976e2bb4815 | |
| parent | c6ff7d492213acc7c8e1e7a5d22d8dfdee619b64 (diff) | |
| download | eclipse.pde.ui-54f28d1df708c084068cfe9dfec61c9a30ef0fcb.tar.gz eclipse.pde.ui-54f28d1df708c084068cfe9dfec61c9a30ef0fcb.tar.xz eclipse.pde.ui-54f28d1df708c084068cfe9dfec61c9a30ef0fcb.zip | |
Bug 386197 - add view to browse for plug-in imagesv20121016-184347I20121016-2240
Improve image caching
7 files changed, 219 insertions, 113 deletions
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java index 172aa40421..cb62562ebd 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java @@ -2212,6 +2212,8 @@ public class PDEUIMessages extends NLS { public static String AbstractPluginBlock_counter; + public static String AbstractRepository_ScanForUI; + public static String EquinoxPluginBlock_levelColumn; public static String EquinoxPluginBlock_autoColumn; diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties index 1a3f5b0e7c..9b9f903f52 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties @@ -804,6 +804,7 @@ AbstractLauncherToolbar_noProblems=No problems were detected. AbstractSchemaDetails_minOccurLabel=Min Occurrences: AbstractSchemaDetails_maxOccurLabel=Max Occurrences: AbstractLauncherToolbar_noSelection=No {0} are selected. +AbstractRepository_ScanForUI=Scan for UI images AbstractSchemaDetails_unboundedButton=Unbounded AbstractSchemaDetails_descriptionLabel=Description: diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/IImageTarget.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/IImageTarget.java index 8cc8a1228a..5cc32f9ed7 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/IImageTarget.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/IImageTarget.java @@ -11,9 +11,19 @@ package org.eclipse.pde.internal.ui.views.imagebrowser; -import org.eclipse.swt.graphics.ImageData; - public interface IImageTarget { - void notifyImage(ImageData imageData, String plugin, String path); + /** + * Notifies the target that an image was found. + * + * @param element detected image data + */ + void notifyImage(ImageElement element); + + /** + * Query the target whether additional images are needed + * + * @return <code>true</code> when more images should be fetched + */ + boolean needsMore(); } diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/ImageBrowserView.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/ImageBrowserView.java index 3522daf356..07d2c7d42b 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/ImageBrowserView.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/ImageBrowserView.java @@ -13,9 +13,6 @@ package org.eclipse.pde.internal.ui.views.imagebrowser; import java.util.*; import java.util.List; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.viewers.*; import org.eclipse.osgi.util.NLS; import org.eclipse.pde.internal.ui.PDEUIMessages; @@ -26,7 +23,8 @@ import org.eclipse.pde.internal.ui.views.imagebrowser.repositories.*; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.*; -import org.eclipse.swt.graphics.*; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.eclipse.ui.ISourceProvider; @@ -40,11 +38,9 @@ import org.eclipse.ui.services.ISourceProviderService; */ public class ImageBrowserView extends ViewPart implements IImageTarget { - private ScanJob mScanJob = null; private final UpdateUI mUIJob = new UpdateUI(); private final List<IFilter<ImageElement>> mFilters = new ArrayList<IFilter<ImageElement>>(); - private final ElementsFilter mVisitedElementsFilter; private final IFilter<ImageElement> disabledIcons; private final IFilter<ImageElement> enabledIcons; private final IFilter<ImageElement> wizard; @@ -82,8 +78,6 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { wizard = new AndFilter<ImageElement>(new IFilter[] {wizardSize, wizardName}); mFilters.add(enabledIcons); - mVisitedElementsFilter = new ElementsFilter(); - mFilters.add(new NotFilter<ImageElement>(mVisitedElementsFilter)); } /* (non-Javadoc) @@ -107,15 +101,14 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { sourceCombo.setContentProvider(new ArrayContentProvider()); sourceCombo.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { - mVisitedElementsFilter.clear(); scanImages(); } }); ArrayList<Object> sourceComboInput = new ArrayList<Object>(); - sourceComboInput.add(new TargetPlatformRepository(true)); - sourceComboInput.add(new TargetPlatformRepository(false)); - sourceComboInput.add(new WorkspaceRepository()); + sourceComboInput.add(new TargetPlatformRepository(this, true)); + sourceComboInput.add(new TargetPlatformRepository(this, false)); + sourceComboInput.add(new WorkspaceRepository(this)); sourceCombo.setInput(sourceComboInput); SWTFactory.createHorizontalSpacer(sourceComp, 3); @@ -140,8 +133,6 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { case 3 : default : } - mFilters.add(new NotFilter<ImageElement>(mVisitedElementsFilter)); - mVisitedElementsFilter.clear(); scanImages(); } }); @@ -160,8 +151,6 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { nextButton = SWTFactory.createPushButton(pageComp, PDEUIMessages.ImageBrowserView_ShowMore, null); nextButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { - Collection<ImageElement> elements = getImageElements(scrolledComposite); - mVisitedElementsFilter.addAll(elements); scanImages(); } }); @@ -215,19 +204,16 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { } } - public void notifyImage(final ImageData imageData, final String plugin, final String path) { - final ImageElement element = new ImageElement(imageData, plugin, path); - + public void notifyImage(final ImageElement element) { for (final IFilter<ImageElement> filter : mFilters) { if (!filter.accept(element)) return; } - if (mImageCounter-- > 0) - mUIJob.addImage(element); + mUIJob.addImage(element); + mImageCounter--; - else { - mScanJob.cancel(); + if (mImageCounter <= 0) { Display.getDefault().asyncExec(new Runnable() { public void run() { @@ -237,10 +223,12 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { } } + public boolean needsMore() { + return mImageCounter > 0; + } + private void scanImages() { nextButton.setEnabled(false); - if (mScanJob != null) - mScanJob.cancel(); // reset UI components mUIJob.reset(); @@ -250,24 +238,21 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { lblHeight.setText(""); //$NON-NLS-1$ txtReference.setText(""); //$NON-NLS-1$ - // dispose old images - for (Image image : displayedImages) { - image.dispose(); - } - displayedImages.clear(); - + // first dispose controls for (final Control control : imageComposite.getChildren()) { control.dispose(); } + // then dispose images used in controls + disposeImages(); + // initialize scan job if (!sourceCombo.getSelection().isEmpty()) { // set maximum image counter mImageCounter = spinMaxImages.getSelection(); final AbstractRepository repository = (AbstractRepository) ((IStructuredSelection) sourceCombo.getSelection()).getFirstElement(); - mScanJob = new ScanJob(repository); - mScanJob.schedule(); + repository.schedule(); } } @@ -276,43 +261,16 @@ public class ImageBrowserView extends ViewPart implements IImageTarget { */ @Override public void dispose() { + disposeImages(); + } + + private void disposeImages() { for (Image image : displayedImages) { image.dispose(); } displayedImages.clear(); } - private static Collection<ImageElement> getImageElements(final Composite parent) { - HashSet<ImageElement> result = new HashSet<ImageElement>(); - - for (final Control control : parent.getChildren()) { - if (control instanceof Composite) - result.addAll(getImageElements((Composite) control)); - - else { - Object data = control.getData(); - if (data instanceof ImageElement) - result.add((ImageElement) data); - } - } - - return result; - } - - private class ScanJob extends Job { - - private final AbstractRepository mImageRepository; - - public ScanJob(final AbstractRepository imageRepository) { - super(PDEUIMessages.ImageBrowserView_ScanningForImagesJob); - mImageRepository = imageRepository; - } - - protected IStatus run(final IProgressMonitor monitor) { - return mImageRepository.searchImages(ImageBrowserView.this, monitor); - } - } - private class UpdateUI implements Runnable, SelectionListener { Collection<ImageElement> mElements = new LinkedList<ImageElement>(); diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/AbstractRepository.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/AbstractRepository.java index 57049d37b4..916f26c857 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/AbstractRepository.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/AbstractRepository.java @@ -12,25 +12,68 @@ package org.eclipse.pde.internal.ui.views.imagebrowser.repositories; import java.io.*; -import java.util.Enumeration; +import java.util.*; import java.util.zip.*; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.pde.internal.ui.PDEPlugin; +import org.eclipse.pde.internal.ui.PDEUIMessages; import org.eclipse.pde.internal.ui.views.imagebrowser.IImageTarget; +import org.eclipse.pde.internal.ui.views.imagebrowser.ImageElement; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.ImageData; -public abstract class AbstractRepository { +public abstract class AbstractRepository extends Job { + + private List<ImageElement> mElementsCache = new LinkedList<ImageElement>(); + + private int mCacheIndex = 0; + + private IImageTarget mTarget; + + public AbstractRepository(IImageTarget target) { + super(PDEUIMessages.AbstractRepository_ScanForUI); + + mTarget = target; + } private static final String[] KNOWN_EXTENSIONS = new String[] {".gif", ".png"}; //$NON-NLS-1$ //$NON-NLS-2$ - public abstract IStatus searchImages(IImageTarget target, IProgressMonitor monitor); + @Override + protected synchronized IStatus run(IProgressMonitor monitor) { + while ((mTarget.needsMore()) && (!monitor.isCanceled())) { + if (mElementsCache.size() <= mCacheIndex) { + // need more images in cache - protected ImageData createImageData(final File file) throws FileNotFoundException { - return new ImageData(new BufferedInputStream(new FileInputStream(file))); + if (!populateCache(monitor)) { + // could not populate cache, giving up + return Status.OK_STATUS; + } + } else { + // return 1 image from cache + mTarget.notifyImage(mElementsCache.get(mCacheIndex++)); + } + } + + return Status.OK_STATUS; + } + + public synchronized void setCacheIndex(int index) { + mCacheIndex = Math.min(index, mElementsCache.size()); + } + + public synchronized int getCacheIndex() { + return mCacheIndex; + } + + public synchronized void clearCache() { + mElementsCache = null; + mCacheIndex = 0; } + protected abstract boolean populateCache(IProgressMonitor monitor); + protected ImageData createImageData(final IFile file) throws CoreException { return new ImageData(new BufferedInputStream(file.getContents())); } @@ -55,7 +98,7 @@ public abstract class AbstractRepository { return file.getName().toLowerCase().endsWith(".jar"); //$NON-NLS-1$ } - protected void searchJarFile(final File jarFile, final IImageTarget target, final IProgressMonitor monitor) { + protected void searchJarFile(final File jarFile, final IProgressMonitor monitor) { try { ZipFile zipFile = new ZipFile(jarFile); Enumeration<? extends ZipEntry> entries = zipFile.entries(); @@ -64,7 +107,7 @@ public abstract class AbstractRepository { if (isImageName(entry.getName().toLowerCase())) { try { ImageData imageData = new ImageData(zipFile.getInputStream(entry)); - target.notifyImage(imageData, jarFile.getName(), entry.getName()); + addImageElement(new ImageElement(imageData, jarFile.getName(), entry.getName())); } catch (IOException e) { PDEPlugin.log(e); } catch (SWTException e) { @@ -79,4 +122,60 @@ public abstract class AbstractRepository { PDEPlugin.log(e); } } + + protected void searchDirectory(File directory, final IProgressMonitor monitor) { + File manifest = new File(directory, "META-INF/MANIFEST.MF"); //$NON-NLS-1$ + if (manifest.exists()) { + try { + String pluginName = getPluginName(new FileInputStream(manifest)); + int directoryPathLength = directory.getAbsolutePath().length(); + + Collection<File> locations = new HashSet<File>(); + locations.add(directory); + do { + File next = locations.iterator().next(); + locations.remove(next); + + for (File resource : next.listFiles()) { + if (monitor.isCanceled()) + return; + + if (resource.isDirectory()) { + locations.add(resource); + + } else { + try { + if (isImage(resource)) { + addImageElement(new ImageElement(createImageData((IFile) resource), pluginName, resource.getAbsolutePath().substring(directoryPathLength))); + } + + } catch (Exception e) { + // could not create image for location + } + } + } + + } while ((!locations.isEmpty()) && (!monitor.isCanceled())); + } catch (IOException e) { + // could not read manifest + PDEPlugin.log(e); + } + } + } + + protected String getPluginName(final InputStream manifest) throws IOException { + Properties properties = new Properties(); + BufferedInputStream stream = new BufferedInputStream(manifest); + properties.load(stream); + stream.close(); + String property = properties.getProperty("Bundle-SymbolicName"); //$NON-NLS-1$ + if (property.contains(";")) //$NON-NLS-1$ + return property.substring(0, property.indexOf(';')).trim(); + + return property.trim(); + } + + protected void addImageElement(ImageElement element) { + mElementsCache.add(element); + } } diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/TargetPlatformRepository.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/TargetPlatformRepository.java index 2de27673aa..1c93d0359c 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/TargetPlatformRepository.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/TargetPlatformRepository.java @@ -11,19 +11,21 @@ package org.eclipse.pde.internal.ui.views.imagebrowser.repositories; -import org.eclipse.pde.internal.ui.PDEUIMessages; - import java.io.File; import java.net.URI; -import org.eclipse.core.runtime.*; +import java.util.*; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.osgi.util.NLS; import org.eclipse.pde.core.target.*; import org.eclipse.pde.internal.ui.PDEPlugin; +import org.eclipse.pde.internal.ui.PDEUIMessages; import org.eclipse.pde.internal.ui.views.imagebrowser.IImageTarget; import org.eclipse.ui.PlatformUI; public class TargetPlatformRepository extends AbstractRepository { + private List<TargetBundle> fBundles = null; private boolean fUseCurrent; /** @@ -31,42 +33,67 @@ public class TargetPlatformRepository extends AbstractRepository { * the current target platform set on the preference page. If <code>false</code> * a default target definition (the running application) will be used. * + * @param target whom to notify upon found images * @param useCurrent whether to use the current target platform or the default target (running application) */ - public TargetPlatformRepository(boolean useCurrent) { + public TargetPlatformRepository(IImageTarget target, boolean useCurrent) { + super(target); + fUseCurrent = useCurrent; } - public IStatus searchImages(final IImageTarget target, final IProgressMonitor monitor) { + protected boolean populateCache(final IProgressMonitor monitor) { + if (fBundles == null) + initialize(monitor); + + if (!fBundles.isEmpty()) { + TargetBundle bundle = fBundles.remove(fBundles.size() - 1); + URI location = bundle.getBundleInfo().getLocation(); + File file = new File(location); + if (isJar(file)) { + searchJarFile(file, monitor); + + } else if (file.isDirectory()) { + searchDirectory(file, monitor); + } + + return true; + } + + return false; + } + + private void initialize(final IProgressMonitor monitor) { + try { ITargetPlatformService service = (ITargetPlatformService) PlatformUI.getWorkbench().getService(ITargetPlatformService.class); if (service != null) { - ITargetDefinition definition = null; + ITargetDefinition fDefinition = null; if (fUseCurrent) { ITargetHandle workspaceTargetHandle = service.getWorkspaceTargetHandle(); if (workspaceTargetHandle != null) { - definition = workspaceTargetHandle.getTargetDefinition(); + fDefinition = workspaceTargetHandle.getTargetDefinition(); } } else { - definition = service.newDefaultTarget(); + fDefinition = service.newDefaultTarget(); } - if (definition != null) { + if (fDefinition != null) { + + if (!fDefinition.isResolved()) + fDefinition.resolve(monitor); - if (!definition.isResolved()) - definition.resolve(monitor); + TargetBundle[] allBundles = fDefinition.getAllBundles(); - TargetBundle[] allBundles = definition.getAllBundles(); + // populate bundles to visit if (allBundles != null) { - for (TargetBundle bundle : allBundles) { - URI location = bundle.getBundleInfo().getLocation(); - File file = new File(location); - if (isJar(file)) - searchJarFile(file, target, monitor); - } + fBundles = new ArrayList<TargetBundle>(Arrays.asList(allBundles)); + } else { + fBundles = Collections.emptyList(); } } + } else { PDEPlugin.logErrorMessage(PDEUIMessages.TargetPlatformRepository_CouldNotFindTargetPlatformService); } @@ -74,8 +101,6 @@ public class TargetPlatformRepository extends AbstractRepository { } catch (CoreException e) { PDEPlugin.log(e); } - - return Status.OK_STATUS; } public String toString() { diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/WorkspaceRepository.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/WorkspaceRepository.java index 1ac3f66e91..199fe67b14 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/WorkspaceRepository.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/imagebrowser/repositories/WorkspaceRepository.java @@ -11,19 +11,31 @@ package org.eclipse.pde.internal.ui.views.imagebrowser.repositories; -import java.io.*; +import java.io.IOException; import java.util.*; import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.pde.internal.ui.PDEPlugin; import org.eclipse.pde.internal.ui.views.imagebrowser.IImageTarget; +import org.eclipse.pde.internal.ui.views.imagebrowser.ImageElement; public class WorkspaceRepository extends AbstractRepository { - public WorkspaceRepository() { + private List<IProject> fProjects = null; + + public WorkspaceRepository(IImageTarget target) { + super(target); } - public IStatus searchImages(final IImageTarget target, final IProgressMonitor monitor) { - for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { + @Override + protected boolean populateCache(IProgressMonitor monitor) { + if (fProjects == null) + initialize(monitor); + + if (!fProjects.isEmpty()) { + IProject project = fProjects.get(fProjects.size() - 1); + // look for a manifest IFile manifest = project.getFile("META-INF/MANIFEST.MF"); //$NON-NLS-1$ if (manifest.exists()) { @@ -40,12 +52,12 @@ public class WorkspaceRepository extends AbstractRepository { for (IResource resource : next.members()) { if (monitor.isCanceled()) - return Status.OK_STATUS; + return true; if (resource instanceof IFile) { try { - if (isImageName(resource.getName())) - target.notifyImage(createImageData((IFile) resource), pluginName, resource.getProjectRelativePath().toPortableString()); + if (isImageName(resource.getName().toLowerCase())) + addImageElement(new ImageElement(createImageData((IFile) resource), pluginName, resource.getProjectRelativePath().toPortableString())); } catch (Exception e) { // could not create image for location @@ -56,24 +68,23 @@ public class WorkspaceRepository extends AbstractRepository { } while ((!locations.isEmpty()) && (!monitor.isCanceled())); } catch (CoreException e) { + PDEPlugin.log(e); } catch (IOException e) { + PDEPlugin.log(e); } } + return true; } - return Status.OK_STATUS; + return false; } - private String getPluginName(final InputStream manifest) throws IOException { - Properties properties = new Properties(); - BufferedInputStream stream = new BufferedInputStream(manifest); - properties.load(stream); - stream.close(); - String property = properties.getProperty("Bundle-SymbolicName"); //$NON-NLS-1$ - if (property.contains(";")) //$NON-NLS-1$ - return property.substring(0, property.indexOf(';')).trim(); - - return property.trim(); + private void initialize(IProgressMonitor monitor) { + IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + if (projects != null) + fProjects = new ArrayList<IProject>(Arrays.asList(projects)); + else + fProjects = Collections.emptyList(); } public String toString() { |
