diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java index 1d23a7f9fc..006fbd846f 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java @@ -130,19 +130,6 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro //Case is closed, do nothig. } } - - @Subscribe - void historyChange(CVTEvents.StateEvent event) { - try { - final CommunicationsManager commsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); - accountsTableEM.setRootContext(new AbstractNode(Children.create(new AccountDeviceInstanceNodeFactory(commsManager, event.getCommunicationsState().getCommunicationsFilter()), true))); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "There was an error getting the CommunicationsManager for the current case.", ex); - } catch (NoCurrentCaseException ex) { //NOPMD empty catch clause - //Case is closed, do nothig. - } - - } /** * This method is called from within the constructor to initialize the form. diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties index f00a02cf9d..6665c2e958 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties @@ -22,6 +22,7 @@ CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=Visualiz CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize 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 @@ -32,21 +33,9 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in VisualizationPanel.zoomInButton.text= VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.text= -<<<<<<< HEAD -VisualizationPanel.fastOrganicLayoutButton.text=Redraw -VisualizationPanel.clearVizButton.text_1=Clear -VisualizationPanel.backButton.text_1= -VisualizationPanel.forwardButton.text= -======= VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.organicLayoutButton.text=Organic -VisualizationPanel.fastOrganicLayoutButton.text= +VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical -VisualizationPanel.clearVizButton.text_1= +VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report ->>>>>>> develop -VisualizationPanel.clearVizButton.actionCommand= -VisualizationPanel.backButton.toolTipText=Click to go back -VisualizationPanel.forwardButton.toolTipText=Click to go forward -VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart -VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED index c9f38865a8..e4daded09b 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle.properties-MERGED @@ -58,6 +58,7 @@ CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=Visualiz CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize VisualizationPanel.fitGraphButton.text= VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin. +VisualizationPanel.jLabel1.text=Layouts: # {0} - layout name VisualizationPanel.layoutFail.text={0} layout failed. Try a different layout. # {0} - layout name @@ -76,24 +77,12 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in VisualizationPanel.zoomInButton.text= VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.text= -<<<<<<< HEAD -VisualizationPanel.fastOrganicLayoutButton.text=Redraw -VisualizationPanel.clearVizButton.text_1=Clear -VisualizationPanel.backButton.text_1= -VisualizationPanel.forwardButton.text= -======= VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.organicLayoutButton.text=Organic -VisualizationPanel.fastOrganicLayoutButton.text= +VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.hierarchyLayoutButton.text=Hierarchical -VisualizationPanel.clearVizButton.text_1= +VisualizationPanel.clearVizButton.text_1=Clear Viz. VisualizationPanel.snapshotButton.text_1=Snapshot Report ->>>>>>> develop -VisualizationPanel.clearVizButton.actionCommand= -VisualizationPanel.backButton.toolTipText=Click to go back -VisualizationPanel.forwardButton.toolTipText=Click to go forward -VisualizationPanel.fastOrganicLayoutButton.toolTipText=Click to redraw the chart -VisualizationPanel.clearVizButton.toolTipText=Click to clear the chart VisualizationPanel_action_dialogs_title=Communications VisualizationPanel_action_name_text=Snapshot Report VisualizationPanel_module_name=Communications diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java b/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java index 051ff2b193..6a6a60d3da 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTEvents.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.eventbus.EventBus; import java.util.Collection; import org.sleuthkit.datamodel.CommunicationsFilter; -import org.sleuthkit.autopsy.communications.StateManager.CommunicationsState; /** * Provide the singleton EventBus. @@ -38,9 +37,6 @@ final class CVTEvents { private CVTEvents() { } - /** - * Invoked when a ComminucationsFilter change occures. - */ static final class FilterChangeEvent { private final CommunicationsFilter newFilter; @@ -55,9 +51,6 @@ final class CVTEvents { } - /** - * Invoked when a change in the pinned accounts occures. - */ static final class PinAccountsEvent { private final ImmutableSet accountDeviceInstances; @@ -77,9 +70,6 @@ final class CVTEvents { } } - /** - * Invoked when a change in the unpinned accounts occures. - */ static final class UnpinAccountsEvent { private final ImmutableSet accountDeviceInstances; @@ -92,34 +82,4 @@ final class CVTEvents { this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances); } } - - /** - * Invoked when there is a change in the state of the window. - */ - static final class StateEvent { - private final CommunicationsState newState; - - StateEvent(CommunicationsState newState) { - this.newState = newState; - } - - public CommunicationsState getCommunicationsState(){ - return newState; - } - } - - /** - * Invoked when change in the link analysis graph scale occures. - */ - static final class ZoomEvent { - private final double zoomValue; - - ZoomEvent(double zoomValue) { - this.zoomValue = zoomValue; - } - - public double getZoomValue(){ - return zoomValue; - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java index bc8047d473..1e1004de25 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java @@ -65,8 +65,8 @@ public final class CVTTopComponent extends TopComponent { proxyLookup.setNewLookups(selectedComponent.getLookup()); filtersPane.setDeviceAccountTypeEnabled(browseVisualizeTabPane.getSelectedIndex() != 0); }); - - + + /* * Connect the filtersPane to the accountsBrowser and visualizaionPanel * via an Eventbus @@ -74,7 +74,6 @@ public final class CVTTopComponent extends TopComponent { CVTEvents.getCVTEventBus().register(this); CVTEvents.getCVTEventBus().register(vizPanel); CVTEvents.getCVTEventBus().register(accountsBrowser); - CVTEvents.getCVTEventBus().register(filtersPane); } @Subscribe diff --git a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java index a6ed7e5aef..587bf47260 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/FiltersPanel.java @@ -19,17 +19,12 @@ package org.sleuthkit.autopsy.communications; import com.google.common.collect.ImmutableSet; -import com.google.common.eventbus.Subscribe; import java.awt.event.ItemListener; import java.beans.PropertyChangeListener; -import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; @@ -265,75 +260,6 @@ final public class FiltersPanel extends JPanel { logger.log(Level.SEVERE, "There was a error loading the datasources for the case.", tskCoreException); } } - - /** - * Given a list of subFilters, set the states of the panel controls - * accordingly. - * - * @param subFilters A list of subFilters - */ - public void setFilters(List subFilters) { - - subFilters.forEach(subFilter -> { - if( subFilter instanceof DeviceFilter ) { - setDeviceFilter((DeviceFilter)subFilter); - } else if (subFilter instanceof DateRangeFilter) { - setDateRangeFilter( (DateRangeFilter) subFilter); - } else if( subFilter instanceof AccountTypeFilter) { - setAccountTypeFilter((AccountTypeFilter) subFilter); - } - }); - } - - /** - * Sets the state of the device filter checkboxes - * - * @param deviceFilter Selected devices - */ - private void setDeviceFilter(DeviceFilter deviceFilter) { - Collection deviceIDs = deviceFilter.getDevices(); - devicesMap.forEach((type, cb) -> { - cb.setSelected(deviceIDs.contains(type)); - }); - } - - /** - * Sets the value of the DateRangeFilters. - * - * @param dateFilter - */ - private void setDateRangeFilter(DateRangeFilter dateFilter) { - ZonedDateTime zoneDate = ZonedDateTime.ofInstant(Instant.ofEpochSecond(dateFilter.getStartDate()), Utils.getUserPreferredZoneId()); - startDatePicker.setEnabled(dateFilter.isStartDateEnabled()); - startCheckBox.setSelected(dateFilter.isStartDateEnabled()); - startDatePicker.setDate(zoneDate.toLocalDate()); - - zoneDate = ZonedDateTime.ofInstant(Instant.ofEpochSecond(dateFilter.getEndDate()), Utils.getUserPreferredZoneId()); - endDatePicker.setEnabled(dateFilter.isEndDateEnabled()); - endCheckBox.setSelected(dateFilter.isEndDateEnabled()); - endDatePicker.setDate(zoneDate.toLocalDate()); - } - - /** - * Set the state of the account type checkboxes to match the passed in filter - * - * @param typeFilter Account Types to be selected - */ - private void setAccountTypeFilter(AccountTypeFilter typeFilter){ - - accountTypeMap.forEach((type, cb) -> { - cb.setSelected(typeFilter.getAccountTypes().contains(type)); - }); - } - - @Subscribe - void filtersBack(CVTEvents.StateEvent event) { - if(event.getCommunicationsState().getCommunicationsFilters() != null){ - setFilters(event.getCommunicationsState().getCommunicationsFilters()); - needsRefresh = false; - validateFilters(); - } - } /** * This method is called from within the constructor to initialize the form. @@ -582,12 +508,7 @@ final public class FiltersPanel extends JPanel { validateFilters(); } - /** - * Get an instance of CommunicationsFilters base on the current panel state. - * - * @return an instance of CommunicationsFilter - */ - protected CommunicationsFilter getFilter() { + private CommunicationsFilter getFilter() { CommunicationsFilter commsFilter = new CommunicationsFilter(); commsFilter.addAndFilter(getDeviceFilter()); commsFilter.addAndFilter(getAccountTypeFilter()); @@ -632,11 +553,9 @@ final public class FiltersPanel extends JPanel { */ private DateRangeFilter getDateRangeFilter() { ZoneId zone = Utils.getUserPreferredZoneId(); - - return new DateRangeFilter(startDatePicker.isEnabled(), - startDatePicker.getDate().atStartOfDay(zone).toEpochSecond(), - endDatePicker.isEnabled(), - endDatePicker.getDate().atStartOfDay(zone).toEpochSecond()); + long start = startDatePicker.isEnabled() ? startDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0; + long end = endDatePicker.isEnabled() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0; + return new DateRangeFilter(start, end); } /** diff --git a/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java b/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java index c9fe899c3f..f7fb7d1232 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/PinnedAccountModel.java @@ -57,7 +57,7 @@ class PinnedAccountModel { * * @param accountDeviceInstances The accounts to unpin. */ - void unpinAccount(Set accountDeviceInstances) { + void unpinAccount(ImmutableSet accountDeviceInstances) { pinnedAccountDevices.removeAll(accountDeviceInstances); } @@ -68,7 +68,7 @@ class PinnedAccountModel { * * @param accountDeviceInstances The accounts to pin. */ - void pinAccount(Set accountDeviceInstances) { + void pinAccount(ImmutableSet accountDeviceInstances) { pinnedAccountDevices.addAll(accountDeviceInstances); } @@ -86,7 +86,7 @@ class PinnedAccountModel { pinnedAccountDevices.clear(); } - ImmutableSet getPinnedAccounts() { + Iterable getPinnedAccounts() { return ImmutableSet.copyOf(pinnedAccountDevices); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/StateManager.java b/Core/src/org/sleuthkit/autopsy/communications/StateManager.java deleted file mode 100755 index 9e7d78da93..0000000000 --- a/Core/src/org/sleuthkit/autopsy/communications/StateManager.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2019 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.communications; - -import com.google.common.collect.ImmutableSet; -import com.google.common.eventbus.Subscribe; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import org.sleuthkit.autopsy.coreutils.History; -import org.sleuthkit.datamodel.CommunicationsFilter; -import org.sleuthkit.datamodel.CommunicationsFilter.SubFilter; -import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG; -import static org.sleuthkit.datamodel.Relationship.Type.MESSAGE; - -/** - * Manages the state history for the Communications window. History is currently - * maintained for the CommunicationsFilter, the List of pinned accounts and the - * scale value of the graph. - */ -final class StateManager { - - private final History historyManager = new History<>(); - private CommunicationsFilter comFilter; - private final PinnedAccountModel pinModel; - - /** - * Manages the state history for the Communications window. - * - * @param pinModel PinnedACcountModel - */ - public StateManager(PinnedAccountModel pinModel){ - this.pinModel = pinModel; - CVTEvents.getCVTEventBus().register(this); - } - - @Subscribe - void pinAccount(CVTEvents.PinAccountsEvent pinEvent) { - if(pinEvent.isReplace()){ - HashSet pinnedList = new HashSet<>(); - pinnedList.addAll(pinEvent.getAccountDeviceInstances()); - historyManager.advance(new CommunicationsState(comFilter.getAndFilters(), pinnedList, -1)); - } else { - HashSet pinnedList = new HashSet<>(); - pinnedList.addAll(pinEvent.getAccountDeviceInstances()); - pinnedList.addAll(pinModel.getPinnedAccounts()); - - historyManager.advance(new CommunicationsState( comFilter.getAndFilters(), pinnedList, -1)); - } - } - - @Subscribe - void filterChange(CVTEvents.FilterChangeEvent fileterEvent) { - comFilter = fileterEvent.getNewFilter(); - historyManager.advance(new CommunicationsState(comFilter.getAndFilters(), pinModel.getPinnedAccounts(), -1)); - } - - @Subscribe - void unpinAccounts(CVTEvents.UnpinAccountsEvent pinEvent) { - - HashSet pinnedList = new HashSet<>(); - pinnedList.addAll(pinModel.getPinnedAccounts()); - pinnedList.removeAll(pinEvent.getAccountDeviceInstances()); - - historyManager.advance(new CommunicationsState(comFilter.getAndFilters(), pinnedList, -1)); - } - - @Subscribe - void zoomedGraph(CVTEvents.ZoomEvent zoomEvent) { - historyManager.advance(new CommunicationsState(comFilter.getAndFilters(), pinModel.getPinnedAccounts(), zoomEvent.getZoomValue())); - } - - /** - * Returns the next state object in the history. - * - * @return CommunicationsState or null if canRetreat is null - */ - public CommunicationsState retreat(){ - if(canRetreat()) { - return historyManager.retreat(); - } else { - return null; - } - } - - /** - * Returns the next state object in the forward history. - * - * @return CommunicationsState or null if canAdvance is null - */ - public CommunicationsState advance() { - if(canAdvance()) { - return historyManager.advance(); - } else { - return null; - } - } - - /** - * Returns true if there is a history of states. - * - * @return boolean - */ - public boolean canRetreat() { - return historyManager.canRetreat(); - } - - /** - * Returns true if there is history to advance too. - * - * @return - */ - public boolean canAdvance(){ - return historyManager.canAdvance(); - } - - /** - * Object to store one instance of the state of the Communications window. - */ - final class CommunicationsState{ - private final List communcationFilters; - private final Set pinnedList; - private final double zoomValue; - - /** - * Stores all the properties of the current state of the Communications - * window. - * - * @param communcationFilters List of the SubFilters from the FiltersPanel - * @param pinnedList Set of AccountDeviceInstanceKey - * @param zoomValue Double value of the current graph scale - */ - protected CommunicationsState(List communcationFilters, Set pinnedList, double zoomValue){ - this.pinnedList = pinnedList; - this.communcationFilters = communcationFilters; - this.zoomValue = zoomValue; - } - - /** - * Return whether or not this state contains a zoom change - * - * @return boolean - */ - public boolean isZoomChange() { - return (zoomValue != -1); - } - - /** - * Returns a list of the currently pinned accounts. - * - * @return Set of AccountDeviceInstanceKey - */ - public Set getPinnedList(){ - return pinnedList; - } - - /** - * Returns a list of communication SubFilters. - * - * @return List of SubFilter - */ - public List getCommunicationsFilters(){ - return communcationFilters; - } - - /** - * Return a new CommunicationsFilter object based on the list of - * SubFilters - * - * @return CommunicationsFilter - */ - public CommunicationsFilter getCommunicationsFilter() { - CommunicationsFilter newFilters = new CommunicationsFilter(); - newFilters.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(ImmutableSet.of(CALL_LOG, MESSAGE))); - communcationFilters.forEach(filter -> { - newFilters.addAndFilter(filter); - }); - - return newFilters; - } - - /** - * Return the value for the % zoom. - * - * @return double value % zoom or -1 if zoom did not change - */ - public double getZoomValue() { - return zoomValue; - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/communications/UnpinAccountsAction.java b/Core/src/org/sleuthkit/autopsy/communications/UnpinAccountsAction.java index 58ace503d9..ba0bbc545b 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/UnpinAccountsAction.java +++ b/Core/src/org/sleuthkit/autopsy/communications/UnpinAccountsAction.java @@ -46,7 +46,7 @@ final class UnpinAccountsAction extends AbstractCVTAction { public void actionPerformed(final ActionEvent event) { CVTEvents.getCVTEventBus().post(new CVTEvents.UnpinAccountsEvent(getSelectedAccounts())); } - + @Override String getActionDisplayName() { return getSelectedAccounts().size() > 1 ? PLURAL_TEXT : SINGULAR_TEXT; diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form index f2e3052f47..4e0a73a6c7 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.form @@ -11,7 +11,7 @@ - + @@ -49,9 +49,9 @@ - + - + @@ -93,28 +93,32 @@ - - - - - + + + + + - - + + + + + + - + - + - + - + - + - + @@ -129,7 +133,12 @@ + + + + + @@ -138,11 +147,8 @@ - - - @@ -150,21 +156,58 @@ + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -263,12 +306,6 @@ - - - - - - @@ -279,39 +316,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -330,11 +334,6 @@ - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index dd6826570b..f3d4f95bb2 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.communications; -import com.google.common.collect.ImmutableSet; import com.google.common.eventbus.Subscribe; import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; import com.mxgraph.layout.mxCircleLayout; @@ -42,6 +41,7 @@ import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Cursor; import java.awt.Desktop; import java.awt.Dimension; import java.awt.Font; @@ -163,8 +163,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider private final Map layoutButtons = new HashMap<>(); private NamedGraphLayout currentLayout; - private final StateManager stateManager; - @NbBundle.Messages("VisalizationPanel.paintingError=Problem painting visualization.") public VisualizationPanel() { initComponents(); @@ -243,6 +241,10 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider graph.getView().addListener(mxEvent.UNDO, undoListener); FastOrganicLayoutImpl fastOrganicLayout = new FastOrganicLayoutImpl(graph); + CircleLayoutImpl circleLayout = new CircleLayoutImpl(graph); + OrganicLayoutImpl organicLayout = new OrganicLayoutImpl(graph); + organicLayout.setMaxIterations(10); + HierarchicalLayoutImpl hierarchyLayout = new HierarchicalLayoutImpl(graph); //local method to configure layout buttons BiConsumer configure = (layoutButton, layout) -> { @@ -250,13 +252,12 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider layoutButton.addActionListener(event -> applyLayout(layout)); }; //configure layout buttons. + configure.accept(circleLayoutButton, circleLayout); + configure.accept(organicLayoutButton, organicLayout); configure.accept(fastOrganicLayoutButton, fastOrganicLayout); + configure.accept(hierarchyLayoutButton, hierarchyLayout); applyLayout(fastOrganicLayout); - - stateManager = new StateManager(pinnedAccountModel); - - setStateButtonsEnabled(); } @Override @@ -285,8 +286,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider rebuildGraph(); // Updates the display graph.getModel().endUpdate(); - - setStateButtonsEnabled(); } @Subscribe @@ -299,8 +298,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider rebuildGraph(); // Updates the display graph.getModel().endUpdate(); - - setStateButtonsEnabled(); } @Subscribe @@ -311,8 +308,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider rebuildGraph(); // Updates the display graph.getModel().endUpdate(); - - setStateButtonsEnabled(); } @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @@ -354,9 +349,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider try { commsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); //NON-NLS + 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); //NON-NLS + logger.log(Level.SEVERE, "Can't get CommunicationsManager when there is no case open.", ex); } Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> { @@ -373,7 +368,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider try { commsManager = currentCase.getSleuthkitCase().getCommunicationsManager(); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); //NON-NLS + logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); } } }); @@ -393,7 +388,12 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider placeHolderPanel = new JPanel(); jTextArea1 = new JTextArea(); toolbar = new JPanel(); + jLabel1 = new JLabel(); + hierarchyLayoutButton = new JButton(); fastOrganicLayoutButton = new JButton(); + organicLayoutButton = new JButton(); + circleLayoutButton = new JButton(); + jSeparator1 = new JToolBar.Separator(); zoomOutButton = new JButton(); zoomInButton = new JButton(); zoomActualButton = new JButton(); @@ -402,11 +402,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider zoomLabel = new JLabel(); clearVizButton = new JButton(); jSeparator2 = new JToolBar.Separator(); - backButton = new JButton(); - forwardButton = new JButton(); snapshotButton = new JButton(); jSeparator3 = new JToolBar.Separator(); - jSeparator4 = new JToolBar.Separator(); notificationsJFXPanel = new JFXPanel(); setLayout(new BorderLayout()); @@ -426,9 +423,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider placeHolderPanel.setLayout(placeHolderPanelLayout); placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING) .add(placeHolderPanelLayout.createSequentialGroup() - .addContainerGap(250, Short.MAX_VALUE) + .addContainerGap(268, Short.MAX_VALUE) .add(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE) - .addContainerGap(423, Short.MAX_VALUE)) + .addContainerGap(445, Short.MAX_VALUE)) ); placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING) .add(placeHolderPanelLayout.createSequentialGroup() @@ -439,12 +436,30 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER); - fastOrganicLayoutButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png"))); // NOI18N + jLabel1.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jLabel1.text")); // NOI18N + + hierarchyLayoutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.hierarchyLayoutButton.text")); // NOI18N + hierarchyLayoutButton.setFocusable(false); + hierarchyLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER); + hierarchyLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM); + fastOrganicLayoutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N - fastOrganicLayoutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.toolTipText")); // NOI18N fastOrganicLayoutButton.setFocusable(false); + fastOrganicLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER); fastOrganicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM); + organicLayoutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.organicLayoutButton.text")); // NOI18N + organicLayoutButton.setFocusable(false); + organicLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER); + organicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM); + + circleLayoutButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.circleLayoutButton.text")); // NOI18N + circleLayoutButton.setFocusable(false); + circleLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER); + circleLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM); + + 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 @@ -499,8 +514,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider 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.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.toolTipText")); // NOI18N - clearVizButton.setActionCommand(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.clearVizButton.actionCommand")); // NOI18N clearVizButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { clearVizButtonActionPerformed(evt); @@ -509,25 +522,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider jSeparator2.setOrientation(SwingConstants.VERTICAL); - backButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_previous.png"))); // NOI18N - backButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N - backButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.toolTipText")); // NOI18N - backButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - backButtonActionPerformed(evt); - } - }); - - forwardButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/resultset_next.png"))); // NOI18N - forwardButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N - forwardButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.toolTipText")); // NOI18N - forwardButton.setHorizontalTextPosition(SwingConstants.LEADING); - forwardButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - forwardButtonActionPerformed(evt); - } - }); - snapshotButton.setIcon(new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/report/images/image.png"))); // NOI18N snapshotButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.snapshotButton.text_1")); // NOI18N snapshotButton.addActionListener(new ActionListener() { @@ -538,22 +532,24 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider jSeparator3.setOrientation(SwingConstants.VERTICAL); - jSeparator4.setOrientation(SwingConstants.VERTICAL); - GroupLayout toolbarLayout = new GroupLayout(toolbar); toolbar.setLayout(toolbarLayout); toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) .add(toolbarLayout.createSequentialGroup() .addContainerGap() - .add(backButton) - .addPreferredGap(LayoutStyle.RELATED) - .add(forwardButton) - .addPreferredGap(LayoutStyle.RELATED) - .add(jSeparator4, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) + .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) .addPreferredGap(LayoutStyle.RELATED) - .add(clearVizButton) + .add(organicLayoutButton) + .addPreferredGap(LayoutStyle.RELATED) + .add(hierarchyLayoutButton) + .addPreferredGap(LayoutStyle.RELATED) + .add(circleLayoutButton) .addPreferredGap(LayoutStyle.RELATED) .add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.RELATED) @@ -578,7 +574,12 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider .add(toolbarLayout.createSequentialGroup() .add(3, 3, 3) .add(toolbarLayout.createParallelGroup(GroupLayout.CENTER) + .add(jLabel1, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE) + .add(hierarchyLayoutButton) .add(fastOrganicLayoutButton) + .add(organicLayoutButton) + .add(circleLayoutButton) + .add(jSeparator1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(zoomOutButton) .add(zoomInButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) @@ -587,11 +588,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider .add(zoomLabel) .add(clearVizButton) .add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(backButton) - .add(forwardButton) .add(snapshotButton) - .add(jSeparator3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(jSeparator4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .add(jSeparator3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .add(3, 3, 3)) ); @@ -609,17 +607,14 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider private void zoomActualButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomActualButtonActionPerformed graphComponent.zoomActual(); - CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale())); }//GEN-LAST:event_zoomActualButtonActionPerformed private void zoomInButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomInButtonActionPerformed graphComponent.zoomIn(); - CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale())); }//GEN-LAST:event_zoomInButtonActionPerformed private void zoomOutButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomOutButtonActionPerformed graphComponent.zoomOut(); - CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale())); }//GEN-LAST:event_zoomOutButtonActionPerformed /** @@ -661,66 +656,30 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider get(); } catch (InterruptedException | ExecutionException ex) { logger.log(Level.WARNING, "CVT graph layout failed.", ex); + String message = (lockedVertexModel.isEmpty()) + ? Bundle.VisualizationPanel_layoutFail_text(layout.getDisplayName()) + : Bundle.VisualizationPanel_layoutFailWithLockedVertices_text(layout.getDisplayName()); + + Platform.runLater(() + -> Notifications.create().owner(notificationsJFXPanel.getScene().getWindow()) + .text(message) + .showWarning() + ); } } }.execute(); } private void clearVizButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearVizButtonActionPerformed - CVTEvents.getCVTEventBus().post(new CVTEvents.UnpinAccountsEvent(pinnedAccountModel.getPinnedAccounts())); - }//GEN-LAST:event_clearVizButtonActionPerformed - - private void forwardButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_forwardButtonActionPerformed - handleStateChange(stateManager.advance()); - }//GEN-LAST:event_forwardButtonActionPerformed - - private void backButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed - handleStateChange(stateManager.retreat()); - }//GEN-LAST:event_backButtonActionPerformed - - /** - * Manages the redo and undo actions. - * - * @param newState a CommunicationsState - */ - private void handleStateChange(StateManager.CommunicationsState newState ){ - if(newState == null) { - return; - } - - // If the zoom was changed, only change the zoom. - if(newState.isZoomChange()) { - graph.getView().setScale(newState.getZoomValue()); - return; - } - - // This will cause the FilterPane to update its controls - CVTEvents.getCVTEventBus().post(new CVTEvents.StateEvent(newState)); - setStateButtonsEnabled(); - + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); graph.getModel().beginUpdate(); - graph.resetGraph(); - - if(newState.getPinnedList() != null) { - pinnedAccountModel.pinAccount(newState.getPinnedList()); - } else { - pinnedAccountModel.clear(); - } - - currentFilter = newState.getCommunicationsFilter(); - + pinnedAccountModel.clear(); + graph.clear(); rebuildGraph(); // Updates the display graph.getModel().endUpdate(); - - fitGraph(); - - } - - private void setStateButtonsEnabled() { - backButton.setEnabled(stateManager.canRetreat()); - forwardButton.setEnabled(stateManager.canAdvance()); - } + setCursor(Cursor.getDefaultCursor()); + }//GEN-LAST:event_clearVizButtonActionPerformed @NbBundle.Messages({ "VisualizationPanel_snapshot_report_failure=Snapshot report not created. An error occurred during creation." @@ -766,12 +725,12 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider graphComponent.zoom((heightFactor + widthFactor) / 2.0); } - + /** * Handle the ActionPerformed event from the Snapshot button. - * + * * @throws NoCurrentCaseException - * @throws IOException + * @throws IOException */ @NbBundle.Messages({ "VisualizationPanel_action_dialogs_title=Communications", @@ -803,14 +762,14 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider if (result == JOptionPane.OK_OPTION) { String enteredReportName = text.getText(); - + if(enteredReportName.trim().isEmpty()){ result = JOptionPane.showConfirmDialog(graphComponent, Bundle.VisualizationPane_accept_defaultName(defaultReportName), Bundle.VisualizationPane_blank_report_title(), JOptionPane.OK_CANCEL_OPTION); if(result != JOptionPane.OK_OPTION) { return; } } - + String reportName = StringUtils.defaultIfBlank(enteredReportName, defaultReportName); Path reportPath = Paths.get(currentCase.getReportDirectory(), reportName); if (Files.exists(reportPath)) { @@ -828,14 +787,14 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider } } } - + /** * Create the Snapshot Report. - * + * * @param currentCase The current case * @param reportName User selected name for the report - * - * @throws IOException + * + * @throws IOException */ @NbBundle.Messages({ "VisualizationPane_DisplayName=Open Report", @@ -849,12 +808,12 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider "VisualizationPane_Report_OK_Button=OK", "VisualizationPane_Open_Report=Open Report",}) private void createReport(Case currentCase, String reportName) throws IOException { - + // Create the report. Path reportFolderPath = Paths.get(currentCase.getReportDirectory(), reportName, Bundle.VisualizationPane_reportName()); //NON_NLS BufferedImage image = mxCellRenderer.createBufferedImage(graph, null, graph.getView().getScale(), Color.WHITE, true, null); Path reportPath = new CommSnapShotReportWriter(currentCase, reportFolderPath, reportName, new Date(), image, currentFilter).writeReport(); - + // Report success to the user and offer to open the report. String message = Bundle.VisualizationPane_Report_Success(reportPath.toAbsolutePath()); String[] buttons = {Bundle.VisualizationPane_Open_Report(), Bundle.VisualizationPane_Report_OK_Button()}; @@ -891,18 +850,20 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider } // Variables declaration - do not modify//GEN-BEGIN:variables - private JButton backButton; private JPanel borderLayoutPanel; + private JButton circleLayoutButton; private JButton clearVizButton; private JButton fastOrganicLayoutButton; private JButton fitZoomButton; - private JButton forwardButton; + private JButton hierarchyLayoutButton; + private JLabel jLabel1; private JLabel jLabel2; + private JToolBar.Separator jSeparator1; private JToolBar.Separator jSeparator2; private JToolBar.Separator jSeparator3; - private JToolBar.Separator jSeparator4; private JTextArea jTextArea1; private JFXPanel notificationsJFXPanel; + private JButton organicLayoutButton; private JPanel placeHolderPanel; private JButton snapshotButton; private JSplitPane splitPane; @@ -1132,8 +1093,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider } else if (event.getPreciseWheelRotation() > 0) { graphComponent.zoomOut(); } - - CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale())); } /** diff --git a/Core/src/org/sleuthkit/autopsy/images/resultset_next.png b/Core/src/org/sleuthkit/autopsy/images/resultset_next.png deleted file mode 100755 index e252606d3e..0000000000 Binary files a/Core/src/org/sleuthkit/autopsy/images/resultset_next.png and /dev/null differ diff --git a/Core/src/org/sleuthkit/autopsy/images/resultset_previous.png b/Core/src/org/sleuthkit/autopsy/images/resultset_previous.png deleted file mode 100755 index 18f9cc1094..0000000000 Binary files a/Core/src/org/sleuthkit/autopsy/images/resultset_previous.png and /dev/null differ diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/Back.java b/Core/src/org/sleuthkit/autopsy/timeline/actions/Back.java index 43c1a62933..8ee6aa3cd2 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/actions/Back.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/Back.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.timeline.TimeLineController; //TODO: This and the corresponding imageanalyzer action are identical except for the type of the controller... abstract something! -jm public class Back extends Action { - private static final Image BACK_IMAGE = new Image("/org/sleuthkit/autopsy/images/resultset_previous.png", 16, 16, true, true, true); // NON-NLS + private static final Image BACK_IMAGE = new Image("/org/sleuthkit/autopsy/timeline/images/arrow-180.png", 16, 16, true, true, true); // NON-NLS private final TimeLineController controller; diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/Forward.java b/Core/src/org/sleuthkit/autopsy/timeline/actions/Forward.java index 9f1d265d60..851731528b 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/actions/Forward.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/Forward.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.timeline.TimeLineController; //TODO: This and the corresponding imageanalyzer action are identical except for the type of the controller... abstract something! -jm public class Forward extends Action { - private static final Image FORWARD_IMAGE = new Image("/org/sleuthkit/autopsy/images/resultset_next.png", 16, 16, true, true, true); // NON-NLS + private static final Image FORWARD_IMAGE = new Image("/org/sleuthkit/autopsy/timeline/images/arrow.png", 16, 16, true, true, true); // NON-NLS private final TimeLineController controller;