From bd9c9109e465ceb357d4f8592813e28fbfeb99eb Mon Sep 17 00:00:00 2001
From: jmillman <jmillman@basistech.com>
Date: Tue, 13 Oct 2015 16:41:50 -0400
Subject: [PATCH] adjust EventClusterNode subbundle loading

---
 .../ui/detailview/EventBundleNodeBase.java    |   6 +-
 .../ui/detailview/EventClusterNode.java       | 144 +++++++++---------
 .../ui/detailview/EventStripeNode.java        |   2 -
 .../timeline/zooming/DescriptionLoD.java      |   4 +-
 4 files changed, 75 insertions(+), 81 deletions(-)

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 69d757eae8..ee57b6fe0d 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventBundleNodeBase.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventBundleNodeBase.java
@@ -98,7 +98,7 @@ static void show(Node b, boolean show) {
 
     protected final EventDetailChart chart;
     final SimpleObjectProperty<DescriptionLoD> descLOD = new SimpleObjectProperty<>();
-    final SimpleObjectProperty<DescriptionVisibility> descVisibility= new SimpleObjectProperty<>(DescriptionVisibility.SHOWN);
+    final SimpleObjectProperty<DescriptionVisibility> descVisibility = new SimpleObjectProperty<>(DescriptionVisibility.SHOWN);
     protected final BundleType eventBundle;
 
     protected final ParentNodeType parentNode;
@@ -181,7 +181,7 @@ public EventBundleNodeBase(EventDetailChart chart, BundleType eventBundle, Paren
                 parentNode.showHoverControls(true);
             }
         });
