/*******************************************************************************
* Copyright (c) 2017 Rogue Wave Software Inc. 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:
* Rogue Wave Software Inc. - initial implementation
*******************************************************************************/
package org.eclipse.php.profile.ui.views;
import java.util.ArrayList;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.php.profile.core.data.ProfilerCallTrace;
import org.eclipse.php.profile.core.data.ProfilerCallTraceLayer;
import org.eclipse.php.profile.core.engine.IProfileSessionListener;
import org.eclipse.php.profile.core.engine.ProfileSessionsManager;
import org.eclipse.php.profile.core.engine.ProfilerDB;
import org.eclipse.php.profile.ui.PHPProfileUIMessages;
import org.eclipse.php.profile.ui.actions.ExecutionFlowActionGroup;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
/**
* Execution flow view.
*/
public class ExecutionFlowView extends AbstractProfilerFunctionsView
implements IDoubleClickListener, IMenuListener, IProfileSessionListener {
private TreeViewer fViewer;
private String fColumnHeaders[] = new String[] { PHPProfileUIMessages.getString("ExecutionFlowView_0"), //$NON-NLS-1$
PHPProfileUIMessages.getString("ExecutionFlowView_1"), //$NON-NLS-1$
PHPProfileUIMessages.getString("ExecutionFlowView_2"), //$NON-NLS-1$
PHPProfileUIMessages.getString("ExecutionFlowView_3") //$NON-NLS-1$
};
private int[] fColumnWidths = new int[] { 300, 200, 150, 150 };
private int[] fNumericColumns = new int[] { 2, 3 };
private ExecutionFlowActionGroup fActionSet;
private Tree fTree;
private Menu fContextMenu;
private ProfilerDB fProfilerDB;
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.
* widgets.Composite)
*/
public void createPartControl(Composite parent) {
fTree = new Tree(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
fTree.setLinesVisible(true);
fTree.setHeaderVisible(true);
for (int i = 0; i < fColumnHeaders.length; ++i) {
TreeColumn tableColumn = new TreeColumn(fTree, SWT.LEFT, i);
tableColumn.setText(fColumnHeaders[i]);
tableColumn.setWidth(fColumnWidths[i]);
for (int c = 0; c < fNumericColumns.length; ++c) {
if (fNumericColumns[c] == i) {
tableColumn.setAlignment(SWT.RIGHT);
break;
}
}
}
fViewer = new TreeViewer(fTree);
fViewer.setContentProvider(new ExecutionFlowContentProvider());
fViewer.setLabelProvider(new ExecutionFlowLabelProvider());
fViewer.addDoubleClickListener(this);
fActionSet = new ExecutionFlowActionGroup(this);
fActionSet.fillActionBars(getViewSite().getActionBars());
hookContextMenu();
ProfileSessionsManager.addProfileSessionListener(this);
setInput(ProfileSessionsManager.getCurrent());
// TODO - help context
// parent.setData(WorkbenchHelpSystem.HELP_KEY,
// IStudioHelpContextIds.EXECUTION_FLOW_VIEW);
// parent.addHelpListener(new HelpListener() {
// public void helpRequested(HelpEvent arg0) {
// org.eclipse.swt.program.Program
// .launch(IStudioHelpContextIds.EXECUTION_FLOW_VIEW);
// }
// });
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#dispose()
*/
public void dispose() {
if (fViewer != null) {
fViewer.removeDoubleClickListener(this);
}
ProfileSessionsManager.removeProfileSessionListener(this);
super.dispose();
}
public void setFocus() {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.php.profile.ui.views.AbstractProfilerView#getInput()
*/
public ProfilerDB getInput() {
return fProfilerDB;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.php.profile.ui.views.AbstractProfilerView#setInput(org.
* eclipse. php.profile.core.profiler.ProfilerDB)
*/
public void setInput(ProfilerDB profilerDB) {
if (fViewer == null || fViewer.getContentProvider() == null) {
return;
}
if (fProfilerDB != profilerDB) {
if (profilerDB != null) {
ProfilerCallTrace callTrace = profilerDB.getCallTrace();
if (callTrace != null) {
ProfilerCallTraceLayer[] layers = callTrace.getLayers();
ExecutionFlowTreeElement current = null;
ExecutionFlowTreeElement root = new ExecutionFlowTreeElement();
ArrayList<ExecutionFlowTreeElement> elements = new ArrayList<ExecutionFlowTreeElement>();
for (int i = 0; i < layers.length; ++i) {
if (layers[i].getType() == ProfilerCallTraceLayer.ENTER) { // enter
// function
ExecutionFlowTreeElement element = new ExecutionFlowTreeElement(i);
element.setData(profilerDB.getFunctionData(layers[i].getCalledID()));
element.setLayer(layers[i]);
if (current != null) {
current.addChild(element);
element.setParent(current);
}
current = element;
elements.add(element);
} else { // exit function
if (current != null) {
ProfilerCallTraceLayer currentLayer = (ProfilerCallTraceLayer) current.getLayer();
currentLayer.setDuration(layers[i].getTimestampSeconds(),
layers[i].getTimestampMicroseconds());
current.setDuration(currentLayer.getDurationInMilli());
if (current.getParent() != null) {
current = (ExecutionFlowTreeElement) current.getParent();
}
}
}
}
if (current != null) { // current element is a top element
// (main
// function)
double totalDuration = profilerDB.getGlobalData().getGlobalTimeInMilli();
for (int i = 0; i < elements.size(); ++i) {
ExecutionFlowTreeElement element = (ExecutionFlowTreeElement) elements.get(i);
element.setTimePercentage(element.getDuration() / totalDuration * 100);
}
root.addChild(current);
current.setParent(root);
fViewer.setInput(root);
}
}
} else {
fViewer.setInput(null);
}
fViewer.getControl().setRedraw(false);
fViewer.refresh();
fViewer.getControl().setRedraw(true);
fProfilerDB = profilerDB;
}
}
public void doubleClick(DoubleClickEvent event) {
fActionSet.viewFunctionCallInEditor(event.getSelection());
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.php.profile.ui.views.AbstractProfilerFunctionsView#getViewer(
* )
*/
public TreeViewer getViewer() {
return fViewer;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ITreeViewerListener#treeCollapsed(org.eclipse
* .jface.viewers.TreeExpansionEvent)
*/
public void treeCollapsed(TreeExpansionEvent event) {
TreeElement element = (TreeElement) event.getElement();
element.setExpanded(false);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ITreeViewerListener#treeExpanded(org.eclipse
* .jface.viewers.TreeExpansionEvent)
*/
public void treeExpanded(TreeExpansionEvent event) {
TreeElement element = (TreeElement) event.getElement();
element.setExpanded(true);
}
public void hookContextMenu() {
MenuManager menuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuManager.setRemoveAllWhenShown(true);
menuManager.addMenuListener(this);
fContextMenu = menuManager.createContextMenu(fTree);
fTree.setMenu(fContextMenu);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface
* .action.IMenuManager)
*/
public void menuAboutToShow(IMenuManager manager) {
fActionSet.fillContextMenu(manager);
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.php.profile.core.profiler.IProfileSessionListener#
* currentSessionChanged(org.eclipse.php.profile.core.profiler.ProfilerDB)
*/
public void currentSessionChanged(final ProfilerDB current) {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
setInput(current);
}
});
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.php.profile.core.profiler.IProfileSessionListener#
* profileSessionAdded(org.eclipse.php.profile.core.profiler.ProfilerDB)
*/
public void profileSessionAdded(ProfilerDB db) {
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.php.profile.core.profiler.IProfileSessionListener#
* profileSessionRemoved(org.eclipse.php.profile.core.profiler.ProfilerDB)
*/
public void profileSessionRemoved(ProfilerDB db) {
}
}