package com.mobilesorcery.sdk.profiling.ui.views;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.ILocationProvider;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.statushandlers.StatusManager;
import com.mobilesorcery.sdk.core.IFilter;
import com.mobilesorcery.sdk.core.ParseException;
import com.mobilesorcery.sdk.core.Util;
import com.mobilesorcery.sdk.profiling.IInvocation;
import com.mobilesorcery.sdk.profiling.IProfilingListener;
import com.mobilesorcery.sdk.profiling.IProfilingSession;
import com.mobilesorcery.sdk.profiling.ProfilingPlugin;
import com.mobilesorcery.sdk.profiling.ProfilingSessionEditorInput;
import com.mobilesorcery.sdk.profiling.ProfilingSessionParser;
import com.mobilesorcery.sdk.profiling.filter.NameFilter;
import com.mobilesorcery.sdk.profiling.ui.ProfilingUiPlugin;
import com.mobilesorcery.sdk.ui.CollapseAllAction;
import com.mobilesorcery.sdk.ui.DescriptiveTextFieldListener;
import com.mobilesorcery.sdk.ui.ExpandAllAction;
import com.mobilesorcery.sdk.ui.UIUtils;
public class ProfilingEditor extends EditorPart {
public final static String ID = "com.mobilesorcery.sdk.profiling.ui.profiling";
public class ProfilingListener implements IProfilingListener {
public void handleEvent(final ProfilingEventType eventType, final IProfilingSession session) {
if (hotspotProfilingComposite != null) {
hotspotProfilingComposite.getDisplay().asyncExec(new Runnable() {
public void run() {
if (eventType == ProfilingEventType.STARTED) {
initSessionsCombo();
sessionsList.setSelection(new StructuredSelection(session), true);
} else if (eventType == ProfilingEventType.STOPPED) {
updateProfilingComposites(session);
}
}
});
}
}
}
private ProfilingComposite hotspotProfilingComposite;
private ProfilingListener profilingEventListener;
private ProfilingComposite callTreeProfilingComposite;
private ComboViewer sessionsList;
private Composite toolComposite;
private ExpandAllAction expandAllAction;
private CollapseAllAction collapseAllAction;
protected ProfilingComposite currentProfilingView;
private Text filter;
private List<IProfilingSession> sessions = new ArrayList<IProfilingSession>();
private boolean trackProfilingHistory = false;
private IPath path;
private DescriptiveTextFieldListener filterDescription;
public ProfilingEditor() {
profilingEventListener = new ProfilingListener();
}
public void createPartControl(Composite parent) {
Composite main = new Composite(parent, SWT.NONE);
main.setLayout(new GridLayout(2, false));
toolComposite = new Composite(main, SWT.NONE);
toolComposite.setLayout(new GridLayout(2, false));
toolComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Composite sessionComposite = new Composite(toolComposite, SWT.NONE);
sessionComposite.setLayout(new GridLayout(2, false));
Label sessionsLabel = new Label(sessionComposite, SWT.NONE);
sessionsLabel.setText("&Sessions:");
sessionsList = new ComboViewer(sessionComposite);
sessionsList.setLabelProvider(new ProfilingSessionLabelProvider());
sessionsList.setContentProvider(new ArrayContentProvider());
sessionsList.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IProfilingSession session = (IProfilingSession) ((IStructuredSelection)event.getSelection()).getFirstElement();
updateProfilingComposites(session);
if (filterDescription != null) {
filterDescription.setText("");
}
}
});
filter = new Text(toolComposite, SWT.BORDER | SWT.SINGLE);
GridData filterData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
filterData.widthHint = UIUtils.getDefaultFieldSize();
filter.setLayoutData(filterData);
filterDescription = new DescriptiveTextFieldListener(filter, "Quick Filter");
CTabFolder results = new CTabFolder(main, SWT.BOTTOM | SWT.BORDER);
results.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
final CTabItem hotSpotTab = new CTabItem(results, SWT.NONE);
hotSpotTab.setText("Hotspots");
final CTabItem callTreeTab = new CTabItem(results, SWT.NONE);
callTreeTab.setText("Call Tree");
hotspotProfilingComposite = new ProfilingComposite(results, SWT.FLAT);
hotspotProfilingComposite.setStatusLineManager(getEditorSite().getActionBars().getStatusLineManager());
hotSpotTab.setControl(hotspotProfilingComposite);
hotSpotTab.setImage(ProfilingUiPlugin.getDefault().getImageRegistry().get(ProfilingUiPlugin.HOTSPOTS_TAB_IMG));
callTreeProfilingComposite = new ProfilingComposite(results, SWT.NONE);
callTreeProfilingComposite.setStatusLineManager(getEditorSite().getActionBars().getStatusLineManager());
callTreeTab.setControl(callTreeProfilingComposite);
callTreeTab.setImage(ProfilingUiPlugin.getDefault().getImageRegistry().get(ProfilingUiPlugin.CALL_TREE_TAB_IMG));
results.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
if (e.item == hotSpotTab) {
currentProfilingView = hotspotProfilingComposite;
} else if (e.item == callTreeTab) {
currentProfilingView = callTreeProfilingComposite;
}
updateActionBars();
}
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
results.setSelection(hotSpotTab);
filter.addListener(SWT.Modify, new Listener() {
public void handleEvent(Event event) {
IFilter<IInvocation> nameFilter;
try {
nameFilter = NameFilter.create(filterDescription.getText(), NameFilter.Criteria.NAME, NameFilter.MatchType.CONTAINS, true);
hotspotProfilingComposite.setFilter(nameFilter, false);
callTreeProfilingComposite.setFilter(nameFilter, true);
} catch (ParseException e) {
// TODO: Flag in ui!??
}
}
});
ProfilingPlugin.getDefault().addProfilingListener(profilingEventListener);
initSessionsCombo();
initActionBars();
}
public void doSave(IProgressMonitor monitor) {
}
public void doSaveAs() {
FileDialog dialog = new FileDialog(getEditorSite().getShell(), SWT.SAVE);
dialog.setFilterExtensions(new String[] { "prof" });
dialog.setFilterNames(new String[] { "MoSync Profiling Data Files" });
String file = dialog.open();
if (file != null) {
try {
if (path != null) {
// This was a profiling session on-file
Util.copy(null, path.toFile(), new File(file), null);
} else {
ProfilingSessionParser parser = new ProfilingSessionParser();
parser.unparse(sessions, new File(file));
}
} catch (Exception e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, ProfilingUiPlugin.PLUGIN_ID, e.getMessage(), e), StatusManager.SHOW);
}
path = new Path(new File(file).getAbsolutePath());
setPartName(computePartName());
}
}
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
setSite(site);
setInput(input);
if (input instanceof ProfilingSessionEditorInput) {
sessions = Arrays.asList(((ProfilingSessionEditorInput) input).getSession());
} else if (input instanceof IAdaptable) {
path = getPath(input);
ProfilingSessionParser parser = new ProfilingSessionParser();
try {
sessions = Arrays.asList(parser.parse(path.toFile()));
} catch (Exception e) {
throw new PartInitException(new Status(IStatus.ERROR, ProfilingUiPlugin.PLUGIN_ID, e.getMessage(), e));
}
}
setPartName(computePartName());
}
private IPath getPath(IEditorInput input) {
ILocationProvider location = (ILocationProvider) ((IAdaptable) input).getAdapter(ILocationProvider.class);
IPath path = location == null ? null : location.getPath(input);
return path;
}
private String computePartName() {
if (path != null) {
return path.lastSegment();
}
if (sessions.size() == 1) {
// Support for more soon
return sessions.get(0).getName();
}
return getPartName();
}
public int getSessionCount() {
return sessions.size();
}
public boolean isDirty() {
return false;
}
public boolean isSaveAsAllowed() {
return true;
}
private void initActionBars() {
IToolBarManager tbMgr = getEditorSite().getActionBars().getToolBarManager();
expandAllAction = new ExpandAllAction();
expandAllAction.setToolTipText("Expand all profiling nodes");
collapseAllAction = new CollapseAllAction();
collapseAllAction.setToolTipText("Collapse all profiling nodes");
tbMgr.add(expandAllAction);
tbMgr.add(collapseAllAction);
}
private void updateActionBars() {
if (currentProfilingView != null) {
expandAllAction.setViewer(currentProfilingView.getViewer());
collapseAllAction.setViewer(currentProfilingView.getViewer());
expandAllAction.setEnabled(!currentProfilingView.isFlat());
collapseAllAction.setEnabled(!currentProfilingView.isFlat());
}
}
protected void updateProfilingComposites(IProfilingSession session) {
hotspotProfilingComposite.setInput(session);
callTreeProfilingComposite.setInput(session);
}
private void initSessionsCombo() {
if (trackProfilingHistory) {
sessions = ProfilingPlugin.getDefault().getSessions();
}
sessionsList.setInput(sessions);
if (sessionsList.getSelection().isEmpty() && !sessions.isEmpty()) {
sessionsList.setSelection(new StructuredSelection(sessions.get(0)));
}
toolComposite.layout();
}
public void dispose() {
ProfilingPlugin.getDefault().removeProfilingListener(profilingEventListener);
super.dispose();
}
public void setFocus() {
hotspotProfilingComposite.setFocus();
}
}