diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.traceview/src')
3 files changed, 460 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/TraceviewLauncher.java b/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/TraceviewLauncher.java new file mode 100644 index 000000000..b232bac3d --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/TraceviewLauncher.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.traceview; + +import com.android.ide.eclipse.ddms.ITraceviewLauncher; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Path; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.ide.IDE; + +public class TraceviewLauncher implements ITraceviewLauncher { + + @Override + public boolean openFile(String osPath) { + final IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(osPath)); + if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) { + // before we open the file in an editor window, we make sure the current + // workbench page has an editor area (typically the ddms perspective doesn't). + final IWorkbench workbench = PlatformUI.getWorkbench(); + Display display = workbench.getDisplay(); + final boolean[] result = new boolean[] { false }; + display.syncExec(new Runnable() { + @Override + public void run() { + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + IWorkbenchPage page = window.getActivePage(); + if (page.isEditorAreaVisible() == false) { + IAdaptable input; + if (page != null) + input= page.getInput(); + else + input= ResourcesPlugin.getWorkspace().getRoot(); + try { + workbench.showPerspective("org.eclipse.debug.ui.DebugPerspective", + window, input); + } catch (WorkbenchException e) { + } + } + + try { + result[0] = IDE.openEditorOnFileStore(page, fileStore) != null; + } catch (PartInitException e) { + // return false below + } + } + }); + + return result[0]; + } + + return false; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/TraceviewPlugin.java b/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/TraceviewPlugin.java new file mode 100644 index 000000000..e11f7c929 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/TraceviewPlugin.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ide.eclipse.traceview; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class TraceviewPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "com.android.ide.eclipse.traceview"; // $NON-NLS-1$ + + // The shared instance + private static TraceviewPlugin sPlugin; + + /** + * The constructor + */ + public TraceviewPlugin() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + sPlugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + sPlugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static TraceviewPlugin getDefault() { + return sPlugin; + } + +} diff --git a/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/editors/TraceviewEditor.java b/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/editors/TraceviewEditor.java new file mode 100644 index 000000000..6d07018cd --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.traceview/src/com/android/ide/eclipse/traceview/editors/TraceviewEditor.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ide.eclipse.traceview.editors; + +import com.android.ide.eclipse.ddms.JavaSourceRevealer; +import com.android.ide.eclipse.traceview.TraceviewPlugin; +import com.android.traceview.ColorController; +import com.android.traceview.DmTraceReader; +import com.android.traceview.MethodData; +import com.android.traceview.ProfileView; +import com.android.traceview.ProfileView.MethodHandler; +import com.android.traceview.SelectionController; +import com.android.traceview.TimeLineView; +import com.android.traceview.TraceReader; +import com.android.traceview.TraceUnits; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IWorkspace; +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; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.dialogs.SaveAsDialog; +import org.eclipse.ui.ide.FileStoreEditorInput; +import org.eclipse.ui.part.EditorPart; +import org.eclipse.ui.part.FileEditorInput; + +import java.io.File; +import java.io.IOException; +import java.net.URI; + +public class TraceviewEditor extends EditorPart implements MethodHandler { + + private Composite mParent; + private String mFilename; + private Composite mContents; + + @Override + public void doSave(IProgressMonitor monitor) { + // We do not modify the file + } + + /* + * Copied from org.eclipse.ui.texteditor.AbstractDecoratedTextEditor. + */ + /** + * Checks whether there given file store points to a file in the workspace. + * Only returns a workspace file if there's a single match. + * + * @param fileStore the file store + * @return the <code>IFile</code> that matches the given file store + */ + private IFile getWorkspaceFile(IFileStore fileStore) { + IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + IFile[] files = workspaceRoot.findFilesForLocationURI(fileStore.toURI()); + if (files != null && files.length == 1) + return files[0]; + return null; + } + + /* + * Based on the performSaveAs() method defined in class + * org.eclipse.ui.texteditor.AbstractDecoratedTextEditor of the + * org.eclipse.ui.editors plugin. + */ + @Override + public void doSaveAs() { + Shell shell = getSite().getShell(); + final IEditorInput input = getEditorInput(); + + final IEditorInput newInput; + + if (input instanceof FileEditorInput) { + // the file is part of the current workspace + FileEditorInput fileEditorInput = (FileEditorInput) input; + SaveAsDialog dialog = new SaveAsDialog(shell); + + IFile original = fileEditorInput.getFile(); + if (original != null) { + dialog.setOriginalFile(original); + } + + dialog.create(); + + if (original != null && !original.isAccessible()) { + String message = String.format( + "The original file ''%s'' has been deleted or is not accessible.", + original.getName()); + dialog.setErrorMessage(null); + dialog.setMessage(message, IMessageProvider.WARNING); + } + + if (dialog.open() == Window.CANCEL) { + return; + } + + IPath filePath = dialog.getResult(); + if (filePath == null) { + return; + } + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IFile file = workspace.getRoot().getFile(filePath); + + if (copy(shell, fileEditorInput.getURI(), file.getLocationURI()) == null) { + return; + } + + try { + file.refreshLocal(IFile.DEPTH_ZERO, null); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + newInput = new FileEditorInput(file); + setInput(newInput); + setPartName(newInput.getName()); + } else if (input instanceof FileStoreEditorInput) { + // the file is not part of the current workspace + FileStoreEditorInput fileStoreEditorInput = (FileStoreEditorInput) input; + FileDialog dialog = new FileDialog(shell, SWT.SAVE); + IPath oldPath = URIUtil.toPath(fileStoreEditorInput.getURI()); + if (oldPath != null) { + dialog.setFileName(oldPath.lastSegment()); + dialog.setFilterPath(oldPath.toOSString()); + } + + String path = dialog.open(); + if (path == null) { + return; + } + + // Check whether file exists and if so, confirm overwrite + final File localFile = new File(path); + if (localFile.exists()) { + MessageDialog overwriteDialog = new MessageDialog( + shell, + "Save As", + null, + String.format( + "%s already exists.\nDo you want to replace it?" + , path), + MessageDialog.WARNING, + new String[] { + IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL + }, 1); // 'No' is the default + if (overwriteDialog.open() != Window.OK) { + return; + } + } + + IFileStore destFileStore = copy(shell, fileStoreEditorInput.getURI(), localFile.toURI()); + if (destFileStore != null) { + IFile file = getWorkspaceFile(destFileStore); + if (file != null) { + newInput = new FileEditorInput(file); + } else { + newInput = new FileStoreEditorInput(destFileStore); + } + setInput(newInput); + setPartName(newInput.getName()); + } + } + } + + private IFileStore copy(Shell shell, URI source, URI dest) { + IFileStore destFileStore = null; + IFileStore sourceFileStore = null; + try { + destFileStore = EFS.getStore(dest); + sourceFileStore = EFS.getStore(source); + sourceFileStore.copy(destFileStore, EFS.OVERWRITE, null); + } catch (CoreException ex) { + String title = "Problems During Save As..."; + String msg = String.format("Save could not be completed. %s", + ex.getMessage()); + MessageDialog.openError(shell, title, msg); + return null; + } + return destFileStore; + } + + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + // The contract of init() mentions we need to fail if we can't + // understand the input. + if (input instanceof FileEditorInput) { + // We try to open a file that is part of the current workspace + FileEditorInput fileEditorInput = (FileEditorInput) input; + mFilename = fileEditorInput.getPath().toOSString(); + setSite(site); + setInput(input); + setPartName(input.getName()); + } else if (input instanceof FileStoreEditorInput) { + // We try to open a file that is not part of the current workspace + FileStoreEditorInput fileStoreEditorInput = (FileStoreEditorInput) input; + mFilename = fileStoreEditorInput.getURI().getPath(); + setSite(site); + setInput(input); + setPartName(input.getName()); + } else { + throw new PartInitException("Input is not of type FileEditorInput " + //$NON-NLS-1$ + "nor FileStoreEditorInput: " + //$NON-NLS-1$ + input == null ? "null" : input.toString()); //$NON-NLS-1$ + } + } + + @Override + public boolean isDirty() { + return false; + } + + @Override + public boolean isSaveAsAllowed() { + return true; + } + + @Override + public void createPartControl(Composite parent) { + mParent = parent; + try { + TraceReader reader = new DmTraceReader(mFilename, false); + reader.getTraceUnits().setTimeScale(TraceUnits.TimeScale.MilliSeconds); + + mContents = new Composite(mParent, SWT.NONE); + + Display display = mContents.getDisplay(); + ColorController.assignMethodColors(display, reader.getMethods()); + SelectionController selectionController = new SelectionController(); + + GridLayout gridLayout = new GridLayout(1, false); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + gridLayout.horizontalSpacing = 0; + gridLayout.verticalSpacing = 0; + mContents.setLayout(gridLayout); + + Color darkGray = display.getSystemColor(SWT.COLOR_DARK_GRAY); + + // Create a sash form to separate the timeline view (on top) + // and the profile view (on bottom) + SashForm sashForm1 = new SashForm(mContents, SWT.VERTICAL); + sashForm1.setBackground(darkGray); + sashForm1.SASH_WIDTH = 3; + GridData data = new GridData(GridData.FILL_BOTH); + sashForm1.setLayoutData(data); + + // Create the timeline view + new TimeLineView(sashForm1, reader, selectionController); + + // Create the profile view + new ProfileView(sashForm1, reader, selectionController).setMethodHandler(this); + } catch (IOException e) { + Label l = new Label(parent, 0); + l.setText("Failed to read the stack trace."); + + Status status = new Status(IStatus.ERROR, TraceviewPlugin.PLUGIN_ID, + "Failed to read the stack trace.", e); + TraceviewPlugin.getDefault().getLog().log(status); + } + + mParent.layout(); + } + + @Override + public void setFocus() { + mParent.setFocus(); + } + + // ---- MethodHandler methods + + @Override + public void handleMethod(MethodData method) { + String methodName = method.getMethodName(); + String className = method.getClassName().replaceAll("/", "."); //$NON-NLS-1$ //$NON-NLS-2$ + String fqmn = className + "." + methodName; //$NON-NLS-1$ + + JavaSourceRevealer.revealMethod(fqmn, null, -1, null); + } +} |