mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 11:07:43 +00:00
extend DetailViewNode interface to support more features of old visualization in new mode.
This commit is contained in:
parent
874703030d
commit
2250b01a56
@ -22,8 +22,9 @@ package org.sleuthkit.autopsy.timeline.ui.detailview;
|
|||||||
* Level of description shown in UI NOTE: this is a separate concept form
|
* Level of description shown in UI NOTE: this is a separate concept form
|
||||||
* {@link DescriptionLOD}
|
* {@link DescriptionLOD}
|
||||||
*/
|
*/
|
||||||
enum DescriptionVisibility {
|
public enum DescriptionVisibility {
|
||||||
|
|
||||||
HIDDEN, COUNT_ONLY, SHOWN;
|
|
||||||
|
|
||||||
|
HIDDEN,
|
||||||
|
COUNT_ONLY,
|
||||||
|
SHOWN;
|
||||||
}
|
}
|
||||||
|
@ -7,22 +7,21 @@ package org.sleuthkit.autopsy.timeline.ui.detailview;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
|
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface DetailViewNode {
|
public interface DetailViewNode<S extends DetailViewNode<S>> {
|
||||||
|
|
||||||
long getStartMillis();
|
public long getStartMillis();
|
||||||
|
|
||||||
long getEndMillis();
|
public long getEndMillis();
|
||||||
|
|
||||||
public void setDescriptionVisibility(DescriptionVisibility get);
|
public void setDescriptionVisibility(DescriptionVisibility get);
|
||||||
|
|
||||||
public Pane getSubNodePane();
|
public List<S> getSubNodes();
|
||||||
|
|
||||||
public void setSpanWidths(List<Double> spanWidths);
|
public void setSpanWidths(List<Double> spanWidths);
|
||||||
|
|
||||||
@ -32,10 +31,16 @@ public interface DetailViewNode {
|
|||||||
|
|
||||||
public Set<Long> getEventIDs();
|
public Set<Long> getEventIDs();
|
||||||
|
|
||||||
public void applySelectionEffect(boolean applied);
|
|
||||||
|
|
||||||
public String getDescription();
|
public String getDescription();
|
||||||
|
|
||||||
public EventBundle getBundleDescriptor();
|
public EventBundle getBundleDescriptor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apply the 'effect' to visually indicate highlighted nodes
|
||||||
|
*
|
||||||
|
* @param applied true to apply the highlight 'effect', false to remove it
|
||||||
|
*/
|
||||||
|
void applyHighlightEffect(boolean applied);
|
||||||
|
|
||||||
|
public void applySelectionEffect(boolean applied);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
@ -101,7 +100,7 @@ import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
|||||||
* TODO: refactor common code out of this class and CountsChartPane into
|
* TODO: refactor common code out of this class and CountsChartPane into
|
||||||
* {@link AbstractVisualization}
|
* {@link AbstractVisualization}
|
||||||
*/
|
*/
|
||||||
public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster, DetailViewNode, EventDetailChart> {
|
public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster, DetailViewNode<?>, EventDetailChart> {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(CountsViewPane.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(CountsViewPane.class.getName());
|
||||||
|
|
||||||
@ -121,7 +120,7 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
|
|||||||
|
|
||||||
private final ObservableList<EventCluster> aggregatedEvents = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
|
private final ObservableList<EventCluster> aggregatedEvents = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
|
||||||
|
|
||||||
private final ObservableList<EventClusterNode> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
|
private final ObservableList<DetailViewNode<?>> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
|
||||||
|
|
||||||
public ObservableList<EventCluster> getAggregatedEvents() {
|
public ObservableList<EventCluster> getAggregatedEvents() {
|
||||||
return aggregatedEvents;
|
return aggregatedEvents;
|
||||||
@ -150,7 +149,7 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
|
|||||||
vertScrollBar.visibleAmountProperty().bind(chart.heightProperty().multiply(100).divide(chart.getMaxVScroll()));
|
vertScrollBar.visibleAmountProperty().bind(chart.heightProperty().multiply(100).divide(chart.getMaxVScroll()));
|
||||||
requestLayout();
|
requestLayout();
|
||||||
|
|
||||||
highlightedNodes.addListener((ListChangeListener.Change<? extends EventClusterNode> change) -> {
|
highlightedNodes.addListener((ListChangeListener.Change<? extends DetailViewNode<?>> change) -> {
|
||||||
while (change.next()) {
|
while (change.next()) {
|
||||||
change.getAddedSubList().forEach(aeNode -> {
|
change.getAddedSubList().forEach(aeNode -> {
|
||||||
aeNode.applyHighlightEffect(true);
|
aeNode.applyHighlightEffect(true);
|
||||||
@ -167,7 +166,7 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
|
|||||||
|
|
||||||
//These scroll related handlers don't affect any other view or the model, so they are handled internally
|
//These scroll related handlers don't affect any other view or the model, so they are handled internally
|
||||||
//mouse wheel scroll handler
|
//mouse wheel scroll handler
|
||||||
this.onScrollProperty().set((EventHandler<ScrollEvent>) (ScrollEvent t) -> {
|
this.onScrollProperty().set((ScrollEvent t) -> {
|
||||||
vertScrollBar.valueProperty().set(Math.max(0, Math.min(100, vertScrollBar.getValue() - t.getDeltaY() / 200.0)));
|
vertScrollBar.valueProperty().set(Math.max(0, Math.min(100, vertScrollBar.getValue() - t.getDeltaY() / 200.0)));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -213,8 +212,8 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
|
|||||||
selectedNodes.addListener((Observable observable) -> {
|
selectedNodes.addListener((Observable observable) -> {
|
||||||
highlightedNodes.clear();
|
highlightedNodes.clear();
|
||||||
selectedNodes.stream().forEach((tn) -> {
|
selectedNodes.stream().forEach((tn) -> {
|
||||||
for (EventClusterNode n : chart.getNodes((EventClusterNode t)
|
for (DetailViewNode<?> n : chart.getNodes((DetailViewNode<?> t)
|
||||||
-> t.getEvent().getDescription().equals(tn.getDescription()))) {
|
-> t.getDescription().equals(tn.getDescription()))) {
|
||||||
highlightedNodes.add(n);
|
highlightedNodes.add(n);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -237,8 +236,8 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
|
|||||||
treeSelectionModel.getSelectedItems().addListener((Observable observable) -> {
|
treeSelectionModel.getSelectedItems().addListener((Observable observable) -> {
|
||||||
highlightedNodes.clear();
|
highlightedNodes.clear();
|
||||||
for (TreeItem<NavTreeNode> tn : treeSelectionModel.getSelectedItems()) {
|
for (TreeItem<NavTreeNode> tn : treeSelectionModel.getSelectedItems()) {
|
||||||
for (EventClusterNode n : chart.getNodes((EventClusterNode t)
|
for (DetailViewNode<?> n : chart.getNodes((DetailViewNode<?> t)
|
||||||
-> t.getEvent().getDescription().equals(tn.getValue().getDescription()))) {
|
-> t.getDescription().equals(tn.getValue().getDescription()))) {
|
||||||
highlightedNodes.add(n);
|
highlightedNodes.add(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,7 +357,7 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applySelectionEffect(DetailViewNode c1, Boolean applied) {
|
protected void applySelectionEffect(DetailViewNode<?> c1, Boolean applied) {
|
||||||
c1.applySelectionEffect(applied);
|
c1.applySelectionEffect(applied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
/**
|
/**
|
||||||
* Represents an {@link EventCluster} in a {@link EventDetailChart}.
|
* Represents an {@link EventCluster} in a {@link EventDetailChart}.
|
||||||
*/
|
*/
|
||||||
public class EventClusterNode extends StackPane implements DetailViewNode {
|
public class EventClusterNode extends StackPane implements DetailViewNode<EventClusterNode> {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(EventClusterNode.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(EventClusterNode.class.getName());
|
||||||
|
|
||||||
@ -148,18 +148,23 @@ public class EventClusterNode extends StackPane implements DetailViewNode {
|
|||||||
|
|
||||||
private final Button plusButton = new Button(null, new ImageView(PLUS)) {
|
private final Button plusButton = new Button(null, new ImageView(PLUS)) {
|
||||||
{
|
{
|
||||||
setMinSize(16, 16);
|
configureLODButton(this);
|
||||||
setMaxSize(16, 16);
|
|
||||||
setPrefSize(16, 16);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final Button minusButton = new Button(null, new ImageView(MINUS)) {
|
private final Button minusButton = new Button(null, new ImageView(MINUS)) {
|
||||||
{
|
{
|
||||||
setMinSize(16, 16);
|
configureLODButton(this);
|
||||||
setMaxSize(16, 16);
|
|
||||||
setPrefSize(16, 16);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static void configureLODButton(Button b) {
|
||||||
|
b.setMinSize(16, 16);
|
||||||
|
b.setMaxSize(16, 16);
|
||||||
|
b.setPrefSize(16, 16);
|
||||||
|
b.setVisible(false);
|
||||||
|
b.setManaged(false);
|
||||||
|
}
|
||||||
|
|
||||||
private final EventDetailChart chart;
|
private final EventDetailChart chart;
|
||||||
|
|
||||||
private SimpleObjectProperty<DescriptionLOD> descLOD = new SimpleObjectProperty<>();
|
private SimpleObjectProperty<DescriptionLOD> descLOD = new SimpleObjectProperty<>();
|
||||||
@ -196,10 +201,6 @@ public class EventClusterNode extends StackPane implements DetailViewNode {
|
|||||||
hBox.setPadding(new Insets(2, 5, 2, 5));
|
hBox.setPadding(new Insets(2, 5, 2, 5));
|
||||||
hBox.setAlignment(Pos.CENTER_LEFT);
|
hBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
minusButton.setVisible(false);
|
|
||||||
plusButton.setVisible(false);
|
|
||||||
minusButton.setManaged(false);
|
|
||||||
plusButton.setManaged(false);
|
|
||||||
final BorderPane borderPane = new BorderPane(subNodePane, hBox, null, null, null);
|
final BorderPane borderPane = new BorderPane(subNodePane, hBox, null, null, null);
|
||||||
BorderPane.setAlignment(subNodePane, Pos.TOP_LEFT);
|
BorderPane.setAlignment(subNodePane, Pos.TOP_LEFT);
|
||||||
borderPane.setPrefWidth(USE_COMPUTED_SIZE);
|
borderPane.setPrefWidth(USE_COMPUTED_SIZE);
|
||||||
@ -322,8 +323,10 @@ public class EventClusterNode extends StackPane implements DetailViewNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pane getSubNodePane() {
|
public List<EventClusterNode> getSubNodes() {
|
||||||
return subNodePane;
|
return subNodePane.getChildrenUnmodifiable().stream()
|
||||||
|
.map(EventClusterNode.class::cast)
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized public EventCluster getEvent() {
|
synchronized public EventCluster getEvent() {
|
||||||
@ -413,7 +416,7 @@ public class EventClusterNode extends StackPane implements DetailViewNode {
|
|||||||
*
|
*
|
||||||
* @param applied true to apply the highlight 'effect', false to remove it
|
* @param applied true to apply the highlight 'effect', false to remove it
|
||||||
*/
|
*/
|
||||||
synchronized void applyHighlightEffect(boolean applied) {
|
public synchronized void applyHighlightEffect(boolean applied) {
|
||||||
|
|
||||||
if (applied) {
|
if (applied) {
|
||||||
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
|
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
|
||||||
@ -457,7 +460,7 @@ public class EventClusterNode extends StackPane implements DetailViewNode {
|
|||||||
* @param newDescriptionLOD
|
* @param newDescriptionLOD
|
||||||
*/
|
*/
|
||||||
synchronized private void loadSubClusters(DescriptionLOD newDescriptionLOD) {
|
synchronized private void loadSubClusters(DescriptionLOD newDescriptionLOD) {
|
||||||
getSubNodePane().getChildren().clear();
|
subNodePane.getChildren().clear();
|
||||||
if (newDescriptionLOD == aggEvent.getDescriptionLOD()) {
|
if (newDescriptionLOD == aggEvent.getDescriptionLOD()) {
|
||||||
chart.setRequiresLayout(true);
|
chart.setRequiresLayout(true);
|
||||||
chart.requestChartLayout();
|
chart.requestChartLayout();
|
||||||
@ -494,7 +497,7 @@ public class EventClusterNode extends StackPane implements DetailViewNode {
|
|||||||
try {
|
try {
|
||||||
chart.setCursor(Cursor.WAIT);
|
chart.setCursor(Cursor.WAIT);
|
||||||
//assign subNodes and request chart layout
|
//assign subNodes and request chart layout
|
||||||
getSubNodePane().getChildren().setAll(get());
|
subNodePane.getChildren().setAll(get());
|
||||||
setDescriptionVisibility(descrVis);
|
setDescriptionVisibility(descrVis);
|
||||||
chart.setRequiresLayout(true);
|
chart.setRequiresLayout(true);
|
||||||
chart.requestChartLayout();
|
chart.requestChartLayout();
|
||||||
|
@ -31,6 +31,7 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.KeyValue;
|
import javafx.animation.KeyValue;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
@ -167,7 +168,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
*/
|
*/
|
||||||
private final SimpleBooleanProperty oneEventPerRow = new SimpleBooleanProperty(false);
|
private final SimpleBooleanProperty oneEventPerRow = new SimpleBooleanProperty(false);
|
||||||
|
|
||||||
private final ObservableMap<DetailViewNode, Line> projectionMap = FXCollections.observableHashMap();
|
private final ObservableMap<DetailViewNode<?>, Line> projectionMap = FXCollections.observableHashMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* flag indicating whether this chart actually needs a layout pass
|
* flag indicating whether this chart actually needs a layout pass
|
||||||
@ -175,7 +176,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
@GuardedBy(value = "this")
|
@GuardedBy(value = "this")
|
||||||
private boolean requiresLayout = true;
|
private boolean requiresLayout = true;
|
||||||
|
|
||||||
final ObservableList<DetailViewNode> selectedNodes;
|
final ObservableList<DetailViewNode<?>> selectedNodes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list of series of data added to this chart TODO: replace this with a map
|
* list of series of data added to this chart TODO: replace this with a map
|
||||||
@ -205,7 +206,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
private final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
|
private final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
|
||||||
private final SimpleBooleanProperty alternateLayout = new SimpleBooleanProperty(true);
|
private final SimpleBooleanProperty alternateLayout = new SimpleBooleanProperty(true);
|
||||||
|
|
||||||
EventDetailChart(DateAxis dateAxis, final Axis<EventCluster> verticalAxis, ObservableList<DetailViewNode> selectedNodes) {
|
EventDetailChart(DateAxis dateAxis, final Axis<EventCluster> verticalAxis, ObservableList<DetailViewNode<?>> selectedNodes) {
|
||||||
super(dateAxis, verticalAxis);
|
super(dateAxis, verticalAxis);
|
||||||
dateAxis.setAutoRanging(false);
|
dateAxis.setAutoRanging(false);
|
||||||
|
|
||||||
@ -285,7 +286,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
setOnMouseReleased(dragHandler);
|
setOnMouseReleased(dragHandler);
|
||||||
setOnMouseDragged(dragHandler);
|
setOnMouseDragged(dragHandler);
|
||||||
|
|
||||||
projectionMap.addListener((MapChangeListener.Change<? extends DetailViewNode, ? extends Line> change) -> {
|
projectionMap.addListener((MapChangeListener.Change<? extends DetailViewNode<?>, ? extends Line> change) -> {
|
||||||
final Line valueRemoved = change.getValueRemoved();
|
final Line valueRemoved = change.getValueRemoved();
|
||||||
if (valueRemoved != null) {
|
if (valueRemoved != null) {
|
||||||
getChartChildren().removeAll(valueRemoved);
|
getChartChildren().removeAll(valueRemoved);
|
||||||
@ -298,12 +299,12 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
|
|
||||||
this.selectedNodes = selectedNodes;
|
this.selectedNodes = selectedNodes;
|
||||||
this.selectedNodes.addListener((
|
this.selectedNodes.addListener((
|
||||||
ListChangeListener.Change<? extends DetailViewNode> c) -> {
|
ListChangeListener.Change<? extends DetailViewNode<?>> c) -> {
|
||||||
while (c.next()) {
|
while (c.next()) {
|
||||||
c.getRemoved().forEach((DetailViewNode t) -> {
|
c.getRemoved().forEach((DetailViewNode<?> t) -> {
|
||||||
projectionMap.remove(t);
|
projectionMap.remove(t);
|
||||||
});
|
});
|
||||||
c.getAddedSubList().forEach((DetailViewNode t) -> {
|
c.getAddedSubList().forEach((DetailViewNode<?> t) -> {
|
||||||
Line line = new Line(dateAxis.localToParent(dateAxis.getDisplayPosition(new DateTime(t.getStartMillis(), TimeLineController.getJodaTimeZone())), 0).getX(), dateAxis.getLayoutY() + PROJECTED_LINE_Y_OFFSET,
|
Line line = new Line(dateAxis.localToParent(dateAxis.getDisplayPosition(new DateTime(t.getStartMillis(), TimeLineController.getJodaTimeZone())), 0).getX(), dateAxis.getLayoutY() + PROJECTED_LINE_Y_OFFSET,
|
||||||
dateAxis.localToParent(dateAxis.getDisplayPosition(new DateTime(t.getEndMillis(), TimeLineController.getJodaTimeZone())), 0).getX(), dateAxis.getLayoutY() + PROJECTED_LINE_Y_OFFSET
|
dateAxis.localToParent(dateAxis.getDisplayPosition(new DateTime(t.getEndMillis(), TimeLineController.getJodaTimeZone())), 0).getX(), dateAxis.getLayoutY() + PROJECTED_LINE_Y_OFFSET
|
||||||
);
|
);
|
||||||
@ -316,7 +317,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.controller.selectEventIDs(selectedNodes.stream()
|
this.controller.selectEventIDs(selectedNodes.stream()
|
||||||
.flatMap((DetailViewNode aggNode) -> aggNode.getEventIDs().stream())
|
.flatMap(detailNode -> detailNode.getEventIDs().stream())
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -420,7 +421,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
return EventStripe.merge(u, v);
|
return EventStripe.merge(u, v);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
EventStripeNode clusterNode = new EventStripeNode(eventCluster,null, EventDetailChart.this);
|
EventStripeNode clusterNode = new EventStripeNode(eventCluster, null, EventDetailChart.this);
|
||||||
stripeNodeMap.put(eventCluster, clusterNode);
|
stripeNodeMap.put(eventCluster, clusterNode);
|
||||||
nodeGroup.getChildren().add(clusterNode);
|
nodeGroup.getChildren().add(clusterNode);
|
||||||
} else {
|
} else {
|
||||||
@ -486,11 +487,11 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
if (bandByType.get() == false) {
|
if (bandByType.get() == false) {
|
||||||
if (alternateLayout.get() == true) {
|
if (alternateLayout.get() == true) {
|
||||||
List<EventStripeNode> nodes = new ArrayList<>(stripeNodeMap.values());
|
List<EventStripeNode> nodes = new ArrayList<>(stripeNodeMap.values());
|
||||||
Collections.sort(nodes, Comparator.comparing(DetailViewNode::getStartMillis));
|
nodes.sort(Comparator.comparing(DetailViewNode<?>::getStartMillis));
|
||||||
layoutNodes(nodes, minY, 0);
|
layoutNodes(nodes, minY, 0);
|
||||||
} else {
|
} else {
|
||||||
List<EventClusterNode> nodes = new ArrayList<>(nodeMap.values());
|
List<EventClusterNode> nodes = new ArrayList<>(nodeMap.values());
|
||||||
Collections.sort(nodes, Comparator.comparing(DetailViewNode::getStartMillis));
|
nodes.sort(Comparator.comparing(DetailViewNode<?>::getStartMillis));
|
||||||
layoutNodes(nodes, minY, 0);
|
layoutNodes(nodes, minY, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,22 +546,28 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
return descrVisibility;
|
return descrVisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized ReadOnlyDoubleProperty
|
synchronized ReadOnlyDoubleProperty getMaxVScroll() {
|
||||||
getMaxVScroll() {
|
|
||||||
return maxY.getReadOnlyProperty();
|
return maxY.getReadOnlyProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<EventClusterNode> getNodes(Predicate<EventClusterNode> p) {
|
Iterable<DetailViewNode<?>> getNodes(Predicate<DetailViewNode<?>> p) {
|
||||||
List<EventClusterNode> nodes = new ArrayList<>();
|
Collection<? extends DetailViewNode<?>> values = alternateLayout.get()
|
||||||
|
? stripeNodeMap.values()
|
||||||
|
: nodeMap.values();
|
||||||
|
|
||||||
for (EventClusterNode node : nodeMap.values()) {
|
//collapse tree of DetailViewNoeds to list and then filter on given predicate
|
||||||
checkNode(node, p, nodes);
|
return values.stream()
|
||||||
}
|
.flatMap(EventDetailChart::flatten)
|
||||||
|
.filter(p).collect(Collectors.toList());
|
||||||
return nodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<EventClusterNode> getAllNodes() {
|
public static Stream<? extends DetailViewNode<?>> flatten(DetailViewNode<?> node) {
|
||||||
|
return Stream.concat(
|
||||||
|
Stream.of(node),
|
||||||
|
node.getSubNodes().stream().flatMap(EventDetailChart::flatten));
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterable<DetailViewNode<?>> getAllNodes() {
|
||||||
return getNodes(x -> true);
|
return getNodes(x -> true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,17 +583,6 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
nodeGroup.setTranslateY(-d * h);
|
nodeGroup.setTranslateY(-d * h);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkNode(EventClusterNode node, Predicate<EventClusterNode> p, List<EventClusterNode> nodes) {
|
|
||||||
if (node != null) {
|
|
||||||
if (p.test(node)) {
|
|
||||||
nodes.add(node);
|
|
||||||
}
|
|
||||||
for (Node n : node.getSubNodePane().getChildrenUnmodifiable()) {
|
|
||||||
checkNode((EventClusterNode) n, p, nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearGuideLine() {
|
private void clearGuideLine() {
|
||||||
getChartChildren().remove(guideLine);
|
getChartChildren().remove(guideLine);
|
||||||
guideLine = null;
|
guideLine = null;
|
||||||
@ -599,12 +595,12 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
* @param nodes
|
* @param nodes
|
||||||
* @param minY
|
* @param minY
|
||||||
*/
|
*/
|
||||||
private synchronized <D extends Region & DetailViewNode> double layoutNodes(final Collection<D> nodes, final double minY, final double xOffset) {
|
private synchronized <DVRegion extends Region & DetailViewNode<DVRegion>> double layoutNodes(final Collection<DVRegion> nodes, final double minY, final double xOffset) {
|
||||||
//hash map from y value to right most occupied x value. This tells you for a given 'row' what is the first avaialable slot
|
//hash map from y value to right most occupied x value. This tells you for a given 'row' what is the first avaialable slot
|
||||||
Map<Integer, Double> maxXatY = new HashMap<>();
|
Map<Integer, Double> maxXatY = new HashMap<>();
|
||||||
double localMax = minY;
|
double localMax = minY;
|
||||||
//for each node lay size it and position it in first available slot
|
//for each node lay size it and position it in first available slot
|
||||||
for (D n : nodes) {
|
for (DVRegion n : nodes) {
|
||||||
n.setDescriptionVisibility(descrVisibility.get());
|
n.setDescriptionVisibility(descrVisibility.get());
|
||||||
double rawDisplayPosition = getXAxis().getDisplayPosition(new DateTime(n.getStartMillis()));
|
double rawDisplayPosition = getXAxis().getDisplayPosition(new DateTime(n.getStartMillis()));
|
||||||
|
|
||||||
@ -613,27 +609,19 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
double layoutNodesResultHeight = 0;
|
double layoutNodesResultHeight = 0;
|
||||||
|
|
||||||
double span = 0;
|
double span = 0;
|
||||||
|
List<DVRegion> subNodes = n.getSubNodes();
|
||||||
|
if (subNodes.isEmpty() == false) {
|
||||||
|
subNodes.sort(Comparator.comparing((DVRegion t) -> t.getStartMillis()));
|
||||||
|
layoutNodesResultHeight = layoutNodes(subNodes, 0, rawDisplayPosition);
|
||||||
|
}
|
||||||
|
|
||||||
if (n instanceof EventClusterNode) {
|
if (n instanceof EventClusterNode) {
|
||||||
if (n.getSubNodePane().getChildren().isEmpty() == false) {
|
|
||||||
List<EventClusterNode> children = n.getSubNodePane().getChildren().stream()
|
|
||||||
.map(EventClusterNode.class::cast)
|
|
||||||
.sorted(Comparator.comparing(DetailViewNode::getStartMillis))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
layoutNodesResultHeight = layoutNodes(children, 0, rawDisplayPosition);
|
|
||||||
}
|
|
||||||
double endX = getXAxis().getDisplayPosition(new DateTime(n.getEndMillis())) - xOffset;
|
double endX = getXAxis().getDisplayPosition(new DateTime(n.getEndMillis())) - xOffset;
|
||||||
span = endX - startX;
|
span = endX - startX;
|
||||||
|
|
||||||
//size timespan border
|
//size timespan border
|
||||||
n.setSpanWidths(Arrays.asList(span));
|
n.setSpanWidths(Arrays.asList(span));
|
||||||
} else {
|
} else {
|
||||||
if (n.getSubNodePane().getChildren().isEmpty() == false) {
|
|
||||||
List<EventStripeNode> children = n.getSubNodePane().getChildren().stream()
|
|
||||||
.map(EventStripeNode.class::cast)
|
|
||||||
.sorted(Comparator.comparing(DetailViewNode::getStartMillis))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
layoutNodesResultHeight = layoutNodes(children, 0, rawDisplayPosition);
|
|
||||||
}
|
|
||||||
EventStripeNode cn = (EventStripeNode) n;
|
EventStripeNode cn = (EventStripeNode) n;
|
||||||
List<Double> spanWidths = new ArrayList<>();
|
List<Double> spanWidths = new ArrayList<>();
|
||||||
double x = getXAxis().getDisplayPosition(new DateTime(cn.getStartMillis()));;
|
double x = getXAxis().getDisplayPosition(new DateTime(cn.getStartMillis()));;
|
||||||
@ -720,8 +708,8 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
private static final int DEFAULT_ROW_HEIGHT = 24;
|
private static final int DEFAULT_ROW_HEIGHT = 24;
|
||||||
|
|
||||||
private void layoutProjectionMap() {
|
private void layoutProjectionMap() {
|
||||||
for (final Map.Entry<DetailViewNode, Line> entry : projectionMap.entrySet()) {
|
for (final Map.Entry<DetailViewNode<?>, Line> entry : projectionMap.entrySet()) {
|
||||||
final DetailViewNode aggNode = entry.getKey();
|
final DetailViewNode<?> aggNode = entry.getKey();
|
||||||
final Line line = entry.getValue();
|
final Line line = entry.getValue();
|
||||||
|
|
||||||
line.setStartX(getParentXForValue(new DateTime(aggNode.getStartMillis(), TimeLineController.getJodaTimeZone())));
|
line.setStartX(getParentXForValue(new DateTime(aggNode.getStartMillis(), TimeLineController.getJodaTimeZone())));
|
||||||
@ -760,7 +748,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
|
|||||||
return alternateLayout;
|
return alternateLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StartTimeComparator<T extends Node & DetailViewNode> implements Comparator<T> {
|
private static class StartTimeComparator<T extends Node & DetailViewNode<?>> implements Comparator<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(T n1, T n2) {
|
public int compare(T n1, T n2) {
|
||||||
|
@ -18,6 +18,7 @@ import javafx.event.EventHandler;
|
|||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.OverrunStyle;
|
import javafx.scene.control.OverrunStyle;
|
||||||
@ -29,7 +30,6 @@ import javafx.scene.input.MouseEvent;
|
|||||||
import javafx.scene.layout.Background;
|
import javafx.scene.layout.Background;
|
||||||
import javafx.scene.layout.BackgroundFill;
|
import javafx.scene.layout.BackgroundFill;
|
||||||
import javafx.scene.layout.Border;
|
import javafx.scene.layout.Border;
|
||||||
import javafx.scene.layout.BorderPane;
|
|
||||||
import javafx.scene.layout.BorderStroke;
|
import javafx.scene.layout.BorderStroke;
|
||||||
import javafx.scene.layout.BorderStrokeStyle;
|
import javafx.scene.layout.BorderStrokeStyle;
|
||||||
import javafx.scene.layout.BorderWidths;
|
import javafx.scene.layout.BorderWidths;
|
||||||
@ -41,6 +41,7 @@ import javafx.scene.layout.Region;
|
|||||||
import static javafx.scene.layout.Region.USE_COMPUTED_SIZE;
|
import static javafx.scene.layout.Region.USE_COMPUTED_SIZE;
|
||||||
import static javafx.scene.layout.Region.USE_PREF_SIZE;
|
import static javafx.scene.layout.Region.USE_PREF_SIZE;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
@ -64,7 +65,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class EventStripeNode extends StackPane implements DetailViewNode {
|
public class EventStripeNode extends StackPane implements DetailViewNode<EventStripeNode> {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(EventClusterNode.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(EventClusterNode.class.getName());
|
||||||
|
|
||||||
@ -94,20 +95,28 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
private final ImageView tagIV = new ImageView(TAG);
|
private final ImageView tagIV = new ImageView(TAG);
|
||||||
private final Button plusButton = new Button(null, new ImageView(PLUS)) {
|
private final Button plusButton = new Button(null, new ImageView(PLUS)) {
|
||||||
{
|
{
|
||||||
setMinSize(16, 16);
|
configureLODButton(this);
|
||||||
setMaxSize(16, 16);
|
|
||||||
setPrefSize(16, 16);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final Button minusButton = new Button(null, new ImageView(MINUS)) {
|
private final Button minusButton = new Button(null, new ImageView(MINUS)) {
|
||||||
{
|
{
|
||||||
setMinSize(16, 16);
|
configureLODButton(this);
|
||||||
setMaxSize(16, 16);
|
|
||||||
setPrefSize(16, 16);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static void configureLODButton(Button b) {
|
||||||
|
b.setMinSize(16, 16);
|
||||||
|
b.setMaxSize(16, 16);
|
||||||
|
b.setPrefSize(16, 16);
|
||||||
|
show(b, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void show(Node b, boolean show) {
|
||||||
|
b.setVisible(show);
|
||||||
|
b.setManaged(show);
|
||||||
|
}
|
||||||
private DescriptionVisibility descrVis;
|
private DescriptionVisibility descrVis;
|
||||||
private final HBox spanRegion = new HBox();
|
private final HBox spansHBox = new HBox();
|
||||||
/**
|
/**
|
||||||
* The IamgeView used to show the icon for this node's event's type
|
* The IamgeView used to show the icon for this node's event's type
|
||||||
*/
|
*/
|
||||||
@ -127,43 +136,36 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
final Region spacer = new Region();
|
final Region spacer = new Region();
|
||||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||||
|
|
||||||
final HBox hBox = new HBox(descrLabel, countLabel, spacer, hashIV, tagIV, minusButton, plusButton);
|
final HBox header = new HBox(descrLabel, countLabel, hashIV, tagIV, spacer, minusButton, plusButton);
|
||||||
if (cluster.getEventIDsWithHashHits().isEmpty()) {
|
if (cluster.getEventIDsWithHashHits().isEmpty()) {
|
||||||
hashIV.setManaged(false);
|
show(hashIV, false);
|
||||||
hashIV.setVisible(false);
|
|
||||||
}
|
}
|
||||||
if (cluster.getEventIDsWithTags().isEmpty()) {
|
if (cluster.getEventIDsWithTags().isEmpty()) {
|
||||||
tagIV.setManaged(false);
|
show(tagIV, false);
|
||||||
tagIV.setVisible(false);
|
|
||||||
}
|
}
|
||||||
hBox.setPrefWidth(USE_COMPUTED_SIZE);
|
header.setMinWidth(USE_PREF_SIZE);
|
||||||
hBox.setMinWidth(USE_PREF_SIZE);
|
header.setPadding(new Insets(2, 5, 2, 5));
|
||||||
hBox.setPadding(new Insets(2, 5, 2, 5));
|
header.setAlignment(Pos.CENTER_LEFT);
|
||||||
hBox.setAlignment(Pos.CENTER_LEFT);
|
|
||||||
|
|
||||||
minusButton.setVisible(false);
|
final VBox internalVBox = new VBox(header, subNodePane);
|
||||||
plusButton.setVisible(false);
|
internalVBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
minusButton.setManaged(false);
|
|
||||||
plusButton.setManaged(false);
|
|
||||||
final BorderPane borderPane = new BorderPane(subNodePane, hBox, null, null, null);
|
|
||||||
BorderPane.setAlignment(subNodePane, Pos.TOP_LEFT);
|
|
||||||
borderPane.setPrefWidth(USE_COMPUTED_SIZE);
|
|
||||||
final Color evtColor = cluster.getType().getColor();
|
final Color evtColor = cluster.getType().getColor();
|
||||||
|
|
||||||
spanFill = new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .2), CORNER_RADII, Insets.EMPTY));
|
spanFill = new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .2), CORNER_RADII, Insets.EMPTY));
|
||||||
for (Range<Long> r : cluster.getRanges()) {
|
for (Range<Long> r : cluster.getRanges()) {
|
||||||
Region region = new Region();
|
Region spanRegion = new Region();
|
||||||
region.setStyle("-fx-border-width:2 1 2 1; -fx-border-radius: 1; -fx-border-color: " + ColorUtilities.getRGBCode(evtColor.deriveColor(0, 1, 1, .3)) + ";"); // NON-NLS
|
spanRegion.setStyle("-fx-border-width:2 1 2 1; -fx-border-radius: 1; -fx-border-color: " + ColorUtilities.getRGBCode(evtColor.deriveColor(0, 1, 1, .3)) + ";"); // NON-NLS
|
||||||
region.setBackground(spanFill);
|
spanRegion.setBackground(spanFill);
|
||||||
spanRegion.getChildren().addAll(region, new Region());
|
spansHBox.getChildren().addAll(spanRegion, new Region());
|
||||||
}
|
}
|
||||||
spanRegion.getChildren().remove(spanRegion.getChildren().size() - 1);
|
spansHBox.getChildren().remove(spansHBox.getChildren().size() - 1);
|
||||||
|
spansHBox.setMaxWidth(USE_PREF_SIZE);
|
||||||
getChildren().addAll(spanRegion, borderPane);
|
setMaxWidth(USE_PREF_SIZE);
|
||||||
setBackground(new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .1), CORNER_RADII, Insets.EMPTY)));
|
getChildren().addAll(spansHBox, internalVBox);
|
||||||
|
setBackground(new Background(new BackgroundFill(evtColor.deriveColor(0, 1, 1, .05), CORNER_RADII, Insets.EMPTY)));
|
||||||
setAlignment(Pos.TOP_LEFT);
|
setAlignment(Pos.TOP_LEFT);
|
||||||
setMinHeight(24);
|
setMinHeight(24);
|
||||||
minWidthProperty().bind(spanRegion.widthProperty());
|
minWidthProperty().bind(spansHBox.widthProperty());
|
||||||
setPrefHeight(USE_COMPUTED_SIZE);
|
setPrefHeight(USE_COMPUTED_SIZE);
|
||||||
setMaxHeight(USE_PREF_SIZE);
|
setMaxHeight(USE_PREF_SIZE);
|
||||||
|
|
||||||
@ -189,20 +191,20 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
setOnMouseEntered((MouseEvent e) -> {
|
setOnMouseEntered((MouseEvent e) -> {
|
||||||
//defer tooltip creation till needed, this had a surprisingly large impact on speed of loading the chart
|
//defer tooltip creation till needed, this had a surprisingly large impact on speed of loading the chart
|
||||||
// installTooltip();
|
// installTooltip();
|
||||||
spanRegion.setEffect(new DropShadow(10, evtColor));
|
spansHBox.setEffect(new DropShadow(10, evtColor));
|
||||||
minusButton.setVisible(true);
|
show(spacer, true);
|
||||||
plusButton.setVisible(true);
|
show(minusButton, true);
|
||||||
minusButton.setManaged(true);
|
show(plusButton, true);
|
||||||
plusButton.setManaged(true);
|
|
||||||
toFront();
|
toFront();
|
||||||
});
|
});
|
||||||
|
|
||||||
setOnMouseExited((MouseEvent e) -> {
|
setOnMouseExited((MouseEvent e) -> {
|
||||||
spanRegion.setEffect(null);
|
spansHBox.setEffect(null);
|
||||||
minusButton.setVisible(false);
|
show(spacer, false);
|
||||||
plusButton.setVisible(false);
|
show(minusButton, false);
|
||||||
minusButton.setManaged(false);
|
show(plusButton, false);
|
||||||
plusButton.setManaged(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
plusButton.disableProperty().bind(descLOD.isEqualTo(DescriptionLOD.FULL));
|
plusButton.disableProperty().bind(descLOD.isEqualTo(DescriptionLOD.FULL));
|
||||||
@ -232,11 +234,11 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
@Override
|
@Override
|
||||||
public void setSpanWidths(List<Double> spanWidths) {
|
public void setSpanWidths(List<Double> spanWidths) {
|
||||||
for (int i = 0; i < spanWidths.size(); i++) {
|
for (int i = 0; i < spanWidths.size(); i++) {
|
||||||
Region get = (Region) spanRegion.getChildren().get(i);
|
Region spanRegion = (Region) spansHBox.getChildren().get(i);
|
||||||
Double w = spanWidths.get(i);
|
Double w = spanWidths.get(i);
|
||||||
get.setPrefWidth(w);
|
spanRegion.setPrefWidth(w);
|
||||||
get.setMaxWidth(w);
|
spanRegion.setMaxWidth(w);
|
||||||
get.setMinWidth(Math.max(2, w));
|
spanRegion.setMinWidth(Math.max(2, w));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,8 +282,10 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pane getSubNodePane() {
|
public List<EventStripeNode> getSubNodes() {
|
||||||
return subNodePane;
|
return subNodePane.getChildrenUnmodifiable().stream()
|
||||||
|
.map(EventStripeNode.class::cast)
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -339,6 +343,26 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apply the 'effect' to visually indicate highlighted nodes
|
||||||
|
*
|
||||||
|
* @param applied true to apply the highlight 'effect', false to remove it
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized void applyHighlightEffect(boolean applied) {
|
||||||
|
if (applied) {
|
||||||
|
descrLabel.setStyle("-fx-font-weight: bold;"); // NON-NLS
|
||||||
|
spanFill = new Background(new BackgroundFill(cluster.getType().getColor().deriveColor(0, 1, 1, .3), CORNER_RADII, Insets.EMPTY));
|
||||||
|
spansHBox.setBackground(spanFill);
|
||||||
|
setBackground(new Background(new BackgroundFill(cluster.getType().getColor().deriveColor(0, 1, 1, .2), CORNER_RADII, Insets.EMPTY)));
|
||||||
|
} else {
|
||||||
|
descrLabel.setStyle("-fx-font-weight: normal;"); // NON-NLS
|
||||||
|
spanFill = new Background(new BackgroundFill(cluster.getType().getColor().deriveColor(0, 1, 1, .1), CORNER_RADII, Insets.EMPTY));
|
||||||
|
spansHBox.setBackground(spanFill);
|
||||||
|
setBackground(new Background(new BackgroundFill(cluster.getType().getColor().deriveColor(0, 1, 1, .1), CORNER_RADII, Insets.EMPTY)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return cluster.getDescription();
|
return cluster.getDescription();
|
||||||
@ -355,11 +379,14 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
* @param newDescriptionLOD
|
* @param newDescriptionLOD
|
||||||
*/
|
*/
|
||||||
synchronized private void loadSubClusters(DescriptionLOD newDescriptionLOD) {
|
synchronized private void loadSubClusters(DescriptionLOD newDescriptionLOD) {
|
||||||
getSubNodePane().getChildren().clear();
|
subNodePane.getChildren().clear();
|
||||||
|
|
||||||
if (newDescriptionLOD == cluster.getDescriptionLOD()) {
|
if (newDescriptionLOD == cluster.getDescriptionLOD()) {
|
||||||
|
spansHBox.setVisible(true);
|
||||||
chart.setRequiresLayout(true);
|
chart.setRequiresLayout(true);
|
||||||
chart.requestChartLayout();
|
chart.requestChartLayout();
|
||||||
} else {
|
} else {
|
||||||
|
spansHBox.setVisible(false);
|
||||||
RootFilter combinedFilter = eventsModel.filterProperty().get().copyOf();
|
RootFilter combinedFilter = eventsModel.filterProperty().get().copyOf();
|
||||||
//make a new filter intersecting the global filter with text(description) and type filters to restrict sub-clusters
|
//make a new filter intersecting the global filter with text(description) and type filters to restrict sub-clusters
|
||||||
combinedFilter.getSubFilters().addAll(new TextFilter(cluster.getDescription()),
|
combinedFilter.getSubFilters().addAll(new TextFilter(cluster.getDescription()),
|
||||||
@ -402,7 +429,7 @@ public class EventStripeNode extends StackPane implements DetailViewNode {
|
|||||||
try {
|
try {
|
||||||
chart.setCursor(Cursor.WAIT);
|
chart.setCursor(Cursor.WAIT);
|
||||||
//assign subNodes and request chart layout
|
//assign subNodes and request chart layout
|
||||||
getSubNodePane().getChildren().setAll(get());
|
subNodePane.getChildren().setAll(get());
|
||||||
setDescriptionVisibility(descrVis);
|
setDescriptionVisibility(descrVis);
|
||||||
chart.setRequiresLayout(true);
|
chart.setRequiresLayout(true);
|
||||||
chart.requestChartLayout();
|
chart.requestChartLayout();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user