Inital commit of back\forward code for Communications window

This commit is contained in:
Kelly Kelly 2019-03-25 18:31:01 -04:00
parent 9623734723
commit 2824a75a3b
12 changed files with 459 additions and 158 deletions

View File

@ -22,7 +22,6 @@ CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=Visualiz
CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize
VisualizationPanel.fitGraphButton.text= VisualizationPanel.fitGraphButton.text=
VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin. 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.zoomLabel.text=100%
VisualizationPanel.jLabel2.text=Zoom: VisualizationPanel.jLabel2.text=Zoom:
VisualizationPanel.fitZoomButton.toolTipText=fit visualization VisualizationPanel.fitZoomButton.toolTipText=fit visualization
@ -33,8 +32,7 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in
VisualizationPanel.zoomInButton.text= VisualizationPanel.zoomInButton.text=
VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.toolTipText=Zoom out
VisualizationPanel.zoomOutButton.text= VisualizationPanel.zoomOutButton.text=
VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.fastOrganicLayoutButton.text=Redraw
VisualizationPanel.organicLayoutButton.text=Organic VisualizationPanel.clearVizButton.text_1=Clear
VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.backButton.text_1=Undo
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.forwardButton.text=Redo
VisualizationPanel.clearVizButton.text_1=Clear Viz.

View File

@ -41,7 +41,6 @@ CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=Visualiz
CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize
VisualizationPanel.fitGraphButton.text= VisualizationPanel.fitGraphButton.text=
VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin. VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin.
VisualizationPanel.jLabel1.text=Layouts:
# {0} - layout name # {0} - layout name
VisualizationPanel.layoutFail.text={0} layout failed. Try a different layout. VisualizationPanel.layoutFail.text={0} layout failed. Try a different layout.
# {0} - layout name # {0} - layout name
@ -60,8 +59,7 @@ VisualizationPanel.zoomInButton.toolTipText=Zoom in
VisualizationPanel.zoomInButton.text= VisualizationPanel.zoomInButton.text=
VisualizationPanel.zoomOutButton.toolTipText=Zoom out VisualizationPanel.zoomOutButton.toolTipText=Zoom out
VisualizationPanel.zoomOutButton.text= VisualizationPanel.zoomOutButton.text=
VisualizationPanel.circleLayoutButton.text=Circle VisualizationPanel.fastOrganicLayoutButton.text=Redraw
VisualizationPanel.organicLayoutButton.text=Organic VisualizationPanel.clearVizButton.text_1=Clear
VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic VisualizationPanel.backButton.text_1=Undo
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical VisualizationPanel.forwardButton.text=Redo
VisualizationPanel.clearVizButton.text_1=Clear Viz.

View File

