mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07: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
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.tenyears.text=Ten Years
|
||||
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}
|
||||
VisualizationPanel.histogramTask.title=Rebuild Histogram
|
||||
VisualizationPanel.histogramTask.preparing=preparing
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.timeline.ui;
|
||||
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.event.EventType;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Cursor;
|
||||
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 <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;
|
||||
|
||||
@ -77,46 +78,80 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
|
||||
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) {
|
||||
this.chart = chart;
|
||||
this.dateAxis = dateAxis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MouseEvent t) {
|
||||
if (t.getButton() == MouseButton.SECONDARY) {
|
||||
|
||||
if (t.getEventType() == MouseEvent.MOUSE_PRESSED) {
|
||||
//caputure x-position, incase we are repositioning existing selector
|
||||
startX = t.getX();
|
||||
chart.setCursor(Cursor.E_RESIZE);
|
||||
} else if (t.getEventType() == MouseEvent.MOUSE_DRAGGED) {
|
||||
if (chart.getIntervalSelector() == null) {
|
||||
//make new interval selector
|
||||
chart.setIntervalSelector(chart.newIntervalSelector(t.getX(), dateAxis));
|
||||
chart.getIntervalSelector().heightProperty().bind(chart.heightProperty().subtract(dateAxis.heightProperty().subtract(dateAxis.tickLengthProperty())));
|
||||
chart.getIntervalSelector().addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
|
||||
if (event.getButton() == MouseButton.SECONDARY) {
|
||||
chart.clearIntervalSelector();
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
startX = t.getX();
|
||||
} else {
|
||||
//resize/position existing selector
|
||||
if (t.getX() > startX) {
|
||||
chart.getIntervalSelector().setX(startX);
|
||||
chart.getIntervalSelector().setWidth(t.getX() - startX);
|
||||
} else {
|
||||
chart.getIntervalSelector().setX(t.getX());
|
||||
chart.getIntervalSelector().setWidth(startX - t.getX());
|
||||
public void handle(MouseEvent mouseEvent) {
|
||||
EventType<? extends MouseEvent> mouseEventType = mouseEvent.getEventType();
|
||||
if (mouseEventType == MouseEvent.MOUSE_PRESSED) {
|
||||
//caputure x-position, incase we are repositioning existing selector
|
||||
startX = mouseEvent.getX();
|
||||
// chart.setCursor(Cursor.H_RESIZE);
|
||||
} else if ((mouseEventType == MouseEvent.MOUSE_DRAGGED)
|
||||
|| mouseEventType == MouseEvent.MOUSE_MOVED && (requireDrag == false)) {
|
||||
if (chart.getIntervalSelector() == null) {
|
||||
//make new interval selector
|
||||
chart.setIntervalSelector(chart.newIntervalSelector(mouseEvent.getX(), dateAxis));
|
||||
chart.getIntervalSelector().heightProperty().bind(chart.heightProperty().subtract(dateAxis.heightProperty().subtract(dateAxis.tickLengthProperty())));
|
||||
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();
|
||||
}
|
||||
}
|
||||
} else if (t.getEventType() == MouseEvent.MOUSE_RELEASED) {
|
||||
chart.setCursor(Cursor.DEFAULT);
|
||||
});
|
||||
}
|
||||
startX = mouseEvent.getX();
|
||||
} else {
|
||||
//resize/position existing selector
|
||||
if (mouseEvent.getX() > startX) {
|
||||
chart.getIntervalSelector().setX(startX);
|
||||
chart.getIntervalSelector().setWidth(mouseEvent.getX() - startX);
|
||||
} else {
|
||||
chart.getIntervalSelector().setX(mouseEvent.getX());
|
||||
chart.getIntervalSelector().setWidth(startX - mouseEvent.getX());
|
||||
}
|
||||
}
|
||||
} else if (mouseEventType == MouseEvent.MOUSE_RELEASED) {
|
||||
// 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
t.consume();
|
||||
}
|
||||
// mouseEvent.consume();
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,15 +175,12 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
*/
|
||||
private final Axis<X> dateAxis;
|
||||
|
||||
protected Tooltip tooltip;
|
||||
private Tooltip tooltip;
|
||||
|
||||
/////////drag state
|
||||
private DragPosition dragPosition;
|
||||
|
||||
private double startLeft;
|
||||
|
||||
private double startX;
|
||||
|
||||
private double startWidth;
|
||||
/////////end drag state
|
||||
|
||||
@ -179,7 +211,8 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
Point2D localMouse = sceneToLocal(new Point2D(event.getSceneX(), event.getSceneY()));
|
||||
final double diffX = getX() - localMouse.getX();
|
||||
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 {
|
||||
setCursor(Cursor.HAND);
|
||||
}
|
||||
@ -221,9 +254,7 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
//convert to DateTimes, using max/min if null(off axis)
|
||||
DateTime start = parseDateTime(getSpanStart());
|
||||
DateTime end = parseDateTime(getSpanEnd());
|
||||
|
||||
Interval i = adjustInterval(start.isBefore(end) ? new Interval(start, end) : new Interval(end, start));
|
||||
|
||||
controller.pushTimeRange(i);
|
||||
}
|
||||
}
|
||||
@ -258,13 +289,15 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
*/
|
||||
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() {
|
||||
final X start = getSpanStart();
|
||||
final X end = getSpanEnd();
|
||||
Tooltip.uninstall(this, tooltip);
|
||||
tooltip = new Tooltip(
|
||||
NbBundle.getMessage(TimeLineChart.class, "Timeline.ui.TimeLineChart.tooltip.text", formatSpan(start),
|
||||
formatSpan(end)));
|
||||
Bundle.Timeline_ui_TimeLineChart_tooltip_text(formatSpan(start), formatSpan(end)));
|
||||
Tooltip.install(this, tooltip);
|
||||
}
|
||||
|
||||
@ -290,7 +323,9 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
*/
|
||||
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.loggedTask.updatingCounts=updating counts
|
||||
CountsViewPane.loggedTask.wrappingUp=wrapping up
|
||||
EventCountsChart.contextMenu.zoomHistory.name=Zoom History
|
||||
CountsViewPane.scaleLabel.text=Scale\:
|
||||
CountsViewPane.logRadio.text=Logarithmic
|
||||
CountsViewPane.linearRadio.text=Linear
|
||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.ui.countsview;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.MissingResourceException;
|
||||
import javafx.scene.chart.Axis;
|
||||
import javafx.scene.chart.CategoryAxis;
|
||||
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
|
||||
* 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;
|
||||
|
||||
@ -58,6 +59,7 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
||||
* by padding the end with one 'period'
|
||||
*/
|
||||
private RangeDivisionInfo rangeInfo;
|
||||
private final ChartDragHandler<String, EventCountsChart> dragHandler;
|
||||
|
||||
EventCountsChart(CategoryAxis dateAxis, NumberAxis countAxis) {
|
||||
super(dateAxis, countAxis);
|
||||
@ -81,15 +83,19 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
||||
setTitle(null);
|
||||
|
||||
//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);
|
||||
setOnMouseReleased(dragHandler);
|
||||
setOnMouseDragged(dragHandler);
|
||||
setOnMouseMoved(dragHandler);
|
||||
|
||||
setOnMouseClicked((MouseEvent clickEvent) -> {
|
||||
contextMenu.hide();
|
||||
if (chartContextMenu != null) {
|
||||
chartContextMenu.hide();
|
||||
}
|
||||
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();
|
||||
}
|
||||
});
|
||||
@ -101,17 +107,34 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
||||
intervalSelector = null;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"EventCountsChart.contextMenu.zoomHistory.name=Zoom History"})
|
||||
ContextMenu getChartContextMenu(MouseEvent clickEvent) throws MissingResourceException {
|
||||
if (chartContextMenu != null) {
|
||||
chartContextMenu.hide();
|
||||
}
|
||||
|
||||
chartContextMenu = ActionUtils.createContextMenu(Arrays.asList(
|
||||
// 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 Forward(controller))));
|
||||
chartContextMenu.setAutoHide(true);
|
||||
return chartContextMenu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized void setController(TimeLineController controller) {
|
||||
public synchronized void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(this.controller.getEventsModel());
|
||||
//we have defered creating context menu until control is available
|
||||
contextMenu = ActionUtils.createContextMenu(
|
||||
Arrays.asList(new ActionGroup(
|
||||
NbBundle.getMessage(this.getClass(), "EventCountsChart.contextMenu.zoomHistory.name"),
|
||||
new Back(controller),
|
||||
new Forward(controller))));
|
||||
contextMenu.setAutoHide(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -145,7 +168,7 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
||||
* @return the context menu for this chart
|
||||
*/
|
||||
ContextMenu getContextMenu() {
|
||||
return contextMenu;
|
||||
return chartContextMenu;
|
||||
}
|
||||
|
||||
void setRangeInfo(RangeDivisionInfo rangeInfo) {
|
||||
@ -177,7 +200,7 @@ class EventCountsChart extends StackedBarChart<String, Number> implements TimeLi
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user