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:
jmillman 2016-02-23 17:01:10 -05:00
parent 64d3f09118
commit a6bfbf467a
13 changed files with 203 additions and 213 deletions

View File

@ -47,7 +47,7 @@ public interface MultiEvent<ParentType extends MultiEvent<?>> extends TimeLineEv
Optional<ParentType> getParentBundle();
default int getCount() {
default int getSize() {
return getEventIDs().size();
}

View File

@ -44,7 +44,7 @@ public interface TimeLineEvent {
long getStartMillis();
default int getCount() {
default int getSize() {
return getEventIDs().size();
}

View File

@ -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() {

View File

@ -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();
}

View File

@ -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);
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);
if (eventStripe.getClusters().size() > 1) {
for (EventCluster cluster : eventStripe.getClusters()) {
subNodes.add(createChildNode(cluster));
}
getChildren().addAll(new VBox(infoHBox, subNodePane));
} 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:

View File

@ -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();

View File

@ -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();

View File

@ -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())

View File

@ -52,7 +52,7 @@ class EventDescriptionTreeItem extends NavTreeItem {
@Override
public long getCount() {
return getValue().getCount();
return getValue().getSize();
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)

View File

@ -44,7 +44,7 @@ class EventTypeTreeItem extends NavTreeItem {
@Override
public long getCount() {
return getValue().getCount();
return getValue().getSize();
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)

View File

@ -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());

View File

@ -51,7 +51,7 @@ class RootItem extends NavTreeItem {
@Override
public long getCount() {
return getValue().getCount();
return getValue().getSize();
}
/**

View File

@ -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()) {