diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/FilteredEventsModel.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/FilteredEventsModel.java index f3764b622a..418e45f2ea 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/FilteredEventsModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/FilteredEventsModel.java @@ -348,7 +348,7 @@ public final class FilteredEventsModel { * range and pass the requested filter, using the given aggregation * to control the grouping of events */ - public List getEventClusters(ZoomParams params) { + public List getEventStripes(ZoomParams params) { return repo.getEventStripes(params); } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventBundleNodeBase.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventBundleNodeBase.java index 6ff8a44087..f39840ae8f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventBundleNodeBase.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventBundleNodeBase.java @@ -30,9 +30,7 @@ import java.util.stream.Collectors; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; -import javafx.application.Platform; import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ObservableValue; import javafx.concurrent.Task; import javafx.geometry.Insets; import javafx.geometry.Orientation; @@ -104,7 +102,7 @@ public abstract class EventBundleNodeBase descLOD = new SimpleObjectProperty<>(); - final SimpleObjectProperty descVisibility = new SimpleObjectProperty<>(DescriptionVisibility.SHOWN); + final SimpleObjectProperty descVisibility = new SimpleObjectProperty<>(); protected final BundleType eventBundle; protected final ParentNodeType parentNode; @@ -150,9 +148,13 @@ public abstract class EventBundleNodeBase { - chart.requestChartLayout(); - }); + + /* + * This triggers the layout when a mousover causes the action buttons to + * interesect with another node, forcing it down. + */ + heightProperty().addListener(heightProp -> chart.requestChartLayout()); + setMaxHeight(USE_PREF_SIZE); setMinWidth(USE_PREF_SIZE); setMaxWidth(USE_PREF_SIZE); @@ -176,11 +178,7 @@ public abstract class EventBundleNodeBase { - /* - * defer tooltip content creation till needed, this had a - * surprisingly large impact on speed of loading the chart - */ - installTooltip(); + Tooltip.uninstall(chart, AbstractVisualizationPane.getDefaultTooltip()); showHoverControls(true); toFront(); @@ -194,11 +192,8 @@ public abstract class EventBundleNodeBase observable, DescriptionVisibility oldValue, DescriptionVisibility newValue) -> { - setDescriptionVisibiltiyImpl(newValue); - }); - setDescriptionVisibiltiyImpl(DescriptionVisibility.SHOWN); - + descVisibility.addListener(observable -> setDescriptionVisibiltiyImpl(descVisibility.get())); + descVisibility.set(DescriptionVisibility.SHOWN); //trigger listener for initial value } final DescriptionLoD getDescriptionLoD() { @@ -215,6 +210,17 @@ public abstract class EventBundleNodeBase new DropShadow(-10, eventType.getColor())); setEffect(showControls ? dropShadow : null); + installTooltip(); enableTooltip(showControls); if (parentNode != null) { - parentNode.enableTooltip(false); parentNode.showHoverControls(false); } - } final EventType getEventType() { @@ -366,12 +371,15 @@ public abstract class EventBundleNodeBase Platform.runLater(chart::requestChartLayout)); + timeline.setOnFinished(finished -> chart.requestChartLayout()); timeline.play(); } + } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java index 371f70e8b9..fd2e563d44 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java @@ -18,16 +18,15 @@ */ package org.sleuthkit.autopsy.timeline.ui.detailview; +import com.google.common.collect.Lists; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import static java.util.Objects.nonNull; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.stream.Collectors; import javafx.beans.binding.Bindings; import javafx.concurrent.Task; -import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.scene.Cursor; @@ -71,8 +70,20 @@ final public class EventClusterNode extends EventBundleNodeBase - subNodes.stream().anyMatch(subNode -> - bundle.equals(subNode.getEventStripe())) - ); + chart.getEventStripes().removeAll(Lists.transform(subNodes, EventStripeNode::getEventStripe)); subNodes.clear(); /* @@ -169,29 +175,22 @@ final public class EventClusterNode extends EventBundleNodeBase call() throws Exception { - Collection bundles = null; + Collection bundles; DescriptionLoD next = loadedDescriptionLoD; do { loadedDescriptionLoD = next; if (loadedDescriptionLoD == getEventBundle().getDescriptionLoD()) { return Collections.emptySet(); } - bundles = eventsModel.getEventClusters(zoomParams.withDescrLOD(loadedDescriptionLoD)).stream() - .collect(Collectors.toMap(EventStripe::getDescription, //key - eventStripe -> eventStripe.withParent(getEventCluster()), //value - EventStripe::merge) //merge method - ).values(); + bundles = eventsModel.getEventStripes(zoomParams.withDescrLOD(loadedDescriptionLoD)); next = loadedDescriptionLoD.withRelativeDetail(relativeDetail); } while (bundles.size() == 1 && nonNull(next)); - // return list of AbstractEventStripeNodes representing sub-bundles return bundles; - } @Override protected void succeeded() { - try { Collection bundles = get(); @@ -203,7 +202,6 @@ final public class EventClusterNode extends EventBundleNodeBase { - final DescriptionLoD next = descLOD.get().moreDetailed(); - if (next != null) { + setEventHandler(actionEvent -> { + if (descLOD.get().moreDetailed() != null) { loadSubBundles(DescriptionLoD.RelativeDetail.MORE); } }); @@ -320,9 +317,8 @@ final public class EventClusterNode extends EventBundleNodeBase { - final DescriptionLoD previous = descLOD.get().lessDetailed(); - if (previous != null) { + setEventHandler(actionEvent -> { + if (descLOD.get().lessDetailed() != null) { loadSubBundles(DescriptionLoD.RelativeDetail.LESS); } }); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventDetailsChart.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventDetailsChart.java index 80f10c0279..5fb0047807 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventDetailsChart.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventDetailsChart.java @@ -493,9 +493,7 @@ public final class EventDetailsChart extends XYChart impl localMax = Math.max(yTop + h, localMax); if ((xLeft != bundleNode.getLayoutX()) || (yTop != bundleNode.getLayoutY())) { -// bundleNode.relocate(xLeft, yTop); -// requestChartLayout(); -// //animate node to new position + //animate node to new position bundleNode.animateTo(xLeft, yTop); } } @@ -517,7 +515,7 @@ public final class EventDetailsChart extends XYChart impl @Override public void requestChartLayout() { - super.requestChartLayout(); //To change body of generated methods, choose Tools | Templates. + super.requestChartLayout(); } private double getXForEpochMillis(Long millis) { @@ -647,9 +645,7 @@ public final class EventDetailsChart extends XYChart impl DescriptionFilter descriptionFilter = getController().getQuickHideFilters().stream() .filter(testFilter::equals) .findFirst().orElseGet(() -> { - testFilter.selectedProperty().addListener((Observable observable) -> { - requestChartLayout(); - }); + testFilter.selectedProperty().addListener(observable -> requestChartLayout()); getController().getQuickHideFilters().add(testFilter); return testFilter; }); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java index 9620fcabdd..101b54e67c 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java @@ -42,7 +42,7 @@ import static org.sleuthkit.autopsy.timeline.ui.detailview.EventBundleNodeBase.c final public class EventStripeNode extends EventBundleNodeBase { private static final Logger LOGGER = Logger.getLogger(EventStripeNode.class.getName()); - final Button hideButton; + private Button hideButton; /** * Pane that contains EventStripeNodes for any 'subevents' if they are * displayed @@ -53,16 +53,22 @@ final public class EventStripeNode extends EventBundleNodeBase