@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.EventBus; import com.google.common.eventbus.EventBus;
import java.util.Collection; import java.util.Collection;
import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.autopsy.communications.StateManager.CommunicationsState;
/** /**
* Provide the singleton EventBus. * Provide the singleton EventBus.
@ -82,4 +83,28 @@ final class CVTEvents {
this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances); this.accountDeviceInstances = ImmutableSet.copyOf(accountDeviceInstances);
} }
} }
static final class StateEvent {
private final CommunicationsState newState;
StateEvent(CommunicationsState newState) {
this.newState = newState;
}
public CommunicationsState getCommunicationsState(){
return newState;
}
}
static final class ZoomEvent {
private final double zoomValue;
ZoomEvent(double zoomValue) {
this.zoomValue = zoomValue;
}
public double getZoomValue(){
return zoomValue;
}
}
} }

View File

@ -74,6 +74,7 @@ public final class CVTTopComponent extends TopComponent {
CVTEvents.getCVTEventBus().register(this); CVTEvents.getCVTEventBus().register(this);
CVTEvents.getCVTEventBus().register(vizPanel); CVTEvents.getCVTEventBus().register(vizPanel);
CVTEvents.getCVTEventBus().register(accountsBrowser); CVTEvents.getCVTEventBus().register(accountsBrowser);
CVTEvents.getCVTEventBus().register(filtersPane);
} }
@Subscribe @Subscribe

View File

@ -19,12 +19,15 @@
package org.sleuthkit.autopsy.communications; package org.sleuthkit.autopsy.communications;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.Subscribe;
import java.awt.event.ItemListener; import java.awt.event.ItemListener;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Collection;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.logging.Level; import java.util.logging.Level;
@ -261,6 +264,75 @@ final public class FiltersPanel extends JPanel {
} }
} }
/**
* Given a list of subFilters, set the states of the panel controls
* accordingly.
*
* @param subFilters A list of subFilters
*/
public void setFilters(List<CommunicationsFilter.SubFilter> 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<String> 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) {
startDatePicker.setEnabled(dateFilter.isStartDateEnabled());
startCheckBox.setEnabled(dateFilter.isStartDateEnabled());
startDatePicker.setDate(LocalDate.ofEpochDay(dateFilter.getStartDate()));
endDatePicker.setEnabled(dateFilter.isEndDateEnabled());
endCheckBox.setEnabled(dateFilter.isEndDateEnabled());
endDatePicker.setDate(LocalDate.ofEpochDay(dateFilter.getEndDate()));
}
/**
* 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){
Collection<Account.Type> typeSet = typeFilter.getAccountTypes();
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. * This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always * WARNING: Do NOT modify this code. The content of this method is always
@ -508,7 +580,12 @@ final public class FiltersPanel extends JPanel {
validateFilters(); validateFilters();
} }
private CommunicationsFilter getFilter() { /**
* Get an instance of CommunicationsFilters base on the current panel state.
*
* @return an instance of CommunicationsFilter
*/
protected CommunicationsFilter getFilter() {
CommunicationsFilter commsFilter = new CommunicationsFilter(); CommunicationsFilter commsFilter = new CommunicationsFilter();
commsFilter.addAndFilter(getDeviceFilter()); commsFilter.addAndFilter(getDeviceFilter());
commsFilter.addAndFilter(getAccountTypeFilter()); commsFilter.addAndFilter(getAccountTypeFilter());
@ -553,9 +630,12 @@ final public class FiltersPanel extends JPanel {
*/ */
private DateRangeFilter getDateRangeFilter() { private DateRangeFilter getDateRangeFilter() {
ZoneId zone = Utils.getUserPreferredZoneId(); ZoneId zone = Utils.getUserPreferredZoneId();
long start = startDatePicker.isEnabled() ? startDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0;
long end = endDatePicker.isEnabled() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0; long value = startDatePicker.getDate().atStartOfDay(zone).toEpochSecond();
return new DateRangeFilter(start, end); return new DateRangeFilter(startDatePicker.isEnabled(),
startDatePicker.getDate().atStartOfDay(zone).toEpochSecond(),
endDatePicker.isEnabled(),
endDatePicker.getDate().atStartOfDay(zone).toEpochSecond());
} }
/** /**

View File

@ -57,7 +57,7 @@ class PinnedAccountModel {
* *
* @param accountDeviceInstances The accounts to unpin. * @param accountDeviceInstances The accounts to unpin.
*/ */
void unpinAccount(ImmutableSet<AccountDeviceInstanceKey> accountDeviceInstances) { void unpinAccount(Set<AccountDeviceInstanceKey> accountDeviceInstances) {
pinnedAccountDevices.removeAll(accountDeviceInstances); pinnedAccountDevices.removeAll(accountDeviceInstances);
} }
@ -68,7 +68,7 @@ class PinnedAccountModel {
* *
* @param accountDeviceInstances The accounts to pin. * @param accountDeviceInstances The accounts to pin.
*/ */
void pinAccount(ImmutableSet<AccountDeviceInstanceKey> accountDeviceInstances) { void pinAccount(Set<AccountDeviceInstanceKey> accountDeviceInstances) {
pinnedAccountDevices.addAll(accountDeviceInstances); pinnedAccountDevices.addAll(accountDeviceInstances);
} }
@ -86,7 +86,7 @@ class PinnedAccountModel {
pinnedAccountDevices.clear(); pinnedAccountDevices.clear();
} }
Iterable<AccountDeviceInstanceKey> getPinnedAccounts() { ImmutableSet<AccountDeviceInstanceKey> getPinnedAccounts() {
return ImmutableSet.copyOf(pinnedAccountDevices); return ImmutableSet.copyOf(pinnedAccountDevices);
} }

View File

@ -0,0 +1,188 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications;
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;
/**
* 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<CommunicationsState> 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<AccountDeviceInstanceKey> pinnedList = new HashSet<>();
pinnedList.addAll(pinEvent.getAccountDeviceInstances());
historyManager.advance(new CommunicationsState(comFilter.getAndFilters(), pinnedList, -1));
} else {
HashSet<AccountDeviceInstanceKey> 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<AccountDeviceInstanceKey> 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<SubFilter> communcationFilters;
private final Set<AccountDeviceInstanceKey> pinnedList;
private double zoomValue = -1;
/**
* 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<SubFilter> communcationFilters, Set<AccountDeviceInstanceKey> 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<AccountDeviceInstanceKey> getPinnedList(){
return pinnedList;
}
/**
* Returns a list of communication SubFilters.
*
* @return List of SubFilter
*/
public List<SubFilter> getCommunicationsFilters(){
return communcationFilters;
}
/**
* Return the value for the % zoom.
*
* @return double value % zoom or -1 if zoom did not change
*/
public double getZoomValue() {
return zoomValue;
}
}
}

