+
+ IAction previousEventAction = new SearchEventAction(false, PackageMessages.ControlFlowView_PreviousEventJobName);
+ previousEventAction.setText(PackageMessages.ControlFlowView_PreviousEventActionName);
+ previousEventAction.setToolTipText(PackageMessages.ControlFlowView_PreviousEventActionTooltip);
+ previousEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(PREV_EVENT_ICON_PATH));
+ manager.add(previousEventAction);
+
+ IAction nextEventAction = new SearchEventAction(true, PackageMessages.ControlFlowView_NextEventJobName);
+ nextEventAction.setText(PackageMessages.ControlFlowView_NextEventActionName);
+ nextEventAction.setToolTipText(PackageMessages.ControlFlowView_NextEventActionTooltip);
+ nextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(NEXT_EVENT_ICON_PATH));
+ manager.add(nextEventAction);
+ }
+
+ @Override
+ protected void fillLocalMenu(IMenuManager manager) {
+ super.fillLocalMenu(manager);
+ final MenuManager item = new MenuManager(Messages.ControlFlowView_threadPresentation);
+ fFlatAction = createFlatAction();
+ item.add(fFlatAction);
+
+ fHierarchicalAction = createHierarchicalAction();
+ item.add(fHierarchicalAction);
+ manager.add(item);
+
+ }
+
+ /**
+ * Base Action for the "Go to Next/Previous Event for thread" actions
+ */
+ private class SearchEventAction extends Action {
+
+ private final boolean ifDirection;
+ private final String ifJobName;
+
+ /**
+ * Constructor
+ *
+ * @param direction
+ * The direction of the search, "true" for forwards and
+ * "false" for backwards.
+ * @param jobName
+ * The name of the job that will be spawned
+ */
+ public SearchEventAction(boolean direction, String jobName) {
+ ifDirection = direction;
+ ifJobName = jobName;
+ }
+
+ @Override
+ public void run() {
+ TimeGraphControl ctrl = getTimeGraphViewer().getTimeGraphControl();
+
+ ITimeGraphEntry traceEntry = ctrl.getSelectedTrace();
+ long ts = ctrl.getTimeDataProvider().getSelectionBegin();
+ ITmfTimestamp ts2 = TmfTraceManager.getInstance().getCurrentTraceContext().getSelectionRange().getStartTime();
+ ITimeEvent selectedState = Utils.findEvent(traceEntry, ts, 0);
+
+ if (selectedState == null) {
+ return;
+ }
+ ITimeGraphEntry entry = selectedState.getEntry();
+ if (!(entry instanceof ControlFlowEntry)) {
+ return;
+ }
+ ControlFlowEntry cfEntry = (ControlFlowEntry) entry;
+ int tid = cfEntry.getThreadId();
+
+ Job job = new Job(ifJobName) {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ ITmfTrace trace = cfEntry.getTrace();
+ ITmfContext ctx = trace.seekEvent(ts2);
+ long rank = ctx.getRank();
+
+ Predicate<@NonNull ITmfEvent> predicate = event -> {
+ Integer eventTid = KernelTidAspect.INSTANCE.resolve(event);
+ return (eventTid != null && eventTid.intValue() == tid);
+ };
+
+ ITmfEvent event = (ifDirection ?
+ TmfTraceUtils.getNextEventMatching(cfEntry.getTrace(), rank, predicate) :
+ TmfTraceUtils.getPreviousEventMatching(cfEntry.getTrace(), rank, predicate));
+ if (event != null) {
+ TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(this, event.getTimestamp()));
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+ }
+ }
+
+ private IAction createHierarchicalAction() {
+ IAction action = new Action(Messages.ControlFlowView_hierarchicalViewLabel, IAction.AS_RADIO_BUTTON) {
+ @Override
+ public void run() {
+ ITmfTrace parentTrace = getTrace();
+ synchronized (fFlatTraces) {
+ fFlatTraces.remove(parentTrace);
+ for (ITmfTrace trace : TmfTraceManager.getTraceSet(parentTrace)) {
+ final ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+ for (TimeGraphEntry traceEntry : getEntryList(ss)) {
+ List<ControlFlowEntry> currentRootList = traceEntry.getChildren().stream()
+ .filter(e -> e instanceof ControlFlowEntry)
+ .map(e -> (ControlFlowEntry) e).collect(Collectors.toList());
+ addEntriesToHierarchicalTree(currentRootList, traceEntry);
+ }
+ }
+ }
+ refresh();
+ }
+ };
+ action.setChecked(true);
+ action.setToolTipText(Messages.ControlFlowView_hierarchicalViewToolTip);
+ return action;
+ }
+
+ private IAction createFlatAction() {
+ IAction action = new Action(Messages.ControlFlowView_flatViewLabel, IAction.AS_RADIO_BUTTON) {
+ @Override
+ public void run() {
+ ITmfTrace parentTrace = getTrace();
+ synchronized (fFlatTraces) {
+ fFlatTraces.add(parentTrace);
+ for (ITmfTrace trace : TmfTraceManager.getTraceSet(parentTrace)) {
+ final ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+ for (TimeGraphEntry traceEntry : getEntryList(ss)) {
+ hierarchicalToFlatTree(traceEntry);
+ }
+ }
+ }
+ refresh();
+ }
+ };
+ action.setToolTipText(Messages.ControlFlowView_flatViewToolTip);
+ return action;