From 0096dc317060f3751c6971be1faba1012df07482 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Fri, 23 Mar 2018 14:22:57 +0100 Subject: [PATCH 1/5] fix tagging in timeline window --- .../communications/MessageBrowser.java | 77 ++++++++++--------- .../communications/MessageDataContent.java | 7 +- .../timeline/DataContentExplorerPanel.java | 72 +++++++++++++++++ .../timeline/ModifiableProxyLookup.java | 46 +++++++++++ .../timeline/TimeLineTopComponent.java | 73 +++++++++++++++--- 5 files changed, 227 insertions(+), 48 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java create mode 100644 Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java index 94d96c4456..1258c2d525 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java @@ -50,9 +50,46 @@ public final class MessageBrowser extends JPanel implements ExplorerManager.Prov private final DataResultPanel messagesResultPanel; /* lookup that will be exposed through the (Global Actions Context) */ private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup(); - /* Listener that keeps the proxyLookup in sync with the focused area of the - * UI. */ - private final FocusPropertyListener focusPropertyListener = new FocusPropertyListener(); + + /** + * Listener that keeps the proxyLookup in sync with the focused area of the + * UI. + * + * Since the embedded MessageContentViewer (attachments panel) is not in its + * own TopComponenet, its selection does not get proxied into the Global + * Actions Context (GAC), and many of the available actions don't work on + * it. Further, we can't put the selection from both the Messages table and + * the Attachments table in the GAC because they could both include + * AbstractFiles, muddling the selection seen by the actions. Instead, + * depending on where the focus is in the window, we want to put different + * Content in the Global Actions Context to be picked up by, e.g., the + * tagging actions. The best way I could figure to do this was to listen to + * all focus events and swap out what is in the lookup appropriately. An + * alternative to this would be to investigate using the ContextAwareAction + * interface. + * + * @see org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a similar + * situation and a similar solution. + */ + private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() { + + @Override + public void propertyChange(final PropertyChangeEvent focusEvent) { + if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) { + final Component newFocusOwner = (Component) focusEvent.getNewValue(); + + if (newFocusOwner != null) { + if (isDescendingFrom(newFocusOwner, messageDataContent)) { + //if the focus owner is within the MessageContentViewer ( the attachments table) + proxyLookup.setNewLookups(createLookup(messageDataContent.getExplorerManager(), getActionMap())); + } else if (isDescendingFrom(newFocusOwner, messagesResultPanel)) { + //... or if it is within the Messages table. + proxyLookup.setNewLookups(createLookup(gacExplorerManager, getActionMap())); + } + } + } + } + }; /** * Constructs the right hand side of the Communications Visualization Tool @@ -178,38 +215,4 @@ public final class MessageBrowser extends JPanel implements ExplorerManager.Prov private javax.swing.JSplitPane splitPane; // End of variables declaration//GEN-END:variables - /** - * Since the embedded MessageContentViewer (attachments panel) is not in its - * own TopComponenet, its selection does not get proxied into the Global - * Actions Context (GAC), and many of the available actions don't work on - * it. Further, we can't put the selection from both the Messages table and - * the Attachments table in the GAC because they could include have - * AbstractFiles, muddling the selection seen by the actions. Instead, - * depending on where the focus is in the window, we want to put different - * Content in the Global Actions Context to be picked up by, e.g., the - * tagging actions. The best way I could figure to do this was to listen to - * all focus events and swap out what is in the lookup appropriately. An - * alternative to this would be to investigate using the ContextAwareAction - * interface. - */ - private class FocusPropertyListener implements PropertyChangeListener { - - @Override - public void propertyChange(final PropertyChangeEvent focusEvent) { - - if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) { - final Component newFocusOwner = (Component) focusEvent.getNewValue(); - - if (newFocusOwner != null) { - if (isDescendingFrom(newFocusOwner, messageDataContent)) { - //if the focus owner is within the MessageContentViewer ( the attachments table) - proxyLookup.setNewLookups(createLookup(messageDataContent.getExplorerManager(), getActionMap())); - } else if (isDescendingFrom(newFocusOwner, messagesResultPanel)) { - //... or if it is within the Messages table. - proxyLookup.setNewLookups(createLookup(gacExplorerManager, getActionMap())); - } - } - } - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageDataContent.java b/Core/src/org/sleuthkit/autopsy/communications/MessageDataContent.java index ad7229157d..33df9bd3d9 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageDataContent.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageDataContent.java @@ -25,7 +25,12 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; /** * Extends MessageContentViewer so that it implements DataContent and can be set - * as the only ContentViewer for a DataResultPanel + * as the only ContentViewer for a DataResultPanel. In addition it provides an + * ExplorerManager. + * + * @see org.sleuthkit.autopsy.timeline.DataContentExplorerPanel for another + * solution to a very similar problem. + * */ final class MessageDataContent extends MessageContentViewer implements DataContent, ExplorerManager.Provider { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java b/Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java new file mode 100644 index 0000000000..d87cae18c0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java @@ -0,0 +1,72 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +import java.awt.BorderLayout; +import java.beans.PropertyChangeEvent; +import javax.swing.JPanel; +import org.openide.explorer.ExplorerManager; +import org.openide.nodes.Node; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; +import org.sleuthkit.autopsy.corecomponents.DataContentPanel; + +/** + * Panel that wraps a DataContentPanel and implements ExplorerManager.Provider. + * This allows the explorer manager found by the DataContentPanel to be + * controlled easily. + * + * @see org.sleuthkit.autopsy.communications.MessageDataContent for another + * solution to a very similar problem. + */ +final class DataContentExplorerPanel extends JPanel implements ExplorerManager.Provider, DataContent { + + private final ExplorerManager explorerManager = new ExplorerManager(); + private final DataContentPanel wrapped; + + DataContentExplorerPanel() { + super(new BorderLayout()); + wrapped = DataContentPanel.createInstance(); + } + + @Override + public ExplorerManager getExplorerManager() { + return explorerManager; + } + + @Override + public void setNode(Node selectedNode) { + wrapped.setNode(selectedNode); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + wrapped.propertyChange(evt); + } + + /** + * Initialize the contents of this panel for use. Specifically add the + * wrapped DataContentPanel to the AWT/Swing containment hierarchy. This + * will trigger the addNotify() method of the embeded Message + * MessageContentViewer causing it to look for a ExplorerManager; it should + * find the one provided by this DataContentExplorerPanel. + */ + void initialize() { + add(wrapped, BorderLayout.CENTER); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java b/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java new file mode 100644 index 0000000000..bbeea62e1a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java @@ -0,0 +1,46 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit 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; + +import org.openide.util.Lookup; +import org.openide.util.lookup.ProxyLookup; + +/** + * Extension of ProxyLookup that exposes the ability to change the Lookups + * delegated to. + * + */ +final class ModifiableProxyLookup extends ProxyLookup { + + ModifiableProxyLookup(final Lookup... lookups) { + super(lookups); + } + + /** + * Set the Lookups delegated to by this lookup. + * + * @param lookups The new Lookups to delegate to. + */ + void setNewLookups(final Lookup... lookups) { + /* + * default + */ + setLookups(lookups); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index 2b0bf5d383..920e3c8fa5 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -18,6 +18,10 @@ */ package org.sleuthkit.autopsy.timeline; +import java.awt.Component; +import java.awt.KeyboardFocusManager; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.util.List; import java.util.logging.Level; @@ -37,11 +41,12 @@ import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javax.swing.JComponent; import javax.swing.SwingUtilities; +import static javax.swing.SwingUtilities.isDescendingFrom; import org.controlsfx.control.Notifications; import org.joda.time.Interval; import org.joda.time.format.DateTimeFormatter; import org.openide.explorer.ExplorerManager; -import org.openide.explorer.ExplorerUtils; +import static org.openide.explorer.ExplorerUtils.createLookup; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -52,7 +57,6 @@ import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.actions.AddBookmarkTagAction; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.corecomponents.DataContentPanel; import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.coreutils.Logger; @@ -84,16 +88,60 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer private static final Logger LOGGER = Logger.getLogger(TimeLineTopComponent.class.getName()); @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private final DataContentPanel contentViewerPanel; + private final DataContentExplorerPanel contentViewerPanel; @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private DataResultPanel dataResultPanel; + private final DataResultPanel dataResultPanel; @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private final ExplorerManager em = new ExplorerManager(); + private final ExplorerManager explorerManager = new ExplorerManager(); private final TimeLineController controller; + /** Lookup that will be exposed through the (Global Actions Context) */ + private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup(); + + /** + * Listener that keeps the proxyLookup in sync with the focused area of the + * UI. + * + * Since the embedded MessageContentViewer (attachments panel) inside the + * DataContentPanel is not in its own TopComponenet, its selection does not + * get proxied into the Global Actions Context (GAC) automatically, and many + * of the available actions don't work on it. Further, we can't put the + * selection from both the Result table and the Attachments table in the GAC + * because they could bouth include AbstractFiles, muddling the selection + * seen by the actions. Instead, depending on where the focus is in the + * window, we want to put different Content in the Global Actions Context to + * be picked up by, e.g., the tagging actions. The best way I could figure + * to do this was to listen to all focus events and swap out what is in the + * lookup appropriately. An alternative to this would be to investigate + * using the ContextAwareAction interface. + * + * @see org.sleuthkit.autopsy.communications.MessageBrowser for a similar + * situation and a similar solution. + */ + private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() { + + @Override + public void propertyChange(final PropertyChangeEvent focusEvent) { + + if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) { + final Component newFocusOwner = (Component) focusEvent.getNewValue(); + + if (newFocusOwner != null) { + if (isDescendingFrom(newFocusOwner, contentViewerPanel)) { + //if the focus owner is within the MessageContentViewer (the attachments table) + proxyLookup.setNewLookups(createLookup(contentViewerPanel.getExplorerManager(), getActionMap())); + } else if (isDescendingFrom(newFocusOwner, TimeLineTopComponent.this)) { + //... or if it is within the Results table. + proxyLookup.setNewLookups(createLookup(explorerManager, getActionMap())); + } + } + } + } + }; + /** * Listener that drives the result viewer or content viewer (depending on * view mode) according to the controller's selected event IDs @@ -118,10 +166,10 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer SwingUtilities.invokeLater(() -> { //set generic container node as root context - em.setRootContext(new AbstractNode(children)); + explorerManager.setRootContext(new AbstractNode(children)); try { //set selected nodes for actions - em.setSelectedNodes(childArray); + explorerManager.setSelectedNodes(childArray); } catch (PropertyVetoException ex) { //I don't know why this would ever happen. LOGGER.log(Level.SEVERE, "Selecting the event node was vetoed.", ex); // NON-NLS @@ -197,7 +245,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer */ public TimeLineTopComponent(TimeLineController controller) { initComponents(); - associateLookup(ExplorerUtils.createLookup(em, getActionMap())); + associateLookup(proxyLookup); setName(NbBundle.getMessage(TimeLineTopComponent.class, "CTL_TimeLineTopComponent")); getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(AddBookmarkTagAction.BOOKMARK_SHORTCUT, "addBookmarkTag"); //NON-NLS @@ -206,7 +254,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer this.controller = controller; //create linked result and content views - contentViewerPanel = DataContentPanel.createInstance(); + contentViewerPanel = new DataContentExplorerPanel(); dataResultPanel = DataResultPanel.createInstanceUninitialized("", "", Node.EMPTY, 0, contentViewerPanel); //add them to bottom splitpane @@ -214,6 +262,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer horizontalSplitPane.setRightComponent(contentViewerPanel); dataResultPanel.open(); //get the explorermanager + contentViewerPanel.initialize(); Platform.runLater(this::initFXComponents); @@ -224,6 +273,10 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer //Listen to ViewMode and adjust GUI componenets as needed. controller.viewModeProperty().addListener(viewMode -> syncViewMode()); syncViewMode(); + + //add listener that maintains correct selection in the Global Actions Context + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .addPropertyChangeListener("focusOwner", focusPropertyListener); } /** @@ -387,7 +440,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer @Override public ExplorerManager getExplorerManager() { - return em; + return explorerManager; } /** From 94aae4b04f07f7cf8e3e30c24df5d7d89ed18589 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Fri, 23 Mar 2018 16:28:44 +0100 Subject: [PATCH 2/5] fix codacy warnings and improve comments --- .../communications/MessageBrowser.java | 67 +++++++++------- .../timeline/TimeLineTopComponent.java | 78 ++++++++++--------- 2 files changed, 80 insertions(+), 65 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java index 1258c2d525..da3416f003 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java @@ -51,42 +51,45 @@ public final class MessageBrowser extends JPanel implements ExplorerManager.Prov /* lookup that will be exposed through the (Global Actions Context) */ private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup(); - /** - * Listener that keeps the proxyLookup in sync with the focused area of the - * UI. - * - * Since the embedded MessageContentViewer (attachments panel) is not in its - * own TopComponenet, its selection does not get proxied into the Global - * Actions Context (GAC), and many of the available actions don't work on - * it. Further, we can't put the selection from both the Messages table and - * the Attachments table in the GAC because they could both include - * AbstractFiles, muddling the selection seen by the actions. Instead, - * depending on where the focus is in the window, we want to put different - * Content in the Global Actions Context to be picked up by, e.g., the - * tagging actions. The best way I could figure to do this was to listen to - * all focus events and swap out what is in the lookup appropriately. An - * alternative to this would be to investigate using the ContextAwareAction - * interface. - * - * @see org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a similar - * situation and a similar solution. - */ private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() { - + /** + * Listener that keeps the proxyLookup in sync with the focused area of + * the UI. + * + * Since the embedded MessageContentViewer (attachments panel) is not in + * its own TopComponenet, its selection does not get proxied into the + * Global Actions Context (GAC), and many of the available actions don't + * work on it. Further, we can't put the selection from both the + * Messages table and the Attachments table in the GAC because they + * could both include AbstractFiles, muddling the selection seen by the + * actions. Instead, depending on where the focus is in the window, we + * want to put different Content in the Global Actions Context to be + * picked up by, e.g., the tagging actions. The best way I could figure + * to do this was to listen to all focus events and swap out what is in + * the lookup appropriately. An alternative to this would be to + * investigate using the ContextAwareAction interface. + * + * @see org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a + * similar situation and a similar solution. + * + * @param focusEvent The focus change event. + */ @Override public void propertyChange(final PropertyChangeEvent focusEvent) { if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) { final Component newFocusOwner = (Component) focusEvent.getNewValue(); - if (newFocusOwner != null) { - if (isDescendingFrom(newFocusOwner, messageDataContent)) { - //if the focus owner is within the MessageContentViewer ( the attachments table) - proxyLookup.setNewLookups(createLookup(messageDataContent.getExplorerManager(), getActionMap())); - } else if (isDescendingFrom(newFocusOwner, messagesResultPanel)) { - //... or if it is within the Messages table. - proxyLookup.setNewLookups(createLookup(gacExplorerManager, getActionMap())); - } + if (newFocusOwner == null) { + return; } + if (isDescendingFrom(newFocusOwner, messageDataContent)) { + //if the focus owner is within the MessageContentViewer ( the attachments table) + proxyLookup.setNewLookups(createLookup(messageDataContent.getExplorerManager(), getActionMap())); + } else if (isDescendingFrom(newFocusOwner, messagesResultPanel)) { + //... or if it is within the Messages table. + proxyLookup.setNewLookups(createLookup(gacExplorerManager, getActionMap())); + } + } } }; @@ -120,6 +123,12 @@ public final class MessageBrowser extends JPanel implements ExplorerManager.Prov .addPropertyChangeListener("focusOwner", focusPropertyListener); this.tableEM.addPropertyChangeListener(new PropertyChangeListener() { + /** + * Listener that pushes selections in the tableEM (the Accounts + * table) into the Messages table. + * + * @param pce The ExplorerManager event. + */ @Override public void propertyChange(PropertyChangeEvent pce) { if (pce.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index 920e3c8fa5..ccde0aaa37 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -101,53 +101,59 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer /** Lookup that will be exposed through the (Global Actions Context) */ private final ModifiableProxyLookup proxyLookup = new ModifiableProxyLookup(); - /** - * Listener that keeps the proxyLookup in sync with the focused area of the - * UI. - * - * Since the embedded MessageContentViewer (attachments panel) inside the - * DataContentPanel is not in its own TopComponenet, its selection does not - * get proxied into the Global Actions Context (GAC) automatically, and many - * of the available actions don't work on it. Further, we can't put the - * selection from both the Result table and the Attachments table in the GAC - * because they could bouth include AbstractFiles, muddling the selection - * seen by the actions. Instead, depending on where the focus is in the - * window, we want to put different Content in the Global Actions Context to - * be picked up by, e.g., the tagging actions. The best way I could figure - * to do this was to listen to all focus events and swap out what is in the - * lookup appropriately. An alternative to this would be to investigate - * using the ContextAwareAction interface. - * - * @see org.sleuthkit.autopsy.communications.MessageBrowser for a similar - * situation and a similar solution. - */ private final PropertyChangeListener focusPropertyListener = new PropertyChangeListener() { - + /** + * Listener that keeps the proxyLookup in sync with the focused area of + * the UI. + * + * Since the embedded MessageContentViewer (attachments panel) inside + * the DataContentPanel is not in its own TopComponenet, its selection + * does not get proxied into the Global Actions Context (GAC) + * automatically, and many of the available actions don't work on it. + * Further, we can't put the selection from both the Result table and + * the Attachments table in the GAC because they could bouth include + * AbstractFiles, muddling the selection seen by the actions. Instead, + * depending on where the focus is in the window, we want to put + * different Content in the Global Actions Context to be picked up by, + * e.g., the tagging actions. The best way I could figure to do this was + * to listen to all focus events and swap out what is in the lookup + * appropriately. An alternative to this would be to investigate using + * the ContextAwareAction interface. + * + * @see org.sleuthkit.autopsy.communications.MessageBrowser for a + * similar situation and a similar solution. + * + * @param focusEvent The focus change event. + */ @Override public void propertyChange(final PropertyChangeEvent focusEvent) { - if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) { final Component newFocusOwner = (Component) focusEvent.getNewValue(); - if (newFocusOwner != null) { - if (isDescendingFrom(newFocusOwner, contentViewerPanel)) { - //if the focus owner is within the MessageContentViewer (the attachments table) - proxyLookup.setNewLookups(createLookup(contentViewerPanel.getExplorerManager(), getActionMap())); - } else if (isDescendingFrom(newFocusOwner, TimeLineTopComponent.this)) { - //... or if it is within the Results table. - proxyLookup.setNewLookups(createLookup(explorerManager, getActionMap())); - } + if (newFocusOwner == null) { + return; + } + if (isDescendingFrom(newFocusOwner, contentViewerPanel)) { + //if the focus owner is within the MessageContentViewer (the attachments table) + proxyLookup.setNewLookups(createLookup(contentViewerPanel.getExplorerManager(), getActionMap())); + } else if (isDescendingFrom(newFocusOwner, TimeLineTopComponent.this)) { + //... or if it is within the Results table. + proxyLookup.setNewLookups(createLookup(explorerManager, getActionMap())); + } } } }; - /** - * Listener that drives the result viewer or content viewer (depending on - * view mode) according to the controller's selected event IDs - */ @NbBundle.Messages({"TimelineTopComponent.selectedEventListener.errorMsg=There was a problem getting the content for the selected event."}) private final InvalidationListener selectedEventsListener = new InvalidationListener() { + /** + * Listener that drives the result viewer or content viewer (depending + * on view mode) according to the controller's selected event IDs + * + * @param observable Observable that was invalidated. Usually + * irrelevant. + */ @Override public void invalidated(Observable observable) { List selectedEventIDs = controller.getSelectedEventIDs(); @@ -220,7 +226,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer */ SwingUtilities.invokeLater(() -> { splitYPane.remove(contentViewerPanel); - if ((horizontalSplitPane.getParent() == splitYPane) == false) { + if (horizontalSplitPane.getParent() != splitYPane) { splitYPane.setBottomComponent(horizontalSplitPane); horizontalSplitPane.setRightComponent(contentViewerPanel); } @@ -308,7 +314,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer final TabPane leftTabPane = new TabPane(filterTab, eventsTreeTab); VBox.setVgrow(leftTabPane, Priority.ALWAYS); controller.viewModeProperty().addListener(viewMode -> { - if (controller.getViewMode().equals(ViewMode.DETAIL) == false) { + if (controller.getViewMode() != ViewMode.DETAIL) { //if view mode is not details, switch back to the filter tab leftTabPane.getSelectionModel().select(filterTab); } From afd68ee70c7f45686a872ad6f64f7f9a9cf920d6 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Fri, 23 Mar 2018 17:42:47 +0100 Subject: [PATCH 3/5] add Clear Viz. button --- .../autopsy/communications/Bundle.properties | 23 ++-- .../communications/VisualizationPanel.form | 63 +++++++--- .../communications/VisualizationPanel.java | 110 ++++++++++++------ .../autopsy/communications/images/broom.png | Bin 0 -> 784 bytes 4 files changed, 134 insertions(+), 62 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/communications/images/broom.png diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index 96d76fe34a..559e9bba86 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -24,6 +24,17 @@ VisualizationPanel.jButton6.text=Hierarchy VisualizationPanel.jButton7.text=Circle VisualizationPanel.jButton8.text=Organic VisualizationPanel.fitGraphButton.text= +VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin. +VisualizationPanel.jLabel1.text=Layouts: +VisualizationPanel.zoomLabel.text=100% +VisualizationPanel.jLabel2.text=Zoom: +VisualizationPanel.fitZoomButton.toolTipText=fit visualization +VisualizationPanel.fitZoomButton.text= +VisualizationPanel.zoomActualButton.toolTipText=reset zoom +VisualizationPanel.zoomActualButton.text= +VisualizationPanel.zoomInButton.toolTipText=Zoom in +VisualizationPanel.zoomInButton.text= +VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.text= # To change this license header, choose License Headers in Project Properties. # To change this template file, choose Tools | Templates @@ -32,14 +43,4 @@ VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.organicLayoutButton.text=Organic VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchy -VisualizationPanel.zoomLabel.text=100% -VisualizationPanel.jLabel1.text=Layouts: -VisualizationPanel.jLabel2.text=Zoom: -VisualizationPanel.fitZoomButton.toolTipText=fit visualization -VisualizationPanel.fitZoomButton.text= -VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin. -VisualizationPanel.zoomActualButton.toolTipText=reset zoom -VisualizationPanel.zoomActualButton.text= -VisualizationPanel.zoomInButton.toolTipText=Zoom in -VisualizationPanel.zoomInButton.text= -VisualizationPanel.zoomOutButton.toolTipText=Zoom out +VisualizationPanel.clearVizButton.text_1=Clear Viz. diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form index d73c5e907c..9d5722443e 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form @@ -11,7 +11,7 @@ - + @@ -68,15 +68,15 @@ - - - + + + @@ -92,7 +92,11 @@ + + + + @@ -103,7 +107,11 @@ - + + + + + @@ -112,11 +120,7 @@ - - - - - + @@ -137,6 +141,8 @@ + + @@ -204,6 +210,9 @@ + + + @@ -213,11 +222,11 @@ + + - - @@ -232,11 +241,11 @@ + + - - @@ -251,11 +260,11 @@ + + - - @@ -270,11 +279,11 @@ + + - - @@ -295,6 +304,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index ca6973573b..d6047768dd 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -39,6 +39,7 @@ import com.mxgraph.util.mxUndoableEdit; import com.mxgraph.view.mxGraph; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.ActionEvent; @@ -80,6 +81,7 @@ import org.openide.util.NbBundle; import org.openide.util.lookup.ProxyLookup; import org.sleuthkit.autopsy.casemodule.Case; import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator; @@ -105,16 +107,16 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(VisualizationPanel.class.getName()); private static final String BASE_IMAGE_PATH = "/org/sleuthkit/autopsy/communications/images"; - static final private ImageIcon pinIcon = - new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/marker--pin.png")); - static final private ImageIcon addPinIcon = - new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/marker--plus.png")); - static final private ImageIcon unpinIcon = - new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/marker--minus.png")); - static final private ImageIcon unlockIcon = - new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/lock_large_unlocked.png")); - static final private ImageIcon lockIcon = - new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/lock_large_locked.png")); + static final private ImageIcon pinIcon + = new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/marker--pin.png")); + static final private ImageIcon addPinIcon + = new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/marker--plus.png")); + static final private ImageIcon unpinIcon + = new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/marker--minus.png")); + static final private ImageIcon unlockIcon + = new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/lock_large_unlocked.png")); + static final private ImageIcon lockIcon + = new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/lock_large_locked.png")); private static final String CANCEL = Bundle.VisualizationPanel_cancelButton_text(); @@ -167,13 +169,17 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider //install rubber band selection handler rubberband = new mxRubberband(graphComponent); - final mxEventSource.mxIEventListener scaleListener = (Object sender, mxEventObject evt) -> - zoomLabel.setText(DecimalFormat.getPercentInstance().format(graph.getView().getScale())); + final mxEventSource.mxIEventListener scaleListener = (Object sender, mxEventObject evt) + -> zoomLabel.setText(DecimalFormat.getPercentInstance().format(graph.getView().getScale())); graph.getView().addListener(mxEvent.SCALE, scaleListener); graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, scaleListener); - //right click handler graphComponent.getGraphControl().addMouseWheelListener(new MouseAdapter() { + /** + * Translate mouse wheel events into zooming. + * + * @param event The MouseWheelEvent + */ @Override public void mouseWheelMoved(final MouseWheelEvent event) { super.mouseWheelMoved(event); @@ -186,6 +192,11 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider }); graphComponent.getGraphControl().addMouseListener(new MouseAdapter() { + /** + * Right click handler: show context menu. + * + * @param event The MouseEvent + */ @Override public void mouseClicked(final MouseEvent event) { super.mouseClicked(event); @@ -246,8 +257,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider //feed selection to explorermanager graph.getSelectionModel().addListener(null, new SelectionListener()); - final mxEventSource.mxIEventListener undoListener = (Object sender, mxEventObject evt) -> - undoManager.undoableEditHappened((mxUndoableEdit) evt.getProperty("edit")); + final mxEventSource.mxIEventListener undoListener = (Object sender, mxEventObject evt) + -> undoManager.undoableEditHappened((mxUndoableEdit) evt.getProperty("edit")); graph.getModel().addListener(mxEvent.UNDO, undoListener); graph.getView().addListener(mxEvent.UNDO, undoListener); @@ -339,12 +350,11 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider windowAncestor = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, this); try { - commsManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager(); - } catch (IllegalStateException ex) { - logger.log(Level.SEVERE, "Can't get CommunicationsManager when there is no case open.", ex); + commsManager = Case.getOpenCase().getSleuthkitCase().getCommunicationsManager(); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); - + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Can't get CommunicationsManager when there is no case open.", ex); } Case.addEventTypeSubscriber(EnumSet.of(CURRENT_CASE), evt -> { @@ -399,6 +409,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider fitZoomButton = new JButton(); jLabel2 = new JLabel(); zoomLabel = new JLabel(); + clearVizButton = new JButton(); + jSeparator2 = new JToolBar.Separator(); setLayout(new BorderLayout()); @@ -407,11 +419,11 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider borderLayoutPanel.setLayout(new BorderLayout()); - jTextArea1.setBackground(new Color(240, 240, 240)); jTextArea1.setColumns(20); jTextArea1.setLineWrap(true); jTextArea1.setRows(5); jTextArea1.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextArea1.text")); // NOI18N + jTextArea1.setBackground(new Color(240, 240, 240)); GroupLayout placeHolderPanelLayout = new GroupLayout(placeHolderPanel); placeHolderPanel.setLayout(placeHolderPanelLayout); @@ -472,11 +484,13 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider } }); + jSeparator1.setOrientation(SwingConstants.VERTICAL); + zoomOutButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png"))); // NOI18N zoomOutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N - zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N zoomOutButton.setFocusable(false); zoomOutButton.setHorizontalTextPosition(SwingConstants.CENTER); + zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N zoomOutButton.setVerticalTextPosition(SwingConstants.BOTTOM); zoomOutButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { @@ -486,9 +500,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider zoomInButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png"))); // NOI18N zoomInButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.text")); // NOI18N - zoomInButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N zoomInButton.setFocusable(false); zoomInButton.setHorizontalTextPosition(SwingConstants.CENTER); + zoomInButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomInButton.toolTipText")); // NOI18N zoomInButton.setVerticalTextPosition(SwingConstants.BOTTOM); zoomInButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { @@ -498,9 +512,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider zoomActualButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png"))); // NOI18N zoomActualButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.text")); // NOI18N - zoomActualButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N zoomActualButton.setFocusable(false); zoomActualButton.setHorizontalTextPosition(SwingConstants.CENTER); + zoomActualButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomActualButton.toolTipText")); // NOI18N zoomActualButton.setVerticalTextPosition(SwingConstants.BOTTOM); zoomActualButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { @@ -510,9 +524,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider fitZoomButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png"))); // NOI18N fitZoomButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.text")); // NOI18N - fitZoomButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N fitZoomButton.setFocusable(false); fitZoomButton.setHorizontalTextPosition(SwingConstants.CENTER); + fitZoomButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fitZoomButton.toolTipText")); // NOI18N fitZoomButton.setVerticalTextPosition(SwingConstants.BOTTOM); fitZoomButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { @@ -524,11 +538,25 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider zoomLabel.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomLabel.text")); // NOI18N + clearVizButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/broom.png"))); // NOI18N + clearVizButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.text_1")); // NOI18N + clearVizButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + clearVizButtonActionPerformed(evt); + } + }); + + jSeparator2.setOrientation(SwingConstants.VERTICAL); + GroupLayout toolbarLayout = new GroupLayout(toolbar); toolbar.setLayout(toolbarLayout); toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) .add(toolbarLayout.createSequentialGroup() + .addContainerGap() + .add(clearVizButton) .add(3, 3, 3) + .add(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) + .add(5, 5, 5) .add(jLabel1) .addPreferredGap(LayoutStyle.RELATED) .add(fastOrganicLayoutButton) @@ -539,7 +567,11 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider .addPreferredGap(LayoutStyle.RELATED) .add(circleLayoutButton) .addPreferredGap(LayoutStyle.RELATED) - .add(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) + .add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.RELATED) + .add(jLabel2) + .addPreferredGap(LayoutStyle.RELATED) + .add(zoomLabel) .addPreferredGap(LayoutStyle.RELATED) .add(zoomOutButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.RELATED) @@ -548,11 +580,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider .add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.RELATED) .add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(jLabel2) - .addPreferredGap(LayoutStyle.RELATED) - .add(zoomLabel) - .add(27, 27, 27)) + .addContainerGap(12, Short.MAX_VALUE)) ); toolbarLayout.setVerticalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) .add(toolbarLayout.createSequentialGroup() @@ -569,7 +597,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider .add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(fitZoomButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(jLabel2) - .add(zoomLabel)) + .add(zoomLabel) + .add(clearVizButton) + .add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .add(3, 3, 3)) ); @@ -612,6 +642,18 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider morph(hierarchicalLayout); }//GEN-LAST:event_hierarchyLayoutButtonActionPerformed + private void clearVizButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearVizButtonActionPerformed + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + graph.getModel().beginUpdate(); + pinnedAccountModel.clear(); + graph.clear(); + rebuildGraph(); + // Updates the display + graph.getModel().endUpdate(); + setCursor(Cursor.getDefaultCursor()); + + }//GEN-LAST:event_clearVizButtonActionPerformed + private void applyOrganicLayout(int iterations) { organicLayout.setMaxIterations(iterations); morph(organicLayout); @@ -652,7 +694,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider ModalDialogProgressIndicator progress = new ModalDialogProgressIndicator(windowAncestor, "Computing layout", new String[]{CANCEL}, CANCEL, cancelationListener); SwingWorker morphWorker = new SwingWorker() { @Override - protected Void doInBackground() throws Exception { + protected Void doInBackground() { progress.start("Computing layout"); layout.execute(graph.getDefaultParent()); if (isCancelled()) { @@ -694,12 +736,14 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider // Variables declaration - do not modify//GEN-BEGIN:variables private JPanel borderLayoutPanel; private JButton circleLayoutButton; + private JButton clearVizButton; private JButton fastOrganicLayoutButton; private JButton fitZoomButton; private JButton hierarchyLayoutButton; private JLabel jLabel1; private JLabel jLabel2; private JToolBar.Separator jSeparator1; + private JToolBar.Separator jSeparator2; private JTextArea jTextArea1; private JButton organicLayoutButton; private JPanel placeHolderPanel; @@ -856,7 +900,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider } @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(ActionEvent event) { progress.setCancelling("Cancelling..."); cancellable.cancel(true); progress.finish(); diff --git a/Core/src/org/sleuthkit/autopsy/communications/images/broom.png b/Core/src/org/sleuthkit/autopsy/communications/images/broom.png new file mode 100644 index 0000000000000000000000000000000000000000..2c6152ef621a20c8bb016742c08153f20cd8e71e GIT binary patch literal 784 zcmV+r1MmEaP)0Hy9IdnOjm|8iDrb~(_gorLm$cws&E&`E?@S>Xnp>MK_0tqxD+)y*nqBPRUqEyO{ zSeYd{zqWL9@Ah^ME(k&jeBt*#hvz)cbN=U?=MbLfv7S$Ovnm9v1gpa!WOahs(+xcK z>j})ct8)R0XP8Hr5GH>Bbv_?zL;hot0-AS^LB~63A=8ovbvw!q>D|ky6aFJP&0^!T z>+f7S$s|~A)JT6WBiUfwrEhxBV&nX4D~O}kgqZI^7F%-V8%|kzB3M@yrJj$9so`uIV{MDI}O3`ihEN7c7=06c?M( zI+%n-$09fmgaUynhd6p{{CrPWU#5tMTofA(S-JuOdRO1=IhaxR0p Date: Fri, 23 Mar 2018 18:01:02 +0100 Subject: [PATCH 4/5] fix codacy issues --- .../communications/ModifiableProxyLookup.java | 4 +- .../timeline/DataContentExplorerPanel.java | 72 ------------------- .../timeline/ModifiableProxyLookup.java | 5 +- .../timeline/TimeLineTopComponent.java | 49 +++++++++++++ 4 files changed, 52 insertions(+), 78 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/communications/ModifiableProxyLookup.java b/Core/src/org/sleuthkit/autopsy/communications/ModifiableProxyLookup.java index cc8657d638..ad3babc504 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/ModifiableProxyLookup.java +++ b/Core/src/org/sleuthkit/autopsy/communications/ModifiableProxyLookup.java @@ -37,8 +37,8 @@ final class ModifiableProxyLookup extends ProxyLookup { * * @param lookups The new Lookups to delegate to. */ - void setNewLookups(final Lookup... lookups) { - /* default */ + public void setNewLookups(final Lookup... lookups) { + setLookups(lookups); } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java b/Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java deleted file mode 100644 index d87cae18c0..0000000000 --- a/Core/src/org/sleuthkit/autopsy/timeline/DataContentExplorerPanel.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2018 Basis Technology Corp. - * Contact: carrier sleuthkit 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; - -import java.awt.BorderLayout; -import java.beans.PropertyChangeEvent; -import javax.swing.JPanel; -import org.openide.explorer.ExplorerManager; -import org.openide.nodes.Node; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; -import org.sleuthkit.autopsy.corecomponents.DataContentPanel; - -/** - * Panel that wraps a DataContentPanel and implements ExplorerManager.Provider. - * This allows the explorer manager found by the DataContentPanel to be - * controlled easily. - * - * @see org.sleuthkit.autopsy.communications.MessageDataContent for another - * solution to a very similar problem. - */ -final class DataContentExplorerPanel extends JPanel implements ExplorerManager.Provider, DataContent { - - private final ExplorerManager explorerManager = new ExplorerManager(); - private final DataContentPanel wrapped; - - DataContentExplorerPanel() { - super(new BorderLayout()); - wrapped = DataContentPanel.createInstance(); - } - - @Override - public ExplorerManager getExplorerManager() { - return explorerManager; - } - - @Override - public void setNode(Node selectedNode) { - wrapped.setNode(selectedNode); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - wrapped.propertyChange(evt); - } - - /** - * Initialize the contents of this panel for use. Specifically add the - * wrapped DataContentPanel to the AWT/Swing containment hierarchy. This - * will trigger the addNotify() method of the embeded Message - * MessageContentViewer causing it to look for a ExplorerManager; it should - * find the one provided by this DataContentExplorerPanel. - */ - void initialize() { - add(wrapped, BorderLayout.CENTER); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java b/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java index bbeea62e1a..6cd1559825 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ModifiableProxyLookup.java @@ -37,10 +37,7 @@ final class ModifiableProxyLookup extends ProxyLookup { * * @param lookups The new Lookups to delegate to. */ - void setNewLookups(final Lookup... lookups) { - /* - * default - */ + public void setNewLookups(final Lookup... lookups) { setLookups(lookups); } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index ccde0aaa37..65db353507 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.timeline; +import java.awt.BorderLayout; import java.awt.Component; import java.awt.KeyboardFocusManager; import java.beans.PropertyChangeEvent; @@ -40,6 +41,7 @@ import javafx.scene.input.KeyEvent; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javax.swing.JComponent; +import javax.swing.JPanel; import javax.swing.SwingUtilities; import static javax.swing.SwingUtilities.isDescendingFrom; import org.controlsfx.control.Notifications; @@ -57,6 +59,8 @@ import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.actions.AddBookmarkTagAction; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; +import org.sleuthkit.autopsy.corecomponents.DataContentPanel; import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.coreutils.Logger; @@ -474,4 +478,49 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer return Bundle.TimeLineResultView_startDateToEndDate_text(start, end); } } + + /** + * Panel that wraps a DataContentPanel and implements + * ExplorerManager.Provider. This allows the explorer manager found by the + * DataContentPanel to be controlled easily. + * + * @see org.sleuthkit.autopsy.communications.MessageDataContent for another + * solution to a very similar problem. + */ + final private static class DataContentExplorerPanel extends JPanel implements ExplorerManager.Provider, DataContent { + + private final ExplorerManager explorerManager = new ExplorerManager(); + private final DataContentPanel wrapped; + + private DataContentExplorerPanel() { + super(new BorderLayout()); + wrapped = DataContentPanel.createInstance(); + } + + @Override + public ExplorerManager getExplorerManager() { + return explorerManager; + } + + @Override + public void setNode(Node selectedNode) { + wrapped.setNode(selectedNode); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + wrapped.propertyChange(evt); + } + + /** + * Initialize the contents of this panel for use. Specifically add the + * wrapped DataContentPanel to the AWT/Swing containment hierarchy. This + * will trigger the addNotify() method of the embeded Message + * MessageContentViewer causing it to look for a ExplorerManager; it + * should find the one provided by this DataContentExplorerPanel. + */ + private void initialize() { + add(wrapped, BorderLayout.CENTER); + } + } } From d98eabb22dc8aab9a911533c56c52d101ef5fc21 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Mon, 26 Mar 2018 14:06:48 +0200 Subject: [PATCH 5/5] fix listener adding/removal --- .../autopsy/communications/MessageBrowser.java | 12 ++++++++---- .../autopsy/timeline/TimeLineTopComponent.java | 12 ++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java index da3416f003..68309f5195 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/MessageBrowser.java @@ -118,10 +118,6 @@ public final class MessageBrowser extends JPanel implements ExplorerManager.Prov Bundle.MessageBrowser_DataResultViewerTable_title())); messagesResultPanel.open(); - //add listener that maintains correct selection in the Global Actions Context - KeyboardFocusManager.getCurrentKeyboardFocusManager() - .addPropertyChangeListener("focusOwner", focusPropertyListener); - this.tableEM.addPropertyChangeListener(new PropertyChangeListener() { /** * Listener that pushes selections in the tableEM (the Accounts @@ -176,6 +172,14 @@ public final class MessageBrowser extends JPanel implements ExplorerManager.Prov return proxyLookup; } + @Override + public void addNotify() { + super.addNotify(); + //add listener that maintains correct selection in the Global Actions Context + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .addPropertyChangeListener("focusOwner", focusPropertyListener); + } + @Override public void removeNotify() { super.removeNotify(); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index 65db353507..3d19bd4226 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -446,6 +446,17 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer public void componentOpened() { super.componentOpened(); WindowManager.getDefault().setTopComponentFloating(this, true); + + //add listener that maintains correct selection in the Global Actions Context + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .addPropertyChangeListener("focusOwner", focusPropertyListener); + } + + @Override + protected void componentClosed() { + super.componentClosed(); + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .removePropertyChangeListener("focusOwner", focusPropertyListener); } @Override @@ -476,6 +487,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer .withZone(TimeLineController.getJodaTimeZone()) .toString(zonedFormatter); return Bundle.TimeLineResultView_startDateToEndDate_text(start, end); + } }