+ /**
+ * 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();
+ }
+ }
+