mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 11:07:43 +00:00
Merge pull request #2100 from millmanorama/TL-only-snapshot-visualization
TL only snapshot visualization
This commit is contained in:
commit
1793aa2c5d
@ -25,6 +25,7 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javafx.embed.swing.SwingFXUtils;
|
import javafx.embed.swing.SwingFXUtils;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
@ -81,7 +82,7 @@ public class SaveSnapshotAsReport extends Action {
|
|||||||
"SaveSnapShotAsReport.reportName.prompt=leave empty for default report name: {0}.",
|
"SaveSnapShotAsReport.reportName.prompt=leave empty for default report name: {0}.",
|
||||||
"SaveSnapShotAsReport.reportName.header=Enter a report name for the Timeline Snapshot Report."
|
"SaveSnapShotAsReport.reportName.header=Enter a report name for the Timeline Snapshot Report."
|
||||||
})
|
})
|
||||||
public SaveSnapshotAsReport(TimeLineController controller, Node node) {
|
public SaveSnapshotAsReport(TimeLineController controller, Supplier<Node> nodeSupplier) {
|
||||||
super(Bundle.SaveSnapShotAsReport_action_name_text());
|
super(Bundle.SaveSnapShotAsReport_action_name_text());
|
||||||
setLongText(Bundle.SaveSnapShotAsReport_action_longText());
|
setLongText(Bundle.SaveSnapShotAsReport_action_longText());
|
||||||
setGraphic(new ImageView(SNAP_SHOT));
|
setGraphic(new ImageView(SNAP_SHOT));
|
||||||
@ -93,8 +94,7 @@ public class SaveSnapshotAsReport extends Action {
|
|||||||
//capture generation date and use to make default report name
|
//capture generation date and use to make default report name
|
||||||
Date generationDate = new Date();
|
Date generationDate = new Date();
|
||||||
final String defaultReportName = FileUtil.escapeFileName(currentCase.getName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS
|
final String defaultReportName = FileUtil.escapeFileName(currentCase.getName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS
|
||||||
|
BufferedImage snapshot = SwingFXUtils.fromFXImage(nodeSupplier.get().snapshot(null, null), null);
|
||||||
BufferedImage snapshot = SwingFXUtils.fromFXImage(node.snapshot(null, null), null);
|
|
||||||
|
|
||||||
//prompt user to pick report name
|
//prompt user to pick report name
|
||||||
TextInputDialog textInputDialog = new TextInputDialog();
|
TextInputDialog textInputDialog = new TextInputDialog();
|
||||||
|
@ -29,6 +29,7 @@ import java.util.logging.Level;
|
|||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.InvalidationListener;
|
import javafx.beans.InvalidationListener;
|
||||||
import javafx.beans.Observable;
|
import javafx.beans.Observable;
|
||||||
|
import javafx.beans.binding.DoubleBinding;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
@ -46,9 +47,11 @@ import javafx.scene.control.OverrunStyle;
|
|||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.effect.Effect;
|
import javafx.scene.effect.Effect;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
import javafx.scene.text.FontWeight;
|
import javafx.scene.text.FontWeight;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
@ -81,15 +84,15 @@ import org.sleuthkit.autopsy.timeline.events.RefreshRequestedEvent;
|
|||||||
* common history context menu items out of derived classes? -jm
|
* common history context menu items out of derived classes? -jm
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, ChartType extends Region & TimeLineChart<X>> extends BorderPane {
|
public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, ChartType extends Region & TimeLineChart<X>> extends BorderPane {
|
||||||
|
|
||||||
@NbBundle.Messages("AbstractVisualization.Default_Tooltip.text=Drag the mouse to select a time interval to zoom into.\nRight-click for more actions.")
|
@NbBundle.Messages("AbstractVisualization.Default_Tooltip.text=Drag the mouse to select a time interval to zoom into.\nRight-click for more actions.")
|
||||||
private static final Tooltip DEFAULT_TOOLTIP = new Tooltip(Bundle.AbstractVisualization_Default_Tooltip_text());
|
private static final Tooltip DEFAULT_TOOLTIP = new Tooltip(Bundle.AbstractVisualization_Default_Tooltip_text());
|
||||||
private static final Logger LOGGER = Logger.getLogger(AbstractVisualizationPane.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(AbstractVisualizationPane.class.getName());
|
||||||
|
|
||||||
public static Tooltip getDefaultTooltip() {
|
public static Tooltip getDefaultTooltip() {
|
||||||
return DEFAULT_TOOLTIP;
|
return DEFAULT_TOOLTIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final SimpleBooleanProperty hasEvents = new SimpleBooleanProperty(true);
|
protected final SimpleBooleanProperty hasEvents = new SimpleBooleanProperty(true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,29 +100,29 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
*/
|
*/
|
||||||
protected final ObservableList<XYChart.Series<X, Y>> dataSeries = FXCollections.<XYChart.Series<X, Y>>observableArrayList();
|
protected final ObservableList<XYChart.Series<X, Y>> dataSeries = FXCollections.<XYChart.Series<X, Y>>observableArrayList();
|
||||||
protected final Map<EventType, XYChart.Series<X, Y>> eventTypeToSeriesMap = new HashMap<>();
|
protected final Map<EventType, XYChart.Series<X, Y>> eventTypeToSeriesMap = new HashMap<>();
|
||||||
|
|
||||||
protected ChartType chart;
|
protected ChartType chart;
|
||||||
|
|
||||||
//// replacement axis label componenets
|
//// replacement axis label componenets
|
||||||
private final Pane leafPane; // container for the leaf lables in the declutterd axis
|
private final Pane leafPane = new Pane(); // container for the leaf lables in the declutterd axis
|
||||||
private final Pane branchPane;// container for the branch lables in the declutterd axis
|
private final Pane branchPane = new Pane();// container for the branch lables in the declutterd axis
|
||||||
protected final Region spacer;
|
protected final Region spacer = new Region();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* task used to reload the content of this visualization
|
* task used to reload the content of this visualization
|
||||||
*/
|
*/
|
||||||
private Task<Boolean> updateTask;
|
private Task<Boolean> updateTask;
|
||||||
|
|
||||||
final protected TimeLineController controller;
|
final protected TimeLineController controller;
|
||||||
|
|
||||||
final protected FilteredEventsModel filteredEvents;
|
final protected FilteredEventsModel filteredEvents;
|
||||||
|
|
||||||
final protected ObservableList<NodeType> selectedNodes = FXCollections.observableArrayList();
|
final protected ObservableList<NodeType> selectedNodes = FXCollections.observableArrayList();
|
||||||
|
|
||||||
private InvalidationListener invalidationListener = (Observable observable) -> {
|
private InvalidationListener invalidationListener = (Observable observable) -> {
|
||||||
update();
|
update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public ObservableList<NodeType> getSelectedNodes() {
|
public ObservableList<NodeType> getSelectedNodes() {
|
||||||
return selectedNodes;
|
return selectedNodes;
|
||||||
}
|
}
|
||||||
@ -129,7 +132,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
* an implementations constructor.
|
* an implementations constructor.
|
||||||
*/
|
*/
|
||||||
protected List<Node> settingsNodes;
|
protected List<Node> settingsNodes;
|
||||||
|
|
||||||
public TimeLineController getController() {
|
public TimeLineController getController() {
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
@ -196,7 +199,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
* @return the vertical axis used by this Visualization's chart
|
* @return the vertical axis used by this Visualization's chart
|
||||||
*/
|
*/
|
||||||
abstract protected Axis<Y> getYAxis();
|
abstract protected Axis<Y> getYAxis();
|
||||||
|
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
abstract protected void resetData();
|
abstract protected void resetData();
|
||||||
|
|
||||||
@ -233,7 +236,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
});
|
});
|
||||||
controller.monitorTask(updateTask);
|
controller.monitorTask(updateTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
final synchronized public void dispose() {
|
final synchronized public void dispose() {
|
||||||
if (updateTask != null) {
|
if (updateTask != null) {
|
||||||
updateTask.cancel(true);
|
updateTask.cancel(true);
|
||||||
@ -264,32 +267,40 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
protected final XYChart.Series<X, Y> getSeries(final EventType et) {
|
protected final XYChart.Series<X, Y> getSeries(final EventType et) {
|
||||||
return eventTypeToSeriesMap.get(et);
|
return eventTypeToSeriesMap.get(et);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractVisualizationPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) {
|
protected AbstractVisualizationPane(TimeLineController controller) {
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
this.filteredEvents = controller.getEventsModel();
|
this.filteredEvents = controller.getEventsModel();
|
||||||
this.filteredEvents.registerForEvents(this);
|
this.filteredEvents.registerForEvents(this);
|
||||||
this.filteredEvents.zoomParametersProperty().addListener(invalidationListener);
|
this.filteredEvents.zoomParametersProperty().addListener(invalidationListener);
|
||||||
this.leafPane = partPane;
|
Platform.runLater(() -> {
|
||||||
this.branchPane = contextPane;
|
VBox vBox = new VBox(leafPane, branchPane);
|
||||||
this.spacer = spacer;
|
vBox.setFillWidth(false);
|
||||||
|
HBox hBox = new HBox(spacer, vBox);
|
||||||
|
hBox.setFillHeight(false);
|
||||||
|
setBottom(hBox);
|
||||||
|
DoubleBinding spacerSize = getYAxis().widthProperty().add(getYAxis().tickLengthProperty()).add(getAxisMargin());//getXAxis().startMarginProperty().multiply(2));
|
||||||
|
spacer.minWidthProperty().bind(spacerSize);
|
||||||
|
spacer.prefWidthProperty().bind(spacerSize);
|
||||||
|
spacer.maxWidthProperty().bind(spacerSize);
|
||||||
|
});
|
||||||
|
|
||||||
createSeries();
|
createSeries();
|
||||||
|
|
||||||
selectedNodes.addListener((ListChangeListener.Change<? extends NodeType> c) -> {
|
selectedNodes.addListener((ListChangeListener.Change<? extends NodeType> c) -> {
|
||||||
while (c.next()) {
|
while (c.next()) {
|
||||||
c.getRemoved().forEach(n -> applySelectionEffect(n, false));
|
c.getRemoved().forEach(n -> applySelectionEffect(n, false));
|
||||||
c.getAddedSubList().forEach(n -> applySelectionEffect(n, true));
|
c.getAddedSubList().forEach(n -> applySelectionEffect(n, true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
TimeLineController.getTimeZone().addListener(invalidationListener);
|
TimeLineController.getTimeZone().addListener(invalidationListener);
|
||||||
|
|
||||||
//show tooltip text in status bar
|
//show tooltip text in status bar
|
||||||
hoverProperty().addListener(observable -> controller.setStatus(isHover() ? DEFAULT_TOOLTIP.getText() : ""));
|
hoverProperty().addListener(observable -> controller.setStatus(isHover() ? DEFAULT_TOOLTIP.getText() : ""));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void handleRefreshRequested(RefreshRequestedEvent event) {
|
public void handleRefreshRequested(RefreshRequestedEvent event) {
|
||||||
update();
|
update();
|
||||||
@ -321,7 +332,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
//make a clone of the list sorted by position along axis
|
//make a clone of the list sorted by position along axis
|
||||||
ObservableList<Axis.TickMark<X>> tickMarks = FXCollections.observableArrayList(getXAxis().getTickMarks());
|
ObservableList<Axis.TickMark<X>> tickMarks = FXCollections.observableArrayList(getXAxis().getTickMarks());
|
||||||
tickMarks.sort(Comparator.comparing(Axis.TickMark::getPosition));
|
tickMarks.sort(Comparator.comparing(Axis.TickMark::getPosition));
|
||||||
|
|
||||||
if (tickMarks.isEmpty() == false) {
|
if (tickMarks.isEmpty() == false) {
|
||||||
//get the spacing between ticks in the underlying axis
|
//get the spacing between ticks in the underlying axis
|
||||||
double spacing = getTickSpacing();
|
double spacing = getTickSpacing();
|
||||||
@ -333,7 +344,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
|
|
||||||
//x-positions (pixels) of the current branch and leaf labels
|
//x-positions (pixels) of the current branch and leaf labels
|
||||||
double leafLabelX = 0;
|
double leafLabelX = 0;
|
||||||
|
|
||||||
if (dateTime.branch.isEmpty()) {
|
if (dateTime.branch.isEmpty()) {
|
||||||
//if there is only one part to the date (ie only year), just add a label for each tick
|
//if there is only one part to the date (ie only year), just add a label for each tick
|
||||||
for (Axis.TickMark<X> t : tickMarks) {
|
for (Axis.TickMark<X> t : tickMarks) {
|
||||||
@ -342,7 +353,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
leafLabelX,
|
leafLabelX,
|
||||||
isTickBold(t.getValue())
|
isTickBold(t.getValue())
|
||||||
);
|
);
|
||||||
|
|
||||||
leafLabelX += spacing; //increment x
|
leafLabelX += spacing; //increment x
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -350,7 +361,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
//initialize additional state
|
//initialize additional state
|
||||||
double branchLabelX = 0;
|
double branchLabelX = 0;
|
||||||
double branchLabelWidth = 0;
|
double branchLabelWidth = 0;
|
||||||
|
|
||||||
for (Axis.TickMark<X> t : tickMarks) { //for each tick
|
for (Axis.TickMark<X> t : tickMarks) { //for each tick
|
||||||
|
|
||||||
//split the label into a TwoPartDateTime
|
//split the label into a TwoPartDateTime
|
||||||
@ -391,21 +402,21 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
* @param bold true if the text should be bold, false otherwise
|
* @param bold true if the text should be bold, false otherwise
|
||||||
*/
|
*/
|
||||||
private synchronized void assignLeafLabel(String labelText, double labelWidth, double labelX, boolean bold) {
|
private synchronized void assignLeafLabel(String labelText, double labelWidth, double labelX, boolean bold) {
|
||||||
|
|
||||||
Text label = new Text(" " + labelText + " "); //NOI18N
|
Text label = new Text(" " + labelText + " "); //NOI18N
|
||||||
label.setTextAlignment(TextAlignment.CENTER);
|
label.setTextAlignment(TextAlignment.CENTER);
|
||||||
label.setFont(Font.font(null, bold ? FontWeight.BOLD : FontWeight.NORMAL, 10));
|
label.setFont(Font.font(null, bold ? FontWeight.BOLD : FontWeight.NORMAL, 10));
|
||||||
//position label accounting for width
|
//position label accounting for width
|
||||||
label.relocate(labelX + labelWidth / 2 - label.getBoundsInLocal().getWidth() / 2, 0);
|
label.relocate(labelX + labelWidth / 2 - label.getBoundsInLocal().getWidth() / 2, 0);
|
||||||
label.autosize();
|
label.autosize();
|
||||||
|
|
||||||
if (leafPane.getChildren().isEmpty()) {
|
if (leafPane.getChildren().isEmpty()) {
|
||||||
//just add first label
|
//just add first label
|
||||||
leafPane.getChildren().add(label);
|
leafPane.getChildren().add(label);
|
||||||
} else {
|
} else {
|
||||||
//otherwise don't actually add the label if it would intersect with previous label
|
//otherwise don't actually add the label if it would intersect with previous label
|
||||||
final Text lastLabel = (Text) leafPane.getChildren().get(leafPane.getChildren().size() - 1);
|
final Text lastLabel = (Text) leafPane.getChildren().get(leafPane.getChildren().size() - 1);
|
||||||
|
|
||||||
if (!lastLabel.getBoundsInParent().intersects(label.getBoundsInParent())) {
|
if (!lastLabel.getBoundsInParent().intersects(label.getBoundsInParent())) {
|
||||||
leafPane.getChildren().add(label);
|
leafPane.getChildren().add(label);
|
||||||
}
|
}
|
||||||
@ -421,7 +432,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
* @param labelX the horizontal position in the partPane of the text
|
* @param labelX the horizontal position in the partPane of the text
|
||||||
*/
|
*/
|
||||||
private synchronized void assignBranchLabel(String labelText, double labelWidth, double labelX) {
|
private synchronized void assignBranchLabel(String labelText, double labelWidth, double labelX) {
|
||||||
|
|
||||||
Label label = new Label(labelText);
|
Label label = new Label(labelText);
|
||||||
label.setAlignment(Pos.CENTER);
|
label.setAlignment(Pos.CENTER);
|
||||||
label.setTextAlignment(TextAlignment.CENTER);
|
label.setTextAlignment(TextAlignment.CENTER);
|
||||||
@ -434,15 +445,17 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
label.setPrefWidth(labelWidth);
|
label.setPrefWidth(labelWidth);
|
||||||
label.setMaxWidth(labelWidth);
|
label.setMaxWidth(labelWidth);
|
||||||
label.relocate(labelX, 0);
|
label.relocate(labelX, 0);
|
||||||
|
|
||||||
if (labelX == 0) { // first label has no border
|
if (labelX == 0) { // first label has no border
|
||||||
label.setStyle("-fx-border-width: 0 0 0 0 ; -fx-border-color:black;"); // NON-NLS //NOI18N
|
label.setStyle("-fx-border-width: 0 0 0 0 ; -fx-border-color:black;"); // NON-NLS //NOI18N
|
||||||
} else { // subsequent labels have border on left to create dividers
|
} else { // subsequent labels have border on left to create dividers
|
||||||
label.setStyle("-fx-border-width: 0 0 0 1; -fx-border-color:black;"); // NON-NLS //NOI18N
|
label.setStyle("-fx-border-width: 0 0 0 1; -fx-border-color:black;"); // NON-NLS //NOI18N
|
||||||
}
|
}
|
||||||
|
|
||||||
branchPane.getChildren().add(label);
|
branchPane.getChildren().add(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract double getAxisMargin();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple data object used to represent a partial date as up to two parts.
|
* A simple data object used to represent a partial date as up to two parts.
|
||||||
@ -465,7 +478,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
* the highest frequency part of a date/time eg 14 (2pm)
|
* the highest frequency part of a date/time eg 14 (2pm)
|
||||||
*/
|
*/
|
||||||
private final String leaf;
|
private final String leaf;
|
||||||
|
|
||||||
TwoPartDateTime(String dateString) {
|
TwoPartDateTime(String dateString) {
|
||||||
//find index of separator to spit on
|
//find index of separator to spit on
|
||||||
int splitIndex = StringUtils.lastIndexOfAny(dateString, " ", "-", ":"); //NOI18N
|
int splitIndex = StringUtils.lastIndexOfAny(dateString, " ", "-", ":"); //NOI18N
|
||||||
@ -478,7 +491,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Interval getTimeRange() {
|
protected Interval getTimeRange() {
|
||||||
return filteredEvents.timeRangeProperty().get();
|
return filteredEvents.timeRangeProperty().get();
|
||||||
}
|
}
|
||||||
@ -490,7 +503,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
* @param <AxisValuesType> the type of data displayed along the X-Axis.
|
* @param <AxisValuesType> the type of data displayed along the X-Axis.
|
||||||
*/
|
*/
|
||||||
abstract protected class VisualizationUpdateTask<AxisValuesType> extends LoggedTask<Boolean> {
|
abstract protected class VisualizationUpdateTask<AxisValuesType> extends LoggedTask<Boolean> {
|
||||||
|
|
||||||
protected VisualizationUpdateTask(String taskName, boolean logStateChanges) {
|
protected VisualizationUpdateTask(String taskName, boolean logStateChanges) {
|
||||||
super(taskName, logStateChanges);
|
super(taskName, logStateChanges);
|
||||||
}
|
}
|
||||||
@ -516,7 +529,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
setCenter(new StackPane(center, maskerPane));
|
setCenter(new StackPane(center, maskerPane));
|
||||||
setCursor(Cursor.WAIT);
|
setCursor(Cursor.WAIT);
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private final Node center = getCenter();
|
private final Node center = getCenter();
|
||||||
@ -530,7 +543,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
protected void succeeded() {
|
protected void succeeded() {
|
||||||
super.succeeded();
|
super.succeeded();
|
||||||
layoutDateLabels();
|
layoutDateLabels();
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
setCenter(center); //clear masker pane
|
setCenter(center); //clear masker pane
|
||||||
setCursor(Cursor.DEFAULT);
|
setCursor(Cursor.DEFAULT);
|
||||||
@ -545,13 +558,13 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
|||||||
*/
|
*/
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.NOT_UI)
|
@ThreadConfined(type = ThreadConfined.ThreadType.NOT_UI)
|
||||||
protected void resetChart(AxisValuesType axisValues) {
|
protected void resetChart(AxisValuesType axisValues) {
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
resetData();
|
resetData();
|
||||||
setDateAxisValues(axisValues);
|
setDateAxisValues(axisValues);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected void setDateAxisValues(AxisValuesType values);
|
abstract protected void setDateAxisValues(AxisValuesType values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.scene.text.*?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import java.lang.*?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.geometry.*?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.MenuButton?>
|
||||||
<?import javafx.scene.image.*?>
|
<?import javafx.scene.control.Separator?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.control.ToggleButton?>
|
||||||
|
<?import javafx.scene.control.ToolBar?>
|
||||||
|
<?import javafx.scene.image.Image?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
|
<?import javafx.scene.layout.BorderPane?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.layout.StackPane?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<?import javafx.scene.text.Font?>
|
||||||
|
<?import org.controlsfx.control.SegmentedButton?>
|
||||||
<?import jfxtras.scene.control.*?>
|
<?import jfxtras.scene.control.*?>
|
||||||
<?import org.controlsfx.control.*?>
|
|
||||||
|
|
||||||
<fx:root prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.BorderPane" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
|
<fx:root prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.BorderPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<top>
|
<top>
|
||||||
<ToolBar fx:id="toolBar" prefWidth="200.0" BorderPane.alignment="CENTER">
|
<ToolBar fx:id="toolBar" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||||
<items>
|
<items>
|
||||||
@ -78,17 +86,6 @@
|
|||||||
<bottom>
|
<bottom>
|
||||||
<VBox maxHeight="-Infinity">
|
<VBox maxHeight="-Infinity">
|
||||||
<children>
|
<children>
|
||||||
<HBox fillHeight="false" BorderPane.alignment="CENTER">
|
|
||||||
<children>
|
|
||||||
<Region fx:id="spacer" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="5.0" prefWidth="20.0" />
|
|
||||||
<VBox fillWidth="false">
|
|
||||||
<children>
|
|
||||||
<Pane fx:id="partPane" />
|
|
||||||
<Pane fx:id="contextPane" />
|
|
||||||
</children>
|
|
||||||
</VBox>
|
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
<Separator />
|
<Separator />
|
||||||
<Separator />
|
<Separator />
|
||||||
<StackPane fx:id="rangeHistogramStack" maxHeight="-Infinity" BorderPane.alignment="CENTER">
|
<StackPane fx:id="rangeHistogramStack" maxHeight="-Infinity" BorderPane.alignment="CENTER">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-15 Basis Technology Corp.
|
* Copyright 2013-16 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -51,7 +51,6 @@ import javafx.scene.layout.BackgroundFill;
|
|||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.CornerRadii;
|
import javafx.scene.layout.CornerRadii;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import static javafx.scene.layout.Region.USE_PREF_SIZE;
|
import static javafx.scene.layout.Region.USE_PREF_SIZE;
|
||||||
@ -141,14 +140,6 @@ final public class VisualizationPanel extends BorderPane {
|
|||||||
@FXML
|
@FXML
|
||||||
private Label endLabel;
|
private Label endLabel;
|
||||||
|
|
||||||
//// replacemetn axis label componenets
|
|
||||||
@FXML
|
|
||||||
private Pane partPane;
|
|
||||||
@FXML
|
|
||||||
private Pane contextPane;
|
|
||||||
@FXML
|
|
||||||
private Region spacer;
|
|
||||||
|
|
||||||
//// header toolbar componenets
|
//// header toolbar componenets
|
||||||
@FXML
|
@FXML
|
||||||
private ToolBar toolBar;
|
private ToolBar toolBar;
|
||||||
@ -288,7 +279,7 @@ final public class VisualizationPanel extends BorderPane {
|
|||||||
setViewMode(controller.viewModeProperty().get());
|
setViewMode(controller.viewModeProperty().get());
|
||||||
|
|
||||||
//configure snapshor button / action
|
//configure snapshor button / action
|
||||||
ActionUtils.configureButton(new SaveSnapshotAsReport(controller, VisualizationPanel.this), snapShotButton);
|
ActionUtils.configureButton(new SaveSnapshotAsReport(controller, notificationPane::getContent), snapShotButton);
|
||||||
|
|
||||||
/////configure start and end pickers
|
/////configure start and end pickers
|
||||||
startLabel.setText(Bundle.VisualizationPanel_startLabel_text());
|
startLabel.setText(Bundle.VisualizationPanel_startLabel_text());
|
||||||
@ -359,11 +350,11 @@ final public class VisualizationPanel extends BorderPane {
|
|||||||
private void setViewMode(VisualizationMode visualizationMode) {
|
private void setViewMode(VisualizationMode visualizationMode) {
|
||||||
switch (visualizationMode) {
|
switch (visualizationMode) {
|
||||||
case COUNTS:
|
case COUNTS:
|
||||||
setVisualization(new CountsViewPane(controller, partPane, contextPane, spacer));
|
setVisualization(new CountsViewPane(controller));
|
||||||
countsToggle.setSelected(true);
|
countsToggle.setSelected(true);
|
||||||
break;
|
break;
|
||||||
case DETAIL:
|
case DETAIL:
|
||||||
setVisualization(new DetailViewPane(controller, partPane, contextPane, spacer));
|
setVisualization(new DetailViewPane(controller));
|
||||||
detailsToggle.setSelected(true);
|
detailsToggle.setSelected(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -427,54 +418,54 @@ final public class VisualizationPanel extends BorderPane {
|
|||||||
|
|
||||||
histogramTask = new LoggedTask<Void>(
|
histogramTask = new LoggedTask<Void>(
|
||||||
NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.title"), true) { // NON-NLS
|
NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.title"), true) { // NON-NLS
|
||||||
private final Lighting lighting = new Lighting();
|
private final Lighting lighting = new Lighting();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void call() throws Exception {
|
protected Void call() throws Exception {
|
||||||
|
|
||||||
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.preparing")); // NON-NLS
|
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.preparing")); // NON-NLS
|
||||||
|
|
||||||
long max = 0;
|
long max = 0;
|
||||||
final RangeDivisionInfo rangeInfo = RangeDivisionInfo.getRangeDivisionInfo(filteredEvents.getSpanningInterval());
|
final RangeDivisionInfo rangeInfo = RangeDivisionInfo.getRangeDivisionInfo(filteredEvents.getSpanningInterval());
|
||||||
final long lowerBound = rangeInfo.getLowerBound();
|
final long lowerBound = rangeInfo.getLowerBound();
|
||||||
final long upperBound = rangeInfo.getUpperBound();
|
final long upperBound = rangeInfo.getUpperBound();
|
||||||
Interval timeRange = new Interval(new DateTime(lowerBound, TimeLineController.getJodaTimeZone()), new DateTime(upperBound, TimeLineController.getJodaTimeZone()));
|
Interval timeRange = new Interval(new DateTime(lowerBound, TimeLineController.getJodaTimeZone()), new DateTime(upperBound, TimeLineController.getJodaTimeZone()));
|
||||||
|
|
||||||
//extend range to block bounderies (ie day, month, year)
|
//extend range to block bounderies (ie day, month, year)
|
||||||
int p = 0; // progress counter
|
int p = 0; // progress counter
|
||||||
|
|
||||||
//clear old data, and reset ranges and series
|
//clear old data, and reset ranges and series
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.resetUI")); // NON-NLS
|
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.resetUI")); // NON-NLS
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ArrayList<Long> bins = new ArrayList<>();
|
ArrayList<Long> bins = new ArrayList<>();
|
||||||
|
|
||||||
DateTime start = timeRange.getStart();
|
DateTime start = timeRange.getStart();
|
||||||
while (timeRange.contains(start)) {
|
while (timeRange.contains(start)) {
|
||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
DateTime end = start.plus(rangeInfo.getPeriodSize().getPeriod());
|
DateTime end = start.plus(rangeInfo.getPeriodSize().getPeriod());
|
||||||
final Interval interval = new Interval(start, end);
|
final Interval interval = new Interval(start, end);
|
||||||
//increment for next iteration
|
//increment for next iteration
|
||||||
|
|
||||||
start = end;
|
start = end;
|
||||||
|
|
||||||
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.queryDb")); // NON-NLS
|
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.queryDb")); // NON-NLS
|
||||||
//query for current range
|
//query for current range
|
||||||
long count = filteredEvents.getEventCounts(interval).values().stream().mapToLong(Long::valueOf).sum();
|
long count = filteredEvents.getEventCounts(interval).values().stream().mapToLong(Long::valueOf).sum();
|
||||||
bins.add(count);
|
bins.add(count);
|
||||||
|
|
||||||
max = Math.max(count, max);
|
max = Math.max(count, max);
|
||||||
|
|
||||||
final double fMax = Math.log(max);
|
final double fMax = Math.log(max);
|
||||||
final ArrayList<Long> fbins = new ArrayList<>(bins);
|
final ArrayList<Long> fbins = new ArrayList<>(bins);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.updateUI2")); // NON-NLS
|
updateMessage(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.histogramTask.updateUI2")); // NON-NLS
|
||||||
|
|
||||||
histogramBox.getChildren().clear();
|
histogramBox.getChildren().clear();
|
||||||
|
|
||||||
for (Long bin : fbins) {
|
for (Long bin : fbins) {
|
||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
@ -499,7 +490,7 @@ final public class VisualizationPanel extends BorderPane {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
new Thread(histogramTask).start();
|
new Thread(histogramTask).start();
|
||||||
controller.monitorTask(histogramTask);
|
controller.monitorTask(histogramTask);
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,6 @@ import javafx.scene.control.ToggleGroup;
|
|||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.effect.Effect;
|
import javafx.scene.effect.Effect;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import org.joda.time.Interval;
|
import org.joda.time.Interval;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
@ -100,8 +98,8 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
|||||||
return new CountsUpdateTask();
|
return new CountsUpdateTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CountsViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) {
|
public CountsViewPane(TimeLineController controller) {
|
||||||
super(controller, partPane, contextPane, spacer);
|
super(controller);
|
||||||
chart = new EventCountsChart(controller, dateAxis, countAxis, selectedNodes);
|
chart = new EventCountsChart(controller, dateAxis, countAxis, selectedNodes);
|
||||||
|
|
||||||
chart.setData(dataSeries);
|
chart.setData(dataSeries);
|
||||||
@ -111,19 +109,9 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
|||||||
|
|
||||||
settingsNodes = new ArrayList<>(new CountsViewSettingsPane().getChildrenUnmodifiable());
|
settingsNodes = new ArrayList<>(new CountsViewSettingsPane().getChildrenUnmodifiable());
|
||||||
|
|
||||||
dateAxis.getTickMarks().addListener((Observable observable) -> {
|
dateAxis.getTickMarks().addListener((Observable observable) -> layoutDateLabels());
|
||||||
layoutDateLabels();
|
dateAxis.categorySpacingProperty().addListener((Observable observable) -> layoutDateLabels());
|
||||||
});
|
dateAxis.getCategories().addListener((Observable observable) -> layoutDateLabels());
|
||||||
dateAxis.categorySpacingProperty().addListener((Observable observable) -> {
|
|
||||||
layoutDateLabels();
|
|
||||||
});
|
|
||||||
dateAxis.getCategories().addListener((Observable observable) -> {
|
|
||||||
layoutDateLabels();
|
|
||||||
});
|
|
||||||
|
|
||||||
spacer.minWidthProperty().bind(countAxis.widthProperty().add(countAxis.tickLengthProperty()).add(dateAxis.startMarginProperty().multiply(2)));
|
|
||||||
spacer.prefWidthProperty().bind(countAxis.widthProperty().add(countAxis.tickLengthProperty()).add(dateAxis.startMarginProperty().multiply(2)));
|
|
||||||
spacer.maxWidthProperty().bind(countAxis.widthProperty().add(countAxis.tickLengthProperty()).add(dateAxis.startMarginProperty().multiply(2)));
|
|
||||||
|
|
||||||
scale.addListener(o -> {
|
scale.addListener(o -> {
|
||||||
countAxis.tickLabelsVisibleProperty().bind(scale.isEqualTo(ScaleType.LINEAR));
|
countAxis.tickLabelsVisibleProperty().bind(scale.isEqualTo(ScaleType.LINEAR));
|
||||||
@ -135,12 +123,12 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NumberAxis getYAxis() {
|
final protected NumberAxis getYAxis() {
|
||||||
return countAxis;
|
return countAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CategoryAxis getXAxis() {
|
final protected CategoryAxis getXAxis() {
|
||||||
return dateAxis;
|
return dateAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +152,11 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getAxisMargin() {
|
||||||
|
return dateAxis.getStartMargin() + dateAxis.getEndMargin();
|
||||||
|
}
|
||||||
|
|
||||||
private class CountsViewSettingsPane extends HBox {
|
private class CountsViewSettingsPane extends HBox {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -42,8 +42,6 @@ import javafx.scene.control.ToggleButton;
|
|||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.effect.Effect;
|
import javafx.scene.effect.Effect;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.controlsfx.control.action.Action;
|
import org.controlsfx.control.action.Action;
|
||||||
@ -57,8 +55,6 @@ import org.sleuthkit.autopsy.timeline.TimeLineController;
|
|||||||
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
||||||
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
|
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
|
||||||
import org.sleuthkit.autopsy.timeline.ui.detailview.HideDescriptionAction;
|
|
||||||
import org.sleuthkit.autopsy.timeline.ui.detailview.UnhideDescriptionAction;
|
|
||||||
import org.sleuthkit.autopsy.timeline.utils.MappedList;
|
import org.sleuthkit.autopsy.timeline.utils.MappedList;
|
||||||
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
||||||
|
|
||||||
@ -103,8 +99,8 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
|||||||
* axis
|
* axis
|
||||||
* @param bottomLeftSpacer a spacer to keep everything aligned.
|
* @param bottomLeftSpacer a spacer to keep everything aligned.
|
||||||
*/
|
*/
|
||||||
public DetailViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region bottomLeftSpacer) {
|
public DetailViewPane(TimeLineController controller) {
|
||||||
super(controller, partPane, contextPane, bottomLeftSpacer);
|
super(controller);
|
||||||
this.selectedEvents = new MappedList<>(getSelectedNodes(), EventNodeBase<?>::getEvent);
|
this.selectedEvents = new MappedList<>(getSelectedNodes(), EventNodeBase<?>::getEvent);
|
||||||
|
|
||||||
//initialize chart;
|
//initialize chart;
|
||||||
@ -116,9 +112,6 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
|||||||
detailsChartDateAxis.getTickMarks().addListener((Observable observable) -> layoutDateLabels());
|
detailsChartDateAxis.getTickMarks().addListener((Observable observable) -> layoutDateLabels());
|
||||||
detailsChartDateAxis.getTickSpacing().addListener(observable -> layoutDateLabels());
|
detailsChartDateAxis.getTickSpacing().addListener(observable -> layoutDateLabels());
|
||||||
verticalAxis.setAutoRanging(false); //prevent XYChart.updateAxisRange() from accessing dataSeries on JFX thread causing ConcurrentModificationException
|
verticalAxis.setAutoRanging(false); //prevent XYChart.updateAxisRange() from accessing dataSeries on JFX thread causing ConcurrentModificationException
|
||||||
bottomLeftSpacer.minWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
|
|
||||||
bottomLeftSpacer.prefWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
|
|
||||||
bottomLeftSpacer.maxWidthProperty().bind(verticalAxis.widthProperty().add(verticalAxis.tickLengthProperty()));
|
|
||||||
|
|
||||||
selectedNodes.addListener((Observable observable) -> {
|
selectedNodes.addListener((Observable observable) -> {
|
||||||
//update selected nodes highlight
|
//update selected nodes highlight
|
||||||
@ -175,7 +168,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Axis<DateTime> getXAxis() {
|
final public DateAxis getXAxis() {
|
||||||
return detailsChartDateAxis;
|
return detailsChartDateAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +208,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Axis<EventStripe> getYAxis() {
|
final protected Axis<EventStripe> getYAxis() {
|
||||||
return verticalAxis;
|
return verticalAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +237,11 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
|||||||
c1.applySelectionEffect(selected);
|
c1.applySelectionEffect(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getAxisMargin() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Pane that contains widgets to adjust settings specific to a
|
* A Pane that contains widgets to adjust settings specific to a
|
||||||
* DetailViewPane
|
* DetailViewPane
|
||||||
|
Loading…
x
Reference in New Issue
Block a user