mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
add scale to counts y axis label. cleanup in CountsViewPane.java and related code.
This commit is contained in:
parent
076ee69394
commit
a23c6d19f8
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014-15 Basis Technology Corp.
|
||||
* Copyright 2014-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -44,7 +44,6 @@ import javafx.scene.chart.XYChart;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.OverrunStyle;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.effect.Effect;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Region;
|
||||
@ -143,62 +142,70 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value a value along this visualization's x axis
|
||||
* Should the tick mark at the given value be bold, because it has
|
||||
* interesting data associated with it?
|
||||
*
|
||||
* @return true if the tick label for the given value should be bold ( has
|
||||
* relevant data), false* otherwise
|
||||
* @param value A value along this visualization's x axis
|
||||
*
|
||||
* @return True if the tick label for the given value should be bold ( has
|
||||
* relevant data), false otherwise
|
||||
*/
|
||||
abstract protected Boolean isTickBold(X value);
|
||||
|
||||
/**
|
||||
* apply this visualization's 'selection effect' to the given node
|
||||
* Apply this visualization's 'selection effect' to the given node
|
||||
*
|
||||
* @param node the node to apply the 'effect' to
|
||||
* @param applied true if the effect should be applied, false if the effect
|
||||
* should
|
||||
* @param node The node to apply the 'effect' to
|
||||
* @param applied True if the effect should be applied, false if the effect
|
||||
* should not
|
||||
*/
|
||||
abstract protected void applySelectionEffect(NodeType node, Boolean applied);
|
||||
|
||||
/**
|
||||
* @return a task to execute on a background thread to reload this
|
||||
* Get a background Task that fetches the appropriate data and loads it into
|
||||
* this visualization.
|
||||
*
|
||||
* @return A task to execute on a background thread to reload this
|
||||
* visualization with different data.
|
||||
*/
|
||||
abstract protected Task<Boolean> getUpdateTask();
|
||||
|
||||
/**
|
||||
* @return return the {@link Effect} applied to 'selected nodes' in this
|
||||
* visualization, or null if selection is visualized via another
|
||||
* mechanism
|
||||
*/
|
||||
abstract protected Effect getSelectionEffect();
|
||||
|
||||
/**
|
||||
* @param tickValue
|
||||
* Get the label that should be used for a tick mark at the given value.
|
||||
*
|
||||
* @return a String to use for a tick mark label given a tick value
|
||||
* @param tickValue The value to get a label for.
|
||||
*
|
||||
* @return a String to use for a tick mark label given a tick value.
|
||||
*/
|
||||
abstract protected String getTickMarkLabel(X tickValue);
|
||||
|
||||
/**
|
||||
* the spacing (in pixels) between tick marks of the horizontal axis. This
|
||||
* will be used to layout the decluttered replacement labels.
|
||||
* Get the spacing, in pixels, between tick marks of the horizontal axis.
|
||||
* This will be used to layout the decluttered replacement labels.
|
||||
*
|
||||
* @return the spacing in pixels between tick marks of the horizontal axis
|
||||
* @return The spacing, in pixels, between tick marks of the horizontal axis
|
||||
*/
|
||||
abstract protected double getTickSpacing();
|
||||
|
||||
/**
|
||||
* Get the X-Axis of this Visualization's chart
|
||||
*
|
||||
* @return the horizontal axis used by this Visualization's chart
|
||||
*/
|
||||
abstract protected Axis<X> getXAxis();
|
||||
|
||||
/**
|
||||
* Get the Y-Axis of this Visualization's chart
|
||||
*
|
||||
* @return the vertical axis used by this Visualization's chart
|
||||
*/
|
||||
abstract protected Axis<Y> getYAxis();
|
||||
|
||||
/**
|
||||
* Clear all data items from this chart.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
abstract protected void resetData();
|
||||
abstract protected void clearChartData();
|
||||
|
||||
/**
|
||||
* update this visualization based on current state of zoom / filters.
|
||||
@ -243,7 +250,7 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
||||
}
|
||||
|
||||
/**
|
||||
* make a series for each event type in a consistent order
|
||||
* Make a series for each event type in a consistent order
|
||||
*/
|
||||
protected final void createSeries() {
|
||||
for (EventType eventType : EventType.allTypes) {
|
||||
@ -538,16 +545,15 @@ public abstract class AbstractVisualizationPane<X, Y, NodeType extends Node, Cha
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the chart data and sets the horisontal axis range. For use
|
||||
* Clears the chart data and sets the horizontal axis range. For use
|
||||
* within the derived implementation of the call() method.
|
||||
*
|
||||
* @param axisValues
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.NOT_UI)
|
||||
protected void resetChart(AxisValuesType axisValues) {
|
||||
|
||||
Platform.runLater(() -> {
|
||||
resetData();
|
||||
clearChartData();
|
||||
setDateAxisValues(axisValues);
|
||||
});
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#this is the label for the vetical axis
|
||||
CountsChartPane.numberOfEvents=Number of Events
|
||||
|
||||
CountsViewPane.scaleLabel.text=Scale\:
|
||||
CountsViewPane.logRadio.text=Logarithmic
|
||||
CountsViewPane.linearRadio.text=Linear
|
@ -1,14 +1,14 @@
|
||||
CountsChartPane.numberOfEvents=\u30A4\u30D9\u30F3\u30C8\u6570
|
||||
CountsViewPane.detailSwitchMessage=\u79D2\u3088\u308A\u5C0F\u3055\u3044\u5358\u4F4D\u306F\u3042\u308A\u307E\u305B\u3093\u3002\n\u8A73\u7D30\u30D3\u30E5\u30FC\u306B\u5909\u66F4\u3057\u307E\u3059\u304B\uFF1F
|
||||
CountsViewPane.detailSwitchTitle=\u8A73\u7D30\u30D3\u30E5\u30FC\u306B\u5909\u66F4\u3057\u307E\u3059\u304B\uFF1F
|
||||
Timeline.ui.countsview.menuItem.selectEventType=\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u3092\u9078\u629E
|
||||
Timeline.ui.countsview.menuItem.selectTimeandType=\u6642\u9593\u3068\u30BF\u30A4\u30D7\u3092\u9078\u629E
|
||||
Timeline.ui.countsview.menuItem.selectTimeRange=\u6642\u9593\u7BC4\u56F2\u3092\u9078\u629E
|
||||
Timeline.ui.countsview.menuItem.zoomIntoTimeRange=\u6642\u9593\u7BC4\u56F2\u3078\u30BA\u30FC\u30E0\u30A4\u30F3
|
||||
CountsViewPane.loggedTask.name=\u30AB\u30A6\u30F3\u30C8\u30D3\u30E5\u30FC\u3092\u66F4\u65B0\u4E2D
|
||||
CountsViewPane.loggedTask.updatingCounts=\u30D3\u30B8\u30E5\u30A2\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\uFF08\u53EF\u8996\u5316\uFF09\u3092\u5165\u529B\u4E2D
|
||||
CountsViewPane.tooltip.text={0} {1} \u30A4\u30D9\u30F3\u30C8\n{2}\u3068\n{3}\u306E\u9593
|
||||
CountsViewPane.linearRadio.text=\u30EA\u30CB\u30A2
|
||||
CountsViewPane.logRadio.text=\u5BFE\u6570\u7684
|
||||
CountsViewPane.scaleLabel.text=\u30B9\u30B1\u30FC\u30EB\uFF1A
|
||||
*=Autopsy\u30D5\u30A9\u30EC\u30F3\u30B8\u30C3\u30AF\u30D6\u30E9\u30A6\u30B6
|
||||
CountsViewPane.numberOfEvents=\u30a4\u30d9\u30f3\u30c8\u6570
|
||||
CountsViewPane.detailSwitchMessage=\u79d2\u3088\u308a\u5c0f\u3055\u3044\u5358\u4f4d\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u8a73\u7d30\u30d3\u30e5\u30fc\u306b\u5909\u66f4\u3057\u307e\u3059\u304b\uff1f
|
||||
CountsViewPane.detailSwitchTitle=\u8a73\u7d30\u30d3\u30e5\u30fc\u306b\u5909\u66f4\u3057\u307e\u3059\u304b\uff1f
|
||||
Timeline.ui.countsview.menuItem.selectEventType=\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7\u3092\u9078\u629e
|
||||
Timeline.ui.countsview.menuItem.selectTimeandType=\u6642\u9593\u3068\u30bf\u30a4\u30d7\u3092\u9078\u629e
|
||||
Timeline.ui.countsview.menuItem.selectTimeRange=\u6642\u9593\u7bc4\u56f2\u3092\u9078\u629e
|
||||
Timeline.ui.countsview.menuItem.zoomIntoTimeRange=\u6642\u9593\u7bc4\u56f2\u3078\u30ba\u30fc\u30e0\u30a4\u30f3
|
||||
CountsViewPane.loggedTask.name=\u30ab\u30a6\u30f3\u30c8\u30d3\u30e5\u30fc\u3092\u66f4\u65b0\u4e2d
|
||||
CountsViewPane.loggedTask.updatingCounts=\u30d3\u30b8\u30e5\u30a2\u30e9\u30a4\u30bc\u30fc\u30b7\u30e7\u30f3\uff08\u53ef\u8996\u5316\uff09\u3092\u5165\u529b\u4e2d
|
||||
CountsViewPane.tooltip.text={0} {1} \u30a4\u30d9\u30f3\u30c8\n{2}\u3068\n{3}\u306e\u9593
|
||||
CountsViewPane.linearRadio.text=\u30ea\u30cb\u30a2
|
||||
CountsViewPane.logRadio.text=\u5bfe\u6570\u7684
|
||||
CountsViewPane.scaleLabel.text=\u30b9\u30b1\u30fc\u30eb\uff1a
|
||||
*=Autopsy\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30d6\u30e9\u30a6\u30b6
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.concurrent.Task;
|
||||
@ -32,13 +33,11 @@ import javafx.fxml.FXML;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.chart.CategoryAxis;
|
||||
import javafx.scene.chart.NumberAxis;
|
||||
import javafx.scene.chart.StackedBarChart;
|
||||
import javafx.scene.chart.XYChart;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.effect.Effect;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Region;
|
||||
@ -48,32 +47,26 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.DetailViewPane;
|
||||
import static org.sleuthkit.autopsy.timeline.ui.countsview.Bundle.*;
|
||||
import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
||||
|
||||
/**
|
||||
* FXML Controller class for a {@link StackedBarChart<String,Number>} based
|
||||
* implementation of a {@link TimeLineView}.
|
||||
* FXML Controller class for a StackedBarChart<String,Number> based
|
||||
* implementation of a TimeLineChart.
|
||||
*
|
||||
* This class listens to changes in the assigned {@link FilteredEventsModel} and
|
||||
* updates the internal {@link StackedBarChart} to reflect the currently
|
||||
* requested events.
|
||||
* This class listens to changes in the assigned FilteredEventsModel and updates
|
||||
* the internal EventCountsChart to reflect the currently requested events.
|
||||
*
|
||||
* This class captures input from the user in the form of mouse clicks on graph
|
||||
* bars, and forwards them to the assigned {@link TimeLineController} *
|
||||
* bars, and forwards them to the assigned TimeLineController
|
||||
*
|
||||
* Concurrency Policy: Access to the private members stackedBarChart, countAxis,
|
||||
* dateAxis, EventTypeMap, and dataSets affects the stackedBarChart so they all
|
||||
* must only be manipulated on the JavaFx thread (through {@link Platform#runLater(java.lang.Runnable)}
|
||||
*
|
||||
* {@link CountsChartPane#filteredEvents} should encapsulate all need
|
||||
* synchronization internally.
|
||||
*
|
||||
* TODO: refactor common code out of this class and {@link DetailViewPane} into
|
||||
* {@link AbstractVisualizationPane}
|
||||
* must only be manipulated on the JavaFx thread (through
|
||||
* Platform.runLater(java.lang.Runnable). The FilteredEventsModel should
|
||||
* encapsulate all need synchronization internally.
|
||||
*/
|
||||
public class CountsViewPane extends AbstractVisualizationPane<String, Number, Node, EventCountsChart> {
|
||||
|
||||
@ -82,7 +75,7 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
private final NumberAxis countAxis = new NumberAxis();
|
||||
private final CategoryAxis dateAxis = new CategoryAxis(FXCollections.<String>observableArrayList());
|
||||
|
||||
private final SimpleObjectProperty<ScaleType> scale = new SimpleObjectProperty<>(ScaleType.LOGARITHMIC);
|
||||
private final SimpleObjectProperty<Scale> scaleProp = new SimpleObjectProperty<>(Scale.LOGARITHMIC);
|
||||
|
||||
@Override
|
||||
protected String getTickMarkLabel(String labelValueString) {
|
||||
@ -100,38 +93,42 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
return new CountsUpdateTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param controller The TimelineController for this visualization
|
||||
* @param partPane
|
||||
* @param contextPane
|
||||
* @param spacer
|
||||
*/
|
||||
@NbBundle.Messages({"CountsViewPane.numberOfEvents=Number of Events ({0})"})
|
||||
public CountsViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) {
|
||||
super(controller, partPane, contextPane, spacer);
|
||||
chart = new EventCountsChart(controller, dateAxis, countAxis, selectedNodes);
|
||||
|
||||
chart.setData(dataSeries);
|
||||
setCenter(chart);
|
||||
|
||||
Tooltip.install(chart, getDefaultTooltip());
|
||||
|
||||
settingsNodes = new ArrayList<>(new CountsViewSettingsPane().getChildrenUnmodifiable());
|
||||
|
||||
dateAxis.getTickMarks().addListener((Observable observable) -> {
|
||||
layoutDateLabels();
|
||||
});
|
||||
dateAxis.categorySpacingProperty().addListener((Observable observable) -> {
|
||||
layoutDateLabels();
|
||||
});
|
||||
dateAxis.getCategories().addListener((Observable observable) -> {
|
||||
layoutDateLabels();
|
||||
});
|
||||
dateAxis.getTickMarks().addListener((Observable tickMarks) -> layoutDateLabels());
|
||||
dateAxis.categorySpacingProperty().addListener((Observable spacing) -> layoutDateLabels());
|
||||
dateAxis.getCategories().addListener((Observable categories) -> 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 -> {
|
||||
countAxis.tickLabelsVisibleProperty().bind(scale.isEqualTo(ScaleType.LINEAR));
|
||||
countAxis.tickMarkVisibleProperty().bind(scale.isEqualTo(ScaleType.LINEAR));
|
||||
countAxis.minorTickVisibleProperty().bind(scale.isEqualTo(ScaleType.LINEAR));
|
||||
//bind tick visibility to scaleProp
|
||||
BooleanBinding scaleIsLinear = scaleProp.isEqualTo(Scale.LINEAR);
|
||||
countAxis.tickLabelsVisibleProperty().bind(scaleIsLinear);
|
||||
countAxis.tickMarkVisibleProperty().bind(scaleIsLinear);
|
||||
countAxis.minorTickVisibleProperty().bind(scaleIsLinear);
|
||||
scaleProp.addListener(scale -> {
|
||||
update();
|
||||
countAxis.setLabel(Bundle.CountsViewPane_numberOfEvents(scaleProp.get().getDisplayName()));
|
||||
});
|
||||
|
||||
countAxis.setLabel(Bundle.CountsViewPane_numberOfEvents(scaleProp.get().getDisplayName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -150,28 +147,74 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Effect getSelectionEffect() {
|
||||
return chart.getSelectionEffect();
|
||||
protected void applySelectionEffect(Node c1, Boolean applied) {
|
||||
c1.setEffect(applied ? chart.getSelectionEffect() : null);
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
@Override
|
||||
protected void applySelectionEffect(Node c1, Boolean applied) {
|
||||
if (applied) {
|
||||
c1.setEffect(getSelectionEffect());
|
||||
} else {
|
||||
c1.setEffect(null);
|
||||
protected void clearChartData() {
|
||||
for (XYChart.Series<String, Number> series : dataSeries) {
|
||||
series.getData().clear();
|
||||
}
|
||||
dataSeries.clear();
|
||||
eventTypeToSeriesMap.clear();
|
||||
createSeries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for the Scales available in the Counts View.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ScaleType.Linear=Linear",
|
||||
"ScaleType.Logarithmic=Logarithmic"
|
||||
})
|
||||
private static enum Scale implements Function<Long, Double> {
|
||||
|
||||
LINEAR(Bundle.ScaleType_Linear()) {
|
||||
@Override
|
||||
public Double apply(Long inValue) {
|
||||
return inValue.doubleValue();
|
||||
}
|
||||
},
|
||||
LOGARITHMIC(Bundle.ScaleType_Logarithmic()) {
|
||||
@Override
|
||||
public Double apply(Long inValue) {
|
||||
return Math.log10(inValue) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param displayName The display name for this Scale.
|
||||
*/
|
||||
Scale(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display name of this ScaleType
|
||||
*
|
||||
* @return The display name.
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A Pane that contains widgets to adjust settings specific to a
|
||||
* CountsViewPane
|
||||
*/
|
||||
private class CountsViewSettingsPane extends HBox {
|
||||
|
||||
@FXML
|
||||
private RadioButton logRadio;
|
||||
|
||||
@FXML
|
||||
private RadioButton linearRadio;
|
||||
|
||||
@FXML
|
||||
private ToggleGroup scaleGroup;
|
||||
|
||||
@ -179,58 +222,40 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
private Label scaleLabel;
|
||||
|
||||
@FXML
|
||||
@NbBundle.Messages({
|
||||
"CountsViewPane.logRadio.text=Logarithmic",
|
||||
"CountsViewPane.scaleLabel.text=Scale:",
|
||||
"CountsViewPane.linearRadio.text=Linear"})
|
||||
void initialize() {
|
||||
assert logRadio != null : "fx:id=\"logRadio\" was not injected: check your FXML file 'CountsViewSettingsPane.fxml'."; // NON-NLS
|
||||
assert linearRadio != null : "fx:id=\"linearRadio\" was not injected: check your FXML file 'CountsViewSettingsPane.fxml'."; // NON-NLS
|
||||
logRadio.setSelected(true);
|
||||
scaleGroup.selectedToggleProperty().addListener(observable -> {
|
||||
if (scaleGroup.getSelectedToggle() == linearRadio) {
|
||||
scale.set(ScaleType.LINEAR);
|
||||
}
|
||||
if (scaleGroup.getSelectedToggle() == logRadio) {
|
||||
scale.set(ScaleType.LOGARITHMIC);
|
||||
scaleProp.set(Scale.LINEAR);
|
||||
} else if (scaleGroup.getSelectedToggle() == logRadio) {
|
||||
scaleProp.set(Scale.LOGARITHMIC);
|
||||
}
|
||||
});
|
||||
|
||||
logRadio.setText(NbBundle.getMessage(CountsViewPane.class, "CountsViewPane.logRadio.text"));
|
||||
linearRadio.setText(NbBundle.getMessage(CountsViewPane.class, "CountsViewPane.linearRadio.text"));
|
||||
scaleLabel.setText(NbBundle.getMessage(CountsViewPane.class, "CountsViewPane.scaleLabel.text"));
|
||||
logRadio.setText(CountsViewPane_logRadio_text());
|
||||
linearRadio.setText(CountsViewPane_linearRadio_text());
|
||||
scaleLabel.setText(CountsViewPane_scaleLabel_text());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
CountsViewSettingsPane() {
|
||||
FXMLConstructor.construct(this, "CountsViewSettingsPane.fxml"); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
@Override
|
||||
protected void resetData() {
|
||||
for (XYChart.Series<String, Number> s : dataSeries) {
|
||||
s.getData().clear();
|
||||
}
|
||||
|
||||
dataSeries.clear();
|
||||
eventTypeToSeriesMap.clear();
|
||||
createSeries();
|
||||
}
|
||||
|
||||
private static enum ScaleType implements Function<Long, Double> {
|
||||
|
||||
LINEAR(Long::doubleValue),
|
||||
LOGARITHMIC(t -> Math.log10(t) + 1);
|
||||
|
||||
private final Function<Long, Double> func;
|
||||
|
||||
ScaleType(Function<Long, Double> func) {
|
||||
this.func = func;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double apply(Long t) {
|
||||
return func.apply(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Task that clears the Chart, fetches new data according to the current
|
||||
* ZoomParams and loads it into the Chart
|
||||
*
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"CountsViewPane.loggedTask.name=Updating Counts View",
|
||||
"CountsViewPane.loggedTask.updatingCounts=Populating visualization"})
|
||||
@ -249,24 +274,21 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
|
||||
final RangeDivisionInfo rangeInfo = RangeDivisionInfo.getRangeDivisionInfo(getTimeRange());
|
||||
chart.setRangeInfo(rangeInfo); //do we need this. It seems like a hack.
|
||||
|
||||
List<Interval> intervals = rangeInfo.getIntervals();
|
||||
List<String> categories = Lists.transform(intervals, rangeInfo::formatForTick);
|
||||
|
||||
//clear old data, and reset ranges and series
|
||||
resetChart(categories);
|
||||
resetChart(Lists.transform(intervals, rangeInfo::formatForTick));
|
||||
|
||||
updateMessage(Bundle.CountsViewPane_loggedTask_updatingCounts());
|
||||
int chartMax = 0;
|
||||
int numIntervals = intervals.size();
|
||||
Scale activeScale = scaleProp.get();
|
||||
|
||||
/*
|
||||
* for each interval query database for event counts and add to
|
||||
* chart.
|
||||
*
|
||||
* Doing this in chunks might seem inefficient but it lets us reuse
|
||||
* more cached results as the user navigates to overlapping viewws
|
||||
*
|
||||
* //TODO: implement similar chunked caching in DetailsView -jm
|
||||
* For each interval, query the database for event counts and add
|
||||
* the counts to the chart. Doing this in chunks might seem
|
||||
* inefficient but it lets us reuse more cached results as the user
|
||||
* navigates to overlapping views.
|
||||
*/
|
||||
for (int i = 0; i < numIntervals; i++) {
|
||||
if (isCancelled()) {
|
||||
@ -288,7 +310,7 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
final Long count = eventCounts.get(eventType);
|
||||
if (count > 0) {
|
||||
final String intervalCategory = rangeInfo.formatForTick(interval);
|
||||
final double adjustedCount = scale.get().apply(count);
|
||||
final double adjustedCount = activeScale.apply(count);
|
||||
|
||||
final XYChart.Data<String, Number> dataItem =
|
||||
new XYChart.Data<>(intervalCategory, adjustedCount,
|
||||
@ -299,9 +321,10 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
}
|
||||
chartMax = Math.max(chartMax, maxPerInterval);
|
||||
}
|
||||
|
||||
//adjust vertical axis according to scale type and max counts
|
||||
double countAxisUpperbound = 1 + chartMax * 1.2;
|
||||
double tickUnit = ScaleType.LINEAR.equals(scale.get())
|
||||
double tickUnit = Scale.LINEAR.equals(activeScale)
|
||||
? Math.pow(10, Math.max(0, Math.floor(Math.log10(chartMax)) - 1))
|
||||
: Double.MAX_VALUE;
|
||||
Platform.runLater(() -> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014-15 Basis Technology Corp.
|
||||
* Copyright 2014-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -87,7 +87,6 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
dateAxis.setTickLabelsVisible(false);
|
||||
dateAxis.setTickLabelGap(0);
|
||||
|
||||
countAxis.setLabel(NbBundle.getMessage(CountsViewPane.class, "CountsChartPane.numberOfEvents"));
|
||||
countAxis.setAutoRanging(false);
|
||||
countAxis.setLowerBound(0);
|
||||
countAxis.setAnimated(true);
|
||||
@ -167,6 +166,7 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
return new CountsIntervalSelector(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableList<Node> getSelectedNodes() {
|
||||
return selectedNodes;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.effect.Effect;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Region;
|
||||
@ -57,8 +56,6 @@ import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
||||
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.zooming.DescriptionLoD;
|
||||
|
||||
@ -205,7 +202,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
@Override
|
||||
protected void resetData() {
|
||||
protected void clearChartData() {
|
||||
chart.reset();
|
||||
}
|
||||
|
||||
@ -234,11 +231,6 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
||||
return new DetailsUpdateTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Effect getSelectionEffect() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySelectionEffect(EventNodeBase<?> c1, Boolean selected) {
|
||||
c1.applySelectionEffect(selected);
|
||||
|
Loading…
x
Reference in New Issue
Block a user