View File

@ -11,7 +11,7 @@
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-93,0,0,3,71"/> <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-127,0,0,5,3"/>
</AuxValues> </AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
@ -49,9 +49,9 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace pref="71" max="32767" attributes="0"/> <EmptySpace pref="280" max="32767" attributes="0"/>
<Component id="jTextArea1" min="-2" pref="424" max="-2" attributes="0"/> <Component id="jTextArea1" min="-2" pref="424" max="-2" attributes="0"/>
<EmptySpace pref="248" max="32767" attributes="0"/> <EmptySpace pref="455" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -92,35 +92,29 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="clearVizButton" min="-2" max="-2" attributes="0"/> <Component id="clearVizButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="backButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="forwardButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="fastOrganicLayoutButton" min="-2" max="-2" attributes="0"/> <Component id="fastOrganicLayoutButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="organicLayoutButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="hierarchyLayoutButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="circleLayoutButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/> <Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/> <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="zoomLabel" min="-2" max="-2" attributes="0"/> <Component id="zoomLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="zoomOutButton" min="-2" pref="32" max="-2" attributes="0"/> <Component id="zoomOutButton" min="-2" pref="32" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="zoomInButton" min="-2" pref="32" max="-2" attributes="0"/> <Component id="zoomInButton" min="-2" pref="32" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="zoomActualButton" min="-2" pref="33" max="-2" attributes="0"/> <Component id="zoomActualButton" min="-2" pref="33" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="fitZoomButton" min="-2" pref="32" max="-2" attributes="0"/> <Component id="fitZoomButton" min="-2" pref="32" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/> <EmptySpace pref="157" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -129,12 +123,7 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/> <EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0"> <Group type="103" groupAlignment="2" attributes="0">
<Component id="jLabel1" alignment="2" min="-2" pref="25" max="-2" attributes="0"/>
<Component id="hierarchyLayoutButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="fastOrganicLayoutButton" alignment="2" min="-2" max="-2" attributes="0"/> <Component id="fastOrganicLayoutButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="organicLayoutButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="circleLayoutButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator1" alignment="2" max="32767" attributes="0"/>
<Component id="zoomOutButton" alignment="2" min="-2" max="-2" attributes="0"/> <Component id="zoomOutButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="zoomInButton" alignment="2" max="32767" attributes="0"/> <Component id="zoomInButton" alignment="2" max="32767" attributes="0"/>
<Component id="zoomActualButton" alignment="2" max="32767" attributes="0"/> <Component id="zoomActualButton" alignment="2" max="32767" attributes="0"/>
@ -143,6 +132,8 @@
<Component id="zoomLabel" alignment="2" min="-2" max="-2" attributes="0"/> <Component id="zoomLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="clearVizButton" alignment="2" min="-2" max="-2" attributes="0"/> <Component id="clearVizButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator2" alignment="2" max="32767" attributes="0"/> <Component id="jSeparator2" alignment="2" max="32767" attributes="0"/>
<Component id="backButton" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="forwardButton" alignment="2" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/> <EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
</Group> </Group>
@ -150,23 +141,6 @@
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="hierarchyLayoutButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.hierarchyLayoutButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="fastOrganicLayoutButton"> <Component class="javax.swing.JButton" name="fastOrganicLayoutButton">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -177,31 +151,6 @@
<Property name="verticalTextPosition" type="int" value="3"/> <Property name="verticalTextPosition" type="int" value="3"/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JButton" name="organicLayoutButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.organicLayoutButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="circleLayoutButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.circleLayoutButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
</Component>
<Component class="javax.swing.JToolBar$Separator" name="jSeparator1">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="zoomOutButton"> <Component class="javax.swing.JButton" name="zoomOutButton">
<Properties> <Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
@ -310,6 +259,26 @@
<Property name="orientation" type="int" value="1"/> <Property name="orientation" type="int" value="1"/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JButton" name="backButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.backButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="backButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="forwardButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.forwardButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="forwardButtonActionPerformed"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javafx.embed.swing.JFXPanel" name="notificationsJFXPanel"> <Container class="javafx.embed.swing.JFXPanel" name="notificationsJFXPanel">

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.communications; package org.sleuthkit.autopsy.communications;
import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; import com.mxgraph.layout.hierarchical.mxHierarchicalLayout;
import com.mxgraph.layout.mxCircleLayout; import com.mxgraph.layout.mxCircleLayout;
@ -40,7 +41,6 @@ import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxGraphView; import com.mxgraph.view.mxGraphView;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
import java.awt.Frame; import java.awt.Frame;
@ -51,6 +51,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException; import java.beans.PropertyVetoException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.Arrays; import java.util.Arrays;
@ -100,6 +101,8 @@ import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
import org.sleuthkit.datamodel.CommunicationsFilter; import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager; import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG;
import static org.sleuthkit.datamodel.Relationship.Type.MESSAGE;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -148,6 +151,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
private final Map<NamedGraphLayout, JButton> layoutButtons = new HashMap<>(); private final Map<NamedGraphLayout, JButton> layoutButtons = new HashMap<>();
private NamedGraphLayout currentLayout; private NamedGraphLayout currentLayout;
private final StateManager stateManager;
@NbBundle.Messages("VisalizationPanel.paintingError=Problem painting visualization.") @NbBundle.Messages("VisalizationPanel.paintingError=Problem painting visualization.")
public VisualizationPanel() { public VisualizationPanel() {
initComponents(); initComponents();
@ -226,10 +231,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
graph.getView().addListener(mxEvent.UNDO, undoListener); graph.getView().addListener(mxEvent.UNDO, undoListener);
FastOrganicLayoutImpl fastOrganicLayout = new FastOrganicLayoutImpl(graph); 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 //local method to configure layout buttons
BiConsumer<JButton, NamedGraphLayout> configure = (layoutButton, layout) -> { BiConsumer<JButton, NamedGraphLayout> configure = (layoutButton, layout) -> {
@ -237,12 +238,13 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
layoutButton.addActionListener(event -> applyLayout(layout)); layoutButton.addActionListener(event -> applyLayout(layout));
}; };
//configure layout buttons. //configure layout buttons.
configure.accept(circleLayoutButton, circleLayout);
configure.accept(organicLayoutButton, organicLayout);
configure.accept(fastOrganicLayoutButton, fastOrganicLayout); configure.accept(fastOrganicLayoutButton, fastOrganicLayout);
configure.accept(hierarchyLayoutButton, hierarchyLayout);
applyLayout(fastOrganicLayout); applyLayout(fastOrganicLayout);
stateManager = new StateManager(pinnedAccountModel);
setStateButtonsEnabled();
} }
@Override @Override
@ -271,6 +273,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
rebuildGraph(); rebuildGraph();
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
setStateButtonsEnabled();
} }
@Subscribe @Subscribe
@ -283,6 +287,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
rebuildGraph(); rebuildGraph();
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
setStateButtonsEnabled();
} }
@Subscribe @Subscribe
@ -293,6 +299,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
rebuildGraph(); rebuildGraph();
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
setStateButtonsEnabled();
} }
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
@ -334,9 +342,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
try { try {
commsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager(); commsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); //NON-NLS
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Can't get CommunicationsManager when there is no case open.", ex); logger.log(Level.SEVERE, "Can't get CommunicationsManager when there is no case open.", ex); //NON-NLS
} }
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> { Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> {
@ -353,7 +361,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
try { try {
commsManager = currentCase.getSleuthkitCase().getCommunicationsManager(); commsManager = currentCase.getSleuthkitCase().getCommunicationsManager();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); logger.log(Level.SEVERE, "Error getting CommunicationsManager for the current case.", ex); //NON-NLS
} }
} }
}); });
@ -373,12 +381,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
placeHolderPanel = new JPanel(); placeHolderPanel = new JPanel();
jTextArea1 = new JTextArea(); jTextArea1 = new JTextArea();
toolbar = new JPanel(); toolbar = new JPanel();
jLabel1 = new JLabel();
hierarchyLayoutButton = new JButton();
fastOrganicLayoutButton = new JButton(); fastOrganicLayoutButton = new JButton();
organicLayoutButton = new JButton();
circleLayoutButton = new JButton();
jSeparator1 = new JToolBar.Separator();
zoomOutButton = new JButton(); zoomOutButton = new JButton();
zoomInButton = new JButton(); zoomInButton = new JButton();
zoomActualButton = new JButton(); zoomActualButton = new JButton();
@ -387,6 +390,8 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
zoomLabel = new JLabel(); zoomLabel = new JLabel();
clearVizButton = new JButton(); clearVizButton = new JButton();
jSeparator2 = new JToolBar.Separator(); jSeparator2 = new JToolBar.Separator();
backButton = new JButton();
forwardButton = new JButton();
notificationsJFXPanel = new JFXPanel(); notificationsJFXPanel = new JFXPanel();
setLayout(new BorderLayout()); setLayout(new BorderLayout());
@ -406,9 +411,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
placeHolderPanel.setLayout(placeHolderPanelLayout); placeHolderPanel.setLayout(placeHolderPanelLayout);
placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING) placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
.add(placeHolderPanelLayout.createSequentialGroup() .add(placeHolderPanelLayout.createSequentialGroup()
.addContainerGap(71, Short.MAX_VALUE) .addContainerGap(280, Short.MAX_VALUE)
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE) .add(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE)
.addContainerGap(248, Short.MAX_VALUE)) .addContainerGap(455, Short.MAX_VALUE))
); );
placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING) placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
.add(placeHolderPanelLayout.createSequentialGroup() .add(placeHolderPanelLayout.createSequentialGroup()
@ -419,30 +424,11 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER); borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
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.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.fastOrganicLayoutButton.text")); // NOI18N
fastOrganicLayoutButton.setFocusable(false); fastOrganicLayoutButton.setFocusable(false);
fastOrganicLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER); fastOrganicLayoutButton.setHorizontalTextPosition(SwingConstants.CENTER);
fastOrganicLayoutButton.setVerticalTextPosition(SwingConstants.BOTTOM); 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.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.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.text")); // NOI18N
zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N zoomOutButton.setToolTipText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.zoomOutButton.toolTipText")); // NOI18N
@ -505,25 +491,33 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
jSeparator2.setOrientation(SwingConstants.VERTICAL); jSeparator2.setOrientation(SwingConstants.VERTICAL);
backButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.backButton.text_1")); // NOI18N
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
backButtonActionPerformed(evt);
}
});
forwardButton.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.forwardButton.text")); // NOI18N
forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
forwardButtonActionPerformed(evt);
}
});
GroupLayout toolbarLayout = new GroupLayout(toolbar); GroupLayout toolbarLayout = new GroupLayout(toolbar);
toolbar.setLayout(toolbarLayout); toolbar.setLayout(toolbarLayout);
toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) toolbarLayout.setHorizontalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
.add(toolbarLayout.createSequentialGroup() .add(toolbarLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.add(clearVizButton) .add(clearVizButton)
.add(3, 3, 3) .addPreferredGap(LayoutStyle.RELATED)
.add(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) .add(backButton)
.add(5, 5, 5) .addPreferredGap(LayoutStyle.RELATED)
.add(jLabel1) .add(forwardButton)
.addPreferredGap(LayoutStyle.RELATED) .addPreferredGap(LayoutStyle.RELATED)
.add(fastOrganicLayoutButton) .add(fastOrganicLayoutButton)
.addPreferredGap(LayoutStyle.RELATED) .addPreferredGap(LayoutStyle.RELATED)
.add(organicLayoutButton)
.addPreferredGap(LayoutStyle.RELATED)
.add(hierarchyLayoutButton)
.addPreferredGap(LayoutStyle.RELATED)
.add(circleLayoutButton)
.addPreferredGap(LayoutStyle.RELATED)
.add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) .add(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED) .addPreferredGap(LayoutStyle.RELATED)
.add(jLabel2) .add(jLabel2)
@ -537,18 +531,13 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
.add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) .add(zoomActualButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.RELATED) .addPreferredGap(LayoutStyle.RELATED)
.add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE) .add(fitZoomButton, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(157, Short.MAX_VALUE))
); );
toolbarLayout.setVerticalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING) toolbarLayout.setVerticalGroup(toolbarLayout.createParallelGroup(GroupLayout.LEADING)
.add(toolbarLayout.createSequentialGroup() .add(toolbarLayout.createSequentialGroup()
.add(3, 3, 3) .add(3, 3, 3)
.add(toolbarLayout.createParallelGroup(GroupLayout.CENTER) .add(toolbarLayout.createParallelGroup(GroupLayout.CENTER)
.add(jLabel1, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
.add(hierarchyLayoutButton)
.add(fastOrganicLayoutButton) .add(fastOrganicLayoutButton)
.add(organicLayoutButton)
.add(circleLayoutButton)
.add(jSeparator1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(zoomOutButton) .add(zoomOutButton)
.add(zoomInButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(zoomInButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(zoomActualButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
@ -556,7 +545,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
.add(jLabel2) .add(jLabel2)
.add(zoomLabel) .add(zoomLabel)
.add(clearVizButton) .add(clearVizButton)
.add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .add(jSeparator2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(backButton)
.add(forwardButton))
.add(3, 3, 3)) .add(3, 3, 3))
); );
@ -574,14 +565,17 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
private void zoomActualButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomActualButtonActionPerformed private void zoomActualButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomActualButtonActionPerformed
graphComponent.zoomActual(); graphComponent.zoomActual();
CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale()));
}//GEN-LAST:event_zoomActualButtonActionPerformed }//GEN-LAST:event_zoomActualButtonActionPerformed
private void zoomInButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomInButtonActionPerformed private void zoomInButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomInButtonActionPerformed
graphComponent.zoomIn(); graphComponent.zoomIn();
CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale()));
}//GEN-LAST:event_zoomInButtonActionPerformed }//GEN-LAST:event_zoomInButtonActionPerformed
private void zoomOutButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomOutButtonActionPerformed private void zoomOutButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_zoomOutButtonActionPerformed
graphComponent.zoomOut(); graphComponent.zoomOut();
CVTEvents.getCVTEventBus().post(new CVTEvents.ZoomEvent(graph.getView().getScale()));
}//GEN-LAST:event_zoomOutButtonActionPerformed }//GEN-LAST:event_zoomOutButtonActionPerformed
/** /**
@ -638,15 +632,65 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
} }
private void clearVizButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearVizButtonActionPerformed private void clearVizButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearVizButtonActionPerformed
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 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();
graph.getModel().beginUpdate(); graph.getModel().beginUpdate();
pinnedAccountModel.clear(); graph.resetGraph();
graph.clear();
if(newState.getPinnedList() != null) {
pinnedAccountModel.pinAccount(newState.getPinnedList());
} else {
pinnedAccountModel.clear();
}
currentFilter = new CommunicationsFilter();
currentFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(
ImmutableSet.of(CALL_LOG, MESSAGE)));
newState.getCommunicationsFilters().forEach(filter -> {
currentFilter.addAndFilter(filter);
});
rebuildGraph(); rebuildGraph();
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
setCursor(Cursor.getDefaultCursor());
}//GEN-LAST:event_clearVizButtonActionPerformed fitGraph();
}
private void setStateButtonsEnabled() {
backButton.setEnabled(stateManager.canRetreat());
forwardButton.setEnabled(stateManager.canAdvance());
}
private void fitGraph() { private void fitGraph() {
graphComponent.zoomTo(1, true); graphComponent.zoomTo(1, true);
@ -677,19 +721,16 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private JButton backButton;
private JPanel borderLayoutPanel; private JPanel borderLayoutPanel;
private JButton circleLayoutButton;
private JButton clearVizButton; private JButton clearVizButton;
private JButton fastOrganicLayoutButton; private JButton fastOrganicLayoutButton;
private JButton fitZoomButton; private JButton fitZoomButton;
private JButton hierarchyLayoutButton; private JButton forwardButton;
private JLabel jLabel1;
private JLabel jLabel2; private JLabel jLabel2;
private JToolBar.Separator jSeparator1;
private JToolBar.Separator jSeparator2; private JToolBar.Separator jSeparator2;
private JTextArea jTextArea1; private JTextArea jTextArea1;
private JFXPanel notificationsJFXPanel; private JFXPanel notificationsJFXPanel;
private JButton organicLayoutButton;
private JPanel placeHolderPanel; private JPanel placeHolderPanel;
private JSplitPane splitPane; private JSplitPane splitPane;
private JPanel toolbar; private JPanel toolbar;

View File

@ -34,6 +34,7 @@ KeywordSearchIngestModule.startupMessage.failedToGetIndexSchema=Failed to get sc
KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found. KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found.
KeywordSearchResultFactory.query.exception.msg=Could not perform the query KeywordSearchResultFactory.query.exception.msg=Could not perform the query
OpenIDE-Module-Display-Category=Ingest Module OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found.
OpenIDE-Module-Name=KeywordSearch OpenIDE-Module-Name=KeywordSearch
OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Name_KeywordSearchOptions=Keyword Search

View File

@ -59,7 +59,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files
ExtractZone_Restricted=Restricted Sites Zone ExtractZone_Restricted=Restricted Sites Zone
ExtractZone_Trusted=Trusted Sites Zone ExtractZone_Trusted=Trusted Sites Zone
OpenIDE-Module-Display-Category=Ingest Module OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\n\The module currently supports Windows only disk images.\n\The plugin is also fully functional when deployed on Windows version of Autopsy.
OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Name=RecentActivity
OpenIDE-Module-Short-Description=Recent Activity finder ingest module OpenIDE-Module-Short-Description=Recent Activity finder ingest module
Chrome.moduleName=Chrome Chrome.moduleName=Chrome
@ -188,7 +188,7 @@ SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}.
SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine
SearchEngineURLQueryAnalyzer.engineName.none=NONE SearchEngineURLQueryAnalyzer.engineName.none=NONE
SearchEngineURLQueryAnalyzer.domainSubStr.none=NONE SearchEngineURLQueryAnalyzer.domainSubStr.none=NONE
SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\ncount: {2}\nSplit Tokens: \n{3} SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\n\count: {2}\nSplit Tokens: \n{3}
SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=RecentActivity SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=RecentActivity
SearchEngineURLQueryAnalyzer.parentModuleName=Recent Activity SearchEngineURLQueryAnalyzer.parentModuleName=Recent Activity
UsbDeviceIdMapper.parseAndLookup.text=Product: {0} UsbDeviceIdMapper.parseAndLookup.text=Product: {0}