diff options
author | Ken Ryall | 2008-03-24 21:21:02 +0000 |
---|---|---|
committer | Ken Ryall | 2008-03-24 21:21:02 +0000 |
commit | 3071e4834e349169773a86177381f2831e494b1d (patch) | |
tree | a0df77d9d498ed24d62d86c01f33c3a7f1a87475 /debug | |
parent | 2e3fbf6c23755e395ff5ba843f9e1b35279ab32e (diff) | |
download | org.eclipse.cdt-3071e4834e349169773a86177381f2831e494b1d.tar.gz org.eclipse.cdt-3071e4834e349169773a86177381f2831e494b1d.tar.xz org.eclipse.cdt-3071e4834e349169773a86177381f2831e494b1d.zip |
Bug 182388, Executables view and supporting classes.
Diffstat (limited to 'debug')
32 files changed, 2611 insertions, 9 deletions
diff --git a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF index 62f3ed6be9b..0b9c5f5322e 100644 --- a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF @@ -12,6 +12,7 @@ Export-Package: org.eclipse.cdt.debug.core, org.eclipse.cdt.debug.core.cdi.event, org.eclipse.cdt.debug.core.cdi.model, org.eclipse.cdt.debug.core.cdi.model.type, + org.eclipse.cdt.debug.core.executables, org.eclipse.cdt.debug.core.model, org.eclipse.cdt.debug.core.sourcelookup, org.eclipse.cdt.debug.internal.core, @@ -21,6 +22,7 @@ Export-Package: org.eclipse.cdt.debug.core, Require-Bundle: org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)", org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)", org.eclipse.cdt.core;bundle-version="[5.0.0,6.0.0)", - org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)" + org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)", + org.eclipse.core.filesystem;bundle-version="1.2.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java new file mode 100644 index 00000000000..688d9101b30 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java @@ -0,0 +1,309 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.ISymbolReader; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.core.model.BinaryParserConfig; +import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit; +import org.eclipse.cdt.internal.core.model.TranslationUnit; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; + +public class Executable extends PlatformObject { + + private IPath path; + private IProject project; + private String name; + private IResource resource; + private Map<ITranslationUnit, String> remappedPaths; + private ArrayList<ITranslationUnit> sourceFiles; + + public IPath getPath() { + return path; + } + + public IProject getProject() { + return project; + } + + public Executable(IPath path, IProject project, IResource resource) { + this.path = path; + this.project = project; + this.name = new File(path.toOSString()).getName(); + this.resource = resource; + remappedPaths = new HashMap<ITranslationUnit, String>(); + sourceFiles = new ArrayList<ITranslationUnit>(); + } + + public IResource getResource() { + return resource; + } + + @Override + public String toString() { + return path.toString(); + } + + public String getName() { + return name; + } + + @SuppressWarnings("unchecked") + @Override + public Object getAdapter(Class adapter) { + if (adapter.equals(IResource.class)) + if (getResource() != null) + return getResource(); + else + return this.getProject(); + return super.getAdapter(adapter); + } + + static public boolean isExecutableFile(IPath path) { + // ignore directories + if (path.toFile().isDirectory()) { + return false; + } + // Only if file has no extension, has an extension that is an integer + // or is a binary file content type + String ext = path.getFileExtension(); + if (ext != null) { + // shared libraries often have a version number + boolean isNumber = true; + for (int i = 0; i < ext.length(); ++i) + if (!Character.isDigit(ext.charAt(i))) { + isNumber = false; + break; + } + if (!isNumber) { + boolean isBinary = false; + final IContentTypeManager ctm = Platform.getContentTypeManager(); + final IContentType ctbin = ctm.getContentType(CCorePlugin.CONTENT_TYPE_BINARYFILE); + final IContentType[] cts = ctm.findContentTypesFor(path.toFile().getName()); + for (int i = 0; !isBinary && i < cts.length; i++) { + isBinary = cts[i].isKindOf(ctbin); + } + if (!isBinary) { + return false; + } + } + } + return true; + } + + public IBinaryFile createBinaryFile() { + CModelManager factory = CModelManager.getDefault(); + + if (resource != null && resource instanceof IFile) + return factory.createBinaryFile((IFile) resource); + + BinaryParserConfig[] parsers = factory.getBinaryParser(getProject()); + if (parsers.length == 0) { + return null; + } + + if (!isExecutableFile(path)) + return null; + + File f = new File(path.toOSString()); + if (f.length() == 0) { + return null; + } + + int hints = 0; + + for (int i = 0; i < parsers.length; i++) { + IBinaryParser parser = null; + try { + parser = parsers[i].getBinaryParser(); + if (parser.getHintBufferSize() > hints) { + hints = parser.getHintBufferSize(); + } + } catch (CoreException e) { + } + } + byte[] bytes = new byte[hints]; + if (hints > 0) { + InputStream is = null; + try { + is = new FileInputStream(path.toFile()); + int count = 0; + // Make sure we read up to 'hints' bytes if we possibly can + while (count < hints) { + int bytesRead = is.read(bytes, count, hints - count); + if (bytesRead < 0) + break; + count += bytesRead; + } + if (count > 0 && count < bytes.length) { + byte[] array = new byte[count]; + System.arraycopy(bytes, 0, array, 0, count); + bytes = array; + } + } catch (IOException e) { + return null; + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + for (int i = 0; i < parsers.length; i++) { + try { + IBinaryParser parser = parsers[i].getBinaryParser(); + if (parser.isBinary(bytes, path)) { + IBinaryFile binFile = parser.getBinary(bytes, path); + if (binFile != null) { + return binFile; + } + } + } catch (IOException e) { + } catch (CoreException e) { + } + } + return null; + } + + public ITranslationUnit[] getSourceFiles() { + // Try to get the list of source files used to build the binary from the + // symbol information. + + remappedPaths.clear(); + + sourceFiles.clear(); + + CModelManager factory = CModelManager.getDefault(); + IBinaryFile bin = createBinaryFile(); + + if (bin != null) { + ICProject cproject = factory.create(project); + + ISymbolReader symbolreader = (ISymbolReader) bin.getAdapter(ISymbolReader.class); + if (symbolreader != null) { + String[] symReaderSources = symbolreader.getSourceFiles(); + if (symReaderSources != null && symReaderSources.length > 0) { + for (int i = 0; i < symReaderSources.length; i++) { + String filename = symReaderSources[i]; + String orgPath = filename; + + filename = ExecutablesManager.getExecutablesManager().remapSourceFile(filename); + + // Sometimes the path in the symbolics will have a + // different + // case than the actual file system path. Even if the + // file + // system is not case sensitive this will confuse the + // Path + // class. + // So make sure the path is canonical, otherwise + // breakpoints + // won't be resolved, etc.. + // Also check for relative path names and attempt to + // resolve + // them relative to the executable. + + try { + File file = new File(filename); + if (file.exists()) { + filename = file.getCanonicalPath(); + } else if (filename.startsWith(".")) { //$NON-NLS-1$ + file = new File(bin.getPath().removeLastSegments(1).toOSString(), filename); + filename = file.getCanonicalPath(); + } + } catch (IOException e) { // Do nothing. + } + + // See if this source file is already in the project. + // We check this to determine if we should create a + // TranslationUnit or ExternalTranslationUnit + IFile sourceFile = getProject().getFile(filename); + IPath path = new Path(filename); + + IFile wkspFile = null; + if (sourceFile.exists()) + wkspFile = sourceFile; + else { + IFile[] filesInWP = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(path); + + for (int j = 0; j < filesInWP.length; j++) { + if (filesInWP[j].isAccessible()) { + wkspFile = filesInWP[j]; + break; + } + } + } + + // Create a translation unit for this file and add it as + // a child of the binary + String id = CoreModel.getRegistedContentTypeId(sourceFile.getProject(), sourceFile.getName()); + + if (id != null) { // Don't add files we can't get an + // ID for. + TranslationUnit tu; + if (wkspFile != null) + tu = new TranslationUnit(cproject, wkspFile, id); + else + tu = new ExternalTranslationUnit(cproject, URIUtil.toURI(path), id); + + sourceFiles.add(tu); + + if (!orgPath.equals(filename)) { + remappedPaths.put(tu, orgPath); + } + } + } + } + } + + } + + return sourceFiles.toArray(new TranslationUnit[sourceFiles.size()]); + } + + public String getOriginalLocation(ITranslationUnit tu) { + String orgLocation = remappedPaths.get(tu); + if (orgLocation == null) + orgLocation = tu.getPath().toOSString(); + return orgLocation; + } + +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesChangeEvent.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesChangeEvent.java new file mode 100644 index 00000000000..60bd74ce9d5 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesChangeEvent.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +import java.util.ArrayList; + +import org.eclipse.core.runtime.PlatformObject; + +public class ExecutablesChangeEvent extends PlatformObject implements IExecutablesChangeEvent { + + private Executable[] oldExecutables; + private Executable[] newExecutables; + + public ExecutablesChangeEvent(ArrayList<Executable> oldList, ArrayList<Executable> newList) { + oldExecutables = oldList.toArray(new Executable[oldList.size()]); + newExecutables = newList.toArray(new Executable[newList.size()]); + } + + public Executable[] getCurrentExecutables() { + return newExecutables; + } + + public Executable[] getPreviousExecutables() { + return oldExecutables; + } + +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java new file mode 100644 index 00000000000..c50e3f5b14a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; + +/** + * The Executables Manager maintains a collection of executables built by all of + * the projects in the workspace. Executables are contributed by instances of + * IExecutablesProvider. + * + * @author Ken Ryall + * + */ +public class ExecutablesManager extends PlatformObject { + + private ArrayList<Executable> executables = new ArrayList<Executable>(); + private List<IExecutablesChangeListener> changeListeners = Collections.synchronizedList(new ArrayList<IExecutablesChangeListener>()); + private List<ISourceFileRemapping> sourceFileRemappings = Collections.synchronizedList(new ArrayList<ISourceFileRemapping>()); + private List<IExecutableProvider> executableProviders = Collections.synchronizedList(new ArrayList<IExecutableProvider>()); + private List<IExecutableImporter> executableImporters = Collections.synchronizedList(new ArrayList<IExecutableImporter>()); + private boolean refreshNeeded = true; + + private Job refreshJob = new Job("Get Executables") { + + @Override + public IStatus run(IProgressMonitor monitor) { + refreshExecutables(monitor); + return Status.OK_STATUS; + } + }; + + private static ExecutablesManager executablesManager = null; + + public static ExecutablesManager getExecutablesManager() { + if (executablesManager == null) + executablesManager = new ExecutablesManager(); + return executablesManager; + } + + public ExecutablesManager() { + addSourceFileRemapping(new StandardSourceFileRemapping()); + addExecutableImporter(new StandardExecutableImporter()); + addExecutablesProvider(new StandardExecutableProvider()); + } + + public void addExecutablesChangeListener(IExecutablesChangeListener listener) { + changeListeners.add(listener); + } + + public void removeExecutablesChangeListener(IExecutablesChangeListener listener) { + changeListeners.remove(listener); + } + + public void addSourceFileRemapping(ISourceFileRemapping remapping) { + sourceFileRemappings.add(remapping); + } + + public void removeSourceFileRemapping(ISourceFileRemapping remapping) { + sourceFileRemappings.remove(remapping); + } + + public void addExecutableImporter(IExecutableImporter importer) { + executableImporters.add(importer); + } + + public void removeExecutableImporter(IExecutableImporter importer) { + executableImporters.remove(importer); + } + + public void addExecutablesProvider(IExecutableProvider provider) { + executableProviders.add(provider); + } + + public void removeExecutablesProvider(IExecutableProvider provider) { + executableProviders.remove(provider); + } + + public IStatus refreshExecutables(IProgressMonitor monitor) { + ArrayList<Executable> oldList = executables; + executables = new ArrayList<Executable>(); + synchronized (executableProviders) { + monitor.beginTask("Refresh Executables", executableProviders.size()); + for (IExecutableProvider provider : executableProviders) { + executables.addAll(provider.getExecutables(new SubProgressMonitor(monitor, 1))); + } + monitor.done(); + } + refreshNeeded = false; + + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesChanged(new ExecutablesChangeEvent(oldList, executables) { + }); + } + } + return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + } + + public Executable[] getExecutables() { + if (refreshNeeded) { + try { + refreshJob.schedule(); + refreshJob.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return executables.toArray(new Executable[executables.size()]); + } + + public String remapSourceFile(String filePath) { + synchronized (sourceFileRemappings) { + for (ISourceFileRemapping remapping : sourceFileRemappings) { + String remappedPath = remapping.remapSourceFile(filePath); + if (!remappedPath.equals(filePath)) + return remappedPath; + } + } + return filePath; + } + + public void importExecutables(String[] fileNames, IProgressMonitor monitor) { + synchronized (executableImporters) { + monitor.beginTask("Import Executables", executableImporters.size()); + for (IExecutableImporter importer : executableImporters) { + importer.importExecutables(fileNames, new SubProgressMonitor(monitor, 1)); + } + monitor.done(); + } + } + + public ISourceFileRemapping[] getSourceFileRemappings() { + return sourceFileRemappings.toArray(new ISourceFileRemapping[sourceFileRemappings.size()]); + } + + public IExecutableProvider[] getExecutableProviders() { + return executableProviders.toArray(new IExecutableProvider[executableProviders.size()]); + } + + public IExecutableImporter[] getExecutableImporters() { + return executableImporters.toArray(new IExecutableImporter[executableImporters.size()]); + } + + public void scheduleRefresh(IExecutableProvider provider, long delay) { + refreshNeeded = true; + refreshJob.schedule(delay); + } + + public boolean refreshNeeded() { + return refreshNeeded; + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java new file mode 100644 index 00000000000..8fe0ef324ce --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +import org.eclipse.core.runtime.IProgressMonitor; + +public interface IExecutableImporter { + + public abstract void importExecutables(String[] fileNames, IProgressMonitor monitor); + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java new file mode 100644 index 00000000000..6c4ede78d09 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +import java.util.Collection; + +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * IExecutablesProvider supplies a list of executables to the Executables + * Manager. + * + * @author Ken Ryall + * + */ +public interface IExecutableProvider { + + Collection<Executable> getExecutables(IProgressMonitor monitor); + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java new file mode 100644 index 00000000000..3c559eadae4 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +public interface IExecutablesChangeEvent { + + public Executable[] getCurrentExecutables(); + + public Executable[] getPreviousExecutables(); +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java new file mode 100644 index 00000000000..bfa0677655f --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +import java.util.EventListener; + +public interface IExecutablesChangeListener extends EventListener { + + public void executablesChanged(IExecutablesChangeEvent event); + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ISourceFileRemapping.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ISourceFileRemapping.java new file mode 100644 index 00000000000..85948e3b61a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ISourceFileRemapping.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +/** + * ISourceFileRemapping is used by the Executables Manager when finding missing + * source files. + * + * @author Ken Ryall + * + */ +public interface ISourceFileRemapping { + + String remapSourceFile(String filePath); + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableImporter.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableImporter.java new file mode 100644 index 00000000000..3d9a20729d0 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableImporter.java @@ -0,0 +1,210 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.debug.core.CDebugCorePlugin; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; + +public class StandardExecutableImporter implements IExecutableImporter { + + public static final String DEBUG_PROJECT_ID = "org.eclipse.cdt.debug"; //$NON-NLS-1$ + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.debug.core.executables.IExecutableImporter#importExecutables(java.lang.String[], + * org.eclipse.core.runtime.IProgressMonitor) + */ + public void importExecutables(String[] fileNames, IProgressMonitor monitor) { + monitor.beginTask("Import Executables", fileNames.length); + + IProject exeProject = null; + boolean checkProject = false; + // Weed out existing ones + for (String path : fileNames) { + + try { + path = new File(path).getCanonicalPath(); + } catch (IOException e1) { + } + if (!executableExists(path)) { + if (!checkProject) { + // See if the default project exists + String defaultProjectName = "Executables"; + ICProject cProject = CoreModel.getDefault().getCModel().getCProject(defaultProjectName); + if (cProject.exists()) { + exeProject = cProject.getProject(); + } else { + final String[] ignoreList = { ".project", //$NON-NLS-1$ + ".cdtproject", //$NON-NLS-1$ + ".cproject", //$NON-NLS-1$ + ".cdtbuild", //$NON-NLS-1$ + ".settings", //$NON-NLS-1$ + }; + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProject newProjectHandle = workspace.getRoot().getProject(defaultProjectName); + + IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName()); + description.setLocation(null); + IFileStore store; + try { + store = EFS.getStore(workspace.getRoot().getLocationURI()); + store = store.getChild(newProjectHandle.getName()); + for (String deleteName : ignoreList) { + IFileStore projFile = store.getChild(deleteName); + projFile.delete(EFS.NONE, monitor); + } + exeProject = CCorePlugin.getDefault().createCProject(description, newProjectHandle, null, DEBUG_PROJECT_ID); + } catch (OperationCanceledException e) { + e.printStackTrace(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + checkProject = true; + } + + importExecutable(exeProject, path); + } + monitor.worked(1); + } + monitor.done(); + } + + private boolean executableExists(String path) { + Executable[] executables = ExecutablesManager.getExecutablesManager().getExecutables(); + for (Executable executable : executables) { + if (executable.getPath().toOSString().equals(path)) + return true; + } + return false; + } + + private void importExecutable(IProject exeProject, String path) { + + IPath location = Path.fromOSString(path); + String executableName = location.toFile().getName(); + IFile exeFile = exeProject.getProject().getFile(executableName); + if (!exeFile.exists() && validateBinaryParsers(exeProject, new File(path))) { + try { + exeFile.createLink(location, 0, null); + } catch (Exception e) { + } + } + + } + + private boolean isExtensionVisible(IExtension ext) { + IConfigurationElement[] elements = ext.getConfigurationElements(); + for (int i = 0; i < elements.length; i++) { + IConfigurationElement[] children = elements[i].getChildren("filter"); //$NON-NLS-1$ + for (int j = 0; j < children.length; j++) { + String name = children[j].getAttribute("name"); //$NON-NLS-1$ + if (name != null && name.equals("visibility")) { //$NON-NLS-1$ + String value = children[j].getAttribute("value"); //$NON-NLS-1$ + if (value != null && value.equals("private")) { //$NON-NLS-1$ + return false; + } + } + } + return true; + } + return false; // invalid extension definition (must have at least + // cextension elements) + } + + private IBinaryParser instantiateBinaryParser(IExtension ext) { + IBinaryParser parser = null; + IConfigurationElement[] elements = ext.getConfigurationElements(); + for (int i = 0; i < elements.length; i++) { + IConfigurationElement[] children = elements[i].getChildren("run"); //$NON-NLS-1$ + for (int j = 0; j < children.length; j++) { + try { + parser = (IBinaryParser) children[j].createExecutableExtension("class"); + } catch (CoreException e) { + CDebugCorePlugin.log(e); + } + } + } + return parser; + } + + private boolean validateBinaryParsers(IProject exeProject, File file) { + IExtension[] binaryParserExtensions; + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.BINARY_PARSER_SIMPLE_ID); + if (point != null) { + IExtension[] exts = point.getExtensions(); + ArrayList<IExtension> extensionsInUse = new ArrayList<IExtension>(); + for (int i = 0; i < exts.length; i++) { + if (isExtensionVisible(exts[i])) { + extensionsInUse.add(exts[i]); + } + } + binaryParserExtensions = extensionsInUse.toArray(new IExtension[extensionsInUse.size()]); + + for (int i = 0; i < binaryParserExtensions.length; i++) { + IBinaryParser parser = instantiateBinaryParser(binaryParserExtensions[i]); + if (isBinary(file, parser)) { + String parserID = binaryParserExtensions[i].getUniqueIdentifier(); + // Make sure the project has this parser + ICProjectDescription pd = CCorePlugin.getDefault().getProjectDescription(exeProject); + try { + pd.getDefaultSettingConfiguration().create(CCorePlugin.BINARY_PARSER_UNIQ_ID, parserID); + CCorePlugin.getDefault().setProjectDescription(exeProject, pd, true, new NullProgressMonitor()); + } catch (CoreException e) { + } + return true; + } + } + } + + return false; + } + + private boolean isBinary(File file, IBinaryParser parser) { + if (parser != null) { + try { + IBinaryParser.IBinaryFile bin = parser.getBinary(new Path(file.getAbsolutePath())); + return bin != null && (bin.getType() == IBinaryParser.IBinaryFile.EXECUTABLE || bin.getType() == IBinaryParser.IBinaryFile.SHARED); + } catch (IOException e) { + return false; + } + } else + return false; + } + +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java new file mode 100644 index 00000000000..cdb81086350 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; +import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +public class StandardExecutableProvider implements IResourceChangeListener, ICProjectDescriptionListener, IExecutableProvider { + + private ArrayList<Executable> executables = new ArrayList<Executable>(); + + public StandardExecutableProvider() { + ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); + CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, + CProjectDescriptionEvent.DATA_APPLIED | CProjectDescriptionEvent.LOADDED); + } + + public void resourceChanged(IResourceChangeEvent event) { + + // refresh when projects are opened or closed. note that deleted + // projects are handled later + // in this method. new projects are handled in handleEvent. + // resource changed events always start at the workspace root, so + // projects + // are the next level down + IResourceDelta[] projects = event.getDelta().getAffectedChildren(); + for (IResourceDelta projectDelta : projects) { + if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { + if (projectDelta.getKind() == IResourceDelta.CHANGED) { + // project was opened or closed + ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); + return; + } + } + } + + try { + final StandardExecutableProvider provider = this; + event.getDelta().accept(new IResourceDeltaVisitor() { + + public boolean visit(IResourceDelta delta) throws CoreException { + if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) { + IResource deltaResource = delta.getResource(); + if (deltaResource != null) { + boolean refresh = false; + if (delta.getKind() == IResourceDelta.REMOVED && deltaResource instanceof IProject) { + // project deleted + refresh = true; + } else { + // see if a binary has been added/removed + IPath resourcePath = delta.getResource().getLocation(); + if (resourcePath != null && Executable.isExecutableFile(resourcePath)) { + refresh = true; + } + } + if (refresh) { + ExecutablesManager.getExecutablesManager().scheduleRefresh(provider, 0); + return false; + } + } + } + return true; + } + }); + } catch (CoreException e) { + } + } + + public void handleEvent(CProjectDescriptionEvent event) { + // this handles the cases where the active build configuration changes, + // and when new + // projects are created. + boolean refresh = false; + + int eventType = event.getEventType(); + + if (eventType == CProjectDescriptionEvent.DATA_APPLIED) { + // see if the active build config has changed + ICProjectDescription newDesc = event.getNewCProjectDescription(); + ICProjectDescription oldDesc = event.getOldCProjectDescription(); + if (oldDesc != null && newDesc != null) { + String newConfigName = newDesc.getActiveConfiguration().getName(); + String oldConfigName = oldDesc.getActiveConfiguration().getName(); + refresh = (!newConfigName.equals(oldConfigName)); + } else if (newDesc != null && oldDesc == null) { + // project just created + refresh = true; + } + } + + if (refresh) { + ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); + } + } + + public Collection<Executable> getExecutables(IProgressMonitor monitor) { + executables.clear(); + + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IProject[] projects = root.getProjects(); + + monitor.beginTask("Checking C/C++ Projects", projects.length); + + for (IProject project : projects) { + + if (monitor.isCanceled()) + break; + + try { + if (CoreModel.hasCNature(project)) { + CModelManager manager = CModelManager.getDefault(); + ICProject cproject = manager.create(project); + try { + IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); + for (IBinary binary : binaries) { + if (binary.isExecutable() || binary.isSharedLib()) { + IPath exePath = binary.getResource().getLocation(); + if (exePath == null) + exePath = binary.getPath(); + Executable exe = new Executable(exePath, project, binary.getResource()); + executables.add(exe); + } + } + } catch (CModelException e) { + } + } + } catch (Exception e) { + e.printStackTrace(); + } + monitor.worked(1); + } + monitor.done(); + + return executables; + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardSourceFileRemapping.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardSourceFileRemapping.java new file mode 100644 index 00000000000..001dd717dde --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardSourceFileRemapping.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +import org.eclipse.cdt.debug.core.CDebugCorePlugin; +import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator; +import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.model.ISourceLocator; +import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage; + +public class StandardSourceFileRemapping implements ISourceFileRemapping { + + public String remapSourceFile(String filePath) { + + try { + Object[] foundElements = CDebugCorePlugin.getDefault().getCommonSourceLookupDirector().findSourceElements(filePath); + + if (foundElements.length == 0) { + Object foundElement = null; + ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager(); + ILaunch[] launches = launchMgr.getLaunches(); + for (ILaunch launch : launches) { + ISourceLocator locator = launch.getSourceLocator(); + if (locator instanceof ICSourceLocator || locator instanceof CSourceLookupDirector) { + if (locator instanceof ICSourceLocator) + foundElement = ((ICSourceLocator) locator).findSourceElement(filePath); + else + foundElement = ((CSourceLookupDirector) locator).getSourceElement(filePath); + } + } + if (foundElement != null) + foundElements = new Object[] { foundElement }; + } + + if (foundElements.length == 1 && foundElements[0] instanceof LocalFileStorage) { + LocalFileStorage newLocation = (LocalFileStorage) foundElements[0]; + filePath = newLocation.getFullPath().toOSString(); + } + + } catch (CoreException e) { + } + return filePath; + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/sourcelookup/AbsolutePathSourceContainer.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/sourcelookup/AbsolutePathSourceContainer.java index 4e99c16951f..38dead7aa3a 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/sourcelookup/AbsolutePathSourceContainer.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/sourcelookup/AbsolutePathSourceContainer.java @@ -24,7 +24,9 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.sourcelookup.ISourceContainerType; +import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.debug.core.sourcelookup.containers.AbstractSourceContainer; import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage; @@ -48,14 +50,22 @@ public class AbsolutePathSourceContainer extends AbstractSourceContainer { return wfiles; // The file is not already in the workspace so try to create an external translation unit for it. - String projectName = getDirector().getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$ - if (projectName != "") { - ICProject project = CoreModel.getDefault().getCModel().getCProject(projectName); - if (project != null) + ISourceLookupDirector director = getDirector(); + if (director != null) + { + ILaunchConfiguration launch = director.getLaunchConfiguration(); + if (launch != null) { - IPath path = Path.fromOSString(file.getCanonicalPath()); - String id = CoreModel.getRegistedContentTypeId(project.getProject(), path.lastSegment()); - return new ExternalTranslationUnit[] { new ExternalTranslationUnit(project, file.toURI(), id) }; + String projectName = getDirector().getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$ + if (projectName != "") { + ICProject project = CoreModel.getDefault().getCModel().getCProject(projectName); + if (project != null) + { + IPath path = Path.fromOSString(file.getCanonicalPath()); + String id = CoreModel.getRegistedContentTypeId(project.getProject(), path.lastSegment()); + return new ExternalTranslationUnit[] { new ExternalTranslationUnit(project, file.toURI(), id) }; + } + } } } } catch (IOException e) { // ignore if getCanonicalPath throws diff --git a/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF index d912ffb4090..87f0bd6ea89 100644 --- a/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF @@ -16,6 +16,7 @@ Export-Package: org.eclipse.cdt.debug.internal.ui.sourcelookup, org.eclipse.cdt.debug.internal.ui.views, org.eclipse.cdt.debug.internal.ui.views.disassembly, + org.eclipse.cdt.debug.internal.ui.views.executables, org.eclipse.cdt.debug.internal.ui.views.modules, org.eclipse.cdt.debug.internal.ui.views.signals, org.eclipse.cdt.debug.ui, diff --git a/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/columns.gif b/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/columns.gif Binary files differnew file mode 100644 index 00000000000..9328079cf9c --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/columns.gif diff --git a/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/import.gif b/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/import.gif Binary files differnew file mode 100644 index 00000000000..d38085ad9c2 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/import.gif diff --git a/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/refresh.gif b/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/refresh.gif Binary files differnew file mode 100644 index 00000000000..6eafa48cfb0 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/dlcl16/refresh.gif diff --git a/debug/org.eclipse.cdt.debug.ui/icons/elcl16/columns.gif b/debug/org.eclipse.cdt.debug.ui/icons/elcl16/columns.gif Binary files differnew file mode 100644 index 00000000000..e5e5263eb46 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/elcl16/columns.gif diff --git a/debug/org.eclipse.cdt.debug.ui/icons/elcl16/import.gif b/debug/org.eclipse.cdt.debug.ui/icons/elcl16/import.gif Binary files differnew file mode 100644 index 00000000000..d38085ad9c2 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/elcl16/import.gif diff --git a/debug/org.eclipse.cdt.debug.ui/icons/elcl16/refresh.gif b/debug/org.eclipse.cdt.debug.ui/icons/elcl16/refresh.gif Binary files differnew file mode 100644 index 00000000000..e3831471a65 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/elcl16/refresh.gif diff --git a/debug/org.eclipse.cdt.debug.ui/icons/obj16/exec_view_obj.gif b/debug/org.eclipse.cdt.debug.ui/icons/obj16/exec_view_obj.gif Binary files differnew file mode 100644 index 00000000000..d5f502a9746 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/icons/obj16/exec_view_obj.gif diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.properties b/debug/org.eclipse.cdt.debug.ui/plugin.properties index dc1a1876dec..62dfebaa642 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.properties +++ b/debug/org.eclipse.cdt.debug.ui/plugin.properties @@ -15,6 +15,7 @@ providerName=Eclipse.org MemoryView.name=Memory ModulesView.name=Modules SignalsView.name=Signals +ExecutablesView.name=Executables CDebuggerPage.name=C Debugger UI Page MemoryPreferencePage.name=Memory View diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.xml b/debug/org.eclipse.cdt.debug.ui/plugin.xml index 5e775e60491..adb67e005f9 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.xml +++ b/debug/org.eclipse.cdt.debug.ui/plugin.xml @@ -17,6 +17,13 @@ <extension point="org.eclipse.ui.views"> <view + name="%ExecutablesView.name" + icon="icons/obj16/exec_view_obj.gif" + category="org.eclipse.debug.ui" + class="org.eclipse.cdt.debug.internal.ui.views.executables.ExecutablesView" + id="org.eclipse.cdt.debug.ui.executablesView"> + </view> + <view name="%SignalsView.name" icon="icons/view16/signals_view.gif" category="org.eclipse.debug.ui" @@ -89,6 +96,14 @@ <viewShortcut id="org.eclipse.ui.views.ProblemView"> </viewShortcut> + <view + id="org.eclipse.cdt.debug.ui.executablesView" + relative="org.eclipse.ui.console.ConsoleView" + relationship="stack"> + </view> + <viewShortcut + id="org.eclipse.cdt.debug.internal.ui.views.executables.ExecutablesView"> + </viewShortcut> <actionSet id="org.eclipse.cdt.debug.ui.debugActionSet"> </actionSet> diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/BaseViewer.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/BaseViewer.java new file mode 100644 index 00000000000..69df1bc481a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/BaseViewer.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TreeColumn; + +/** + * Base viewer used by both the executables viewers and the source files viewer. + */ +abstract class BaseViewer extends TreeViewer { + + // Common columns + protected TreeColumn nameColumn; + protected TreeColumn locationColumn; + protected TreeColumn sizeColumn; + protected TreeColumn modifiedColumn; + protected TreeColumn typeColumn; + + private static final int NUM_COLUMNS = 7; + int column_order[] = new int[NUM_COLUMNS]; + + private ExecutablesView executablesView; + + class ColumnSelectionAdapter extends SelectionAdapter { + + private int selector; + + public ColumnSelectionAdapter(int selector) { + this.selector = selector; + } + + public void widgetSelected(SelectionEvent e) { + column_order[selector] *= -1; + ViewerComparator comparator = getViewerComparator(selector); + setComparator(comparator); + executablesView.getMemento().putInteger(ExecutablesView.P_ORDER_VALUE_SF, column_order[selector]); + executablesView.getMemento().putInteger(ExecutablesView.P_ORDER_TYPE_SF, selector); + setColumnSorting((TreeColumn) e.getSource(), column_order[selector]); + } + + } + + public BaseViewer(ExecutablesView view, Composite parent, int style) { + super(parent, style); + executablesView = view; + } + + public ExecutablesView getExecutablesView() { + return executablesView; + } + + protected void packColumns() { + TreeColumn[] columns = getTree().getColumns(); + for (TreeColumn treeColumn : columns) { + if (treeColumn.getWidth() > 0) { + treeColumn.pack(); + treeColumn.setWidth(treeColumn.getWidth() + ExecutablesView.COLUMN_WIDTH_PADDING); + } + } + } + + protected void setColumnSorting(TreeColumn column, int order) { + getTree().setSortColumn(column); + getTree().setSortDirection(order == ExecutablesView.ASCENDING ? SWT.UP : SWT.DOWN); + } + + abstract protected ViewerComparator getViewerComparator(int sortType); + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java new file mode 100644 index 00000000000..67a28e1c979 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import java.text.DateFormat; +import java.util.Date; + +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.cdt.debug.core.executables.ExecutablesManager; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerCell; + +class ExecutablesContentProvider extends ColumnLabelProvider implements IStructuredContentProvider, ITreeContentProvider { + + private TreeViewer viewer; + + public ExecutablesContentProvider(TreeViewer viewer) { + this.viewer = viewer; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public void dispose() { + } + + public Object[] getElements(final Object inputElement) { + if (inputElement instanceof ExecutablesManager) { + final ExecutablesManager em = (ExecutablesManager) inputElement; + if (em.refreshNeeded()) { + // do this asynchronously. just return an empty array + // immediately, and then refresh the view + // once the list of executables has been calculated. this can + // take a while and we don't want + // to block the UI. + Job refreshJob = new Job("Fetching executables") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + IStatus status = em.refreshExecutables(monitor); + + // Are we in the UIThread? If so spin it until we are + // done + if (viewer.getControl().getDisplay().getThread() == Thread.currentThread()) { + viewer.refresh(inputElement); + } else { + viewer.getControl().getDisplay().asyncExec(new Runnable() { + public void run() { + viewer.refresh(inputElement); + } + }); + } + + monitor.done(); + return status; + } + }; + + refreshJob.schedule(); + + } else { + return em.getExecutables(); + } + } + return new Object[] {}; + } + + public Object getParent(Object element) { + return null; + } + + public boolean hasChildren(Object element) { + return false; + } + + @Override + public void update(ViewerCell cell) { + super.update(cell); + Object element = cell.getElement(); + if (element instanceof Executable) { + Executable exe = (Executable) element; + String cellText = exe.getName(); + if (cell.getColumnIndex() == 1) + cellText = exe.getProject().getName(); + else if (cell.getColumnIndex() == 2) + cellText = exe.getPath().toOSString(); + else if (cell.getColumnIndex() == 3) { + cellText = ""; + IPath path = exe.getPath(); + if (path != null && path.toFile().exists()) { + long fileLength = path.toFile().length(); + cellText = Long.toString(fileLength); + } + cell.setImage(null); + } else if (cell.getColumnIndex() == 4) { + cellText = ""; + IPath path = exe.getPath(); + if (path != null && path.toFile().exists()) { + long modified = path.toFile().lastModified(); + cellText = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date(modified)); + } + cell.setImage(null); + } else if (cell.getColumnIndex() == 5) { + cellText = exe.getPath().getFileExtension().toUpperCase(); + } + cell.setText(cellText); + } + } + + @Override + public String getText(Object element) { + if (element instanceof Executable) { + return ((Executable) element).getName(); + } else + return super.getText(element); + } + + public Object[] getChildren(Object parentElement) { + return new Object[] {}; + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java new file mode 100644 index 00000000000..5382fefa415 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java @@ -0,0 +1,500 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.cdt.debug.core.executables.ExecutablesManager; +import org.eclipse.cdt.debug.ui.CDebugUIPlugin; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Preferences; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.XMLMemento; +import org.eclipse.ui.dialogs.ListSelectionDialog; +import org.eclipse.ui.part.ViewPart; + +/** + * ExecutablesView displays a list of executable files either in the workspace + * or created by projects in the workspace. The list of executables comes from + * the ExecutablesManager. This view has two subviews: one that shows the list + * of executables and another that shows the list of source files in the + * selected executable. + * + */ +public class ExecutablesView extends ViewPart { + + /** + * Settings for the view including the sorted column for the sub views and + * the list of visible columns. + */ + + public static final String P_ORDER_TYPE_EXE = "orderTypeEXE"; //$NON-NLS-1$ + public static final String P_ORDER_VALUE_EXE = "orderValueEXE"; //$NON-NLS-1$ + public static final String P_ORDER_TYPE_SF = "orderTypeSF"; //$NON-NLS-1$ + public static final String P_ORDER_VALUE_SF = "orderValueSF"; //$NON-NLS-1$ + public static final String P_VISIBLE_COLUMNS = "visibleColumns"; //$NON-NLS-1$ + + /** + * Constants for the columns. + */ + + public final static int NAME = 0x0; + public final static int PROJECT = 0x1; + public final static int LOCATION = 0x2; + public final static int ORG_LOCATION = 0x3; + public final static int SIZE = 0x4; + public final static int MODIFIED = 0x5; + public final static int TYPE = 0x6; + + /** + * Constants for the column sort order. + */ + + public static int ASCENDING = 1; + public static int DESCENDING = -1; + + /** + * Display constants and icons. + */ + + public final static String ICONS_PATH = "icons/"; //$NON-NLS-1$ + public static final String EXECUTABLES_VIEW_CONTEXT = "org.eclipse.cdt.debug.ui.executables_View_context"; //$NON-NLS-1$; + private static final String PATH_LCL = ICONS_PATH + "elcl16/"; //$NON-NLS-1$ + private static final String PATH_LCL_DISABLED = ICONS_PATH + "dlcl16/"; //$NON-NLS-1$ + public static final ImageDescriptor DESC_REFRESH = create(PATH_LCL, "refresh.gif"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_REFRESH_DISABLED = create(PATH_LCL_DISABLED, "refresh.gif"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_IMPORT = create(PATH_LCL, "import.gif"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_IMPORT_DISABLED = create(PATH_LCL_DISABLED, "import.gif"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_COLUMNS = create(PATH_LCL, "columns.gif"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_COLUMNS_DISABLED = create(PATH_LCL_DISABLED, "columns.gif"); //$NON-NLS-1$ + public static final int COLUMN_WIDTH_PADDING = 24; + + private static ImageDescriptor create(String prefix, String name) { + return ImageDescriptor.createFromURL(makeIconURL(prefix, name)); + } + + private static URL makeIconURL(String prefix, String name) { + String path = "$nl$/" + prefix + name; //$NON-NLS-1$ + return FileLocator.find(CDebugUIPlugin.getDefault().getBundle(), new Path(path), null); + } + + /** + * Complete list of column names for both sub views. These are not display + * names and should not be localized. Display names are set when the columns + * are created in the sub views. + */ + private String[] columnNames = { "Executable Name", "Executable Project", "Executable Location", "Executable Size", "Executable Date", + "Executable Type", "Source File Name", "Source File Location", "Source File Original Location", "Source File Size", "Source File Date", + "Source File Type" }; + + /** + * Not all the columns are visible by default. Here are the ones that are. + */ + private String defaultVisibleColumns = "Executable Name,Executable Project,Executable Location,Source File Name,Source File Location"; + private TreeColumn[] allColumns = new TreeColumn[columnNames.length]; + + /** + * Configures the list of columns show in the view. + */ + public class ConfigureColumnsAction extends Action { + + public static final String CONFIGURE_COLUMNS_DIALOG = "org.eclipse.cdt.debug.ui.configure_columns_dialog_context"; //$NON-NLS-1$; + public static final String CONFIGURE_COLUMNS_ACTION = "org.eclipse.cdt.debug.ui.configure_columns_action_context"; //$NON-NLS-1$; + + class ColumnContentProvider implements IStructuredContentProvider { + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return columnNames; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, + * java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + class ColumnLabelProvider extends LabelProvider { + + public String getText(Object element) { + return (String) element; + } + + } + + public ConfigureColumnsAction() { + setText("Configure Columns"); + setId(CDebugUIPlugin.getUniqueIdentifier() + ".ConfigureColumnsAction"); //$NON-NLS-1$ + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, CONFIGURE_COLUMNS_ACTION); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + ListSelectionDialog dialog = new ListSelectionDialog(ExecutablesView.this.getExecutablesViewer().getTree().getShell(), this, + new ColumnContentProvider(), new ColumnLabelProvider(), "Select the columns to show"); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, CONFIGURE_COLUMNS_DIALOG); + String[] visibleColumns = getVisibleColumns(); + List<String> initialSelection = new ArrayList<String>(visibleColumns.length); + for (int i = 0; i < visibleColumns.length; i++) { + initialSelection.add(visibleColumns[i]); + } + dialog.setTitle("Configure COlumns"); + dialog.setInitialElementSelections(initialSelection); + if (dialog.open() == Window.OK) { + Object[] result = dialog.getResult(); + String[] ids = new String[result.length]; + System.arraycopy(result, 0, ids, 0, result.length); + setVisibleColumns(ids); + } + + } + + } + + /** + * Sub viewers and trees + */ + private SourceFilesViewer sourceFilesViewer; + private ExecutablesViewer executablesViewer; + + /** + * Associated Actions + */ + Action refreshAction; + Action importAction; + private Action configureColumnsAction; + + private IMemento memento; + + /** + * Create contents of the Executables View + * + * @param parent + */ + @Override + public void createPartControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + container.setLayout(new FillLayout()); + + final SashForm sashForm = new SashForm(container, SWT.NONE); + + // Create the two sub viewers. + executablesViewer = new ExecutablesViewer(this, sashForm, SWT.FULL_SELECTION + SWT.BORDER); + ExecutablesManager.getExecutablesManager().addExecutablesChangeListener(executablesViewer); + sourceFilesViewer = new SourceFilesViewer(this, sashForm, SWT.BORDER); + + sashForm.setWeights(new int[] { 1, 1 }); + + // Keep a combined list of all the columns so + // we can easily operate on them all. + allColumns[0] = executablesViewer.nameColumn; + allColumns[1] = executablesViewer.projectColumn; + allColumns[2] = executablesViewer.locationColumn; + allColumns[3] = executablesViewer.sizeColumn; + allColumns[4] = executablesViewer.modifiedColumn; + allColumns[5] = executablesViewer.typeColumn; + allColumns[6] = sourceFilesViewer.nameColumn; + allColumns[7] = sourceFilesViewer.locationColumn; + allColumns[8] = sourceFilesViewer.originalLocationColumn; + allColumns[9] = sourceFilesViewer.sizeColumn; + allColumns[10] = sourceFilesViewer.modifiedColumn; + allColumns[11] = sourceFilesViewer.typeColumn; + + createActions(); + + // When the selection changes in the executables list + // update the source files viewer + executablesViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + public void selectionChanged(SelectionChangedEvent event) { + ISelection newSelection = event.getSelection(); + if (newSelection instanceof IStructuredSelection) { + Object firstElement = ((IStructuredSelection) newSelection).getFirstElement(); + sourceFilesViewer.setInput(firstElement); + if (firstElement instanceof Executable) { + sourceFilesViewer.packColumns(); + } + } + } + }); + + // Initialize the list of visible columns + if (memento.getString(P_VISIBLE_COLUMNS).length() > 0) { + String[] visibleColumns = memento.getString(P_VISIBLE_COLUMNS).split(","); + setVisibleColumns(visibleColumns); + } else { + setVisibleColumns(defaultVisibleColumns.split(",")); + } + sourceFilesViewer.packColumns(); + + PlatformUI.getWorkbench().getHelpSystem().setHelp(container, EXECUTABLES_VIEW_CONTEXT); + } + + private void setVisibleColumns(String[] ids) { + List<String> visibleNames = Arrays.asList(ids); + for (int i = 0; i < columnNames.length; i++) { + makeColumnVisible(visibleNames.contains(columnNames[i]), allColumns[i]); + } + + StringBuffer visibleColumns = new StringBuffer(); + for (int i = 0; i < ids.length; i++) { + if (i > 0) + visibleColumns.append(","); + visibleColumns.append(ids[i]); + } + memento.putString(P_VISIBLE_COLUMNS, visibleColumns.toString()); + } + + private void makeColumnVisible(boolean visible, TreeColumn column) { + boolean isVisible = column.getWidth() > 0; + if (isVisible != visible) { + if (visible) { + column.setResizable(true); + column.pack(); + column.setWidth(column.getWidth() + COLUMN_WIDTH_PADDING); + } else { + column.setWidth(0); + column.setResizable(false); + } + } + } + + private String[] getVisibleColumns() { + ArrayList<String> visibleNames = new ArrayList<String>(); + + for (int i = 0; i < columnNames.length; i++) { + if (allColumns[i].getWidth() > 0) + visibleNames.add(columnNames[i]); + } + + return visibleNames.toArray(new String[visibleNames.size()]); + } + + /** + * Create the actions to refresh, import, and configure the columns + */ + private void createActions() { + IActionBars bars = getViewSite().getActionBars(); + IToolBarManager toolBarManager = bars.getToolBarManager(); + + refreshAction = createRefreshAction(); + toolBarManager.add(refreshAction); + + importAction = createImportAction(); + toolBarManager.add(importAction); + + configureColumnsAction = createConfigureColumnsAction(); + toolBarManager.add(configureColumnsAction); + + } + + private Action createConfigureColumnsAction() { + ConfigureColumnsAction action = new ConfigureColumnsAction(); + action.setToolTipText("Columns"); + action.setImageDescriptor(ExecutablesView.DESC_COLUMNS); + action.setDisabledImageDescriptor(ExecutablesView.DESC_COLUMNS_DISABLED); + action.setEnabled(true); + return action; + } + + protected void importExecutables(final String[] fileNames) { + if (fileNames.length > 0) { + + Job importJob = new Job("Import Executables") { + + @Override + public IStatus run(IProgressMonitor monitor) { + ExecutablesManager.getExecutablesManager().importExecutables(fileNames, monitor); + return Status.OK_STATUS; + } + }; + importJob.schedule(); + } + } + + private Action createImportAction() { + Action action = new Action("Import") { + public void run() { + FileDialog dialog = new FileDialog(getViewSite().getShell(), SWT.NONE); + dialog.setText("Select an executable file"); + String res = dialog.open(); + if (res != null) { + if (Platform.getOS().equals(Platform.OS_MACOSX) && res.endsWith(".app")) { + // On Mac OS X the file dialog will let you select the + // package but not the executable inside. + Path macPath = new Path(res); + res = res + "/Contents/MacOS/" + macPath.lastSegment(); + res = res.substring(0, res.length() - 4); + } + importExecutables(new String[] { res }); + } + } + }; + action.setToolTipText("Import an executable file"); + action.setImageDescriptor(ExecutablesView.DESC_IMPORT); + action.setDisabledImageDescriptor(ExecutablesView.DESC_IMPORT_DISABLED); + action.setEnabled(true); + return action; + } + + private Action createRefreshAction() { + Action action = new Action("Refresh") { + public void run() { + ExecutablesManager.getExecutablesManager().scheduleRefresh(null, 0); + } + }; + action.setToolTipText("Refresh the list of executables"); + action.setImageDescriptor(ExecutablesView.DESC_REFRESH); + action.setDisabledImageDescriptor(ExecutablesView.DESC_REFRESH_DISABLED); + action.setEnabled(true); + return action; + } + + @Override + public void setFocus() { + // Set the focus + } + + @Override + public void init(IViewSite site, IMemento memento) throws PartInitException { + if (memento == null) + this.memento = XMLMemento.createWriteRoot("EXECUTABLESVIEW"); //$NON-NLS-1$ + else + this.memento = memento; + super.init(site, memento); + readSettings(); + } + + private Preferences getViewPreferences() { + return CDebugUIPlugin.getDefault().getPluginPreferences(); + } + + private void initializeMemento() { + memento.putInteger(P_ORDER_VALUE_EXE, DESCENDING); + memento.putInteger(P_ORDER_TYPE_EXE, NAME); + memento.putInteger(P_ORDER_VALUE_SF, DESCENDING); + memento.putInteger(P_ORDER_TYPE_SF, NAME); + memento.putString(P_VISIBLE_COLUMNS, defaultVisibleColumns); + } + + private void readSettings() { + Preferences p = getViewPreferences(); + if (p == null) { + initializeMemento(); + return; + } + try { + int order = p.getInt(P_ORDER_VALUE_EXE); + memento.putInteger(P_ORDER_VALUE_EXE, order == 0 ? DESCENDING : order); + memento.putInteger(P_ORDER_TYPE_EXE, p.getInt(P_ORDER_TYPE_EXE)); + order = p.getInt(P_ORDER_VALUE_SF); + memento.putInteger(P_ORDER_VALUE_SF, order == 0 ? DESCENDING : order); + memento.putInteger(P_ORDER_TYPE_SF, p.getInt(P_ORDER_TYPE_SF)); + memento.putString(P_VISIBLE_COLUMNS, p.getString(P_VISIBLE_COLUMNS)); + } catch (NumberFormatException e) { + memento.putInteger(P_ORDER_TYPE_EXE, NAME); + memento.putInteger(P_ORDER_VALUE_EXE, DESCENDING); + memento.putInteger(P_ORDER_TYPE_SF, NAME); + memento.putInteger(P_ORDER_VALUE_SF, DESCENDING); + } + } + + private void writeSettings() { + Preferences preferences = getViewPreferences(); + int order = memento.getInteger(P_ORDER_VALUE_EXE).intValue(); + preferences.setValue(P_ORDER_VALUE_EXE, order == 0 ? DESCENDING : order); + preferences.setValue(P_ORDER_TYPE_EXE, memento.getInteger(P_ORDER_TYPE_EXE).intValue()); + order = memento.getInteger(P_ORDER_VALUE_SF).intValue(); + preferences.setValue(P_ORDER_VALUE_SF, order == 0 ? DESCENDING : order); + preferences.setValue(P_ORDER_TYPE_SF, memento.getInteger(P_ORDER_TYPE_SF).intValue()); + preferences.setValue(P_VISIBLE_COLUMNS, memento.getString(P_VISIBLE_COLUMNS)); + } + + @Override + public void saveState(IMemento memento) { + if (this.memento == null || memento == null) + return; + memento.putMemento(this.memento); + writeSettings(); + } + + public SourceFilesViewer getSourceFilesViewer() { + return sourceFilesViewer; + } + + public ExecutablesViewer getExecutablesViewer() { + return executablesViewer; + } + + @Override + public void dispose() { + ExecutablesManager.getExecutablesManager().removeExecutablesChangeListener(executablesViewer); + super.dispose(); + } + + public IMemento getMemento() { + return memento; + } + +} diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java new file mode 100644 index 00000000000..631385f844e --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.cdt.debug.core.executables.ExecutablesManager; +import org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent; +import org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.viewers.ViewerDropAdapter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.progress.UIJob; + +/** + * Displays the list of executables gathered by the ExecutablesManager + */ +public class ExecutablesViewer extends BaseViewer implements IExecutablesChangeListener { + + /** + * Handles dropping executable files into the view + */ + public class ExecutablesDropAdapter extends ViewerDropAdapter { + + protected ExecutablesDropAdapter(Viewer viewer) { + super(viewer); + } + + @Override + public boolean performDrop(Object data) { + final String[] fileNames = (String[]) data; + ExecutablesViewer.this.getExecutablesView().importExecutables(fileNames); + return true; + } + + @Override + public boolean validateDrop(Object target, int operation, TransferData transferType) { + return FileTransfer.getInstance().isSupportedType(transferType); + } + + } + + public TreeColumn projectColumn; + + public ExecutablesViewer(ExecutablesView executablesView, Composite parent, int style) { + super(executablesView, parent, style); + + // Setup D&D support + int ops = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_DEFAULT; + Transfer[] transfers = new Transfer[] { FileTransfer.getInstance() }; + ExecutablesDropAdapter adapter = new ExecutablesDropAdapter(this); + adapter.setFeedbackEnabled(false); + addDropSupport(ops | DND.DROP_DEFAULT, transfers, adapter); + + // Setup content provider + ExecutablesContentProvider exeContentProvider = new ExecutablesContentProvider(this); + setContentProvider(exeContentProvider); + setLabelProvider(exeContentProvider); + + getTree().setHeaderVisible(true); + getTree().setLinesVisible(true); + executablesView.getSite().setSelectionProvider(this); + + createColumns(); + initializeSorter(); + + setInput(ExecutablesManager.getExecutablesManager()); + + MenuManager popupMenuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + IMenuListener listener = new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + manager.add(ExecutablesViewer.this.getExecutablesView().refreshAction); + manager.add(ExecutablesViewer.this.getExecutablesView().importAction); + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + }; + popupMenuManager.addMenuListener(listener); + popupMenuManager.setRemoveAllWhenShown(true); + getExecutablesView().getSite().registerContextMenu(popupMenuManager, this.getExecutablesView().getSite().getSelectionProvider()); + Menu menu = popupMenuManager.createContextMenu(getTree()); + getTree().setMenu(menu); + } + + private void createColumns() { + nameColumn = new TreeColumn(getTree(), SWT.NONE); + nameColumn.setWidth(100); + nameColumn.setText("Executable Name"); + nameColumn.setMoveable(true); + nameColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.NAME)); + + projectColumn = new TreeColumn(getTree(), SWT.NONE); + projectColumn.setWidth(100); + projectColumn.setMoveable(true); + projectColumn.setText("Project"); + projectColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.PROJECT)); + + locationColumn = new TreeColumn(getTree(), SWT.NONE); + locationColumn.setWidth(100); + locationColumn.setText("Location"); + locationColumn.setMoveable(true); + locationColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.LOCATION)); + + sizeColumn = new TreeColumn(getTree(), SWT.NONE); + sizeColumn.setWidth(100); + sizeColumn.setText("Size"); + sizeColumn.setMoveable(true); + sizeColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.SIZE)); + + modifiedColumn = new TreeColumn(getTree(), SWT.NONE); + modifiedColumn.setWidth(100); + modifiedColumn.setText("Modified"); + modifiedColumn.setMoveable(true); + modifiedColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.MODIFIED)); + + typeColumn = new TreeColumn(getTree(), SWT.NONE); + typeColumn.setWidth(100); + typeColumn.setText("Type"); + typeColumn.setMoveable(true); + typeColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.TYPE)); + + } + + /** + * Initialize column ordering and sorting + */ + private void initializeSorter() { + byte orderType = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_TYPE_EXE).byteValue(); + switch (orderType) { + case ExecutablesView.NAME: + column_order[ExecutablesView.NAME] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_EXE).intValue(); + column_order[ExecutablesView.PROJECT] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.PROJECT: + column_order[ExecutablesView.PROJECT] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_EXE).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.LOCATION: + column_order[ExecutablesView.LOCATION] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_EXE).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.PROJECT] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.SIZE: + column_order[ExecutablesView.SIZE] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_EXE).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.PROJECT] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.MODIFIED: + column_order[ExecutablesView.MODIFIED] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_EXE).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.PROJECT] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + default: + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.PROJECT] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + } + + ViewerComparator comparator = getViewerComparator(orderType); + setComparator(comparator); + if (orderType == ExecutablesView.NAME) + setColumnSorting(nameColumn, column_order[ExecutablesView.NAME]); + else if (orderType == ExecutablesView.PROJECT) + setColumnSorting(projectColumn, column_order[ExecutablesView.PROJECT]); + else if (orderType == ExecutablesView.LOCATION) + setColumnSorting(locationColumn, column_order[ExecutablesView.LOCATION]); + else if (orderType == ExecutablesView.SIZE) + setColumnSorting(projectColumn, column_order[ExecutablesView.SIZE]); + else if (orderType == ExecutablesView.MODIFIED) + setColumnSorting(locationColumn, column_order[ExecutablesView.MODIFIED]); + } + + @Override + protected ViewerComparator getViewerComparator(int sortType) { + if (sortType == ExecutablesView.PROJECT) { + return new ExecutablesViewerComparator(sortType, column_order[ExecutablesView.PROJECT]) { + @SuppressWarnings("unchecked") + public int compare(Viewer viewer, Object e1, Object e2) { + Executable entry1 = (Executable) e1; + Executable entry2 = (Executable) e2; + return getComparator().compare(entry1.getProject().getName(), entry2.getProject().getName()) + * column_order[ExecutablesView.PROJECT]; + } + }; + } + return new ExecutablesViewerComparator(sortType, column_order[sortType]); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener#executablesChanged(org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent) + */ + public void executablesChanged(IExecutablesChangeEvent event) { + // Executables have changed so refresh the view. + final ExecutablesViewer viewer = this; + UIJob refreshJob = new UIJob("Refresh Executables View") { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + viewer.refresh(null); + viewer.packColumns(); + return Status.OK_STATUS; + } + }; + refreshJob.schedule(); + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewerComparator.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewerComparator.java new file mode 100644 index 00000000000..78049171fd1 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewerComparator.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import java.io.File; + +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +class ExecutablesViewerComparator extends ViewerComparator { + + private int sortType; + private int columnOrder; + + public ExecutablesViewerComparator(int sortType, int columnOrder) { + this.sortType = sortType; + this.columnOrder = columnOrder; + } + + public int category(Object element) { + if (element instanceof ITranslationUnit || element instanceof Executable) + return 1; + return 0; + } + + @SuppressWarnings("unchecked") + public int compare(Viewer viewer, Object e1, Object e2) { + + if (category(e1) == 1 && category(e2) == 1) { + if (sortType == ExecutablesView.NAME) { + String s1 = ((ColumnLabelProvider) ((TreeViewer) viewer).getLabelProvider()).getText(e1); + String s2 = ((ColumnLabelProvider) ((TreeViewer) viewer).getLabelProvider()).getText(e2); + return getComparator().compare(s1, s2) * columnOrder; + } + + if (sortType == ExecutablesView.SIZE) { + long file1 = getFileSize(e1); + long file2 = getFileSize(e2); + return Long.valueOf(file1).compareTo(Long.valueOf(file2)) * columnOrder; + } + + if (sortType == ExecutablesView.LOCATION) { + return getComparator().compare(getPath(e1).toOSString(), getPath(e2).toOSString()) * columnOrder; + } + + if (sortType == ExecutablesView.MODIFIED) { + long file1 = getPath(e1).toFile().lastModified(); + long file2 = getPath(e2).toFile().lastModified(); + return Long.valueOf(file1).compareTo(Long.valueOf(file2)) * columnOrder; + } + + if (sortType == ExecutablesView.TYPE) { + String ext1 = getPath(e1).getFileExtension(); + String s1 = ext1 != null ? ext1.toUpperCase() : ""; + String ext2 = getPath(e2).getFileExtension(); + String s2 = ext2 != null ? ext2.toUpperCase() : ""; + return getComparator().compare(s1, s2) * columnOrder; + } + } + + return super.compare(viewer, e1, e2); + } + + private long getFileSize(Object element) { + File file1 = getPath(element).toFile(); + if (file1.exists()) + return file1.length(); + return 0; + } + + private IPath getPath(Object element) { + if (element instanceof ITranslationUnit) { + return ((ITranslationUnit) element).getPath(); + } else if (element instanceof Executable) { + return ((Executable) element).getPath(); + } + return null; + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesContentProvider.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesContentProvider.java new file mode 100644 index 00000000000..e69e02759a8 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesContentProvider.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.cdt.ui.CElementContentProvider; +import org.eclipse.core.runtime.IPath; + +public class SourceFilesContentProvider extends CElementContentProvider { + + public SourceFilesContentProvider(SourceFilesViewer viewer) { + super(true, true); + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof ITranslationUnit) { + IPath path = ((ITranslationUnit) element).getLocation(); + if (path != null && !path.toFile().exists()) + return false; + } + return super.hasChildren(element); + } + + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Executable) { + Executable executable = (Executable) inputElement; + ITranslationUnit[] sourceFiles = executable.getSourceFiles(); + if (sourceFiles.length == 0) + return new String[] { "No source files found in " + executable.getName() }; + else + return sourceFiles; + } + return new Object[] {}; + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java new file mode 100644 index 00000000000..d813154c0ed --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import java.text.DateFormat; +import java.util.Date; + +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.cdt.ui.CElementLabelProvider; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.resource.FontDescriptor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.TreeColumnViewerLabelProvider; +import org.eclipse.jface.viewers.ViewerCell; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.widgets.Display; + +public class SourceFilesLabelProvider extends TreeColumnViewerLabelProvider { + + private SourceFilesViewer viewer; + + private LocalResourceManager resourceManager = new LocalResourceManager(JFaceResources.getResources()); + + public SourceFilesLabelProvider(SourceFilesViewer viewer) { + super(new CElementLabelProvider()); + this.viewer = viewer; + } + + @Override + public void update(ViewerCell cell) { + super.update(cell); + + int orgColumnIndex = cell.getColumnIndex(); + + if (orgColumnIndex == 0) { + if (cell.getElement() instanceof String) { + cell.setText((String) cell.getElement()); + Font boldFont = resourceManager.createFont(FontDescriptor.createFrom(viewer.getTree().getFont()).setStyle(SWT.BOLD)); + cell.setFont(boldFont); + } + } else if (orgColumnIndex == 1) { + cell.setText(null); + if (cell.getElement() instanceof ITranslationUnit) { + ITranslationUnit tu = (ITranslationUnit) cell.getElement(); + IPath path = tu.getLocation(); + if (path != null) { + cell.setText(path.toOSString()); + if (path.toFile().exists()) + cell.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + else + cell.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY)); + } + } + cell.setImage(null); + } else if (orgColumnIndex == 2) { + cell.setText(null); + if (cell.getElement() instanceof ITranslationUnit) { + Executable executable = (Executable) viewer.getInput(); + Path path = new Path(executable.getOriginalLocation((ITranslationUnit) cell.getElement())); + cell.setText(executable.getOriginalLocation((ITranslationUnit) cell.getElement())); + if (path.toFile().exists()) + cell.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + else + cell.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY)); + } + cell.setImage(null); + } else if (orgColumnIndex == 3) { + cell.setText(null); + if (cell.getElement() instanceof ITranslationUnit) { + ITranslationUnit tu = (ITranslationUnit) cell.getElement(); + IPath path = tu.getLocation(); + if (path != null && path.toFile().exists()) { + long fileLength = path.toFile().length(); + cell.setText(Long.toString(fileLength)); + } + } + cell.setImage(null); + } else if (orgColumnIndex == 4) { + cell.setText(null); + if (cell.getElement() instanceof ITranslationUnit) { + ITranslationUnit tu = (ITranslationUnit) cell.getElement(); + IPath path = tu.getLocation(); + if (path != null && path.toFile().exists()) { + long modified = path.toFile().lastModified(); + String dateTimeString = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date(modified)); + cell.setText(dateTimeString); + } + } + cell.setImage(null); + } else if (orgColumnIndex == 5) { + cell.setText(null); + if (cell.getElement() instanceof ITranslationUnit) { + ITranslationUnit tu = (ITranslationUnit) cell.getElement(); + IPath path = tu.getLocation(); + if (path != null) { + String fileExtension = path.getFileExtension(); + if (fileExtension != null) + cell.setText(fileExtension.toLowerCase()); + } + } + cell.setImage(null); + } + } + +} diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java new file mode 100644 index 00000000000..a3ecf577afa --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java @@ -0,0 +1,276 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.views.executables; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.debug.core.CDebugCorePlugin; +import org.eclipse.cdt.debug.core.executables.Executable; +import org.eclipse.cdt.debug.internal.ui.sourcelookup.CSourceNotFoundEditorInput; +import org.eclipse.cdt.debug.ui.ICDebugUIConstants; +import org.eclipse.cdt.internal.ui.util.EditorUtility; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; +import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.progress.UIJob; + +/** + * Displays the list of source files for the executable selected in the + * ExecutablesViewer. + */ +public class SourceFilesViewer extends BaseViewer implements ISourceLookupParticipant { + + TreeColumn originalLocationColumn; + private Tree sourceFilesTree; + + public SourceFilesViewer(ExecutablesView view, Composite parent, int style) { + super(view, parent, style); + + setContentProvider(new SourceFilesContentProvider(this)); + setLabelProvider(new SourceFilesLabelProvider(this)); + sourceFilesTree = getTree(); + sourceFilesTree.setHeaderVisible(true); + sourceFilesTree.setLinesVisible(true); + + createColumns(); + + this.addOpenListener(new IOpenListener() { + + public void open(OpenEvent event) { + openSourceFile(event); + } + }); + + initializeSorter(); + + // We implement ISourceLookupParticipant so we can listen for changes to + // source lookup as this viewer shows both original and remapped + // locations + CDebugCorePlugin.getDefault().getCommonSourceLookupDirector().addParticipants(new ISourceLookupParticipant[] { this }); + sourceFilesTree.addDisposeListener(new DisposeListener() { + + public void widgetDisposed(DisposeEvent e) { + CDebugCorePlugin.getDefault().getCommonSourceLookupDirector().removeParticipants( + new ISourceLookupParticipant[] { SourceFilesViewer.this }); + } + }); + } + + private void openSourceFile(OpenEvent event) { + boolean opened = false; + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + Object element = selection.getFirstElement(); + if (element instanceof ICElement) { + if (element instanceof ITranslationUnit) { + ITranslationUnit tu = (ITranslationUnit) element; + IPath path = tu.getLocation(); + if (path != null && !path.toFile().exists()) { + // Open the source not found editor + IWorkbenchPage p = CUIPlugin.getActivePage(); + if (p != null) { + try { + String editorID = ICDebugUIConstants.CSOURCENOTFOUND_EDITOR_ID; + p.openEditor(new CSourceNotFoundEditorInput(tu), editorID, true); + opened = true; + } catch (PartInitException e) { + } + } + + } + + } + if (!opened) { + try { + IEditorPart part = EditorUtility.openInEditor(element); + if (part != null) { + IWorkbenchPage page = getExecutablesView().getSite().getPage(); + page.bringToTop(part); + if (element instanceof ISourceReference) { + EditorUtility.revealInEditor(part, (ICElement) element); + } + } + } catch (Exception e) { + } + } + } + } + + private void createColumns() { + nameColumn = new TreeColumn(sourceFilesTree, SWT.NONE); + nameColumn.setWidth(100); + nameColumn.setText("Source File Name"); + nameColumn.setMoveable(true); + nameColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.NAME)); + + locationColumn = new TreeColumn(sourceFilesTree, SWT.NONE); + locationColumn.setWidth(100); + locationColumn.setText("Location"); + locationColumn.setMoveable(true); + locationColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.LOCATION)); + + originalLocationColumn = new TreeColumn(sourceFilesTree, SWT.NONE); + originalLocationColumn.setWidth(100); + originalLocationColumn.setText("Original"); + originalLocationColumn.setMoveable(true); + originalLocationColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.ORG_LOCATION)); + + sizeColumn = new TreeColumn(sourceFilesTree, SWT.NONE); + sizeColumn.setWidth(100); + sizeColumn.setText("Size"); + sizeColumn.setMoveable(true); + sizeColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.SIZE)); + + modifiedColumn = new TreeColumn(sourceFilesTree, SWT.NONE); + modifiedColumn.setWidth(100); + modifiedColumn.setText("Modified"); + modifiedColumn.setMoveable(true); + modifiedColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.MODIFIED)); + + typeColumn = new TreeColumn(sourceFilesTree, SWT.NONE); + typeColumn.setWidth(100); + typeColumn.setText("Type"); + typeColumn.setMoveable(true); + typeColumn.addSelectionListener(new ColumnSelectionAdapter(ExecutablesView.TYPE)); + } + + protected ViewerComparator getViewerComparator(int sortType) { + if (sortType == ExecutablesView.ORG_LOCATION) { + return new ExecutablesViewerComparator(sortType, column_order[ExecutablesView.ORG_LOCATION]) { + + @SuppressWarnings("unchecked") + public int compare(Viewer viewer, Object e1, Object e2) { + if (e1 instanceof ITranslationUnit && e2 instanceof ITranslationUnit) { + ITranslationUnit entry1 = (ITranslationUnit) e1; + ITranslationUnit entry2 = (ITranslationUnit) e2; + Executable exe = (Executable) getInput(); + String originalLocation1 = exe.getOriginalLocation(entry1); + String originalLocation2 = exe.getOriginalLocation(entry2); + return getComparator().compare(originalLocation1, originalLocation2) * column_order[ExecutablesView.ORG_LOCATION]; + } + return super.compare(viewer, e1, e2); + } + }; + } else + return new ExecutablesViewerComparator(sortType, column_order[sortType]); + } + + private void initializeSorter() { + byte orderType = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_TYPE_SF).byteValue(); + switch (orderType) { + case ExecutablesView.NAME: + column_order[ExecutablesView.NAME] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_SF).intValue(); + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.ORG_LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.LOCATION: + column_order[ExecutablesView.LOCATION] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_SF).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.ORG_LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.ORG_LOCATION: + column_order[ExecutablesView.ORG_LOCATION] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_SF).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.SIZE: + column_order[ExecutablesView.SIZE] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_SF).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.ORG_LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + case ExecutablesView.MODIFIED: + column_order[ExecutablesView.MODIFIED] = getExecutablesView().getMemento().getInteger(ExecutablesView.P_ORDER_VALUE_SF).intValue(); + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.ORG_LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + break; + default: + column_order[ExecutablesView.MODIFIED] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.NAME] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.SIZE] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.ORG_LOCATION] = ExecutablesView.DESCENDING; + column_order[ExecutablesView.TYPE] = ExecutablesView.DESCENDING; + } + + ViewerComparator comparator = getViewerComparator(orderType); + setComparator(comparator); + if (orderType == ExecutablesView.NAME) + setColumnSorting(nameColumn, column_order[ExecutablesView.NAME]); + else if (orderType == ExecutablesView.LOCATION) + setColumnSorting(locationColumn, column_order[ExecutablesView.LOCATION]); + else if (orderType == ExecutablesView.ORG_LOCATION) + setColumnSorting(originalLocationColumn, column_order[ExecutablesView.ORG_LOCATION]); + } + + public void dispose() { + } + + public Object[] findSourceElements(Object object) throws CoreException { + return new Object[0]; + } + + public String getSourceName(Object object) throws CoreException { + return ""; + } + + public void init(ISourceLookupDirector director) { + } + + public void sourceContainersChanged(ISourceLookupDirector director) { + UIJob refreshJob = new UIJob("Refresh Source Files") { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + Object input = getInput(); + if (input != null && input instanceof Executable) { + refresh(true); + } + return Status.OK_STATUS; + } + }; + refreshJob.schedule(); + } + +}
\ No newline at end of file diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/ui/ICDebugUIConstants.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/ui/ICDebugUIConstants.java index 727beb01cbf..b9324194a81 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/ui/ICDebugUIConstants.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/ui/ICDebugUIConstants.java @@ -20,7 +20,12 @@ public interface ICDebugUIConstants { public static final String PLUGIN_ID = CDebugUIPlugin.getUniqueIdentifier(); public static final String PREFIX = PLUGIN_ID + "."; //$NON-NLS-1$ - + + /** + * Executables view identifier (value <code>"org.eclipse.cdt.debug.ui.executablesView"</code>). + */ + public static final String ID_EXECUTABLES_VIEW = PREFIX + "executablesView"; //$NON-NLS-1$ + /** * Disassembly view identifier (value <code>"org.eclipse.cdt.debug.ui.DisassemblyView"</code>). */ |