blob: 6d07018cd2a030e983ed25af1da9eb06cc364d06 [file] [log] [blame]
/*
* 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);
}
}