19 package org.sleuthkit.autopsy.timeline;
 
   21 import java.beans.PropertyVetoException;
 
   22 import java.util.Collections;
 
   23 import java.util.List;
 
   24 import java.util.logging.Level;
 
   25 import javafx.application.Platform;
 
   26 import javafx.beans.InvalidationListener;
 
   27 import javafx.beans.Observable;
 
   28 import javafx.scene.Scene;
 
   29 import javafx.scene.control.SplitPane;
 
   30 import javafx.scene.control.Tab;
 
   31 import javafx.scene.control.TabPane;
 
   32 import javafx.scene.image.ImageView;
 
   33 import javafx.scene.input.KeyCode;
 
   34 import javafx.scene.input.KeyCodeCombination;
 
   35 import javafx.scene.input.KeyEvent;
 
   36 import javafx.scene.layout.Priority;
 
   37 import javafx.scene.layout.VBox;
 
   38 import javax.swing.JComponent;
 
   39 import javax.swing.SwingUtilities;
 
   40 import org.controlsfx.control.Notifications;
 
   41 import org.joda.time.Interval;
 
   42 import org.joda.time.format.DateTimeFormatter;
 
   43 import org.openide.explorer.ExplorerManager;
 
   44 import org.openide.explorer.ExplorerUtils;
 
   45 import org.openide.nodes.AbstractNode;
 
   46 import org.openide.nodes.Children;
 
   47 import org.openide.nodes.Node;
 
   48 import org.openide.util.NbBundle;
 
   49 import org.openide.windows.Mode;
 
   50 import org.openide.windows.TopComponent;
 
   51 import static org.openide.windows.TopComponent.PROP_UNDOCKING_DISABLED;
 
   52 import org.openide.windows.WindowManager;
 
   74 @TopComponent.Description(
 
   75         preferredID = 
"TimeLineTopComponent",
 
   77         persistenceType = TopComponent.PERSISTENCE_NEVER)
 
   78 @TopComponent.Registration(mode = 
"timeline", openAtStartup = 
false)
 
   90     private final ExplorerManager 
