diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index fcc95938e3..cf6d1ac690 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -438,8 +438,8 @@ public class TimeLineController { setEventsDBStale(false); filteredEvents.postDBUpdated(); } - - if (file == null && artifact==null) { + + if (file == null && artifact == null) { SwingUtilities.invokeLater(this::showWindow); TimeLineController.this.showFullRange(); } else { @@ -481,7 +481,7 @@ public class TimeLineController { * timeline when done. */ @ThreadConfined(type = ThreadConfined.ThreadType.JFX) - void rebuildTagsTable(AbstractFile file,BlackboardArtifact artifact) { + void rebuildTagsTable(AbstractFile file, BlackboardArtifact artifact) { rebuildRepoHelper(eventsRepository::rebuildTags, false, file, artifact); } @@ -503,7 +503,8 @@ public class TimeLineController { pushTimeRange(interval); } if (eventIDs != null) { - selectEventIDs(eventIDs, () -> setViewMode(ViewMode.LIST)); + setViewMode(ViewMode.LIST); + selectEventIDs(eventIDs); } } } @@ -651,34 +652,8 @@ public class TimeLineController { } public void selectEventIDs(Collection events) { - selectEventIDs(events, () -> { - } - ); - } - - public void selectEventIDs(Collection events, Runnable andThen) { - final LoggedTask selectEventIDsTask = new LoggedTask("Select Event IDs", true) { //NON-NLS - @Override - protected Interval call() throws Exception { - return filteredEvents.getSpanningInterval(events); - } - - @Override - protected void succeeded() { - super.succeeded(); - try { - synchronized (TimeLineController.this) { - selectedTimeRange.set(get()); - selectedEventIDs.setAll(events); - andThen.run(); - } - } catch (InterruptedException | ExecutionException ex) { - LOGGER.log(Level.SEVERE, getTitle() + " Unexpected error", ex); //NON-NLS - } - } - }; - - monitorTask(selectEventIDsTask); + selectedTimeRange.set(filteredEvents.getSpanningInterval(events)); + selectedEventIDs.setAll(events); } /** diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java index 7f6a2efe14..6f4920f2bc 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java @@ -74,7 +74,7 @@ public abstract class AbstractTimeLineView extends BorderPane { */ private Task updateTask; - private final TimeLineController controller; + public final TimeLineController controller; private final FilteredEventsModel filteredEvents; /** diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java index 28f2e2f517..0c5351c684 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java @@ -251,20 +251,8 @@ class ListTimeline extends BorderPane { .map(CombinedEvent::getRepresentativeEventID) .collect(Collectors.toSet())); }); - - Platform.runLater(new Runnable() { - - @Override - public void run() { - Set collect = table.getItems().stream() - .filter(combinedEvent -> combinedEvent.getEventIDs().stream().anyMatch(controller.getSelectedEventIDs()::contains)) - .collect(Collectors.toSet()); - selectEvents(collect); - } - }); - - + selectEvents(controller.getSelectedEventIDs()); } /** @@ -298,17 +286,25 @@ class ListTimeline extends BorderPane { /** * Set the combined events that are selected in this view. * - * @param selectedEvents The events that should be selected. + * @param selectedEventIDs The events that should be selected. */ - void selectEvents(Collection selectedEvents) { + void selectEvents(Collection selectedEventIDs) { table.getSelectionModel().clearSelection(); - if (selectedEvents.isEmpty() == false) { - CombinedEvent firstSelected = selectedEvents.stream().filter(Objects::nonNull).min(Comparator.comparing(CombinedEvent::getStartMillis)).orElse(null); - table.scrollTo(firstSelected); - Set selectedIndices = selectedEvents.stream() + if (selectedEventIDs.isEmpty() == false) { + List selectedCombinedEvents = table.getItems().stream() + .filter(combinedEvent -> combinedEvent.getEventIDs().stream().anyMatch(selectedEventIDs::contains)) + .sorted(Comparator.comparing(CombinedEvent::getStartMillis)) + .collect(Collectors.toList()); + + if (selectedCombinedEvents.size() > 0) { + CombinedEvent firstSelected = selectedCombinedEvents.get(0); + table.scrollTo(firstSelected); + } + Set selectedIndices = selectedCombinedEvents.stream() .map(table.getItems()::indexOf) .filter(index -> index >= 0) .collect(Collectors.toSet()); + Integer[] indices = selectedIndices.toArray(new Integer[selectedIndices.size()]); if (indices.length >= 1) { table.getSelectionModel().selectIndices(indices[0], ArrayUtils.toPrimitive(indices)); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListViewPane.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListViewPane.java index b7688f0d82..882fe00770 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListViewPane.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListViewPane.java @@ -19,9 +19,9 @@ package org.sleuthkit.autopsy.timeline.ui.listvew; import com.google.common.collect.ImmutableList; -import java.util.HashSet; import java.util.List; import javafx.application.Platform; +import javafx.collections.ObservableList; import javafx.concurrent.Task; import javafx.scene.Node; import org.joda.time.Interval; @@ -46,6 +46,7 @@ public class ListViewPane extends AbstractTimeLineView { */ public ListViewPane(TimeLineController controller) { super(controller); + listTimeline = new ListTimeline(controller); //initialize chart; @@ -104,7 +105,7 @@ public class ListViewPane extends AbstractTimeLineView { FilteredEventsModel eventsModel = getEventsModel(); //grab the currently selected event - HashSet selectedEvents = new HashSet<>(listTimeline.getSelectedEvents()); + ObservableList selectedEventIDs = getController().getSelectedEventIDs(); //clear the chart and set the time range. resetView(eventsModel.getTimeRange()); @@ -118,7 +119,7 @@ public class ListViewPane extends AbstractTimeLineView { //put the combined events into the table. listTimeline.setCombinedEvents(combinedEvents); //restore the selected events - listTimeline.selectEvents(selectedEvents); + listTimeline.selectEvents(selectedEventIDs); }); return combinedEvents.isEmpty() == false;