mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +00:00
Merge pull request #3436 from millmanorama/cancellable-graph-loading
Cancellable graph loading
This commit is contained in:
commit
4ba29921ae
@ -24,7 +24,6 @@ VisualizationPanel.jButton6.text=Hierarchy
|
|||||||
VisualizationPanel.jButton7.text=Circle
|
VisualizationPanel.jButton7.text=Circle
|
||||||
VisualizationPanel.jButton8.text=Organic
|
VisualizationPanel.jButton8.text=Organic
|
||||||
VisualizationPanel.fitGraphButton.text=
|
VisualizationPanel.fitGraphButton.text=
|
||||||
VisualizationPanel.statusLabel.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.jLabel1.text=Layouts:
|
||||||
VisualizationPanel.fitZoomButton.text=
|
VisualizationPanel.fitZoomButton.text=
|
||||||
|
@ -40,6 +40,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
@ -51,25 +52,25 @@ import org.sleuthkit.datamodel.CommunicationsManager;
|
|||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
final class mxGraphImpl extends mxGraph {
|
final class CommunicationsGraph extends mxGraph {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(CommunicationsGraph.class.getName());
|
||||||
|
private static final URL MARKER_PIN_URL = CommunicationsGraph.class.getResource("/org/sleuthkit/autopsy/communications/images/marker--pin.png");
|
||||||
|
private static final URL LOCK_URL = CommunicationsGraph.class.getResource("/org/sleuthkit/autopsy/communications/images/lock_large_locked.png");
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(mxGraphImpl.class.getName());
|
|
||||||
private static final URL MARKER_PIN_URL = mxGraphImpl.class.getResource("/org/sleuthkit/autopsy/communications/images/marker--pin.png");
|
|
||||||
private static final URL LOCK_URL = mxGraphImpl.class.getResource("/org/sleuthkit/autopsy/communications/images/lock_large_locked.png");
|
|
||||||
/**
|
/**
|
||||||
* mustache.java template
|
* mustache.java template
|
||||||
*/
|
*/
|
||||||
private final static Mustache labelMustache;
|
private final static Mustache labelMustache;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// String labelTemplatePath = "/org/sleuthkit/autopsy/communications/Vertex_Label_template.html";
|
InputStream templateStream = CommunicationsGraph.class.getResourceAsStream("/org/sleuthkit/autopsy/communications/Vertex_Label_template.html");
|
||||||
InputStream templateStream = mxGraphImpl.class.getResourceAsStream("/org/sleuthkit/autopsy/communications/Vertex_Label_template.html");
|
|
||||||
labelMustache = new DefaultMustacheFactory().compile(new InputStreamReader(templateStream), "Vertex_Label");
|
labelMustache = new DefaultMustacheFactory().compile(new InputStreamReader(templateStream), "Vertex_Label");
|
||||||
}
|
}
|
||||||
|
|
||||||
static final private mxStylesheet mxStylesheet = new mxStylesheet();
|
static final private mxStylesheet mxStylesheet = new mxStylesheet();
|
||||||
private final HashSet<AccountDeviceInstanceKey> pinnedAccountDevices = new HashSet<>();
|
private final Set<AccountDeviceInstanceKey> pinnedAccountDevices = new HashSet<>();
|
||||||
private final HashSet<mxCell> lockedVertices = new HashSet<>();
|
private final Set<mxCell> lockedVertices = new HashSet<>();
|
||||||
|
|
||||||
private final Map<String, mxCell> nodeMap = new HashMap<>();
|
private final Map<String, mxCell> nodeMap = new HashMap<>();
|
||||||
private final Multimap<Content, mxCell> edgeMap = MultimapBuilder.hashKeys().hashSetValues().build();
|
private final Multimap<Content, mxCell> edgeMap = MultimapBuilder.hashKeys().hashSetValues().build();
|
||||||
@ -87,7 +88,7 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
mxStylesheet.getDefaultEdgeStyle().put(mxConstants.STYLE_STARTARROW, mxConstants.NONE);
|
mxStylesheet.getDefaultEdgeStyle().put(mxConstants.STYLE_STARTARROW, mxConstants.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mxGraphImpl() {
|
CommunicationsGraph() {
|
||||||
super(mxStylesheet);
|
super(mxStylesheet);
|
||||||
setAutoSizeCells(true);
|
setAutoSizeCells(true);
|
||||||
setCellsCloneable(false);
|
setCellsCloneable(false);
|
||||||
@ -129,7 +130,7 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
|
|
||||||
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
|
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
|
||||||
scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5));
|
scopes.put("size", Math.round(Math.log(adiKey.getMessageCount()) + 5));
|
||||||
scopes.put("iconFileName", mxGraphImpl.class.getResource("/org/sleuthkit/autopsy/communications/images/"
|
scopes.put("iconFileName", CommunicationsGraph.class.getResource("/org/sleuthkit/autopsy/communications/images/"
|
||||||
+ Utils.getIconFileName(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
|
+ Utils.getIconFileName(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
|
||||||
scopes.put("pinned", pinnedAccountDevices.contains(adiKey));
|
scopes.put("pinned", pinnedAccountDevices.contains(adiKey));
|
||||||
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
|
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
|
||||||
@ -155,7 +156,7 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
|
|
||||||
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
|
scopes.put("accountName", adiKey.getAccountDeviceInstance().getAccount().getTypeSpecificID());
|
||||||
scopes.put("size", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5));
|
scopes.put("size", 12);// Math.round(Math.log(adiKey.getMessageCount()) + 5));
|
||||||
scopes.put("iconFileName", mxGraphImpl.class.getResource("/org/sleuthkit/autopsy/communications/images/"
|
scopes.put("iconFileName", CommunicationsGraph.class.getResource("/org/sleuthkit/autopsy/communications/images/"
|
||||||
+ Utils.getIconFileName(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
|
+ Utils.getIconFileName(adiKey.getAccountDeviceInstance().getAccount().getAccountType())));
|
||||||
scopes.put("pinned", pinnedAccountDevices.contains(adiKey));
|
scopes.put("pinned", pinnedAccountDevices.contains(adiKey));
|
||||||
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
|
scopes.put("MARKER_PIN_URL", MARKER_PIN_URL);
|
||||||
@ -264,7 +265,6 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
if (edgesBetween.length == 0) {
|
if (edgesBetween.length == 0) {
|
||||||
final String edgeName = vertex1.getId() + " <-> " + vertex2.getId();
|
final String edgeName = vertex1.getId() + " <-> " + vertex2.getId();
|
||||||
final HashSet<Content> hashSet = new HashSet<>(relSources);
|
final HashSet<Content> hashSet = new HashSet<>(relSources);
|
||||||
// edgeMap.put(relSource, edge);
|
|
||||||
edge = (mxCell) insertEdge(getDefaultParent(), edgeName, hashSet, vertex1, vertex2,
|
edge = (mxCell) insertEdge(getDefaultParent(), edgeName, hashSet, vertex1, vertex2,
|
||||||
"strokeWidth=" + (Math.log(hashSet.size()) + 1));
|
"strokeWidth=" + (Math.log(hashSet.size()) + 1));
|
||||||
} else {
|
} else {
|
||||||
@ -304,11 +304,13 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
this.currentFilter = currentFilter;
|
this.currentFilter = currentFilter;
|
||||||
this.commsManager = commsManager;
|
this.commsManager = commsManager;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Exception {
|
protected Void doInBackground() throws Exception {
|
||||||
progress.start("Loading accounts", pinnedAccountDevices.size());
|
progress.start("Loading accounts");
|
||||||
|
// progress.switchToDeterminate("Loading accounts", 0,pinnedAccountDevices.size());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
try {
|
try {
|
||||||
/**
|
/**
|
||||||
@ -316,6 +318,9 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
*/
|
*/
|
||||||
Set<AccountDeviceInstanceKey> relatedAccounts = new HashSet<>();
|
Set<AccountDeviceInstanceKey> relatedAccounts = new HashSet<>();
|
||||||
for (AccountDeviceInstanceKey adiKey : pinnedAccountDevices) {
|
for (AccountDeviceInstanceKey adiKey : pinnedAccountDevices) {
|
||||||
|
if (isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
List<AccountDeviceInstance> relatedAccountDeviceInstances =
|
List<AccountDeviceInstance> relatedAccountDeviceInstances =
|
||||||
commsManager.getRelatedAccountDeviceInstances(adiKey.getAccountDeviceInstance(), currentFilter);
|
commsManager.getRelatedAccountDeviceInstances(adiKey.getAccountDeviceInstance(), currentFilter);
|
||||||
relatedAccounts.add(adiKey);
|
relatedAccounts.add(adiKey);
|
||||||
@ -336,7 +341,9 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
for (i = 0; i < relatedAccountsList.size(); i++) {
|
for (i = 0; i < relatedAccountsList.size(); i++) {
|
||||||
AccountDeviceInstanceKey adiKey1 = relatedAccountsList.get(i);
|
AccountDeviceInstanceKey adiKey1 = relatedAccountsList.get(i);
|
||||||
for (int j = i; j < relatedAccountsList.size(); j++) {
|
for (int j = i; j < relatedAccountsList.size(); j++) {
|
||||||
|
if (isCancelled()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
AccountDeviceInstanceKey adiKey2 = relatedAccountsList.get(j);
|
AccountDeviceInstanceKey adiKey2 = relatedAccountsList.get(j);
|
||||||
List<Content> relationships = commsManager.getRelationshipSources(
|
List<Content> relationships = commsManager.getRelationshipSources(
|
||||||
adiKey1.getAccountDeviceInstance(),
|
adiKey1.getAccountDeviceInstance(),
|
||||||
@ -353,6 +360,7 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
logger.log(Level.SEVERE, "Error", tskCoreException);
|
logger.log(Level.SEVERE, "Error", tskCoreException);
|
||||||
} finally {
|
} finally {
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,6 +371,8 @@ final class mxGraphImpl extends mxGraph {
|
|||||||
get();
|
get();
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
logger.log(Level.SEVERE, "Error building graph visualization. ", ex);
|
logger.log(Level.SEVERE, "Error building graph visualization. ", ex);
|
||||||
|
} catch (CancellationException ex) {
|
||||||
|
logger.log(Level.INFO, "Graph visualization cancelled");
|
||||||
} finally {
|
} finally {
|
||||||
progress.finish();
|
progress.finish();
|
||||||
}
|
}
|
@ -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,1,-7,0,0,3,-119"/>
|
<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,1,-1,0,0,3,-123"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
@ -38,65 +38,6 @@
|
|||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JToolBar" name="jToolBar2">
|
|
||||||
<Properties>
|
|
||||||
<Property name="floatable" type="boolean" value="false"/>
|
|
||||||
<Property name="rollover" type="boolean" value="true"/>
|
|
||||||
</Properties>
|
|
||||||
<Constraints>
|
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
|
||||||
<BorderConstraints direction="Last"/>
|
|
||||||
</Constraint>
|
|
||||||
</Constraints>
|
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
|
|
||||||
<SubComponents>
|
|
||||||
<Component class="javax.swing.JLabel" name="statusLabel">
|
|
||||||
<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.statusLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Container class="javax.swing.JPanel" name="progresPanel">
|
|
||||||
<Properties>
|
|
||||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
|
||||||
<Dimension value="[0, 20]"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="name" type="java.lang.String" value="" noResource="true"/>
|
|
||||||
</Properties>
|
|
||||||
|
|
||||||
<Layout>
|
|
||||||
<DimensionLayout dim="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="1" attributes="0">
|
|
||||||
<EmptySpace min="0" pref="447" max="32767" attributes="0"/>
|
|
||||||
<Component id="progressBar" min="-2" pref="350" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
<DimensionLayout dim="1">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="1" attributes="0">
|
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
|
||||||
<Component id="progressBar" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</DimensionLayout>
|
|
||||||
</Layout>
|
|
||||||
<SubComponents>
|
|
||||||
<Component class="javax.swing.JProgressBar" name="progressBar">
|
|
||||||
<Properties>
|
|
||||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
|
||||||
<Dimension value="[200, 14]"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="stringPainted" type="boolean" value="true"/>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
</SubComponents>
|
|
||||||
</Container>
|
|
||||||
<Container class="javax.swing.JPanel" name="placeHolderPanel">
|
<Container class="javax.swing.JPanel" name="placeHolderPanel">
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||||
@ -108,18 +49,18 @@
|
|||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<EmptySpace pref="213" max="32767" attributes="0"/>
|
<EmptySpace pref="208" max="32767" attributes="0"/>
|
||||||
<Component id="jTextArea1" min="-2" pref="372" max="-2" attributes="0"/>
|
<Component id="jTextArea1" min="-2" pref="372" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="214" max="32767" attributes="0"/>
|
<EmptySpace pref="209" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<EmptySpace pref="200" max="32767" attributes="0"/>
|
<EmptySpace pref="213" max="32767" attributes="0"/>
|
||||||
<Component id="jTextArea1" min="-2" pref="43" max="-2" attributes="0"/>
|
<Component id="jTextArea1" min="-2" pref="43" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="200" max="32767" attributes="0"/>
|
<EmptySpace pref="214" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
@ -34,17 +34,19 @@ import com.mxgraph.util.mxEventObject;
|
|||||||
import com.mxgraph.util.mxEventSource;
|
import com.mxgraph.util.mxEventSource;
|
||||||
import com.mxgraph.util.mxPoint;
|
import com.mxgraph.util.mxPoint;
|
||||||
import com.mxgraph.util.mxRectangle;
|
import com.mxgraph.util.mxRectangle;
|
||||||
|
import com.mxgraph.util.mxUndoManager;
|
||||||
|
import com.mxgraph.util.mxUndoableEdit;
|
||||||
import com.mxgraph.view.mxGraph;
|
import com.mxgraph.view.mxGraph;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Frame;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseAdapter;
|
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;
|
||||||
@ -52,15 +54,16 @@ import static java.util.Collections.singleton;
|
|||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JProgressBar;
|
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
@ -78,7 +81,8 @@ import org.openide.util.lookup.ProxyLookup;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE;
|
import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.progress.ProgressIndicator;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
|
import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
|
||||||
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
||||||
import org.sleuthkit.datamodel.CommunicationsFilter;
|
import org.sleuthkit.datamodel.CommunicationsFilter;
|
||||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||||
@ -94,6 +98,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* CVTTopComponent when this tab is active allowing for context sensitive
|
* CVTTopComponent when this tab is active allowing for context sensitive
|
||||||
* actions to work correctly.
|
* actions to work correctly.
|
||||||
*/
|
*/
|
||||||
|
@NbBundle.Messages("VisualizationPanel.cancelButton.text=Cancel")
|
||||||
final public class VisualizationPanel extends JPanel implements Lookup.Provider {
|
final public class VisualizationPanel extends JPanel implements Lookup.Provider {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -110,27 +115,35 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
static final private ImageIcon lockIcon =
|
static final private ImageIcon lockIcon =
|
||||||
new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/lock_large_locked.png"));
|
new ImageIcon(VisualizationPanel.class.getResource(BASE_IMAGE_PATH + "/lock_large_locked.png"));
|
||||||
|
|
||||||
|
private static final String CANCEL = Bundle.VisualizationPanel_cancelButton_text();
|
||||||
|
|
||||||
private final ExplorerManager vizEM = new ExplorerManager();
|
private final ExplorerManager vizEM = new ExplorerManager();
|
||||||
private final ExplorerManager gacEM = new ExplorerManager();
|
private final ExplorerManager gacEM = new ExplorerManager();
|
||||||
private final ProxyLookup proxyLookup = new ProxyLookup(
|
private final ProxyLookup proxyLookup = new ProxyLookup(
|
||||||
ExplorerUtils.createLookup(gacEM, getActionMap()),
|
ExplorerUtils.createLookup(gacEM, getActionMap()),
|
||||||
ExplorerUtils.createLookup(vizEM, getActionMap()));
|
ExplorerUtils.createLookup(vizEM, getActionMap()));
|
||||||
|
|
||||||
private final mxGraphComponent graphComponent;
|
private Frame windowAncestor;
|
||||||
private final mxGraphImpl graph;
|
|
||||||
|
|
||||||
private CommunicationsManager commsManager;
|
private CommunicationsManager commsManager;
|
||||||
private CommunicationsFilter currentFilter;
|
private CommunicationsFilter currentFilter;
|
||||||
|
|
||||||
|
private final mxGraphComponent graphComponent;
|
||||||
|
private final CommunicationsGraph graph;
|
||||||
|
|
||||||
|
protected mxUndoManager undoManager = new mxUndoManager();
|
||||||
private final mxRubberband rubberband;
|
private final mxRubberband rubberband;
|
||||||
private final mxFastOrganicLayout fastOrganicLayout;
|
private final mxFastOrganicLayout fastOrganicLayout;
|
||||||
private final mxCircleLayout circleLayout;
|
private final mxCircleLayout circleLayout;
|
||||||
private final mxOrganicLayout organicLayout;
|
private final mxOrganicLayout organicLayout;
|
||||||
private final mxHierarchicalLayout hierarchicalLayout;
|
private final mxHierarchicalLayout hierarchicalLayout;
|
||||||
|
|
||||||
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
private SwingWorker<?, ?> worker;
|
private SwingWorker<?, ?> worker;
|
||||||
|
|
||||||
public VisualizationPanel() {
|
public VisualizationPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
graph = new mxGraphImpl();
|
graph = new CommunicationsGraph();
|
||||||
|
|
||||||
fastOrganicLayout = new mxFastOrganicLayoutImpl(graph);
|
fastOrganicLayout = new mxFastOrganicLayoutImpl(graph);
|
||||||
circleLayout = new mxCircleLayoutImpl(graph);
|
circleLayout = new mxCircleLayoutImpl(graph);
|
||||||
@ -148,7 +161,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
graphComponent.setToolTips(true);
|
graphComponent.setToolTips(true);
|
||||||
graphComponent.setBackground(Color.WHITE);
|
graphComponent.setBackground(Color.WHITE);
|
||||||
borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
|
borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
|
||||||
progressBar.setVisible(false);
|
|
||||||
|
|
||||||
//install rubber band selection handler
|
//install rubber band selection handler
|
||||||
rubberband = new mxRubberband(graphComponent);
|
rubberband = new mxRubberband(graphComponent);
|
||||||
@ -176,10 +188,10 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
super.mouseClicked(e);
|
super.mouseClicked(e);
|
||||||
if (SwingUtilities.isRightMouseButton(e)) {
|
if (SwingUtilities.isRightMouseButton(e)) {
|
||||||
mxCell cellAt = (mxCell) graphComponent.getCellAt(e.getX(), e.getY());
|
final mxCell cellAt = (mxCell) graphComponent.getCellAt(e.getX(), e.getY());
|
||||||
if (cellAt != null && cellAt.isVertex()) {
|
if (cellAt != null && cellAt.isVertex()) {
|
||||||
JPopupMenu jPopupMenu = new JPopupMenu();
|
final JPopupMenu jPopupMenu = new JPopupMenu();
|
||||||
AccountDeviceInstanceKey adiKey = (AccountDeviceInstanceKey) cellAt.getValue();
|
final AccountDeviceInstanceKey adiKey = (AccountDeviceInstanceKey) cellAt.getValue();
|
||||||
|
|
||||||
if (graph.isVertexLocked(cellAt)) {
|
if (graph.isVertexLocked(cellAt)) {
|
||||||
jPopupMenu.add(new JMenuItem(new AbstractAction("UnLock " + cellAt.getId(), unlockIcon) {
|
jPopupMenu.add(new JMenuItem(new AbstractAction("UnLock " + cellAt.getId(), unlockIcon) {
|
||||||
@ -188,7 +200,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
graph.unlockVertex(cellAt);
|
graph.unlockVertex(cellAt);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
jPopupMenu.add(new JMenuItem(new AbstractAction("Lock " + cellAt.getId(), lockIcon) {
|
jPopupMenu.add(new JMenuItem(new AbstractAction("Lock " + cellAt.getId(), lockIcon) {
|
||||||
@Override
|
@Override
|
||||||
@ -196,7 +207,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
graph.lockVertex(cellAt);
|
graph.lockVertex(cellAt);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
}
|
}
|
||||||
if (graph.isAccountPinned(adiKey)) {
|
if (graph.isAccountPinned(adiKey)) {
|
||||||
jPopupMenu.add(new JMenuItem(new AbstractAction("Unpin " + cellAt.getId(), unpinIcon) {
|
jPopupMenu.add(new JMenuItem(new AbstractAction("Unpin " + cellAt.getId(), unpinIcon) {
|
||||||
@ -206,7 +216,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
jPopupMenu.add(new JMenuItem(new AbstractAction("Pin " + cellAt.getId(), addPinIcon) {
|
jPopupMenu.add(new JMenuItem(new AbstractAction("Pin " + cellAt.getId(), addPinIcon) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -220,7 +229,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
jPopupMenu.show(graphComponent.getGraphControl(), e.getX(), e.getY());
|
jPopupMenu.show(graphComponent.getGraphControl(), e.getX(), e.getY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,6 +239,11 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
|
|
||||||
//feed selection to explorermanager
|
//feed selection to explorermanager
|
||||||
graph.getSelectionModel().addListener(null, new SelectionListener());
|
graph.getSelectionModel().addListener(null, new SelectionListener());
|
||||||
|
final mxEventSource.mxIEventListener undoListener = (Object sender, mxEventObject evt) ->
|
||||||
|
undoManager.undoableEditHappened((mxUndoableEdit) evt.getProperty("edit"));
|
||||||
|
|
||||||
|
graph.getModel().addListener(mxEvent.UNDO, undoListener);
|
||||||
|
graph.getView().addListener(mxEvent.UNDO, undoListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -241,35 +254,24 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
void handleUnPinEvent(CVTEvents.UnpinAccountsEvent pinEvent) {
|
void handleUnPinEvent(CVTEvents.UnpinAccountsEvent pinEvent) {
|
||||||
graph.getModel().beginUpdate();
|
graph.getModel().beginUpdate();
|
||||||
try {
|
graph.unpinAccount(pinEvent.getAccountDeviceInstances());
|
||||||
graph.unpinAccount(pinEvent.getAccountDeviceInstances());
|
graph.clear();
|
||||||
graph.clear();
|
rebuildGraph();
|
||||||
rebuildGraph();
|
// Updates the display
|
||||||
} catch (TskCoreException ex) {
|
graph.getModel().endUpdate();
|
||||||
logger.log(Level.SEVERE, "Error pinning accounts", ex);
|
|
||||||
} finally {
|
|
||||||
// Updates the display
|
|
||||||
graph.getModel().endUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void handlePinEvent(CVTEvents.PinAccountsEvent pinEvent) {
|
void handlePinEvent(CVTEvents.PinAccountsEvent pinEvent) {
|
||||||
graph.getModel().beginUpdate();
|
graph.getModel().beginUpdate();
|
||||||
try {
|
if (pinEvent.isReplace()) {
|
||||||
if (pinEvent.isReplace()) {
|
graph.resetGraph();
|
||||||
graph.resetGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.pinAccount(pinEvent.getAccountDeviceInstances());
|
|
||||||
rebuildGraph();
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Error pinning accounts", ex);
|
|
||||||
} finally {
|
|
||||||
// Updates the display
|
|
||||||
graph.getModel().endUpdate();
|
|
||||||
}
|
}
|
||||||
|
graph.pinAccount(pinEvent.getAccountDeviceInstances());
|
||||||
|
rebuildGraph();
|
||||||
|
// Updates the display
|
||||||
|
graph.getModel().endUpdate();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,43 +279,47 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
void handleFilterEvent(CVTEvents.FilterChangeEvent filterChangeEvent) {
|
void handleFilterEvent(CVTEvents.FilterChangeEvent filterChangeEvent) {
|
||||||
|
|
||||||
graph.getModel().beginUpdate();
|
graph.getModel().beginUpdate();
|
||||||
try {
|
graph.clear();
|
||||||
graph.clear();
|
currentFilter = filterChangeEvent.getNewFilter();
|
||||||
currentFilter = filterChangeEvent.getNewFilter();
|
rebuildGraph();
|
||||||
rebuildGraph();
|
// Updates the display
|
||||||
} catch (TskCoreException ex) {
|
graph.getModel().endUpdate();
|
||||||
logger.log(Level.SEVERE, "Error filtering accounts", ex);
|
|
||||||
} finally {
|
|
||||||
// Updates the display
|
|
||||||
graph.getModel().endUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rebuildGraph() throws TskCoreException {
|
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||||
|
private void rebuildGraph() {
|
||||||
if (graph.isEmpty()) {
|
if (graph.isEmpty()) {
|
||||||
borderLayoutPanel.remove(graphComponent);
|
borderLayoutPanel.remove(graphComponent);
|
||||||
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
|
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
|
||||||
|
repaint();
|
||||||
} else {
|
} else {
|
||||||
borderLayoutPanel.remove(placeHolderPanel);
|
borderLayoutPanel.remove(placeHolderPanel);
|
||||||
borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
|
borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
|
||||||
if (worker != null) {
|
if (worker != null) {
|
||||||
worker.cancel(true);
|
worker.cancel(true);
|
||||||
}
|
}
|
||||||
worker = graph.rebuild(new ProgressIndicatorImpl(), commsManager, currentFilter);
|
|
||||||
|
|
||||||
worker.addPropertyChangeListener(new PropertyChangeListener() {
|
CancelationListener cancelationListener = new CancelationListener();
|
||||||
@Override
|
ModalDialogProgressIndicator progress = new ModalDialogProgressIndicator(windowAncestor, "Loading Visualization", new String[]{CANCEL}, CANCEL, cancelationListener);
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
worker = graph.rebuild(progress, commsManager, currentFilter);
|
||||||
if (worker.isDone()) {
|
cancelationListener.configure(worker, progress);
|
||||||
if (graph.getModel().getChildCount(graph.getDefaultParent()) < 64) {
|
worker.addPropertyChangeListener((final PropertyChangeEvent evt) -> {
|
||||||
applyOrganicLayout(10);
|
if (worker.isDone()) {
|
||||||
} else {
|
if (worker.isCancelled()) {
|
||||||
statusLabel.setText("Too many cells, layout aborted.");
|
graph.resetGraph();
|
||||||
}
|
rebuildGraph();
|
||||||
|
} else if (graph.getModel().getChildCount(graph.getDefaultParent()) < 64) {
|
||||||
|
applyOrganicLayout(10);
|
||||||
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(VisualizationPanel.this,
|
||||||
|
"Too many accounts, layout aborted.",
|
||||||
|
"Autopsy",
|
||||||
|
JOptionPane.WARNING_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.execute();
|
worker.execute();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -322,10 +328,10 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
@Override
|
@Override
|
||||||
public void addNotify() {
|
public void addNotify() {
|
||||||
super.addNotify();
|
super.addNotify();
|
||||||
// IngestManager.getInstance().addIngestModuleEventListener(ingestListener);
|
windowAncestor = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, this);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
commsManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
|
commsManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
|
||||||
|
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException 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);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
@ -357,7 +363,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
@Override
|
@Override
|
||||||
public void removeNotify() {
|
public void removeNotify() {
|
||||||
super.removeNotify();
|
super.removeNotify();
|
||||||
// IngestManager.getInstance().removeIngestModuleEventListener(ingestListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -371,10 +376,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
|
|
||||||
splitPane = new JSplitPane();
|
splitPane = new JSplitPane();
|
||||||
borderLayoutPanel = new JPanel();
|
borderLayoutPanel = new JPanel();
|
||||||
jToolBar2 = new JToolBar();
|
|
||||||
statusLabel = new JLabel();
|
|
||||||
progresPanel = new JPanel();
|
|
||||||
progressBar = new JProgressBar();
|
|
||||||
placeHolderPanel = new JPanel();
|
placeHolderPanel = new JPanel();
|
||||||
jTextArea1 = new JTextArea();
|
jTextArea1 = new JTextArea();
|
||||||
toolbar = new JPanel();
|
toolbar = new JPanel();
|
||||||
@ -398,35 +399,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
|
|
||||||
borderLayoutPanel.setLayout(new BorderLayout());
|
borderLayoutPanel.setLayout(new BorderLayout());
|
||||||
|
|
||||||
jToolBar2.setFloatable(false);
|
|
||||||
jToolBar2.setRollover(true);
|
|
||||||
|
|
||||||
statusLabel.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.statusLabel.text")); // NOI18N
|
|
||||||
jToolBar2.add(statusLabel);
|
|
||||||
|
|
||||||
progresPanel.setMinimumSize(new Dimension(0, 20));
|
|
||||||
progresPanel.setName(""); // NOI18N
|
|
||||||
|
|
||||||
progressBar.setMaximumSize(new Dimension(200, 14));
|
|
||||||
progressBar.setStringPainted(true);
|
|
||||||
|
|
||||||
GroupLayout progresPanelLayout = new GroupLayout(progresPanel);
|
|
||||||
progresPanel.setLayout(progresPanelLayout);
|
|
||||||
progresPanelLayout.setHorizontalGroup(progresPanelLayout.createParallelGroup(GroupLayout.LEADING)
|
|
||||||
.add(GroupLayout.TRAILING, progresPanelLayout.createSequentialGroup()
|
|
||||||
.add(0, 447, Short.MAX_VALUE)
|
|
||||||
.add(progressBar, GroupLayout.PREFERRED_SIZE, 350, GroupLayout.PREFERRED_SIZE))
|
|
||||||
);
|
|
||||||
progresPanelLayout.setVerticalGroup(progresPanelLayout.createParallelGroup(GroupLayout.LEADING)
|
|
||||||
.add(GroupLayout.TRAILING, progresPanelLayout.createSequentialGroup()
|
|
||||||
.add(0, 0, 0)
|
|
||||||
.add(progressBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
|
||||||
);
|
|
||||||
|
|
||||||
jToolBar2.add(progresPanel);
|
|
||||||
|
|
||||||
borderLayoutPanel.add(jToolBar2, BorderLayout.PAGE_END);
|
|
||||||
|
|
||||||
jTextArea1.setBackground(new Color(240, 240, 240));
|
jTextArea1.setBackground(new Color(240, 240, 240));
|
||||||
jTextArea1.setColumns(20);
|
jTextArea1.setColumns(20);
|
||||||
jTextArea1.setLineWrap(true);
|
jTextArea1.setLineWrap(true);
|
||||||
@ -437,15 +409,15 @@ 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(GroupLayout.TRAILING, placeHolderPanelLayout.createSequentialGroup()
|
.add(GroupLayout.TRAILING, placeHolderPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap(213, Short.MAX_VALUE)
|
.addContainerGap(208, Short.MAX_VALUE)
|
||||||
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 372, GroupLayout.PREFERRED_SIZE)
|
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 372, GroupLayout.PREFERRED_SIZE)
|
||||||
.addContainerGap(214, Short.MAX_VALUE))
|
.addContainerGap(209, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
|
placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.LEADING)
|
||||||
.add(GroupLayout.TRAILING, placeHolderPanelLayout.createSequentialGroup()
|
.add(GroupLayout.TRAILING, placeHolderPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap(200, Short.MAX_VALUE)
|
.addContainerGap(213, Short.MAX_VALUE)
|
||||||
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 43, GroupLayout.PREFERRED_SIZE)
|
.add(jTextArea1, GroupLayout.PREFERRED_SIZE, 43, GroupLayout.PREFERRED_SIZE)
|
||||||
.addContainerGap(200, Short.MAX_VALUE))
|
.addContainerGap(214, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
|
|
||||||
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
|
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
|
||||||
@ -638,7 +610,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void fitGraph() {
|
private void fitGraph() {
|
||||||
|
|
||||||
graphComponent.zoomTo(1, true);
|
graphComponent.zoomTo(1, true);
|
||||||
mxPoint translate = graph.getView().getTranslate();
|
mxPoint translate = graph.getView().getTranslate();
|
||||||
if (translate == null || Double.isNaN(translate.getX()) || Double.isNaN(translate.getY())) {
|
if (translate == null || Double.isNaN(translate.getX()) || Double.isNaN(translate.getY())) {
|
||||||
@ -651,7 +622,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
}
|
}
|
||||||
final mxPoint mxPoint = new mxPoint(translate.getX() - boundsForCells.getX(), translate.getY() - boundsForCells.getY());
|
final mxPoint mxPoint = new mxPoint(translate.getX() - boundsForCells.getX(), translate.getY() - boundsForCells.getY());
|
||||||
|
|
||||||
// graph.getView().setTranslate(mxPoint);
|
|
||||||
graph.cellsMoved(graph.getChildCells(graph.getDefaultParent()), mxPoint.getX(), mxPoint.getY(), false, false);
|
graph.cellsMoved(graph.getChildCells(graph.getDefaultParent()), mxPoint.getX(), mxPoint.getY(), false, false);
|
||||||
|
|
||||||
boundsForCells = graph.getCellBounds(graph.getDefaultParent(), true, true, true);
|
boundsForCells = graph.getCellBounds(graph.getDefaultParent(), true, true, true);
|
||||||
@ -662,7 +632,7 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
Dimension size = graphComponent.getSize();
|
Dimension size = graphComponent.getSize();
|
||||||
double widthFactor = size.getWidth() / boundsForCells.getWidth();
|
double widthFactor = size.getWidth() / boundsForCells.getWidth();
|
||||||
|
|
||||||
graphComponent.zoom(widthFactor);//, true);
|
graphComponent.zoom(widthFactor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,27 +640,47 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
// layout using morphing
|
// layout using morphing
|
||||||
graph.getModel().beginUpdate();
|
graph.getModel().beginUpdate();
|
||||||
|
|
||||||
progressBar.setVisible(true);
|
CancelationListener cancelationListener = new CancelationListener();
|
||||||
progressBar.setIndeterminate(true);
|
ModalDialogProgressIndicator progress = new ModalDialogProgressIndicator(windowAncestor, "Computing layout", new String[]{CANCEL}, CANCEL, cancelationListener);
|
||||||
progressBar.setString("applying layout");
|
SwingWorker<Void, Void> morphWorker = new SwingWorker<Void, Void>() {
|
||||||
|
|
||||||
new SwingWorker<Void, Void>() {
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Exception {
|
protected Void doInBackground() throws Exception {
|
||||||
|
progress.start("Computing layout");
|
||||||
layout.execute(graph.getDefaultParent());
|
layout.execute(graph.getDefaultParent());
|
||||||
mxMorphing morph = new mxMorphing(graphComponent, 20, 1.2, 20);
|
if (isCancelled()) {
|
||||||
|
progress.finish();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
mxMorphing morph = new mxMorphing(graphComponent, 20, 1.2, 20) {
|
||||||
|
@Override
|
||||||
|
public void updateAnimation() {
|
||||||
|
fireEvent(new mxEventObject(mxEvent.EXECUTE));
|
||||||
|
super.updateAnimation(); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
morph.addListener(mxEvent.EXECUTE, (Object sender, mxEventObject evt) -> {
|
||||||
|
if (isCancelled()) {
|
||||||
|
morph.stopAnimation();
|
||||||
|
}
|
||||||
|
});
|
||||||
morph.addListener(mxEvent.DONE, (Object sender, mxEventObject event) -> {
|
morph.addListener(mxEvent.DONE, (Object sender, mxEventObject event) -> {
|
||||||
graph.getModel().endUpdate();
|
graph.getModel().endUpdate();
|
||||||
fitGraph();
|
if (isCancelled()) {
|
||||||
progressBar.setVisible(false);
|
undoManager.undo();
|
||||||
progressBar.setValue(0);
|
} else {
|
||||||
|
fitGraph();
|
||||||
|
}
|
||||||
|
progress.finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
morph.startAnimation();
|
morph.startAnimation();
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cancelationListener.configure(morphWorker, progress);
|
||||||
|
morphWorker.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
@ -703,13 +693,9 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
private JLabel jLabel2;
|
private JLabel jLabel2;
|
||||||
private JToolBar.Separator jSeparator1;
|
private JToolBar.Separator jSeparator1;
|
||||||
private JTextArea jTextArea1;
|
private JTextArea jTextArea1;
|
||||||
private JToolBar jToolBar2;
|
|
||||||
private JButton organicLayoutButton;
|
private JButton organicLayoutButton;
|
||||||
private JPanel placeHolderPanel;
|
private JPanel placeHolderPanel;
|
||||||
private JPanel progresPanel;
|
|
||||||
private JProgressBar progressBar;
|
|
||||||
private JSplitPane splitPane;
|
private JSplitPane splitPane;
|
||||||
private JLabel statusLabel;
|
|
||||||
private JPanel toolbar;
|
private JPanel toolbar;
|
||||||
private JButton zoomActualButton;
|
private JButton zoomActualButton;
|
||||||
private JButton zoomInButton;
|
private JButton zoomInButton;
|
||||||
@ -748,79 +734,6 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final private class ProgressIndicatorImpl implements ProgressIndicator {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start(String message, int totalWorkUnits) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setVisible(true);
|
|
||||||
progressBar.setIndeterminate(false);
|
|
||||||
progressBar.setString(message);
|
|
||||||
progressBar.setMaximum(totalWorkUnits);
|
|
||||||
progressBar.setValue(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start(String message) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setVisible(true);
|
|
||||||
progressBar.setString(message);
|
|
||||||
progressBar.setIndeterminate(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void switchToIndeterminate(String message) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setVisible(true);
|
|
||||||
progressBar.setIndeterminate(true);
|
|
||||||
progressBar.setString(message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setVisible(true);
|
|
||||||
progressBar.setIndeterminate(false);
|
|
||||||
progressBar.setString(message);
|
|
||||||
progressBar.setMaximum(totalWorkUnits);
|
|
||||||
progressBar.setValue(workUnitsCompleted);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void progress(String message) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setString(message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void progress(int workUnitsCompleted) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setValue(workUnitsCompleted);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void progress(String message, int workUnitsCompleted) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setString(message);
|
|
||||||
progressBar.setValue(workUnitsCompleted);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
progressBar.setValue(progressBar.getValue());
|
|
||||||
progressBar.setVisible(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final private class mxFastOrganicLayoutImpl extends mxFastOrganicLayout {
|
final private class mxFastOrganicLayoutImpl extends mxFastOrganicLayout {
|
||||||
|
|
||||||
mxFastOrganicLayoutImpl(mxGraph graph) {
|
mxFastOrganicLayoutImpl(mxGraph graph) {
|
||||||
@ -910,4 +823,23 @@ final public class VisualizationPanel extends JPanel implements Lookup.Provider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CancelationListener implements ActionListener {
|
||||||
|
|
||||||
|
private Future<?> cancellable;
|
||||||
|
private ModalDialogProgressIndicator progress;
|
||||||
|
|
||||||
|
void configure(Future<?> cancellable, ModalDialogProgressIndicator progress) {
|
||||||
|
this.cancellable = cancellable;
|
||||||
|
this.progress = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
progress.setCancelling("Cancelling...");
|
||||||
|
cancellable.cancel(true);
|
||||||
|
progress.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
|||||||
DialogDescriptor.BOTTOM_ALIGN,
|
DialogDescriptor.BOTTOM_ALIGN,
|
||||||
HelpCtx.DEFAULT_HELP,
|
HelpCtx.DEFAULT_HELP,
|
||||||
buttonListener);
|
buttonListener);
|
||||||
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
|
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor, parent);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Dialog without buttons.
|
* Dialog without buttons.
|
||||||
@ -256,6 +256,7 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
|||||||
dialog.add(progressPanel);
|
dialog.add(progressPanel);
|
||||||
dialog.pack();
|
dialog.pack();
|
||||||
}
|
}
|
||||||
|
dialog.setResizable(false);
|
||||||
dialog.setLocationRelativeTo(parent);
|
dialog.setLocationRelativeTo(parent);
|
||||||
this.dialog.setVisible(true);
|
this.dialog.setVisible(true);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user