mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
allow user to drag interval selector with any mouse button
This commit is contained in:
parent
3c235d9bac
commit
84a31f3738
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013 Basis Technology Corp.
|
* Copyright 2013-15 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");
|
||||||
@ -35,7 +35,6 @@ Timeline.ui.ZoomRanges.threeyears.text=Three Years
|
|||||||
Timeline.ui.ZoomRanges.fiveyears.text=Five Years
|
Timeline.ui.ZoomRanges.fiveyears.text=Five Years
|
||||||
Timeline.ui.ZoomRanges.tenyears.text=Ten Years
|
Timeline.ui.ZoomRanges.tenyears.text=Ten Years
|
||||||
Timeline.ui.ZoomRanges.all.text=All
|
Timeline.ui.ZoomRanges.all.text=All
|
||||||
Timeline.ui.TimeLineChart.tooltip.text=Double-click to zoom into range\:\n{0} to {1}\nRight-click to clear.
|
|
||||||
TimeLineResultView.startDateToEndDate.text={0} to {1}
|
TimeLineResultView.startDateToEndDate.text={0} to {1}
|
||||||
VisualizationPanel.histogramTask.title=Rebuild Histogram
|
VisualizationPanel.histogramTask.title=Rebuild Histogram
|
||||||
VisualizationPanel.histogramTask.preparing=preparing
|
VisualizationPanel.histogramTask.preparing=preparing
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.timeline.ui;
|
package org.sleuthkit.autopsy.timeline.ui;
|
||||||
|
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.event.EventType;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.chart.Axis;
|
import javafx.scene.chart.Axis;
|
||||||
@ -69,7 +70,7 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
* @param <X> the type of values along the horizontal axis
|
* @param <X> the type of values along the horizontal axis
|
||||||
* @param <Y> the type of chart this is a drag handler for
|
* @param <Y> the type of chart this is a drag handler for
|
||||||
*/
|
*/
|
||||||
class ChartDragHandler<X, Y extends Chart & TimeLineChart<X>> implements EventHandler<MouseEvent> {
|
static class ChartDragHandler<X, Y extends Chart & TimeLineChart<X>> implements EventHandler<MouseEvent> {
|
||||||
|
|
||||||
private final Y chart;
|
private final Y chart;
|
||||||
|
|
||||||
@ -77,46 +78,80 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
|
|
||||||
private double startX; //hanlder mainstains position of drag start
|
private double startX; //hanlder mainstains position of drag start
|
||||||
|
|
||||||
|
private boolean requireDrag = true;
|
||||||
|
|
||||||
|
public boolean isRequireDrag() {
|
||||||
|
return requireDrag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequireDrag(boolean requireDrag) {
|
||||||
|
this.requireDrag = requireDrag;
|
||||||
|
}
|
||||||
|
|
||||||
public ChartDragHandler(Y chart, Axis<X> dateAxis) {
|
public ChartDragHandler(Y chart, Axis<X> dateAxis) {
|
||||||
this.chart = chart;
|
this.chart = chart;
|
||||||
this.dateAxis = dateAxis;
|
this.dateAxis = dateAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(MouseEvent t) {
|
public void handle(MouseEvent mouseEvent) {
|
||||||
if (t.getButton() == MouseButton.SECONDARY) {
|
EventType<? extends MouseEvent> mouseEventType = mouseEvent.getEventType();
|
||||||
|
if (mouseEventType == MouseEvent.MOUSE_PRESSED) {
|
||||||
if (t.getEventType() == MouseEvent.MOUSE_PRESSED) {
|
|
||||||
//caputure x-position, incase we are repositioning existing selector
|
//caputure x-position, incase we are repositioning existing selector
|
||||||
startX = t.getX();
|
startX = mouseEvent.getX();
|
||||||
chart.setCursor(Cursor.E_RESIZE);
|
// chart.setCursor(Cursor.H_RESIZE);
|
||||||
} else if (t.getEventType() == MouseEvent.MOUSE_DRAGGED) {
|
} else if ((mouseEventType == MouseEvent.MOUSE_DRAGGED)
|
||||||
|
|| mouseEventType == MouseEvent.MOUSE_MOVED && (requireDrag == false)) {
|
||||||
if (chart.getIntervalSelector() == null) {
|
if (chart.getIntervalSelector() == null) {
|
||||||
//make new interval selector
|
//make new interval selector
|
||||||
chart.setIntervalSelector(chart.newIntervalSelector(t.getX(), dateAxis));
|
chart.setIntervalSelector(chart.newIntervalSelector(mouseEvent.getX(), dateAxis));
|
||||||
chart.getIntervalSelector().heightProperty().bind(chart.heightProperty().subtract(dateAxis.heightProperty().subtract(dateAxis.tickLengthProperty())));
|
chart.getIntervalSelector().heightProperty().bind(chart.heightProperty().subtract(dateAxis.heightProperty().subtract(dateAxis.tickLengthProperty())));
|
||||||
chart.getIntervalSelector().addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
|
IntervalSelector<? extends X> intervalSelector = chart.getIntervalSelector();
|
||||||
|
if (intervalSelector != null) {
|
||||||
|
intervalSelector.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
|
||||||
if (event.getButton() == MouseButton.SECONDARY) {
|
if (event.getButton() == MouseButton.SECONDARY) {
|
||||||
chart.clearIntervalSelector();
|
chart.clearIntervalSelector();
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
startX = t.getX();
|
}
|
||||||
|
startX = mouseEvent.getX();
|
||||||
} else {
|
} else {
|
||||||
//resize/position existing selector
|
//resize/position existing selector
|
||||||
if (t.getX() > startX) {
|
if (mouseEvent.getX() > startX) {
|
||||||
chart.getIntervalSelector().setX(startX);
|
chart.getIntervalSelector().setX(startX);
|
||||||
chart.getIntervalSelector().setWidth(t.getX() - startX);
|
chart.getIntervalSelector().setWidth(mouseEvent.getX() - startX);
|
||||||
} else {
|
} else {
|
||||||
chart.getIntervalSelector().setX(t.getX());
|
chart.getIntervalSelector().setX(mouseEvent.getX());
|
||||||
chart.getIntervalSelector().setWidth(startX - t.getX());
|
chart.getIntervalSelector().setWidth(startX - mouseEvent.getX());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (t.getEventType() == MouseEvent.MOUSE_RELEASED) {
|
} else if (mouseEventType == MouseEvent.MOUSE_RELEASED) {
|
||||||
chart.setCursor(Cursor.DEFAULT);
|
// chart.setCursor(Cursor.DEFAULT);
|
||||||
|
requireDrag = true;
|
||||||
|
IntervalSelector<? extends X> intervalSelector = chart.getIntervalSelector();
|
||||||
|
if (intervalSelector != null) {
|
||||||
|
intervalSelector.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
|
||||||
|
if (event.getButton() == MouseButton.SECONDARY) {
|
||||||
|
chart.clearIntervalSelector();
|
||||||
|
event.consume();
|
||||||
}
|
}
|
||||||
t.consume();
|
});
|
||||||
}
|
}
|
||||||
|
} else if (mouseEventType == MouseEvent.MOUSE_CLICKED) {
|
||||||
|
// chart.setCursor(Cursor.DEFAULT);
|
||||||
|
requireDrag = true;
|
||||||
|
IntervalSelector<? extends X> intervalSelector = chart.getIntervalSelector();
|
||||||
|
if (intervalSelector != null) {
|
||||||
|
intervalSelector.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
|
||||||
|
if (event.getButton() == MouseButton.SECONDARY) {
|
||||||
|
chart.clearIntervalSelector();
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mouseEvent.consume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,15 +175,12 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
*/
|
*/
|
||||||
private final Axis<X> dateAxis;
|
private final Axis<X> dateAxis;
|
||||||
|
|
||||||
protected Tooltip tooltip;
|
private Tooltip tooltip;
|
||||||
|
|
||||||
/////////drag state
|
/////////drag state
|
||||||
private DragPosition dragPosition;
|
private DragPosition dragPosition;
|
||||||
|
|
||||||
private double startLeft;
|
private double startLeft;
|
||||||
|
|
||||||
private double startX;
|
private double startX;
|
||||||
|
|
||||||
private double startWidth;
|
private double startWidth;
|
||||||
/////////end drag state
|
/////////end drag state
|
||||||
|
|
||||||
@ -179,7 +211,8 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
Point2D localMouse = sceneToLocal(new Point2D(event.getSceneX(), event.getSceneY()));
|
Point2D localMouse = sceneToLocal(new Point2D(event.getSceneX(), event.getSceneY()));
|
||||||
final double diffX = getX() - localMouse.getX();
|
final double diffX = getX() - localMouse.getX();
|
||||||
if (Math.abs(diffX) <= HALF_STROKE || Math.abs(diffX + getWidth()) <= HALF_STROKE) {
|
if (Math.abs(diffX) <= HALF_STROKE || Math.abs(diffX + getWidth()) <= HALF_STROKE) {
|
||||||
setCursor(Cursor.E_RESIZE);
|
//if the mouse is over the stroke, show the resize cursor
|
||||||
|
setCursor(Cursor.H_RESIZE);
|
||||||
} else {
|
} else {
|
||||||
setCursor(Cursor.HAND);
|
setCursor(Cursor.HAND);
|
||||||
}
|
}
|
||||||
@ -221,9 +254,7 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
//convert to DateTimes, using max/min if null(off axis)
|
//convert to DateTimes, using max/min if null(off axis)
|
||||||
DateTime start = parseDateTime(getSpanStart());
|
DateTime start = parseDateTime(getSpanStart());
|
||||||
DateTime end = parseDateTime(getSpanEnd());
|
DateTime end = parseDateTime(getSpanEnd());
|
||||||
|
|
||||||
Interval i = adjustInterval(start.isBefore(end) ? new Interval(start, end) : new Interval(end, start));
|
Interval i = adjustInterval(start.isBefore(end) ? new Interval(start, end) : new Interval(end, start));
|
||||||
|
|
||||||
controller.pushTimeRange(i);
|
controller.pushTimeRange(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,13 +289,15 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
*/
|
*/
|
||||||
protected abstract DateTime parseDateTime(X date);
|
protected abstract DateTime parseDateTime(X date);
|
||||||
|
|
||||||
|
@NbBundle.Messages({"# {0} - start timestamp",
|
||||||
|
"# {1} - end timestamp",
|
||||||
|
"Timeline.ui.TimeLineChart.tooltip.text=Double-click to zoom into range:\n{0} to {1}\nRight-click to clear."})
|
||||||
private void setTooltip() {
|
private void setTooltip() {
|
||||||
final X start = getSpanStart();
|
final X start = getSpanStart();
|
||||||
final X end = getSpanEnd();
|
final X end = getSpanEnd();
|
||||||
Tooltip.uninstall(this, tooltip);
|
Tooltip.uninstall(this, tooltip);
|
||||||
tooltip = new Tooltip(
|
tooltip = new Tooltip(
|
||||||
NbBundle.getMessage(TimeLineChart.class, "Timeline.ui.TimeLineChart.tooltip.text", formatSpan(start),
|
Bundle.Timeline_ui_TimeLineChart_tooltip_text(formatSpan(start), formatSpan(end)));
|
||||||
formatSpan(end)));
|
|
||||||
Tooltip.install(this, tooltip);
|
Tooltip.install(this, tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +323,9 @@ public interface TimeLineChart<X> extends TimeLineView {
|
|||||||
*/
|
*/
|
||||||
private enum DragPosition {
|
private enum DragPosition {
|
||||||
|
|
||||||
LEFT, CENTER, RIGHT
|
LEFT,
|
||||||
|
CENTER,
|
||||||
|
RIGHT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,5 @@ CountsViewPane.loggedTask.resetUI=resetting ui
|
|||||||
CountsViewPane.tooltip.text={0} {1} events\nbetween {2}\nand {3}
|
CountsViewPane.tooltip.text={0} {1} events\nbetween {2}\nand {3}
|
||||||
CountsViewPane.loggedTask.updatingCounts=updating counts
|
CountsViewPane.loggedTask.updatingCounts=updating counts
|
||||||
CountsViewPane.loggedTask.wrappingUp=wrapping up
|
CountsViewPane.loggedTask.wrappingUp=wrapping up
|
||||||
EventCountsChart.contextMenu.zoomHistory.name=Zoom History
|
|
||||||
CountsViewPane.scaleLabel.text=Scale\:
|
|
||||||
CountsViewPane.logRadio.text=Logarithmic
|
CountsViewPane.logRadio.text=Logarithmic
|
||||||
CountsViewPane.linearRadio.text=Linear
|
CountsViewPane.linearRadio.text=Linear
|
||||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.ui.countsview;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
import javafx.scene.chart.Axis;
|
import javafx.scene.chart.Axis;
|
||||||
import javafx.scene.chart.CategoryAxis;
|
import javafx.scene.chart.CategoryAxis;
|
||||||
import javafx.scene.chart.NumberAxis;
|
import javafx.scene.chart.NumberAxis;
|
||||||
@ -44,9 +45,9 @@ import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
|||||||
* Customized {@link StackedBarChart<String, Number>} used to display the event
|
* Customized {@link StackedBarChart<String, Number>} used to display the event
|
||||||
* counts in {@link CountsViewPane}
|
* counts in {@link CountsViewPane}
|
||||||
*/
|
*/
|
||||||
class EventCountsChart extends StackedBarChart<String, Number> implements TimeLineChart<String> {
|
final class EventCountsChart extends StackedBarChart<String, Number> implements TimeLineChart<String> {
|
||||||
|
|
||||||
private ContextMenu contextMenu;
|
private ContextMenu chartContextMenu;
|
||||||
|
|
||||||
private TimeLineController controller;
|
private TimeLineController controller;
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
|||||||
* by padding the end with one 'period'
|
* by padding the end with one 'period'
|
||||||
*/
|
*/
|
||||||
private RangeDivisionInfo rangeInfo;
|
private RangeDivisionInfo rangeInfo;
|
||||||
|
private final ChartDragHandler<String, EventCountsChart> dragHandler;
|
||||||
|
|
||||||
EventCountsChart(CategoryAxis dateAxis, NumberAxis countAxis) {
|
EventCountsChart(CategoryAxis dateAxis, NumberAxis countAxis) {
|
||||||
super(dateAxis, countAxis);
|
super(dateAxis, countAxis);
|
||||||
@ -81,15 +83,19 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
|||||||
setTitle(null);
|
setTitle(null);
|
||||||
|
|
||||||
//use one handler with an if chain because it maintains state
|
//use one handler with an if chain because it maintains state
|
||||||
ChartDragHandler<String, EventCountsChart> dragHandler = new ChartDragHandler<>(this, getXAxis());
|
dragHandler = new ChartDragHandler<>(this, getXAxis());
|
||||||
setOnMousePressed(dragHandler);
|
setOnMousePressed(dragHandler);
|
||||||
setOnMouseReleased(dragHandler);
|
setOnMouseReleased(dragHandler);
|
||||||
setOnMouseDragged(dragHandler);
|
setOnMouseDragged(dragHandler);
|
||||||
|
setOnMouseMoved(dragHandler);
|
||||||
|
|
||||||
setOnMouseClicked((MouseEvent clickEvent) -> {
|
setOnMouseClicked((MouseEvent clickEvent) -> {
|
||||||
contextMenu.hide();
|
if (chartContextMenu != null) {
|
||||||
|
chartContextMenu.hide();
|
||||||
|
}
|
||||||
if (clickEvent.getButton() == MouseButton.SECONDARY && clickEvent.isStillSincePress()) {
|
if (clickEvent.getButton() == MouseButton.SECONDARY && clickEvent.isStillSincePress()) {
|
||||||
contextMenu.show(EventCountsChart.this, clickEvent.getScreenX(), clickEvent.getScreenY());
|
getChartContextMenu(clickEvent);
|
||||||
|
chartContextMenu.show(EventCountsChart.this, clickEvent.getScreenX(), clickEvent.getScreenY());
|
||||||
clickEvent.consume();
|
clickEvent.consume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -101,17 +107,34 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
|||||||
intervalSelector = null;
|
intervalSelector = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NbBundle.Messages({"EventCountsChart.contextMenu.zoomHistory.name=Zoom History"})
|
||||||
public final synchronized void setController(TimeLineController controller) {
|
ContextMenu getChartContextMenu(MouseEvent clickEvent) throws MissingResourceException {
|
||||||
this.controller = controller;
|
if (chartContextMenu != null) {
|
||||||
setModel(this.controller.getEventsModel());
|
chartContextMenu.hide();
|
||||||
//we have defered creating context menu until control is available
|
}
|
||||||
contextMenu = ActionUtils.createContextMenu(
|
|
||||||
Arrays.asList(new ActionGroup(
|
chartContextMenu = ActionUtils.createContextMenu(Arrays.asList(
|
||||||
NbBundle.getMessage(this.getClass(), "EventCountsChart.contextMenu.zoomHistory.name"),
|
// new Action("Select Interval") {
|
||||||
|
// {
|
||||||
|
// setEventHandler((ActionEvent t) -> {
|
||||||
|
// dragHandler.setRequireDrag(false);
|
||||||
|
// dragHandler.handle(clickEvent.copyFor(clickEvent.getSource(), clickEvent.getTarget(), MouseEvent.MOUSE_DRAGGED));
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
new ActionGroup(
|
||||||
|
Bundle.EventCountsChart_contextMenu_zoomHistory_name(),
|
||||||
new Back(controller),
|
new Back(controller),
|
||||||
new Forward(controller))));
|
new Forward(controller))));
|
||||||
contextMenu.setAutoHide(true);
|
chartContextMenu.setAutoHide(true);
|
||||||
|
return chartContextMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setController(TimeLineController controller) {
|
||||||
|
this.controller = controller;
|
||||||
|
setModel(this.controller.getEventsModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -145,7 +168,7 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
|||||||
* @return the context menu for this chart
|
* @return the context menu for this chart
|
||||||
*/
|
*/
|
||||||
ContextMenu getContextMenu() {
|
ContextMenu getContextMenu() {
|
||||||
return contextMenu;
|
return chartContextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRangeInfo(RangeDivisionInfo rangeInfo) {
|
void setRangeInfo(RangeDivisionInfo rangeInfo) {
|
||||||
@ -177,7 +200,7 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
|||||||
*/
|
*/
|
||||||
private class CountsIntervalSelector extends IntervalSelector<String> {
|
private class CountsIntervalSelector extends IntervalSelector<String> {
|
||||||
|
|
||||||
public CountsIntervalSelector(double x, double height, Axis<String> axis, TimeLineController controller) {
|
CountsIntervalSelector(double x, double height, Axis<String> axis, TimeLineController controller) {
|
||||||
super(x, height, axis, controller);
|
super(x, height, axis, controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user