em = new ExplorerManager();
 
   98     @NbBundle.Messages({
"TimelineTopComponent.selectedEventListener.errorMsg=There was a problem getting the content for the selected event."})
 
  101         public void invalidated(Observable observable) {
 
  111                         for (
int i = 0; i < selectedEventIDs.size(); i++) {
 
  114                         Children children = 
new Children.Array();
 
  115                         children.add(childArray);
 
  117                         SwingUtilities.invokeLater(() -> {
 
  119                             em.setRootContext(
new AbstractNode(children));
 
  122                                 em.setSelectedNodes(childArray);
 
  123                             } 
catch (PropertyVetoException ex) {
 
  125                                 LOGGER.log(Level.SEVERE, 
"Selecting the event node was vetoed.", ex); 
 
  128                             if (childArray.length == 1) {
 
  134                     } 
catch (IllegalStateException ex) {
 
  136                         LOGGER.log(Level.SEVERE, 
"There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); 
 
  138                         LOGGER.log(Level.SEVERE, 
"Failed to lookup Sleuthkit object backing a SingleEvent.", ex); 
 
  139                         Platform.runLater(() -> {
 
  140                             Notifications.create()
 
  142                                     .text(Bundle.TimelineTopComponent_selectedEventListener_errorMsg())
 
  152                     SwingUtilities.invokeLater(() -> {
 
  171                 SwingUtilities.invokeLater(() -> {
 
  184                 SwingUtilities.invokeLater(() -> {
 
  200         associateLookup(ExplorerUtils.createLookup(
em, getActionMap()));
 
  203         setIcon(WindowManager.getDefault().getMainWindow().getIconImage()); 
 
  220         Platform.runLater(this::initFXComponents);
 
  235         "TimeLineTopComponent.eventsTab.name=Events",
 
  236         "TimeLineTopComponent.filterTab.name=Filters"})
 
  237     @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
 
  238     void initFXComponents() {
 
  240         final TimeZonePanel timeZonePanel = 
new TimeZonePanel();
 
  241         VBox.setVgrow(timeZonePanel, Priority.SOMETIMES);
 
  242         HistoryToolBar historyToolBar = 
new HistoryToolBar(
controller);
 
  243         final ZoomSettingsPane zoomSettingsPane = 
new ZoomSettingsPane(
controller);
 
  246         final Tab filterTab = 
new Tab(Bundle.TimeLineTopComponent_filterTab_name(), 
new FilterSetPanel(
controller));
 
  247         filterTab.setClosable(
false);
 
  248         filterTab.setGraphic(
new ImageView(
"org/sleuthkit/autopsy/timeline/images/funnel.png")); 
 
  251         final EventsTree eventsTree = 
new EventsTree(
controller);
 
  252         final Tab eventsTreeTab = 
new Tab(Bundle.TimeLineTopComponent_eventsTab_name(), eventsTree);
 
  253         eventsTreeTab.setClosable(
false);
 
  254         eventsTreeTab.setGraphic(
new ImageView(
"org/sleuthkit/autopsy/timeline/images/timeline_marker.png")); 
 
  257         final TabPane leftTabPane = 
new TabPane(filterTab, eventsTreeTab);
 
  258         VBox.setVgrow(leftTabPane, Priority.ALWAYS);
 
  262                 leftTabPane.getSelectionModel().select(filterTab);
 
  267         final VBox leftVBox = 
new VBox(5, timeZonePanel, historyToolBar, zoomSettingsPane, leftTabPane);
 
  268         SplitPane.setResizableWithParent(leftVBox, Boolean.FALSE);
 
  270         final ViewFrame viewFrame = 
new ViewFrame(
controller, eventsTree);
 
  271         final SplitPane mainSplitPane = 
new SplitPane(leftVBox, viewFrame);
 
  272         mainSplitPane.setDividerPositions(0);
 
  274         final Scene scene = 
new Scene(mainSplitPane);
 
  275         scene.addEventFilter(KeyEvent.KEY_PRESSED, keyEvent -> {
 
  276             if (new KeyCodeCombination(KeyCode.LEFT, KeyCodeCombination.ALT_DOWN).match(keyEvent)) {
 
  277                 new Back(controller).handle(null);
 
  278             } 
else if (
new KeyCodeCombination(KeyCode.BACK_SPACE).match(keyEvent)) {
 
  280             } 
else if (
new KeyCodeCombination(KeyCode.RIGHT, KeyCodeCombination.ALT_DOWN).match(keyEvent)) {
 
  282             } 
else if (
new KeyCodeCombination(KeyCode.BACK_SPACE, KeyCodeCombination.SHIFT_DOWN).match(keyEvent)) {
 
  294         return Collections.emptyList();
 
  305         jFXstatusPanel = 
new javafx.embed.swing.JFXPanel();
 
  306         splitYPane = 
new javax.swing.JSplitPane();
 
  307         jFXViewPanel = 
new javafx.embed.swing.JFXPanel();
 
  308         horizontalSplitPane = 
new javax.swing.JSplitPane();
 
  309         leftFillerPanel = 
new javax.swing.JPanel();
 
  310         rightfillerPanel = 
new javax.swing.JPanel();
 
  312         jFXstatusPanel.setPreferredSize(
new java.awt.Dimension(100, 16));
 
  314         splitYPane.setDividerLocation(420);
 
  315         splitYPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
 
  316         splitYPane.setResizeWeight(0.9);
 
  317         splitYPane.setPreferredSize(
new java.awt.Dimension(1024, 400));
 
  318         splitYPane.setLeftComponent(jFXViewPanel);
 
  320         horizontalSplitPane.setDividerLocation(600);
 
  321         horizontalSplitPane.setResizeWeight(0.5);
 
  322         horizontalSplitPane.setPreferredSize(
new java.awt.Dimension(1200, 300));
 
  323         horizontalSplitPane.setRequestFocusEnabled(
false);
 
  325         javax.swing.GroupLayout leftFillerPanelLayout = 
new javax.swing.GroupLayout(leftFillerPanel);
 
  326         leftFillerPanel.setLayout(leftFillerPanelLayout);
 
  327         leftFillerPanelLayout.setHorizontalGroup(
 
  328             leftFillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  329             .addGap(0, 599, Short.MAX_VALUE)
 
  331         leftFillerPanelLayout.setVerticalGroup(
 
  332             leftFillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  333             .addGap(0, 54, Short.MAX_VALUE)
 
  336         horizontalSplitPane.setLeftComponent(leftFillerPanel);
 
  338         javax.swing.GroupLayout rightfillerPanelLayout = 
new javax.swing.GroupLayout(rightfillerPanel);
 
  339         rightfillerPanel.setLayout(rightfillerPanelLayout);
 
  340         rightfillerPanelLayout.setHorizontalGroup(
 
  341             rightfillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  342             .addGap(0, 364, Short.MAX_VALUE)
 
  344         rightfillerPanelLayout.setVerticalGroup(
 
  345             rightfillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  346             .addGap(0, 54, Short.MAX_VALUE)
 
  349         horizontalSplitPane.setRightComponent(rightfillerPanel);
 
  351         splitYPane.setRightComponent(horizontalSplitPane);
 
  353         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  354         this.setLayout(layout);
 
  355         layout.setHorizontalGroup(
 
  356             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  357             .addComponent(splitYPane, javax.swing.GroupLayout.DEFAULT_SIZE, 972, Short.MAX_VALUE)
 
  358             .addComponent(jFXstatusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  360         layout.setVerticalGroup(
 
  361             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  362             .addGroup(layout.createSequentialGroup()
 
  363                 .addComponent(splitYPane, javax.swing.GroupLayout.DEFAULT_SIZE, 482, Short.MAX_VALUE)
 
  365                 .addComponent(jFXstatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  380         WindowManager.getDefault().setTopComponentFloating(
this, 
true);
 
  381         putClientProperty(PROP_UNDOCKING_DISABLED, 
true);
 
  396         "# {0} - start of date range",
 
  397         "# {1} - end of date range",
 
  398         "TimeLineResultView.startDateToEndDate.text={0} to {1}"})
 
  400         Interval selectedTimeRange = controller.getSelectedTimeRange();
 
  401         if (selectedTimeRange == null) {
 
  405             String start = selectedTimeRange.getStart()
 
  407                     .toString(zonedFormatter);
 
  408             String end = selectedTimeRange.getEnd()
 
  410                     .toString(zonedFormatter);
 
  411             return Bundle.TimeLineResultView_startDateToEndDate_text(start, end);
 
TimeLineTopComponent(TimeLineController controller)
 
final InvalidationListener selectedEventsListener
 
static final KeyStroke BOOKMARK_SHORTCUT
 
FilteredEventsModel getEventsModel()
 
static EventNode createEventNode(final Long eventID, FilteredEventsModel eventsModel)
 
void setNode(Node selectedNode)
 
synchronized ViewMode getViewMode()
 
static ReadOnlyObjectProperty< TimeZone > getTimeZone()
 
DataResultPanel dataResultPanel
 
String getResultViewerSummaryString()
 
static final Logger LOGGER
 
static DataResultPanel createInstanceUninitialized(String title, String pathText, Node givenNode, int totalMatches, DataContent dataContent)
 
final TimeLineController controller
 
javafx.embed.swing.JFXPanel jFXstatusPanel
 
void setNode(Node selectedNode)
 
final DataContentPanel contentViewerPanel
 
javax.swing.JSplitPane splitYPane
 
List< Mode > availableModes(List< Mode > modes)
 
static DataContentPanel createInstance()
 
javafx.embed.swing.JFXPanel jFXViewPanel
 
synchronized ObservableList< Long > getSelectedEventIDs()
 
static DateTimeZone getJodaTimeZone()
 
void setPath(String pathText)
 
javax.swing.JSplitPane horizontalSplitPane
 
synchronized ReadOnlyObjectProperty< ViewMode > viewModeProperty()
 
ExplorerManager getExplorerManager()
 
synchronized static Logger getLogger(String name)
 
static DateTimeFormatter getZonedFormatter()
 
javax.swing.JPanel rightfillerPanel
 
javax.swing.JPanel leftFillerPanel