-        
+
         setDescriptionVisibility(DescriptionVisibility.SHOWN);
         descVisibility.addListener((ObservableValue<? extends DescriptionVisibility> observable, DescriptionVisibility oldValue, DescriptionVisibility newValue) -> {
             setDescriptionVisibility(newValue);
@@ -331,7 +331,7 @@ protected void layoutChildren() {
     abstract void setDescriptionWidth(double w);
 
     void setDescriptionVisibilityLevel(DescriptionVisibility get) {
-      descVisibility.set(get);
+        descVisibility.set(get);
     }
 
 }
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 23d6b0a46e..f41be888ce 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventClusterNode.java
@@ -42,6 +42,7 @@
 import javafx.scene.layout.BorderStroke;
 import javafx.scene.layout.BorderStrokeStyle;
 import javafx.scene.layout.BorderWidths;
+import javafx.scene.layout.VBox;
 import org.controlsfx.control.action.Action;
 import org.controlsfx.control.action.ActionUtils;
 import org.joda.time.DateTime;
@@ -92,6 +93,7 @@ public EventClusterNode(EventDetailChart chart, EventCluster eventCluster, Event
         setAlignment(Pos.CENTER_LEFT);
         infoHBox.getChildren().addAll(minusButton, plusButton);
         getChildren().addAll(subNodePane, infoHBox);
+
     }
 
     @Override
@@ -138,90 +140,85 @@ public void setDescriptionVisibility(DescriptionVisibility descrVis) {
      */
     @NbBundle.Messages(value = "EventStripeNode.loggedTask.name=Load sub clusters")
     private synchronized void loadSubBundles(DescriptionLoD.RelativeDetail relativeDetail) {
+        chart.setCursor(Cursor.WAIT);
         chart.getEventBundles().removeIf(bundle ->
                 subNodes.stream().anyMatch(subNode ->
                         bundle.equals(subNode.getEventStripe()))
         );
-        subNodePane.getChildren().clear();
         subNodes.clear();
-        if (descLOD.get().withRelativeDetail(relativeDetail) == getEventBundle().getDescriptionLoD()) {
-            countLabel.setVisible(true);
-            descLOD.set(getEventBundle().getDescriptionLoD());
-            chart.layoutPlotChildren();
-        } else {
-            /*
-             * make new ZoomParams to query with
-             *
-             * We need to extend end time because for the query by one second,
-             * because it is treated as an open interval but we want to include
-             * events at exactly the time of the last event in this cluster
-             */
-            final RootFilter subClusterFilter = getSubClusterFilter();
-            final Interval subClusterSpan = new Interval(getStartMillis(), getEndMillis() + 1000);
-            final EventTypeZoomLevel eventTypeZoomLevel = eventsModel.eventTypeZoomProperty().get();
-            final ZoomParams zoomParams = new ZoomParams(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLoD());
-
-            Task<Collection<EventStripe>> loggedTask = new Task<Collection<EventStripe>>() {
-
-                private volatile DescriptionLoD loadedDescriptionLoD = getDescriptionLoD().withRelativeDetail(relativeDetail);
-
-                {
-                    updateTitle(Bundle.EventStripeNode_loggedTask_name());
-                }
 
-                @Override
-                protected Collection<EventStripe> call() throws Exception {
-                    Collection<EventStripe> bundles;
-                    DescriptionLoD next = loadedDescriptionLoD;
-                    do {
-                        loadedDescriptionLoD = next;
-                        if (loadedDescriptionLoD == getEventBundle().getDescriptionLoD()) {
-                            return Collections.emptySet();
-                        }
-                        bundles = eventsModel.getEventClusters(zoomParams.withDescrLOD(loadedDescriptionLoD)).stream()
-                                .collect(Collectors.toMap((eventCluster) -> eventCluster.getDescription(), //key
-                                                (eventCluster) -> new EventStripe(eventCluster, getEventCluster()), //value
-                                                EventStripe::merge) //merge method
-                                ).values();
-                        next = loadedDescriptionLoD.withRelativeDetail(relativeDetail);
-                    } while (bundles.size() == 1 && nonNull(next));
-
-                    // return list of AbstractEventStripeNodes representing sub-bundles
-                    return bundles;
+        /*
+         * make new ZoomParams to query with
+         *
+         * We need to extend end time because for the query by one second,
+         * because it is treated as an open interval but we want to include
+         * events at exactly the time of the last event in this cluster
+         */
+        final RootFilter subClusterFilter = getSubClusterFilter();
+        final Interval subClusterSpan = new Interval(getStartMillis(), getEndMillis() + 1000);
+        final EventTypeZoomLevel eventTypeZoomLevel = eventsModel.eventTypeZoomProperty().get();
+        final ZoomParams zoomParams = new ZoomParams(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLoD());
 
-                }
+        Task<Collection<EventStripe>> loggedTask = new Task<Collection<EventStripe>>() {
 
-                @Override
-                protected void succeeded() {
-                    chart.setCursor(Cursor.WAIT);
-                    try {
-                        Collection<EventStripe> bundles = get();
-
-                        if (bundles.isEmpty()) {
-                            countLabel.setVisible(true);
-                        } else {
-                            countLabel.setVisible(false);
-                            chart.getEventBundles().addAll(bundles);
-                            subNodes.addAll(bundles.stream()
-                                    .map(EventClusterNode.this::createStripeNode)
-                                    .sorted(Comparator.comparing(EventStripeNode::getStartMillis))
-                                    .collect(Collectors.toList()));
-                            subNodePane.getChildren().addAll(subNodes);
-                        }
-                        descLOD.set(loadedDescriptionLoD);
-                        //assign subNodes and request chart layout
+            private volatile DescriptionLoD loadedDescriptionLoD = getDescriptionLoD().withRelativeDetail(relativeDetail);
 
-                    } catch (InterruptedException | ExecutionException ex) {
-                        LOGGER.log(Level.SEVERE, "Error loading subnodes", ex);
+            {
+                updateTitle(Bundle.EventStripeNode_loggedTask_name());
+            }
+
+            @Override
+            protected Collection<EventStripe> call() throws Exception {
+                Collection<EventStripe> bundles;
+                DescriptionLoD next = loadedDescriptionLoD;
+                do {
+                    loadedDescriptionLoD = next;
+                    if (loadedDescriptionLoD == getEventBundle().getDescriptionLoD()) {
+                        return Collections.emptySet();
                     }
-                    chart.layoutPlotChildren();
-                    chart.setCursor(null);
+                    bundles = eventsModel.getEventClusters(zoomParams.withDescrLOD(loadedDescriptionLoD)).stream()
+                            .collect(Collectors.toMap(EventCluster::getDescription, //key
+                                            (eventCluster) -> new EventStripe(eventCluster, getEventCluster()), //value
+                                            EventStripe::merge) //merge method
+                            ).values();
+                    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<EventStripe> bundles = get();
+
+                    if (bundles.isEmpty()) {
+                        subNodePane.getChildren().clear();
+                        getChildren().setAll(subNodePane, infoHBox);
+                        descLOD.set(getEventBundle().getDescriptionLoD());
+                    } else {
+                        chart.getEventBundles().addAll(bundles);
+                        subNodes.addAll(bundles.stream()
+                                .map(EventClusterNode.this::createStripeNode)
+                                .sorted(Comparator.comparing(EventStripeNode::getStartMillis))
+                                .collect(Collectors.toList()));
+                        subNodePane.getChildren().setAll(subNodes);
+                        getChildren().setAll(new VBox(infoHBox, subNodePane));
+                        descLOD.set(loadedDescriptionLoD);
+                    }
+                } catch (InterruptedException | ExecutionException ex) {
+                    LOGGER.log(Level.SEVERE, "Error loading subnodes", ex);
                 }
-            };
+                chart.layoutPlotChildren();
+                chart.setCursor(null);
+            }
+        };
 
-            //start task
-            chart.getController().monitorTask(loggedTask);
-        }
+        //start task
+        chart.getController().monitorTask(loggedTask);
     }
 
     private EventStripeNode createStripeNode(EventStripe stripe) {
@@ -249,7 +246,7 @@ protected void layoutChildren() {
     RootFilter getSubClusterFilter() {
         RootFilter subClusterFilter = eventsModel.filterProperty().get().copyOf();
         subClusterFilter.getSubFilters().addAll(
-                new DescriptionFilter(getDescriptionLoD(), getDescription(), DescriptionFilter.FilterMode.INCLUDE),
+                new DescriptionFilter(getEventBundle().getDescriptionLoD(), getDescription(), DescriptionFilter.FilterMode.INCLUDE),
                 new TypeFilter(getEventType()));
         return subClusterFilter;
     }
@@ -310,7 +307,6 @@ private class ExpandClusterAction extends Action {
                 final DescriptionLoD next = descLOD.get().moreDetailed();
                 if (next != null) {
                     loadSubBundles(DescriptionLoD.RelativeDetail.MORE);
-
                 }
             });
             disabledProperty().bind(descLOD.isEqualTo(DescriptionLoD.FULL));
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 784191b485..e840b278de 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventStripeNode.java
@@ -57,7 +57,6 @@ public EventStripeNode(EventDetailChart chart, EventStripe eventStripe, EventClu
         super(chart, eventStripe, parentNode);
 
         setMinHeight(48);
-//        minWidthProperty().bind(subNodePane.widthProperty());
 
         EventDetailChart.HideDescriptionAction hideClusterAction = chart.new HideDescriptionAction(getDescription(), eventBundle.getDescriptionLoD());
         hideButton = ActionUtils.createButton(hideClusterAction, ActionUtils.ActionTextBehavior.HIDE);
@@ -70,7 +69,6 @@ public EventStripeNode(EventDetailChart chart, EventStripe eventStripe, EventClu
         descrLabel.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS);
         descrLabel.setGraphic(eventTypeImageView);
 
-//        subNodePane.setPickOnBounds(false);
         setAlignment(subNodePane, Pos.BOTTOM_LEFT);
         for (EventCluster cluster : eventStripe.getClusters()) {
             EventClusterNode clusterNode = new EventClusterNode(chart, cluster, this);
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/zooming/DescriptionLoD.java b/Core/src/org/sleuthkit/autopsy/timeline/zooming/DescriptionLoD.java
index 50d612b210..0fab0442c8 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/zooming/DescriptionLoD.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/zooming/DescriptionLoD.java
@@ -43,7 +43,7 @@ public DescriptionLoD moreDetailed() {
         try {
             return values()[ordinal() + 1];
         } catch (ArrayIndexOutOfBoundsException e) {
-            return null;
+            return FULL;
         }
     }
 
@@ -51,7 +51,7 @@ public DescriptionLoD lessDetailed() {
         try {
             return values()[ordinal() - 1];
         } catch (ArrayIndexOutOfBoundsException e) {
-            return null;
+            return SHORT;
         }
     }
 
-- 
GitLab