19package org.sleuthkit.autopsy.communications;
21import com.google.common.eventbus.Subscribe;
22import com.mxgraph.layout.hierarchical.mxHierarchicalLayout;
23import com.mxgraph.layout.mxCircleLayout;
24import com.mxgraph.layout.mxFastOrganicLayout;
25import com.mxgraph.layout.mxIGraphLayout;
26import com.mxgraph.layout.mxOrganicLayout;
27import com.mxgraph.model.mxCell;
28import com.mxgraph.model.mxICell;
29import com.mxgraph.swing.handler.mxRubberband;
30import com.mxgraph.swing.mxGraphComponent;
31import com.mxgraph.util.mxCellRenderer;
32import com.mxgraph.util.mxEvent;
33import com.mxgraph.util.mxEventObject;
34import com.mxgraph.util.mxEventSource;
35import com.mxgraph.util.mxPoint;
36import com.mxgraph.util.mxRectangle;
37import com.mxgraph.util.mxUndoManager;
38import com.mxgraph.util.mxUndoableEdit;
39import com.mxgraph.view.mxCellState;
40import com.mxgraph.view.mxGraph;
41import com.mxgraph.view.mxGraphView;
42import java.awt.BorderLayout;
44import org.sleuthkit.autopsy.coreutils.Desktop;
45import java.awt.Dimension;
48import java.awt.Graphics;
49import java.awt.GridBagConstraints;
50import java.awt.GridBagLayout;
51import java.awt.GridLayout;
52import java.awt.Insets;
53import java.awt.event.ActionEvent;
54import java.awt.event.ActionListener;
55import java.awt.event.MouseAdapter;
56import java.awt.event.MouseEvent;
57import java.awt.event.MouseWheelEvent;
58import java.awt.image.BufferedImage;
59import java.beans.PropertyChangeEvent;
60import java.io.IOException;
61import java.nio.file.Files;
62import java.nio.file.Path;
63import java.nio.file.Paths;
64import java.text.DecimalFormat;
65import java.text.SimpleDateFormat;
66import java.util.Arrays;
68import java.util.EnumSet;
69import java.util.HashMap;
70import java.util.HashSet;
73import java.util.concurrent.Future;
74import java.util.function.BiConsumer;
75import java.util.logging.Level;
76import java.util.stream.Collectors;
77import java.util.stream.Stream;
78import javafx.application.Platform;
79import javafx.embed.swing.JFXPanel;
80import javafx.scene.Scene;
81import javafx.scene.layout.Pane;
82import javax.swing.AbstractAction;
83import javax.swing.ImageIcon;
84import javax.swing.JButton;
85import javax.swing.JLabel;
86import javax.swing.JMenuItem;
87import javax.swing.JOptionPane;
88import javax.swing.JPanel;
89import javax.swing.JPopupMenu;
90import javax.swing.JTextField;
91import javax.swing.JTextPane;
92import javax.swing.JToolBar;
93import javax.swing.SwingConstants;
94import javax.swing.SwingUtilities;
95import javax.swing.SwingWorker;
96import org.apache.commons.lang3.StringUtils;
97import org.controlsfx.control.Notifications;
98import org.openide.util.NbBundle;
99import org.openide.windows.WindowManager;
100import org.sleuthkit.autopsy.casemodule.Case;
101import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
102import org.sleuthkit.autopsy.communications.relationships.RelationshipBrowser;
103import org.sleuthkit.autopsy.communications.relationships.SelectionInfo;
104import org.sleuthkit.autopsy.communications.snapshot.CommSnapShotReportWriter;
105import org.sleuthkit.autopsy.coreutils.FileUtil;
106import org.sleuthkit.autopsy.coreutils.Logger;
107import org.sleuthkit.autopsy.coreutils.ThreadConfined;
108import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
109import org.sleuthkit.datamodel.AccountDeviceInstance;
110import org.sleuthkit.datamodel.CommunicationsFilter;
111import org.sleuthkit.datamodel.CommunicationsManager;
112import org.sleuthkit.datamodel.TskCoreException;
113import org.sleuthkit.autopsy.guiutils.WrapLayout;
124@SuppressWarnings(
"PMD.SingularField")
129 private static final String
BASE_IMAGE_PATH =
"/org/sleuthkit/autopsy/communications/images";
135 @NbBundle.Messages(
"VisualizationPanel.cancelButton.text=Cancel")
136 private static final String
CANCEL = Bundle.VisualizationPanel_cancelButton_text();
144 private final CommunicationsGraph
graph;
161 @NbBundle.Messages(
"VisalizationPanel.paintingError=Problem painting visualization.")
166 Platform.runLater(() -> {
180 protected mxGraphComponent.mxGraphControl createGraphControl() {
182 return new mxGraphControl() {
185 public void paint(Graphics graphics) {
187 super.paint(graphics);
188 }
catch (NullPointerException ex) {
194 logger.log(Level.WARNING,
"There was a NPE while painting the VisualizationPanel", ex);
217 final mxEventSource.mxIEventListener scaleListener = (Object sender, mxEventObject evt)
219 graph.getView().addListener(mxEvent.SCALE, scaleListener);
220 graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE, scaleListener);
223 graphComponent.getGraphControl().addMouseWheelListener(graphMouseListener);
224 graphComponent.getGraphControl().addMouseListener(graphMouseListener);
228 final mxEventSource.mxIEventListener undoListener = (Object sender, mxEventObject evt)
229 ->
undoManager.undoableEditHappened((mxUndoableEdit) evt.getProperty(
"edit"));
231 graph.getModel().addListener(mxEvent.UNDO, undoListener);
232 graph.getView().addListener(mxEvent.UNDO, undoListener);
237 BiConsumer<JButton, NamedGraphLayout> configure = (layoutButton, layout) -> {
239 layoutButton.addActionListener(event ->
applyLayout(layout));
254 void handle(LockedVertexModel.VertexLockEvent event) {
255 final Set<mxCell> vertices =
event.getVertices();
256 mxGraphView view = graph.getView();
257 vertices.forEach(vertex -> {
258 final mxCellState state = view.getState(vertex,
true);
259 view.updateLabel(state);
260 view.updateLabelBounds(state);
261 view.updateBoundingBox(state);
262 graphComponent.redraw(state);
267 void handle(
final CVTEvents.UnpinAccountsEvent pinEvent) {
268 graph.getModel().beginUpdate();
269 pinnedAccountModel.unpinAccount(pinEvent.getAccountDeviceInstances());
273 graph.getModel().endUpdate();
275 setStateButtonsEnabled();
279 void handle(
final CVTEvents.PinAccountsEvent pinEvent) {
280 graph.getModel().beginUpdate();
281 if (pinEvent.isReplace()) {
284 pinnedAccountModel.pinAccount(pinEvent.getAccountDeviceInstances());
287 graph.getModel().endUpdate();
289 setStateButtonsEnabled();
293 void handle(
final CVTEvents.FilterChangeEvent filterChangeEvent) {
294 graph.getModel().beginUpdate();
296 currentFilter = filterChangeEvent.getNewFilter();
299 graph.getModel().endUpdate();
301 setStateButtonsEnabled();
307 borderLayoutPanel.remove(graphComponent);
308 borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
311 borderLayoutPanel.remove(placeHolderPanel);
312 borderLayoutPanel.add(graphComponent, BorderLayout.CENTER);
313 if (worker != null) {
321 worker.addPropertyChangeListener((
final PropertyChangeEvent evt) -> {
323 if (
worker.isCancelled()) {
338 windowAncestor = (Frame) SwingUtilities.getAncestorOfClass(Frame.class,
this);
342 }
catch (TskCoreException ex) {
343 logger.log(Level.SEVERE,
"Error getting CommunicationsManager for the current case.", ex);
345 logger.log(Level.SEVERE,
"Can't get CommunicationsManager when there is no case open.", ex);
349 graph.getModel().beginUpdate();
353 graph.getModel().endUpdate();
355 if (evt.getNewValue() ==
null) {
358 Case currentCase = (Case) evt.getNewValue();
360 commsManager = currentCase.getSleuthkitCase().getCommunicationsManager();
361 } catch (TskCoreException ex) {
362 logger.log(Level.SEVERE,
"Error getting CommunicationsManager for the current case.", ex);
373 @SuppressWarnings(
"unchecked")
376 GridBagConstraints gridBagConstraints;
398 setLayout(
new BorderLayout());
407 gridBagConstraints =
new GridBagConstraints();
408 gridBagConstraints.anchor = GridBagConstraints.NORTH;
409 gridBagConstraints.weighty = 1.0;
410 gridBagConstraints.insets =
new Insets(50, 0, 0, 0);
420 backButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/resultset_previous.png")));
424 backButton.setHorizontalTextPosition(SwingConstants.CENTER);
425 backButton.setVerticalTextPosition(SwingConstants.BOTTOM);
426 backButton.addActionListener(
new ActionListener() {
427 public void actionPerformed(ActionEvent evt) {
433 forwardButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/resultset_next.png")));
437 forwardButton.setHorizontalTextPosition(SwingConstants.CENTER);
438 forwardButton.setVerticalTextPosition(SwingConstants.BOTTOM);
440 public void actionPerformed(ActionEvent evt) {
447 clearVizButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/broom.png")));
455 public void actionPerformed(ActionEvent evt) {
461 fastOrganicLayoutButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/arrow-circle-double-135.png")));
468 public void actionPerformed(ActionEvent evt) {
481 zoomOutButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-out-red.png")));
485 zoomOutButton.setHorizontalTextPosition(SwingConstants.CENTER);
486 zoomOutButton.setVerticalTextPosition(SwingConstants.BOTTOM);
488 public void actionPerformed(ActionEvent evt) {
494 fitZoomButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-fit.png")));
498 fitZoomButton.setHorizontalTextPosition(SwingConstants.CENTER);
499 fitZoomButton.setVerticalTextPosition(SwingConstants.BOTTOM);
501 public void actionPerformed(ActionEvent evt) {
507 zoomActualButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-actual.png")));
514 public void actionPerformed(ActionEvent evt) {
520 zoomInButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/communications/images/magnifier-zoom-in-green.png")));
524 zoomInButton.setHorizontalTextPosition(SwingConstants.CENTER);
525 zoomInButton.setVerticalTextPosition(SwingConstants.BOTTOM);
527 public void actionPerformed(ActionEvent evt) {
534 snapshotButton.setIcon(
new ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/report/images/image.png")));
541 public void actionPerformed(ActionEvent evt) {
547 add(
toolbar, BorderLayout.NORTH);
556 CVTEvents.getCVTEventBus().post(
new CVTEvents.ScaleChangeEvent(
graph.getView().getScale()));
561 CVTEvents.getCVTEventBus().post(
new CVTEvents.ScaleChangeEvent(
graph.getView().getScale()));
566 CVTEvents.getCVTEventBus().post(
new CVTEvents.ScaleChangeEvent(
graph.getView().getScale()));
575 @NbBundle.Messages({
"VisualizationPanel.computingLayout=Computing Layout",
576 "# {0} - layout name",
577 "VisualizationPanel.layoutFailWithLockedVertices.text={0} layout failed with locked vertices. Unlock some vertices or try a different layout.",
578 "# {0} - layout name",
579 "VisualizationPanel.layoutFail.text={0} layout failed. Try a different layout."})
583 -> button.setFont(button.getFont().deriveFont(layoutKey == layout ? Font.BOLD : Font.PLAIN)));
586 progressIndicator.
start(Bundle.VisualizationPanel_computingLayout());
587 graph.getModel().beginUpdate();
589 layout.execute(
graph.getDefaultParent());
592 graph.getModel().endUpdate();
593 progressIndicator.
finish();
598 CVTEvents.getCVTEventBus().post(
new CVTEvents.UnpinAccountsEvent(
pinnedAccountModel.getPinnedAccounts()));
615 if(newState ==
null) {
620 if(newState.isZoomChange()) {
621 graph.getView().setScale(newState.getZoomValue());
626 CVTEvents.getCVTEventBus().post(
new CVTEvents.StateChangeEvent(newState));
629 graph.getModel().beginUpdate();
632 if(newState.getPinnedList() !=
null) {
642 graph.getModel().endUpdate();
654 "VisualizationPanel_snapshot_report_failure=Snapshot report not created. An error occurred during creation."
660 logger.log(Level.SEVERE,
"Unable to create communications snapsot report", ex);
664 .text(Bundle.VisualizationPanel_snapshot_report_failure())
666 }
catch( TskCoreException ex) {
667 logger.log(Level.WARNING,
"Unable to add report to currenct case", ex);
677 mxPoint translate =
graph.getView().getTranslate();
678 if (translate ==
null || Double.isNaN(translate.getX()) || Double.isNaN(translate.getY())) {
679 translate =
new mxPoint();
682 mxRectangle boundsForCells =
graph.getCellBounds(
graph.getDefaultParent(),
true,
true,
true);
683 if (boundsForCells ==
null || Double.isNaN(boundsForCells.getWidth()) || Double.isNaN(boundsForCells.getHeight())) {
684 boundsForCells =
new mxRectangle(0, 0, 1, 1);
686 final mxPoint mxPoint =
new mxPoint(translate.getX() - boundsForCells.getX(), translate.getY() - boundsForCells.getY());
688 graph.cellsMoved(
graph.getChildCells(
graph.getDefaultParent()), mxPoint.getX(), mxPoint.getY(),
false,
false);
690 boundsForCells =
graph.getCellBounds(
graph.getDefaultParent(),
true,
true,
true);
691 if (boundsForCells ==
null || Double.isNaN(boundsForCells.getWidth()) || Double.isNaN(boundsForCells.getHeight())) {
692 boundsForCells =
new mxRectangle(0, 0, 1, 1);
696 final double widthFactor = size.getWidth() / boundsForCells.getWidth();
697 final double heightFactor = size.getHeight() / boundsForCells.getHeight();
709 "VisualizationPanel_action_dialogs_title=Communications",
710 "VisualizationPanel_module_name=Communications",
711 "VisualizationPanel_action_name_text=Snapshot Report",
712 "VisualizationPane_fileName_prompt=Enter name for the Communications Snapshot Report:",
713 "VisualizationPane_reportName=Communications Snapshot",
714 "# {0} - default name",
715 "VisualizationPane_accept_defaultName=Report name was empty. Press OK to accept default report name: {0}",
716 "VisualizationPane_blank_report_title=Blank Report Name",
717 "# {0} - report name",
718 "VisualizationPane_overrite_exiting=Overwrite existing report?\n{0}"
722 Date generationDate =
new Date();
726 final JTextField text =
new JTextField(50);
727 final JPanel panel =
new JPanel(
new GridLayout(2, 1));
728 panel.add(
new JLabel(Bundle.VisualizationPane_fileName_prompt()));
731 text.setText(defaultReportName);
734 Bundle.VisualizationPanel_action_dialogs_title(), JOptionPane.OK_CANCEL_OPTION);
736 if (result == JOptionPane.OK_OPTION) {
737 String enteredReportName = text.getText();
739 if(enteredReportName.trim().isEmpty()){
740 result = JOptionPane.showConfirmDialog(
graphComponent, Bundle.VisualizationPane_accept_defaultName(defaultReportName), Bundle.VisualizationPane_blank_report_title(), JOptionPane.OK_CANCEL_OPTION);
741 if(result != JOptionPane.OK_OPTION) {
746 String reportName = StringUtils.defaultIfBlank(enteredReportName, defaultReportName);
748 if (Files.exists(reportPath)) {
749 result = JOptionPane.showConfirmDialog(
graphComponent, Bundle.VisualizationPane_overrite_exiting(reportName),
750 Bundle.VisualizationPanel_action_dialogs_title(), JOptionPane.OK_CANCEL_OPTION);
752 if (result == JOptionPane.OK_OPTION) {
758 currentCase.
addReport(reportPath.toString(), Bundle.VisualizationPanel_module_name(), reportName);
773 "VisualizationPane_DisplayName=Open Report",
774 "VisualizationPane_NoAssociatedEditorMessage=There is no associated editor for reports of this type or the associated application failed to launch.",
775 "VisualizationPane_MessageBoxTitle=Open Report Failure",
776 "VisualizationPane_NoOpenInEditorSupportMessage=This platform (operating system) does not support opening a file in an editor this way.",
777 "VisualizationPane_MissingReportFileMessage=The report file no longer exists.",
778 "VisualizationPane_ReportFileOpenPermissionDeniedMessage=Permission to open the report file was denied.",
779 "# {0} - report path",
780 "VisualizationPane_Report_Success=Report Successfully create at:\n{0}",
781 "VisualizationPane_Report_OK_Button=OK",
782 "VisualizationPane_Open_Report=Open Report",})
786 Path reportFolderPath = Paths.get(currentCase.
getReportDirectory(), reportName, Bundle.VisualizationPane_reportName());
787 BufferedImage image = mxCellRenderer.createBufferedImage(
graph,
null,
graph.getView().getScale(), Color.WHITE,
true,
null);
791 String message = Bundle.VisualizationPane_Report_Success(reportPath.toAbsolutePath());
792 String[] buttons = {Bundle.VisualizationPane_Open_Report(), Bundle.VisualizationPane_Report_OK_Button()};
794 int result = JOptionPane.showOptionDialog(
graphComponent, message,
795 Bundle.VisualizationPanel_action_dialogs_title(),
796 JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE,
797 null, buttons, buttons[1]);
798 if (result == JOptionPane.YES_NO_OPTION) {
801 }
catch (IOException ex) {
802 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
803 Bundle.VisualizationPane_NoAssociatedEditorMessage(),
804 Bundle.VisualizationPane_MessageBoxTitle(),
805 JOptionPane.ERROR_MESSAGE);
806 }
catch (UnsupportedOperationException ex) {
807 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
808 Bundle.VisualizationPane_NoOpenInEditorSupportMessage(),
809 Bundle.VisualizationPane_MessageBoxTitle(),
810 JOptionPane.ERROR_MESSAGE);
811 }
catch (IllegalArgumentException ex) {
812 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
813 Bundle.VisualizationPane_MissingReportFileMessage(),
814 Bundle.VisualizationPane_MessageBoxTitle(),
815 JOptionPane.ERROR_MESSAGE);
816 }
catch (SecurityException ex) {
817 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
818 Bundle.VisualizationPane_ReportFileOpenPermissionDeniedMessage(),
819 Bundle.VisualizationPane_MessageBoxTitle(),
820 JOptionPane.ERROR_MESSAGE);
853 @SuppressWarnings(
"unchecked")
855 public void invoke(Object sender, mxEventObject evt) {
856 Object[] selectionCells =
graph.getSelectionCells();
857 if (selectionCells.length > 0) {
858 mxICell[] selectedCells = Arrays.asList(selectionCells).toArray(
new mxCell[selectionCells.length]);
859 HashSet<AccountDeviceInstance> selectedNodes =
new HashSet<>();
861 for (mxICell cell : selectedCells) {
863 mxICell source = (mxICell)
graph.getModel().getTerminal(cell,
true);
864 mxICell target = (mxICell)
graph.getModel().getTerminal(cell,
false);
866 selectedEdges.add(
new SelectionInfo.
GraphEdge(((AccountDeviceInstanceKey) source.getValue()).getAccountDeviceInstance(),
867 ((AccountDeviceInstanceKey) target.getValue()).getAccountDeviceInstance()));
869 }
else if (cell.isVertex()) {
870 selectedNodes.add(((AccountDeviceInstanceKey) cell.getValue()).getAccountDeviceInstance());
892 final private class FastOrganicLayoutImpl
extends mxFastOrganicLayout implements
NamedGraphLayout {
894 FastOrganicLayoutImpl(mxGraph
graph) {
900 return super.isVertexIgnored(vertex)
907 return getVertexBounds(vertex);
909 return super.setVertexLocation(vertex, x, y);
915 return "Fast Organic";
924 CircleLayoutImpl(mxGraph
graph) {
931 return super.isVertexIgnored(vertex)
938 return getVertexBounds(vertex);
940 return super.setVertexLocation(vertex, x, y);
953 final private class OrganicLayoutImpl
extends mxOrganicLayout implements
NamedGraphLayout {
955 OrganicLayoutImpl(mxGraph
graph) {
962 return super.isVertexIgnored(vertex)
969 return getVertexBounds(vertex);
971 return super.setVertexLocation(vertex, x, y);
984 final private class HierarchicalLayoutImpl
extends mxHierarchicalLayout implements
NamedGraphLayout {
986 HierarchicalLayoutImpl(mxGraph
graph) {
992 return super.isVertexIgnored(vertex)
999 return getVertexBounds(vertex);
1001 return super.setVertexLocation(vertex, x, y);
1007 return "Hierarchical";
1027 progress.setCancelling(
"Cancelling...");
1046 super.mouseWheelMoved(event);
1047 if (event.getPreciseWheelRotation() < 0) {
1049 }
else if (event.getPreciseWheelRotation() > 0) {
1053 CVTEvents.getCVTEventBus().post(
new CVTEvents.ScaleChangeEvent(
graph.getView().getScale()));
1063 super.mouseClicked(event);
1064 if (SwingUtilities.isRightMouseButton(event)) {
1065 final mxCell cellAt = (mxCell)
graphComponent.getCellAt(event.getX(), event.getY());
1066 if (cellAt !=
null && cellAt.isVertex()) {
1067 final JPopupMenu jPopupMenu =
new JPopupMenu();
1068 final AccountDeviceInstanceKey adiKey = (AccountDeviceInstanceKey) cellAt.getValue();
1070 Set<mxCell> selectedVertices
1071 = Stream.of(
graph.getSelectionModel().getCells())
1072 .map(mxCell.class::cast)
1073 .filter(mxCell::isVertex)
1074 .collect(Collectors.toSet());
1077 jPopupMenu.add(
new JMenuItem(
new UnlockAction(selectedVertices)));
1079 jPopupMenu.add(
new JMenuItem(
new LockAction(selectedVertices)));
1082 jPopupMenu.add(UnpinAccountsAction.getInstance().getPopupPresenter());
1084 jPopupMenu.add(PinAccountsAction.getInstance().getPopupPresenter());
1085 jPopupMenu.add(ResetAndPinAccountsAction.getInstance().getPopupPresenter());
1087 jPopupMenu.show(
graphComponent.getGraphControl(), event.getX(), event.getY());
1096 @NbBundle.Messages({
1097 "VisualizationPanel.unlockAction.singularText=Unlock Selected Account",
1098 "VisualizationPanel.unlockAction.pluralText=Unlock Selected Accounts",})
1099 private final class UnlockAction extends AbstractAction {
1104 super(
selectedVertices.size() > 1 ? Bundle.VisualizationPanel_unlockAction_pluralText() : Bundle.VisualizationPanel_unlockAction_singularText(),
1119 @NbBundle.Messages({
1120 "VisualizationPanel.lockAction.singularText=Lock Selected Account",
1121 "VisualizationPanel.lockAction.pluralText=Lock Selected Accounts"})
1122 private final class LockAction extends AbstractAction {
1127 super(
selectedVertices.size() > 1 ? Bundle.VisualizationPanel_lockAction_pluralText() : Bundle.VisualizationPanel_lockAction_singularText(),
SleuthkitCase getSleuthkitCase()
static Case getCurrentCaseThrows()
void addReport(String localPath, String srcModuleName, String reportName)
String getReportDirectory()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
ModalDialogProgressIndicator progress
void actionPerformed(ActionEvent event)
boolean isVertexIgnored(Object vertex)
mxRectangle setVertexLocation(Object vertex, double x, double y)
boolean isVertexIgnored(Object vertex)
mxRectangle setVertexLocation(Object vertex, double x, double y)
void mouseClicked(final MouseEvent event)
void mouseWheelMoved(final MouseWheelEvent event)
boolean isVertexIgnored(Object vertex)
mxRectangle setVertexLocation(Object vertex, double x, double y)
void actionPerformed(final ActionEvent event)
final Set< mxCell > selectedVertices
mxRectangle setVertexLocation(Object vertex, double x, double y)
boolean isVertexIgnored(Object vertex)
void invoke(Object sender, mxEventObject evt)
void actionPerformed(final ActionEvent event)
final Set< mxCell > selectedVertices
final CommunicationsGraph graph
VisualizationPanel(RelationshipBrowser relationshipBrowser)
void createReport(Case currentCase, String reportName)
void setStateButtonsEnabled()
final StateManager stateManager
final mxUndoManager undoManager
NamedGraphLayout currentLayout
static final ImageIcon unlockIcon
void forwardButtonActionPerformed(ActionEvent evt)
void fastOrganicLayoutButtonActionPerformed(ActionEvent evt)
void snapshotButtonActionPerformed(ActionEvent evt)
void applyLayout(NamedGraphLayout layout)
void zoomActualButtonActionPerformed(ActionEvent evt)
final Map< NamedGraphLayout, JButton > layoutButtons
JFXPanel notificationsJFXPanel
void backButtonActionPerformed(ActionEvent evt)
final LockedVertexModel lockedVertexModel
final PinnedAccountModel pinnedAccountModel
void clearVizButtonActionPerformed(ActionEvent evt)
JToolBar.Separator jSeparator2
CommunicationsFilter currentFilter
final mxRubberband rubberband
void handleSnapshotEvent()
JButton fastOrganicLayoutButton
void handleStateChange(StateManager.CommunicationsState newState)
CommunicationsManager commsManager
JToolBar.Separator jSeparator3
void zoomOutButtonActionPerformed(ActionEvent evt)
final mxGraphComponent graphComponent
static final ImageIcon lockIcon
static final Logger logger
static final long serialVersionUID
void fitZoomButtonActionPerformed(ActionEvent evt)
final RelationshipBrowser relationshipBrowser
static final String BASE_IMAGE_PATH
void zoomInButtonActionPerformed(ActionEvent evt)
static final String CANCEL
JToolBar.Separator jSeparator1
static Desktop getDesktop()
static String escapeFileName(String fileName)
static boolean deleteFileDir(File path)
synchronized static Logger getLogger(String name)
synchronized void finish()
synchronized void start(String message, int totalWorkUnits)