mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07:42 +00:00
Resolve merge conflict for com.sun.javafx.Utils
This commit is contained in:
commit
ee396f3271
@ -24,10 +24,7 @@ TimelinePanel.jButton7.text=3d
|
||||
TimelinePanel.jButton2.text=1m
|
||||
TimelinePanel.jButton3.text=3m
|
||||
TimelinePanel.jButton4.text=2w
|
||||
TimeLineTopComponent.eventsTab.name=Events
|
||||
TimeLineTopComponent.filterTab.name=Filters
|
||||
OpenTimelineAction.title=Timeline
|
||||
OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources.
|
||||
TimeLineTopComponent.timeZonePanel.text=Display Times In\:
|
||||
ProgressWindow.progressHeader.text=\
|
||||
|
||||
|
@ -316,8 +316,10 @@ public class TimeLineController {
|
||||
LOGGER.log(Level.INFO, "Beginning generation of timeline"); // NON-NLS
|
||||
try {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (isWindowOpen()) {
|
||||
mainFrame.close();
|
||||
synchronized (TimeLineController.this) {
|
||||
if (isWindowOpen()) {
|
||||
mainFrame.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
final SleuthkitCase sleuthkitCase = Case.getCurrentCase().getSleuthkitCase();
|
||||
@ -362,8 +364,10 @@ public class TimeLineController {
|
||||
void rebuildTagsTable() {
|
||||
LOGGER.log(Level.INFO, "starting to rebuild tags table"); // NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (isWindowOpen()) {
|
||||
mainFrame.close();
|
||||
synchronized (TimeLineController.this) {
|
||||
if (isWindowOpen()) {
|
||||
mainFrame.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
synchronized (eventsRepository) {
|
||||
@ -388,16 +392,19 @@ public class TimeLineController {
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener);
|
||||
IngestManager.getInstance().removeIngestJobEventListener(ingestJobListener);
|
||||
Case.removePropertyChangeListener(caseListener);
|
||||
mainFrame.close();
|
||||
mainFrame.setVisible(false);
|
||||
mainFrame = null;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
synchronized (TimeLineController.this) {
|
||||
mainFrame.close();
|
||||
mainFrame = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* show the timeline window and prompt for rebuilding database if necessary.
|
||||
*/
|
||||
synchronized void openTimeLine() {
|
||||
void openTimeLine() {
|
||||
// listen for case changes (specifically images being added, and case changes).
|
||||
if (Case.isCaseOpen() && !listeningToAutopsy) {
|
||||
IngestManager.getInstance().addIngestModuleEventListener(ingestModuleListener);
|
||||
@ -539,20 +546,20 @@ public class TimeLineController {
|
||||
/**
|
||||
* private method to build gui if necessary and make it visible.
|
||||
*/
|
||||
synchronized private void showWindow() {
|
||||
if (mainFrame == null) {
|
||||
LOGGER.log(Level.WARNING, "Tried to show timeline with invalid window. Rebuilding GUI."); // NON-NLS
|
||||
mainFrame = (TimeLineTopComponent) WindowManager.getDefault().findTopComponent(
|
||||
NbBundle.getMessage(TimeLineController.class, "CTL_TimeLineTopComponentAction"));
|
||||
if (mainFrame == null) {
|
||||
mainFrame = new TimeLineTopComponent();
|
||||
}
|
||||
mainFrame.setController(this);
|
||||
}
|
||||
private void showWindow() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
mainFrame.open();
|
||||
mainFrame.setVisible(true);
|
||||
mainFrame.toFront();
|
||||
synchronized (TimeLineController.this) {
|
||||
if (mainFrame == null) {
|
||||
LOGGER.log(Level.WARNING, "Tried to show timeline with invalid window. Rebuilding GUI."); // NON-NLS
|
||||
mainFrame = (TimeLineTopComponent) WindowManager.getDefault().findTopComponent(
|
||||
NbBundle.getMessage(TimeLineController.class, "CTL_TimeLineTopComponentAction"));
|
||||
if (mainFrame == null) {
|
||||
mainFrame = new TimeLineTopComponent(this);
|
||||
}
|
||||
}
|
||||
mainFrame.open();
|
||||
mainFrame.toFront();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.SplitPane;
|
||||
import javafx.scene.control.Tab;
|
||||
@ -34,7 +34,6 @@ import javafx.scene.input.KeyCodeCombination;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.netbeans.api.settings.ConvertAsProperties;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.explorer.ExplorerUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
@ -51,135 +50,103 @@ import org.sleuthkit.autopsy.timeline.ui.StatusBar;
|
||||
import org.sleuthkit.autopsy.timeline.ui.TimeLineResultView;
|
||||
import org.sleuthkit.autopsy.timeline.ui.TimeZonePanel;
|
||||
import org.sleuthkit.autopsy.timeline.ui.VisualizationPanel;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.tree.NavPanel;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.tree.EventsTree;
|
||||
import org.sleuthkit.autopsy.timeline.ui.filtering.FilterSetPanel;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.ZoomSettingsPane;
|
||||
|
||||
/**
|
||||
* TopComponent for the timeline feature.
|
||||
*/
|
||||
@ConvertAsProperties(
|
||||
dtd = "-//org.sleuthkit.autopsy.timeline//TimeLine//EN",
|
||||
autostore = false)
|
||||
@TopComponent.Description(
|
||||
preferredID = "TimeLineTopComponent",
|
||||
//iconBase="SET/PATH/TO/ICON/HERE",
|
||||
persistenceType = TopComponent.PERSISTENCE_NEVER)
|
||||
@TopComponent.Registration(mode = "timeline", openAtStartup = false)
|
||||
public final class TimeLineTopComponent extends TopComponent implements ExplorerManager.Provider, TimeLineUI {
|
||||
public final class TimeLineTopComponent extends TopComponent implements ExplorerManager.Provider {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(TimeLineTopComponent.class.getName());
|
||||
|
||||
private DataContentPanel dataContentPanel;
|
||||
private final DataContentPanel dataContentPanel;
|
||||
|
||||
private TimeLineResultView tlrv;
|
||||
private final TimeLineResultView tlrv;
|
||||
|
||||
private final ExplorerManager em = new ExplorerManager();
|
||||
|
||||
private TimeLineController controller;
|
||||
private final TimeLineController controller;
|
||||
|
||||
////jfx componenets that make up the interface
|
||||
private final FilterSetPanel filtersPanel = new FilterSetPanel();
|
||||
|
||||
private final Tab eventsTab = new Tab(
|
||||
NbBundle.getMessage(TimeLineTopComponent.class, "TimeLineTopComponent.eventsTab.name"));
|
||||
|
||||
private final Tab filterTab = new Tab(
|
||||
NbBundle.getMessage(TimeLineTopComponent.class, "TimeLineTopComponent.filterTab.name"));
|
||||
|
||||
private final VBox leftVBox = new VBox(5);
|
||||
|
||||
private final NavPanel navPanel = new NavPanel();
|
||||
|
||||
private final StatusBar statusBar = new StatusBar();
|
||||
|
||||
private final TabPane tabPane = new TabPane();
|
||||
|
||||
private final ZoomSettingsPane zoomSettingsPane = new ZoomSettingsPane();
|
||||
|
||||
private final VisualizationPanel visualizationPanel = new VisualizationPanel(navPanel);
|
||||
|
||||
private final SplitPane splitPane = new SplitPane();
|
||||
|
||||
private final TimeZonePanel timeZonePanel = new TimeZonePanel();
|
||||
|
||||
public TimeLineTopComponent() {
|
||||
public TimeLineTopComponent(TimeLineController controller) {
|
||||
initComponents();
|
||||
|
||||
this.controller = controller;
|
||||
associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
|
||||
|
||||
setName(NbBundle.getMessage(TimeLineTopComponent.class, "CTL_TimeLineTopComponent"));
|
||||
setToolTipText(NbBundle.getMessage(TimeLineTopComponent.class, "HINT_TimeLineTopComponent"));
|
||||
setIcon(WindowManager.getDefault().getMainWindow().getIconImage()); //use the same icon as main application
|
||||
|
||||
timeZonePanel.setText(NbBundle.getMessage(this.getClass(), "TimeLineTopComponent.timeZonePanel.text"));
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
synchronized private void customizeComponents() {
|
||||
|
||||
dataContentPanel = DataContentPanel.createInstance();
|
||||
this.contentViewerContainerPanel.add(dataContentPanel, BorderLayout.CENTER);
|
||||
tlrv = new TimeLineResultView(dataContentPanel);
|
||||
tlrv = new TimeLineResultView(controller, dataContentPanel);
|
||||
DataResultPanel dataResultPanel = tlrv.getDataResultPanel();
|
||||
this.resultContainerPanel.add(dataResultPanel, BorderLayout.CENTER);
|
||||
dataResultPanel.open();
|
||||
|
||||
Platform.runLater(() -> {
|
||||
//assemble ui componenets together
|
||||
jFXstatusPanel.setScene(new Scene(statusBar));
|
||||
jFXVizPanel.setScene(new Scene(splitPane));
|
||||
|
||||
splitPane.setDividerPositions(0);
|
||||
|
||||
filterTab.setClosable(false);
|
||||
filterTab.setContent(filtersPanel);
|
||||
filterTab.setGraphic(new ImageView("org/sleuthkit/autopsy/timeline/images/funnel.png")); // NON-NLS
|
||||
|
||||
eventsTab.setClosable(false);
|
||||
eventsTab.setContent(navPanel);
|
||||
eventsTab.setGraphic(new ImageView("org/sleuthkit/autopsy/timeline/images/timeline_marker.png")); // NON-NLS
|
||||
|
||||
tabPane.getTabs().addAll(filterTab, eventsTab);
|
||||
VBox.setVgrow(tabPane, Priority.ALWAYS);
|
||||
|
||||
VBox.setVgrow(timeZonePanel, Priority.SOMETIMES);
|
||||
leftVBox.getChildren().addAll(timeZonePanel, zoomSettingsPane, tabPane);
|
||||
|
||||
SplitPane.setResizableWithParent(leftVBox, Boolean.FALSE);
|
||||
splitPane.getItems().addAll(leftVBox, visualizationPanel);
|
||||
});
|
||||
customizeFXComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
|
||||
tlrv.setController(controller);
|
||||
@NbBundle.Messages({"TimeLineTopComponent.eventsTab.name=Events",
|
||||
"TimeLineTopComponent.filterTab.name=Filters"})
|
||||
void customizeFXComponents() {
|
||||
Platform.runLater(() -> {
|
||||
jFXVizPanel.getScene().addEventFilter(KeyEvent.KEY_PRESSED,
|
||||
(KeyEvent event) -> {
|
||||
if (new KeyCodeCombination(KeyCode.LEFT, KeyCodeCombination.ALT_DOWN).match(event)) {
|
||||
new Back(controller).handle(new ActionEvent());
|
||||
} else if (new KeyCodeCombination(KeyCode.BACK_SPACE).match(event)) {
|
||||
new Back(controller).handle(new ActionEvent());
|
||||
} else if (new KeyCodeCombination(KeyCode.RIGHT, KeyCodeCombination.ALT_DOWN).match(event)) {
|
||||
new Forward(controller).handle(new ActionEvent());
|
||||
} else if (new KeyCodeCombination(KeyCode.BACK_SPACE, KeyCodeCombination.SHIFT_DOWN).match(event)) {
|
||||
new Forward(controller).handle(new ActionEvent());
|
||||
}
|
||||
});
|
||||
|
||||
//create and wire up jfx componenets that make up the interface
|
||||
final Tab filterTab = new Tab(Bundle.TimeLineTopComponent_filterTab_name(), new FilterSetPanel(controller));
|
||||
filterTab.setClosable(false);
|
||||
filterTab.setGraphic(new ImageView("org/sleuthkit/autopsy/timeline/images/funnel.png")); // NON-NLS
|
||||
|
||||
final EventsTree eventsTree = new EventsTree(controller);
|
||||
final VisualizationPanel visualizationPanel = new VisualizationPanel(controller, eventsTree);
|
||||
final Tab eventsTreeTab = new Tab(Bundle.TimeLineTopComponent_eventsTab_name(), eventsTree);
|
||||
eventsTreeTab.setClosable(false);
|
||||
eventsTreeTab.setGraphic(new ImageView("org/sleuthkit/autopsy/timeline/images/timeline_marker.png")); // NON-NLS
|
||||
eventsTreeTab.disableProperty().bind(controller.viewModeProperty().isEqualTo(VisualizationMode.COUNTS));
|
||||
|
||||
final TabPane leftTabPane = new TabPane(filterTab, eventsTreeTab);
|
||||
VBox.setVgrow(leftTabPane, Priority.ALWAYS);
|
||||
controller.viewModeProperty().addListener((Observable observable) -> {
|
||||
if (controller.viewModeProperty().get().equals(VisualizationMode.COUNTS)) {
|
||||
tabPane.getSelectionModel().select(filterTab);
|
||||
//if view mode is counts, make sure events tabd is not active
|
||||
leftTabPane.getSelectionModel().select(filterTab);
|
||||
}
|
||||
});
|
||||
eventsTab.disableProperty().bind(controller.viewModeProperty().isEqualTo(VisualizationMode.COUNTS));
|
||||
visualizationPanel.setController(controller);
|
||||
navPanel.setController(controller);
|
||||
filtersPanel.setController(controller);
|
||||
zoomSettingsPane.setController(controller);
|
||||
statusBar.setController(controller);
|
||||
|
||||
final TimeZonePanel timeZonePanel = new TimeZonePanel();
|
||||
VBox.setVgrow(timeZonePanel, Priority.SOMETIMES);
|
||||
|
||||
final ZoomSettingsPane zoomSettingsPane = new ZoomSettingsPane(controller);
|
||||
|
||||
final VBox leftVBox = new VBox(5, timeZonePanel, zoomSettingsPane, leftTabPane);
|
||||
SplitPane.setResizableWithParent(leftVBox, Boolean.FALSE);
|
||||
|
||||
final SplitPane mainSplitPane = new SplitPane(leftVBox, visualizationPanel);
|
||||
mainSplitPane.setDividerPositions(0);
|
||||
|
||||
final Scene scene = new Scene(mainSplitPane);
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED,
|
||||
(KeyEvent event) -> {
|
||||
if (new KeyCodeCombination(KeyCode.LEFT, KeyCodeCombination.ALT_DOWN).match(event)) {
|
||||
new Back(controller).handle(null);
|
||||
} else if (new KeyCodeCombination(KeyCode.BACK_SPACE).match(event)) {
|
||||
new Back(controller).handle(null);
|
||||
} else if (new KeyCodeCombination(KeyCode.RIGHT, KeyCodeCombination.ALT_DOWN).match(event)) {
|
||||
new Forward(controller).handle(null);
|
||||
} else if (new KeyCodeCombination(KeyCode.BACK_SPACE, KeyCodeCombination.SHIFT_DOWN).match(event)) {
|
||||
new Forward(controller).handle(null);
|
||||
}
|
||||
});
|
||||
|
||||
//add ui componenets to JFXPanels
|
||||
jFXVizPanel.setScene(scene);
|
||||
jFXstatusPanel.setScene(new Scene(new StatusBar(controller)));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -196,9 +163,9 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jFXstatusPanel = new javafx.embed.swing.JFXPanel();
|
||||
jFXstatusPanel = new JFXPanel();
|
||||
splitYPane = new javax.swing.JSplitPane();
|
||||
jFXVizPanel = new javafx.embed.swing.JFXPanel();
|
||||
jFXVizPanel = new JFXPanel();
|
||||
lowerSplitXPane = new javax.swing.JSplitPane();
|
||||
resultContainerPanel = new javax.swing.JPanel();
|
||||
contentViewerContainerPanel = new javax.swing.JPanel();
|
||||
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 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.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface TimeLineUI {
|
||||
|
||||
void setController(TimeLineController controller);
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by views of the data.
|
||||
*
|
||||
* Most implementations should install the relevant listeners in their
|
||||
* {@link #setController} and {@link #setModel} methods
|
||||
*/
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
|
||||
public interface TimeLineView extends TimeLineUI {
|
||||
|
||||
@Override
|
||||
void setController(TimeLineController controller);
|
||||
|
||||
void setModel(final FilteredEventsModel filteredEvents);
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
Back.actions.name.text=Back
|
||||
DefaultFilters.action.name.text=apply default filters
|
||||
Forward.action.name.text=Forward
|
||||
ZoomOut.action.name.text=apply default filters
|
||||
|
||||
|
@ -53,7 +53,8 @@ public class SaveSnapshotAsReport extends Action {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(SaveSnapshotAsReport.class.getName());
|
||||
|
||||
@NbBundle.Messages({"SaveSnapshot.action.name.text=save snapshot", "SaveSnapshot.fileChoose.title.text=Save snapshot to"})
|
||||
@NbBundle.Messages({"SaveSnapshot.action.name.text=save snapshot",
|
||||
"SaveSnapshot.fileChoose.title.text=Save snapshot to"})
|
||||
public SaveSnapshotAsReport(TimeLineController controller, WritableImage snapshot) {
|
||||
super(Bundle.SaveSnapshot_action_name_text());
|
||||
setEventHandler(new Consumer<ActionEvent>() {
|
||||
|
44
Core/src/org/sleuthkit/autopsy/timeline/actions/ZoomIn.java
Normal file
44
Core/src/org/sleuthkit/autopsy/timeline/actions/ZoomIn.java
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline.actions;
|
||||
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ZoomIn extends Action {
|
||||
|
||||
private static final Image MAGNIFIER_IN = new Image("/org/sleuthkit/autopsy/timeline/images/magnifier-zoom-in-green.png"); //NOI18N
|
||||
|
||||
@NbBundle.Messages({"ZoomIn.longText=Zoom in to view half as much time.",
|
||||
"ZoomIn.action.text=Zoom in"})
|
||||
public ZoomIn(TimeLineController controller) {
|
||||
super(Bundle.ZoomIn_action_text());
|
||||
setLongText(Bundle.ZoomIn_longText());
|
||||
setGraphic(new ImageView(MAGNIFIER_IN));
|
||||
setEventHandler(actionEvent -> {
|
||||
controller.pushZoomInTime();
|
||||
});
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,7 +19,8 @@
|
||||
package org.sleuthkit.autopsy.timeline.actions;
|
||||
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
@ -30,15 +31,22 @@ import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
*/
|
||||
public class ZoomOut extends Action {
|
||||
|
||||
private final TimeLineController controller;
|
||||
private static final Image MAGNIFIER_OUT = new Image("/org/sleuthkit/autopsy/timeline/images/magnifier-zoom-out-red.png"); //NOI18N
|
||||
|
||||
private final FilteredEventsModel eventsModel;
|
||||
@NbBundle.Messages({"ZoomOut.longText=Zoom out to view 50% more time.",
|
||||
"ZoomOut.action.text=Zoom out"})
|
||||
public ZoomOut(TimeLineController controller) {
|
||||
super(Bundle.ZoomOut_action_text());
|
||||
setLongText(Bundle.ZoomOut_longText());
|
||||
setGraphic(new ImageView(MAGNIFIER_OUT));
|
||||
setEventHandler(actionEvent -> {
|
||||
controller.pushZoomOutTime();
|
||||
});
|
||||
|
||||
public ZoomOut(final TimeLineController controller) {
|
||||
super(NbBundle.getMessage(ZoomOut.class, "ZoomOut.action.name.text"));
|
||||
this.controller = controller;
|
||||
eventsModel = controller.getEventsModel();
|
||||
//disable action when the current time range already encompases the entire case.
|
||||
disabledProperty().bind(new BooleanBinding() {
|
||||
private final FilteredEventsModel eventsModel = controller.getEventsModel();
|
||||
|
||||
{
|
||||
bind(eventsModel.zoomParametersProperty());
|
||||
}
|
||||
@ -48,8 +56,5 @@ public class ZoomOut extends Action {
|
||||
return eventsModel.zoomParametersProperty().getValue().getTimeRange().contains(eventsModel.getSpanningInterval());
|
||||
}
|
||||
});
|
||||
setEventHandler((ActionEvent t) -> {
|
||||
controller.zoomOutToActivity();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014-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.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline.actions;
|
||||
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ZoomToEvents extends Action {
|
||||
|
||||
private static final Image MAGNIFIER_OUT = new Image("/org/sleuthkit/autopsy/timeline/images/magnifier-zoom-out-red.png", 16, 16, true, true); //NOI18N
|
||||
|
||||
@NbBundle.Messages({"ZoomToEvents.action.text=Zoom to events",
|
||||
"ZoomToEvents.longText=Zoom out to show the nearest events."})
|
||||
public ZoomToEvents(final TimeLineController controller) {
|
||||
super(Bundle.ZoomToEvents_action_text());
|
||||
setLongText(Bundle.ZoomToEvents_longText());
|
||||
setGraphic(new ImageView(MAGNIFIER_OUT));
|
||||
setEventHandler(actionEvent -> {
|
||||
controller.zoomOutToActivity();
|
||||
});
|
||||
|
||||
//disable action when the current time range already encompases the entire case.
|
||||
disabledProperty().bind(new BooleanBinding() {
|
||||
private final FilteredEventsModel eventsModel = controller.getEventsModel();
|
||||
|
||||
{
|
||||
bind(eventsModel.zoomParametersProperty());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean computeValue() {
|
||||
//TODO: do a db query to see if using this action will actually result in viewable events
|
||||
return eventsModel.zoomParametersProperty().getValue().getTimeRange().contains(eventsModel.getSpanningInterval());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -41,7 +41,6 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent.DeletedContentTagInfo;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.RootEventType;
|
||||
import org.sleuthkit.autopsy.timeline.db.EventsRepository;
|
||||
|
@ -51,13 +51,11 @@ import javafx.scene.text.Font;
|
||||
import javafx.scene.text.FontWeight;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.events.RefreshRequestedEvent;
|
||||
|
||||
@ -75,7 +73,7 @@ import org.sleuthkit.autopsy.timeline.events.RefreshRequestedEvent;
|
||||
* {@link XYChart} doing the rendering. Is this a good idea? -jm TODO: pull up
|
||||
* common history context menu items out of derived classes? -jm
|
||||
*/
|
||||
public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y> & TimeLineChart<X>> extends BorderPane implements TimeLineView {
|
||||
public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y> & TimeLineChart<X>> extends BorderPane {
|
||||
|
||||
@NbBundle.Messages("AbstractVisualization.Drag_Tooltip.text=Drag the mouse to select a time interval to zoom into.")
|
||||
private static final Tooltip DRAG_TOOLTIP = new Tooltip(Bundle.AbstractVisualization_Drag_Tooltip_text());
|
||||
@ -102,11 +100,15 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
*/
|
||||
private Task<Boolean> updateTask;
|
||||
|
||||
protected TimeLineController controller;
|
||||
final protected TimeLineController controller;
|
||||
|
||||
protected FilteredEventsModel filteredEvents;
|
||||
final protected FilteredEventsModel filteredEvents;
|
||||
|
||||
protected ReadOnlyListWrapper<N> selectedNodes = new ReadOnlyListWrapper<>(FXCollections.observableArrayList());
|
||||
final protected ReadOnlyListWrapper<N> selectedNodes = new ReadOnlyListWrapper<>(FXCollections.observableArrayList());
|
||||
|
||||
private InvalidationListener invalidationListener = (Observable observable) -> {
|
||||
update();
|
||||
};
|
||||
|
||||
public ReadOnlyListProperty<N> getSelectedNodes() {
|
||||
return selectedNodes.getReadOnlyProperty();
|
||||
@ -186,7 +188,7 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
* Primarily this invokes the background {@link Task} returned by
|
||||
* {@link #getUpdateTask()} which derived classes must implement.
|
||||
*/
|
||||
synchronized public void update() {
|
||||
final synchronized public void update() {
|
||||
if (updateTask != null) {
|
||||
updateTask.cancel(true);
|
||||
updateTask = null;
|
||||
@ -212,7 +214,7 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
controller.monitorTask(updateTask);
|
||||
}
|
||||
|
||||
synchronized public void dispose() {
|
||||
final synchronized public void dispose() {
|
||||
if (updateTask != null) {
|
||||
updateTask.cancel(true);
|
||||
}
|
||||
@ -220,7 +222,12 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
invalidationListener = null;
|
||||
}
|
||||
|
||||
protected AbstractVisualizationPane(Pane partPane, Pane contextPane, Region spacer) {
|
||||
protected AbstractVisualizationPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) {
|
||||
this.controller = controller;
|
||||
|
||||
this.filteredEvents = controller.getEventsModel();
|
||||
this.filteredEvents.registerForEvents(this);
|
||||
this.filteredEvents.zoomParametersProperty().addListener(invalidationListener);
|
||||
this.leafPane = partPane;
|
||||
this.branchPane = contextPane;
|
||||
this.spacer = spacer;
|
||||
@ -235,18 +242,9 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
chart.setController(controller);
|
||||
|
||||
setModel(controller.getEventsModel());
|
||||
TimeLineController.getTimeZone().addListener((Observable observable) -> {
|
||||
update();
|
||||
});
|
||||
|
||||
TimeLineController.getTimeZone().addListener(invalidationListener);
|
||||
|
||||
//show tooltip text in status bar
|
||||
hoverProperty().addListener((observable, oldActivated, newActivated) -> {
|
||||
if (newActivated) {
|
||||
@ -255,21 +253,7 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
controller.setStatus("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void setModel(@Nonnull FilteredEventsModel filteredEvents) {
|
||||
|
||||
if (this.filteredEvents != null && this.filteredEvents != filteredEvents) {
|
||||
this.filteredEvents.unRegisterForEvents(this);
|
||||
this.filteredEvents.zoomParametersProperty().removeListener(invalidationListener);
|
||||
}
|
||||
if (this.filteredEvents != filteredEvents) {
|
||||
filteredEvents.registerForEvents(this);
|
||||
filteredEvents.zoomParametersProperty().addListener(invalidationListener);
|
||||
}
|
||||
this.filteredEvents = filteredEvents;
|
||||
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@ -278,10 +262,6 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
|
||||
update();
|
||||
}
|
||||
|
||||
protected InvalidationListener invalidationListener = (Observable observable) -> {
|
||||
update();
|
||||
};
|
||||
|
||||
/**
|
||||
* iterate through the list of tick-marks building a two level structure of
|
||||
* replacement tick marl labels. (Visually) upper level has most
|
||||
|
@ -28,13 +28,12 @@ import javafx.scene.layout.Region;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineUI;
|
||||
|
||||
/**
|
||||
* simple status bar that only shows one possible message determined by
|
||||
* {@link TimeLineController#newEventsFlag}
|
||||
*/
|
||||
public class StatusBar extends ToolBar implements TimeLineUI {
|
||||
public class StatusBar extends ToolBar {
|
||||
|
||||
private TimeLineController controller;
|
||||
|
||||
@ -56,7 +55,8 @@ public class StatusBar extends ToolBar implements TimeLineUI {
|
||||
@FXML
|
||||
private Label messageLabel;
|
||||
|
||||
public StatusBar() {
|
||||
public StatusBar(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
FXMLConstructor.construct(this, "StatusBar.fxml"); // NON-NLS
|
||||
}
|
||||
|
||||
@ -73,11 +73,7 @@ public class StatusBar extends ToolBar implements TimeLineUI {
|
||||
taskLabel.setText(NbBundle.getMessage(this.getClass(), "StatusBar.taskLabel.text"));
|
||||
taskLabel.setVisible(false);
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
refreshLabel.visibleProperty().bind(this.controller.getNewEventsFlag());
|
||||
refreshLabel.managedProperty().bind(this.controller.getNewEventsFlag());
|
||||
taskLabel.textProperty().bind(this.controller.getTaskTitle());
|
||||
|
@ -29,7 +29,6 @@ import javafx.scene.input.MouseEvent;
|
||||
import org.controlsfx.control.action.ActionGroup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.actions.Back;
|
||||
import org.sleuthkit.autopsy.timeline.actions.Forward;
|
||||
|
||||
@ -38,8 +37,9 @@ import org.sleuthkit.autopsy.timeline.actions.Forward;
|
||||
*
|
||||
* @param <X> the type of values along the horizontal axis
|
||||
*/
|
||||
public interface TimeLineChart<X> extends TimeLineView {
|
||||
public interface TimeLineChart<X> {
|
||||
|
||||
// void setController(TimeLineController controller);
|
||||
IntervalSelector<? extends X> getIntervalSelector();
|
||||
|
||||
void setIntervalSelector(IntervalSelector<? extends X> newIntervalSelector);
|
||||
@ -139,6 +139,17 @@ public interface TimeLineChart<X> extends TimeLineView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enum to represent whether the drag is a left/right-edge modification or a
|
||||
* horizontal slide triggered by dragging the center
|
||||
*/
|
||||
enum DragPosition {
|
||||
|
||||
LEFT,
|
||||
CENTER,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"TimeLineChart.zoomHistoryActionGroup.name=Zoom History"})
|
||||
static ActionGroup newZoomHistoyActionGroup(TimeLineController controller) {
|
||||
return new ActionGroup(Bundle.TimeLineChart_zoomHistoryActionGroup_name(),
|
||||
|
@ -25,12 +25,11 @@ import javax.swing.SwingUtilities;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.explorernodes.EventRootNode;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.explorernodes.EventRootNode;
|
||||
|
||||
/**
|
||||
* Since it was too hard to derive from {@link DataResultPanel}, this class
|
||||
@ -39,16 +38,16 @@ import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
|
||||
* {@link DataResultPanel}. That is, this class acts as a sort of bridge/adapter
|
||||
* between a FilteredEventsModel instance and a DataResultPanel instance.
|
||||
*/
|
||||
public class TimeLineResultView implements TimeLineView {
|
||||
public class TimeLineResultView {
|
||||
|
||||
/**
|
||||
* the {@link DataResultPanel} that is the real view proxied by this class
|
||||
*/
|
||||
private final DataResultPanel dataResultPanel;
|
||||
|
||||
private TimeLineController controller;
|
||||
private final TimeLineController controller;
|
||||
|
||||
private FilteredEventsModel filteredEvents;
|
||||
private final FilteredEventsModel filteredEvents;
|
||||
|
||||
private Set<Long> selectedEventIDs = new HashSet<>();
|
||||
|
||||
@ -56,19 +55,11 @@ public class TimeLineResultView implements TimeLineView {
|
||||
return dataResultPanel;
|
||||
}
|
||||
|
||||
public TimeLineResultView(DataContent dataContent) {
|
||||
dataResultPanel = DataResultPanel.createInstanceUninitialized("", "", Node.EMPTY, 0, dataContent);
|
||||
}
|
||||
public TimeLineResultView(TimeLineController controller, DataContent dataContent) {
|
||||
|
||||
/**
|
||||
* Set the Controller for this class. Also sets the model provided by the
|
||||
* controller as the model for this view.
|
||||
*
|
||||
* @param controller
|
||||
*/
|
||||
@Override
|
||||
public void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
this.filteredEvents = controller.getEventsModel();
|
||||
dataResultPanel = DataResultPanel.createInstanceUninitialized("", "", Node.EMPTY, 0, dataContent);
|
||||
|
||||
//set up listeners on relevant properties
|
||||
TimeLineController.getTimeZone().addListener((Observable observable) -> {
|
||||
@ -78,18 +69,7 @@ public class TimeLineResultView implements TimeLineView {
|
||||
controller.getSelectedEventIDs().addListener((Observable o) -> {
|
||||
refresh();
|
||||
});
|
||||
|
||||
setModel(controller.getEventsModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Model for this View
|
||||
*
|
||||
* @param filteredEvents
|
||||
*/
|
||||
@Override
|
||||
synchronized public void setModel(final FilteredEventsModel filteredEvents) {
|
||||
this.filteredEvents = filteredEvents;
|
||||
refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,10 @@ import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.Toggle;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
@ -50,8 +53,9 @@ public class TimeZonePanel extends TitledPane {
|
||||
}
|
||||
|
||||
@FXML
|
||||
@NbBundle.Messages({"TimeZonePanel.title=Display Times In:"})
|
||||
public void initialize() {
|
||||
|
||||
setText(Bundle.TimeZonePanel_title());
|
||||
// localRadio.setText("Local Time Zone: " + getTimeZoneString(TimeZone.getDefault()));
|
||||
localRadio.setText(NbBundle.getMessage(this.getClass(), "TimeZonePanel.localRadio.text"));
|
||||
otherRadio.setText(NbBundle.getMessage(this.getClass(), "TimeZonePanel.otherRadio.text"));
|
||||
|
@ -9,7 +9,7 @@
|
||||
<?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" 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.40" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<top>
|
||||
<ToolBar fx:id="toolBar" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||
<items>
|
||||
@ -115,7 +115,7 @@
|
||||
</Separator>
|
||||
<HBox>
|
||||
<children>
|
||||
<Button fx:id="zoomOutButton" mnemonicParsing="false">
|
||||
<Button fx:id="zoomOutButton" contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false">
|
||||
<graphic>
|
||||
<ImageView pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
@ -127,7 +127,7 @@
|
||||
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
||||
</HBox.margin>
|
||||
</Button>
|
||||
<Button fx:id="zoomInButton" mnemonicParsing="false">
|
||||
<Button fx:id="zoomInButton" contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false">
|
||||
<graphic>
|
||||
<ImageView pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
@ -143,7 +143,7 @@
|
||||
</HBox>
|
||||
<MenuButton fx:id="zoomMenuButton" mnemonicParsing="false">
|
||||
<graphic>
|
||||
<ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
|
||||
<ImageView pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../images/magnifier-left.png" />
|
||||
</image>
|
||||
|
@ -63,6 +63,7 @@ import jfxtras.scene.control.LocalDateTimeTextField;
|
||||
import org.controlsfx.control.NotificationPane;
|
||||
import org.controlsfx.control.RangeSlider;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.controlsfx.control.action.ActionUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.Interval;
|
||||
@ -71,11 +72,12 @@ import org.sleuthkit.autopsy.coreutils.LoggedTask;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.VisualizationMode;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ResetFilters;
|
||||
import org.sleuthkit.autopsy.timeline.actions.SaveSnapshotAsReport;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ZoomIn;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ZoomOut;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ZoomToEvents;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.events.TagsUpdatedEvent;
|
||||
import org.sleuthkit.autopsy.timeline.filters.TagsFilter;
|
||||
@ -83,7 +85,7 @@ import static org.sleuthkit.autopsy.timeline.ui.Bundle.VisualizationPanel_refres
|
||||
import static org.sleuthkit.autopsy.timeline.ui.Bundle.VisualizationPanel_tagsAddedOrDeleted;
|
||||
import org.sleuthkit.autopsy.timeline.ui.countsview.CountsViewPane;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.DetailViewPane;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.tree.NavPanel;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.tree.EventsTree;
|
||||
import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
||||
|
||||
/**
|
||||
@ -94,7 +96,7 @@ import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
||||
*
|
||||
* TODO: refactor common code out of histogram and CountsView? -jm
|
||||
*/
|
||||
public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
final public class VisualizationPanel extends BorderPane {
|
||||
|
||||
private static final Image INFORMATION = new Image("org/sleuthkit/autopsy/timeline/images/information.png", 16, 16, true, true); // NON-NLS
|
||||
private static final Image REFRESH = new Image("org/sleuthkit/autopsy/timeline/images/arrow-circle-double-135.png"); // NON-NLS
|
||||
@ -104,7 +106,7 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
@GuardedBy("this")
|
||||
private LoggedTask<Void> histogramTask;
|
||||
|
||||
private final NavPanel navPanel;
|
||||
private final EventsTree eventsTree;
|
||||
|
||||
private AbstractVisualizationPane<?, ?, ?, ?> visualization;
|
||||
|
||||
@ -204,14 +206,15 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
|
||||
static private final Lighting lighting = new Lighting();
|
||||
|
||||
public VisualizationPanel(NavPanel navPanel) {
|
||||
this.navPanel = navPanel;
|
||||
public VisualizationPanel(TimeLineController controller, EventsTree eventsTree) {
|
||||
this.controller = controller;
|
||||
this.eventsTree = eventsTree;
|
||||
FXMLConstructor.construct(this, "VisualizationPanel.fxml"); // NON-NLS
|
||||
}
|
||||
|
||||
@FXML // This method is called by the FXMLLoader when initialization is complete
|
||||
@NbBundle.Messages("VisualizationPanel.refresh=refresh")
|
||||
protected void initialize() {
|
||||
void initialize() {
|
||||
assert endPicker != null : "fx:id=\"endPicker\" was not injected: check your FXML file 'ViewWrapper.fxml'."; // NON-NLS
|
||||
assert histogramBox != null : "fx:id=\"histogramBox\" was not injected: check your FXML file 'ViewWrapper.fxml'."; // NON-NLS
|
||||
assert startPicker != null : "fx:id=\"startPicker\" was not injected: check your FXML file 'ViewWrapper.fxml'."; // NON-NLS
|
||||
@ -286,13 +289,6 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
}
|
||||
zoomMenuButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomMenuButton.text")); // NON-NLS
|
||||
|
||||
zoomOutButton.setOnAction(e -> {
|
||||
controller.pushZoomOutTime();
|
||||
});
|
||||
zoomInButton.setOnAction(e -> {
|
||||
controller.pushZoomInTime();
|
||||
});
|
||||
|
||||
snapShotButton.setOnAction(event ->
|
||||
this.snapshot(snapShotResult -> {
|
||||
new SaveSnapshotAsReport(controller, snapShotResult.getImage()).handle(event);
|
||||
@ -301,12 +297,22 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
);
|
||||
|
||||
snapShotButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapShotButton.text")); // NON-NLS
|
||||
}
|
||||
if (this.filteredEvents != null && this.filteredEvents != controller.getEventsModel()) {
|
||||
this.filteredEvents.unRegisterForEvents(this);
|
||||
this.filteredEvents.timeRangeProperty().removeListener(timeRangeInvalidationListener);
|
||||
this.filteredEvents.zoomParametersProperty().removeListener(zoomListener);
|
||||
}
|
||||
if (this.filteredEvents != controller.getEventsModel()) {
|
||||
controller.getEventsModel().registerForEvents(this);
|
||||
controller.getEventsModel().timeRangeProperty().addListener(timeRangeInvalidationListener);
|
||||
controller.getEventsModel().zoomParametersProperty().addListener(zoomListener);
|
||||
}
|
||||
|
||||
this.filteredEvents = controller.getEventsModel();
|
||||
refreshTimeUI(controller.getEventsModel().timeRangeProperty().get());
|
||||
ActionUtils.configureButton(new ZoomOut(controller), zoomOutButton);
|
||||
ActionUtils.configureButton(new ZoomIn(controller), zoomInButton);
|
||||
|
||||
@Override
|
||||
public synchronized void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(controller.getEventsModel());
|
||||
setViewMode(controller.viewModeProperty().get());
|
||||
controller.getNeedsHistogramRebuild().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
|
||||
if (newValue) {
|
||||
@ -321,33 +327,14 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
refreshHistorgram();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
if (this.filteredEvents != null && this.filteredEvents != filteredEvents) {
|
||||
this.filteredEvents.unRegisterForEvents(this);
|
||||
this.filteredEvents.timeRangeProperty().removeListener(timeRangeInvalidationListener);
|
||||
this.filteredEvents.zoomParametersProperty().removeListener(zoomListener);
|
||||
}
|
||||
if (this.filteredEvents != filteredEvents) {
|
||||
filteredEvents.registerForEvents(this);
|
||||
filteredEvents.timeRangeProperty().addListener(timeRangeInvalidationListener);
|
||||
filteredEvents.zoomParametersProperty().addListener(zoomListener);
|
||||
}
|
||||
|
||||
this.filteredEvents = filteredEvents;
|
||||
|
||||
refreshTimeUI(filteredEvents.timeRangeProperty().get());
|
||||
|
||||
}
|
||||
|
||||
private void setViewMode(VisualizationMode visualizationMode) {
|
||||
switch (visualizationMode) {
|
||||
case COUNTS:
|
||||
setVisualization(new CountsViewPane(partPane, contextPane, spacer));
|
||||
setVisualization(new CountsViewPane(controller, partPane, contextPane, spacer));
|
||||
countsToggle.setSelected(true);
|
||||
break;
|
||||
case DETAIL:
|
||||
setVisualization(new DetailViewPane(partPane, contextPane, spacer));
|
||||
setVisualization(new DetailViewPane(controller, partPane, contextPane, spacer));
|
||||
detailsToggle.setSelected(true);
|
||||
break;
|
||||
}
|
||||
@ -362,24 +349,25 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
}
|
||||
|
||||
visualization = newViz;
|
||||
visualization.update();
|
||||
toolBar.getItems().addAll(newViz.getSettingsNodes());
|
||||
|
||||
visualization.setController(controller);
|
||||
notificationPane.setContent(visualization);
|
||||
if (visualization instanceof DetailViewPane) {
|
||||
navPanel.setDetailViewPane((DetailViewPane) visualization);
|
||||
eventsTree.setDetailViewPane((DetailViewPane) visualization);
|
||||
}
|
||||
visualization.hasEvents.addListener((observable, oldValue, newValue) -> {
|
||||
if (newValue == false) {
|
||||
|
||||
notificationPane.setContent(new StackPane(visualization, new Region() {
|
||||
{
|
||||
setBackground(new Background(new BackgroundFill(Color.GREY, CornerRadii.EMPTY, Insets.EMPTY)));
|
||||
setOpacity(.3);
|
||||
}
|
||||
}, new NoEventsDialog(() -> {
|
||||
notificationPane.setContent(visualization);
|
||||
})));
|
||||
notificationPane.setContent(
|
||||
new StackPane(visualization,
|
||||
new Region() {
|
||||
{
|
||||
setBackground(new Background(new BackgroundFill(Color.GREY, CornerRadii.EMPTY, Insets.EMPTY)));
|
||||
setOpacity(.3);
|
||||
}
|
||||
},
|
||||
new NoEventsDialog(() -> notificationPane.setContent(visualization))));
|
||||
} else {
|
||||
notificationPane.setContent(visualization);
|
||||
}
|
||||
@ -544,7 +532,6 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
private NoEventsDialog(Runnable closeCallback) {
|
||||
this.closeCallback = closeCallback;
|
||||
FXMLConstructor.construct(this, "NoEventsDialog.fxml"); // NON-NLS
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
@ -554,15 +541,9 @@ public class VisualizationPanel extends BorderPane implements TimeLineView {
|
||||
assert zoomButton != null : "fx:id=\"zoomButton\" was not injected: check your FXML file 'NoEventsDialog.fxml'."; // NON-NLS
|
||||
|
||||
noEventsDialogLabel.setText(NbBundle.getMessage(NoEventsDialog.class, "VisualizationPanel.noEventsDialogLabel.text")); // NON-NLS
|
||||
zoomButton.setText(NbBundle.getMessage(NoEventsDialog.class, "VisualizationPanel.zoomButton.text")); // NON-NLS
|
||||
ActionUtils.configureButton(new ZoomToEvents(controller), zoomButton);
|
||||
|
||||
Action zoomOutAction = new ZoomOut(controller);
|
||||
zoomButton.setOnAction(zoomOutAction);
|
||||
zoomButton.disableProperty().bind(zoomOutAction.disabledProperty());
|
||||
|
||||
dismissButton.setOnAction(e -> {
|
||||
closeCallback.run();
|
||||
});
|
||||
dismissButton.setOnAction(actionEvent -> closeCallback.run());
|
||||
Action defaultFiltersAction = new ResetFilters(controller);
|
||||
resetFiltersButton.setOnAction(defaultFiltersAction);
|
||||
resetFiltersButton.disableProperty().bind(defaultFiltersAction.disabledProperty());
|
||||
|
@ -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");
|
||||
|
@ -66,7 +66,6 @@ import org.sleuthkit.autopsy.coreutils.LoggedTask;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.VisualizationMode;
|
||||
import org.sleuthkit.autopsy.timeline.actions.Back;
|
||||
import org.sleuthkit.autopsy.timeline.actions.Forward;
|
||||
@ -279,9 +278,9 @@ public class CountsViewPane extends AbstractVisualizationPane<String, Number, No
|
||||
};
|
||||
}
|
||||
|
||||
public CountsViewPane(Pane partPane, Pane contextPane, Region spacer) {
|
||||
super(partPane, contextPane, spacer);
|
||||
chart = new EventCountsChart(dateAxis, countAxis);
|
||||
public CountsViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) {
|
||||
super(controller, partPane, contextPane, spacer);
|
||||
chart = new EventCountsChart(controller, dateAxis, countAxis);
|
||||
setChartClickHandler();
|
||||
chart.setData(dataSets);
|
||||
setCenter(chart);
|
||||
|
@ -19,7 +19,6 @@
|
||||
package org.sleuthkit.autopsy.timeline.ui.countsview;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.MissingResourceException;
|
||||
import javafx.scene.chart.CategoryAxis;
|
||||
import javafx.scene.chart.NumberAxis;
|
||||
@ -32,7 +31,6 @@ import org.joda.time.DateTime;
|
||||
import org.joda.time.Interval;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.ui.IntervalSelector;
|
||||
import org.sleuthkit.autopsy.timeline.ui.TimeLineChart;
|
||||
import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
||||
@ -45,11 +43,12 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
|
||||
private ContextMenu chartContextMenu;
|
||||
|
||||
@Override
|
||||
public ContextMenu getChartContextMenu() {
|
||||
return chartContextMenu;
|
||||
}
|
||||
|
||||
private TimeLineController controller;
|
||||
private final TimeLineController controller;
|
||||
|
||||
private IntervalSelector<? extends String> intervalSelector;
|
||||
|
||||
@ -60,8 +59,9 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
*/
|
||||
private RangeDivisionInfo rangeInfo;
|
||||
|
||||
EventCountsChart(CategoryAxis dateAxis, NumberAxis countAxis) {
|
||||
EventCountsChart(TimeLineController controller, CategoryAxis dateAxis, NumberAxis countAxis) {
|
||||
super(dateAxis, countAxis);
|
||||
this.controller = controller;
|
||||
//configure constant properties on axes and chart
|
||||
dateAxis.setAnimated(true);
|
||||
dateAxis.setLabel(null);
|
||||
@ -87,6 +87,7 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
setOnMouseDragged(chartDragHandler);
|
||||
|
||||
setOnMouseClicked(new MouseClickedHandler<>(this));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -95,6 +96,7 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
intervalSelector = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextMenu getChartContextMenu(MouseEvent clickEvent) throws MissingResourceException {
|
||||
if (chartContextMenu != null) {
|
||||
chartContextMenu.hide();
|
||||
@ -112,12 +114,6 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(this.controller.getEventsModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntervalSelector<? extends String> getIntervalSelector() {
|
||||
return intervalSelector;
|
||||
@ -129,14 +125,6 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
getChartChildren().add(getIntervalSelector());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
filteredEvents.zoomParametersProperty().addListener(o -> {
|
||||
clearIntervalSelector();
|
||||
controller.selectEventIDs(Collections.emptyList());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CountsIntervalSelector newIntervalSelector() {
|
||||
return new CountsIntervalSelector(this);
|
||||
@ -179,7 +167,7 @@ final class EventCountsChart extends StackedBarChart<String, Number> implements
|
||||
* Interval Selector for the counts chart, adjusts interval based on
|
||||
* rangeInfo to include final period
|
||||
*/
|
||||
static private class CountsIntervalSelector extends IntervalSelector<String> {
|
||||
final static private class CountsIntervalSelector extends IntervalSelector<String> {
|
||||
|
||||
private final EventCountsChart countsChart;
|
||||
|
||||
|
@ -113,9 +113,10 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
|
||||
return chart.getEventBundles();
|
||||
}
|
||||
|
||||
public DetailViewPane(Pane partPane, Pane contextPane, Region spacer) {
|
||||
super(partPane, contextPane, spacer);
|
||||
chart = new EventDetailsChart(dateAxis, verticalAxis, selectedNodes);
|
||||
|
||||
public DetailViewPane(TimeLineController controller, Pane partPane, Pane contextPane, Region spacer) {
|
||||
super(controller, partPane, contextPane, spacer);
|
||||
chart = new EventDetailsChart(controller, dateAxis, verticalAxis, selectedNodes);
|
||||
setChartClickHandler();
|
||||
chart.setData(dataSets);
|
||||
setCenter(chart);
|
||||
@ -211,11 +212,6 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setModel(FilteredEventsModel filteredEvents) {
|
||||
super.setModel(filteredEvents);
|
||||
}
|
||||
|
||||
private void incrementScrollValue(int factor) {
|
||||
vertScrollBar.valueProperty().set(Math.max(0, Math.min(100, vertScrollBar.getValue() + factor * (chart.getHeight() / chart.maxVScrollProperty().get()))));
|
||||
}
|
||||
|
@ -102,16 +102,19 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
|
||||
private static final int PROJECTED_LINE_Y_OFFSET = 5;
|
||||
private static final int PROJECTED_LINE_STROKE_WIDTH = 5;
|
||||
private static final int MINIMUM_EVENT_NODE_GAP = 4;
|
||||
|
||||
|
||||
private final TimeLineController controller;
|
||||
private final FilteredEventsModel filteredEvents;
|
||||
|
||||
private ContextMenu chartContextMenu;
|
||||
|
||||
|
||||
|
||||
public ContextMenu getChartContextMenu() {
|
||||
return chartContextMenu;
|
||||
}
|
||||
|
||||
private TimeLineController controller;
|
||||
|
||||
private FilteredEventsModel filteredEvents;
|
||||
|
||||
/**
|
||||
* a user positionable vertical line to help compare events
|
||||
*/
|
||||
@ -187,10 +190,21 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
|
||||
*/
|
||||
final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
|
||||
|
||||
EventDetailsChart(DateAxis dateAxis, final Axis<EventCluster> verticalAxis, ObservableList<EventBundleNodeBase<?, ?, ?>> selectedNodes) {
|
||||
EventDetailsChart(TimeLineController controller, DateAxis dateAxis, final Axis<EventCluster> verticalAxis, ObservableList<EventBundleNodeBase<?, ?, ?>> selectedNodes) {
|
||||
super(dateAxis, verticalAxis);
|
||||
this.controller = controller;
|
||||
this.filteredEvents = this.controller.getEventsModel();
|
||||
|
||||
filteredEvents.zoomParametersProperty().addListener(o -> {
|
||||
clearGuideLine();
|
||||
clearIntervalSelector();
|
||||
selectedNodes.clear();
|
||||
projectionMap.clear();
|
||||
controller.selectEventIDs(Collections.emptyList());
|
||||
});
|
||||
Tooltip.install(this, AbstractVisualizationPane.getDragTooltip());
|
||||
|
||||
|
||||
dateAxis.setAutoRanging(false);
|
||||
|
||||
verticalAxis.setVisible(false);//TODO: why doesn't this hide the vertical axis, instead we have to turn off all parts individually? -jm
|
||||
@ -210,6 +224,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
|
||||
truncateAll.addListener(layoutInvalidationListener);
|
||||
truncateWidth.addListener(layoutInvalidationListener);
|
||||
descrVisibility.addListener(layoutInvalidationListener);
|
||||
getController().getQuickHideFilters().addListener(layoutInvalidationListener);
|
||||
|
||||
//this is needed to allow non circular binding of the guideline and timerangeRect heights to the height of the chart
|
||||
//TODO: seems like a hack, can we remove? -jm
|
||||
@ -260,30 +275,6 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
|
||||
return bandByType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(this.controller.getEventsModel());
|
||||
getController().getQuickHideFilters().addListener(layoutInvalidationListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
|
||||
if (this.filteredEvents != filteredEvents) {
|
||||
filteredEvents.zoomParametersProperty().addListener(o -> {
|
||||
clearGuideLine();
|
||||
clearIntervalSelector();
|
||||
|
||||
selectedNodes.clear();
|
||||
projectionMap.clear();
|
||||
controller.selectEventIDs(Collections.emptyList());
|
||||
});
|
||||
}
|
||||
this.filteredEvents = filteredEvents;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntervalSelector<DateTime> newIntervalSelector() {
|
||||
return new DetailIntervalSelector(this);
|
||||
|
@ -1 +0,0 @@
|
||||
NavPanel.eventsTreeLabel.text=Sort By\:
|
@ -1 +1 @@
|
||||
NavPanel.eventsTreeLabel.text=\u4E0B\u8A18\u306B\u5F93\u3044\u4E26\u3079\u66FF\u3048\uFF1A
|
||||
EventsTree.Label.text=\u4e0b\u8a18\u306b\u5f93\u3044\u4e26\u3079\u66ff\u3048\uff1a
|
@ -46,9 +46,7 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
|
||||
import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter;
|
||||
import org.sleuthkit.autopsy.timeline.ui.detailview.DetailViewPane;
|
||||
@ -59,11 +57,9 @@ import org.sleuthkit.autopsy.timeline.ui.detailview.DetailViewPane;
|
||||
* out. Right clicking on a item in the tree shows a context menu to show/hide
|
||||
* it.
|
||||
*/
|
||||
public class NavPanel extends BorderPane implements TimeLineView {
|
||||
final public class EventsTree extends BorderPane {
|
||||
|
||||
private TimeLineController controller;
|
||||
|
||||
private FilteredEventsModel filteredEvents;
|
||||
private final TimeLineController controller;
|
||||
|
||||
private DetailViewPane detailViewPane;
|
||||
|
||||
@ -76,8 +72,10 @@ public class NavPanel extends BorderPane implements TimeLineView {
|
||||
@FXML
|
||||
private ComboBox<Comparator<TreeItem<EventBundle<?>>>> sortByBox;
|
||||
|
||||
public NavPanel() {
|
||||
FXMLConstructor.construct(this, "NavPanel.fxml"); // NON-NLS
|
||||
public EventsTree(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
|
||||
FXMLConstructor.construct(this, "EventsTree.fxml"); // NON-NLS
|
||||
}
|
||||
|
||||
public void setDetailViewPane(DetailViewPane detailViewPane) {
|
||||
@ -112,19 +110,8 @@ public class NavPanel extends BorderPane implements TimeLineView {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(controller.getEventsModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
this.filteredEvents = filteredEvents;
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
@NbBundle.Messages("EventsTree.Label.text=Sort By:")
|
||||
void initialize() {
|
||||
assert sortByBox != null : "fx:id=\"sortByBox\" was not injected: check your FXML file 'NavPanel.fxml'."; // NON-NLS
|
||||
|
||||
@ -137,7 +124,7 @@ public class NavPanel extends BorderPane implements TimeLineView {
|
||||
eventsTree.setCellFactory((TreeView<EventBundle<?>> p) -> new EventBundleTreeCell());
|
||||
eventsTree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||
|
||||
eventsTreeLabel.setText(NbBundle.getMessage(this.getClass(), "NavPanel.eventsTreeLabel.text"));
|
||||
eventsTreeLabel.setText(Bundle.EventsTree_Label_text());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,6 +219,5 @@ public class NavPanel extends BorderPane implements TimeLineView {
|
||||
setContextMenu(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -44,7 +44,6 @@ import org.controlsfx.control.action.ActionUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.VisualizationMode;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ResetFilters;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
@ -64,7 +63,7 @@ import static org.sleuthkit.autopsy.timeline.ui.filtering.Bundle.Timeline_ui_fil
|
||||
* This also implements {@link TimeLineView} since it dynamically updates its
|
||||
* filters based on the contents of a {@link FilteredEventsModel}
|
||||
*/
|
||||
final public class FilterSetPanel extends BorderPane implements TimeLineView {
|
||||
final public class FilterSetPanel extends BorderPane {
|
||||
|
||||
private static final Image TICK = new Image("org/sleuthkit/autopsy/timeline/images/tick.png");
|
||||
|
||||
@ -171,20 +170,25 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
|
||||
legendColumn.setCellValueFactory(param -> param.getValue().valueProperty());
|
||||
legendColumn.setCellFactory(col -> new LegendCell(this.controller));
|
||||
|
||||
}
|
||||
|
||||
public FilterSetPanel() {
|
||||
FXMLConstructor.construct(this, "FilterSetPanel.fxml"); // NON-NLS
|
||||
expansionMap.put(new TypeFilter(RootEventType.getInstance()).getDisplayName(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(TimeLineController timeLineController) {
|
||||
this.controller = timeLineController;
|
||||
Action defaultFiltersAction = new ResetFilters(controller);
|
||||
defaultButton.setOnAction(defaultFiltersAction);
|
||||
defaultButton.disableProperty().bind(defaultFiltersAction.disabledProperty());
|
||||
this.setModel(timeLineController.getEventsModel());
|
||||
|
||||
this.filteredEvents.eventTypeZoomProperty().addListener((Observable observable) -> {
|
||||
applyFilters();
|
||||
});
|
||||
this.filteredEvents.descriptionLODProperty().addListener((Observable observable1) -> {
|
||||
applyFilters();
|
||||
});
|
||||
this.filteredEvents.timeRangeProperty().addListener((Observable observable2) -> {
|
||||
applyFilters();
|
||||
});
|
||||
this.filteredEvents.filterProperty().addListener((Observable o) -> {
|
||||
refresh();
|
||||
});
|
||||
refresh();
|
||||
|
||||
hiddenDescriptionsListView.setItems(controller.getQuickHideFilters());
|
||||
hiddenDescriptionsListView.setCellFactory((ListView<DescriptionFilter> param) -> {
|
||||
@ -237,25 +241,13 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
this.filteredEvents = filteredEvents;
|
||||
this.filteredEvents.eventTypeZoomProperty().addListener((Observable observable) -> {
|
||||
applyFilters();
|
||||
});
|
||||
this.filteredEvents.descriptionLODProperty().addListener((Observable observable) -> {
|
||||
applyFilters();
|
||||
});
|
||||
this.filteredEvents.timeRangeProperty().addListener((Observable observable) -> {
|
||||
applyFilters();
|
||||
});
|
||||
this.filteredEvents.filterProperty().addListener((Observable o) -> {
|
||||
refresh();
|
||||
});
|
||||
refresh();
|
||||
public FilterSetPanel(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
this.filteredEvents = controller.getEventsModel();
|
||||
FXMLConstructor.construct(this, "FilterSetPanel.fxml"); // NON-NLS
|
||||
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
|
||||
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
|
||||
import org.sleuthkit.autopsy.timeline.filters.TextFilter;
|
||||
@ -40,18 +39,19 @@ import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
* A TreeTableCell that shows an icon and color corresponding to the represented
|
||||
* filter
|
||||
*/
|
||||
class LegendCell extends TreeTableCell<AbstractFilter, AbstractFilter> implements TimeLineView {
|
||||
final class LegendCell extends TreeTableCell<AbstractFilter, AbstractFilter> {
|
||||
|
||||
private static final Color CLEAR = Color.rgb(0, 0, 0, 0);
|
||||
|
||||
private TimeLineController controller;
|
||||
private final TimeLineController controller;
|
||||
|
||||
private FilteredEventsModel filteredEvents;
|
||||
private final FilteredEventsModel filteredEvents;
|
||||
|
||||
//We need a controller so we can listen to changes in EventTypeZoom to show/hide legends
|
||||
public LegendCell(TimeLineController controller) {
|
||||
LegendCell(TimeLineController controller) {
|
||||
setEditable(false);
|
||||
setController(controller);
|
||||
this.controller = controller;
|
||||
this.filteredEvents = this.controller.getEventsModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,15 +119,4 @@ class LegendCell extends TreeTableCell<AbstractFilter, AbstractFilter> implement
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public final void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(this.controller.getEventsModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
this.filteredEvents = filteredEvents;
|
||||
}
|
||||
}
|
||||
|
@ -18,19 +18,20 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline.zooming;
|
||||
|
||||
import java.net.URL;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.util.StringConverter;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||
import org.sleuthkit.autopsy.timeline.TimeLineView;
|
||||
import org.sleuthkit.autopsy.timeline.VisualizationMode;
|
||||
import org.sleuthkit.autopsy.timeline.actions.Back;
|
||||
import org.sleuthkit.autopsy.timeline.actions.Forward;
|
||||
@ -44,13 +45,7 @@ import org.sleuthkit.autopsy.timeline.utils.RangeDivisionInfo;
|
||||
* has sliders to provide context/control over three axes of zooming (timescale,
|
||||
* event hierarchy, and description detail).
|
||||
*/
|
||||
public class ZoomSettingsPane extends TitledPane implements TimeLineView {
|
||||
|
||||
@FXML
|
||||
private ResourceBundle resources;
|
||||
|
||||
@FXML
|
||||
private URL location;
|
||||
public class ZoomSettingsPane extends TitledPane {
|
||||
|
||||
@FXML
|
||||
private Button backButton;
|
||||
@ -105,35 +100,6 @@ public class ZoomSettingsPane extends TitledPane implements TimeLineView {
|
||||
timeUnitLabel.setText(NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.timeUnitLabel.text"));
|
||||
zoomLabel.setText(NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.zoomLabel.text"));
|
||||
historyLabel.setText(NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.historyLabel.text"));
|
||||
}
|
||||
|
||||
public ZoomSettingsPane() {
|
||||
FXMLConstructor.construct(this, "ZoomSettingsPane.fxml"); // NON-NLS
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void setController(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
setModel(controller.getEventsModel());
|
||||
descrLODSlider.disableProperty().bind(controller.viewModeProperty().isEqualTo(VisualizationMode.COUNTS));
|
||||
Back back = new Back(controller);
|
||||
backButton.disableProperty().bind(back.disabledProperty());
|
||||
backButton.setOnAction(back);
|
||||
backButton.setTooltip(new Tooltip(
|
||||
NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.backButton.toolTip.text",
|
||||
back.getAccelerator().getName())));
|
||||
Forward forward = new Forward(controller);
|
||||
forwardButton.disableProperty().bind(forward.disabledProperty());
|
||||
forwardButton.setOnAction(forward);
|
||||
forwardButton.setTooltip(new Tooltip(
|
||||
NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.forwardButton.toolTip.text",
|
||||
forward.getAccelerator().getName())));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(FilteredEventsModel filteredEvents) {
|
||||
this.filteredEvents = filteredEvents;
|
||||
|
||||
initializeSlider(timeUnitSlider,
|
||||
() -> {
|
||||
@ -151,18 +117,14 @@ public class ZoomSettingsPane extends TitledPane implements TimeLineView {
|
||||
|
||||
timeUnitSlider.setValue(TimeUnits.fromChronoUnit(chronoUnit).ordinal() - 1);
|
||||
});
|
||||
|
||||
initializeSlider(descrLODSlider,
|
||||
() -> {
|
||||
DescriptionLoD newLOD = DescriptionLoD.values()[Math.round(descrLODSlider.valueProperty().floatValue())];
|
||||
if (controller.pushDescrLOD(newLOD) == false) {
|
||||
descrLODSlider.setValue(new DescrLODConverter().fromString(filteredEvents.getDescriptionLOD().toString()));
|
||||
}
|
||||
}, this.filteredEvents.descriptionLODProperty(),
|
||||
() -> {
|
||||
descrLODSlider.setValue(this.filteredEvents.descriptionLODProperty().get().ordinal());
|
||||
});
|
||||
|
||||
initializeSlider(descrLODSlider, () -> {
|
||||
DescriptionLoD newLOD = DescriptionLoD.values()[Math.round(descrLODSlider.valueProperty().floatValue())];
|
||||
if (controller.pushDescrLOD(newLOD) == false) {
|
||||
descrLODSlider.setValue(new DescrLODConverter().fromString(controller.getEventsModel().getDescriptionLOD().toString()));
|
||||
}
|
||||
}, this.filteredEvents.descriptionLODProperty(), () -> {
|
||||
descrLODSlider.setValue(this.filteredEvents.descriptionLODProperty().get().ordinal());
|
||||
});
|
||||
initializeSlider(typeZoomSlider,
|
||||
() -> {
|
||||
EventTypeZoomLevel newZoomLevel = EventTypeZoomLevel.values()[Math.round(typeZoomSlider.valueProperty().floatValue())];
|
||||
@ -172,6 +134,26 @@ public class ZoomSettingsPane extends TitledPane implements TimeLineView {
|
||||
() -> {
|
||||
typeZoomSlider.setValue(this.filteredEvents.eventTypeZoomProperty().get().ordinal());
|
||||
});
|
||||
descrLODSlider.disableProperty().bind(controller.viewModeProperty().isEqualTo(VisualizationMode.COUNTS));
|
||||
Back back = new Back(controller);
|
||||
backButton.disableProperty().bind(back.disabledProperty());
|
||||
backButton.setOnAction(back);
|
||||
backButton.setTooltip(new Tooltip(
|
||||
NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.backButton.toolTip.text",
|
||||
back.getAccelerator().getName())));
|
||||
Forward forward = new Forward(controller);
|
||||
forwardButton.disableProperty().bind(forward.disabledProperty());
|
||||
forwardButton.setOnAction(forward);
|
||||
forwardButton.setTooltip(new Tooltip(
|
||||
NbBundle.getMessage(this.getClass(), "ZoomSettingsPane.forwardButton.toolTip.text",
|
||||
forward.getAccelerator().getName())));
|
||||
|
||||
}
|
||||
|
||||
public ZoomSettingsPane(TimeLineController controller) {
|
||||
this.controller = controller;
|
||||
this.filteredEvents = controller.getEventsModel();
|
||||
FXMLConstructor.construct(this, "ZoomSettingsPane.fxml"); // NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user