mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
flesh out pinning multievents, and small ui changes to streamline bundles with only one sub-bundle.
move eventTypeImageView into EventNodeBase
This commit is contained in:
parent
64d3f09118
commit
a6bfbf467a
@ -47,7 +47,7 @@ public interface MultiEvent<ParentType extends MultiEvent<?>> extends TimeLineEv
|
||||
|
||||
Optional<ParentType> getParentBundle();
|
||||
|
||||
default int getCount() {
|
||||
default int getSize() {
|
||||
return getEventIDs().size();
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public interface TimeLineEvent {
|
||||
|
||||
long getStartMillis();
|
||||
|
||||
default int getCount() {
|
||||
default int getSize() {
|
||||
return getEventIDs().size();
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,6 @@ import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter;
|
||||
import org.sleuthkit.autopsy.timeline.filters.RootFilter;
|
||||
import org.sleuthkit.autopsy.timeline.filters.TypeFilter;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.detailview.EventNodeBase.configureActionButton;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.detailview.EventNodeBase.show;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.ZoomParams;
|
||||
@ -72,8 +71,8 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
|
||||
private final Border clusterBorder = new Border(new BorderStroke(evtColor.deriveColor(0, 1, 1, .4), BorderStrokeStyle.SOLID, CORNER_RADII_1, CLUSTER_BORDER_WIDTHS));
|
||||
|
||||
private Button plusButton;
|
||||
private Button minusButton;
|
||||
Button plusButton;
|
||||
Button minusButton;
|
||||
|
||||
@Override
|
||||
void installActionButtons() {
|
||||
@ -81,15 +80,14 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
if (plusButton == null) {
|
||||
plusButton = ActionUtils.createButton(new ExpandClusterAction(), ActionUtils.ActionTextBehavior.HIDE);
|
||||
minusButton = ActionUtils.createButton(new CollapseClusterAction(), ActionUtils.ActionTextBehavior.HIDE);
|
||||
infoHBox.getChildren().addAll(minusButton, plusButton);
|
||||
controlsHBox.getChildren().addAll(minusButton, plusButton);
|
||||
|
||||
configureActionButton(plusButton);
|
||||
configureActionButton(minusButton);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public EventClusterNode(DetailsChart chart, EventCluster eventCluster, EventStripeNode parentNode) {
|
||||
EventClusterNode(DetailsChart chart, EventCluster eventCluster, EventStripeNode parentNode) {
|
||||
super(chart, eventCluster, parentNode);
|
||||
|
||||
subNodePane.setBorder(clusterBorder);
|
||||
@ -102,17 +100,10 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
setCursor(Cursor.HAND);
|
||||
getChildren().addAll(subNodePane, infoHBox);
|
||||
|
||||
}
|
||||
if (parentNode == null) {
|
||||
|
||||
@Override
|
||||
void showHoverControls(final boolean showControls) {
|
||||
super.showHoverControls(showControls);
|
||||
installActionButtons();
|
||||
show(plusButton, showControls);
|
||||
show(minusButton, showControls);
|
||||
// if (getEventCluster().getEventIDs().size() == 1) {
|
||||
// show(pinButton, showControls);
|
||||
// }
|
||||
setDescriptionVisibiltiyImpl(DescriptionVisibility.SHOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,14 +111,9 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMaxDescriptionWidth(double max) {
|
||||
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
void setDescriptionVisibiltiyImpl(DescriptionVisibility descrVis) {
|
||||
final int size = getEventCluster().getCount();
|
||||
final int size = getEventCluster().getSize();
|
||||
switch (descrVis) {
|
||||
case HIDDEN:
|
||||
countLabel.setText("");
|
||||
@ -137,9 +123,20 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
descrLabel.setText("");
|
||||
countLabel.setText(String.valueOf(size));
|
||||
break;
|
||||
default:
|
||||
case SHOWN:
|
||||
countLabel.setText(String.valueOf(size));
|
||||
default:
|
||||
String count;
|
||||
String description;
|
||||
if (parentNode == null) {
|
||||
description = tlEvent.getDescription();
|
||||
count = "(" + size + ")";
|
||||
} else {
|
||||
description = "";
|
||||
count = String.valueOf(size);
|
||||
}
|
||||
|
||||
descrLabel.setText(description);
|
||||
countLabel.setText(count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -225,8 +222,6 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
|
||||
@Override
|
||||
EventNodeBase<?> createChildNode(EventStripe stripe) {
|
||||
// return new EventStripeNode(getChart(), stripe, this);
|
||||
|
||||
if (stripe.getEventIDs().size() == 1) {
|
||||
return new SingleEventNode(getChart(), getChart().getController().getEventsModel().getEventById(Iterables.getOnlyElement(stripe.getEventIDs())), this);
|
||||
} else {
|
||||
@ -270,7 +265,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
return mouseEvent -> new ExpandClusterAction().handle(null);
|
||||
}
|
||||
|
||||
private class ExpandClusterAction extends Action {
|
||||
class ExpandClusterAction extends Action {
|
||||
|
||||
@NbBundle.Messages({"ExpandClusterAction.text=Expand"})
|
||||
ExpandClusterAction() {
|
||||
@ -286,7 +281,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
||||
}
|
||||
}
|
||||
|
||||
private class CollapseClusterAction extends Action {
|
||||
class CollapseClusterAction extends Action {
|
||||
|
||||
@NbBundle.Messages({"CollapseClusterAction.text=Collapse"})
|
||||
CollapseClusterAction() {
|
||||
|
@ -29,6 +29,7 @@ import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ButtonBase;
|
||||
@ -42,8 +43,15 @@ import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Background;
|
||||
import javafx.scene.layout.BackgroundFill;
|
||||
import javafx.scene.layout.Border;
|
||||
import javafx.scene.layout.BorderStroke;
|
||||
import javafx.scene.layout.BorderStrokeStyle;
|
||||
import javafx.scene.layout.BorderWidths;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Duration;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.controlsfx.control.action.ActionUtils;
|
||||
@ -55,7 +63,9 @@ import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
|
||||
import org.sleuthkit.autopsy.timeline.ui.TimeLineChart;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.detailview.EventNodeBase.show;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.detailview.MultiEventNodeBase.CORNER_RADII_3;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -71,40 +81,68 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
|
||||
static final Map<EventType, Effect> dropShadowMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final Tooltip tooltip = new Tooltip(Bundle.EventBundleNodeBase_toolTip_loading());
|
||||
|
||||
final Type tlEvent;
|
||||
|
||||
final EventNodeBase<?> parentNode;
|
||||
final Label descrLabel = new Label();
|
||||
final SimpleObjectProperty<DescriptionLoD> descLOD = new SimpleObjectProperty<>();
|
||||
final SimpleObjectProperty<DescriptionVisibility> descVisibility = new SimpleObjectProperty<>();
|
||||
|
||||
static void configureActionButton(ButtonBase b) {
|
||||
b.setMinSize(16, 16);
|
||||
b.setMaxSize(16, 16);
|
||||
b.setPrefSize(16, 16);
|
||||
show(b, false);
|
||||
// show(b, false);
|
||||
}
|
||||
|
||||
static void show(Node b, boolean show) {
|
||||
b.setVisible(show);
|
||||
b.setManaged(show);
|
||||
}
|
||||
private Timeline timeline;
|
||||
final DetailsChart chart;
|
||||
|
||||
public EventNodeBase(Type ievent, EventNodeBase<?> parent, DetailsChart chart) {
|
||||
final Type tlEvent;
|
||||
|
||||
final EventNodeBase<?> parentNode;
|
||||
|
||||
final SimpleObjectProperty<DescriptionLoD> descLOD = new SimpleObjectProperty<>();
|
||||
final SimpleObjectProperty<DescriptionVisibility> descVisibility = new SimpleObjectProperty<>();
|
||||
|
||||
final DetailsChart chart;
|
||||
final Background highlightedBackground;
|
||||
final Background defaultBackground;
|
||||
final Color evtColor;
|
||||
|
||||
final Label countLabel = new Label();
|
||||
final Label descrLabel = new Label();
|
||||
final ImageView hashIV = new ImageView(HASH_PIN);
|
||||
final ImageView tagIV = new ImageView(TAG);
|
||||
|
||||
final HBox controlsHBox = new HBox(5);
|
||||
final HBox infoHBox = new HBox(5, descrLabel, countLabel, hashIV, tagIV, controlsHBox);
|
||||
|
||||
private final Tooltip tooltip = new Tooltip(Bundle.EventBundleNodeBase_toolTip_loading());
|
||||
|
||||
private Timeline timeline;
|
||||
private Button pinButton;
|
||||
private final Border SELECTION_BORDER;
|
||||
final ImageView eventTypeImageView = new ImageView();
|
||||
|
||||
EventNodeBase(Type ievent, EventNodeBase<?> parent, DetailsChart chart) {
|
||||
this.chart = chart;
|
||||
this.tlEvent = ievent;
|
||||
this.parentNode = parent;
|
||||
eventTypeImageView.setImage(getEventType().getFXImage());
|
||||
|
||||
descrLabel.setGraphic(eventTypeImageView);
|
||||
|
||||
if (chart.getController().getEventsModel().getEventTypeZoom() == EventTypeZoomLevel.SUB_TYPE) {
|
||||
evtColor = getEventType().getColor();
|
||||
} else {
|
||||
evtColor = getEventType().getBaseType().getColor();
|
||||
}
|
||||
SELECTION_BORDER = new Border(new BorderStroke(evtColor.darker().desaturate(), BorderStrokeStyle.SOLID, CORNER_RADII_3, new BorderWidths(2)));
|
||||
|
||||
defaultBackground = new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .1), CORNER_RADII_3, Insets.EMPTY));
|
||||
highlightedBackground = new Background(new BackgroundFill(evtColor.deriveColor(0, 1.1, 1.1, .3), CORNER_RADII_3, Insets.EMPTY));
|
||||
descVisibility.addListener(observable -> setDescriptionVisibiltiyImpl(descVisibility.get()));
|
||||
// descVisibility.set(DescriptionVisibility.SHOWN); //trigger listener for initial value
|
||||
setBackground(defaultBackground);
|
||||
|
||||
//set up mouse hover effect and tooltip
|
||||
setOnMouseEntered(mouseEntered -> {
|
||||
|
||||
Tooltip.uninstall(chart.asNode(), AbstractVisualizationPane.getDefaultTooltip());
|
||||
showHoverControls(true);
|
||||
toFront();
|
||||
@ -118,50 +156,50 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
}
|
||||
});
|
||||
setOnMouseClicked(new ClickHandler());
|
||||
show(controlsHBox, false);
|
||||
}
|
||||
|
||||
public Type getEvent() {
|
||||
return tlEvent;
|
||||
}
|
||||
|
||||
public abstract TimeLineChart<DateTime> getChart();
|
||||
|
||||
/**
|
||||
* @param w the maximum width the description label should have
|
||||
*/
|
||||
public void setMaxDescriptionWidth(double w) {
|
||||
descrLabel.setMaxWidth(w);
|
||||
}
|
||||
|
||||
public abstract List<EventNodeBase<?>> getSubNodes();
|
||||
|
||||
/**
|
||||
* apply the 'effect' to visually indicate selection
|
||||
*
|
||||
* @param applied true to apply the selection 'effect', false to remove it
|
||||
*/
|
||||
public void applySelectionEffect(boolean applied) {
|
||||
setBorder(applied ? SELECTION_BORDER : null);
|
||||
}
|
||||
|
||||
protected void layoutChildren() {
|
||||
super.layoutChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* install whatever buttons are visible on hover for this node. likes
|
||||
* Install whatever buttons are visible on hover for this node. likes
|
||||
* tooltips, this had a surprisingly large impact on speed of loading the
|
||||
* chart
|
||||
*/
|
||||
void installActionButtons() {
|
||||
if (pinButton == null) {
|
||||
pinButton = new Button("", new ImageView(PIN));
|
||||
infoHBox.getChildren().add(pinButton);
|
||||
pinButton = new Button();
|
||||
controlsHBox.getChildren().add(pinButton);
|
||||
configureActionButton(pinButton);
|
||||
|
||||
pinButton.setOnAction(actionEvent -> {
|
||||
TimeLineController controller = getChart().getController();
|
||||
if (controller.getPinnedEvents().contains(tlEvent)) {
|
||||
new UnPinEventAction(controller, tlEvent).handle(actionEvent);
|
||||
pinButton.setGraphic(new ImageView(PIN));
|
||||
} else {
|
||||
new PinEventAction(controller, tlEvent).handle(actionEvent);
|
||||
pinButton.setGraphic(new ImageView(UNPIN));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
final Label countLabel = new Label();
|
||||
|
||||
final ImageView hashIV = new ImageView(HASH_PIN);
|
||||
final ImageView tagIV = new ImageView(TAG);
|
||||
final HBox infoHBox = new HBox(5, descrLabel, countLabel, hashIV, tagIV);
|
||||
private Button pinButton;
|
||||
|
||||
abstract public TimeLineChart<DateTime> getChart();
|
||||
|
||||
void showHoverControls(final boolean showControls) {
|
||||
Effect dropShadow = dropShadowMap.computeIfAbsent(getEventType(),
|
||||
eventType -> new DropShadow(-10, eventType.getColor()));
|
||||
@ -169,7 +207,24 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
installTooltip();
|
||||
enableTooltip(showControls);
|
||||
installActionButtons();
|
||||
show(pinButton, showControls);
|
||||
|
||||
TimeLineController controller = getChart().getController();
|
||||
|
||||
if (controller.getPinnedEvents().contains(tlEvent)) {
|
||||
pinButton.setOnAction(actionEvent -> {
|
||||
new UnPinEventAction(controller, tlEvent).handle(actionEvent);
|
||||
showHoverControls(true);
|
||||
});
|
||||
pinButton.setGraphic(new ImageView(UNPIN));
|
||||
} else {
|
||||
pinButton.setOnAction(actionEvent -> {
|
||||
new PinEventAction(controller, tlEvent).handle(actionEvent);
|
||||
showHoverControls(true);
|
||||
});
|
||||
pinButton.setGraphic(new ImageView(PIN));
|
||||
}
|
||||
|
||||
show(controlsHBox, showControls);
|
||||
if (parentNode != null) {
|
||||
parentNode.showHoverControls(false);
|
||||
}
|
||||
@ -185,7 +240,7 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
}
|
||||
}
|
||||
|
||||
EventType getEventType() {
|
||||
final EventType getEventType() {
|
||||
return tlEvent.getEventType();
|
||||
}
|
||||
|
||||
@ -222,10 +277,6 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
|
||||
abstract void setDescriptionVisibiltiyImpl(DescriptionVisibility get);
|
||||
|
||||
abstract void setMaxDescriptionWidth(double descriptionWidth);
|
||||
|
||||
abstract public List<EventNodeBase<?>> getSubNodes();
|
||||
|
||||
abstract void applyHighlightEffect(boolean b);
|
||||
|
||||
void applyHighlightEffect() {
|
||||
@ -238,9 +289,9 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
|
||||
abstract Collection<Long> getEventIDs();
|
||||
|
||||
void applySelectionEffect(Boolean selected) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
abstract EventHandler<MouseEvent> getDoubleClickHandler();
|
||||
|
||||
abstract Collection<? extends Action> getActions();
|
||||
|
||||
static class PinEventAction extends Action {
|
||||
|
||||
@ -300,8 +351,4 @@ public abstract class EventNodeBase<Type extends TimeLineEvent> extends StackPan
|
||||
|
||||
}
|
||||
|
||||
abstract EventHandler<MouseEvent> getDoubleClickHandler();
|
||||
|
||||
abstract Collection<? extends Action> getActions();
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import javafx.event.EventHandler;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.OverrunStyle;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -44,73 +43,47 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(EventStripeNode.class.getName());
|
||||
private Button hideButton;
|
||||
/**
|
||||
* Pane that contains EventStripeNodes for any 'subevents' if they are
|
||||
* displayed
|
||||
*
|
||||
* //TODO: move more of the control of subnodes/events here and out of
|
||||
* EventDetail Chart
|
||||
*/
|
||||
// private final HBox clustersHBox = new HBox();
|
||||
private final ImageView eventTypeImageView = new ImageView();
|
||||
|
||||
@Override
|
||||
void installActionButtons() {
|
||||
super.installActionButtons();
|
||||
if (hideButton == null) {
|
||||
hideButton = ActionUtils.createButton(new HideDescriptionAction(getDescription(), tlEvent.getDescriptionLoD(), chart),
|
||||
ActionUtils.ActionTextBehavior.HIDE);
|
||||
configureActionButton(hideButton);
|
||||
|
||||
infoHBox.getChildren().add(hideButton);
|
||||
}
|
||||
}
|
||||
|
||||
public EventStripeNode(DetailsChart chart, EventStripe eventStripe, EventClusterNode parentNode) {
|
||||
EventStripeNode(DetailsChart chart, EventStripe eventStripe, EventClusterNode parentNode) {
|
||||
super(chart, eventStripe, parentNode);
|
||||
setMinHeight(48);
|
||||
setMinHeight(24);
|
||||
//setup description label
|
||||
eventTypeImageView.setImage(getEventType().getFXImage());
|
||||
|
||||
descrLabel.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS);
|
||||
descrLabel.setGraphic(eventTypeImageView);
|
||||
|
||||
descrLabel.setPrefWidth(USE_COMPUTED_SIZE);
|
||||
setAlignment(subNodePane, Pos.BOTTOM_LEFT);
|
||||
|
||||
if (eventStripe.getClusters().size() > 1) {
|
||||
for (EventCluster cluster : eventStripe.getClusters()) {
|
||||
subNodes.add(createChildNode(cluster));
|
||||
}
|
||||
|
||||
getChildren().addAll(new VBox(infoHBox, subNodePane));
|
||||
}
|
||||
|
||||
@Override
|
||||
EventNodeBase<?> createChildNode(EventCluster cluster) {
|
||||
if (cluster.getEventIDs().size() == 1) {
|
||||
return new SingleEventNode(getChart(), getChart().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())), this);
|
||||
} else {
|
||||
return new EventClusterNode(getChart(), cluster, this);
|
||||
}
|
||||
EventNodeBase<?> childNode;
|
||||
EventCluster cluster = Iterables.getOnlyElement(eventStripe.getClusters());
|
||||
if (cluster.getEventIDs().size() == 1) {
|
||||
SingleEventNode singleEventNode = new SingleEventNode(getChart(), getChart().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())), this);
|
||||
childNode = singleEventNode;
|
||||
} else {
|
||||
EventClusterNode eventClusterNode = new EventClusterNode(getChart(), cluster, this);
|
||||
eventClusterNode.installActionButtons();
|
||||
eventClusterNode.infoHBox.getChildren().remove(eventClusterNode.countLabel);
|
||||
controlsHBox.getChildren().addAll(eventClusterNode.minusButton, eventClusterNode.plusButton);
|
||||
childNode = eventClusterNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
void showHoverControls(final boolean showControls) {
|
||||
super.showHoverControls(showControls);
|
||||
installActionButtons();
|
||||
show(hideButton, showControls);
|
||||
childNode.setDescriptionVisibiltiyImpl(DescriptionVisibility.HIDDEN);
|
||||
subNodes.add(childNode);
|
||||
getChildren().addAll(infoHBox, subNodePane);
|
||||
}
|
||||
}
|
||||
|
||||
public EventStripe getEventStripe() {
|
||||
return getEventBundle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param w the maximum width the description label should have
|
||||
*/
|
||||
@Override
|
||||
public void setMaxDescriptionWidth(double w) {
|
||||
descrLabel.setMaxWidth(w);
|
||||
}
|
||||
|
||||
/**
|
||||
* apply the 'effect' to visually indicate highlighted nodes
|
||||
*
|
||||
@ -127,9 +100,32 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void installActionButtons() {
|
||||
super.installActionButtons();
|
||||
if (hideButton == null) {
|
||||
hideButton = ActionUtils.createButton(new HideDescriptionAction(getDescription(), tlEvent.getDescriptionLoD(), chart),
|
||||
ActionUtils.ActionTextBehavior.HIDE);
|
||||
configureActionButton(hideButton);
|
||||
|
||||
controlsHBox.getChildren().add(hideButton);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
EventNodeBase<?> createChildNode(EventCluster cluster) {
|
||||
if (cluster.getEventIDs().size() == 1) {
|
||||
return new SingleEventNode(getChart(), getChart().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())), this);
|
||||
} else {
|
||||
return new EventClusterNode(getChart(), cluster, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
void setDescriptionVisibiltiyImpl(DescriptionVisibility descrVis) {
|
||||
final int size = getEventStripe().getCount();
|
||||
final int size = getEventStripe().getSize();
|
||||
|
||||
switch (descrVis) {
|
||||
case HIDDEN:
|
||||
|
@ -40,15 +40,8 @@ import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Background;
|
||||
import javafx.scene.layout.BackgroundFill;
|
||||
import javafx.scene.layout.Border;
|
||||
import javafx.scene.layout.BorderStroke;
|
||||
import javafx.scene.layout.BorderStrokeStyle;
|
||||
import javafx.scene.layout.BorderWidths;
|
||||
import javafx.scene.layout.CornerRadii;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Duration;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.joda.time.DateTime;
|
||||
@ -59,7 +52,6 @@ import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.SingleEvent;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.detailview.EventNodeBase.show;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
||||
@ -80,32 +72,21 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
static final CornerRadii CORNER_RADII_3 = new CornerRadii(3);
|
||||
static final CornerRadii CORNER_RADII_1 = new CornerRadii(1);
|
||||
|
||||
private final Border SELECTION_BORDER;
|
||||
|
||||
final SleuthkitCase sleuthkitCase;
|
||||
final FilteredEventsModel eventsModel;
|
||||
|
||||
final Background highlightedBackground;
|
||||
final Background defaultBackground;
|
||||
final Color evtColor;
|
||||
|
||||
final ObservableList<EventNodeBase<?>> subNodes = FXCollections.observableArrayList();
|
||||
final Pane subNodePane = new Pane();
|
||||
|
||||
|
||||
|
||||
private final Tooltip tooltip = new Tooltip(Bundle.EventBundleNodeBase_toolTip_loading());
|
||||
private Timeline timeline;
|
||||
|
||||
public MultiEventNodeBase(DetailsChart chart, BundleType eventBundle, ParentNodeType parentNode) {
|
||||
MultiEventNodeBase(DetailsChart chart, BundleType eventBundle, ParentNodeType parentNode) {
|
||||
super(eventBundle, parentNode, chart);
|
||||
this.descLOD.set(eventBundle.getDescriptionLoD());
|
||||
sleuthkitCase = chart.getController().getAutopsyCase().getSleuthkitCase();
|
||||
eventsModel = chart.getController().getEventsModel();
|
||||
evtColor = getEventType().getColor();
|
||||
defaultBackground = new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .1), CORNER_RADII_3, Insets.EMPTY));
|
||||
highlightedBackground = new Background(new BackgroundFill(evtColor.deriveColor(0, 1.1, 1.1, .3), CORNER_RADII_3, Insets.EMPTY));
|
||||
SELECTION_BORDER = new Border(new BorderStroke(evtColor.darker().desaturate(), BorderStrokeStyle.SOLID, CORNER_RADII_3, new BorderWidths(2)));
|
||||
|
||||
if (eventBundle.getEventIDsWithHashHits().isEmpty()) {
|
||||
show(hashIV, false);
|
||||
}
|
||||
@ -113,7 +94,6 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
show(tagIV, false);
|
||||
}
|
||||
|
||||
setBackground(defaultBackground);
|
||||
setAlignment(Pos.TOP_LEFT);
|
||||
setMaxWidth(USE_PREF_SIZE);
|
||||
infoHBox.setMaxWidth(USE_PREF_SIZE);
|
||||
@ -171,7 +151,6 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
return tlEvent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* defer tooltip content creation till needed, this had a surprisingly large
|
||||
* impact on speed of loading the chart
|
||||
@ -246,15 +225,6 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* apply the 'effect' to visually indicate selection
|
||||
*
|
||||
* @param applied true to apply the selection 'effect', false to remove it
|
||||
*/
|
||||
public void applySelectionEffect(boolean applied) {
|
||||
setBorder(applied ? SELECTION_BORDER : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* apply the 'effect' to visually indicate highlighted nodes
|
||||
*
|
||||
@ -267,10 +237,6 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
return subNodes;
|
||||
}
|
||||
|
||||
final EventType getEventType() {
|
||||
return getEventBundle().getEventType();
|
||||
}
|
||||
|
||||
final String getDescription() {
|
||||
return getEventBundle().getDescription();
|
||||
}
|
||||
@ -300,11 +266,6 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
||||
|
||||
abstract EventNodeBase<?> createChildNode(ParentType rawChild);
|
||||
|
||||
/**
|
||||
* @param w the maximum width the description label should have
|
||||
*/
|
||||
abstract void setMaxDescriptionWidth(double w);
|
||||
|
||||
void animateTo(double xLeft, double yTop) {
|
||||
if (timeline != null) {
|
||||
timeline.stop();
|
||||
|
@ -346,8 +346,8 @@ public final class PinnedEventsChart extends XYChart<DateTime, TimeLineEvent> im
|
||||
eventNode.setVisible(true);
|
||||
eventNode.setManaged(true);
|
||||
//apply advanced layout description visibility options
|
||||
// eventNode.setDescriptionVisibility(descrVisibility.get());
|
||||
// eventNode.setMaxDescriptionWidth(descriptionWidth);
|
||||
eventNode.setDescriptionVisibility(DescriptionVisibility.SHOWN);
|
||||
eventNode.setMaxDescriptionWidth(USE_PREF_SIZE);
|
||||
|
||||
//do recursive layout
|
||||
eventNode.layoutChildren();
|
||||
|
@ -23,29 +23,23 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.OverrunStyle;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Background;
|
||||
import javafx.scene.layout.BackgroundFill;
|
||||
import javafx.scene.layout.Border;
|
||||
import javafx.scene.layout.BorderStroke;
|
||||
import javafx.scene.layout.BorderStrokeStyle;
|
||||
import javafx.scene.layout.BorderWidths;
|
||||
import javafx.scene.layout.CornerRadii;
|
||||
import static javafx.scene.layout.Region.USE_PREF_SIZE;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.joda.time.DateTime;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.SingleEvent;
|
||||
import org.sleuthkit.autopsy.timeline.ui.TimeLineChart;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.detailview.MultiEventNodeBase.CORNER_RADII_3;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -53,10 +47,6 @@ import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
final class SingleEventNode extends EventNodeBase<SingleEvent> {
|
||||
|
||||
private final DetailsChart chart;
|
||||
final Background defaultBackground;
|
||||
private final Color evtColor;
|
||||
|
||||
|
||||
|
||||
static void show(Node b, boolean show) {
|
||||
b.setVisible(show);
|
||||
@ -66,7 +56,6 @@ final class SingleEventNode extends EventNodeBase<SingleEvent> {
|
||||
private static final BorderWidths CLUSTER_BORDER_WIDTHS = new BorderWidths(0, 0, 0, 2);
|
||||
private final ImageView eventTypeImageView = new ImageView();
|
||||
|
||||
|
||||
@Override
|
||||
EventHandler<MouseEvent> getDoubleClickHandler() {
|
||||
return mouseEvent -> {
|
||||
@ -100,19 +89,12 @@ final class SingleEventNode extends EventNodeBase<SingleEvent> {
|
||||
show(tagIV, false);
|
||||
}
|
||||
|
||||
if (chart.getController().getEventsModel().getEventTypeZoom() == EventTypeZoomLevel.SUB_TYPE) {
|
||||
evtColor = getEventType().getColor();
|
||||
} else {
|
||||
evtColor = getEventType().getBaseType().getColor();
|
||||
}
|
||||
final Border clusterBorder = new Border(new BorderStroke(evtColor.deriveColor(0, 1, 1, .4), BorderStrokeStyle.SOLID, CORNER_RADII_1, CLUSTER_BORDER_WIDTHS));
|
||||
setBorder(clusterBorder);
|
||||
defaultBackground = new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .1), CORNER_RADII_3, Insets.EMPTY));
|
||||
setBackground(defaultBackground);
|
||||
|
||||
setMaxWidth(USE_PREF_SIZE);
|
||||
infoHBox.setMaxWidth(USE_PREF_SIZE);
|
||||
getChildren().add(infoHBox);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -125,14 +107,6 @@ final class SingleEventNode extends EventNodeBase<SingleEvent> {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
void showHoverControls(final boolean showControls) {
|
||||
super.showHoverControls(showControls);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void layoutChildren() {
|
||||
super.layoutChildren(); //To change body of generated methods, choose Tools | Templates.
|
||||
@ -153,14 +127,28 @@ final class SingleEventNode extends EventNodeBase<SingleEvent> {
|
||||
chart.requestTimelineChartLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* apply the 'effect' to visually indicate highlighted nodes
|
||||
*
|
||||
* @param applied true to apply the highlight 'effect', false to remove it
|
||||
*/
|
||||
@Override
|
||||
void applyHighlightEffect(boolean b) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
public synchronized void applyHighlightEffect(boolean applied) {
|
||||
if (applied) {
|
||||
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
|
||||
setBackground(highlightedBackground);
|
||||
} else {
|
||||
descrLabel.setStyle("-fx-font-weight: normal;"); // NON-NLS
|
||||
setBackground(defaultBackground);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param w the maximum width the description label should have
|
||||
*/
|
||||
@Override
|
||||
void setMaxDescriptionWidth(double descriptionWidth) {
|
||||
// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
public void setMaxDescriptionWidth(double w) {
|
||||
descrLabel.setMaxWidth(w);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -168,13 +156,16 @@ final class SingleEventNode extends EventNodeBase<SingleEvent> {
|
||||
|
||||
switch (descrVis) {
|
||||
case HIDDEN:
|
||||
countLabel.setText(null);
|
||||
descrLabel.setText("");
|
||||
break;
|
||||
case COUNT_ONLY:
|
||||
countLabel.setText(null);
|
||||
descrLabel.setText("");
|
||||
break;
|
||||
default:
|
||||
case SHOWN:
|
||||
countLabel.setText(null);
|
||||
String description = tlEvent.getFullDescription();
|
||||
description = parentNode != null
|
||||
? " ..." + StringUtils.substringAfter(description, parentNode.getDescription())
|
||||
|
@ -52,7 +52,7 @@ class EventDescriptionTreeItem extends NavTreeItem {
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return getValue().getCount();
|
||||
return getValue().getSize();
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
|
@ -44,7 +44,7 @@ class EventTypeTreeItem extends NavTreeItem {
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return getValue().getCount();
|
||||
return getValue().getSize();
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
|
@ -185,7 +185,7 @@ final public class EventsTree extends BorderPane {
|
||||
setDisable(true);
|
||||
} else {
|
||||
setDisable(false);
|
||||
text = item.getDescription() + " (" + item.getCount() + ")"; // NON-NLS
|
||||
text = item.getDescription() + " (" + item.getSize() + ")"; // NON-NLS
|
||||
TreeItem<TimeLineEvent> parent = getTreeItem().getParent();
|
||||
if (parent != null && parent.getValue() != null && (parent instanceof EventDescriptionTreeItem)) {
|
||||
text = StringUtils.substringAfter(text, parent.getValue().getDescription());
|
||||
|
@ -51,7 +51,7 @@ class RootItem extends NavTreeItem {
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return getValue().getCount();
|
||||
return getValue().getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ enum TreeComparator implements Comparator<TreeItem<TimeLineEvent>> {
|
||||
Count(Bundle.TreeComparator_Count_displayName()) {
|
||||
@Override
|
||||
public int compare(TreeItem<TimeLineEvent> o1, TreeItem<TimeLineEvent> o2) {
|
||||
return Long.compare(o2.getValue().getCount(), o1.getValue().getCount());
|
||||
return Long.compare(o2.getValue().getSize(), o1.getValue().getSize());
|
||||
}
|
||||
},
|
||||
Type(Bundle.TreeComparator_Type_displayName()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user