core/com.nokia.carbide.cpp.ui/src/com/nokia/carbide/cpp/internal/ui/images/CachingImageLoader.java
Extract path-manipulation utilities into PathUtils, to correspond with the same classes in EDC.
-- Also, fix oversight where Win32 paths were not properly converted into IPath on Unix (the device was not set).
/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.carbide.cpp.internal.ui.images;
import com.nokia.carbide.cpp.ui.images.*;
import com.nokia.cpp.internal.api.utils.core.PathUtils;
import org.eclipse.core.runtime.*;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
/**
* This is a cache for the image providers and ImageData created for given files.
*
*/
public class CachingImageLoader implements IImageLoader {
private Map<IPath, IImageDataProvider> pathToImageDataProviderMap = new HashMap<IPath, IImageDataProvider>();
private ImageLoader loader = new ImageLoader();
public CachingImageLoader() {
}
/* (non-Javadoc)
* @see com.nokia.carbide.cpp.project.ui.images.IImageLoader#createImageDataProvider(org.eclipse.core.runtime.IPath)
*/
public synchronized IImageDataProvider createImageDataProvider(IPath origPath)
throws CoreException {
if (origPath == null)
return null;
final IPath path = canonicalizePath(origPath);
IImageDataProvider provider = pathToImageDataProviderMap.get(path);
// check for changes before returning anything cached
if (provider != null) {
provider.notifyIfChanged();
}
if (provider == null) {
final IImageDataProvider baseProvider = loader.createImageDataProvider(path);
provider = new BaseImageDataProvider(path.toFile()) {
/** Cache of Pair<IPath, Point> to ImageData */
private Map<Point, WeakReference<ImageData>> imageDataCache = new HashMap<Point, WeakReference<ImageData>>();
public ImageData getImageData(Point size) throws CoreException {
if (notifyIfChanged() || size == null) {
// original size always cached inside provider
return baseProvider.getImageData(size);
}
ImageData data = null;
WeakReference<ImageData> ref = imageDataCache.get(size);
if (ref != null) {
data = ref.get();
}
if (data == null) {
data = baseProvider.getImageData(size);
imageDataCache.put(size, new WeakReference<ImageData>(data));
}
return data;
}
/* (non-Javadoc)
* @see com.nokia.sdt.utils.IDisposable#dispose()
*/
public void dispose() {
super.dispose();
imageDataCache.clear();
baseProvider.dispose();
}
};
pathToImageDataProviderMap.put(path, provider);
provider.addListener(new IImageDataProviderListener() {
public void changed(IImageDataProvider provider) {
unregister(path);
}
});
}
return provider;
}
private void disposeProvider(IImageDataProvider provider, IPath path) {
provider.dispose();
provider = null;
pathToImageDataProviderMap.remove(path);
}
/* (non-Javadoc)
* @see com.nokia.sdt.utils.IDisposable#dispose()
*/
public synchronized void dispose() {
for (IImageDataProvider provider : pathToImageDataProviderMap.values()) {
provider.dispose();
}
pathToImageDataProviderMap.clear();
loader.dispose();
}
/**
* Get the canonical path so we don't load the same image under different
* cases or paths.
* @param path full path
* @return canonical path (full path)
*/
private IPath canonicalizePath(IPath path) {
try {
return PathUtils.createPath(path.toFile().getCanonicalPath());
} catch (IOException e) {
return path;
}
}
/**
* Unregister a cached image when its underlying resource changes
*/
private synchronized void unregister(IPath path) {
// remove from cache
IImageDataProvider provider = pathToImageDataProviderMap.get(path);
disposeProvider(provider, path);
}
}