mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-13 08:26:15 +00:00
install actions/buttons lazily
This commit is contained in:
parent
5c6714b2f3
commit
5c3adb549e
@ -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<EventStripe> getEventClusters(ZoomParams params) {
|
||||
public List<EventStripe> getEventStripes(ZoomParams params) {
|
||||
return repo.getEventStripes(params);
|
||||
}
|
||||
|
||||
|
@ -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<BundleType extends EventBundle<ParentT
|
||||
|
||||
protected final EventDetailsChart chart;
|
||||
final SimpleObjectProperty<DescriptionLoD> descLOD = new SimpleObjectProperty<>();
|
||||
final SimpleObjectProperty<DescriptionVisibility> descVisibility = new SimpleObjectProperty<>(DescriptionVisibility.SHOWN);
|
||||
final SimpleObjectProperty<DescriptionVisibility> descVisibility = new SimpleObjectProperty<>();
|
||||
protected final BundleType eventBundle;
|
||||
|
||||
protected final ParentNodeType parentNode;
|
||||
@ -150,9 +148,13 @@ public abstract class EventBundleNodeBase<BundleType extends EventBundle<ParentT
|
||||
setAlignment(Pos.TOP_LEFT);
|
||||
|
||||
setPrefHeight(USE_COMPUTED_SIZE);
|
||||
heightProperty().addListener(heightProp -> {
|
||||
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<BundleType extends EventBundle<ParentT
|
||||
|
||||
//set up mouse hover effect and tooltip
|
||||
setOnMouseEntered((MouseEvent e) -> {
|
||||
/*
|
||||
* 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<BundleType extends EventBundle<ParentT
|
||||
}
|
||||
});
|
||||
|
||||
descVisibility.addListener((ObservableValue<? extends DescriptionVisibility> 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<BundleType extends EventBundle<ParentT
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* install whatever buttons are visible on hover for this node. likes
|
||||
* tooltips, this had a surprisingly large impact on speed of loading the
|
||||
* chart
|
||||
*/
|
||||
abstract void installActionButtons();
|
||||
|
||||
/**
|
||||
* defer tooltip content creation till needed, this had a surprisingly large
|
||||
* impact on speed of loading the chart
|
||||
*/
|
||||
@NbBundle.Messages({"# {0} - counts",
|
||||
"# {1} - event type",
|
||||
"# {2} - description",
|
||||
@ -307,12 +313,11 @@ public abstract class EventBundleNodeBase<BundleType extends EventBundle<ParentT
|
||||
Effect dropShadow = dropShadowMap.computeIfAbsent(getEventType(),
|
||||
eventType -> 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<BundleType extends EventBundle<ParentT
|
||||
void animateTo(double xLeft, double yTop) {
|
||||
if (timeline != null) {
|
||||
timeline.stop();
|
||||
chart.requestChartLayout();
|
||||
|
||||
}
|
||||
timeline = new Timeline(new KeyFrame(Duration.millis(100),
|
||||
new KeyValue(layoutXProperty(), xLeft),
|
||||
new KeyValue(layoutYProperty(), yTop))
|
||||
);
|
||||
timeline.setOnFinished(finished -> Platform.runLater(chart::requestChartLayout));
|
||||
timeline.setOnFinished(finished -> chart.requestChartLayout());
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<EventCluster, Ev
|
||||
private static final Image MINUS = new Image("/org/sleuthkit/autopsy/timeline/images/minus-button.png"); // NON-NLS //NOI18N
|
||||
private final Border clusterBorder = new Border(new BorderStroke(evtColor.deriveColor(0, 1, 1, .4), BorderStrokeStyle.SOLID, CORNER_RADII_1, CLUSTER_BORDER_WIDTHS));
|
||||
|
||||
final Button plusButton = ActionUtils.createButton(new ExpandClusterAction(), ActionUtils.ActionTextBehavior.HIDE);
|
||||
final Button minusButton = ActionUtils.createButton(new CollapseClusterAction(), ActionUtils.ActionTextBehavior.HIDE);
|
||||
private Button plusButton;
|
||||
private Button minusButton;
|
||||
|
||||
@Override
|
||||
void installActionButtons() {
|
||||
if (plusButton == null) {
|
||||
plusButton = ActionUtils.createButton(new ExpandClusterAction(), ActionUtils.ActionTextBehavior.HIDE);
|
||||
minusButton = ActionUtils.createButton(new CollapseClusterAction(), ActionUtils.ActionTextBehavior.HIDE);
|
||||
|
||||
configureLoDButton(plusButton);
|
||||
configureLoDButton(minusButton);
|
||||
infoHBox.getChildren().addAll(minusButton, plusButton);
|
||||
}
|
||||
}
|
||||
|
||||
public EventClusterNode(EventDetailsChart chart, EventCluster eventCluster, EventStripeNode parentNode) {
|
||||
super(chart, eventCluster, parentNode);
|
||||
@ -87,11 +98,8 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
|
||||
setCursor(Cursor.HAND);
|
||||
setOnMouseClicked(new MouseClickHandler());
|
||||
|
||||
configureLoDButton(plusButton);
|
||||
configureLoDButton(minusButton);
|
||||
|
||||
setAlignment(Pos.CENTER_LEFT);
|
||||
infoHBox.getChildren().addAll(minusButton, plusButton);
|
||||
|
||||
getChildren().addAll(subNodePane, infoHBox);
|
||||
|
||||
}
|
||||
@ -99,6 +107,7 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
|
||||
@Override
|
||||
void showHoverControls(final boolean showControls) {
|
||||
super.showHoverControls(showControls);
|
||||
installActionButtons();
|
||||
show(plusButton, showControls);
|
||||
show(minusButton, showControls);
|
||||
}
|
||||
@ -141,10 +150,7 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
|
||||
@NbBundle.Messages(value = "EventStripeNode.loggedTask.name=Load sub clusters")
|
||||
private synchronized void loadSubBundles(DescriptionLoD.RelativeDetail relativeDetail) {
|
||||
chart.setCursor(Cursor.WAIT);
|
||||
chart.getEventStripes().removeIf(bundle ->
|
||||
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<EventCluster, Ev
|
||||
|
||||
@Override
|
||||
protected Collection<EventStripe> call() throws Exception {
|
||||
Collection<EventStripe> bundles = null;
|
||||
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(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<EventStripe> bundles = get();
|
||||
|
||||
@ -203,7 +202,6 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
|
||||
chart.getEventStripes().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));
|
||||
@ -303,9 +301,8 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
|
||||
super(Bundle.ExpandClusterAction_text());
|
||||
|
||||
setGraphic(new ImageView(PLUS));
|
||||
setEventHandler((ActionEvent t) -> {
|
||||
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<EventCluster, Ev
|
||||
super(Bundle.CollapseClusterAction_text());
|
||||
|
||||
setGraphic(new ImageView(MINUS));
|
||||
setEventHandler((ActionEvent t) -> {
|
||||
final DescriptionLoD previous = descLOD.get().lessDetailed();
|
||||
if (previous != null) {
|
||||
setEventHandler(actionEvent -> {
|
||||
if (descLOD.get().lessDetailed() != null) {
|
||||
loadSubBundles(DescriptionLoD.RelativeDetail.LESS);
|
||||
}
|
||||
});
|
||||
|
@ -493,9 +493,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventStripe> 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<DateTime, EventStripe> 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<DateTime, EventStripe> 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;
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ import static org.sleuthkit.autopsy.timeline.ui.detailview.EventBundleNodeBase.c
|
||||
final public class EventStripeNode extends EventBundleNodeBase<EventStripe, EventCluster, EventClusterNode> {
|
||||
|
||||
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<EventStripe, Even
|
||||
// private final HBox clustersHBox = new HBox();
|
||||
private final ImageView eventTypeImageView = new ImageView();
|
||||
|
||||
@Override
|
||||
void installActionButtons() {
|
||||
if (hideButton == null) {
|
||||
hideButton = ActionUtils.createButton(chart.new HideDescriptionAction(getDescription(), eventBundle.getDescriptionLoD()),
|
||||
ActionUtils.ActionTextBehavior.HIDE);
|
||||
configureLoDButton(hideButton);
|
||||
|
||||
infoHBox.getChildren().add(hideButton);
|
||||
}
|
||||
}
|
||||
|
||||
public EventStripeNode(EventDetailsChart chart, EventStripe eventStripe, EventClusterNode parentNode) {
|
||||
super(chart, eventStripe, parentNode);
|
||||
|
||||
setMinHeight(48);
|
||||
|
||||
EventDetailsChart.HideDescriptionAction hideClusterAction = chart.new HideDescriptionAction(getDescription(), eventBundle.getDescriptionLoD());
|
||||
hideButton = ActionUtils.createButton(hideClusterAction, ActionUtils.ActionTextBehavior.HIDE);
|
||||
configureLoDButton(hideButton);
|
||||
|
||||
infoHBox.getChildren().add(hideButton);
|
||||
//setup description label
|
||||
eventTypeImageView.setImage(getEventType().getFXImage());
|
||||
descrLabel.setPrefWidth(USE_COMPUTED_SIZE);
|
||||
@ -83,6 +89,7 @@ final public class EventStripeNode extends EventBundleNodeBase<EventStripe, Even
|
||||
@Override
|
||||
void showHoverControls(final boolean showControls) {
|
||||
super.showHoverControls(showControls);
|
||||
installActionButtons();
|
||||
show(hideButton, showControls);
|
||||
}
|
||||
|
||||
@ -178,5 +185,4 @@ final public class EventStripeNode extends EventBundleNodeBase<EventStripe, Even
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user