blob: 9bf08e8f6cf7cd1f92905a2bc8b4dbc8b1dbf393 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
* Patrick Tasse - Support selection range
*******************************************************************************/
package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.test.stub.views;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.test.stub.adaption.TsfImplProvider;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.test.stub.model.EventImpl;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.test.stub.model.TraceImpl;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.test.stub.model.TraceModelImplFactory;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
@SuppressWarnings("javadoc")
public class TsfTraceAnalysisView extends ViewPart implements
ITimeGraphSelectionListener, ITimeGraphTimeListener, ITimeGraphRangeListener {
// ========================================================================
// Data
// ========================================================================
private TreeViewer viewer;
private DrillDownAdapter drillDownAdapter;
private Action action1;
private Action action2;
private Action resetScale;
private Action nextEvent;
private Action prevEvent;
private Action nextTrace;
private Action prevTrace;
private Action showLegent;
private Action zoomIn;
private Action zoomOut;
private Action events300K;
private Action doubleClickAction;
private TimeGraphViewer tsfviewer;
private TimeGraphViewer tsfviewer2;
private static SimpleDateFormat stimeformat = new SimpleDateFormat(
"yy/MM/dd HH:mm:ss");
private TraceModelImplFactory fact;
// ========================================================================
// Inner Classes
// ========================================================================
/*
* The content provider class is responsible for providing objects to the
* view. It can wrap existing objects in adapters or simply return objects
* as-is. These objects may be sensitive to the current input of the view,
* or ignore it and always show the same content (like Task List, for
* example).
*/
class TreeObject extends PlatformObject {
private final String name;
private TreeParent parent;
public TreeObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setParent(TreeParent parent) {
this.parent = parent;
}
public TreeParent getParent() {
return parent;
}
@Override
public String toString() {
return getName();
}
}
class TreeParent extends TreeObject {
private final ArrayList<TreeObject> children;
public TreeParent(String name) {
super(name);
children = new ArrayList<>();
}
public void addChild(TreeObject child) {
children.add(child);
child.setParent(this);
}
public void removeChild(TreeObject child) {
children.remove(child);
child.setParent(null);
}
public TreeObject[] getChildren() {
return children.toArray(new TreeObject[children
.size()]);
}
public boolean hasChildren() {
return children.size() > 0;
}
}
class ViewContentProvider implements ITreeContentProvider {
private TreeParent invisibleRoot;
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
@Override
public void dispose() {
}
@Override
public Object[] getElements(Object parent) {
if (parent.equals(getViewSite())) {
if (invisibleRoot == null) {
initialize();
}
return getChildren(invisibleRoot);
}
return getChildren(parent);
}
@Override
public Object getParent(Object child) {
if (child instanceof TreeObject) {
return ((TreeObject) child).getParent();
}
return null;
}
@Override
public Object[] getChildren(Object parent) {
if (parent instanceof TreeParent) {
return ((TreeParent) parent).getChildren();
}
return new Object[0];
}
@Override
public boolean hasChildren(Object parent) {
if (parent instanceof TreeParent) {
return ((TreeParent) parent).hasChildren();
}
return false;
}
/*
* We will set up a dummy model to initialize tree heararchy. In a real
* code, you will connect to a real model and expose its hierarchy.
*/
private void initialize() {
TreeObject to1 = new TreeObject("Leaf 1");
TreeObject to2 = new TreeObject("Leaf 2");
TreeObject to3 = new TreeObject("Leaf 3");
TreeParent p1 = new TreeParent("Parent 1");
p1.addChild(to1);
p1.addChild(to2);
p1.addChild(to3);
TreeObject to4 = new TreeObject("Leaf 4");
TreeParent p2 = new TreeParent("Parent 2");
p2.addChild(to4);
TreeParent root = new TreeParent("Root");
root.addChild(p1);
root.addChild(p2);
invisibleRoot = new TreeParent("");
invisibleRoot.addChild(root);
}
}
static class ViewLabelProvider extends LabelProvider {
@Override
public String getText(Object obj) {
return obj.toString();
}
@Override
public Image getImage(Object obj) {
String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
if (obj instanceof TreeParent) {
imageKey = ISharedImages.IMG_OBJ_FOLDER;
}
return PlatformUI.getWorkbench().getSharedImages().getImage(
imageKey);
}
}
// ========================================================================
// Methods
// ========================================================================
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
@Override
public void createPartControl(Composite parent) {
final SashForm sashForm = new SashForm(parent, SWT.NONE);
final SashForm sashForm2 = new SashForm(sashForm, SWT.NONE);
tsfviewer = new TimeGraphViewer(sashForm2, SWT.NONE);
tsfviewer.setTimeGraphProvider(new TsfImplProvider());
tsfviewer2 = new TimeGraphViewer(sashForm2, SWT.NONE);
tsfviewer2.setTimeGraphProvider(new TsfImplProvider());
viewer = new TreeViewer(sashForm, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
drillDownAdapter = new DrillDownAdapter(viewer);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setComparator(new ViewerComparator());
viewer.setInput(getViewSite());
sashForm.setWeights(new int[] { 5, 1 });
sashForm2.setWeights(new int[] { 1, 1 });
fact = new TraceModelImplFactory();
ITimeGraphEntry[] traceArr = fact.createTraces();
tsfviewer.setInput(traceArr);
tsfviewer.addSelectionListener(this);
tsfviewer.addRangeListener(this);
tsfviewer.setTimeFormat(TimeFormat.CALENDAR);
tsfviewer2.setInput(traceArr);
tsfviewer2.addSelectionListener(this);
tsfviewer2.addRangeListener(this);
// tsfviewer2.setTimeFormat(TimeGraphViewer.timeFormat.epoch);
makeActions();
hookContextMenu();
hookDoubleClickAction();
contributeToActionBars();
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
TsfTraceAnalysisView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalPullDown(IMenuManager manager) {
manager.add(action1);
manager.add(new Separator());
manager.add(action2);
}
private void fillContextMenu(IMenuManager manager) {
manager.add(action1);
manager.add(action2);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(new Separator());
manager.add(resetScale);
manager.add(nextEvent);
manager.add(prevEvent);
manager.add(nextTrace);
manager.add(prevTrace);
manager.add(showLegent);
manager.add(zoomIn);
manager.add(zoomOut);
manager.add(events300K);
manager.add(new Separator());
drillDownAdapter.addNavigationActions(manager);
}
private TimeGraphViewer getActiveTsfCtrl() {
TimeGraphViewer inFocusViewer = null;
if (tsfviewer.isInFocus()) {
inFocusViewer = tsfviewer;
} else if (tsfviewer2.isInFocus()) {
inFocusViewer = tsfviewer2;
}
return inFocusViewer;
}
private void makeActions() {
// action1
action1 = new Action() {
@Override
public void run() {
showMessage("Action 1 executed");
}
};
action1.setText("Action 1");
action1.setToolTipText("Action 1 tooltip");
action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
// action2
action2 = new Action() {
@Override
public void run() {
showMessage("Action 2 executed");
}
};
action2.setText("Action 2");
action2.setToolTipText("Action 2 tooltip");
action2.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
// action4
resetScale = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.resetStartFinishTime();
}
}
};
resetScale.setText("Reset");
resetScale.setToolTipText("Reset the Time Scale to Default");
// action5
nextEvent = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.selectNextEvent(false);
}
}
};
nextEvent.setText("NextEv");
nextEvent.setToolTipText("Next Event");
// action6
prevEvent = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.selectPrevEvent(false);
}
}
};
prevEvent.setText("PrevEv");
prevEvent.setToolTipText("Previous Event");
// action7
nextTrace = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.selectNextItem();
}
}
};
nextTrace.setText("NextTrace");
nextTrace.setToolTipText("Select Next Trace");
// action8
prevTrace = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.selectPrevItem();
}
}
};
prevTrace.setText("PrevTrace");
prevTrace.setToolTipText("Select Previous Trace");
// action9
showLegent = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.showLegend();
}
}
};
showLegent.setText("Legend");
showLegent.setToolTipText("Show Legend");
// action10
zoomIn = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.zoomIn();
}
}
};
zoomIn.setText("Zoom In");
zoomIn.setToolTipText("Zoom In");
// action10
zoomOut = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
inFocusViewer.zoomOut();
}
// ISelection selection = inFocusViewer.getSelection();
// Object sel = null;
// if (selection != null && !selection.isEmpty()) {
// sel = ((IStructuredSelection) selection)
// .getFirstElement();
// if (sel instanceof EventImpl) {
// EventImpl event = (EventImpl) sel;
// inFocusViewer.selectNextEvent();
// }
// }
}
};
zoomOut.setText("Zoom Out");
zoomOut.setToolTipText("Zoom Out");
// action12
events300K = new Action() {
@Override
public void run() {
TimeGraphViewer inFocusViewer = getActiveTsfCtrl();
if (inFocusViewer != null) {
ITimeGraphEntry[] traceArr = fact
.createLargeTraces(60);
inFocusViewer.setInput(traceArr);
}
}
};
events300K.setText("300K Events");
events300K.setToolTipText("Add 300K Events");
doubleClickAction = new Action() {
@Override
public void run() {
ISelection selection = viewer.getSelection();
Object obj = ((IStructuredSelection) selection)
.getFirstElement();
showMessage("Double-click detected on " + obj.toString());
}
};
}
private void hookDoubleClickAction() {
viewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
doubleClickAction.run();
}
});
}
private void showMessage(String message) {
MessageDialog.openInformation(viewer.getControl().getShell(),
"TsfTrace Analysis View", message);
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
viewer.getControl().setFocus();
}
@Override
public void selectionChanged(TimeGraphSelectionEvent event) {
Object source = event.getSource();
if (source == null || !(source instanceof TimeGraphViewer)) {
return;
}
TimeGraphViewer rViewer = (TimeGraphViewer) event.getSource();
TimeGraphViewer synchViewer = null;
// Synchronize viewer selections if Enabled,
// make sure the selection does not go in loops
if (tsfviewer == rViewer) {
synchViewer = tsfviewer2;
} else {
synchViewer = tsfviewer;
}
Object selection = event.getSelection();
if (selection instanceof EventImpl) {
EventImpl selEvent = (EventImpl) selection;
System.out
.println("TsfTraceAnalysisView.selectionChanged() Selected Event: \nType: "
+ selEvent.getType().toString()
+ "\nTime: "
+ selEvent.getTime()
+ "\nTrace Name: "
+ selEvent.getEntry().getName());
synchViewer.setSelectedEvent(selEvent, source);
} else if (selection instanceof TraceImpl) {
TraceImpl selTrace = (TraceImpl) selection;
System.out
.println("TsfTraceAnalysisView.selectionChanged() Selected Trace: \nName: "
+ selTrace.getName().toString()
+ "\nClass Name: "
+ selTrace.getClassName());
synchViewer.setSelection(selTrace, true);
} else {
System.out
.println("TsfTmIncubatorListener.tsfTmProcessEvent() Unexpected event source received: "
+ selection.getClass().getName());
}
}
@Override
public void timeSelected(TimeGraphTimeEvent event) {
TimeGraphViewer rViewer = (TimeGraphViewer) event.getSource();
TimeGraphViewer synchViewer = null;
// Synchronize viewer selections if Enabled,
// make sure the selection does not go in loops
if (tsfviewer == rViewer) {
synchViewer = tsfviewer2;
} else {
synchViewer = tsfviewer;
}
long selTimens = event.getBeginTime();
long tms = (long) (selTimens * 1E-6);
Date date = new Date(tms);
String fDate = stimeformat.format(date);
String ns = formatNs(selTimens);
System.out.println("TsfTraceAnalysisView.timeSelected() Selected Event: \nTime: "
+ event.getBeginTime()
+ "\nSelected Time: "
+ selTimens + " " + fDate + " " + ns);
synchViewer.setSelectedTime(event.getBeginTime(), true);
}
@Override
public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
if (event == null) {
return;
}
Object source = event.getSource();
if (source == null || !(source instanceof TimeGraphViewer)) {
return;
}
TimeGraphRangeUpdateEvent rEvent = event;
TimeGraphViewer rViewer = (TimeGraphViewer) event
.getSource();
TimeGraphViewer synchViewer = null;
// Synchronize viewer selections if Enabled,
// make sure the selection does not go in loops
if (tsfviewer == rViewer) {
synchViewer = tsfviewer2;
} else {
synchViewer = tsfviewer;
}
synchViewer.setSelectVisTimeWindow(rEvent.getStartTime(), rEvent.getEndTime(), source);
}
/**
* Obtains the remainder fraction on unit Seconds of the entered value in
* nanoseconds. e.g. input: 1241207054171080214 ns The number of seconds can
* be obtain by removing the last 9 digits: 1241207054 the fractional
* portion of seconds, expressed in ns is: 171080214
*
* @param v
* @return
*/
public String formatNs(long v) {
StringBuffer str = new StringBuffer();
long val = v;
boolean neg = val < 0;
if (neg) {
val = -val;
str.append('-');
}
String strVal = String.valueOf(val);
if (val < 1000000000) {
return strVal;
}
// Extract the last nine digits (e.g. fraction of a S expressed in ns
return strVal.substring(strVal.length() - 9);
}
}